随手记录一下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; */
}