<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>All on The SIP Lab</title>
    <link>https://wdd.js.org/zh/categories/all/</link>
    <description>Recent content in All on The SIP Lab</description>
    <generator>Hugo -- 0.151.0</generator>
    <language>zh</language>
    <lastBuildDate>Wed, 11 Mar 2026 21:05:30 +0800</lastBuildDate>
    <atom:link href="https://wdd.js.org/zh/categories/all/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>OpenSIPS vs Kamailio， 你应该选择哪个？</title>
      <link>https://wdd.js.org/zh/posts/2026/opensips-vs-kamilio-which-one-should-you-choose/</link>
      <pubDate>Wed, 11 Mar 2026 21:05:30 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2026/opensips-vs-kamilio-which-one-should-you-choose/</guid>
      <description>&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;维度&lt;/th&gt;
          &lt;th&gt;opensips&lt;/th&gt;
          &lt;th&gt;kamalio&lt;/th&gt;
          &lt;th&gt;说明&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;性能&lt;/td&gt;
          &lt;td&gt;4.5&lt;/td&gt;
          &lt;td&gt;5&lt;/td&gt;
          &lt;td&gt;性能接近&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;脚本能力&lt;/td&gt;
          &lt;td&gt;4&lt;/td&gt;
          &lt;td&gt;5&lt;/td&gt;
          &lt;td&gt;kmailio脚本更友好，支持预处理，宏&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;稳定性&lt;/td&gt;
          &lt;td&gt;4&lt;/td&gt;
          &lt;td&gt;5&lt;/td&gt;
          &lt;td&gt;opensips开发更激进，所以稳定性没有kamailio高&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;特殊能力&lt;/td&gt;
          &lt;td&gt;5&lt;/td&gt;
          &lt;td&gt;3&lt;/td&gt;
          &lt;td&gt;opensips在拓扑隐藏，注册信息同步，动态新增SIP端口方面能力更强&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;无论从哪些方面，OpenSIPS和Kamailio似乎都可以相互替代。&lt;/p&gt;
&lt;p&gt;但是，有几个特别的能力，你可能要提前考虑。&lt;/p&gt;
&lt;h1 id=&#34;1-拓扑隐藏能力&#34;&gt;1. 拓扑隐藏能力&lt;/h1&gt;
&lt;h2 id=&#34;11-什么是拓扑隐藏&#34;&gt;1.1. 什么是拓扑隐藏&lt;/h2&gt;
&lt;p&gt;假设某 VoIP 运营商没有启用拓扑隐藏，对方运营商收到的 &lt;code&gt;INVITE&lt;/code&gt; 可能是这样的：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;INVITE sip:441234567890@carrierB.net SIP/2.0
Via: SIP/2.0/UDP gw3.carrierA.net:5060;branch=z9hG4bK-342343
Via: SIP/2.0/UDP core-switch1.internal.local:5060;branch=z9hG4bK-983423
Via: SIP/2.0/UDP edge1.carrierA.net:5060;branch=z9hG4bK-238472
From: &amp;lt;sip:+12065550123@carrierA.net&amp;gt;;tag=98324
To: &amp;lt;sip:+441234567890@carrierB.net&amp;gt;
Call-ID: a98sdasdh23@10.12.0.15
Contact: &amp;lt;sip:fs1.internal.local:5060&amp;gt;
Record-Route: &amp;lt;sip:edge1.carrierA.net;lr&amp;gt;
Record-Route: &amp;lt;sip:core-switch1.internal.local;lr&amp;gt;
User-Agent: FreeSWITCH-mod_sofia/1.10
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;看起来只是普通 SIP 报文，但实际上信息量&lt;strong&gt;非常巨大&lt;/strong&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Via头会暴露&lt;strong&gt;所有经过的节点&lt;/strong&gt;， 只靠一个包就能画出你的 SIP 网络图&lt;/li&gt;
&lt;li&gt;Call-ID暴露内网地址：Call-ID: &lt;a href=&#34;mailto:a98sdasdh23@10.12.0.15&#34;&gt;a98sdasdh23@10.12.0.15&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;User-Agent暴露了服务器类型和版本，黑客会直接去查询对应版本的CVE和漏洞&lt;/li&gt;
&lt;li&gt;Record-Route暴露dialog经过哪些节点&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;黑客利用上面的信息，针对弱点攻击：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SIP flood&lt;/li&gt;
&lt;li&gt;REGISTER attack&lt;/li&gt;
&lt;li&gt;RTP injection&lt;/li&gt;
&lt;li&gt;SIP scanning&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;启用拓扑隐藏后，对方只能看到一个对外的SIP Server， 内部网络信息被完全隐藏。&lt;/p&gt;</description>
    </item>
    <item>
      <title>图解VoIP#1: 你什么时候需要OpenSIPS或kamailio - 软交换架构演进之路</title>
      <link>https://wdd.js.org/zh/posts/2026/when-you-need-opensips-or-kamailio/</link>
      <pubDate>Mon, 09 Mar 2026 18:26:07 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2026/when-you-need-opensips-or-kamailio/</guid>
      <description>&lt;h1 id=&#34;最简单的架构---1架构&#34;&gt;最简单的架构 - 1架构&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;1架构: 1台FS节点&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;在一个最简单的VoIP架构里，你只需要部署一台具有公网IP的FreeSWITCH,  就可以开始呼叫业务。&lt;/p&gt;
&lt;p&gt;分机直接注册到FS上，然后FS直接对接线路。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/posts/2026/when-you-need-opensips-or-kamailio/p1.drawio.svg&#34;&gt;&lt;/p&gt;
&lt;p&gt;但是要不了多久，你就会发现下面的问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;安全问题&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FS直接公网暴露，必然面临被攻击的事实。因为对接线路虽然可以设置网络策略，但是分机的IP往往是动态变化的。小型的攻击例如恶意的注册扫描，大型的攻击就是DDOS, 直接打满带宽，导致业务必然中断。&lt;/li&gt;
&lt;li&gt;一些简单的安全防范，比如默认端口改成非5060的端口，但是使用现代化的端口扫描工具，6W个端口基本上几秒就能扫描完。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;高可用问题&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;单台FS挂掉，业务就中断了&lt;/li&gt;
&lt;li&gt;停机维护， 业务也会中断&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;扩展问题&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;当业务上量，一台FS就无法满足，必然要增加新的FS节点。&lt;/li&gt;
&lt;li&gt;这时候问题就来了
&lt;ul&gt;
&lt;li&gt;分机信息保存在FS节点中，多FS节点分机注册信息如何同步？&lt;/li&gt;
&lt;li&gt;在呼入的时候，是否要通知SIP-线路去增加新的FS节点信息？ 网络策略是不是又要开一遍？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;支持fs动态扩展架构--2n架构&#34;&gt;支持FS动态扩展架构  2+N架构&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;2+N架构: 2台SIP Proxy，N台FS节点&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/posts/2026/when-you-need-opensips-or-kamailio/p2.drawio.svg&#34;&gt;&lt;/p&gt;
&lt;p&gt;这种架构特点&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;SIP Proxy层具有公网IP，无论分机注册，还是对接线路，SIP信令都需要经过SIP Proxy层&lt;/li&gt;
&lt;li&gt;分机注册信息也保存在SIP Proxy层，FS不再关心分机的注册地址&lt;/li&gt;
&lt;li&gt;SIP Proxy层可以用keep-alive保活，一主一备部署&lt;/li&gt;
&lt;li&gt;FS可以无感扩容，由Proxy层来做负载均衡。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在这个架构图里，我没有引入rtpproxy或者rtpengine的，这时候媒体流的走向就比较尴尬。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;每台FS还必须要要有公网地址&lt;/strong&gt;， 只有这样分机才能直接对接FS。 而原因也很简单，因为opensips或者kamailio没有媒体处理能力。&lt;/p&gt;
&lt;p&gt;这种架构还是无法节约EIP, FS还是可能遭受到公网攻击。&lt;/p&gt;
&lt;h1 id=&#34;2nn架构&#34;&gt;2+N+N架构&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;2+N+N架构: 2台SIP Proxy，N台MediaPrxyo节点, N台FS节点&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;为了彻底让FS不再供网暴露，我们引入媒体代理层。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/posts/2026/when-you-need-opensips-or-kamailio/p3.drawio.svg&#34;&gt;&lt;/p&gt;
&lt;p&gt;这次基于架构2， 引入媒体代理集群，例如使用多台rtpengine机群，用来转发UAC &amp;lt;&amp;gt; FS &amp;lt;&amp;gt; 线路 之间的媒体流&lt;/p&gt;
&lt;h1 id=&#34;三明治架构&#34;&gt;三明治架构&lt;/h1&gt;
&lt;p&gt;可以参考 SIPSwse C5架构 &lt;a href=&#34;https://wdd.js.org/posts/2025/sipwise-c5-arch/&#34;&gt;https://wdd.js.org/posts/2025/sipwise-c5-arch/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/posts/2026/when-you-need-opensips-or-kamailio/p4.drawio.svg&#34;&gt;&lt;/p&gt;
&lt;p&gt;这种架构在媒体层和SIP Proxy层之间又增加一层，我称之为SIP Router层。&lt;/p&gt;</description>
    </item>
    <item>
      <title>ACK消息的URI来自哪里？</title>
      <link>https://wdd.js.org/zh/posts/2026/how-ack-set-request-url/</link>
      <pubDate>Thu, 29 Jan 2026 13:12:36 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2026/how-ack-set-request-url/</guid>
      <description>&lt;h1 id=&#34;简介&#34;&gt;简介&lt;/h1&gt;
&lt;p&gt;这里我们把ACK的场景限定到INVITE收到200响应之后，UAC构造ACK消息的URI来自哪里？&lt;/p&gt;
&lt;p&gt;这里的时序图为&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;sequenceDiagram
    uac -&amp;gt;&amp;gt; uas: INVITE
    uas -&amp;gt;&amp;gt; uac: 200
    uac -&amp;gt;&amp;gt; uas: ACK
&lt;/pre&gt;
&lt;p&gt;我们要把这个问题讲清楚，不要臆造，并且必须提供RFC3261的原文作为参考。&lt;/p&gt;
&lt;h1 id=&#34;rfc3261解读&#34;&gt;RFC3261解读&lt;/h1&gt;
&lt;p&gt;📌 13.2.2.4&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The UAC core MUST generate an ACK request for each 2xx received from the transaction layer&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;✏️ 这里说明，在UAC收到INVITE 200 OK后，必须回复ACK消息。&lt;/p&gt;
&lt;p&gt;📌 12.2.1.1 Generating the Request&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The UAC uses the remote target and route set to build the Request-URI and Route header field of the request. If the route set is empty, the UAC MUST place the remote target URI into the Request-URI. The UAC MUST NOT add a Route header field to the request. If the route set is not empty, and the first URI in the route set contains the lr parameter (see Section 19.1.1), the UAC MUST place the remote target URI into the Request-URI and MUST include a Route header field containing the route set values in order, including all parameters.&lt;/p&gt;</description>
    </item>
    <item>
      <title>天下苦 VOS 久矣</title>
      <link>https://wdd.js.org/zh/posts/2026/the-voip-world-has-suffered-from-vos-for-too-long/</link>
      <pubDate>Tue, 06 Jan 2026 19:00:15 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2026/the-voip-world-has-suffered-from-vos-for-too-long/</guid>
      <description>&lt;p&gt;天下苦 VOS 久矣。
此言非怒而发，乃久用之后，积怨成理也。&lt;/p&gt;
&lt;p&gt;VOS3x、VOS5x，曾有其功。
当年软交换荒芜，SIP 规范未成体系，工程师多凭经验行事。VOS 以一套封装良好的系统，解“能跑”之急，立一时之功，不可不认。&lt;/p&gt;
&lt;p&gt;然功成之后，不思进化；
市占既稳，便少革新。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;天下之患，莫大于此。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一垄断既久问题反成常态&#34;&gt;一、垄断既久，问题反成常态&lt;/h2&gt;
&lt;p&gt;今之 VOS，已非“可选方案”，而成“默认答案”。&lt;/p&gt;
&lt;p&gt;选型之时，不问架构，只问“是不是 VOS”；
排障之时，不查协议，只等“厂商回复”。&lt;/p&gt;
&lt;p&gt;于是，奇景频出：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SIP 行为异于 RFC，而曰“产品设计如此”&lt;/li&gt;
&lt;li&gt;性能瓶颈不可测，而曰“经验上差不多”&lt;/li&gt;
&lt;li&gt;复杂需求难以实现，而曰“VOS 不支持”&lt;/li&gt;
&lt;li&gt;简单需求可实现，而曰“得加钱”&lt;/li&gt;
&lt;li&gt;故障定位止于日志，而曰“已提交工单”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;久而久之，
问题不再被解决，
只是被习惯。&lt;/p&gt;
&lt;h2 id=&#34;二用-vos工程师何其卑微&#34;&gt;二、用 VOS，工程师何其卑微&lt;/h2&gt;
&lt;p&gt;用 VOS 者，常有此感：&lt;/p&gt;
&lt;p&gt;系统在跑，
却不知为何如此跑；
问题已现，
却不知从何而断。&lt;/p&gt;
&lt;p&gt;工程师所做者，不过：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;点配置&lt;/li&gt;
&lt;li&gt;调参数&lt;/li&gt;
&lt;li&gt;猜行为&lt;/li&gt;
&lt;li&gt;等回复&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;软交换本该是工程，
却活成了玄学。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;三opensips--kamailio让系统讲人话&#34;&gt;三、OpenSIPS / Kamailio：让系统“讲人话”&lt;/h2&gt;
&lt;p&gt;或问：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“不用 VOS，又当用谁？”&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;曰：OpenSIPS，Kamailio。&lt;/p&gt;
&lt;p&gt;二者之道，不在“省钱”，而在&lt;strong&gt;透明&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SIP 即 SIP，不自创私货&lt;/li&gt;
&lt;li&gt;路由即代码，行为白纸黑字&lt;/li&gt;
&lt;li&gt;性能可压测，瓶颈可定位&lt;/li&gt;
&lt;li&gt;出问题先看脚本，而非先写邮件&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在此体系之中，
系统不再“猜你想要什么”，
而是“严格执行你所写之逻辑”。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这是工程，
不是占卜。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;四开源之苦在前开源之利在后&#34;&gt;四、开源之苦，在前；开源之利，在后&lt;/h2&gt;
&lt;p&gt;诚然，OpenSIPS / Kamailio 不好上手。
学习曲线陡峭，踩坑在所难免。&lt;/p&gt;</description>
    </item>
    <item>
      <title>SipWise C5 架构分析 WIP</title>
      <link>https://wdd.js.org/zh/posts/2025/sipwise-c5-arch/</link>
      <pubDate>Thu, 16 Oct 2025 17:39:50 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2025/sipwise-c5-arch/</guid>
      <description>&lt;h1 id=&#34;sipwise-c5-架构分析&#34;&gt;SIPWISE C5 架构分析&lt;/h1&gt;
&lt;p&gt;Sipwise C5（又称NGCP——下一代通信平台）是一款基于SIP的开源Class 5 VoIP软交换平台&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/posts/2025/sipwise-c5-arch/arch.drawio.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;整体架构上，sipwise C5 是一个三明治架构， 除了sipwise, 我也看到过类似的VoIP架构， 可见英雄所见略同。&lt;/p&gt;
&lt;h2 id=&#34;接入层&#34;&gt;接入层&lt;/h2&gt;
&lt;p&gt;接入层是整个平台的信令出入口，主要的职责是安全检测和负载均衡。 并不具有业务上的功能，另外也不会使用数据库。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;职责&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;外部SIP信令的入口和内部信令的出口&lt;/li&gt;
&lt;li&gt;SIP信令完整性检查&lt;/li&gt;
&lt;li&gt;拒绝环回SIP信令&lt;/li&gt;
&lt;li&gt;DOS攻击检测&lt;/li&gt;
&lt;li&gt;暴力攻击检测&lt;/li&gt;
&lt;li&gt;TLS转UDP转换&lt;/li&gt;
&lt;li&gt;NAT穿透映射&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;端口&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;5060, SIP/TCP+UDP, 对外接收SIP消息&lt;/li&gt;
&lt;li&gt;5061, SIP/TLS， 对外接收TLS消息&lt;/li&gt;
&lt;li&gt;5060, XMLRPC/TCP, 对内处理RPC调用，来控制kamailio&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;这里有个风险，5060/TCP端口同时用来对外处理SIP消息和对接处理RPC调用，难道&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;实现&lt;/strong&gt;&lt;/p&gt;
&lt;h1 id=&#34;参考&#34;&gt;参考&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sipwise.com/doc/mr6.5.8/sppro/ar01s02.html&#34;&gt;https://www.sipwise.com/doc/mr6.5.8/sppro/ar01s02.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sipwise.com/doc/mr10.3.1/spce/ce/mr10.3.1/architecture/architecture.html&#34;&gt;https://www.sipwise.com/doc/mr10.3.1/spce/ce/mr10.3.1/architecture/architecture.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>使用m4给opensips脚本增加预处理能力</title>
      <link>https://wdd.js.org/zh/posts/2025/m4-with-opensips/</link>
      <pubDate>Sat, 02 Aug 2025 11:17:08 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2025/m4-with-opensips/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;demo 代码仓库 ： &lt;a href=&#34;https://cnb.cool/eddie2072/opensips-forum/-/tree/main/how-to-use-m4&#34;&gt;https://cnb.cool/eddie2072/opensips-forum/-/tree/main/how-to-use-m4&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;h1 id=&#34;使用m4给opensips脚本增加预处理能力&#34;&gt;使用m4给opensips脚本增加预处理能力&lt;/h1&gt;
