前言

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报文