Exosip源码学习
随手记录一下exosip的学习过程:
1. nist 非invite事件服务端处理,nict 非invite事件客户端处理,ist invite服务器处理,ict invite客户端处理。
2. 状态机处理链表,每种状态对应一个处理方式,当事务处于trying状态时,根据超时类型处理,这种链表结构实属优秀了。。
typedef struct _transition_t transition_t;
struct _transition_t {
state_t state;
type_t type;
void (*method) (void *, void *);
struct _transition_t *next;
struct _transition_t *parent;
};
transition_t nict_transition[12] = {
{
NICT_PRE_TRYING,
SND_REQUEST,
(void (*)(void *, void *)) &nict_snd_request,
&nict_transition[1], NULL}
,
{
NICT_TRYING,
TIMEOUT_F,
(void (*)(void *, void *)) &osip_nict_timeout_f_event,
&nict_transition[2], NULL}
,
{
NICT_TRYING,
TIMEOUT_E,
(void (*)(void *, void *)) &osip_nict_timeout_e_event,
&nict_transition[3], NULL}
,
{
NICT_TRYING,
RCV_STATUS_1XX,
(void (*)(void *, void *)) &nict_rcv_1xx,
&nict_transition[4], NULL}
,
{
NICT_TRYING,
RCV_STATUS_2XX,
(void (*)(void *, void *)) &nict_rcv_23456xx,
&nict_transition[5], NULL}
,
{
NICT_TRYING,
RCV_STATUS_3456XX,
(void (*)(void *, void *)) &nict_rcv_23456xx,
&nict_transition[6], NULL}
,
{
NICT_PROCEEDING,
TIMEOUT_F,
(void (*)(void *, void *)) &osip_nict_timeout_f_event,
&nict_transition[7], NULL}
,
{
NICT_PROCEEDING,
TIMEOUT_E,
(void (*)(void *, void *)) &osip_nict_timeout_e_event,
&nict_transition[8], NULL}
,
{
NICT_PROCEEDING,
RCV_STATUS_1XX,
(void (*)(void *, void *)) &nict_rcv_1xx,
&nict_transition[9], NULL}
,
{
NICT_PROCEEDING,
RCV_STATUS_2XX,
(void (*)(void *, void *)) &nict_rcv_23456xx,
&nict_transition[10], NULL}
,
{
NICT_PROCEEDING,
RCV_STATUS_3456XX,
(void (*)(void *, void *)) &nict_rcv_23456xx,
&nict_transition[11], NULL}
,
{
NICT_COMPLETED,
TIMEOUT_K,
(void (*)(void *, void *)) &osip_nict_timeout_k_event,
NULL, NULL}
};
exosip线程执行事件
eXosip_execute (struct eXosip_t *excontext)
{
...
osip_nist_execute (excontext->j_osip);
osip_nict_execute (excontext->j_osip);
osip_ist_execute (excontext->j_osip);
osip_ict_execute (excontext->j_osip);
...
}
int osip_nict_execute (osip_t * osip)
{
for (index = 0; index < len; ++index) {
transaction = (osip_transaction_t *) array[index];
more_event = 1;
do {
se = (osip_event_t *) osip_fifo_tryget (transaction->transactionff);
if (se == NULL) /* no more event for this transaction */
more_event = 0;
else
osip_transaction_execute (transaction, se);
}
while (more_event == 1);
}
}
NICT_PRE_TRYING状态调用nict_snd_request 直接发送并更新状态NICT_TRYING,并设置启动的定时器timer_e_start和timer_e_length,由于没有使用tcp等可靠协议,所以timer_e_start没有修改,使用的默认值 500ms;
int
__osip_nict_init (osip_nict_t ** nict, osip_t * osip, osip_message_t * request)
{
//if (osip_strcasecmp (proto, "TCP") != 0 && osip_strcasecmp (proto, "TLS") != 0 && osip_strcasecmp (proto, "SCTP") != 0) {(*nict)->timer_e_length = DEFAULT_T1;(*nict)->timer_k_length = DEFAULT_T4;(*nict)->timer_e_start.tv_sec = -1;(*nict)->timer_k_start.tv_sec = -1; /* not started */}else { /* reliable protocol is used: */(*nict)->timer_e_length = DEFAULT_T1;(*nict)->timer_k_length = 0; /* MUST do the transition immediatly */(*nict)->timer_e_start.tv_sec = -1;(*nict)->timer_k_start.tv_sec = -1; /* not started */}}
}void
nict_snd_request (osip_transaction_t * nict, osip_event_t * evt)
{int i;osip_t *osip = (osip_t *) nict->config;/* Here we have ict->orig_request == NULL */nict->orig_request = evt->sip;i = osip->cb_send_message (nict, evt->sip, nict->nict_context->destination, nict->nict_context->port, nict->out_socket);#ifndef USE_BLOCKINGSOCKET/*stop timer E in reliable transport - non blocking socket: the message was just sent*/{osip_via_t *via;char *proto;int k;k = osip_message_get_via (nict->orig_request, 0, &via); /* get top via */if (k < 0) {nict_handle_transport_error (nict, -1);return;}proto = via_get_protocol (via);if (proto == NULL) {nict_handle_transport_error (nict, -1);return;}if (i == 0) { /* but message was really sent */if (osip_strcasecmp (proto, "TCP") != 0 && osip_strcasecmp (proto, "TLS") != 0 && osip_strcasecmp (proto, "SCTP") != 0) {}else { /* reliable protocol is used: */nict->nict_context->timer_e_length = -1; /* E is not ACTIVE */nict->nict_context->timer_e_start.tv_sec = -1;}} else {if (osip_strcasecmp (proto, "TCP") != 0 && osip_strcasecmp (proto, "TLS") != 0 && osip_strcasecmp (proto, "SCTP") != 0) {}else { /* reliable protocol is used: */nict->nict_context->timer_e_length = DEFAULT_T1_TCP_PROGRESS;}}}
#endifif (nict->nict_context->timer_e_length > 0) {osip_gettimeofday (&nict->nict_context->timer_e_start, NULL);add_gettimeofday (&nict->nict_context->timer_e_start, nict->nict_context->timer_e_length);}__osip_transaction_set_state (nict, NICT_TRYING);}else {nict_handle_transport_error (nict, i);}
}
下一次循环处理,会先调用osip_timers_nict_execute判断,如果符合状态并且超时,则会添加处理任务到transactionff队列中等待处理,
void
osip_timers_nict_execute (osip_t * osip)
{osip_transaction_t *tr;osip_list_iterator_t iterator;/* handle nict timers */tr = (osip_transaction_t *) osip_list_get_first (&osip->osip_nict_transactions, &iterator);while (osip_list_iterator_has_elem (iterator)) {osip_event_t *evt;evt = __osip_nict_need_timer_k_event (tr->nict_context, tr->state, tr->transactionid);if (evt != NULL)osip_fifo_add (tr->transactionff, evt);else {evt = __osip_nict_need_timer_f_event (tr->nict_context, tr->state, tr->transactionid);if (evt != NULL)osip_fifo_add (tr->transactionff, evt);else {evt = __osip_nict_need_timer_e_event (tr->nict_context, tr->state, tr->transactionid);if (evt != NULL)osip_fifo_add (tr->transactionff, evt);}}tr = (osip_transaction_t *) osip_list_get_next (&iterator);}
}
NICT_TRYING有多种定时器,会根据超时类型做不同处理 ,TIMEOUT_E 每隔两倍时间发一次,TIMEOUT_F直接terminate。
void
osip_nict_timeout_e_event (osip_transaction_t * nict, osip_event_t * evt)
{osip_t *osip = (osip_t *) nict->config;int i;/* reset timer */if (nict->state == NICT_TRYING) {if (nict->nict_context->timer_e_length < DEFAULT_T1)nict->nict_context->timer_e_length = nict->nict_context->timer_e_length + DEFAULT_T1_TCP_PROGRESS;elsenict->nict_context->timer_e_length = nict->nict_context->timer_e_length * 2;if (nict->nict_context->timer_e_length > DEFAULT_T2)nict->nict_context->timer_e_length = DEFAULT_T2;}else /* in PROCEEDING STATE, TIMER is always DEFAULT_T2 */nict->nict_context->timer_e_length = DEFAULT_T2;osip_gettimeofday (&nict->nict_context->timer_e_start, NULL);add_gettimeofday (&nict->nict_context->timer_e_start, nict->nict_context->timer_e_length);/* retransmit REQUEST */i = osip->cb_send_message (nict, nict->orig_request, nict->nict_context->destination, nict->nict_context->port, nict->out_socket);if (i < 0) {nict_handle_transport_error (nict, i);return;}if (i == 0) /* but message was really sent */__osip_message_callback (OSIP_NICT_REQUEST_SENT_AGAIN, nict, nict->orig_request);
}
struct osip_nict {
int timer_e_length; /**< Timer E A=T1, A=2xT1... (unreliable only) */
struct timeval timer_e_start; /**< Timer E (retransmission) */
int timer_f_length; /**< Timer F B = 64* T1 */
struct timeval timer_f_start; /**< Timer F (fire when transaction timeout) */
int timer_k_length; /**< Timer K K = T4 (else = 0) */
struct timeval timer_k_start; /**< Timer K */
char *destination; /**< IP used to send requests */
int port; /**< port of next hop */
};
发送request请求的时候,会把transaction添加到NICT对应的处理队列,并返回TID事务ID。
int eXosip_message_send_request (struct eXosip_t *excontext, osip_message_t * message)
{
osip_transaction_t *transaction;
osip_event_t *sipevent;
int i;
i = _eXosip_transaction_init (excontext, &transaction, NICT, excontext->j_osip, message);
saction_add_event (transaction, sipevent);
_eXosip_wakeup (excontext);
return transaction->transactionid; /* return TID (>0) instead of OSIP_SUCCESS; */
}
Exosip源码学习相关推荐
- Shiro源码学习之二
接上一篇 Shiro源码学习之一 3.subject.login 进入login public void login(AuthenticationToken token) throws Authent ...
- Shiro源码学习之一
一.最基本的使用 1.Maven依赖 <dependency><groupId>org.apache.shiro</groupId><artifactId&g ...
- mutations vuex 调用_Vuex源码学习(六)action和mutation如何被调用的(前置准备篇)...
前言 Vuex源码系列不知不觉已经到了第六篇.前置的五篇分别如下: 长篇连载:Vuex源码学习(一)功能梳理 长篇连载:Vuex源码学习(二)脉络梳理 作为一个Web前端,你知道Vuex的instal ...
- vue实例没有挂载到html上,vue 源码学习 - 实例挂载
前言 在学习vue源码之前需要先了解源码目录设计(了解各个模块的功能)丶Flow语法. src ├── compiler # 把模板解析成 ast 语法树,ast 语法树优化,代码生成等功能. ├── ...
- 2021-03-19Tomcat源码学习--WebAppClassLoader类加载机制
Tomcat源码学习--WebAppClassLoader类加载机制 在WebappClassLoaderBase中重写了ClassLoader的loadClass方法,在这个实现方法中我们可以一窥t ...
- jQuery源码学习之Callbacks
jQuery源码学习之Callbacks jQuery的ajax.deferred通过回调实现异步,其实现核心是Callbacks. 使用方法 使用首先要先新建一个实例对象.创建时可以传入参数flag ...
- JDK源码学习笔记——Integer
一.类定义 public final class Integer extends Number implements Comparable<Integer> 二.属性 private fi ...
- DotText源码学习——ASP.NET的工作机制
--本文是<项目驱动学习--DotText源码学习>系列的第一篇文章,在这之后会持续发表相关的文章. 概论 在阅读DotText源码之前,让我们首先了解一下ASP.NET的工作机制,可以使 ...
- Vuex源码学习(五)加工后的module
没有看过moduleCollection那可不行!Vuex源码学习(四)module与moduleCollection 感谢提出代码块和截图建议的小伙伴 代码块和截图的区别: 代码块部分希望大家按照我 ...
- 我的angularjs源码学习之旅2——依赖注入
依赖注入起源于实现控制反转的典型框架Spring框架,用来削减计算机程序的耦合问题.简单来说,在定义方法的时候,方法所依赖的对象就被隐性的注入到该方法中,在方法中可以直接使用,而不需要在执行该函数的时 ...
最新文章
- seata分布式事务框架原理
- python官方手册笔记_Python学习手册笔记
- winform中treeview控件实现部分节点显示checkbox
- 简单 局部 整体光照模型计算机图形学,计算机图形学北大光照模型.ppt
- ELK篇---------elasticsearch集群安装配置
- 关于Git和Github
- MYSQL Innodb逻辑存储结构
- 工单发料,退料等一些物料的移动
- WPF Name与x:Name 使用
- c++整人小程序无限弹窗(附源码)
- 《金字塔原理》读书笔记
- 服务器怎么开启lldp协议,修改服务器lldp的mac地址
- html 视频类插件,科技常识:HTML5视频播放插件 video.js介绍
- 2020年IT技术的发展趋势!
- 实现折叠的uitableviewcell效果
- (译)Xposed模块开发教程
- flutter 使用MD5加密
- 是对计算机系统或其他网络设备进行,计算机信息系统是由计算机及其相关的和配套的设备、设施(含网络)构成的,按照一定的应用目标和规则对信息进行()等处理的人机系统。...
- 十大干货安全议题,足以展望今年网络安全趋势
- 用QuartusII 操作操作1位全加法器单位延时仿真
热门文章
- 移动机顶盒migu-jt-u1 unt400c刷机 hi3798 root
- android ev3 蓝牙连接,分享一下自己研究EV3蓝牙通信原理的成果 (完结)
- IAPP视频教程全集
- 5分钟学会双拼 双拼输入法 最简单的双拼入门教学 图文教程
- java百度云盘,看完直呼内行
- 自学web前端课程大纲分享,适合所有人学习
- 批量获取图片中的某个点的像素值
- MySQL闪退以及服务中没有MySQL和MySQL 服务无法启动。系统出错。发生系统错误 1067。 进程意外终止。
- 你真的了解“无纸化办公”了吗?
- js输出100以内的质数_用JS编写求出100以内的质数