前言
tl_send_message是一个函数指针,根据不同的网络传输协议,有具体的实现,目前以UDP协议为例子说明,具体实现参考:udp_tl_send_message
调用堆栈
udp_tl_send_message(eXosip_t * excontext, osip_transaction * tr, osip_message * sip, char * host, int port, int out_socket) 行 845 C
_eXosip_snd_message(eXosip_t * excontext, osip_transaction * tr, osip_message * sip, char * host, int port, int out_socket) 行 196 C
cb_snd_message(osip_transaction * tr, osip_message * sip, char * host, int port, int out_socket) 行 211 C
nict_snd_request(osip_transaction * nict, osip_event * evt) 行 119 C
fsm_callmethod(type_t type, _state_t state, osip_statemachine * statemachine, void * sipevent, void * transaction) 行 53 C
osip_transaction_execute(osip_transaction * transaction, osip_event * evt) 行 363 C
osip_nict_execute(osip * osip) 行 1206 C
eXosip_execute(eXosip_t * excontext) 行 807 C
_eXosip_thread(void * arg) 行 1099 C
剖析
_eXosip_snd_message是上层发送的调用接口,至于底层是采用TCP或者UDP进行发送,最终会调用excontext->eXtl_transport.tl_send_message进行选择
当前分析下发送目的的IP地址和端口,哪里来的
如果host为空,且消息是一个请求,读取route字段,作为目的IP和端口
如果不是一个请求,读取vias字段,作为目的IP和端口
如果host不为空,则会尝试读取vias中的received字段值,作为目的IP和端口
源码
int
_eXosip_snd_message (struct eXosip_t *excontext, osip_transaction_t * tr, osip_message_t * sip, char *host, int port, int out_socket)
{
int i;
osip_via_t *via;
if (sip->status_code == 101)
return OSIP_SUCCESS;
via = (osip_via_t *) osip_list_get (&sip->vias, 0);
if (via == NULL || via->protocol == NULL)
return -1;
if (host == NULL) {
if (MSG_IS_REQUEST (sip)) {
osip_route_t *route;
osip_message_get_route (sip, 0, &route);
if (route != NULL) {
osip_uri_param_t *lr_param = NULL;
osip_uri_uparam_get_byname (route->url, "lr", &lr_param);
if (lr_param == NULL)
route = NULL;
}
if (route != NULL) {
port = 5060;
if (route->url->port != NULL)
port = osip_atoi (route->url->port);
host = route->url->host;
}
else {
/* search for maddr parameter */
osip_uri_param_t *maddr_param = NULL;
osip_uri_uparam_get_byname (sip->req_uri, "maddr", &maddr_param);
host = NULL;
if (maddr_param != NULL && maddr_param->gvalue != NULL)
host = maddr_param->gvalue;
port = 5060;
if (sip->req_uri->port != NULL)
port = osip_atoi (sip->req_uri->port);
if (host == NULL)
host = sip->req_uri->host;
}
}
else {
osip_generic_param_t *maddr;
osip_generic_param_t *received;
osip_generic_param_t *rport;
osip_via_param_get_byname (via, "maddr", &maddr);
osip_via_param_get_byname (via, "received", &received);
osip_via_param_get_byname (via, "rport", &rport);
if (maddr != NULL && maddr->gvalue != NULL)
host = maddr->gvalue;
else if (received != NULL && received->gvalue != NULL)
host = received->gvalue;
else
host = via->host;
if (rport == NULL || rport->gvalue == NULL) {
if (via->port != NULL)
port = osip_atoi (via->port);
else
port = 5060;
}
else
port = osip_atoi (rport->gvalue);
}
}
if (excontext->cbsipCallback != NULL) {
excontext->cbsipCallback (sip, 0);
}
i = -1;
/*lbh modify:add mutex*/
osip_mutex_lock(excontext->j_sendmutexlock);
i = excontext->eXtl_transport.tl_send_message (excontext, tr, sip, host, port, out_socket);
osip_mutex_unlock(excontext->j_sendmutexlock);
if (i != 0) {
return i;
}
return OSIP_SUCCESS;
}
UDP发送函数原型
static int
udp_tl_send_message (struct eXosip_t *excontext,
osip_transaction_t * tr,
osip_message_t * sip,
char *host,
int port,
int out_socket)
发送的IP和端口参数
char *host, int port
发送代码
i = sendto (reserved->udp_socket,
message,
length,
0,
(struct sockaddr *)paddr,
len);
调整报文中route
remove preloaded route if there is no tag in the To header
{
osip_route_t *route = NULL;
osip_generic_param_t *tag = NULL;
osip_message_get_route (sip, 0, &route);
osip_to_get_tag (sip->to, &tag);
if (tag == NULL && route != NULL && route->url != NULL) {
osip_list_remove (&sip->routes, 0);
}
i = osip_message_to_str (sip, &message, &length);
if (tag == NULL && route != NULL && route->url != NULL) {
osip_list_add (&sip->routes, route, 0);
}
}
在这里只有if (1 == osip_message_get__property (sip))
才会重新构建message报文