⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 li1s.c

📁 自己写的SIP小程序
💻 C
字号:

    
/******************************************
编译方法:
     gcc xxx.c -o xxx -leXosip2
****************************************/
/*******************UAS*****************************************************
本文可以任意转载,但必须保留出处
作者:rainfish
网址:http://blog.csdn.net/bat603/
测试环境:eXosip3.0.1/redhat AS 4
***************************************************************************/
#include <eXosip2/eXosip.h>
#include <osip2/osip_mt.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>

int
main (int argc, char *argv[])
{
   eXosip_event_t *je = NULL;
   osip_message_t *ack = NULL;
   osip_message_t *invite = NULL;
   osip_message_t *answer = NULL;
   sdp_message_t *remote_sdp = NULL;

   int call_id, dialog_id;
   int i,j;
   int id;
   char *sour_call = "sip:140@192.168.0.114:5070";
   char *dest_call = "sip:133@192.168.0.114:5060";

   char command;
   char tmp[4096];
   char localip[128];

   int pos = 0;

   //初始化sip
   i = eXosip_init ();
   if (i != 0)
     {
       printf ("Can't initialize eXosip!\n");
       return -1;
     }
   else
     {
       printf ("eXosip_init successfully!\n");
     }

   i = eXosip_listen_addr (IPPROTO_UDP, NULL, 5070, AF_INET, 0);
   if (i != 0)
     {
       eXosip_quit ();
       fprintf (stderr, "eXosip_listen_addr error!\nCouldn't initialize transport layer!\n");
     }

   for(;;)
     {
       //侦听是否有消息到来
       je = eXosip_event_wait (0,50); 

       //协议栈带有此语句,具体作用未知
       eXosip_lock ();
       eXosip_default_action (je);
       eXosip_automatic_refresh ();
       eXosip_unlock ();

       if (je == NULL)//没有接收到消息
     continue;
       // printf ("the cid is %s, did is %s\n", je->did, je->cid);
       switch (je->type)
     {
     case EXOSIP_MESSAGE_NEW://新的消息到来
       printf (" EXOSIP_MESSAGE_NEW!\n");
       if (MSG_IS_MESSAGE (je->request))//如果接受到的消息类型是MESSAGE
         {
       {
         osip_body_t *body;
         osip_message_get_body (je->request, 0, &body); 
         printf ("I get the msg is: %s\n", body->body);
         //printf ("the cid is %s, did is %s\n", je->did, je->cid);
       }
       //按照规则,需要回复200 OK信息
       eXosip_message_build_answer (je->tid, 200,&answer);
       eXosip_message_send_answer (je->tid, 200,answer);
         }
       break;
     case EXOSIP_CALL_INVITE:
       //得到接收到消息的具体信息
             printf ("Received a INVITE msg from %s:%s, UserName is %s, password is %s\n",je->request->req_uri->host,
           je->request->req_uri->port, je->request->req_uri->username, je->request->req_uri->password);
       //得到消息体,认为该消息就是SDP格式.
       remote_sdp = eXosip_get_remote_sdp (je->did);
       call_id = je->cid;
       dialog_id = je->did;
      
       eXosip_lock ();
       eXosip_call_send_answer (je->tid, 180, NULL);
       i = eXosip_call_build_answer (je->tid, 200, &answer);
       if (i != 0)
         {
           printf ("This request msg is invalid!Cann't response!\n");
           eXosip_call_send_answer (je->tid, 400, NULL);
         }
       else
         {
           snprintf (tmp, 4096,
                "v=0\r\n"
                "o=anonymous 0 0 IN IP4 0.0.0.0\r\n"
                "t=1 10\r\n"
                "a=username:rainfish\r\n"
                "a=password:123\r\n");
          
           //设置回复的SDP消息体,下一步计划分析消息体
           //没有分析消息体,直接回复原来的消息,这一块做的不好。
           osip_message_set_body (answer, tmp, strlen(tmp));
           osip_message_set_content_type (answer, "application/sdp");
          
           eXosip_call_send_answer (je->tid, 200, answer);
           printf ("send 200 over!\n");
         }
       eXosip_unlock ();
      
       //显示出在sdp消息体中的 attribute 的内容,里面计划存放我们的信息
       printf ("the INFO is :\n");
       while (!osip_list_eol (&(remote_sdp->a_attributes), pos))
         {
           sdp_attribute_t *at;
          
           at = (sdp_attribute_t *) osip_list_get (&(remote_sdp->a_attributes), pos);
           printf ("%s : %s\n", at->a_att_field, at->a_att_value);//这里解释了为什么在SDP消息体中属性a里面存放必须是两列 
          
           pos ++;
         }
       break;
     case EXOSIP_CALL_ACK:
       printf ("ACK recieved!\n");
       // printf ("the cid is %s, did is %s\n", je->did, je->cid); 
       break;
     case EXOSIP_CALL_CLOSED:
       printf ("the remote hold the session!\n");
       // eXosip_call_build_ack(dialog_id, &ack);
       //eXosip_call_send_ack(dialog_id, ack); 
       i = eXosip_call_build_answer (je->tid, 200, &answer);
       if (i != 0)
         {
           printf ("This request msg is invalid!Cann't response!\n");
           eXosip_call_send_answer (je->tid, 400, NULL);
        
           }
       else
         {
           eXosip_call_send_answer (je->tid, 200, answer);
           printf ("bye send 200 over!\n");
         }        
       break;

     case EXOSIP_CALL_MESSAGE_NEW://至于该类型和EXOSIP_MESSAGE_NEW的区别,源代码这么解释的
     
     /* request related events within calls (except INVITE) */
          /* EXOSIP_CALL_MESSAGE_NEW,   < announce new incoming request. */
     /* response received for request outside calls */
           /*  EXOSIP_MESSAGE_NEW,      < announce new incoming request. */
    /*     我也不是很明白,理解是: EXOSIP_CALL_MESSAGE_NEW是一个呼叫中的新的消息到来,比如ring trying都算,所以在接受到后必须判断
             该消息类型,EXOSIP_MESSAGE_NEW而是表示不是呼叫内的消息到来。
             该解释有不妥地方,仅供参考。
     */
       printf("EXOSIP_CALL_MESSAGE_NEW\n");
       if (MSG_IS_INFO(je->request))//如果传输的是INFO方法
       {
         eXosip_lock ();
         i = eXosip_call_build_answer (je->tid, 200, &answer);
         if (i == 0)
                 {
                   eXosip_call_send_answer (je->tid, 200, answer);
                 }
        eXosip_unlock ();
               {
         osip_body_t *body;
         osip_message_get_body (je->request, 0, &body);
         printf ("the body is %s\n", body->body);
                }
       }
       break; 
     default:
       printf ("Could not parse the msg!\n");
     }
     }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -