Asterisk 1.8 sip 协议栈分析

看了一下 asterisk 1.8 ,chan_sip 更新了许多内容,下面结合asterisk 1.4 asterisk 1.6 分析一下sip协议栈。

此笔记为本人学习记录,有些地方描述其他人可能看不懂,望见谅。

 

分析路线

sipsock_read->parse_request->find_call->handle_inconming->handle_request_方法名。。。。 

 

协议栈初始化:load_module() 函数加载SIP配置信息,解析sip.conf挂载到全局变量中。

     首先初始化user,peer,register全局链表(1.6 版本中已经改为hash存储 估计性能提高不少),这三个链表分别存储用户,peer,register三个实体。

 

   接下来创建 调度器,IO管理器,这里IO即监听socket fd句柄上的IO事件,chan_sip用poll异步IO实现此功能,io_context 结构封装了此功能。

 

 创建IO调度器后注册各种app, load_module()最后调用restart_monitor()函数创建一个线程(do_monitor())监听sip 端口(5060)上的事件, 在do_monitor()函数中首先将sip socket 句柄添加到之前创建的IO管理器中,同时指定此sip socket句柄上的IO事件对应的回调函数(sipsock_read),即当监听的sip socket 句柄上有事件发生时调用 sipsocket_read函数,此函数是所有sip包的入口,负责接收监听端口(5060)上的数据包。do_monitor函数接下来,遍历全局sip channle 链表iflock ,遍历的同时 考虑 channle 的重载 (cli reload), ,挂断那些不符合规则的sip channel,比如 rtp 超时,onhold rtp 超时、释放sip channle 资源(调用sip_destroy()函数), 锁的释放,rtp,vrtp,udps 等 结构的释放。

 

 

现在回到 sipsock_read函数:

 

sipsock_read 函数调用 经典的udp socket 函数 recvfrom(1.8版本中已将这些经典函数封装) 读取网络数据包,保存到buffer中,

 

 此函数中声明sip_request 结构,此结构如下:

struct sip_request {

ptrdiff_t rlPart1;      /*!< Offset of the SIP Method Name or "SIP/2.0" protocol version */
 ptrdiff_t rlPart2;      /*!< Offset of the Request URI or Response Status */
 int len;                /*!< bytes used in data[], excluding trailing null terminator. Rarely used. */
 int headers;            /*!< # of SIP Headers */
 int method;             /*!< Method of this request */
 int lines;              /*!< Body Content */
 unsigned int sdp_start; /*!< the line number where the SDP begins */
 unsigned int sdp_count; /*!< the number of lines of SDP */
 char debug;             /*!< print extra debugging if non zero */
 char has_to_tag;        /*!< non-zero if packet has To: tag */
 char ignore;            /*!< if non-zero This is a re-transmit, ignore it */
 ptrdiff_t header[SIP_MAX_HEADERS]; /*!< Array of offsets into the request string of each SIP header*/
 ptrdiff_t line[SIP_MAX_LINES];     /*!< Array of offsets into the request string of each SDP line*/
 struct ast_str *data; 
 struct ast_str *content;
 /* XXX Do we need to unref socket.ser when the request goes away? */
 struct sip_socket socket;          /*!< The socket used for this request */
 AST_LIST_ENTRY(sip_request) next;
};

 

对于每一个udp数据都作为为是一次请求,此结构封装了sip 协议的消息头,方法,body,及此请求的socket 句柄,保存此次请求数据的data字段,此处只是将sipsock_read读到的数据包保存到sip_request 结构的 data字段,数据包的处理留给 parse_request()函数处理。

 

sipsock_read函数接下来调用handle_request_do(&req, &addr); 函数处理此次请求,参数为sip_request 结构及此此数据包的来源。

handle_request_do(&req, &addr) 函数内部首先 对 pedanticsipchecking 处理,此处解释一下 pedanticsipchecking

pedanticsipchecking 为sip.conf文件的一个配置选项,表示是否开启将多个请求头放在一个请求头里的情况,我们知道sip消息由若干个消息头(from, to,contact 等)组成,每个请求头部用/r/n分隔,但是有些情况下所有sip轻轻头放在一个轻轻头部,而没有用/r/n分隔,所以当pedanticsipchecking 设置为yes时handle_request_do 会调用lws2sws函数处理此种情况,如果不显示设置pedanticsipchecking  为no,貌似1.8中默认为yes了,如果将sip

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值