eXosip 学习小计

1. 从利用eXosip的注册开始

    int i; 
    char identity[50]; 
    char registerer[50]; 
    char localip[128]; 
    static int flag = 0; 
    int id; 
    eXosip_guess_localip (AF_INET, localip, 128); 

    sprintf(identity,"sip:%s@%s",username,localip); 
    sprintf(registerer,"sip:%s:%s",ip_url,port); 

    //初始化  
    if( flag == 0) 
    { 
        i = eXosip_init(); 
        if (i != 0) 
        { 
            return -1; 
        } 
        TRACE("eXosip_init success/n"); 
        flag ++; 
        i = eXosip_listen_addr(IPPROTO_UDP, NULL, 5060, AF_INET, 0); 
        if (i != 0) 
        { 
            eXosip_quit(); 
            fprintf(stderr, "could not initialize transport layer/n"); 
            return -1; 
        } 
        TRACE("eXosip_listen_addr success/n"); 
    } 
    osip_message_t *reg = NULL; 

    eXosip_lock(); 
    id = eXosip_register_build_initial_register (identity,registerer, NULL, 1800, &reg); 
    printf("id = %d", id); 

    if (id < 0) 
    { 
        eXosip_unlock(); 
        fprintf (stderr, "eXosip_register_build_initial_register failed:(bad arguments?)/n"); 
        return 0; 
    } 
    eXosip_lock(); 
    i = eXosip_register_send_register(id, reg); 
    if (i != 0) 
    { 
        fprintf (stderr, "eXosip_register_send_register failed: (bad arguments?)/n"); 
        return 0;      } 
    eXosip_unlock (); 

    TRACE("eXosip_register_send_register OK/n"); 

    eXosip_event_t *je; 
    for (;;) 
    { 
        je = eXosip_event_wait (0, 50); 

        eXosip_lock(); 
        eXosip_automatic_action (); 
        eXosip_unlock(); 

        if (je == NULL) 
        { 
            continue; 
        } 

        if (je->type == EXOSIP_REGISTRATION_SUCCESS) 
        { 
            TRACE("textinfo is %s/n", je->textinfo); 
            return 1; 
            break; 
        } 
        if(je->type == EXOSIP_REGISTRATION_FAILURE) 
        { 
            //注册失败之后,再次提交授权信息, 也可放在上面  
            eXosip_add_authentication_info(username, username,password, NULL, NULL); 
        } 
        if(je->type == EXOSIP_REGISTRATION_REFRESHED) 
        { 
            TRACE("refreshed"); 
            return 0; 
        } 
    } 
    eXosip_quit();

 

eXosip_guess_localip (AF_INET, localip, 128);

这句在eXosip中的实现为

eXosip_guess_localip (int family, char *address, int size)

address在函数体外首先进行定义为一数组,分配好空间,再给形式参数传指针过去,在函数体内对实际参数address赋值。这里就是本地的ip地址。

参见eXosip_guess_localip 的实现

int
eXosip_guess_ip_for_via (int family, char *address, int size)
{
  SOCKET sock;

  SOCKADDR_STORAGE local_addr;

  int local_addr_len;

  struct addrinfo *addrf;

  address[0] = '\0';
  sock = socket (family, SOCK_DGRAM, 0);

  if (family == AF_INET)
    {
      getaddrinfo (eXosip.ipv4_for_gateway, NULL, NULL, &addrf);
  } else if (family == AF_INET6)
    {
      getaddrinfo (eXosip.ipv6_for_gateway, NULL, NULL, &addrf);
    }

  if (addrf == NULL)
    {
      closesocket (sock);
      snprintf (address, size, (family == AF_INET) ? "127.0.0.1" : "::1");
      return OSIP_NO_NETWORK;
    }

  if (WSAIoctl
      (sock, SIO_ROUTING_INTERFACE_QUERY, addrf->ai_addr, addrf->ai_addrlen,
       &local_addr, sizeof (local_addr), &local_addr_len, NULL, NULL) != 0)
    {
      closesocket (sock);
      freeaddrinfo (addrf);
      snprintf (address, size, (family == AF_INET) ? "127.0.0.1" : "::1");
      return OSIP_NO_NETWORK;
    }

  closesocket (sock);
  freeaddrinfo (addrf);

  if (getnameinfo ((const struct sockaddr *) &local_addr,
                   local_addr_len, address, size, NULL, 0, NI_NUMERICHOST))
    {
      snprintf (address, size, (family == AF_INET) ? "127.0.0.1" : "::1");
      return OSIP_NO_NETWORK;
    }

  return OSIP_SUCCESS;
}

通过debug验证和结合eXosip的code,这里得到的地址为环回地址127.0.0.1.不知道得到这个地址有什么用?

 

下一步是eXosip_init()

eXosip_init()的源code如下:

