随手记录一下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源码学习相关推荐

  1. Shiro源码学习之二

    接上一篇 Shiro源码学习之一 3.subject.login 进入login public void login(AuthenticationToken token) throws Authent ...

  2. Shiro源码学习之一

    一.最基本的使用 1.Maven依赖 <dependency><groupId>org.apache.shiro</groupId><artifactId&g ...

  3. mutations vuex 调用_Vuex源码学习(六)action和mutation如何被调用的(前置准备篇)...

    前言 Vuex源码系列不知不觉已经到了第六篇.前置的五篇分别如下: 长篇连载:Vuex源码学习(一)功能梳理 长篇连载:Vuex源码学习(二)脉络梳理 作为一个Web前端,你知道Vuex的instal ...

  4. vue实例没有挂载到html上,vue 源码学习 - 实例挂载

    前言 在学习vue源码之前需要先了解源码目录设计(了解各个模块的功能)丶Flow语法. src ├── compiler # 把模板解析成 ast 语法树,ast 语法树优化,代码生成等功能. ├── ...

  5. 2021-03-19Tomcat源码学习--WebAppClassLoader类加载机制

    Tomcat源码学习--WebAppClassLoader类加载机制 在WebappClassLoaderBase中重写了ClassLoader的loadClass方法,在这个实现方法中我们可以一窥t ...

  6. jQuery源码学习之Callbacks

    jQuery源码学习之Callbacks jQuery的ajax.deferred通过回调实现异步,其实现核心是Callbacks. 使用方法 使用首先要先新建一个实例对象.创建时可以传入参数flag ...

  7. JDK源码学习笔记——Integer

    一.类定义 public final class Integer extends Number implements Comparable<Integer> 二.属性 private fi ...

  8. DotText源码学习——ASP.NET的工作机制

    --本文是<项目驱动学习--DotText源码学习>系列的第一篇文章,在这之后会持续发表相关的文章. 概论 在阅读DotText源码之前,让我们首先了解一下ASP.NET的工作机制,可以使 ...

  9. Vuex源码学习(五)加工后的module

    没有看过moduleCollection那可不行!Vuex源码学习(四)module与moduleCollection 感谢提出代码块和截图建议的小伙伴 代码块和截图的区别: 代码块部分希望大家按照我 ...

  10. 我的angularjs源码学习之旅2——依赖注入

    依赖注入起源于实现控制反转的典型框架Spring框架,用来削减计算机程序的耦合问题.简单来说,在定义方法的时候,方法所依赖的对象就被隐性的注入到该方法中,在方法中可以直接使用,而不需要在执行该函数的时 ...

最新文章

  1. seata分布式事务框架原理
  2. python官方手册笔记_Python学习手册笔记
  3. winform中treeview控件实现部分节点显示checkbox
  4. 简单 局部 整体光照模型计算机图形学,计算机图形学北大光照模型.ppt
  5. ELK篇---------elasticsearch集群安装配置
  6. 关于Git和Github
  7. MYSQL Innodb逻辑存储结构
  8. 工单发料,退料等一些物料的移动
  9. WPF Name与x:Name 使用
  10. c++整人小程序无限弹窗(附源码)
  11. 《金字塔原理》读书笔记
  12. 服务器怎么开启lldp协议,修改服务器lldp的mac地址
  13. html 视频类插件,科技常识:HTML5视频播放插件 video.js介绍
  14. 2020年IT技术的发展趋势!
  15. 实现折叠的uitableviewcell效果
  16. (译)Xposed模块开发教程
  17. flutter 使用MD5加密
  18. 是对计算机系统或其他网络设备进行,计算机信息系统是由计算机及其相关的和配套的设备、设施(含网络)构成的,按照一定的应用目标和规则对信息进行()等处理的人机系统。...
  19. 十大干货安全议题,足以展望今年网络安全趋势
  20. 用QuartusII 操作操作1位全加法器单位延时仿真

热门文章

  1. 移动机顶盒migu-jt-u1 unt400c刷机 hi3798 root
  2. android ev3 蓝牙连接,分享一下自己研究EV3蓝牙通信原理的成果 (完结)
  3. IAPP视频教程全集
  4. 5分钟学会双拼 双拼输入法 最简单的双拼入门教学 图文教程
  5. java百度云盘,看完直呼内行
  6. 自学web前端课程大纲分享,适合所有人学习
  7. 批量获取图片中的某个点的像素值
  8. MySQL闪退以及服务中没有MySQL和MySQL 服务无法启动。系统出错。发生系统错误 1067。 进程意外终止。
  9. 你真的了解“无纸化办公”了吗?
  10. js输出100以内的质数_用JS编写求出100以内的质数