&lt;h2 id=&#34;为什么要预处理&#34;&gt;为什么要预处理？&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;运维便利&lt;/strong&gt;。有预处理，脚本里的IP地址，端口，密码，用户名等信息，可以由运维人员统一配置，脚本只需要引用配置文件，就可以完成脚本的运行。否则，运维人员只能手工去修改每个配置写死的地方。容易出错，且非常麻烦。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;所以，我们在写脚本的时候，需要从脚本中抽离配置性质的数据。例如监听的IP地址，端口，数据库的用户名和密码等信息。&lt;/p&gt;
&lt;p&gt;这样脚本就变层两个部份，配置文件 + 脚本本身。&lt;/p&gt;
&lt;p&gt;运维人员只需要修改配置文件就可以。 以本demo为例子， 运维在线上部署脚本，只需要修改env.prd.m4文件就可以。&lt;/p&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;预处理可以增加脚本的复用性&lt;/strong&gt;。 不同环境，往往需要的功能不同。A环境需要X功能，B环境不需要X功能，那么怎么维护呢。 不用怕，有了m4条件分支，可以根据不同不配置，渲染出不同的结果。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;m4基本在所有linux都已经安装好了&lt;/strong&gt;，不用额外在安装依赖。 很多有经验的程序员，往往也不知道什么是m4, 其实大名顶顶的autoconf, 底层就依赖了m4。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;m4难不难学&#34;&gt;m4难不难学？&lt;/h2&gt;
&lt;p&gt;m4语法简单，语法强大，但是我们能用到的，基本不超过5个语法。&lt;/p&gt;
&lt;h3 id=&#34;定义宏&#34;&gt;定义宏&lt;/h3&gt;
&lt;p&gt;下面是定义宏的语法，这样写之后，所有字符串ENV_LISTEN_IP都会被替换为127.0.0.1&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;define&lt;/span&gt;(ENV_LISTEN_IP, &lt;span style=&#34;color:#ae81ff&#34;&gt;127.0.0.1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;引用其他文件&#34;&gt;引用其他文件&lt;/h3&gt;
&lt;p&gt;有了引用，我们就不需要把所有功能放到一个大文件中。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;include(&amp;lt;&amp;lt;src/loadmodule.m4&amp;gt;&amp;gt;)
include(&amp;lt;&amp;lt;src/request.m4&amp;gt;&amp;gt;)
include(&amp;lt;&amp;lt;src/relay.m4&amp;gt;&amp;gt;)
include(&amp;lt;&amp;lt;src/per_branch_ops.m4&amp;gt;&amp;gt;)
include(&amp;lt;&amp;lt;src/handle_nat.m4&amp;gt;&amp;gt;)
include(&amp;lt;&amp;lt;src/missed_call.m4&amp;gt;&amp;gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;ifelsecond1cond2-yes-no&#34;&gt;ifelse(cond1,cond2, yes, no)&lt;/h3&gt;
&lt;p&gt;如果cond1和cond2相同，则展开第三个参数yes, 否则展开第四个参数no&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ifelse(ENV_ENABLE_NAT,yes,use nat, not use nat)
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;引号&#34;&gt;引号&lt;/h3&gt;
&lt;p&gt;引号，就是用来告诉m4, 引号里的内容应该看作是一个整体。&lt;/p&gt;
&lt;p&gt;m4默认的引号是``&amp;rsquo;&amp;rsquo;,  看起来很怪异，很难从视觉上做配对。 所有有强迫症，或者视觉洁癖的人，会非常讨厌m4。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;define&lt;/span&gt;(&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;`&lt;/span&gt;ENV_LISTEN_IP&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;127.0.0.1&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;但是这个引号是可以修改的，我们用changequote去修改默认的引号, 将引号改为&lt;code&gt;&amp;lt;&amp;lt;&amp;gt;&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;changequote&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;,&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;define&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;ENV_LISTEN_IP&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;127.0.0.1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;如何调试宏-使用-dv-参数&#34;&gt;如何调试宏, 使用-dV 参数&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;m4 -dV opensips.m4
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;解决宏冲突问题&#34;&gt;解决宏冲突问题&lt;/h3&gt;
&lt;p&gt;如果脚本里有个变量和m4的宏名字冲突，那么往往会出现一些怪异的问题。&lt;/p&gt;
&lt;p&gt;m4早就想到了解决方案， 在执行m4时候，可以加上-P参数，m4所有内置的宏就会必须写成以m4_开头。 例如&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;m4_define&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;ENV_LISTEN_IP&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;127.0.0.1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;m4 -P opensips.m4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;m4的劣势&#34;&gt;m4的劣势&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;m4没有类似foreach的循环，但是可以通过m4的递归实现。&lt;/li&gt;
&lt;li&gt;m4做简单的字符串替换，但是对于复杂字符串处理，m4的效率会比较低，而且语法比较复杂。 但是对于处理opensips的配置文件，m4则是刚刚好的完美工具。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;有意思的几个扩展&#34;&gt;有意思的几个扩展&lt;/h2&gt;
&lt;h3 id=&#34;检查宏是否未定义或者是否为空字符串空则报错退出&#34;&gt;检查宏是否未定义，或者是否为空字符串，空则报错退出&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;m4_divert&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;m4_define&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;ASSERT_NOT_EMPTY&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;,&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;m4_ifelse&lt;/span&gt;(&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;,,&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;m4_errprint&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; is empty &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;m4_m4exit&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;,)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;m4_divert&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)m4_dnl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;ASSERT_NOT_EMPTY&lt;/span&gt;(this_is_empty)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;foreach-循环&#34;&gt;foreach 循环&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;m4_changequote&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;,&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;)m4_dnl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;m4_divert&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;m4_define&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;X_FOREACH&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;m4_pushdef&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;_foreach&lt;/span&gt;(&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$@&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;m4_popdef&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;m4_define&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;_arg1&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;m4_define&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;_foreach&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;m4_ifelse&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;()&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&amp;gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;m4_define&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;, _arg1&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;, (m4_shift&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;), &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;m4_divert&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)m4_dnl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;X_FOREACH&lt;/span&gt;(x,(a.com,b.com,c.com),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  alias&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;udp:x
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  )
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上面会输出&lt;/p&gt;</description>
    </item>
    <item>
      <title>【案例分享】JSSIP 电话无法挂断问题</title>
      <link>https://wdd.js.org/zh/posts/2025/jssip-can-not-drop-call/</link>
      <pubDate>Tue, 15 Jul 2025 20:00:08 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2025/jssip-can-not-drop-call/</guid>
      <description>&lt;p&gt;当听到分机无法挂断电话时，通常有以下几种可能的原因：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在做Record-Route时，使用了错误的内外网IP地址。导致BYE请求按照route头发送时，无法正确找到对应的服务器。&lt;/li&gt;
&lt;li&gt;Contact头部的URI不正确，导致BYE请求无法找到对应的服务器。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;时序图如下；&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;sequenceDiagram
autonumber
participant u1 as user1
participant o as opensips
participant u2 as user2

u1-&amp;gt;&amp;gt;o: INVITE
o-&amp;gt;&amp;gt;u2: INVITE
u2--&amp;gt;&amp;gt;o: 200 OK
o--&amp;gt;&amp;gt;u1: 200 OK
u1-&amp;gt;&amp;gt;o: ACK
o-&amp;gt;&amp;gt;u2: ACK
u2-&amp;gt;&amp;gt;o: BYE
o--&amp;gt;&amp;gt;u2: 477 Send failed (477/TM)
&lt;/pre&gt;
&lt;p&gt;477错误一般是按照route头或者contact转发时，找不到对应的socket。 在使用tcp作为传输协议时，例如tcp/tls/wss注册的分机比较常见。&lt;/p&gt;
&lt;p&gt;有以下可能&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;分机到opensips的tcp连接断开&lt;/li&gt;
&lt;li&gt;contact使用错误的transport参数&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;从过观察第2个信令的Conact头，发现transport=ws, User-Agent=JSSip。 正常情况下，jssip应该使用wss作为transport。&lt;/p&gt;
&lt;p&gt;所以解决办法是，在jssip的配置中，将transport改为wss。&lt;/p&gt;
&lt;p&gt;还有一个解决方案， 就是让jssip通过nginx转发wss请求，让nginx转发到opensips的ws端口, 也能解决问题。&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;sequenceDiagram
autonumber

jssip -&amp;gt;&amp;gt; nginx: wss
nginx -&amp;gt;&amp;gt; opensips: ws
&lt;/pre&gt;</description>
    </item>
    <item>
      <title>【案例分享】外线呼入，SIP分机为何无响应？</title>
      <link>https://wdd.js.org/zh/posts/2025/ua-not-answer/</link>
      <pubDate>Tue, 15 Jul 2025 19:39:57 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2025/ua-not-answer/</guid>
      <description>&lt;h1 id=&#34;案例分享&#34;&gt;案例分享&lt;/h1&gt;
&lt;p&gt;最近有客户反馈，自己的话机最近一两周都没有收到来电了，感觉很奇怪，他自己呼叫400号码，然后转分机，也接不通。&lt;/p&gt;
&lt;h2 id=&#34;组网结构&#34;&gt;组网结构&lt;/h2&gt;
&lt;pre class=&#34;mermaid&#34;&gt;flowchart LR
ua1(分机)
fw1(防火墙)
uas1(SIP服务器)

ua1 --&amp;gt; fw1
fw1 --&amp;gt; uas1
&lt;/pre&gt;
&lt;h2 id=&#34;排查思路&#34;&gt;排查思路&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;首先排查服务端，从日志来看，分机的注册是正常的，每隔30多秒就注册一次。&lt;/li&gt;
&lt;li&gt;然后排查呼叫信令图，发现发送给分机的INVITE， 分机那边没有任何反应&lt;/li&gt;
&lt;li&gt;接着请求客户远程协助，在分机上抓包，发现只能抓到注册包，没有INVITE的回应。&lt;/li&gt;
&lt;li&gt;询问客户，他们公司有没有使用防火墙，客户说有。&lt;/li&gt;
&lt;li&gt;然后让客户检查他们防火墙的设置，关闭SIP ALG功能，但是也无效&lt;/li&gt;
&lt;li&gt;然后让客户找网络负责人，在防火墙上抓包，发现防火墙收到了INVITE，但是没有转发给内部分机, 原因未知&lt;/li&gt;
&lt;li&gt;最后找防火墙厂商，发现是防火墙的UDP组包没有开启，开启UDP分片重组后，呼入电话能正常进线&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;
&lt;p&gt;此刻，我回想起曾经写的 &lt;a href=&#34;https://wdd.js.org/opensips/ch7/big-udp-msg/&#34;&gt;UDP分片导致SIP消息丢失&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;没想到，在防火墙上也遇到了同样的问题。&lt;/p&gt;</description>
    </item>
    <item>
      <title>SIP安全 - DTLS client Hello 攻击白皮书</title>
      <link>https://wdd.js.org/zh/posts/2025/dtls-hello-attack/</link>
      <pubDate>Mon, 14 Jul 2025 23:13:23 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2025/dtls-hello-attack/</guid>
      <description>&lt;h1 id=&#34;tldr&#34;&gt;TL;DR&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;攻击者伪造DTLS ClientHello消息，在SIP服务器和客户端之间建立一个非预期的连接。导致正常链接被阻断。&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;影响软件&#34;&gt;影响软件&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;FreeSWITCH&lt;/li&gt;
&lt;li&gt;RTPengine&lt;/li&gt;
&lt;li&gt;asterisk&lt;/li&gt;
&lt;li&gt;FreePBX&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;漏洞白皮书&#34;&gt;漏洞白皮书&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://wdd.js.org/zh/posts/2025/dtls-hello-attack/webrtc-hello-race-conditions-paper.pdf&#34;&gt;webrtc-hello-race-conditions-paper&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&#34;表现&#34;&gt;表现&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;应答后呼叫无声&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;参考&#34;&gt;参考&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/EnableSecurity/advisories/tree/master/ES2023-03-rtpengine-dtls-hello-race&#34;&gt;https://github.com/EnableSecurity/advisories/tree/master/ES2023-03-rtpengine-dtls-hello-race&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/EnableSecurity/advisories/tree/master/ES2023-02-freeswitch-dtls-hello-race&#34;&gt;https://github.com/EnableSecurity/advisories/tree/master/ES2023-02-freeswitch-dtls-hello-race&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/EnableSecurity/advisories/tree/master/ES2023-03-rtpengine-dtls-hello-race&#34;&gt;https://github.com/EnableSecurity/advisories/tree/master/ES2023-03-rtpengine-dtls-hello-race&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>OpenSIPS Summit 2025 速看</title>
      <link>https://wdd.js.org/zh/posts/2025/opensips-summit-2025/</link>
      <pubDate>Mon, 14 Jul 2025 21:52:23 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2025/opensips-summit-2025/</guid>
      <description>&lt;p&gt;2025 年 5 月 27 - 5 月 30 日, OpenSIPS Summit 2025 在荷兰阿姆斯特丹举行。&lt;/p&gt;
&lt;p&gt;最近我才有时间，看完所有的会议资料，包括 PDF 和 PPT。&lt;/p&gt;
&lt;p&gt;下面是我整理的，认为比较有价值的一些内容。以飨读者。&lt;/p&gt;
&lt;h1 id=&#34;1-加强-sdp-处理&#34;&gt;1. 加强 SDP 处理&lt;/h1&gt;
&lt;p&gt;对 SDP 的处理，如果用 OpenSIPS 脚本来做，将会非常蹩脚。 生产环境一般都是使用 rtpengine 或者 rtpproxy 来处理。&lt;/p&gt;
&lt;p&gt;但是，最近的 OpenSIPS 版本，已经可以支持 SDP 处理了。 可以直接在 OpenSIPS 脚本里处理 SDP。&lt;/p&gt;
&lt;p&gt;说实话，我看了新的方案，我觉得，还不如用 rtpengine 或者 rtpproxy。&lt;/p&gt;
&lt;p&gt;但是聊胜于无吧，感兴趣的可以看看原文。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://wdd.js.org/zh/posts/2025/opensips-summit-2025/OpenSIPS%20Summit%202025%20-%20Liviu%20Chircu%20-%20Enhanced%20Media%20Operations%20with%20Structured%20SDP.pdf&#34;&gt;OpenSIPS Summit 2025 - Liviu Chircu - Enhanced Media Operations with Structured SDP&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;除此以外，PDF 也提到一些有趣的事情，比如 SDP 随着时间推移，增强和很多功能，包也变得越来越大&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;时期&lt;/th&gt;
          &lt;th&gt;内容&lt;/th&gt;
          &lt;th&gt;包大小&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;1998&lt;/td&gt;
          &lt;td&gt;基本媒体行&lt;/td&gt;
          &lt;td&gt;200-400 bytes&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2002&lt;/td&gt;
          &lt;td&gt;编码协商，rtpmap&lt;/td&gt;
          &lt;td&gt;500-1000 bytes&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2010&lt;/td&gt;
          &lt;td&gt;ICE/DTLS&lt;/td&gt;
          &lt;td&gt;1-2 kb&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2015&lt;/td&gt;
          &lt;td&gt;WebRTC, Simulcast, Bound, MID&lt;/td&gt;
          &lt;td&gt;2-3kb&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;在线会议，SFU&lt;/td&gt;
          &lt;td&gt;3-5 kb&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;可以想象，随着媒体能力的增强，UDP包的SIP信令中的分片几乎成为必然，所以，是否可以考虑有限使用TCP/TLS来传输信令呢？&lt;/p&gt;</description>
    </item>
    <item>
      <title>DTLS协商失败导致无声问题</title>
      <link>https://wdd.js.org/zh/posts/2025/dtls-negotiation-failed-no-audio/</link>
      <pubDate>Tue, 24 Jun 2025 21:06:11 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2025/dtls-negotiation-failed-no-audio/</guid>
      <description>&lt;h1 id=&#34;1-简介&#34;&gt;1. 简介&lt;/h1&gt;
&lt;p&gt;DTLS（Datagram Transport Layer Security，数据报传输层安全协议）是一种为基于数据报的应用（如UDP）提供安全通信的协议。它是TLS（传输层安全协议）的扩展，专门设计用于不可靠的传输协议（如UDP），以实现数据加密、身份认证和消息完整性保护。DTLS常用于VoIP、视频会议、WebRTC等实时通信场景。&lt;/p&gt;
&lt;p&gt;DTLS在WebRTC音视频中是强制必须使用的，否则媒体协商阶段就会失败。&lt;/p&gt;
&lt;p&gt;使用DTLS后，就算中间人从网络中抓包，抓到了RTP流，在播放RTP流时，里面也全是噪声，无法播放的。&lt;/p&gt;
&lt;p&gt;今天要讲的是就是DTLS协商失败导致电话即使接通，也无声的问题。&lt;/p&gt;
&lt;h1 id=&#34;2-网络结构说明&#34;&gt;2. 网络结构说明&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;UAS: sip server, OpenSIPS + RTPEngine组成&lt;/li&gt;
&lt;li&gt;UAC: WebRTC 分机&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;F1. UAS ----&amp;gt; UAC: INVITE &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;SDP&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;F2. UAS &amp;lt;---- UAC: &lt;span style=&#34;color:#ae81ff&#34;&gt;180&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;F3. UAS &amp;lt;---- UAC: &lt;span style=&#34;color:#ae81ff&#34;&gt;200&lt;/span&gt; Ok &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;SDP&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;F4. UAS ----&amp;gt; UAC: ACK
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;从SIP信令上看，被叫应答后，UAS和UAC之间的双向媒体流应该建立起来，但是实际上却无声。&lt;/p&gt;
&lt;h1 id=&#34;3-icestundtls&#34;&gt;3. ICE/STUN/DTLS&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ICE&lt;/strong&gt;: WebRTC中的ICE（Interactive Connectivity Establishment，交互式连接建立）是一种网络协议，用于帮助WebRTC客户端在不同网络环境下建立点对点（P2P）连接。ICE的主要作用是解决NAT穿透和防火墙问题，使两个终端能够找到最佳的通信路径。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;STUN&lt;/strong&gt;: WebRTC中的STUN（Session Traversal Utilities for NAT，NAT会话穿越实用工具）是一种网络协议，主要用于帮助客户端发现自己的公网IP地址和端口。由于很多设备处于NAT（网络地址转换）或防火墙之后，直接通信会遇到障碍，STUN可以让客户端知道外部网络如何访问自己&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在分机应答后，并在WebRTC发送本地媒体流前，还需要两个步骤协商完成UAC才会发送语音流&lt;/p&gt;
&lt;h2 id=&#34;31-stun协商&#34;&gt;3.1 STUN协商&lt;/h2&gt;
&lt;p&gt;UAC收到来自UAS的SDP, 里面一般有如下内容&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;m&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;audio &lt;span style=&#34;color:#ae81ff&#34;&gt;54322&lt;/span&gt; UDP/TLS/RTP/SAVPF &lt;span style=&#34;color:#ae81ff&#34;&gt;111&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;ice-ufrag:abcd
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;ice-pwd:1234567890abcdef
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;ice-options:trickle
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;fingerprint:sha-256 12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;setup:actpass
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;candidate:1 &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; udp &lt;span style=&#34;color:#ae81ff&#34;&gt;2130706431&lt;/span&gt; 1.2.3.4 &lt;span style=&#34;color:#ae81ff&#34;&gt;54322&lt;/span&gt; typ host
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;STUN是一个请求响应模型的协议。UAC将会向&lt;code&gt;a=candidate&lt;/code&gt;里的1.2.3.4:54322 发送UDP消息&lt;/p&gt;</description>
    </item>
    <item>
      <title>RTPEngine mr13版本, 特殊的fmtp参数会导致某些语音编码被移除</title>
      <link>https://wdd.js.org/zh/posts/2025/rtpengine-fmtp-g711-remove-codec/</link>
      <pubDate>Wed, 18 Jun 2025 20:04:52 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2025/rtpengine-fmtp-g711-remove-codec/</guid>
      <description>&lt;h1 id=&#34;场景说明&#34;&gt;场景说明&lt;/h1&gt;
&lt;p&gt;如下图所示&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Offer阶段，F1, F2 步骤里PCMU编码有个fmtp参数&lt;code&gt;abc=no&lt;/code&gt;, 这个参数可能只对呼叫发起方有意义，对被叫方来说，只会被忽略。&lt;/li&gt;
&lt;li&gt;Answer阶段, 例如被叫是个FreeSWITCH, 它不认识abc=no, 就直接忽略，然后应答编码是PCMU。但是rtpengine认为不带abc=no的参数，就认为这个PCMU的编码是不可能被选中的，然后就直接删掉了PCMU编码， 只保留了一个101编码&lt;/li&gt;
&lt;li&gt;由于主叫收到101的编码，而没有语音的编码，所以主叫收到200 Ok后立马就发送了BYE&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;// F1: send offer to rtpegnine
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;m&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;audio &lt;span style=&#34;color:#ae81ff&#34;&gt;2000&lt;/span&gt; RTP/AVP &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;101&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;rtpmap:0 PCMU/8000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;fmtp:0 abc&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;no
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;rtpmap:8 PCMA/8000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;fmtp:8 abc&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;no
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;rtpmap:101 telephone-event/8000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;fmtp:101 0-15
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;// F2: receive offer from rtpengine
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;m&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;audio PORT RTP/AVP &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;101&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;c&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;IN IP4 203.0.113.1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;rtpmap:0 PCMU/8000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;fmtp:0 abc&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;no
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;rtpmap:8 PCMA/8000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;fmtp:8 abc&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;no
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;rtpmap:101 telephone-event/8000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;fmtp:101 0-15
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;// F3: send answer to rtepngine
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;m&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;audio &lt;span style=&#34;color:#ae81ff&#34;&gt;2002&lt;/span&gt; RTP/AVP &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;101&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;rtpmap:0 PCMU/8000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;rtpmap:101 telephone-event/8000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;fmtp:101 0-15
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;// F4: expect receive answer from rtpengine
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;m&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;audio PORT RTP/AVP &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;101&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;c&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;IN IP4 203.0.113.1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;rtpmap:0 PCMU/8000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;rtpmap:101 telephone-event/8000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;fmtp:101 0-15
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;问题原因&#34;&gt;问题原因&lt;/h1&gt;
&lt;p&gt;刚开始我以为是， &lt;a href=&#34;https://github.com/sipwise/rtpengine/commit/9c00f30&#34;&gt;https://github.com/sipwise/rtpengine/commit/9c00f30&lt;/a&gt; 这次commit引起的问题，我尝试注释代码，然后进行测试，发现可以解决问题。&lt;/p&gt;</description>
    </item>
    <item>
      <title>VoIP Server 高可用架构设计</title>
      <link>https://wdd.js.org/zh/opensips/ch1/ha/</link>
      <pubDate>Tue, 27 May 2025 20:10:22 +0800</pubDate>
      <guid>https://wdd.js.org/zh/opensips/ch1/ha/</guid>
      <description>&lt;h1 id=&#34;简介&#34;&gt;简介&lt;/h1&gt;
&lt;p&gt;VoIP高可用包含很多方面，主要包括：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;接入层高可用：怎么保证某个接入点出现问题，不会影响到整个平台不可用？&lt;/li&gt;
&lt;li&gt;核心层高可用：怎么保证路由选择的高可用，某个网关不可用，继续尝试其他网关？&lt;/li&gt;
&lt;li&gt;存储层高可用：怎么保证不会丢失录音文件，怎么保证录音文件的完整性？&lt;/li&gt;
&lt;li&gt;数据库层高可用：怎么保证注册信息能够在集群中同步？&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;接入层高可用&#34;&gt;接入层高可用&lt;/h1&gt;
&lt;p&gt;最简单的场景， 只有一个fs, 无论是ua还是gw都接入到fs1上&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ua1 ----&amp;gt; fs1
ua2 ----&amp;gt; fs1
gw1 ----&amp;gt; fs1
gw2 ----&amp;gt; fs1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果要实现高可用，最简单的做法就是再加一个fs2。但是加了fs2之后，ua和gw的接入策略就需要改变了。&lt;/p&gt;
&lt;p&gt;为了保持客户端的接入策略不变，最简单的做法加上一个负载均衡器，然后由负载均衡器来做信令转发。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ua1 ----&amp;gt; op1 ----&amp;gt; fs1
ua2 ----&amp;gt; |   ----&amp;gt; fs2
gw1 ----&amp;gt; |
gw2 ----&amp;gt; |
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;op1是单节点的，也会存在单点故障问题，因此引入op2。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ua1 ----&amp;gt; op1 ----&amp;gt; fs1
ua2 ----&amp;gt; op2 ----&amp;gt; fs2
gw1 ----&amp;gt; |
gw2 ----&amp;gt; |
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;引入op2之后，有两个方案来保证高可用：&lt;/p&gt;
&lt;p&gt;方案1, 主备: op1和op2用VIP来对外提供服务，op1和op2的VIP是一样的。实际只有一个在工作，另外一个处于备份状态。 一旦op1出现问题，op2接管VIP对外提供服务。
- 优点: 简单
- 缺点:
- 兼容性：不是所有云平台都支持VIP
- 成本：需要额外的硬件成本，而且还是闲置状态
- 负载：op1和op2都需要对外提供服务，但是实际上只有一个在工作，一个节点的处理能力有限，总会达到瓶颈&lt;/p&gt;</description>
    </item>
    <item>
      <title>离谱的通话无声问题排查记录</title>
      <link>https://wdd.js.org/zh/posts/2025/no-sound-during-a-call/</link>
      <pubDate>Wed, 07 May 2025 22:45:26 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2025/no-sound-during-a-call/</guid>
      <description>&lt;h1 id=&#34;简化网络模型&#34;&gt;简化网络模型&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;A 硬件话机&lt;/li&gt;
&lt;li&gt;S SIP 服务器/媒体服务器&lt;/li&gt;
&lt;li&gt;B 客户手机&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;A &amp;lt;-SIP/RTP&amp;gt; S &amp;lt;-SIP/RTP&amp;gt; B
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;问题说明&#34;&gt;问题说明&lt;/h1&gt;
&lt;p&gt;通话接通后，双方听不到对方的声音。&lt;/p&gt;
&lt;h1 id=&#34;呼叫流程&#34;&gt;呼叫流程&lt;/h1&gt;
&lt;p&gt;S 发起呼叫，A 接听后，bridge B&lt;/p&gt;
&lt;h1 id=&#34;排查思路&#34;&gt;排查思路&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;检查S在INVITE A时，SDP里携带的c=行，是否是S的公网IP。检查后无问题&lt;/li&gt;
&lt;li&gt;在A上抓包，发现有 S-&amp;gt;A的RTP包，也有 A-&amp;gt;S 的 RTP 包。&lt;/li&gt;
&lt;li&gt;将第二步的抓包文件拿到wireshark中分析。发现S-&amp;gt;A方向的包是正常的，能播放出声音；A-&amp;gt;S方向虽然有RTP包，但是看波形是一条直线，非常奇怪。&lt;/li&gt;
&lt;li&gt;S-&amp;gt;A方向的RTP包，在wireshark中能播放出声音，理论上A应该能听到B的声音的。但是用户反馈听不到。&lt;/li&gt;
&lt;li&gt;咨询用户，用户是如何接听电话的。用户反馈是通过话机手柄接听的电话&lt;/li&gt;
&lt;li&gt;让后让客户使用免提的方式拨打接听电话，发现可以听到声音。&lt;/li&gt;
&lt;li&gt;让客户拍照话机手柄插入话机的接口，发现手柄插入的接头插入了耳麦的接口。&lt;/li&gt;
&lt;li&gt;让客户将手柄插入正确的手柄接口，问题解决。&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;延伸思考&#34;&gt;延伸思考&lt;/h1&gt;
&lt;p&gt;这次问题排查，让我想起了之前看过的思科的&lt;a href=&#34;https://www.cisco.com/c/zh_cn/support/docs/voice/voice-quality/211299-Troubleshoot-Voice-Quality-Issues.pdf&#34;&gt;排除语音质量问题&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这篇文章把语音质量问题分为三类：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;网络相关(包括网关(GW)和PSTN问题)&lt;/li&gt;
&lt;li&gt;电话型号/固件相关&lt;/li&gt;
&lt;li&gt;设备(例如头戴式耳机)相关&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在步骤上：&lt;/p&gt;
&lt;p&gt;步骤1.隔离语音质量问题的第一步是找出确切的用户体验并与他们交谈（无论是面对面还是通过电话），以获得对语音质量问题的准确描述。如果有大量用户报告问题，请与他们的样本（可能是5-10个）交谈，以获得对症状的准确描述。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;但是实际情况下，我们有时候迫于形势，往往只从一两个客户那里获得只言片语的信息，然后就开始排查了。客户的只言片语如果带有误导性，那么排查的方向就错了。&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;步骤2.记录物理位置(例如站点A，2楼)、用户名（用户的电话）、目录号码(DN)、电话型号（例如8865）、电话固件(例如11.5.1)和遇到语音质量问题的电话的IP地址。创建一个按物理位置排序的电子表格。在开始排除故障时创建此电子表格需要30分钟（或更短时间），可节省数小时甚至数天的故障排除时间。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;记录信息很重要，但是实际操作中，往往因为时间紧迫，而没有记录这些信息。或者这些信息记录在头脑中，但是排查到最后才发现，自己忘记了某些信息。&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;步骤3.创建电子表格后，查看电话列表，了解电话有哪些共同之处，以及它们与没有语音质量问题的其他电话有何不同。之后，您可以意识到所有有问题的电话都位于同一栋大楼和同一楼层，您可以意识到有问题的电话连接到最近升级的交换机，或者您可以看到所有有问题的电话都位于特定固件上。&lt;/p&gt;
&lt;h1 id=&#34;总结&#34;&gt;总结&lt;/h1&gt;
&lt;p&gt;搞VoIP这么久，碰到过很多疑难杂症。排查思路往往都是从软件或者网络策略层面去排查。 很少考虑到终端的固件和硬件设备上。&lt;/p&gt;
&lt;p&gt;但是这次排查通话无声的问题，让我印象深刻的是，排查到最后才发现是硬件问题。&lt;/p&gt;
&lt;p&gt;从声音的输出输出上，有不同的设备，例如有线耳机、蓝牙耳机、话机手柄、免提等。&lt;/p&gt;
&lt;p&gt;排查这类问题，需要多方面考量。需要挖掘客户的实际使用场景，才能定位到真正的问题。&lt;/p&gt;
&lt;h1 id=&#34;反思&#34;&gt;反思&lt;/h1&gt;
&lt;p&gt;客户的硬件话机，有两个接口。 手柄的接口和耳麦的接口是共用一套接口的。虽然接口上标注的很清楚，但是客户在接线的时候，没有注意到这点。&lt;/p&gt;
&lt;p&gt;这要怎么避免呢？ 骂客户是傻逼吗？&lt;/p&gt;
&lt;p&gt;是不是在设计接口的时候，就应该使用不同形状的接口。 比如手柄接口是圆形，耳麦接口是方形。 这样就能避免这种问题了。&lt;/p&gt;
&lt;p&gt;或者说，接口是通用的。无论是手柄还是耳麦，插上都能用呢。&lt;/p&gt;
&lt;p&gt;还有一种方案，就是只保留一个接口，手柄和耳麦共用一套接口。两者是互斥关系。&lt;/p&gt;</description>
    </item>
    <item>
      <title>DNS域名解析对MicroSIP注册的影响分析</title>
      <link>https://wdd.js.org/zh/posts/2025/dns-and-microsip-register/</link>
      <pubDate>Wed, 30 Apr 2025 17:36:58 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2025/dns-and-microsip-register/</guid>
      <description>&lt;h1 id=&#34;microsip-dns域名解析影响分析&#34;&gt;microSIP DNS域名解析影响分析&lt;/h1&gt;
&lt;p&gt;MicroSIP是一款流行的windows VoIP客户端，它允许用户通过互联网进行语音和视频通话。在使用MicroSIP时，DNS域名解析是确保正确连接到服务器的重要步骤之一。&lt;/p&gt;
&lt;p&gt;DNS域名解析是将人类可读的域名（如www.example.com）转换为机器可读的IP地址的过程。这个过程通常由用户的网络服务提供商(ISP)或本地计算机上的DNS缓存完成。&lt;/p&gt;
&lt;p&gt;域名解析可以将一个域名解析为多个IP地址，例如：[ip1, ip2, ip3], 但是每次解析返回的顺序往往是不确定的，这取决于DNS服务器的配置和负载均衡策略。&lt;/p&gt;
&lt;p&gt;例如第一次解析的结果可能是[ip1, ip2, ip3]，而第二次解析的结果可能是[ip2, ip3, ip1]。&lt;/p&gt;
&lt;p&gt;MicroSIP客户端在注册时，会尝试连接到这些IP地址中的第一个。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;当分机使用TCP方式注册时，如果其第一个IP地址无法连接，它会继续尝试下一个IP地址，直到成功或所有IP地址都失败为止&lt;/li&gt;
&lt;li&gt;如果分机使用UDP方式注册，它只会用第一个IP地址尝试注册，如果失败，还是继续尝试第一个IP。 这种行为似乎有点傻，为什么一直要尝试第一个IP地址，而不是尝试下一个呢？ MicroSIP底层用了pjsip库，而pjsip只有在用tcp/tls注册时， 才会自动尝试下一个IP。pjsip官网也给出了具体的解决方案，就是应用层主动调用 pjsua_acc_modify() 函数，手动修改账号配置，然后重新注册。 但是microSIP并没有这么做，而是直接用一个固定的IP地址去尝试注册。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Our DNS SRV failover support is only limited to TCP (or TLS) connect failure, which in this case pjsip will automatically retries the next server.
&lt;a href=&#34;https://docs.pjsip.org/en/latest/specific-guides/sip/dns_failover.html&#34;&gt;https://docs.pjsip.org/en/latest/specific-guides/sip/dns_failover.html&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;所以，总体上说。在使用域名注册的情况下，当前的注册和上一次的注册可能发往不同的SIP服务器。&lt;/p&gt;
&lt;p&gt;考虑如下场景：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# t1 dns解析结果 ip1, ip2, ip3
REGISTER sip:ip1:5060 SIP/2.0
200 Ok

# t2 dns解析结果 ip3, ip1, ip2
REGISTER sip:ip3:5060 SIP/2.0
200 ok
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;一般分机都在内网环境，出口的公网IP是不变的，但是t1和t2的注册由于目标IP不同，所以出口的NAT映射的端口也是不同的。&lt;/p&gt;</description>
    </item>
    <item>
      <title>读到无法解析的TCP包后, kamailio如何处理？</title>
      <link>https://wdd.js.org/zh/kamailio/read-bad-tcp/</link>
      <pubDate>Fri, 18 Apr 2025 23:05:15 +0800</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/read-bad-tcp/</guid>
      <description>&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;receive_msg&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;buf, &lt;span style=&#34;color:#66d9ef&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; len, &lt;span style=&#34;color:#66d9ef&#34;&gt;receive_info_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;rcv_info) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2&lt;/span&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;parse_msg&lt;/span&gt;(buf, len, msg) &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3&lt;/span&gt;&lt;span&gt;		errsipmsg &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4&lt;/span&gt;&lt;span&gt;		evp.data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)msg;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#3c3d38&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// note: 这里尝试查找并执行nosip模块的 event_route[nosip:msg]事件路由
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 一般情况下，如果没有找到，那么ret的值是-1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 那么这里的if内部不会执行
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;((ret &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sr_event_exec&lt;/span&gt;(SREV_RCV_NOSIP, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;evp)) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; NONSIP_MSG_DROP) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10&lt;/span&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;LM_DBG&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;attempt of nonsip message processing failed&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11&lt;/span&gt;&lt;span&gt;		} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(ret &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; NONSIP_MSG_DROP) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12&lt;/span&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;// 这里也不会执行
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;LM_DBG&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;nonsip message processing completed&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14&lt;/span&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;goto&lt;/span&gt; end;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15&lt;/span&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16&lt;/span&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 由于在上面的判断里errsipmsg被设置成1，所以这里的if条件成立
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(errsipmsg &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 打印报错信息，并执行核心错误处理
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;LOG&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;cfg_get&lt;/span&gt;(core, core_cfg, sip_parser_log),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22&lt;/span&gt;&lt;span&gt;				&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;core parsing of SIP message failed (%s:%d/%d)&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23&lt;/span&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;ip_addr2a&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;msg&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;rcv.src_ip), (&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;)msg&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;rcv.src_port,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24&lt;/span&gt;&lt;span&gt;				(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;)msg&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;rcv.proto);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25&lt;/span&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;sr_core_ert_run&lt;/span&gt;(msg, SR_CORE_ERT_RECEIVE_PARSE_ERROR);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;26&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;27&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 跳转到error02标签，执行后续的清理工作
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;28&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;goto&lt;/span&gt; error02;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;29&lt;/span&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;30&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;31&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 跳转到error02标签，执行后续的清理工作
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;32&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;error02:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;33&lt;/span&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;free_sip_msg&lt;/span&gt;(msg);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;34&lt;/span&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;pkg_free&lt;/span&gt;(msg);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;35&lt;/span&gt;&lt;span&gt;error00:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;36&lt;/span&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;ksr_msg_env_reset&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;37&lt;/span&gt;&lt;span&gt;	&lt;span style=&#34;color:#75715e&#34;&gt;/* reset log prefix */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;38&lt;/span&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;log_prefix_set&lt;/span&gt;(NULL);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;39&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;40&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 返回-1，表示出错
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;41&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;42&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;如果调用receive_msg返回负数，那么从调用栈向上查找receive_tcp_msg函数也会返回负数
&lt;ul&gt;
&lt;li&gt;int receive_tcp_msg(char *tcpbuf, unsigned int len,struct receive_info *rcv_info, struct tcp_connection *con)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;receive_tcp_msg函数返回负数，那么向上查找，tcp_read_req也会返回负数
&lt;ul&gt;
&lt;li&gt;int tcp_read_req(struct tcp_connection *con, int *bytes_read,rd_conn_flags_t *read_flags)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;tcp_read_req返回负数
&lt;ul&gt;
&lt;li&gt;inline static int handle_io(struct fd_map *fm, short events, int idx)在这个函数内部&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;unlikely&lt;/span&gt;(bytes &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;LOG&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;cfg_get&lt;/span&gt;(core, core_cfg, corelog),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ERROR: tcp_read_req: error reading - c: %p r: %p (%d)&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					con, req, bytes);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			resp &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; CONN_ERROR;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;goto&lt;/span&gt; end_req;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        resp &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;tcp_read_req&lt;/span&gt;(con, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;n, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;read_flags);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;unlikely&lt;/span&gt;(resp &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#75715e&#34;&gt;/* some error occurred, but on the new fd, not on the tcp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;				 * main fd, so keep the ret value */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;unlikely&lt;/span&gt;(resp &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; CONN_EOF))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					con&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;state &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; S_CONN_BAD;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;release_tcpconn&lt;/span&gt;(con, resp, tcpmain_sock);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;整个调用链条是这样的：
handle_io -&amp;gt; tcp_read_req -&amp;gt; receive_tcp_msg -&amp;gt; receive_msg&lt;/p&gt;</description>
    </item>
    <item>
      <title>Hot Reload OpenSIPS vs Kamailio</title>
      <link>https://wdd.js.org/zh/posts/2025/hot-reload-opensips-vs-kamailio/</link>
      <pubDate>Sat, 29 Mar 2025 13:49:38 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2025/hot-reload-opensips-vs-kamailio/</guid>
      <description>&lt;p&gt;用过nginx的都知道，改了nginx的配置文件，只需要执行&lt;code&gt;nginx -s reload&lt;/code&gt;就可以让改动生效，而不用重启整个服务。&lt;/p&gt;
&lt;p&gt;在kamailio和opensips中，也有类似的热重载功能。&lt;/p&gt;
&lt;p&gt;在kamailio中，如果要热重载配置文件，只需要执行&lt;code&gt;kamcmd app_jsdt.reload&lt;/code&gt;即可。
在opensips中，如果要热重载配置文件，只需要执行&lt;code&gt;opensips-cli -x mi reload_routes&lt;/code&gt;即可。&lt;/p&gt;
&lt;p&gt;理想很丰满，现实很骨感。&lt;/p&gt;
&lt;p&gt;如果要只是修改路由模块，两者都可以做热重载。 如果要动态的新增一些模块，那就必须要重启。&lt;/p&gt;
&lt;h1 id=&#34;kamailio的实现方案&#34;&gt;Kamailio的实现方案&lt;/h1&gt;
&lt;p&gt;必须要用KEMI框架： cfg + [lua|js|python|ruby]&lt;/p&gt;
&lt;p&gt;用这个框架，你写的路由脚本将包括两个部分&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;核心模块，全局配置，模块加载，模块配置，事件路由这部分内容还是写在cfg文件中。&lt;/li&gt;
&lt;li&gt;请求路由、响应路由、分支路由、失败路由等这部分内容可以用lua、js、 python等来写。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在热重载的时候，实际上只有外部脚本会被重新加载，而核心模块是不会被重新加载的。&lt;/p&gt;
&lt;p&gt;因为部分路由用其他脚本编写，必然涉及到性能比较。官方给出的结论是，在同等条件下，lua的性能是最好的。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.kamailio.org/wikidocs/devel/config-engines/#interpreters-performances&#34;&gt;https://www.kamailio.org/wikidocs/devel/config-engines/#interpreters-performances&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;但是实际生产环境如何，还不好说。&lt;/p&gt;
&lt;p&gt;另外一点，就是并不是所有模块都实现了KEMI框架的接口，可能存在风险。&lt;/p&gt;
&lt;h1 id=&#34;opensips的实现方案&#34;&gt;OpenSIPS的实现方案&lt;/h1&gt;
&lt;p&gt;OpenSIPS在3.0版本首次引入了热重载路由脚本的能力，脚本还是cfg，没有引入其他语言。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.opensips.org/Documentation/Interface-CoreMI-3-0#toc8&#34;&gt;https://www.opensips.org/Documentation/Interface-CoreMI-3-0#toc8&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&#34;结论&#34;&gt;结论&lt;/h1&gt;
&lt;p&gt;总体而言，目的是相同的，都是为了热重载路由。&lt;/p&gt;
&lt;p&gt;kamailio的方案看似灵活，实则复杂。如果cfg本身就能做热重载，那么就没必要引入其他语言。&lt;/p&gt;
&lt;p&gt;我更倾向使用OpenSIPS的方案&lt;/p&gt;
&lt;h1 id=&#34;参考&#34;&gt;参考&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.opensips.org/2019/04/04/no-downtime-for-opensips-3-0-restarts/&#34;&gt;https://blog.opensips.org/2019/04/04/no-downtime-for-opensips-3-0-restarts/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>开发学习笔记</title>
      <link>https://wdd.js.org/zh/kamailio/devel-guide-note/</link>
      <pubDate>Fri, 21 Feb 2025 22:17:35 +0800</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/devel-guide-note/</guid>
      <description>&lt;h1 id=&#34;架构图&#34;&gt;架构图&lt;/h1&gt;
&lt;p&gt;kamailio 1.x版本
&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/kamailio/devel-guide-note/atta/2025-02-21-22-18-34.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;kamailio 3.x版本。相比于1.x版本，两个核心模块移动到外部模块。
&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/kamailio/devel-guide-note/atta/2025-02-21-22-19-54.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;核心模块
The core includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;memory manager&lt;/li&gt;
&lt;li&gt;SIP message parser&lt;/li&gt;
&lt;li&gt;locking system&lt;/li&gt;
&lt;li&gt;DNS and transport layer management (UDP, TCP, TLS, SCTP)&lt;/li&gt;
&lt;li&gt;configuration file parser and interpreter&lt;/li&gt;
&lt;li&gt;stateless forwarding&lt;/li&gt;
&lt;li&gt;pseudo-variables and transformations engines&lt;/li&gt;
&lt;li&gt;RPC control interface API&lt;/li&gt;
&lt;li&gt;timer API&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The internal libraries include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;some components from old Kamailio v1.5.x core&lt;/li&gt;
&lt;li&gt;database abstraction layers (DB API v1 and v2)&lt;/li&gt;
&lt;li&gt;management interface (MI) API&lt;/li&gt;
&lt;li&gt;statistics engine&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;sip消息处理&#34;&gt;SIP消息处理&lt;/h1&gt;
&lt;p&gt;请求处理
&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/kamailio/devel-guide-note/atta/2025-02-21-22-23-52.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;响应处理。 这里可以看到，是先执行响应路由，再执行失败路由。
&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/kamailio/devel-guide-note/atta/2025-02-21-22-24-59.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>HEP 协议学习笔记</title>
      <link>https://wdd.js.org/zh/posts/2025/hep-protocol/</link>
      <pubDate>Sun, 02 Feb 2025 15:12:40 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2025/hep-protocol/</guid>
      <description>&lt;h1 id=&#34;hep简介&#34;&gt;HEP简介&lt;/h1&gt;
&lt;p&gt;HEP协议目前叫做EEP(Extensible Encapsulation Protocol), 那之前的缩写HEP的H，我只能推测为homer。&lt;/p&gt;
&lt;p&gt;这个协议的主要功能是对VoIP连路上的数据包，例如SIP进行封装，方便后续分析SIP信令图。&lt;/p&gt;
&lt;p&gt;目前这个协议已经升级到V3版本，在这个pdf&lt;a href=&#34;https://github.com/sipcapture/HEP/blob/master/docs/HEP3_Network_Protocol_Specification_REV_36.pdf&#34;&gt;HEP3_Network_Protocol_Specification_REV_36&lt;/a&gt;中有详细的介绍。&lt;/p&gt;
&lt;p&gt;今天我们主要看这个协议的V3版本的协议是如何实现的。&lt;/p&gt;
&lt;h1 id=&#34;包头&#34;&gt;包头&lt;/h1&gt;
&lt;pre class=&#34;mermaid&#34;&gt;packet-beta
title HEP Packet
0-3: &amp;#34;版本号&amp;#34;
4-5: &amp;#34;总长度&amp;#34;
6-15: &amp;#34;数据段(变长)&amp;#34;
&lt;/pre&gt;
&lt;p&gt;HEPv3的包头是6个字节，主要分为三个部分&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;版本号：固定4个字节长度，是HEP3&lt;/li&gt;
&lt;li&gt;总长度：固定2个字节长度，是包的总长度，这个总长度包括了包头的六个字节。所以HEP包的大小范围一般是6-65535之间。&lt;/li&gt;
&lt;li&gt;数据段：数据段的长度不固定&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;注意事项：假如从传输层读到1000个字节的数据，在解析前6个字节是，发现总长度(total length)的子段是1200，那就说明本次读到的数据还不是一个完整的&lt;/p&gt;&lt;/blockquote&gt;
&lt;h1 id=&#34;数据段解析&#34;&gt;数据段解析&lt;/h1&gt;
&lt;p&gt;数据段由固定6字节长度的头部和变长的payload部分。&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;packet-beta
title HEP Packet
0-1: &amp;#34;vendor ID&amp;#34;
2-3: &amp;#34;type ID&amp;#34;
4-5: &amp;#34;length&amp;#34;
6-15: &amp;#34;payload&amp;#34;
&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;vendor ID: 固定2字节长度, 其实意义不大，&lt;/li&gt;
&lt;li&gt;type ID: 固定2字节长度，这个子段很重要，决定了payload的类型。可以理解为是一个对象的key, 然后把payload理解为value&lt;/li&gt;
&lt;li&gt;length: 固定2字节长度，范围是0-65535，这个字段是也是整个数据段的长度，也就是包括了6个字节的段头&lt;/li&gt;
&lt;li&gt;payload: 长度是length的长度-6，表示数据长度&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;hep协议有个type ID的映射表&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;chunk type ID&lt;/th&gt;
          &lt;th&gt;类型&lt;/th&gt;
          &lt;th&gt;描述&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;0x0001&lt;/td&gt;
          &lt;td&gt;uint8&lt;/td&gt;
          &lt;td&gt;IP类型，0x02=IPv4, 0x0a=IPv6&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;0x0002&lt;/td&gt;
          &lt;td&gt;uint8&lt;/td&gt;
          &lt;td&gt;协议类型 0x06=TCP, 0x11=UDP， 可以参考&lt;a href=&#34;https://zh.wikipedia.org/wiki/IP%E5%8D%8F%E8%AE%AE%E5%8F%B7%E5%88%97%E8%A1%A8&#34;&gt;IP协议号列表&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;其他的字段还有很多，可以参考&lt;a href=&#34;https://github.com/sipcapture/HEP/blob/master/docs/HEP3_Network_Protocol_Specification_REV_36.pdf&#34;&gt;HEP3_Network_Protocol_Specification_REV_36&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>RFC768 UDP包学习笔记</title>
      <link>https://wdd.js.org/zh/network/rfc768-udp/</link>
      <pubDate>Wed, 01 Jan 2025 20:23:41 +0800</pubDate>
      <guid>https://wdd.js.org/zh/network/rfc768-udp/</guid>
      <description>&lt;h1 id=&#34;包格式&#34;&gt;包格式&lt;/h1&gt;
&lt;p&gt;UDP包头工占用8个字节,  其中源端口和目标端口各占2个字节，长度占2个字节，校验和占2个字节。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;    0      7 8     15 16    23 24    31
   +--------+--------+--------+--------+
   |     Source      |   Destination   |
   |      Port       |      Port       |
   +--------+--------+--------+--------+
   |                 |                 |
   |     Length      |    Checksum     |
   +--------+--------+--------+--------+
   |
   |          data octets ...
   +---------------- ...

        User Datagram Header Format
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;字段&#34;&gt;字段&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;源端口&lt;/strong&gt;，可选字段，默认为0，如果是有意义的其他端口，表示后续响应可以送回到该端口&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;目标端口&lt;/strong&gt;，必须字段，用来关联目标主机上进程监听的端口&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;长度&lt;/strong&gt;，长度是整个UDP包的长度，也就是包头 + 包的数据，包头固定8字节，那么length的最小长度就是8&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;校验和&lt;/strong&gt;，用来验证传输过程中是否发生了错误。校验和的计算结果与源IP、目标IP、UDP的包长有关。 如果校验和失败，那么消息会被丢弃。 有些校验和计算的工作会被放置在网卡上，从而减少CPU的负载。当然如果在网卡上因为校验和的问题被网卡丢弃，上层应用是收不到不到UDP包的。但是用tcpdump可以抓到这种校验和有问题的包。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;思考1： 为什么源端口可以设置为0？&lt;/p&gt;
&lt;p&gt;答：有些UDP包，是不需要响应的，只需要发送出消息。&lt;/p&gt;&lt;/blockquote&gt;
&lt;h1 id=&#34;参考&#34;&gt;参考&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc768&#34;&gt;https://datatracker.ietf.org/doc/html/rfc768&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/opensips/ch7/big-udp-msg/&#34;&gt;https://wdd.js.org/opensips/ch7/big-udp-msg/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/network/udp-checksum-offload/&#34;&gt;https://wdd.js.org/network/udp-checksum-offload/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>源码笔记 - 自定义事件路由(中)</title>
      <link>https://wdd.js.org/zh/kamailio/route-list-action/</link>
      <pubDate>Sat, 28 Dec 2024 09:43:00 +0800</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/route-list-action/</guid>
      <description>&lt;p&gt;[[&lt;em&gt;TOC&lt;/em&gt;]]&lt;/p&gt;
&lt;h1 id=&#34;route_list&#34;&gt;route_list&lt;/h1&gt;
&lt;p&gt;route.h定义了几个函数分别用来获取、查找、新增route&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// src/core/route.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;route_get&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; route_list &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;rt, &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;route_lookup&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; route_list &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;rt, &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;push&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; action &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;a, &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; action &lt;span style=&#34;color:#f92672&#34;&gt;**&lt;/span&gt;head);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; route_list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; action &lt;span style=&#34;color:#f92672&#34;&gt;**&lt;/span&gt;rlist;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; idx;					 &lt;span style=&#34;color:#75715e&#34;&gt;/* first empty entry */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; entries;				 &lt;span style=&#34;color:#75715e&#34;&gt;/* total number of entries */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; str_hash_table names; &lt;span style=&#34;color:#75715e&#34;&gt;/* name to route index mappings */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;rlist&#34;&gt;rlist&lt;/h2&gt;
&lt;p&gt;我们对route_list数据模型进行简化:&lt;/p&gt;
&lt;p&gt;rlist是一个固定长度的一维数组，通过索引来访问对应的值。如果数组的空间不足，那么就创建一个两倍大的空数据，然后先把原始数据复制过去。这种复制方式保持的原始数据的索引位置。有点像golang的切片扩容机制。&lt;/p&gt;
&lt;p&gt;这里最为重要的就是保持数组元素的索引位置在扩容后不变。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;route_new_list&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; route_list &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;rt)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; ret;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; action &lt;span style=&#34;color:#f92672&#34;&gt;**&lt;/span&gt;tmp;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	ret &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(rt&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;idx &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; rt&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;entries) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 两倍扩容
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;		tmp &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;pkg_realloc&lt;/span&gt;(rt&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;rlist, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; rt&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;entries &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; action &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(tmp &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;LM_CRIT&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;out of memory&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;goto&lt;/span&gt; end;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#75715e&#34;&gt;/* init the newly allocated memory chunk */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;memset&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;tmp[rt&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;entries], &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, rt&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;entries &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; action &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		rt&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;rlist &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; tmp;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		rt&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;entries &lt;span style=&#34;color:#f92672&#34;&gt;*=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(rt&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;idx &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; rt&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;entries) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		ret &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; rt&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;idx;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		rt&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;idx&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;end:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; ret;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;str_hash_table&#34;&gt;str_hash_table&lt;/h2&gt;
&lt;p&gt;我们对hash_table的数据模型进行简化，它其实就是一hash表，key是路由的名，值是一个正数，正数代表了路由执行单元的索引位置。&lt;/p&gt;</description>
    </item>
    <item>
      <title>源码笔记 - 自定义事件路由(上)</title>
      <link>https://wdd.js.org/zh/kamailio/customer-event-route/</link>
      <pubDate>Fri, 27 Dec 2024 20:45:03 +0800</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/customer-event-route/</guid>
      <description>&lt;p&gt;[[&lt;em&gt;TOC&lt;/em&gt;]]&lt;/p&gt;
&lt;h1 id=&#34;事件路由简介&#34;&gt;事件路由简介&lt;/h1&gt;
&lt;p&gt;在某些模块中，我们看到有一些模块自定义的事件路由。&lt;/p&gt;
&lt;p&gt;例如dispatcher模块，或者rtpengine模块。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;event_route&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;dispatcher:dst-down&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    xlog&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;L_ERR&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Destination down: &lt;/span&gt;$rm&lt;span style=&#34;color:#e6db74&#34;&gt; &lt;/span&gt;$ru&lt;span style=&#34;color:#e6db74&#34;&gt; (&lt;/span&gt;$du&lt;span style=&#34;color:#e6db74&#34;&gt;)\n&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;event_route&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;rtpengine:dtmf-event&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    xlog&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;L_INFO&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;callid: &lt;/span&gt;$avp&lt;span style=&#34;color:#e6db74&#34;&gt;(dtmf_event_callid)\n&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		xlog&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;L_INFO&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;source_tag: &lt;/span&gt;$avp&lt;span style=&#34;color:#e6db74&#34;&gt;(dtmf_event_source_tag)\n&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		xlog&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;L_INFO&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;timestamp: &lt;/span&gt;$avp&lt;span style=&#34;color:#e6db74&#34;&gt;(dtmf_event_timestamp)\n&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		xlog&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;L_INFO&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dtmf: &lt;/span&gt;$avp&lt;span style=&#34;color:#e6db74&#34;&gt;(dtmf_event)\n&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;disapcher模块&#34;&gt;disapcher模块&lt;/h1&gt;
&lt;p&gt;在dispatch.c文件中，我们看到如下代码&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;ds_skip_dst&lt;/span&gt;(old_state) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ds_skip_dst&lt;/span&gt;(idx&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;dlist[i].flags)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;ds_run_route&lt;/span&gt;(msg, address, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dispatcher:dst-down&amp;#34;&lt;/span&gt;, rctx);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ds_skip_dst&lt;/span&gt;(old_state) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;ds_skip_dst&lt;/span&gt;(idx&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;dlist[i].flags))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;ds_run_route&lt;/span&gt;(msg, address, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dispatcher:dst-up&amp;#34;&lt;/span&gt;, rctx);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ds_run_route还是定义在dispatch.c文件中，&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ds_run_route&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;sip_msg_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;msg, str &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;uri, &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;route, &lt;span style=&#34;color:#66d9ef&#34;&gt;ds_rctx_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;rctx)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;接着又一个重要调用。 这里似乎在查找路由。&lt;/p&gt;
&lt;p&gt;route这个参数其实就是&lt;strong&gt;dispatcher:dst-down&lt;/strong&gt;， 或者 &lt;strong&gt;dispatcher:dst-up&lt;/strong&gt;，&lt;/p&gt;
&lt;p&gt;那么event_rt又是什么鬼呢？&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rt &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;route_lookup&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;event_rt, route);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;event_rt是一个route_list的结构体&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// route.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; route_list event_rt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;route_list的结构如下，重点是这个str_hash_table这个字段，它似乎是一个hash&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; route_list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; action &lt;span style=&#34;color:#f92672&#34;&gt;**&lt;/span&gt;rlist;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; idx;					 &lt;span style=&#34;color:#75715e&#34;&gt;/* first empty entry */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; entries;				 &lt;span style=&#34;color:#75715e&#34;&gt;/* total number of entries */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; str_hash_table names; &lt;span style=&#34;color:#75715e&#34;&gt;/* name to route index mappings */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;str_hash_table的结构如下：&lt;/p&gt;</description>
    </item>
    <item>
      <title>DMQ模块源码学习笔记</title>
      <link>https://wdd.js.org/zh/kamailio/dmq-note/</link>
      <pubDate>Sun, 22 Dec 2024 18:07:08 +0800</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/dmq-note/</guid>
      <description>&lt;h1 id=&#34;背景&#34;&gt;背景&lt;/h1&gt;
&lt;p&gt;多个SIP注册服务器之间，如何同步分机的注册信息呢？&lt;/p&gt;
&lt;p&gt;简单的方案就是使用共享数据库的方式同步注册信息，这个方案实现起来简单，但是分机的注册信息本身就是个需要频繁增删改查的，数据库很可能在大量注册分机的压力下，成为性能的瓶颈。&lt;/p&gt;
&lt;p&gt;除了数据库之外，OpenSIPS和kamailio分别提供了不同的方案。&lt;/p&gt;
&lt;p&gt;OpenSIPS提供的方案是使用cluster模块，cluster模块在多个实例之间同步分机的注册信息，注册信息的格式是OpenSIPS自定义的格式。
Kamailio的方案是DMQ模块， DMQ听起来高大上，放佛是依赖外部的一个服务。 但它其实就是扩展SIP消息，通过SIP消息来广播分机的注册信息。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-log&#34; data-lang=&#34;log&#34;&gt;KDMQ sip:notification_peer@192.168.40.15:5090 SIP/2.0
Via: SIP/2.0/UDP 192.168.40.15;branch=z9hG4bK55e5.423d95110000
To: &amp;lt;sip:notification_peer@192.168.40.15:5090&amp;gt;
From: &amp;lt;sip:notification_peer@192.168.40.15:5060&amp;gt;;tag=2cdb7a33a7f21abb98fd3a44968e3ffd-5b01
CSeq: 10 KDMQ
Call-ID: 1fe138e07b5d0a7a-50419@192.168.40.15
Content-Length: 116
User-Agent: kamailio (4.3.0 (x86_64/linneaus))
Max-Forwards: 1
Content-Type: text/plain

sip:192.168.40.16:5060;status=active
sip:192.168.40.15:5060;status=disabled
sip:192.168.40.17:5060;status=active
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;源码分析&#34;&gt;源码分析&lt;/h1&gt;
&lt;p&gt;该模块一共暴露了8个参数，其中7个参数都是简单类型，INT和STR，就直接取对应变量的地址就可以了。&lt;/p&gt;
&lt;p&gt;其中notification_address参数是用来配置集群中其他节点的通信地址的，因为要配置多次，所以需要用一个函数来解析。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// dmq.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;param_export_t&lt;/span&gt; params[] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	{&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;num_workers&amp;#34;&lt;/span&gt;, PARAM_INT, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;dmq_num_workers},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	{&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ping_interval&amp;#34;&lt;/span&gt;, PARAM_INT, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;dmq_ping_interval},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	{&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;server_address&amp;#34;&lt;/span&gt;, PARAM_STR, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;dmq_server_address},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	{&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;server_socket&amp;#34;&lt;/span&gt;, PARAM_STR, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;dmq_server_socket},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	{&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;notification_address&amp;#34;&lt;/span&gt;, PARAM_STR&lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt;PARAM_USE_FUNC, dmq_add_notification_address},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	{&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;notification_channel&amp;#34;&lt;/span&gt;, PARAM_STR, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;dmq_notification_channel},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	{&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;multi_notify&amp;#34;&lt;/span&gt;, PARAM_INT, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;dmq_multi_notify},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	{&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;worker_usleep&amp;#34;&lt;/span&gt;, PARAM_INT, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;dmq_worker_usleep},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	{&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这些参数都没有加上static关键词，主要目的为了在dmq模块的其他c文件能使用。&lt;/p&gt;</description>
    </item>
    <item>
      <title>路由执行的顺序</title>
      <link>https://wdd.js.org/zh/kamailio/msg-flow/</link>
      <pubDate>Sun, 22 Dec 2024 16:20:42 +0800</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/msg-flow/</guid>
      <description>&lt;h1 id=&#34;1-请求消息处理过程&#34;&gt;1. 请求消息处理过程&lt;/h1&gt;
&lt;p&gt;请求可以&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;直接丢弃，不返回任何响应。对于恶意请求，SIP Flood攻击，最好不要返回任何响应。&lt;/li&gt;
&lt;li&gt;直接返回状态码，不做转发，例如直接返回301重定向&lt;/li&gt;
&lt;li&gt;无状态转发&lt;/li&gt;
&lt;li&gt;有状态转发
&lt;ul&gt;
&lt;li&gt;执行分支路由，分支路由也可以将消息丢弃&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;无论有无状态，请求发出去前都会执行onsend_route路由，在onsend_route内部，已经不能对SIP消息再做拦截&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/kamailio/msg-flow/atta/2024-12-22-17-46-29.png&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;2-响应消息处理过程&#34;&gt;2. 响应消息处理过程&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;首先执行reply_route{}, 在这个路由里可以将消息丢弃&lt;/li&gt;
&lt;li&gt;然后判断消息是否有状态的
&lt;ul&gt;
&lt;li&gt;有状态，这执行onreply_route[ID]路由
&lt;ul&gt;
&lt;li&gt;如果响应是失败的，还可以执行failure_route[ID], 当前前提是在请求路由里是否设置了钩子&lt;/li&gt;
&lt;li&gt;在失败路由可以，可以再次设置新的目标地址，进行转发； 设置了新的目标地址后，还可以设置分支路由&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;notice tip&#34;&gt;
  &lt;div class=&#34;notice-title&#34;&gt;
    &lt;i class=&#34;fa fa-lightbulb-o&#34; aria-hidden=&#34;true&#34;&gt;&lt;/i&gt;Tip
  &lt;/div&gt;
  &lt;div class=&#34;notice-content&#34;&gt;这里要注意的是，响应路由在失败路由之前执行。&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/kamailio/msg-flow/atta/2024-12-22-17-47-27.png&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;3-重传处理&#34;&gt;3. 重传处理&lt;/h1&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/kamailio/msg-flow/atta/2024-12-22-17-49-19.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>kamailio 启动参数控制</title>
      <link>https://wdd.js.org/zh/kamailio/kamailio-cli-params/</link>
      <pubDate>Sun, 22 Dec 2024 15:46:13 +0800</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/kamailio-cli-params/</guid>
      <description>&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -a mode      Auto aliases mode: enable with yes or on,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  disable with no or off
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  一般都是关闭
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --alias&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;val  Add an alias, the value has to be &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;[proto:]hostname[:port]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;like &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;alias&amp;#39;&lt;/span&gt; global parameter&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  设置对外别名, 在多个对外别名时，相比于在脚本中写死, 更好的方式
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  是在启动时传入, alias一般都是服务的对外域名或者IP
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  如果km有多个对外域名，并且不同的环境都不同，这块配置就合适在脚本里写死
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --atexit&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;val Control atexit callbacks execution from external libraries
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  which may access destroyed shm memory causing crash on shutdown.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  Can be y&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;es&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; or &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; to enable atexit callbacks, n&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;o&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; or &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; to disable,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  default is no.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  没用过
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -A define    Add config pre-processor define &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;e.g., -A WITH_AUTH,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  -A &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;FLT_ACC=1&amp;#39;&lt;/span&gt;, -A &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;DEFVAL=&amp;#34;str-val&amp;#34;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  预处理的变量定义
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -b nr        Maximum OS UDP receive buffer size which will not be exceeded by
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  auto-probing-and-increase procedure even &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; OS allows
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -B nr        Maximum OS UDP send buffer size which will not be exceeded by
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  auto-probing-and-increase procedure even &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; OS allows
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  这和上面的有啥区别呢？
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -c           Check configuration file &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; syntax errors
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                可以检查配置文件的语法错误。如果这个选项开启，就只能做检查语法，而不能启动kama
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --cfg-print  Print configuration file evaluating includes and ifdefs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 在脚本里有很多预处理指令时，可以用这个参数打印出预处理之后的脚本 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -d           Debugging level control &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;multiple -d to increase the level from 0&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                调试界别
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --debug&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;val  Debugging level value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -D           Control how daemonize is &lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  -D..do not fork &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;almost&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; anyway;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  -DD..do not daemonize creator;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  -DDD..daemonize &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;default&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                控制是否开启守护进程
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -e           Log messages printed in terminal colors &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;requires -E&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -E           Log to stderr
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -f file      Configuration file &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;default: /usr/local/etc/kamailio/kamailio.cfg&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                设置配置文件的位置, 可以覆盖默认的位置
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -g gid       Change gid &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;group id&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -G file      Create a pgid file
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -h           This help message
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --help       Long option &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;-h&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -I           Print more internal compile flags and options
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -K           Turn on &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;via:&amp;#34;&lt;/span&gt; host checking when forwarding replies
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -l address   Listen on the specified address/interface &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;multiple -l
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  mean listening on more addresses&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;. The address format is
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;proto:&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;addr_lst&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;:port&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;/advaddr&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;/socket_name&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  where proto&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;udp|tcp|tls|sctp, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  addr_lst&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; addr|&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;addr, addr_lst&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  addr&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;host|ip_address|interface_name, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  advaddr&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;addr&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;:port&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;advertised address&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; and 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  socket_name&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;identifying name.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  E.g: -l localhost, -l udp:127.0.0.1:5080, -l eth0:5062,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  -l udp:127.0.0.1:5080/1.2.3.4:5060,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  -l udp:127.0.0.1:5080//local,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  -l udp:127.0.0.1:5080/1.2.3.4:5060/local,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  -l &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sctp:(eth0)&amp;#34;&lt;/span&gt;, -l &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;(eth0, eth1, 127.0.0.1):5065&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  The default behaviour is to listen on all the interfaces.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                控制listen的地址
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --loadmodule&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;name load the module specified by name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --log-engine&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;log engine name and data
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -L path      Modules search path &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;default: /usr/local/lib64/kamailio/modules&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -m nr        Size of shared memory allocated in Megabytes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                共享内存的大小设置
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --modparam&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;modname:paramname:type:value set the module parameter
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  type has to be &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;s&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; string value and &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;i&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; int value, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  example: --modparam&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;corex:alias_subdomains:s:kamailio.org
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  设置模块的启动参数
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  对于不方便在脚本里写死的模块参数，这个方式也挺好用
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --all-errors Print details about all config errors that can be detected
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                调试模式比较好用，打印详细的日志报错 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -M nr        Size of private memory allocated, in Megabytes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                控制私有内存的大小
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -n processes Number of child processes to fork per interface
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;default: 8&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -N           Number of tcp child processes &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;default: equal to &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;-n&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    -O nr        Script optimization level (debugging option)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    -P file      Create a pid file
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    -Q           Number of sctp child processes (default: equal to `-n&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -r           Use dns to check &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; is necessary to add a &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;received=&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  field to a via
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -R           Same as &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;-r&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt; but use reverse dns;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;to use both use &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;-rR&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --server-id&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;num set the value &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; server_id
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --subst&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;exp set a subst preprocessor directive
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --substdef&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;exp set a substdef preprocessor directive
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --substdefs&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;exp set a substdefs preprocessor directive
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -S           disable sctp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -t dir       Chroot to &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dir&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -T           Disable tcp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -u uid       Change uid &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;user id&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -v           Version number
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --version    Long option &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;-v&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -V           Alternative &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;-v&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -x name      Specify internal manager &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; shared memory &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;shm&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  - can be: fm, qm or tlsf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -X name      Specify internal manager &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; private memory &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;pkg&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  - &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; omitted, the one &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; shm is used
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -Y dir       Runtime dir path
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -w dir       Change the working directory to &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dir&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;default: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    -W type      poll method &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;depending on support in OS, it can be: poll,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  epoll_lt, epoll_et, sigio_rt, &lt;span style=&#34;color:#66d9ef&#34;&gt;select&lt;/span&gt;, kqueue, /dev/poll&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    <item>
      <title>DDOS学习笔记</title>
      <link>https://wdd.js.org/zh/posts/2024/ddos/</link>
      <pubDate>Tue, 17 Dec 2024 21:10:40 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2024/ddos/</guid>
      <description>&lt;h1 id=&#34;攻击分类&#34;&gt;攻击分类&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;网络层&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ICMP Flood攻击&lt;/strong&gt;: ICMP（Internet Control Message Protocol，因特网控制报文协议）是TCP/IP协议族的一个子协议，用于在IP主机、路由器之间传递控制消息。ICMP协议本身特点决定了它非常容易被用于攻击网络上的路由器和主机。当攻击者向目标网络发送大量的ICMP数据包时，目标主机会耗费大量的CPU资源去处理和响应，直至耗尽设备资源，无法为合法用户提供正常服务。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ARP Flood攻击&lt;/strong&gt;: ARP（Address Resolution Protocol，地址解析协议）是用来将IP地址解析为MAC地址的协议。ARP协议主要以广播的方式发送ARP请求。同网段内的主机都可以收到广播请求，这为攻击者提供了可乘之机。攻击者通过发送大量的ARP请求，使有限的网络资源被无用的广播信息所占用，造成网络拥堵。其次，因为ARP协议没有安全认证机制，所以只要主机接收到ARP应答包，都会缓存在ARP表中，这为ARP欺骗提供了可能。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IP分片攻击&lt;/strong&gt;: IP协议在传输数据包时，会将数据报文分为若干分片进行传输，并在目标系统中进行重组。IP分片是网络环境中经常发生的事件，但是，如果数据被人为恶意分片就会产生DDoS攻击。攻击者将经过恶意分段的数据包发送至目标网络，导致目标网络耗费大量资源进行重组，直至资源枯竭。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;传输层攻击&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SYN Flood攻击&lt;/strong&gt;: SYN Flood是互联网最原始、最经典的DDoS攻击之一，主要利用了TCP协议的三次握手机制。攻击者通常利用工具或控制僵尸主机向服务器发送海量的变源IP地址或变源端口的SYN报文，服务器响应报文后产生大量的半连接，直至系统资源被耗尽，服务器无法提供正常的服务。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ACK Flood攻击&lt;/strong&gt;: 攻击者通过僵尸网络向目标服务器发送大量的ACK报文，报文带有超大载荷，会引起链路拥塞。或向目标服务器发送极高速率的变源变端口请求，导致转发设备异常，从而引起网络瘫痪。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UDP Flood攻击&lt;/strong&gt;: UDP Flood攻击常用于大带宽DDoS攻击。攻击者使用包含无状态UDP协议的IP数据包充塞目标主机的端口，受害主机会寻找与UDP数据包相关的应用程序。如果没有找到，就向发送者回发一条“目标不可达”消息。一旦目标主机被攻击流量淹没，系统就会失去响应，从而造成合法用户无法正常访问的现象。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;应用层攻击&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DNS Flood攻击&lt;/strong&gt;: 攻击者通过操纵大量傀儡机器，对目标网络发起海量域名查询请求，以中断该域的DNS解析。这种攻击将会破坏网站、API或Web应用程序响应合法流量的能力，让合法用户无法查找到用于调用特定资源的地址，导致业务暂时中断或停止。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP Flood攻击&lt;/strong&gt;: HTTP GET 攻击：攻击者操控多台设备向目标服务器发送对图像、文件或其他资产请求，当目标服务器被传入请求和响应所淹没时，来自正常流量源的业务请求也将被拒绝。
HTTP POST 攻击：与发送 POST 请求所需的处理能力和带宽相比，处理表单数据和运行必要数据库命令的过程相对密集。这种攻击利用相对资源消耗的差异，直接向目标服务器发送大量POST请求，直至目标服务器容量饱和并拒绝服务为止。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CC攻击&lt;/strong&gt;: CC攻击常用于攻击提供网页访问服务的服务器。攻击者通过代理服务器向目标服务器发送大量貌似合法的请求，使CPU长时间处于高负荷运行状态，永远都有处理不完的连接。攻击会导致正常访问被中止，最终宕机崩溃。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SIP注册 Flood攻击&lt;/strong&gt;: 攻击者发送大量的SIP注册请求到SIP服务端，SIP服务器需要查询数据库，拖慢正常的数据库查询，也回占用大量的资源来维护注册的事务。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;faq&#34;&gt;FAQ&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;防火墙能否拦截DDOS攻击？
&lt;ul&gt;
&lt;li&gt;拦截不了，防火墙就好比饭店的保安，保安再多，但是饭店门口道路交通堵塞了，饭店的营业额下降，再多的保安也无能为力&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;在遭受DDOS攻击后，用什么手段防御？
&lt;ol&gt;
&lt;li&gt;购买硬件设备：除了比较贵之外，对于使用云服务器的服务也无能为力&lt;/li&gt;
&lt;li&gt;更换公网IP：对于使用云服务器来说，更换云服务器的公网IP看起来比较简单方便。但是也有麻烦的地方，比如自己的服务可能要涉及到配置改变和服务重启，和自己相关的第三方，也可能要修改IP的访问地址&lt;/li&gt;
&lt;li&gt;使用云服务厂商提供的DDOS服务&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;如何感知到自己的服务正在遭受DDOS攻击？
&lt;ol&gt;
&lt;li&gt;异常大的流量波动&lt;/li&gt;
&lt;li&gt;正常用户大量离线&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;参考&#34;&gt;参考&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://info.support.huawei.com/info-finder/encyclopedia/zh/DDoS%E6%94%BB%E5%87%BB.html&#34;&gt;https://info.support.huawei.com/info-finder/encyclopedia/zh/DDoS%E6%94%BB%E5%87%BB.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.microsoft.com/zh-cn/security/business/security-101/what-is-a-ddos-attack&#34;&gt;https://www.microsoft.com/zh-cn/security/business/security-101/what-is-a-ddos-attack&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>你不怕暴露自己的无知吗？</title>
      <link>https://wdd.js.org/zh/posts/2024/121701/</link>
      <pubDate>Sat, 07 Dec 2024 14:17:28 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2024/121701/</guid>
      <description>&lt;h1 id=&#34;公开自己的错误&#34;&gt;公开自己的错误&lt;/h1&gt;
&lt;p&gt;我在写博客时，有时候脑海里总会蹦出一个小人，面露鄙夷的脸色对我说：你写这么多没啥技术含量的垃圾，公开在网上，难道不怕暴露自己的无知吗？&lt;/p&gt;
&lt;p&gt;说实话，我是有这样的担忧。&lt;/p&gt;
&lt;p&gt;因为我是有自知之明的，我知道自己估计也是黄老师那种&amp;quot;样样通，样样松&amp;quot;的人。 写的东西也都是一些表面的东西，甚至有错误的可能。这并不是自谦。&lt;/p&gt;
&lt;p&gt;我一直无法找到反击脑海里小人的理由。&lt;/p&gt;
&lt;p&gt;今天，我在读一本书的时候，学到了一个概念，这个概念叫做坎宁安定律。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;在互联网上获得正确答案的最好方法并不是提出问题，而是发布错误的答案&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;也许我的答案是错误的，但是它并没有被隐藏我脑海的某个角落，二是被公开在了网上。&lt;/p&gt;
&lt;p&gt;即使我的小破站再小，必然也会有几个阅读量吧，或许能有读者对错误的答案提出自己的异议。&lt;/p&gt;
&lt;h1 id=&#34;学习金字塔理论&#34;&gt;学习金字塔理论&lt;/h1&gt;
&lt;p&gt;如果仅仅是通过阅读学习，学习内容的平均存留率只有5%。&lt;/p&gt;
&lt;p&gt;如果把学习内容公开，这其中就暗示了你可能需要把自己学到的内容教授给他人这一心理。&lt;/p&gt;
&lt;p&gt;那么在记录笔记的时候，就会想办法把问题讲解的让别人更清楚，从而加深了自己的学习知识吸收。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/posts/2024/121701/atta/2024-12-22-13-17-38.png&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;参考&#34;&gt;参考&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://baike.baidu.com/item/%E5%AD%A6%E4%B9%A0%E9%87%91%E5%AD%97%E5%A1%94/9515094&#34;&gt;https://baike.baidu.com/item/%E5%AD%A6%E4%B9%A0%E9%87%91%E5%AD%97%E5%A1%94/9515094&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>第一节 如何熟悉Kamailio文档的文档结构</title>
      <link>https://wdd.js.org/zh/kamailio/docs-index/</link>
      <pubDate>Mon, 02 Dec 2024 22:43:24 +0800</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/docs-index/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;我始终认为，快速学习一门知识，最为重要的就是熟悉它的文档结构。&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;对于熟悉OpenSIPS的文档结构来说的人，看了Kamailio的文档，往往觉得无从下手。&lt;/p&gt;
&lt;p&gt;当我们打开Km的官网(kamailio.org)后， 会重定向到https://www.kamailio.org/w/,  在页面的右侧，&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/kamailio/docs-index/atta/2024-12-02-22-57-06.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;接着，我们会导航到 &lt;a href=&#34;https://www.kamailio.org/w/documentation/&#34;&gt;https://www.kamailio.org/w/documentation/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这个页面的结构需要烂熟于心&lt;/p&gt;
&lt;h1 id=&#34;1-模块文档&#34;&gt;1. 模块文档&lt;/h1&gt;
&lt;p&gt;如果你知道km的版本号和对应的模块，可以点击这里进入对应版本，然后再选择对应模块&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/kamailio/docs-index/atta/2024-12-02-23-03-53.png&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;2-wiki部分&#34;&gt;2. wiki部分&lt;/h1&gt;
&lt;h2 id=&#34;21-必学部分&#34;&gt;2.1 必学部分&lt;/h2&gt;
&lt;p&gt;wiki部分主要是一些教程，非常值得看。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/kamailio/docs-index/atta/2024-12-02-23-05-57.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;其中有三个重点部分&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;core cookbook&lt;/strong&gt;： 主要讲解km的脚本的结构、全局参数、模块参数、路由类型、预处理、脚本操作等等，是编写km脚本的必学之处，各种参数都可以看看&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pseudo-Variables CookBook&lt;/strong&gt;：主要讲解各种伪变量，用来读写SIP消息&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transformations CookBook&lt;/strong&gt;： 主要讲解各种操作变换，例如把字符串型转为int型数据&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/kamailio/docs-index/atta/2024-12-02-23-07-06.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;全部函数索引&#34;&gt;全部函数索引&lt;/h2&gt;
&lt;p&gt;在km的wiki官网，即https://www.kamailio.org/wikidocs/， 其中Alphabetic Indexes就是所有的参数或者函数的索引。&lt;/p&gt;
&lt;p&gt;在你学些km的脚本时，有时候想知道某个函数在哪个模块中，就可以用这个全部函数索引中查找。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/kamailio/docs-index/atta/2024-12-07-11-37-37.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;源码安装&#34;&gt;源码安装&lt;/h2&gt;
&lt;p&gt;这部分讲解如何通过GIT进行源码安装。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/kamailio/docs-index/atta/2024-12-02-23-12-53.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;faq&#34;&gt;FAQ&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://www.kamailio.org/wikidocs/tutorials/faq/main/&#34;&gt;https://www.kamailio.org/wikidocs/tutorials/faq/main/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;外部资源&#34;&gt;外部资源&lt;/h2&gt;
&lt;p&gt;这里涉及了如何用km和常见的媒体服务器如何集成&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/kamailio/docs-index/atta/2024-12-02-23-16-07.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/kamailio/docs-index/atta/2024-12-02-23-31-00.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/kamailio/docs-index/atta/2024-12-02-23-33-15.png&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;其他&#34;&gt;其他&lt;/h1&gt;
&lt;p&gt;官方的Web版本的wiki, 对于刚入门的人来说，还是有点绕的。&lt;/p&gt;
&lt;p&gt;另外一个问题就是mkdocs的页面渲染效果的确不太行，目录滚动一点都不灵敏。&lt;/p&gt;
&lt;p&gt;如果你想看的不是某个模块的说明文档，我更建议你直接把https://github.com/kamailio/kamailio-wiki 这个git仓库下载到本地查看。&lt;/p&gt;
&lt;h1 id=&#34;总结&#34;&gt;总结&lt;/h1&gt;
&lt;p&gt;总体来说，km的文档算是非常完整了，但是和OpenSIPS相比，还有待加强。&lt;/p&gt;</description>
    </item>
    <item>
      <title>AXB的玩法说明</title>
      <link>https://wdd.js.org/zh/opensips/ch2/axb/</link>
      <pubDate>Mon, 18 Nov 2024 19:58:38 +0800</pubDate>
      <guid>https://wdd.js.org/zh/opensips/ch2/axb/</guid>
      <description></description>
    </item>
    <item>
      <title>第二份工作的辞职总结</title>
      <link>https://wdd.js.org/zh/posts/2024/leave-the-second-job/</link>
      <pubDate>Tue, 10 Sep 2024 21:08:51 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2024/leave-the-second-job/</guid>
      <description>&lt;h1 id=&#34;总结&#34;&gt;总结&lt;/h1&gt;
&lt;p&gt;第二份工作快到一年了，我最近申请离职了。&lt;/p&gt;
&lt;p&gt;同事问我离职原因，我说被领导骂了，感觉自尊受辱，索性不干了。&lt;/p&gt;
&lt;p&gt;实际上被领导骂只是压死骆驼的最后一根稻草，我也不是那种会心血来潮说干就不干的。&lt;/p&gt;
&lt;p&gt;这份工作，我做了不到一年，大部分的时间我是做的不开心的。&lt;/p&gt;
&lt;p&gt;所以离职是一直在心里酝酿。&lt;/p&gt;
&lt;p&gt;为什么会工作不开心？&lt;/p&gt;
&lt;p&gt;主要原因有以下四点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;行业前景暗淡&lt;/strong&gt;：S公司处在行业的中游，上游受到运营商管控，下游在客户层面话语权也不大。这是一个资源限制型的行业，行业的命脉就在运营商，可能运营商有个风吹草动，整个行业就要翻江倒海。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自研能力薄弱&lt;/strong&gt;：S公司大部分业务都是购买的第三方的软件，各种变更都受到制约，添加一个小功能都要付费升级。自研能力弱的一个原因可能就是前些年赚钱太容易了，投资研发哪有赚快钱来的舒服呢。同时也是这个原因，多个第三方软件之间也造成了数据割裂，运行维护困难。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;家族企业制约&lt;/strong&gt;：S公司大部分人员都是老板的亲朋好友，家族式企业的优点是内聚力强，但是包容性弱。之前也有一些大厂进来的员工，没多久就辞职了。 我曾经也跟老板沟通过，似乎老板也有心做些变革。但是变革哪有那么容易，要变革不早都变了，还要等到现在？&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;短期主义&lt;/strong&gt;：似乎S公司没有什么具体的愿景，唯一感觉到的愿景就是赚快钱。一旦发现投入的回报太少，就立即切换目标。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;企业关怀差&lt;/strong&gt;：说实在，我没有感觉到多少员工关怀。在S公司的工作和在地主家做短工也没啥区别，老板想什么都要管，但是即管不了那么多，又管的不好。所以给人的感觉就是东一棒槌，西一榔头，看起来很卖力，实际上并没有什么产出。几乎每个月都有人离职，对员工都吝啬，不考虑员工的自尊，员工怎么可能对公司有归属感。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工作压力大&lt;/strong&gt;：受限于资源收紧、产品优势小，老板想提高营业额的方法是提高员工的服务水平。说实在，这真是杯水车薪。不想着从底层系统的解决问题，只想着通过给员工压力、通过加班来解决问题，只会造成工作压力大、人员流失大。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;所以，我的离职，实际上也是考虑再三的一个选择。&lt;/p&gt;
&lt;p&gt;当然，我在S公司也不是什么收获都没有。&lt;/p&gt;
&lt;h1 id=&#34;收获总结&#34;&gt;收获总结&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;深入了解了行业的运行原理、客户、资源、政策等信息&lt;/li&gt;
&lt;li&gt;对于数据分析方面有了较大的进步，毕竟我做了40+个数据报表来分析运行数据&lt;/li&gt;
&lt;li&gt;深入学习了python, 主要用来做数据分析。数据分析方面的协议栈主要有pandas、duckdb、doris(MySQL)、grafana来组成&lt;/li&gt;
&lt;li&gt;深入学习了python的GUI开发，主要用到的框架是wxPython，开发的两个工具分别给到运维人员和客服去使用，来提高运行效率&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>Windows安装Tesserocr</title>
      <link>https://wdd.js.org/zh/posts/2024/windows-install-tesserocr/</link>
      <pubDate>Wed, 24 Apr 2024 08:34:07 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2024/windows-install-tesserocr/</guid>
      <description>&lt;h1 id=&#34;安装tesserocr-windows_build&#34;&gt;安装tesserocr-windows_build&lt;/h1&gt;
&lt;p&gt;到&lt;a href=&#34;tesserocr-windows_build&#34;&gt;tesserocr-windows_build release&lt;/a&gt;页面下载对应的whl文件&lt;/p&gt;
&lt;p&gt;如下载 tesserocr-2.6.2-cp312-cp312-win_amd64.whl， 下载之后用pip安装&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;pip install tesserocr-2.6.2-cp312-cp312-win_amd64.whl
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;安装ocr-windows-exe程序&#34;&gt;安装ocr windows exe程序&lt;/h1&gt;
&lt;p&gt;在这个页面，有对应的exe程序，https://digi.bib.uni-mannheim.de/tesseract/&lt;/p&gt;
&lt;p&gt;例如下载这个exe文件 &lt;a href=&#34;https://digi.bib.uni-mannheim.de/tesseract/tesseract-ocr-w64-setup-v5.3.0.20221214.exe&#34;&gt;https://digi.bib.uni-mannheim.de/tesseract/tesseract-ocr-w64-setup-v5.3.0.20221214.exe&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;下载完成之后点击安装，一般我们不需要修改他的安装位置，默认的安装位置是C:\Program Files\Tesseract-OCR&lt;/p&gt;
&lt;p&gt;我们将C:\Program Files\Tesseract-OCR\tessdata下的所有文件，复制到C:\Program Files\Tesseract-OCR\目录下&lt;/p&gt;
&lt;h1 id=&#34;参考&#34;&gt;参考&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/simonflueckiger/tesserocr-windows_build/releases&#34;&gt;https://github.com/simonflueckiger/tesserocr-windows_build/releases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://digi.bib.uni-mannheim.de/tesseract/&#34;&gt;https://digi.bib.uni-mannheim.de/tesseract/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://tesseract-ocr.github.io/tessdoc/Downloads.html&#34;&gt;https://tesseract-ocr.github.io/tessdoc/Downloads.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.csdn.net/Yuyh131/article/details/103880585&#34;&gt;https://blog.csdn.net/Yuyh131/article/details/103880585&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>使用Excel理解prometheus的变化率相关函数</title>
      <link>https://wdd.js.org/zh/posts/2024/learn-prom-with-excel/</link>
      <pubDate>Sat, 16 Mar 2024 08:38:46 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2024/learn-prom-with-excel/</guid>
      <description>&lt;h1 id=&#34;counter类型的变化率-rate-irate-increase&#34;&gt;counter类型的变化率 rate, irate, increase&lt;/h1&gt;
&lt;p&gt;counter类型一般是只增不减的累积值，例如系统累计的http请求数量, 累计的话单数量。&lt;/p&gt;
&lt;p&gt;counter类型的指标变化率一般使用三个函数来计算，rate, irate, increase&lt;/p&gt;
&lt;p&gt;指标每隔15s采样一次数据, A列是采集的指标值，B列是对应的采集时间。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;demo_api_request_duration_seconds_count&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;instance&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;demo-service-0:10000&amp;#34;&lt;/span&gt;,path&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/api/bar&amp;#34;&lt;/span&gt;,status&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;200&amp;#34;&lt;/span&gt;,method&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;GET&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}[&lt;/span&gt;1m&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;序号&lt;/th&gt;
          &lt;th&gt;A&lt;/th&gt;
          &lt;th&gt;B&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;294401976&lt;/td&gt;
          &lt;td&gt;1710549816.105&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2&lt;/td&gt;
          &lt;td&gt;294402185&lt;/td&gt;
          &lt;td&gt;1710549831.105&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;3&lt;/td&gt;
          &lt;td&gt;294402393&lt;/td&gt;
          &lt;td&gt;1710549846.105&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;4&lt;/td&gt;
          &lt;td&gt;294402599&lt;/td&gt;
          &lt;td&gt;1710549861.105&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;rate是计算每秒的变化率,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rate 计算方案 (A4-A1) / (B4-B1)， 这里选择了首尾两个值的差值，除以时长秒&lt;/li&gt;
&lt;li&gt;irate 计算方案 (A4-A3) / (B4-B3) , 这里只选择里最后两个点的差值，除以时长秒&lt;/li&gt;
&lt;li&gt;increase 计算方式 (A4-A1) / (B4-B1) * 60,  这里的60是1m,  其实increase就是rate() * windows_seconds的语法糖&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;guage&#34;&gt;guage&lt;/h1&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;296164749 @1710648381.105
296165055 @1710648396.105
296165364 @1710648411.105
296165668 @1710648426.105
296165978 @1710648441.105
296166186 @1710648456.105
296166505 @1710648471.105
296166826 @1710648486.105
296167151 @1710648501.105
296167478 @1710648516.105
296167810 @1710648531.105
296168139 @1710648546.105
296168472 @1710648561.105
296168764 @1710648576.105
296169026 @1710648591.105
296169363 @1710648606.105
296169709 @1710648621.105
296170059 @1710648636.105
296170410 @1710648651.105
296170759 @1710648666.107
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    <item>
      <title>解决 VsCode pwsh终端环境变量不生效问题</title>
      <link>https://wdd.js.org/zh/posts/2023/vscode-pwsh-env-not-work/</link>
      <pubDate>Thu, 16 Nov 2023 08:08:39 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2023/vscode-pwsh-env-not-work/</guid>
      <description>&lt;p&gt;我在系统的环境变量设置里，用户和系统中，都加入了&lt;code&gt;ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/&lt;/code&gt;这个环境变量。&lt;/p&gt;
&lt;p&gt;单独打开windows Terminal应用，使用 &lt;code&gt;env | grep ELE&lt;/code&gt; 是能搜到我设置的环境变量的。但是在vscode中，这个环境变量不存在。&lt;/p&gt;
&lt;p&gt;我尝试了以下几个方法&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;重启电脑，无效&lt;/li&gt;
&lt;li&gt;配置&lt;code&gt;&amp;quot;terminal.integrated.persistentSessionReviveProcess&amp;quot;: &amp;quot;never&amp;quot;&lt;/code&gt;, 然后重启电脑，无效&lt;/li&gt;
&lt;li&gt;在终端直接执行&lt;code&gt;code .&lt;/code&gt;, 在终端打开vscode, 依然无效&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;因此，我想起了之前配置的pwsh的配置文件。 可以使用&lt;code&gt;code $PROFILE&lt;/code&gt;, 打开pwsh的配置文件。&lt;/p&gt;
&lt;p&gt;然后再配置文件中设置环境变量， 之后重启vscode, 环境变量就正常能读取到了。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 文件名 Microsoft.PowerShell_profile.ps1
$env:ELECTRON_MIRROR=&amp;#34;https://npmmirror.com/mirrors/electron/&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;参考&#34;&gt;参考&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.zhihu.com/question/266858097&#34;&gt;https://www.zhihu.com/question/266858097&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>如何选择，汉王Clear7与文石Leaf3</title>
      <link>https://wdd.js.org/zh/posts/2023/hanvon-clear7-vs-book-leaf3/</link>
      <pubDate>Mon, 06 Nov 2023 09:30:34 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2023/hanvon-clear7-vs-book-leaf3/</guid>
      <description>&lt;h1 id=&#34;购买选择&#34;&gt;购买选择&lt;/h1&gt;
&lt;p&gt;我的kindle pw4已经用了快三年了，机器性能有些不足，电池也有些不够用了。正逢双十一之际，我觉得可以买一个开放系统的电纸书来用用。&lt;/p&gt;
&lt;p&gt;买开放系统的另一个原因是自从亚马逊退出中国后，我用微信读书比较多，也买了微信读书的会员。&lt;/p&gt;
&lt;p&gt;开放系统基本上都是基于安卓系统定制的，可以选择的厂商比较多。&lt;/p&gt;
&lt;p&gt;最终筛选下来，我选择了汉王clear7和文石leaf3， 我下单了两个，觉得先体验一下，然后在退一个。&lt;/p&gt;
&lt;p&gt;然而用了不到两天之后，我还是决定把两个机器都给退了，继续用我的kindle pw4。&lt;/p&gt;
&lt;h1 id=&#34;选择因素&#34;&gt;选择因素&lt;/h1&gt;
&lt;p&gt;就我个人而言，电子书最为重要的选择因素有以下三点。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;显示效果&lt;/strong&gt;: 说实在的，现在的电子书基本上都是carta1200、300ppi、冷暖光。基本上从显示效果上来说，各大厂家都是半斤八两。就我自己体验而言，我并没有发现汉王的显示效果和文石leaf3有何不同。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;握持手感&lt;/strong&gt;: 外观影响握持手感，外观一般分为两类，一类是就是平板设计，像kindle paperwhite系列。另一类就是书脊式设计，握持更舒适，像kindle os3, 汉王clear7之类的。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;简洁系统&lt;/strong&gt;: 电子书并不是手机，不需要太多的功能，功能太多反而成为累赘&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;稳定性&lt;/strong&gt;: 点子产品难免被摔、或者淋水，对于这些意外情况，如果产品非常脆弱，那么很大可能会损失大笔的金额。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;续航&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;文石的缺点&#34;&gt;文石的缺点&lt;/h1&gt;
&lt;p&gt;文石和汉王的两款产品，拿到手开机不到一小时，我就决定先退了文石。&lt;/p&gt;
&lt;p&gt;原因有以下几点&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;显示效果文石和汉王差不多，没啥突出亮点&lt;/li&gt;
&lt;li&gt;握持手感文石肯定比不过汉王的书脊式设计, 并且汉王更轻&lt;/li&gt;
&lt;li&gt;文石的系统太复杂，设置太多，甚至还有个iphone类似的小白点设计，小白点点击之后展开很多图标，每个图标我都不知道做什么的&lt;/li&gt;
&lt;li&gt;掉电速度，文石的电量肉眼可见的在不断减少&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;汉王的缺点&#34;&gt;汉王的缺点&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;微信读书功能阉割, 这不是汉王的问题，而是微信读书自身的问题。例如书架页面，书籍只有一个排序的顺序，就是按照最近阅读的排序。而无法像ios或者安卓app一样能够按照阅读进度排序，另外也没有阅读时长分析的功能。 另外我也注意到，微信读书电纸书版，扫码登录的有效期是24小时，我不知道这是不是意味着24小时之后我又要重新扫码。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;触感光滑，汉王的背板的触感让人感觉非常光滑，感觉稍不注意就会滑下去的样子。完全没有kindle pw4那种拿在手机，就粘在手上的感觉。所以我觉得，买汉王，就必须要买一个保护套，但是官方卖的保护套也太贵了吧，居然要110多块，这点有点像割韭菜。什么保护套能卖那么贵，都快赶上十分之一的电纸书的价格了。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;词典缺陷，汉王的词典也是我要吐槽的功能之一，只能把单词的原型加入到单词本，单词来个复数或者过去分词，就不能加入单词本了。kindle的生词本，所有单词，无论什么形式都能加入单词本。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;掉电速度, 从昨晚五点多开机，到今天早上，基本上没到一天，电池已经掉电接近40%了&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;自动关机, 为了省电，汉王在2小时不使用后，会自动关机。然而这个开机时间就有点久，你可设想一下，每天早上，你想看书的时候，你都要等几十秒的开机时间，那你能受得了吗？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;按钮反馈，松松垮垮, 触感没有一致性体验&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;结论&#34;&gt;结论&lt;/h1&gt;
&lt;p&gt;目前而言，国产的电纸书系统，除了开放的系统之外，其他各个方面还是存在与kindle有较大的差距。&lt;/p&gt;
&lt;p&gt;当然，如果你从未使用过kindle系列的产品，国产的电纸书还是值得买的。&lt;/p&gt;</description>
    </item>
    <item>
      <title>MacBook icloud 同步卡死， 请尝试重启电脑</title>
      <link>https://wdd.js.org/zh/posts/2023/macbook-icloud-sync-stuck/</link>
      <pubDate>Sun, 20 Aug 2023 13:07:40 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2023/macbook-icloud-sync-stuck/</guid>
      <description>&lt;h1 id=&#34;环境说明&#34;&gt;环境说明&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;MacBook Pro M2&lt;/li&gt;
&lt;li&gt;系统版本 13.4.1&lt;/li&gt;
&lt;li&gt;网络环境为wifi&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;操作步骤&#34;&gt;操作步骤&lt;/h1&gt;
&lt;p&gt;我往icloud的文件夹下，粘贴几个文件夹，文件的内容挺多的，然后finder上显示icloud的状态就一直是处于同步中了。&lt;/p&gt;
&lt;p&gt;等了好久，同步的过程似乎卡住了。&lt;/p&gt;
&lt;p&gt;网上看了一些解决方案，似乎都没啥作用。&lt;/p&gt;
&lt;p&gt;我想起来以前的同样的一次卡顿同步的解决方案：重启电脑&lt;/p&gt;
&lt;p&gt;于是，我重启了一次电脑，再次开机，打开finder, icloud文件状态非常快同步完了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>安装NodeJS, N命令似乎卡住了</title>
      <link>https://wdd.js.org/zh/posts/2023/n-stucked/</link>
      <pubDate>Sun, 09 Jul 2023 14:20:45 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2023/n-stucked/</guid>
      <description>&lt;p&gt;我一般会紧跟着NodeJS官网的最新版，来更新本地的NodeJS版本。&lt;/p&gt;
&lt;p&gt;我的系统是ubuntu 20.4, 我用&lt;a href=&#34;https://github.com/tj/n&#34;&gt;tj/n&lt;/a&gt;这个工具来更新Node。&lt;/p&gt;
&lt;p&gt;但是这一次，这个命令似乎卡住了。&lt;/p&gt;
&lt;p&gt;我排查后发现，是n这个命令在访问https://nodejs.org/dist/index.tab这个地址时，卡住了。&lt;/p&gt;
&lt;p&gt;请求超时，因为默认没有设置超时时长，所以等待了很久才显示超时的报错，表现象上看起来就是卡住了。&lt;/p&gt;
&lt;p&gt;首先我用dig命令查了nodejs.org的dns解析，我发现是正常解析的。&lt;/p&gt;
&lt;p&gt;然后我又用curl对nodejs官网做了一个测试，发现也是请求超时。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i -m &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt; https://nodejs.org
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl: &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;28&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; Failed to connect to nodejs.org port &lt;span style=&#34;color:#ae81ff&#34;&gt;443&lt;/span&gt; after &lt;span style=&#34;color:#ae81ff&#34;&gt;3854&lt;/span&gt; ms: 连接超时
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这样问题就清楚了，然后我就想起来npmirrror上应该有nodejs的镜像。 在查看n这个工具的文档时，我也发现，它是支持设置mirror的。&lt;/p&gt;
&lt;p&gt;其中给的例子用的就是淘宝NPM&lt;/p&gt;
&lt;p&gt;就是设置了一个环境变量。然后执行&lt;code&gt;source ~/.zshrc&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;export N_NODE_MIRROR=https://npmmirror.com/mirrors/node
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;但是，我发现在命令行里用echo可以打印N_NODE_MIRROR这个变量的值，但是在安装脚本里，还是无法获取设置的这个mirror。&lt;/p&gt;
&lt;p&gt;我想或许和我在执行&lt;code&gt;sudo n lts&lt;/code&gt;时的sudo有关，这个.zshrc在sudo这种管理员模式下是不生效的。普通用户的环境变量也不会继承到sudo执行的环境变量里&lt;/p&gt;
&lt;p&gt;最后，我用&lt;code&gt;sudo -E n lts&lt;/code&gt;, 成功的从npmmirror上更新了nodejs的版本。&lt;/p&gt;
&lt;p&gt;关于curl超时的这个问题，我也给n仓库提出了pull request, &lt;a href=&#34;https://github.com/tj/n/pull/771&#34;&gt;https://github.com/tj/n/pull/771&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>VScode激活Tab更容易区分</title>
      <link>https://wdd.js.org/zh/posts/2023/vscode-highlight-tab/</link>
      <pubDate>Tue, 18 Apr 2023 13:43:07 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2023/vscode-highlight-tab/</guid>
      <description>&lt;p&gt;默认情况下VScode的tab栏，当前的颜色会更深一点。如下图所示，第三个就是激活的。&lt;/p&gt;
&lt;p&gt;但是实际上并没有太高的区分度，特别是当显示屏有点反光的时候。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/posts/2023/vscode-highlight-tab/2023-04-18-13-45-18.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;我想应该不止一个人有这个问题吧&lt;/p&gt;
&lt;p&gt;看了github上，有个人反馈了这个问题，https://github.com/Microsoft/vscode/issues/24586&lt;/p&gt;
&lt;p&gt;后面有人回复了&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;workbench.colorCustomizations&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;tab.activeBorder&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;#ff0000&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;tab.unfocusedActiveBorder&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上面就是用来配置Tab边界的颜色的。&lt;/p&gt;
&lt;p&gt;看下效果，当前激活的Tab下有明显的红线，是不是更容易区分了呢&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/posts/2023/vscode-highlight-tab/2023-04-18-13-51-17.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>行位结束符引起的问题</title>
      <link>https://wdd.js.org/zh/posts/2023/tips-about-cr-lf/</link>
      <pubDate>Mon, 16 Jan 2023 15:03:03 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2023/tips-about-cr-lf/</guid>
      <description>&lt;h1 id=&#34;crlf&#34;&gt;CRLF&lt;/h1&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;二进制&lt;/th&gt;
          &lt;th&gt;十进制&lt;/th&gt;
          &lt;th&gt;十六进制&lt;/th&gt;
          &lt;th&gt;八进制&lt;/th&gt;
          &lt;th&gt;字符/缩写&lt;/th&gt;
          &lt;th&gt;解释&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;00001010&lt;/td&gt;
          &lt;td&gt;10&lt;/td&gt;
          &lt;td&gt;0A&lt;/td&gt;
          &lt;td&gt;012&lt;/td&gt;
          &lt;td&gt;LF/NL(Line Feed/New Line)&lt;/td&gt;
          &lt;td&gt;换行键&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;00001101&lt;/td&gt;
          &lt;td&gt;13&lt;/td&gt;
          &lt;td&gt;0D&lt;/td&gt;
          &lt;td&gt;085&lt;/td&gt;
          &lt;td&gt;CR (Carriage Return)&lt;/td&gt;
          &lt;td&gt;回车键&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;CR代表回车符，LF代表换行符。&lt;/p&gt;
&lt;p&gt;这两个符号本身都是不可见的。&lt;/p&gt;
&lt;p&gt;如果打印出来&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CR 会显示 &lt;code&gt;\r&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;LF 会显示 &lt;code&gt;\n&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;不同系统的行结束符&#34;&gt;不同系统的行结束符&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Linux系统和Mac换行符是 &lt;code&gt;\n&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Windows系统的换行符是 &lt;code&gt;\r\n&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;如何区分文件的换行符&#34;&gt;如何区分文件的换行符？&lt;/h1&gt;
&lt;p&gt;可以使用od命令&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;od -bc index.md
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;假如文件的原始内容如下&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;- 1
- 2
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;注意012是八进制的数，十进制对应的数字是10，也就是换行符。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;0000000 055 040 061 012 055 040 062
          -       1  \n   -       2
0000007
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果用vscode打开文件，也能看到对应的文件格式，如LF。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://wdd.js.org/zh/posts/2023/tips-about-cr-lf/2023-01-16-15-56-34.png&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;换行符的的差异会导致哪些问题&#34;&gt;换行符的的差异会导致哪些问题？&lt;/h1&gt;
&lt;h2 id=&#34;shell脚本问题&#34;&gt;shell脚本问题&lt;/h2&gt;
&lt;p&gt;如果bash脚本里包含CRLF,  可能导致脚本无法解析等各种异常问题。&lt;/p&gt;
&lt;p&gt;例如下面的报错，docker启动shell脚本可能是在windows下编写的。所以脚本无法&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;standard_init_linux.go:211: exec user process caused &amp;#34;no such file or directory&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;如何把windows文件类型转为unix&#34;&gt;如何把windows文件类型转为unix?&lt;/h1&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 可以把windows文件类型转为unix

dos2unix file
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果是vscode，也可以点击对应的文件格式按钮。&lt;/p&gt;</description>
    </item>
    <item>
      <title>为什么我不再使用语雀</title>
      <link>https://wdd.js.org/zh/posts/2022/12/why-i-dont-not-use-yuque-any-more/</link>
      <pubDate>Tue, 06 Dec 2022 21:10:38 +0800</pubDate>
      <guid>https://wdd.js.org/zh/posts/2022/12/why-i-dont-not-use-yuque-any-more/</guid>
      <description>&lt;p&gt;我在2019年的六月份时候，开始使用语雀。&lt;/p&gt;
&lt;p&gt;一路走来，我见证了语雀的功能越来越多，但是于此同时，我也越来越讨厌语雀。&lt;/p&gt;
&lt;p&gt;2022年12月初，我基本上把语雀上的所有内容都迁移到我的hugo博客上。&lt;/p&gt;
&lt;p&gt;我的博客很乱，也很多。我写了一个脚本，一个一个知识库的搬迁，总体速度还算快，唯一不便的就是图片需要一个一个复制粘贴。&lt;/p&gt;
&lt;p&gt;有些图片是用语雀的绘图语言例如plantuml编写的，就只能截图保存了。&lt;/p&gt;
&lt;p&gt;总之，我也是蛮累的。&lt;/p&gt;
&lt;p&gt;简单列一下我不喜欢语雀的几个原因:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;性能差，首页渲染慢&lt;/strong&gt;，常常要等很久，首页才能打开&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;产品定位混乱，随意更改用户数据&lt;/strong&gt;
&lt;ol&gt;
&lt;li&gt;我记得有时候我把知识库升级成了空间，过了一段时间，不知道为什么空间由变成了知识库。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数字花园这个概念真的很烂&lt;/strong&gt;。我好好的个人主页，某一天打开，大变样，换了个名字，叫做数字花园。甚至没有给用户一个选择保留老版本的个人主页的权利。&lt;strong&gt;太不尊重用户了&lt;/strong&gt;！！ 就好像你下班回家，看见房门被人撬开，你打开房门，看见有人在你的客厅种满大蒜，然后还兴高采烈的告诉你，看，这是您的数字菜园！多好，以后不用买蒜了。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;会员的流量计费规则&lt;/strong&gt;， 或许现在的计费规则已经变了，我也没有再充会员，但是再以前。即使是会员，也是按流量计费的。什么叫按流量计费，假如你的一篇博客里上传了一张1mb的图片，即使你后来把这个图片删了，这1mb的流量还是会存在。而且流量是一直往上涨的，还不像运营商，每月一号给你清零一次的机会。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
    <item>
      <title>模块传参的重构</title>
      <link>https://wdd.js.org/zh/opensips/3x/module-args/</link>
      <pubDate>Sat, 03 Dec 2022 21:01:02 +0800</pubDate>
      <guid>https://wdd.js.org/zh/opensips/3x/module-args/</guid>
      <description>&lt;p&gt;写过opensips脚本的同学，往往对函数的传参感到困惑。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ds_select_dst()可以接受整数或者值为正数的变量作为第一个参数，但是nat_uac_test()的第一个参数就只能是整数，而不能是变量&lt;/li&gt;
&lt;li&gt;为什么rl_check()可以接受格式化的字符串，而save()只能接受字符串。&lt;/li&gt;
&lt;li&gt;为什么&lt;code&gt;ds_select_dst(&amp;quot;1&amp;quot;, &amp;quot;4&amp;quot;)&lt;/code&gt; 作为整数也要加上双引号？&lt;/li&gt;
&lt;li&gt;为什么变量要加上双引号？ &lt;code&gt;ds_select_dst(&amp;quot;$var(aa)&amp;quot;, &amp;quot;4&amp;quot;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;为什么&lt;code&gt;t_on_branch(&amp;quot;1&amp;quot;)&lt;/code&gt;路由的钩子要加上双引号？&lt;/li&gt;
&lt;li&gt;为什么&lt;code&gt;route(go_to_something);&lt;/code&gt;这里又不需要加上引号？&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ds_select_dst&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;0&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$var&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;aa&lt;span style=&#34;color:#f92672&#34;&gt;)=&lt;/span&gt;1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ds_select_dst&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$var&lt;span style=&#34;color:#e6db74&#34;&gt;(aa)&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;0&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rl_check&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gw_&lt;/span&gt;$ru&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$var&lt;span style=&#34;color:#e6db74&#34;&gt;(limit)&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;; &lt;span style=&#34;color:#75715e&#34;&gt;#格式化的gw_$ru&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;save&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;location&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;; &lt;span style=&#34;color:#75715e&#34;&gt;#单纯的字符串作为参数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;从3.0开始，传参可以更加自然。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;整数可以直接传参，不用加双引号&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;do_something&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;1, 1&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;输入或者输出的$var(), 不用加双引号，加了反而会报错&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;do_something&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;$var&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;a&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;, $var&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;b&lt;span style=&#34;color:#f92672&#34;&gt;))&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;格式化字符串，需要加双引号&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;do_something&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;1, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$var&lt;span style=&#34;color:#e6db74&#34;&gt;(bb)_&lt;/span&gt;$var&lt;span style=&#34;color:#e6db74&#34;&gt;(b)&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;参考&#34;&gt;参考&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.opensips.org/2019/11/05/the-module-function-interface-rework-in-opensips-3-0/&#34;&gt;https://blog.opensips.org/2019/11/05/the-module-function-interface-rework-in-opensips-3-0/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.opensips.org/Documentation/Script-Syntax-3-0&#34;&gt;https://www.opensips.org/Documentation/Script-Syntax-3-0#&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>Pdf学习资料</title>
      <link>https://wdd.js.org/zh/opensips/pdf/</link>
      <pubDate>Sat, 03 Dec 2022 16:02:18 +0800</pubDate>
      <guid>https://wdd.js.org/zh/opensips/pdf/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/TelNYX.pdf&#34;&gt;TelNYX.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/OpenSIPS%202.3.pdf&#34;&gt;OpenSIPS 2.3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/mediasoup%20Cutting%20Edge%20WebRTC%20Video%20COnferencing.pdf&#34;&gt;mediasoup Cutting Edge WebRTC Video COnferencing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/FreeSWITCH-driven%20routing%20in%20OpenSIPS.pdf&#34;&gt;FreeSWITCH-driven routing in OpenSIPS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Contact%20center%20on%20Steroids%20Voicenter.pdf&#34;&gt;Voicenter: Contact center on Steroids&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Vlad_Paiu-Distributed_OpenSIPS_Systems_Cluecon14.pdf&#34;&gt;Vlad_Paiu-Distributed_OpenSIPS_Systems_Cluecon14.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Vlad_Paiu-OpenSIPS_Summit_Austin_2015-Async.pdf&#34;&gt;Vlad_Paiu-OpenSIPS_Summit_Austin_2015-Async.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Ionut_Ionita-OpenSIPS_Summit2017-Capturing_beyond_SIP.pdf&#34;&gt;Ionut_Ionita-OpenSIPS_Summit2017-Capturing_beyond_SIP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/FLAVIO_GONCALVES-Fraud_in_VoIP_Today.pdf&#34;&gt;FLAVIO_GONCALVES-Fraud_in_VoIP_Today.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Alexandr_Dubovikov-OpenSIPS_Summit2017-RTC_Threat_Intelligence_Exchange.pdf&#34;&gt;Alexandr_Dubovikov-OpenSIPS_Summit2017-RTC_Threat_Intelligence_Exchange.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/OpenSIPS_LoadBalancing.pdf&#34;&gt;OpenSIPS_LoadBalancing.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Vlad_Paiu-OpenSIPS_Summit_2104-OpenSIPS_End_User_Services.pdf&#34;&gt;Vlad_Paiu-OpenSIPS_Summit_2104-OpenSIPS_End_User_Services.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Razvan_Crainea-OpenSIPS_Summit2017-From_SIPI_Trunks_to_End_Users.pdf&#34;&gt;Razvan_Crainea-OpenSIPS_Summit2017-From_SIPI_Trunks_to_End_Users.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Razvan_Crainea-OpenSIPS_Summit-Scaling_Asterisk.pdf&#34;&gt;Razvan_Crainea-OpenSIPS_Summit-Scaling_Asterisk.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Vlad_Paiu-OpenSIPS_Summit-Service_Enabling_for_Asterisk.pdf&#34;&gt;Vlad_Paiu-OpenSIPS_Summit-Service_Enabling_for_Asterisk.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Jonas_Borjesson-OpenSIPS_Summit_Austin_2015.pdf&#34;&gt;Jonas_Borjesson-OpenSIPS_Summit_Austin_2015.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Michele_Pinasi-OpenSIPS_Summit2017-How_we_did_VoIP.pdf&#34;&gt;Michele_Pinasi-OpenSIPS_Summit2017-How_we_did_VoIP.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Bogdan_Iancu-OpenSIPS_Summit_Keynotes.pdf&#34;&gt;Bogdan_Iancu-OpenSIPS_Summit_Keynotes.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Giovanni_Maruzselli-OpenSIPS_Summit2017-Scaling_FreeSWITCHes.pdf&#34;&gt;Giovanni_Maruzselli-OpenSIPS_Summit2017-Scaling_FreeSWITCHes.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Maksym_Sobolyev-OpenSIPS_Summit2017-Sippy_Labs_update.pdf&#34;&gt;Maksym_Sobolyev-OpenSIPS_Summit2017-Sippy_Labs_update.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/docker-cluster.pdf&#34;&gt;docker-cluster.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/voip%20malware%20attack%20tool%20.pdf&#34;&gt;voip malware attack tool .pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Bogdan_Iancu-OpenSIPS_Summit-OpenSIPS_2_1.pdf&#34;&gt;Bogdan_Iancu-OpenSIPS_Summit-OpenSIPS_2_1.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Pete_Kelly-OpenSIPS_Workshop_Chicago_2015-Calling_Cards_B2BUA.pdf&#34;&gt;Pete_Kelly-OpenSIPS_Workshop_Chicago_2015-Calling_Cards_B2BUA.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Bogdan_Iancu-OpenSIPS_Summit-keynotes.pdf&#34;&gt;Bogdan_Iancu-OpenSIPS_Summit-keynotes.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Alex_Goulis-Opensips_CNAME.pdf&#34;&gt;Alex_Goulis-Opensips_CNAME.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/OpenSIPS_2.0_Framework.pdf&#34;&gt;OpenSIPS_2.0_Framework.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/opensips/pdf/Norman_Brandinger-OpenSIPS_Summit_2014-Advanced_SIP_Routing_with_OpenSIPS_modules.pdf&#34;&gt;Norman_Brandinger-OpenSIPS_Summit_2014-Advanced_SIP_Routing_with_OpenSIPS_modules.pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>1.1 脚本结构 - 全局参数、模块配置、路由</title>
      <link>https://wdd.js.org/zh/kamailio/56/structure/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/structure/</guid>
      <description>&lt;h1 id=&#34;1-structure&#34;&gt;1. Structure&lt;/h1&gt;
&lt;p&gt;The structure of the kamailio.cfg can be seen as three parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;global parameters&lt;/li&gt;
&lt;li&gt;modules settings&lt;/li&gt;
&lt;li&gt;routing blocks&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For clarity and making it easy to maintain, it is recommended to keep
them in this order, although some of them can be mixed.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;✅ 这三个部分可以混合，但为了清晰和维护的方便，建议按照这个顺序排列。&lt;/p&gt;&lt;/blockquote&gt;
&lt;h1 id=&#34;2-global-parameters-section&#34;&gt;2. Global Parameters Section&lt;/h1&gt;
&lt;p&gt;This is the first part of the configuration file, containing the
parameters for the core of kamailio and custom global parameters.&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.10 SCTP参数</title>
      <link>https://wdd.js.org/zh/kamailio/56/sctp-params/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/sctp-params/</guid>
      <description>&lt;h1 id=&#34;1-disable_sctp&#34;&gt;1. disable_sctp&lt;/h1&gt;
&lt;p&gt;Global parameter to disable SCTP support in the SIP server. see
enable_sctp&lt;/p&gt;
&lt;p&gt;Default value is &amp;lsquo;auto&amp;rsquo;.&lt;/p&gt;
&lt;p&gt;Example of usage:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  disable_sctp=yes
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;2-enable_sctp&#34;&gt;2. enable_sctp&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;enable_sctp = 0/1/2  - SCTP disabled (0)/ SCTP enabled (1)/auto (2),
                       default auto (2)
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;3-sctp_children&#34;&gt;3. sctp_children&lt;/h1&gt;
&lt;p&gt;sctp children no (similar to udp children)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sctp_children = number
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;4-sctp_socket_rcvbuf&#34;&gt;4. sctp_socket_rcvbuf&lt;/h1&gt;
&lt;p&gt;Size for the sctp socket receive buffer&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alias name:&lt;/strong&gt; &lt;strong&gt;sctp_socket_receive_buffer&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sctp_socket_rcvbuf = number
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;5-sctp_socket_sndbuf&#34;&gt;5. sctp_socket_sndbuf&lt;/h1&gt;
&lt;p&gt;Size for the sctp socket send buffer&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.11 UDP参数</title>
      <link>https://wdd.js.org/zh/kamailio/56/udp-params/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/udp-params/</guid>
      <description>&lt;h1 id=&#34;1-udp4_raw&#34;&gt;1. udp4_raw&lt;/h1&gt;
&lt;p&gt;Enables raw socket support for sending UDP IPv4 datagrams (40-50%
performance increase on linux multi-cpu).&lt;/p&gt;
&lt;p&gt;Possible values: 0 - disabled (default), 1 - enabled, -1 auto.&lt;/p&gt;
&lt;p&gt;In &amp;ldquo;auto&amp;rdquo; mode it will be enabled if possible (sr started as root or
with CAP_NET_RAW). udp4_raw can be used on Linux and FreeBSD. For other
BSDs and Darwin one must compile with -DUSE_RAW_SOCKS. On Linux one
should also set udp4_raw_mtu if the MTU on any network interface that
could be used for sending is smaller than 1500.&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.12 黑名单参数</title>
      <link>https://wdd.js.org/zh/kamailio/56/bl-params/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/bl-params/</guid>
      <description>&lt;h1 id=&#34;1-dst_blocklist_expire&#34;&gt;1. dst_blocklist_expire&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Alias name:&lt;/strong&gt; &lt;strong&gt;dst_blocklist_ttl&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;How much time a blocklisted destination will be kept in the blocklist
(w/o any update).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dst_blocklist_expire = time in s (default 60 s)
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;2-dst_blocklist_gc_interval&#34;&gt;2. dst_blocklist_gc_interval&lt;/h1&gt;
&lt;p&gt;How often the garbage collection will run (eliminating old, expired
entries).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dst_blocklist_gc_interval = time in s (default 60 s)
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;3-dst_blocklist_init&#34;&gt;3. dst_blocklist_init&lt;/h1&gt;
&lt;p&gt;If off, the blocklist is not initialized at startup and cannot be
enabled at runtime, this saves some memory.&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.13 实时参数</title>
      <link>https://wdd.js.org/zh/kamailio/56/rt-params/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/rt-params/</guid>
      <description>&lt;h1 id=&#34;1-real_time&#34;&gt;1. real_time&lt;/h1&gt;
&lt;p&gt;Sets real time priority for all the Kamailio processes, or the timers
(bitmask).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   Possible values:   0  - off
                      1  - the &amp;quot;fast&amp;quot; timer
                      2  - the &amp;quot;slow&amp;quot; timer
                      4  - all processes, except the timers
   Example: real_time= 7 =&amp;gt; everything switched to real time priority.

real_time = &amp;lt;int&amp;gt; (flags) (default off)
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;2-rt_policy&#34;&gt;2. rt_policy&lt;/h1&gt;
&lt;p&gt;Real time scheduling policy, 0 = SCHED_OTHER, 1= SCHED_RR and
2=SCHED_FIFO&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rt_policy= &amp;lt;0..3&amp;gt; (default 0)
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;3-rt_prio&#34;&gt;3. rt_prio&lt;/h1&gt;
&lt;p&gt;Real time priority used for everything except the timers, if real_time
is enabled.&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.14 核心函数</title>
      <link>https://wdd.js.org/zh/kamailio/56/core-func/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/core-func/</guid>
      <description>&lt;p&gt;Functions exported by core that can be used in route blocks.&lt;/p&gt;
&lt;h1 id=&#34;1-add_local_rport-&#34;&gt;1. add_local_rport ⭐️&lt;/h1&gt;
&lt;p&gt;Add &lt;strong&gt;rport&lt;/strong&gt; parameter to local generated Via header &amp;ndash; see RFC3581. In
effect for forwarded SIP requests.&lt;/p&gt;
&lt;p&gt;Example of usage:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;add_local_rport&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;2-avpflags&#34;&gt;2. avpflags&lt;/h1&gt;
&lt;h1 id=&#34;3-break&#34;&gt;3. break&lt;/h1&gt;
&lt;p&gt;&amp;lsquo;break&amp;rsquo; statement can be used to end a &amp;lsquo;case&amp;rsquo; block in a &amp;lsquo;switch&amp;rsquo;
statement or exit from a &amp;lsquo;while&amp;rsquo; statement.&lt;/p&gt;
&lt;h1 id=&#34;4-drop-&#34;&gt;4. drop ⭐️&lt;/h1&gt;
&lt;p&gt;Stop the execution of the configuration script and alter the implicit
action which is done afterwards.&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.15 自定义全局参数</title>
      <link>https://wdd.js.org/zh/kamailio/56/custom-params/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/custom-params/</guid>
      <description>&lt;p&gt;These are parameters that can be defined by the writer of kamailio.cfg
in order to be used inside routing blocks. One of the important
properties for custom global parameters is that their value can be
changed at runtime via RPC commands, without restarting Kamailio.&lt;/p&gt;
&lt;p&gt;The definition of a custom global parameter must follow the pattern:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;group.variable = value desc &amp;quot;description&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The value can be a quoted string or integer number.&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.16 路由块 - 请求路由、响应路由、分支路由、失败路由等</title>
      <link>https://wdd.js.org/zh/kamailio/56/routing-blocks/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/routing-blocks/</guid>
      <description>&lt;h1 id=&#34;1-routing-blocks&#34;&gt;1. Routing Blocks&lt;/h1&gt;
&lt;p&gt;The routing blocks are the parts of the configuration file executed by
kamailio at runtime. They can be seen as blocks of actions similar to
functions (or procedures) from common programming languages.&lt;/p&gt;
&lt;p&gt;A routing block is identified by a specific token, followed by a name in
between square brackets and actions in between curly braces.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;route_block_id[NAME] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ACTIONS
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The name can be any alphanumeric string, with specific routing blocks
enforcing a particular format.&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.17 脚本语法 - if、else、switch、while、赋值、比较、算数等</title>
      <link>https://wdd.js.org/zh/kamailio/56/script-statements/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/script-statements/</guid>
      <description>&lt;h1 id=&#34;1-if&#34;&gt;1. if&lt;/h1&gt;
&lt;p&gt;IF-ELSE statement&lt;/p&gt;
&lt;p&gt;Prototype:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    if(expr) {
       actions;
    } else {
       actions;
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;expr&lt;/code&gt; should be a valid logical expression.&lt;/p&gt;
&lt;p&gt;The logical operators that can be used in &lt;code&gt;expr&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;==&lt;/code&gt;:      equal&lt;/li&gt;
&lt;li&gt;&lt;code&gt;!=&lt;/code&gt;:      not equal&lt;/li&gt;
&lt;li&gt;&lt;code&gt;=~&lt;/code&gt;:      case-insensitive regular expression matching: Note: Posix regular expressions will be used, e.g. use &lt;code&gt;[[:digit:]]{3}&lt;/code&gt; instead of &lt;code&gt;\d\d\d&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;!~&lt;/code&gt;:      regular expression not-matching (NOT PORTED from Kamailio 1.x, use &lt;code&gt;!(x =~ y)&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;gt;&lt;/code&gt;:       greater&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;gt;=&lt;/code&gt;:      greater or equal&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;&lt;/code&gt;:       less&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;=&lt;/code&gt;:      less or equal&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;:      logical AND&lt;/li&gt;
&lt;li&gt;&lt;code&gt;||&lt;/code&gt;:      logical OR&lt;/li&gt;
&lt;li&gt;&lt;code&gt;!&lt;/code&gt;:       logical NOT&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example of usage:&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.18 命令行参数</title>
      <link>https://wdd.js.org/zh/kamailio/56/cli-params/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/cli-params/</guid>
      <description>&lt;h1 id=&#34;command-line-parameters&#34;&gt;Command Line Parameters&lt;/h1&gt;
&lt;p&gt;Kamailio can be started with a set of command line parameters, providing
more flexibility to control what is doing at runtime. Some of them can
be quite useful when running on containerised environments.&lt;/p&gt;
&lt;p&gt;To see the the available command line parameters, run &lt;strong&gt;kamailio -h&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# kamailio -h

version: kamailio 5.4.0-dev4 (x86_64/darwin) 8c1864
Usage: kamailio [options]
Options:
    -a mode      Auto aliases mode: enable with yes or on,
                  disable with no or off
    --alias=val  Add an alias, the value has to be &#39;[proto:]hostname[:port]&#39;
                  (like for &#39;alias&#39; global parameter)
    -A define    Add config pre-processor define (e.g., -A WITH_AUTH,
                  -A &#39;FLT_ACC=1&#39;, -A &#39;DEFVAL=&amp;quot;str-val&amp;quot;&#39;)
    -b nr        Maximum receive buffer size which will not be exceeded by
                  auto-probing procedure even if  OS allows
    -c           Check configuration file for syntax errors
    -d           Debugging mode (multiple -d increase the level)
    -D           Control how daemonize is done:
                  -D..do not fork (almost) anyway;
                  -DD..do not daemonize creator;
                  -DDD..daemonize (default)
    -e           Log messages printed in terminal colors (requires -E)
    -E           Log to stderr
    -f file      Configuration file (default: /usr/local/etc/kamailio/kamailio.cfg)
    -g gid       Change gid (group id)
    -G file      Create a pgid file
    -h           This help message
    --help       Long option for `-h`
    -I           Print more internal compile flags and options
    -K           Turn on &amp;quot;via:&amp;quot; host checking when forwarding replies
    -l address   Listen on the specified address/interface (multiple -l
                  mean listening on more addresses). The address format is
                  [proto:]addr_lst[:port][/advaddr],
                  where proto=udp|tcp|tls|sctp,
                  addr_lst= addr|(addr, addr_lst),
                  addr=host|ip_address|interface_name and
                  advaddr=addr[:port] (advertised address).
                  E.g: -l localhost, -l udp:127.0.0.1:5080, -l eth0:5062,
                  -l udp:127.0.0.1:5080/1.2.3.4:5060,
                  -l &amp;quot;sctp:(eth0)&amp;quot;, -l &amp;quot;(eth0, eth1, 127.0.0.1):5065&amp;quot;.
                  The default behaviour is to listen on all the interfaces.
    --loadmodule=name load the module specified by name
    --log-engine=log engine name and data
    -L path      Modules search path (default: /usr/local/lib64/kamailio/modules)
    -m nr        Size of shared memory allocated in Megabytes
    --modparam=modname:paramname:type:value set the module parameter
                  type has to be &#39;s&#39; for string value and &#39;i&#39; for int value,
                  example: --modparam=corex:alias_subdomains:s:kamailio.org
    -M nr        Size of private memory allocated, in Megabytes
    -n processes Number of child processes to fork per interface
                  (default: 8)
    -N           Number of tcp child processes (default: equal to `-n&#39;)
    -O nr        Script optimization level (debugging option)
    -P file      Create a pid file
    -Q           Number of sctp child processes (default: equal to `-n&#39;)
    -r           Use dns to check if is necessary to add a &amp;quot;received=&amp;quot;
                  field to a via
    -R           Same as `-r` but use reverse dns;
                  (to use both use `-rR`)
    --server-id=num set the value for server_id
    --subst=exp set a subst preprocessor directive
    --substdef=exp set a substdef preprocessor directive
    --substdefs=exp set a substdefs preprocessor directive
    -S           disable sctp
    -t dir       Chroot to &amp;quot;dir&amp;quot;
    -T           Disable tcp
    -u uid       Change uid (user id)
    -v           Version number
    --version    Long option for `-v`
    -V           Alternative for `-v`
    -x name      Specify internal manager for shared memory (shm)
                  - can be: fm, qm or tlsf
    -X name      Specify internal manager for private memory (pkg)
                  - if omitted, the one for shm is used
    -Y dir       Runtime dir path
    -w dir       Change the working directory to &amp;quot;dir&amp;quot; (default: &amp;quot;/&amp;quot;)
    -W type      poll method (depending on support in OS, it can be: poll,
                  epoll_lt, epoll_et, sigio_rt, select, kqueue, /dev/poll)
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    <item>
      <title>1.19 日志引擎</title>
      <link>https://wdd.js.org/zh/kamailio/56/log-engine/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/log-engine/</guid>
      <description>&lt;h1 id=&#34;log-engine-cli-parameter&#34;&gt;Log Engine CLI Parameter&lt;/h1&gt;
&lt;p&gt;The &lt;strong&gt;&amp;ndash;log-engine&lt;/strong&gt; parameter allows to specify what logging engine to
be used, which is practically about the format of the log messages. If
not set at all, then Kamailio does the classic style of line-based plain
text log messages.&lt;/p&gt;
&lt;p&gt;The value of this parameter can be &lt;strong&gt;&amp;ndash;log-engine=name&lt;/strong&gt; or
&lt;strong&gt;&amp;ndash;log-engine=name:data&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The name of the log engine can be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;json&lt;/strong&gt; - write logs in structured JSON format
&lt;ul&gt;
&lt;li&gt;the &lt;strong&gt;data&lt;/strong&gt; for &lt;strong&gt;json&lt;/strong&gt; log engine can be a set of character
flags:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;a&lt;/strong&gt; - add log prefix as a special field&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A&lt;/strong&gt; - do not add log prefix&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;c&lt;/strong&gt; - add Call-ID (when available) as a dedicated JSON
attribute&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;j&lt;/strong&gt; - the log prefix and message fields are printed in
JSON structure format, detecting if they are enclosed in
between &lt;strong&gt;{ }&lt;/strong&gt; or adding them as a &lt;strong&gt;text&lt;/strong&gt; field&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;M&lt;/strong&gt; - strip EOL (&amp;rsquo;\n&amp;rsquo;) from the value of the log message
field&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;N&lt;/strong&gt; - do not add EOL at the end of JSON document&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;p&lt;/strong&gt; - the log prefix is printed as it is in the root json
document, it has to start with comma (&lt;strong&gt;,&lt;/strong&gt;) and be a valid
set of json fields&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;U&lt;/strong&gt; - CEE (Common Event Expression) schema format -
&lt;a href=&#34;https://cee.mitre.org/language/1.0-beta1/core-profile.html&#34;&gt;https://cee.mitre.org/language/1.0-beta1/core-profile.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example of JSON logs when running Kamailio with
&amp;ldquo;&lt;strong&gt;&amp;ndash;log-engine=json:M&lt;/strong&gt;&amp;rdquo; :&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.2 通用元素 - 注释、标识符、变量、值、表达式</title>
      <link>https://wdd.js.org/zh/kamailio/56/generic-elements/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/generic-elements/</guid>
      <description>&lt;h1 id=&#34;1-comments&#34;&gt;1. Comments&lt;/h1&gt;
&lt;p&gt;Line comments start with &lt;strong&gt;#&lt;/strong&gt; (hash/pound character - like in shell) or
&lt;strong&gt;/ /&lt;/strong&gt; (double forward slash - like in C++/Java).&lt;/p&gt;
&lt;p&gt;Block comments start with /* (forward slash and asterisk) and are ended
by */ (sterisk and forward slash) (like in C, C++, Java).&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  # this is a line comment

  // this is another line comment

  /* this
     is
     a
     block
     comment */
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Important: be aware of preprocessor directives that start with &lt;strong&gt;#!&lt;/strong&gt;
(hash/pound and exclamation) - those are no longer line comments.&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.3 预处理指令 - 文件导入、宏定义、环境变量读取</title>
      <link>https://wdd.js.org/zh/kamailio/56/pre-processor/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/pre-processor/</guid>
      <description>&lt;p&gt;预处理指令主要的目的是方便脚本维护，方便脚本在不同环境下运行。
预处理之后，脚本才会开始解析。&lt;/p&gt;
&lt;h1 id=&#34;1-include_file&#34;&gt;1. include_file&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;   include_file &amp;quot;path_to_file&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Include the content of the file in config before parsing. path_to_file
must be a static string. Including file operation is done at startup. If
you change the content of included file, you have to restart the SIP
server to become effective.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;路径必须是静态，修改脚本要重启&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The path_to_file can be relative or absolute. If it is not absolute
path, first attempt is to locate it relative to current directory, and
if fails, relative to directory of the file that includes it. There is
no restriction where include can be used or what can contain - any part
of config file is ok. There is a limit of maximum 10 includes in depth,
otherwise you can use as many includes as you want. Reporting of the cfg
file syntax errors prints now the file name for easier troubleshooting.&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.4 关键词</title>
      <link>https://wdd.js.org/zh/kamailio/56/core-keywords/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/core-keywords/</guid>
      <description>&lt;p&gt;Keywords specific to SIP messages which can be used mainly in &lt;code&gt;if&lt;/code&gt;
expressions.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;核心关键词主要用在if语句里，如果用在xlog里打印，那么就打印的是字符串了呀&lt;/p&gt;&lt;/blockquote&gt;
&lt;h1 id=&#34;1-af&#34;&gt;1. af&lt;/h1&gt;
&lt;p&gt;The address family of the received SIP message. It is INET if the
message was received over IPv4 or INET6 if the message was received over
IPv6.&lt;/p&gt;
&lt;p&gt;Exampe of usage:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (af&lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt;INET6) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Message received over IPv6 link&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;2-dst_ip&#34;&gt;2. dst_ip&lt;/h1&gt;
&lt;p&gt;The IP of the local interface where the SIP message was received. When
the proxy listens on many network interfaces, makes possible to detect
which was the one that received the packet.&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.5 核心值</title>
      <link>https://wdd.js.org/zh/kamailio/56/core-values/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/core-values/</guid>
      <description>&lt;p&gt;Values that can be used in &lt;code&gt;&#39;if&lt;/code&gt;&amp;rsquo; expressions to check against Core
Keywords&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;主要还是用在if语句里做比较&lt;/p&gt;&lt;/blockquote&gt;
&lt;h1 id=&#34;1-inet&#34;&gt;1. INET&lt;/h1&gt;
&lt;p&gt;This keyword can be used to test whether the SIP packet was received
over an IPv4 connection.&lt;/p&gt;
&lt;p&gt;Example of usage:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (af&lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt;INET) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;the SIP message was received over IPv4&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;2-inet6&#34;&gt;2. INET6&lt;/h1&gt;
&lt;p&gt;This keyword can be used to test whether the SIP packet was received
over an IPv6 connection.&lt;/p&gt;
&lt;p&gt;Example of usage:&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.6 核心参数</title>
      <link>https://wdd.js.org/zh/kamailio/56/core-params/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/core-params/</guid>
      <description>&lt;p&gt;kamailio和核心参数有106个，控制了kamailio的运行方式。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#1-advertised_address&#34;&gt;1. advertised_address&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#2-advertised_port&#34;&gt;2. advertised_port&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#3-alias-%ef%b8%8f&#34;&gt;3. alias ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#4-async_workers&#34;&gt;4. async_workers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#5-async_nonblock&#34;&gt;5. async_nonblock&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#6-async_usleep&#34;&gt;6. async_usleep&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#7-async_workers_group&#34;&gt;7. async_workers_group&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#8-auto_aliases&#34;&gt;8. auto_aliases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#9-auto_bind_ipv6&#34;&gt;9. auto_bind_ipv6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#10-bind_ipv6_link_local&#34;&gt;10. bind_ipv6_link_local&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#11-check_via-%ef%b8%8f&#34;&gt;11. check_via ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#12-children&#34;&gt;12. children&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#13-chroot&#34;&gt;13. chroot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#14-corelog&#34;&gt;14. corelog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#15-debug-%ef%b8%8f&#34;&gt;15. debug ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#16-description&#34;&gt;16. description&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#17-disable_core_dump&#34;&gt;17. disable_core_dump&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#18-disable_tls&#34;&gt;18. disable_tls&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#19-enable_tls&#34;&gt;19. enable_tls&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#20-exit_timeout&#34;&gt;20. exit_timeout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#21-flags&#34;&gt;21. flags&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#22-force_rport-%ef%b8%8f&#34;&gt;22. force_rport ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#23-fork&#34;&gt;23. fork&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#24-fork_delay&#34;&gt;24. fork_delay&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#25-group&#34;&gt;25. group&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#26-http_reply_parse&#34;&gt;26. http_reply_parse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#27-ip_free_bind&#34;&gt;27. ip_free_bind&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#28-ipv6_hex_style&#34;&gt;28. ipv6_hex_style&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#29-kemionsend_route_callback&#34;&gt;29. kemi.onsend_route_callback&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#30-kemireceived_route_callback&#34;&gt;30. kemi.received_route_callback&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#31-kemireply_route_callback&#34;&gt;31. kemi.reply_route_callback&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#32-kemipre_routing_callback&#34;&gt;32. kemi.pre_routing_callback&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#33-latency_cfg_log-%ef%b8%8f&#34;&gt;33. latency_cfg_log ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#34-latency_limit_action-%ef%b8%8f&#34;&gt;34. latency_limit_action ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#35-latency_limit_db-%ef%b8%8f&#34;&gt;35. latency_limit_db ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#36-latency_log-%ef%b8%8f&#34;&gt;36. latency_log ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#37-listen-%ef%b8%8f&#34;&gt;37. listen ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#38-loadmodule&#34;&gt;38. loadmodule&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#39-loadmodulex&#34;&gt;39. loadmodulex&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#40-loadpath&#34;&gt;40. loadpath&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#41-local_rport-%ef%b8%8f&#34;&gt;41. local_rport ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#42-log_engine_data&#34;&gt;42. log_engine_data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#43-log_engine_type&#34;&gt;43. log_engine_type&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#44-log_facility-%ef%b8%8f&#34;&gt;44. log_facility ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#45-log_name-%ef%b8%8f&#34;&gt;45. log_name ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#46-log_prefix-%ef%b8%8f&#34;&gt;46. log_prefix ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#47-log_prefix_mode-%ef%b8%8f&#34;&gt;47. log_prefix_mode ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#48-log_stderror&#34;&gt;48. log_stderror&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#49-cfgengine&#34;&gt;49. cfgengine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#50-maxbuffer-%ef%b8%8f&#34;&gt;50. maxbuffer ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#51-max_branches&#34;&gt;51. max_branches&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#52-max_recursive_level&#34;&gt;52. max_recursive_level&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#53-max_while_loops-%ef%b8%8f&#34;&gt;53. max_while_loops ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#54-mcast&#34;&gt;54. mcast&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#55-mcast_loopback&#34;&gt;55. mcast_loopback&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#56-mcast_ttl&#34;&gt;56. mcast_ttl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#57-memdbg&#34;&gt;57. memdbg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#58-memlog-%ef%b8%8f&#34;&gt;58. memlog ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#59-mem_join&#34;&gt;59. mem_join&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#60-mem_safety&#34;&gt;60. mem_safety&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#61-mem_status_mode&#34;&gt;61. mem_status_mode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#62-mem_summary&#34;&gt;62. mem_summary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#63-mhomed&#34;&gt;63. mhomed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#64-mlock_pages&#34;&gt;64. mlock_pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#65-modinit_delay&#34;&gt;65. modinit_delay&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#66-modparam&#34;&gt;66. modparam&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#67-modparamx&#34;&gt;67. modparamx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#68-onsend_route_reply&#34;&gt;68. onsend_route_reply&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#69-open_files_limit&#34;&gt;69. open_files_limit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#70-phone2tel&#34;&gt;70. phone2tel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#71-pmtu_discovery&#34;&gt;71. pmtu_discovery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#72-port&#34;&gt;72. port&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#73-pv_buffer_size&#34;&gt;73. pv_buffer_size&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#74-pv_buffer_slots&#34;&gt;74. pv_buffer_slots&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#75-pv_cache_limit&#34;&gt;75. pv_cache_limit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#76-pv_cache_action&#34;&gt;76. pv_cache_action&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#77-rundir&#34;&gt;77. rundir&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#78-received_route_mode&#34;&gt;78. received_route_mode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#79-reply_to_via&#34;&gt;79. reply_to_via&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#80-route_locks_size&#34;&gt;80. route_locks_size&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#81-server_id&#34;&gt;81. server_id&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#82-server_header-%ef%b8%8f&#34;&gt;82. server_header ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#83-server_signature-%ef%b8%8f&#34;&gt;83. server_signature ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#84-shm_force_alloc&#34;&gt;84. shm_force_alloc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#85-shm_mem_size&#34;&gt;85. shm_mem_size&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#86-sip_parser_log&#34;&gt;86. sip_parser_log&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#87-sip_parser_mode-%ef%b8%8f&#34;&gt;87. sip_parser_mode ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#88-sip_warning-noisy-feedback&#34;&gt;88. sip_warning (noisy feedback)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#89-socket_workers&#34;&gt;89. socket_workers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#90-sql_buffer_size-%ef%b8%8f&#34;&gt;90. sql_buffer_size ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#91-statistics-%ef%b8%8f&#34;&gt;91. statistics ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#92-stats_name_separator&#34;&gt;92. stats_name_separator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#93-tos&#34;&gt;93. tos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#94-udp_mtu-%ef%b8%8f&#34;&gt;94. udp_mtu ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#95-udp_mtu_try_proto&#34;&gt;95. udp_mtu_try_proto&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#96-uri_host_extra_chars&#34;&gt;96. uri_host_extra_chars&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#97-user-%ef%b8%8f&#34;&gt;97. user ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#98-user_agent_header-%ef%b8%8f&#34;&gt;98. user_agent_header ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#99-verbose_startup-%ef%b8%8f&#34;&gt;99. verbose_startup ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#100-version_table-%ef%b8%8f&#34;&gt;100. version_table ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#101-wait_worker1_mode&#34;&gt;101. wait_worker1_mode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#102-wait_worker1_time&#34;&gt;102. wait_worker1_time&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#103-wait_worker1_usleep&#34;&gt;103. wait_worker1_usleep&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#104-workdir-%ef%b8%8f&#34;&gt;104. workdir ⭐️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#105-xavp_via_params&#34;&gt;105. xavp_via_params&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wdd.js.org/zh/kamailio/56/core-params/#106-xavp_via_fields&#34;&gt;106. xavp_via_fields&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;1-advertised_address&#34;&gt;1. advertised_address&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;用处不大，将会废弃&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.7 DNS 参数</title>
      <link>https://wdd.js.org/zh/kamailio/56/dns-params/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/dns-params/</guid>
      <description>&lt;p&gt;Note: See also file doc/tutorials/dns.txt for details about Kamailio&amp;rsquo;s
DNS client.&lt;/p&gt;
&lt;p&gt;Kamailio has an internal DNS resolver with caching capabilities. If this
caching resolver is activated (default setting) then the system&amp;rsquo;s stub
resolver won&amp;rsquo;t be used. Thus, also local name resolution configuration
like /etc/hosts entries will not be used. If the DNS cache is
deactivated (use_dns_cache=no), then system&amp;rsquo;s resolver will be used. The
DNS failover functionality in the tm module references directly records
in the DNS cache (which saves a lot of memory) and hence DNS based
failover only works if the internal DNS cache is enabled.&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.8 TCP参数</title>
      <link>https://wdd.js.org/zh/kamailio/56/tcp-params/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/tcp-params/</guid>
      <description>&lt;p&gt;The following parameters allows to tweak the TCP behaviour.&lt;/p&gt;
&lt;h1 id=&#34;1-disable_tcp&#34;&gt;1. disable_tcp&lt;/h1&gt;
&lt;p&gt;Global parameter to disable TCP support in the SIP server. Default value
is &amp;rsquo;no&#39;.&lt;/p&gt;
&lt;p&gt;Example of usage:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  disable_tcp=yes
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;2-tcp_accept_aliases&#34;&gt;2. tcp_accept_aliases&lt;/h1&gt;
&lt;p&gt;If a message received over a tcp connection has &amp;ldquo;alias&amp;rdquo; in its via a new
tcp alias port will be created for the connection the message came from
(the alias port will be set to the via one).&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.9 TLS参数</title>
      <link>https://wdd.js.org/zh/kamailio/56/tls-params/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://wdd.js.org/zh/kamailio/56/tls-params/</guid>
      <description>&lt;p&gt;Most of TLS layer attributes can be configured via TLS module
parameters.&lt;/p&gt;
&lt;h1 id=&#34;1-tls_port_no&#34;&gt;1. tls_port_no&lt;/h1&gt;
&lt;p&gt;The port the SIP server listens to for TLS connections.&lt;/p&gt;
&lt;p&gt;Default value is 5061.&lt;/p&gt;
&lt;p&gt;Example of usage:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  tls_port_no=6061
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;2-tls_max_connections&#34;&gt;2. tls_max_connections&lt;/h1&gt;
&lt;p&gt;Maximum number of TLS connections (if the number is exceeded no new TLS
connections will be accepted). It cannot exceed tcp_max_connections.&lt;/p&gt;
&lt;p&gt;Default value is 2048.&lt;/p&gt;
&lt;p&gt;Example of usage:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  tls_max_connections=4096
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
  </channel>
</rss>