eXosip_init (void)
{
  osip_t *osip;
  int i;

  memset (&eXosip, 0, sizeof (eXosip));

  snprintf (eXosip.ipv4_for_gateway, 256, "%s", "217.12.3.11");
  snprintf (eXosip.ipv6_for_gateway, 256, "%s",
            "2001:638:500:101:2e0:81ff:fe24:37c6");
#ifndef MINISIZE
  snprintf (eXosip.event_package, 256, "%s", "dialog");
#endif

#ifdef WIN32
 
  {
    WORD wVersionRequested;
    WSADATA wsaData;

    wVersionRequested = MAKEWORD (1, 1);
    i = WSAStartup (wVersionRequested, &wsaData);
    if (i != 0)
      {
        OSIP_TRACE (osip_trace
                    (__FILE__, __LINE__, OSIP_WARNING, NULL,
                     "eXosip: Unable to initialize WINSOCK, reason: %d\n", i));
       
      }
  }
#endif

  eXosip.user_agent = osip_strdup ("eXosip/" EXOSIP_VERSION);
  if (eXosip.user_agent == NULL)
    return OSIP_NOMEM;

  eXosip.j_calls = NULL;
  eXosip.j_stop_ua = 0;
#ifdef OSIP_MT
  eXosip.j_thread = NULL;
#endif
  i = osip_list_init (&eXosip.j_transactions);
  eXosip.j_reg = NULL;

#ifdef OSIP_MT
#if !defined (_WIN32_WCE)
  eXosip.j_cond = (struct osip_cond *) osip_cond_init ();
  if (eXosip.j_cond == NULL)
    {
      osip_free (eXosip.user_agent);
      eXosip.user_agent = NULL;
      return OSIP_NOMEM;
    }
#endif

  eXosip.j_mutexlock = (struct osip_mutex *) osip_mutex_init ();
  if (eXosip.j_mutexlock == NULL)
    {
      osip_free (eXosip.user_agent);
      eXosip.user_agent = NULL;
#if !defined (_WIN32_WCE)
      osip_cond_destroy ((struct osip_cond *) eXosip.j_cond);
      eXosip.j_cond = NULL;
#endif
      return OSIP_NOMEM;
    }
#endif

  i = osip_init (&osip);
  if (i != 0)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: Cannot initialize osip!\n"));
      return i;
    }

  osip_set_application_context (osip, &eXosip);

  eXosip_set_callbacks (osip);

  eXosip.j_osip = osip;

#ifdef OSIP_MT
 
  eXosip.j_socketctl = jpipe ();
  if (eXosip.j_socketctl == NULL)
    return OSIP_UNDEFINED_ERROR;

  eXosip.j_socketctl_event = jpipe ();
  if (eXosip.j_socketctl_event == NULL)
    return OSIP_UNDEFINED_ERROR;
#endif

 
  eXosip.j_events = (osip_fifo_t *) osip_malloc (sizeof (osip_fifo_t));
  if (eXosip.j_events == NULL)
    return OSIP_NOMEM;
  osip_fifo_init (eXosip.j_events);

  eXosip.use_rport = 1;
  eXosip.use_naptr = 1;
  eXosip.keep_alive = 17000;

  eXtl_udp.tl_init ();
  eXtl_tcp.tl_init ();
#ifdef HAVE_OPENSSL_SSL_H
#if !(OPENSSL_VERSION_NUMBER < 0x00908000L)
  eXtl_dtls.tl_init ();
#endif
  eXtl_tls.tl_init ();
#endif
  return OSIP_SUCCESS;
}

 

看上去代码很多,其实主要是判断的宏太多了,一步步的理清。

eXosip 为全局变量,里面定义了一大堆变量。

接着初始化eXosip的两个成员变量,但是不知道这两个初始化的值是从哪里来的

接下来看win32的部分,是用WSAStartup对windows的网络部分进行初始化。

为了在应用程序当中调用任何一个Winsock API函数,首先第一件事情就是必须通过WSAStartup函数完成对Winsock服务的初始化,因此需要调用WSAStartup函数。使用Socket的程序在使用Socket之前必须调用WSAStartup函数。

 

接下来对eXosip结构的user_agent进行初始化。把参数的字符串复制给user_agent,里面的实现实际就是分配内存,然后进行str拷贝的操作。

eXosip.j_stop_ua = 0;这个变量比较重要,通过这个值判断协议栈是否要一直运行

i = osip_list_init (&eXosip.j_transactions);

初始化,用memset设置为0

……

在初始化完eXosip结构的一些变量后,初始化osip结构

i = osip_init (&osip);

osip_set_application_context (osip, &eXosip);

以上这句很有意思,在很多情况下,我们可以学习这个做法。将eXosip的结构设置到osip中进行保存,然后一边会有一个osip_get_application方法来取出这个eXosip结构。也就是说可以在osip的环境中取出exosip,调用exosip的东西。

eXosip_set_callbacks (osip);

设置osip的回调函数,这里很重要。

……

eXtl_udp.tl_init ();
eXtl_tcp.tl_init ();

这两句是搞社么的?(对udp,tcp两个不同的socket进行一些初始化的工作, 在后面通过判断是使用tcp还是udp,来对应open某个socket)

 

接下来

eXosip_listen_addr

根据udp或者tcp,open上文定义好的socket。

 

eXosip_register_build_initial_register

构建注册消息。

eXosip_register_send_register

发出注册消息

你可能感兴趣的:(socket,struct,null,application,events,transactions)