当前位置: 首页 > 工具软件 > eXosip > 使用案例 >

Exosip源码学习

董高朗
2023-12-01

随手记录一下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;
        }
      }
    }
#endif
    if (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;
    else
      nict->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; */
}

 类似资料: