一个用eXosip实现的UAC和UAS的例子

经过一段时间的学习,对sip总算有了一点认识,在学习过程中,遇到了太多的问题,郁闷过,惆怅过,但是一咬牙,还是过来了。令我感动的是,在网上遇到一些很热心的朋友,不厌其烦地给我以解惑,感谢他们,尤其是友善的大狗,呵呵,希望将来有一天他能看到这篇文章。
我是利用eXosip协议栈进行开发的,网上有一篇<一个简单的sip呼叫例子>,写的不错,但是好像有一些问题,而对于初学者来说,能拿到 一个好的例子,对sip的理解可以到达事半功倍的效果。于是便把自己的写的例子拿出来,让大家参考一下,若有问题,欢迎指正。
只需把里面的IP地址改正、编译即可使用。

/******************************************
编译方法:gcc xxx.c -o xxx -leXosip2
****************************************/
/*******************UAS***********************
本文可以任意转载,但必须保留出处
作者:rainfish
网址:http://blog.csdn.net/bat603/
测试环境:eXosip3.0.1/redhat AS 4
************************************************/

 
 
  1. #include <eXosip2/eXosip.h> 
  2. #include <osip2/osip_mt.h> 
  3. #include <stdio.h> 
  4. #include <stdlib.h> 
  5. #include <netinet/in.h> 
  6. #include <sys/socket.h> 
  7. #include <sys/types.h> 
  8.  
  9. int 
  10. main (int argc, char *argv[]) 
  11.   eXosip_event_t *je = NULL; 
  12.   osip_message_t *ack = NULL; 
  13.   osip_message_t *invite = NULL; 
  14.   osip_message_t *answer = NULL; 
  15.   sdp_message_t *remote_sdp = NULL; 
  16.  
  17.   int call_id, dialog_id; 
  18.   int i,j; 
  19.   int id; 
  20.   char *sour_call = "sip:133@192.168.0.133"
  21.   char *dest_call = "sip:140@192.168.0.140:5060"
  22.  
  23.   char command; 
  24.   char tmp[4096]; 
  25.   char localip[128]; 
  26.  
  27.   int pos = 0; 
  28.  
  29.   //初始化sip 
  30.   i = eXosip_init (); 
  31.   if (i != 0) 
  32.     { 
  33.       printf ("Can't initialize eXosip!/n"); 
  34.       return -1; 
  35.     } 
  36.   else 
  37.     { 
  38.       printf ("eXosip_init successfully!/n"); 
  39.     } 
  40.  
  41.   i = eXosip_listen_addr (IPPROTO_UDP, NULL, 5060, AF_INET, 0); 
  42.   if (i != 0) 
  43.     { 
  44.       eXosip_quit (); 
  45. fprintf (stderr, "eXosip_listen_addr error!/nCouldn't initialize transport layer!/n"); 
  46.     } 
  47.  
  48.   for(;;) 
  49.     { 
  50.       //侦听是否有消息到来 
  51.       je = eXosip_event_wait (0,50); 
  52.  
  53.       //协议栈带有此语句,具体作用未知 
  54.       eXosip_lock (); 
  55.       eXosip_default_action (je); 
  56.       eXosip_automatic_refresh (); 
  57.       eXosip_unlock (); 
  58.  
  59.       if (je == NULL)//没有接收到消息 
  60.     continue
  61.       // printf ("the cid is %s, did is %s/n", je->did, je->cid); 
  62.       switch (je->type) 
  63.     { 
  64.     case EXOSIP_MESSAGE_NEW://新的消息到来 
  65.       printf (" EXOSIP_MESSAGE_NEW!/n"); 
  66.       if (MSG_IS_MESSAGE (je->request))//如果接受到的消息类型是MESSAGE 
  67.       { 
  68.         osip_body_t *body; 
  69.         osip_message_get_body (je->request, 0, &body); 
  70.         printf ("I get the msg is: %s/n", body->body); 
  71.         //printf ("the cid is %s, did is %s/n", je->did, je->cid); 
  72.       } 
  73.       //按照规则,需要回复200 OK信息 
  74.       eXosip_message_build_answer (je->tid, 200,&answer); 
  75.       eXosip_message_send_answer (je->tid, 200,answer); 
  76.         } 
  77.       break
  78.     case EXOSIP_CALL_INVITE: 
  79. //得到接收到消息的具体信息 
  80. printf ("Received a INVITE msg from %s:%s, UserName is %s, password is %s/n"
  81. ,je->request->req_uri->host, je->request->req_uri->port, je->request->req_uri->username
  82. , je->request->req_uri->password); 
  83.       //得到消息体,认为该消息就是SDP格式. 
  84.       remote_sdp = eXosip_get_remote_sdp (je->did); 
  85.       call_id = je->cid; 
  86.       dialog_id = je->did; 
  87.       
  88.       eXosip_lock (); 
  89.       eXosip_call_send_answer (je->tid, 180, NULL); 
  90.       i = eXosip_call_build_answer (je->tid, 200, &answer); 
  91.       if (i != 0) 
  92.         { 
  93.           printf ("This request msg is invalid!Cann't response!/n"); 
  94.           eXosip_call_send_answer (je->tid, 400, NULL); 
  95.         } 
  96.       else 
  97.         { 
  98.           snprintf (tmp, 4096, 
  99.                "v=0/r/n" 
  100.                "o=anonymous 0 0 IN IP4 0.0.0.0/r/n" 
  101.                "t=1 10/r/n" 
  102.                "a=username:rainfish/r/n" 
  103.                "a=password:123/r/n"); 
  104.           
  105.           //设置回复的SDP消息体,下一步计划分析消息体 
  106.           //没有分析消息体,直接回复原来的消息,这一块做的不好。 
  107.           osip_message_set_body (answer, tmp, strlen(tmp)); 
  108.           osip_message_set_content_type (answer, "application/sdp"); 
  109.           
  110.           eXosip_call_send_answer (je->tid, 200, answer); 
  111.           printf ("send 200 over!/n"); 
  112.         } 
  113.       eXosip_unlock (); 
  114.       
  115.       //显示出在sdp消息体中的 attribute 的内容,里面计划存放我们的信息 
  116.       printf ("the INFO is :/n"); 
  117.       while (!osip_list_eol (remote_sdp->a_attributes, pos)) 
  118.         { 
  119.           sdp_attribute_t *at; 
  120.           
  121. at = (sdp_attribute_t *) osip_list_get (remote_sdp->a_attributes, pos); 
  122. printf ("%s : %s/n", at->a_att_field, at->a_att_value);
  123. //这里解释了为什么在SDP消息体中属性a里面存放必须是两列 
  124.           
  125.           pos ++; 
  126.         } 
  127.       break
  128.     case EXOSIP_CALL_ACK: 
  129.       printf ("ACK recieved!/n"); 
  130.       // printf ("the cid is %s, did is %s/n", je->did, je->cid); 
  131.       break
  132.     case EXOSIP_CALL_CLOSED: 
  133.       printf ("the remote hold the session!/n"); 
  134.       // eXosip_call_build_ack(dialog_id, &ack); 
  135.       //eXosip_call_send_ack(dialog_id, ack); 
  136.       i = eXosip_call_build_answer (je->tid, 200, &answer); 
  137.       if (i != 0) 
  138.         { 
  139.           printf ("This request msg is invalid!Cann't response!/n"); 
  140.           eXosip_call_send_answer (je->tid, 400, NULL); 
  141.         
  142.           } 
  143.       else 
  144.         { 
  145.           eXosip_call_send_answer (je->tid, 200, answer); 
  146.           printf ("bye send 200 over!/n"); 
  147.         }        
  148.       break
  149.  
  150.     case EXOSIP_CALL_MESSAGE_NEW:
  151. //至于该类型和EXOSIP_MESSAGE_NEW的区别,源代码这么解释的 
  152.     /* 
  153. request related events within calls (except INVITE)
  154.     EXOSIP_CALL_MESSAGE_NEW, //< announce new incoming request.
  155. response received for request outside calls
  156.     EXOSIP_MESSAGE_NEW,      //< announce new incoming request.
  157. 我也不是很明白,理解是: EXOSIP_CALL_MESSAGE_NEW是一个呼叫中的新的消息到来,
  158. 比如ring trying都算,所以在接受到后必须判断 
  159. 该消息类型,EXOSIP_MESSAGE_NEW而是表示不是呼叫内的消息到来。 
  160. 该解释有不妥地方,仅供参考。 
  161.     */ 
  162.       printf(" EXOSIP_CALL_MESSAGE_NEW/n"); 
  163.       if (MSG_IS_INFO(je->request)//如果传输的是INFO方法 
  164.       { 
  165.                    eXosip_lock (); 
  166.               i = eXosip_call_build_answer (je->tid, 200, &answer); 
  167.               if (i == 0) 
  168.                 { 
  169.                   eXosip_call_send_answer (je->tid, 200, answer); 
  170.                 } 
  171.               eXosip_unlock (); 
  172.           { 
  173.         osip_body_t *body; 
  174.         osip_message_get_body (je->request, 0, &body); 
  175.         printf ("the body is %s/n", body->body); 
  176.           } 
  177.       } 
  178.       break
  179.     default
  180.       printf ("Could not parse the msg!/n"); 
  181.     } 
  182.     } 

