1.大概读完了收到上行invite到给下行发送ack的整体流程

2.通过上面的点呼流程,协议栈的消息收发、状态机处理流程已大概了解,其他的sip消息细节如注册的处理等,结合rfc3261来看更好一点
3.只看了udp消息的收发,接下来要看下tcp的处理
4.收发sip消息的超时处理这块没有看,需要看一下
5.关注一下代码中出现的通用写法
This commit is contained in:
gazall
2018-11-03 21:31:59 +08:00
parent b91eebffd5
commit 71ec43966b
14 changed files with 197 additions and 8 deletions

View File

@@ -118,6 +118,12 @@ _eXosip_call_reuse_contact (osip_message_t * invite, osip_message_t * msg)
return i;
}
//通过tid从excontext->j_calls中匹配到calldialogtransaction
//匹配规则如下:
//1.先看tid能否匹配到call的上行invite对应的事务
//2.再看tid能否匹配到call的下行invite对应的事务
//3.看tid能否匹配到call中的上行非invite消息对应的事务
//4.看tid能否匹配到call中的下行invite对应的事务
int
_eXosip_call_transaction_find (struct eXosip_t *excontext, int tid, eXosip_call_t ** jc, eXosip_dialog_t ** jd, osip_transaction_t ** tr)
{
@@ -236,6 +242,11 @@ eXosip_call_build_initial_invite (struct eXosip_t *excontext, osip_message_t **
return OSIP_SUCCESS;
}
//初始化eXosip_call_t和osip_transaction_tosip_transaction_t保存执行eXosip_call_t的指针
//将eXosip_t的指针加入到eXosip_t->j_calls链表中
//将osip_transaction_t挂载到eXosip_t->j_osip->osip_***_transaction状态机链表上
//初始化osip_event_t添加到transaction->transactionff队列中设置transaction的状态和osip_event_t的类型
//调用eXosip_wakeup激活状态机函数实际的消息发送是在状态机函数中进行的
int
eXosip_call_send_initial_invite (struct eXosip_t *excontext, osip_message_t * invite)
{
@@ -277,6 +288,8 @@ eXosip_call_send_initial_invite (struct eXosip_t *excontext, osip_message_t * in
return jc->c_id;
}
//构造ack消息did的作用是找到该ack消息所属的dialog和call
//根据dialog和call的信息来构造该ack消息
int
eXosip_call_build_ack (struct eXosip_t *excontext, int did, osip_message_t ** _ack)
{
@@ -352,6 +365,14 @@ eXosip_call_build_ack (struct eXosip_t *excontext, int did, osip_message_t ** _a
return OSIP_SUCCESS;
}
//发送ack消息
//目的host/port填充规则如下:
//1.先看:要发送的ack消息存在route头域,且route头域存在"lr"
//则使用route的host/port填充目的host/port
//2.上述不成立,再看:要发送的ack消息的request line存在maddr
//用maddr填充host用request line的port填充port
//3.上述都不成立,使用request line的host/port填充目的host/port
int
eXosip_call_send_ack (struct eXosip_t *excontext, int did, osip_message_t * ack)
{
@@ -672,6 +693,8 @@ eXosip_call_build_notify (struct eXosip_t *excontext, int did, int subscription_
#endif
//根据tid匹配已有的事务
//根据已有的事务信息构建answer消息
int
eXosip_call_build_answer (struct eXosip_t *excontext, int tid, int status, osip_message_t ** answer)
{
@@ -748,6 +771,9 @@ _eXosip_header_strcasestr(osip_message_t *message, const char *hname, const char
return header;
}
//发送180ring消息时
//1.如果参数answer为空则先构造answer再通知状态机发送该消息
//2.如果answer非空直接发送消息
int
eXosip_call_send_answer (struct eXosip_t *excontext, int tid, int status, osip_message_t * answer)
{

View File

@@ -1018,6 +1018,7 @@ eXosip_automatic_action (struct eXosip_t *excontext)
}
//更新新建的call和dialog的cid和did
void
_eXosip_update (struct eXosip_t *excontext)
{

View File

@@ -437,6 +437,8 @@ struct eXosip_counters {
char *user_agent;
eXosip_reg_t *j_reg; /* my registrations */
//j_calls主要用来收发消息时的会话和事务的匹配
eXosip_call_t *j_calls; /* my calls */ //发invite/notify或者收invite时会初始化一个eXosip_call_t放入j_calls
#ifndef MINISIZE
eXosip_subscribe_t *j_subscribes; /* my friends */
@@ -445,7 +447,7 @@ struct eXosip_counters {
#endif
osip_list_t j_transactions;
osip_t *j_osip;
osip_t *j_osip; //用来存储事务队列,供状态机函数使用
int j_stop_ua;
#ifndef OSIP_MONOTHREAD
void *j_cond;

View File

@@ -155,6 +155,8 @@ _eXosip_register_contact_is_modified(struct eXosip_t *excontext, eXosip_reg_t *j
}
}
//将消息转成字符串,再发送出去
//实际是调用eXtl_udp.tl_send_message来发送消息
int
_eXosip_snd_message (struct eXosip_t *excontext, osip_transaction_t * tr, osip_message_t * sip, char *host, int port, int out_socket)
{
@@ -467,6 +469,10 @@ _eXosip_delete_reserved (osip_transaction_t * transaction)
osip_transaction_set_reserved5 (transaction, NULL);
}
//收到1xx消息时状态机里会调用该函数进行处理
//如果是100trying消息上报给业务层一个EXOSIP_CALL_PROCEEDING事件然后退出当前函数
//如果是180ring消息构建一个eXosip_dialog_t放入eXosip_call_t->j_calls中。之后给业务层
//上报EXOSIP_CALL_RINGING事件
static void
cb_rcv1xx (int type, osip_transaction_t * tr, osip_message_t * sip)
{

View File

@@ -32,6 +32,8 @@
#include "eXosip2.h"
//根据参数jid(did)找到和该did相匹配的eXosip_call_t和eXosip_dialog_t
int
_eXosip_call_dialog_find (struct eXosip_t *excontext, int jid, eXosip_call_t ** jc, eXosip_dialog_t ** jd)
{

View File

@@ -172,6 +172,7 @@ _eXosip_build_response_default (struct eXosip_t *excontext, osip_message_t ** de
return OSIP_SUCCESS;
}
//设置response的contactrecord-route(把request的record-route拷贝到response消息上)
int
_eXosip_complete_answer_that_establish_a_dialog (struct eXosip_t *excontext, osip_message_t * response, osip_message_t * request)
{
@@ -268,6 +269,8 @@ _eXosip_complete_answer_that_establish_a_dialog (struct eXosip_t *excontext, osi
return OSIP_SUCCESS;
}
//根据jc,jd构建answer消息send = 1表示通知状态机触发发送消息。
//send设置非1表示只构建消息不发送函数
int
_eXosip_answer_invite_123456xx (struct eXosip_t *excontext, eXosip_call_t * jc, eXosip_dialog_t * jd, int code, osip_message_t ** answer, int send)
{

View File

@@ -138,6 +138,8 @@ _eXosip_process_bye (struct eXosip_t *excontext, eXosip_call_t * jc, eXosip_dial
_eXosip_wakeup (excontext);
}
//构造eXosip_event_t *je用于向业务层上报EXOSIP_CALL_ACK事件
//从该ACK消息匹配到的事务中获取orig_request/last_response赋值给je->request/response
static void
_eXosip_process_ack (struct eXosip_t *excontext, eXosip_call_t * jc, eXosip_dialog_t * jd, osip_event_t * evt)
{
@@ -1420,6 +1422,7 @@ udp_tl_learn_port_from_via (struct eXosip_t *excontext, osip_message_t * sip)
return;
}
//处理接收socket接收到的消息该函数是接收线程处理的主流程
int
_eXosip_handle_incoming_message (struct eXosip_t *excontext, char *buf, size_t length, int socket, char *host, int port, char *received_host, int *rport_port)
{

View File

@@ -716,6 +716,10 @@ osip_find_transaction (osip_t * osip, osip_event_t * evt)
}
#endif
//查找收到或发出去的消息(evt)是否和已存在的事务相匹配
//先判断evt属于osip->osip_***_transactions中的哪一个类型
//然后调用osip_transaction_find函数判断evt和对应类型的事务中的事务是否匹配
//consume = 1表示如果匹配上将evt push_back到查找到的transaction->transactionff中
osip_transaction_t *
__osip_find_transaction (osip_t * osip, osip_event_t * evt, int consume)
{
@@ -868,6 +872,12 @@ osip_create_transaction (osip_t * osip, osip_event_t * evt)
return transaction;
}
//判断evt是否和transactions中的某个事务相匹配
//判断规则如下:
//对于请求消息收到的消息和已存在的transactions中的transaction相比较
// topvia的brach、host和port字段、CSeq的Method字段都相等则认为是同一个transaction
//对于回复消息收到的消息和transactions中的transaction相比较topvia的
// branch、CSeq的Method字段都相等则认为是同一个transaction
osip_transaction_t *
osip_transaction_find (osip_list_t * transactions, osip_event_t * evt)
{

View File

@@ -71,6 +71,7 @@ osip_dialog_update_osip_cseq_as_uas (osip_dialog_t * dialog, osip_message_t * in
return OSIP_SUCCESS;
}
//更新osip_dialog_t->route_set
int
osip_dialog_update_route_set_as_uac (osip_dialog_t * dialog, osip_message_t * response)
{
@@ -125,6 +126,7 @@ osip_dialog_update_route_set_as_uac (osip_dialog_t * dialog, osip_message_t * re
return OSIP_SUCCESS;
}
osip_dialog_t->remote_tag(sip消息->to tag)
int
osip_dialog_update_tag_as_uac (osip_dialog_t * dialog, osip_message_t * response)
{
@@ -227,6 +229,10 @@ osip_dialog_match_as_uac (osip_dialog_t * dlg, osip_message_t * answer)
return OSIP_UNDEFINED_ERROR;
}
//匹配uas dialog
//匹配规则:
//1.先匹配callid
//2.再匹配remote tag
int
osip_dialog_match_as_uas (osip_dialog_t * dlg, osip_message_t * request)
{
@@ -295,6 +301,7 @@ osip_dialog_match_as_uas (osip_dialog_t * dlg, osip_message_t * request)
return OSIP_UNDEFINED_ERROR;
}
//init dialog,为dialog的各个字段赋值
static int
__osip_dialog_init (osip_dialog_t ** dialog, osip_message_t * invite, osip_message_t * response, osip_from_t * local, osip_to_t * remote, osip_message_t * remote_msg)
{
@@ -417,6 +424,7 @@ __osip_dialog_init (osip_dialog_t ** dialog, osip_message_t * invite, osip_messa
return OSIP_SUCCESS;
}
//初始化uac eXosip_dialog_t下行在收到180的时候调用该函数
int
osip_dialog_init_as_uac (osip_dialog_t ** dialog, osip_message_t * response)
{

View File

@@ -88,6 +88,8 @@ __osip_event_new (type_t type, int transactionid)
/* USED ONLY BY THE USER. */
/* INPUT : osip_message_t *sip | sip message for transaction. */
/* returns null on error. */
//将osip_message_t组成osip_event_t
osip_event_t *
osip_new_outgoing_sipmessage (osip_message_t * sip)
{

View File

@@ -45,6 +45,7 @@ add_gettimeofday (struct timeval *atv, int ms)
atv->tv_sec += m;
}
//如果tv1比tv2大就把tv2赋值给tv1
void
min_timercmp (struct timeval *tv1, struct timeval *tv2)
{

View File

@@ -342,6 +342,8 @@ osip_transaction_add_event (osip_transaction_t * transaction, osip_event_t * evt
return OSIP_SUCCESS;
}
//evt是从transaction->transactionff中取出来的
//根据transaction->state(事务的当前状态)和evt->type(新收到消息的类型) 来执行相应的状态机函数
int
osip_transaction_execute (osip_transaction_t * transaction, osip_event_t * evt)
{
@@ -806,6 +808,11 @@ __osip_transaction_need_timer_x_event (void *xixt, struct timeval * timer, int c
return NULL;
}
//发送回复消息
//发送的目的host/port填充方式如下:
//1.topvia maddr不空host = maddr->gvalue否则host = received->gvalue
//如果topvia received也为空host = topvia->host
//2.rport不空port = rport->gvalue否则port = topvia->port
int
__osip_transaction_snd_xxx (osip_transaction_t * ist, osip_message_t * msg)
{

View File

@@ -108,6 +108,7 @@ __osip_message_startline_to_strresp (osip_message_t * sip, char **dest)
return OSIP_SUCCESS;
}
//将消息的第一行转成字符串存入dest
static int
__osip_message_startline_to_str (osip_message_t * sip, char **dest)
{

View File

@@ -65,7 +65,7 @@
};
//收到invite构建uas dialog. 收到180/notify/200OK for subscribe, 构建uac dialog
//相比osip_dialog_teXosip_dialog_t有了自己的状态最新的收发消息是上面(d_inc_trs/d_out_trs)
//相比osip_dialog_teXosip_dialog_t有了自己的状态会保存最新的收发消息(d_inc_trs/d_out_trs)
struct eXosip_dialog_t {
int d_id;
osip_dialog_t *d_dialog; /* active dialog */
@@ -95,7 +95,7 @@
eXosip_dialog_t *c_dialogs; //上行:收到invite下行:收到180ring的时候会使用invite或180消息初始化一个
//eXosip_dialog_t放入c_dialogs。主要是初始化eXosip_dialog_t->d_dialog
//eXosip_dialog_t->d_inc_trs/d_out_trs没有赋值只分配了一块空间
osip_transaction_t *c_inc_tr; //收到invite时将invite transaction存在c_inc_tr
osip_transaction_t *c_out_tr; //发invite或notify时,会将out transaction赋给c_out_tr
int c_retry; /* avoid too many unsuccessful retry */
@@ -107,6 +107,7 @@
eXosip_call_t *parent;
};
struct eXosip_t { //全局结构体(excontext)
#ifndef MINISIZE
struct eXosip_stats statistics;
@@ -130,6 +131,8 @@
char *user_agent;
eXosip_reg_t *j_reg; /* my registrations */
//j_calls主要用来收发消息时的会话和事务的匹配
eXosip_call_t *j_calls; /* my calls */ //发invite/notify或者收invite时会初始化一个eXosip_call_t放入j_calls
#ifndef MINISIZE
eXosip_subscribe_t *j_subscribes; /* my friends */
@@ -138,7 +141,7 @@
#endif
osip_list_t j_transactions;
osip_t *j_osip;
osip_t *j_osip; //用来存储事务队列,供状态机函数使用
int j_stop_ua;
#ifndef OSIP_MONOTHREAD
void *j_cond;
@@ -225,6 +228,7 @@ int _eXosip_event_add (struct eXosip_t *excontext, eXosip_event_t * je)
//该函数做的事情:socket, bind, listen, put listen socket to select, recvfrom, handle_msg
int eXosip_listen_addr (struct eXosip_t *excontext, int transport, const char *addr, int port, int family, int secure)
//单线程的时候将接收socket放到selectsocket有消息到来触发select。执行read_message->handle_message等
//一系列函数。执行过程中会根据不同的消息通知上层业务相关的业务到来或者向transaction->transactionff
//中写数据之后osip_***_execute这些状态机函数会从transactionff中取数据执行相应的状态机处理流程。
@@ -244,6 +248,10 @@ int eXosip_execute (struct eXosip_t *excontext);
int _eXosip_read_message (struct eXosip_t *excontext, int max_message_nb, int sec_max, int usec_max)
//向管道写数据,触发管道读端,执行状态机函数。
void _eXosip_wakeup (struct eXosip_t *excontext);
/*****初始化部分的函数 end*********/
//更新新建call和dialog的cid和did
void _eXosip_update (struct eXosip_t *excontext);
@@ -253,8 +261,117 @@ int _eXosip_build_response_default (struct eXosip_t *excontext, osip_message_t *
//设置response的contact, record-route(把request的record-route拷贝到response消息上)
int _eXosip_complete_answer_that_establish_a_dialog (struct eXosip_t *excontext, osip_message_t * response, osip_message_t * request);
//业务线程等待协议栈上报eXosip_event_t
eXosip_event_t *eXosip_event_wait (struct eXosip_t * excontext, int tv_s, int tv_ms)
//匹配uas dialog
//匹配规则:
//1.先匹配callid
//2.再匹配remote tag
int osip_dialog_match_as_uas (osip_dialog_t * dlg, osip_message_t * request)
//如果tv1比tv2大就把tv2赋值给tv1
void min_timercmp (struct timeval *tv1, struct timeval *tv2)
//将osip_message_t组成osip_event_t
osip_event_t *osip_new_outgoing_sipmessage (osip_message_t * sip);
//发送回复消息
//发送的目的host/port填充方式如下:
//1.topvia maddr不空host = maddr->gvalue否则host = received->gvalue
//如果topvia received也为空host = topvia->host
//2.rport不空port = rport->gvalue否则port = topvia->port
int __osip_transaction_snd_xxx (osip_transaction_t * ist, osip_message_t * msg)
//将消息转成字符串,再发送出去
//实际是调用eXtl_udp.tl_send_message来发送消息
int _eXosip_snd_message (struct eXosip_t *excontext, osip_transaction_t * tr, osip_message_t * sip, char *host, int port, int out_socket)
//evt是从transaction->transactionff中取出来的
//根据transaction->state(事务的当前状态)和evt->type(新收到消息的类型) 来执行相应的状态机函数
int osip_transaction_execute (osip_transaction_t * transaction, osip_event_t * evt)
//初始化eXosip_call_t和osip_transaction_tosip_transaction_t保存执行eXosip_call_t的指针
//将eXosip_t的指针加入到eXosip_t->j_calls链表中
//将osip_transaction_t挂载到eXosip_t->j_osip->osip_***_transaction状态机链表上
//初始化osip_event_t添加到transaction->transactionff队列中设置transaction的状态和osip_event_t的类型
//调用eXosip_wakeup激活状态机函数实际的消息发送是在状态机函数中进行的
int eXosip_call_send_initial_invite (struct eXosip_t *excontext, osip_message_t * invite)
//查找收到或发出去的消息(evt)是否和已存在的事务相匹配
//先判断evt属于osip->osip_***_transactions中的哪一个类型
//然后调用osip_transaction_find函数判断evt和对应类型的事务中的事务是否匹配
//consume = 1表示如果匹配上将evt push_back到查找到的transaction->transactionff中
osip_transaction_t *__osip_find_transaction (osip_t * osip, osip_event_t * evt, int consume)
//判断evt是否和transactions中的某个事务相匹配
//判断规则如下:
//对于请求消息收到的消息和已存在的transactions中的transaction相比较
// topvia的brach、host和port字段、CSeq的Method字段都相等则认为是同一个transaction
//对于回复消息收到的消息和transactions中的transaction相比较topvia的
// branch、CSeq的Method字段都相等则认为是同一个transaction
osip_transaction_t *osip_transaction_find (osip_list_t * transactions, osip_event_t * evt)
//收到1xx消息时状态机里会调用该函数进行处理
//如果是100trying消息上报给业务层一个EXOSIP_CALL_PROCEEDING事件然后退出当前函数
//如果是180ring消息构建一个eXosip_dialog_t放入eXosip_call_t->j_calls中。之后给业务层
//上报EXOSIP_CALL_RINGING事件
static void cb_rcv1xx (int type, osip_transaction_t * tr, osip_message_t * sip)
//更新新建的call和dialog的cid和did
void _eXosip_update (struct eXosip_t *excontext)
//通过tid从excontext->j_calls中匹配到calldialogtransaction
//匹配规则如下:
//1.先看tid能否匹配到call的上行invite对应的事务
//2.再看tid能否匹配到call的下行invite对应的事务
//3.看tid能否匹配到call中的上行非invite消息对应的事务
//4.看tid能否匹配到call中的下行invite对应的事务
int _eXosip_call_transaction_find (struct eXosip_t *excontext, int tid, eXosip_call_t ** jc, eXosip_dialog_t ** jd, osip_transaction_t ** tr)
//设置response的contactrecord-route(把request的record-route拷贝到response消息上)
int _eXosip_complete_answer_that_establish_a_dialog (struct eXosip_t *excontext, osip_message_t * response, osip_message_t * request)
//根据tid匹配已有的事务
//根据已有的事务信息构建answer消息
int eXosip_call_build_answer (struct eXosip_t *excontext, int tid, int status, osip_message_t **answer)
//发送180ring消息时
//1.如果参数answer为空则先构造answer再通知状态机发送该消息
//2.如果answer非空直接发送消息
int
eXosip_call_send_answer (struct eXosip_t *excontext, int tid, int status, osip_message_t * answer)
//根据jc,jd构建answer消息send = 1表示通知状态机触发发送消息。
//send设置非1表示只构建消息不发送函数
int _eXosip_answer_invite_123456xx (struct eXosip_t *excontext, eXosip_call_t * jc, eXosip_dialog_t * jd, int code, osip_message_t ** answer, int send)
接上面的函数说明:业务层调用时只需要调用eXosip_call_send_answer参数answer填NULL即可检测到answer为NULL时该函数会调用_eXosip_answer_invite_123456xx来构建answer。
业务层不必显示调用eXosip_call_build_answer构造消息再调用eXosip_call_send_answer发送消息。
//处理接收socket接收到的消息该函数是接收线程处理的主流程
int _eXosip_handle_incoming_message (struct eXosip_t *excontext, char *buf, size_t length, int socket, char *host, int port, char *received_host, int *rport_port)
//构造eXosip_event_t *je用于向业务层上报EXOSIP_CALL_ACK事件
//从该ACK消息匹配到的事务中获取orig_request/last_response赋值给je->request/response
static void _eXosip_process_ack (struct eXosip_t *excontext, eXosip_call_t * jc, eXosip_dialog_t * jd, osip_event_t * evt)
//根据参数jid(did)找到和该did相匹配的eXosip_call_t和eXosip_dialog_t
int _eXosip_call_dialog_find (struct eXosip_t *excontext, int jid, eXosip_call_t ** jc, eXosip_dialog_t ** jd)
//构造ack消息did的作用是找到该ack消息所属的dialog和call
//根据dialog和call的信息来构造该ack消息
int eXosip_call_build_ack (struct eXosip_t *excontext, int did, osip_message_t ** _ack)
//发送ack消息
//目的host/port填充规则如下:
//1.先看:要发送的ack消息存在route头域,且route头域存在"lr"
//则使用route的host/port填充目的host/port
//2.上述不成立,再看:要发送的ack消息的request line存在maddr
//用maddr填充host用request line的port填充port
//3.上述都不成立,使用request line的host/port填充目的host/port
int eXosip_call_send_ack (struct eXosip_t *excontext, int did, osip_message_t * ack)
//init dialog,为dialog的各个字段赋值
static int __osip_dialog_init (osip_dialog_t ** dialog, osip_message_t * invite, osip_message_t * response, osip_from_t * local, osip_to_t * remote, osip_message_t * remote_msg)
//初始化uac eXosip_dialog_t下行在收到180的时候调用该函数
int osip_dialog_init_as_uac (osip_dialog_t ** dialog, osip_message_t * response)
//触发
_eXosip_wakeup (struct eXosip_t *excontext);