/*******************UAC*********************
本文可以任意转载,但必须保留出处
作者:rainfish
网址:http://blog.csdn.net/bat603/
测试环境:eXosip3.0.1/redhat AS 4
***************************************************************************/

 
 
  1. #include <eXosip2/eXosip.h> 
  2. #include <stdio.h> 
  3. #include <stdlib.h> 
  4. #include <netinet/in.h> 
  5. #include <sys/socket.h> 
  6. #include <sys/types.h> 
  7.  
  8. int 
  9. main (int argc, char *argv[]) 
  10.   eXosip_event_t *je; 
  11.   osip_message_t *reg = NULL; 
  12.   osip_message_t *invite = NULL; 
  13.   osip_message_t *ack = NULL; 
  14.   osip_message_t *info = NULL; 
  15.   osip_message_t *message = NULL; 
  16.  
  17.   int call_id, dialog_id; 
  18.   int i,flag; 
  19.   int flag1 = 1; 
  20.   int id; 
  21.   
  22.   char *identity = "sip:140@192.168.0.140"
  23.   char *registerer = "sip:192.168.0.133:5060"
  24.   char *source_call = "sip:140@192.168.0.140"
  25.   char *dest_call = "sip:133@192.168.0.133:5060"
  26.   
  27.   char command; 
  28.   char tmp[4096]; 
  29.   char localip[128]; 
  30.  
  31.   printf("r     向服务器注册/n/n"); 
  32.   printf("c     取消注册/n/n"); 
  33.   printf("i     发起呼叫请求/n/n"); 
  34.   printf("h     挂断/n/n"); 
  35.   printf("q     退出程序/n/n"); 
  36.   printf("s     执行方法INFO/n/n"); 
  37.   printf("m     执行方法MESSAGE/n/n"); 
  38.   //初始化 
  39.   i = eXosip_init (); 
  40.   if (i != 0) 
  41.     { 
  42.       printf ("Couldn't initialize eXosip!/n"); 
  43.       return -1; 
  44.     } 
  45.   else 
  46.     { 
  47.       printf ("eXosip_init successfully!/n"); 
  48.     } 
  49.  
  50.   i = eXosip_listen_addr (IPPROTO_UDP, NULL, 5060, AF_INET, 0); 
  51.   if (i != 0) 
  52.     { 
  53.       eXosip_quit (); 
  54.       fprintf (stderr, "Couldn't initialize transport layer!/n"); 
  55.       return -1; 
  56.     } 
  57.   flag = 1; 
  58.   while (flag) 
  59.     { 
  60.       printf ("please input the comand:/n"); 
  61.        
  62.       scanf ("%c", &command); 
  63.       getchar (); 
  64.        
  65.       switch (command) 
  66.     { 
  67.     case 'r'
  68.       printf ("This modal isn't commpleted!/n"); 
  69.       break
  70.     case 'i':/* INVITE */ 
  71.       i = eXosip_call_build_initial_invite (&invite, dest_call
  72. , source_call, NULL, "This si a call for a conversation"); 
  73.       if (i != 0) 
  74.         { 
  75.           printf ("Intial INVITE failed!/n"); 
  76.           break
  77.         } 
  78. //符合SDP格式,其中属性a是自定义格式,也就是说可以存放自己的信息,但是只能是两列,比如帐户信息 
  79. //但是经测试,格式:v o t必不可少,原因未知,估计是协议栈在传输时需要检查的 
  80.       snprintf (tmp, 4096, 
  81.             "v=0/r/n" 
  82.             "o=anonymous 0 0 IN IP4 0.0.0.0/r/n" 
  83.             "t=1 10/r/n" 
  84.             "a=username:rainfish/r/n" 
  85.             "a=password:123/r/n"); 
  86.       osip_message_set_body (invite, tmp, strlen(tmp)); 
  87.       osip_message_set_content_type (invite, "application/sdp"); 
  88.        
  89.       eXosip_lock (); 
  90.       i = eXosip_call_send_initial_invite (invite); 
  91.       eXosip_unlock (); 
  92.       flag1 = 1; 
  93.       while (flag1) 
  94.         { 
  95.           je = eXosip_event_wait (0, 200); 
  96.            
  97.           if (je == NULL) 
  98.         { 
  99.           printf ("No response or the time is over!/n"); 
  100.           break
  101.         } 
  102.            
  103.           switch (je->type) 
  104.         { 
  105.         case EXOSIP_CALL_INVITE: 
  106.           printf ("a new invite reveived!/n"); 
  107.           break
  108.         case EXOSIP_CALL_PROCEEDING: 
  109.           printf ("proceeding!/n"); 
  110.           break
  111.         case EXOSIP_CALL_RINGING: 
  112.           printf ("ringing!/n"); 
  113.           // call_id = je->cid; 
  114.           // dialog_id = je->did; 
  115.           printf ("call_id is %d, dialog_id is %d /n", je->cid, je->did); 
  116.           break
  117.         case EXOSIP_CALL_ANSWERED: 
  118.           printf ("ok! connected!/n"); 
  119.           call_id = je->cid; 
  120.           dialog_id = je->did; 
  121.           printf ("call_id is %d, dialog_id is %d /n", je->cid, je->did); 
  122.  
  123.           eXosip_call_build_ack (je->did, &ack); 
  124.           eXosip_call_send_ack (je->did, ack); 
  125.           flag1 = 0; 
  126.           break
  127.         case EXOSIP_CALL_CLOSED: 
  128.           printf ("the other sid closed!/n"); 
  129.           break
  130.         case EXOSIP_CALL_ACK: 
  131.           printf ("ACK received!/n"); 
  132.           break
  133.         default
  134.           printf ("other response!/n"); 
  135.           break
  136.         } 
  137.           eXosip_event_free (je); 
  138.           
  139.         } 
  140.       break
  141.     case 'h'
  142.       printf ("Holded !/n"); 
  143.        
  144.       eXosip_lock (); 
  145.       eXosip_call_terminate (call_id, dialog_id); 
  146.       eXosip_unlock (); 
  147.       break
  148.     case 'c'
  149.       printf ("This modal isn't commpleted!/n"); 
  150.       break
  151.     case 's'
  152.     //传输INFO方法 
  153.       eXosip_call_build_info (dialog_id, &info); 
  154.       snprintf (tmp , 4096, 
  155.             "hello,rainfish"); 
  156.       osip_message_set_body (info, tmp, strlen(tmp)); 
  157.       //格式可以任意设定,text/plain代表文本信息 
  158.       osip_message_set_content_type (info, "text/plain"); 
  159.       eXosip_call_send_request (dialog_id, info); 
  160.       break
  161.     case 'm'
  162. //传输MESSAGE方法,也就是即时消息,和INFO方法相比,我认为主要区别
  163. //,是MESSAGE不用建立连接,直接传输信息,而INFO必须 
  164. //在建立INVITE的基础上传输。 
  165.       printf ("the mothed :MESSAGE/n"); 
  166.       eXosip_message_build_request (&message, "MESSAGE", dest_call, source_call, NULL); 
  167.       snprintf (tmp, 4096, 
  168.             "hellor rainfish"); 
  169.       osip_message_set_body (message, tmp, strlen(tmp)); 
  170.       //假设格式是xml 
  171.       osip_message_set_content_type (message, "text/xml"); 
  172.       eXosip_message_send_request (message); 
  173.       break
  174.     case 'q'
  175.       eXosip_quit (); 
  176.       printf ("Exit the setup!/n"); 
  177.       flag = 0; 
  178.       break
  179.     } 
  180.     } 
  181.   return (0); 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值