一个基于 exosip 库的 UAC 和 UAS 的代码整理

http://ordinarysky.cn/?p=164

———– UAC 代理客户端的代码整理 —————

[cpp]  view plain copy
  1. /**  
  2. * 一个使用了 osip 和 eXosip 库的 UAC 代理客户端的演示程序  
  3.  
  4. * - 只是简单的演示了使用了 osip 和 eXosip2 库的 UAC 代理客户端的如下几个功能:  
  5. * * i 发起呼叫 INVITE 请求  
  6. * * h 挂断会话  
  7. * * s 执行方法 INFO  
  8. * * m 执行方法 MESSAGE 
  9.  
  10.  
  11.  
  12.  
  13. * 编 译:g++ -I/usr/local/include -L/usr/local/lib ua_client.cpp -o ua_client -leXosip2 -losip2 -losipparser2 -lpthread  
  14.  
  15. */   
  16. #include <osip2/osip_mt.h>   
  17. #include <eXosip2/eXosip.h>   
  18. #include <netinet/in.h>   
  19. #include <sys/socket.h>   
  20. #include <sys/types.h>   
  21. #include <iostream>   
  22. #include <string>   
  23. using namespace std;   
  24. int main(int argc, char* argv[])   
  25. {   
  26.     eXosip_event_t *je;   
  27.     osip_message_t *reg = NULL;   
  28.     osip_message_t *invite = NULL;   
  29.     osip_message_t *ack = NULL;   
  30.     osip_message_t *info = NULL;   
  31.     osip_message_t *message = NULL;   
  32. int call_id, dialog_id;   
  33. int i,flag;   
  34. int flag1 = 1;   
  35. int id;   
  36. string strIdentity = "sip:136@133.37.55.136";   
  37. string strRegisterer = "sip:133.37.55.136:5060"// server ip   
  38. string strSrcCall = "sip:136@133.37.55.136";   
  39. string strDestCall = "sip:136@133.37.55.136:5060"// server ip   
  40. char command;   
  41. char tmp[4096];   
  42. char localip[128];   
  43. string strHelp = string("\n\t--> 命令字符 功能描述 <--\n\n")   
  44. "\t\tr 向服务器注册\n"   
  45. "\t\tc 取消注册\n"   
  46. "\t\ti 发起呼叫请求\n"   
  47. "\t\th 挂断\n"   
  48. "\t\tq 退出程序\n"   
  49. "\t\ts 执行方法 INFO\n"   
  50. "\t\tm 执行方法 MESSAGE\n"   
  51. "\t\te 帮助\n\n";   
  52. cout << strHelp;   
  53. string strMsg;   
  54.     i = eXosip_init ();   
  55. if (i != 0)   
  56. {   
  57. cout << "\t--> Couldn't initialize eXosip! <--\n";   
  58. return -1;   
  59. }   
  60. else   
  61. {   
  62. cout << "\t--> eXosip_init successfully! <-- \n\n";   
  63. }   
  64.     i = eXosip_listen_addr (IPPROTO_UDP, NULL, 5061, AF_INET, 0);   
  65. if (i != 0)   
  66. {   
  67.         eXosip_quit ();   
  68. cerr << "\n\t--> Couldn't initialize transport layer! <-- \n\n";   
  69. return -1;   
  70. }   
  71.     flag = 1;   
  72. while (flag)   
  73. {   
  74. cout << "请输入一个命令字符:\t";   
  75. cin >> command;   
  76. switch (command)   
  77. {   
  78. case 'r':   
  79. cout << "\n\t--> This modal isn't commpleted! \n" << endl;   
  80. break;   
  81. case 'i'// 初始化的 INVITE 请求   
  82.             i = eXosip_call_build_initial_invite (&invite,   
  83.                                                   strDestCall.c_str(),   
  84.                                                   strSrcCall.c_str(),   
  85. NULL,   
  86. "This is a call for a conversation");   
  87. if (i != 0)   
  88. {   
  89. cout << "\n --> Intial INVITE failed! <-- \n";   
  90. break;   
  91. }   
  92. // 符合 SDP 格式, 其中属性 a 是自定义格式,也就是说可以存放自己的信息,    
  93. // 但是只能是两列,比如帐户信息   
  94. // 但是经测试,格式: v o t必不可少,原因未知,估计是协议栈在传输时需要检查的   
  95.             strMsg = string("v=0\r\n")   
  96. "o=anonymous 0 0 IN IP4 0.0.0.0\r\n"   
  97. "t=1 10\r\n"   
  98. "a=username:bluesea\r\n"   
  99. "a=password:123456\r\n";   
  100.             osip_message_set_body (invite, strMsg.c_str(), strMsg.length());   
  101.             osip_message_set_content_type (invite, "application/sdp");   
  102. // 这里使用了锁机制以保证同步   
  103.             eXosip_lock ();   
  104.             i = eXosip_call_send_initial_invite (invite);   
  105.             eXosip_unlock ();   
  106.             flag1 = 1;   
  107. while (flag1)   
  108. {   
  109.                 je = eXosip_event_wait (0, 200);   
  110. if (je == NULL)   
  111. {   
  112. cout << "\n\t--> No response or the time is over! <--\n" << endl;   
  113. break;   
  114. }   
  115. switch (je->type)   
  116. {   
  117. case EXOSIP_CALL_INVITE:   
  118. cout << "\n\t--> a new invite reveived! <--\n" << endl;   
  119. break;   
  120. // announce processing by a remote app   
  121. case EXOSIP_CALL_PROCEEDING:   
  122. cout << "\n\t--> proceeding! <--\n" << endl;   
  123. break;   
  124. // announce ringback   
  125. case EXOSIP_CALL_RINGING:   
  126. cout << "\n\t--> ringing! <--\n"   
  127. << "\n\tcall_id is " << je->cid   
  128. << ", dialog_id is " << je->did << endl;   
  129. break;   
  130. // 收到请求,表示连接成功,下面发送回复确认   
  131. case EXOSIP_CALL_ANSWERED:   
  132. cout << "\n\t--> ok! connected! <--\n" << endl;   
  133.                     call_id = je->cid;   
  134.                     dialog_id = je->did;   
  135. cout << "\n\tcall_id is " << je->cid   
  136. << ", dialog_id is " << je->did << endl;   
  137.                     eXosip_call_build_ack (je->did, &ack);   
  138.                     eXosip_call_send_ack (je->did, ack);   
  139.                     flag1 = 0;   
  140. break;   
  141. case EXOSIP_CALL_CLOSED:   
  142. cout << "\n\t--> the other sid closed! <--\n" << endl;   
  143. break;   
  144. case EXOSIP_CALL_ACK:   
  145. cout << "\n\t--> ACK received! <--\n" << endl;   
  146. break;   
  147. default:   
  148. cout << "\n\t--> other response!\n" <<endl;   
  149. break;   
  150. }   
  151.                 eXosip_event_free (je);   
  152. }   
  153. break;   
  154. case 'h':   
  155. cout << "\n\t--> Holded ! \n" << endl;   
  156.             eXosip_lock ();   
  157.             eXosip_call_terminate (call_id, dialog_id);   
  158.             eXosip_unlock ();   
  159. break;   
  160. case 'c':   
  161. cout << "\n\t--> This modal isn't commpleted! \n" << endl;   
  162. break;   
  163. case 's':   
  164. // 传输 INFO 方法   
  165.             eXosip_call_build_info (dialog_id, &info);   
  166.             snprintf (tmp , 4096, "hello,bluesea");   
  167.             osip_message_set_body (info, tmp, strlen(tmp));   
  168. // 格式可以任意设定, text/plain 代表文本信息   
  169.             osip_message_set_content_type (info, "text/plain");   
  170.             eXosip_call_send_request (dialog_id, info);   
  171. break;   
  172. case 'm':   
  173. // 传输 MESSAGE方法,也就是即时消息,   
  174. // 和 INFO 方法相比,主要区别,是 MESSAGE 不用建立连接,直接传输信息,   
  175. // 而 INFO 必须在建立 INVITE 的基础上传输。   
  176. cout << "\n\t--> the mothed :MESSAGE \n" << endl;   
  177.             eXosip_message_build_request (&message,   
  178. "MESSAGE",   
  179.                                           strDestCall.c_str(),   
  180.                                           strSrcCall.c_str(),   
  181. NULL);   
  182.             strMsg = "message: hello bluesea!";   
  183.             osip_message_set_body (message, strMsg.c_str(), strMsg.length());   
  184. // 假设格式是xml   
  185.             osip_message_set_content_type (message, "text/xml");   
  186.             eXosip_message_send_request (message);   
  187. break;   
  188. case 'q':   
  189.             eXosip_quit ();   
  190. cout << "\n\t--> Exit the setup! \n" << endl;;   
  191.             flag = 0;   
  192. break;   
  193. case 'e':   
  194. cout << strHelp << endl;   
  195. break;   
  196. default:   
  197. cout << "\n\t--> 不支持的命令 <--\n" << endl;   
  198. break;   
  199. }   
  200. }   
  201. return 0;   
  202. }  




 ———– UAS 代理服务器端的代码整理 —————

[cpp]  view plain copy
  1. /**  
  2. * 一个使用了 osip 和 eXosip 库的 UAS 代理服务端的演示程序  
  3.  
  4. * - 只是简单的演示了使用了 osip 和 eXosip2 库的 UAS 代理服务端的如下几个功能:  
  5.  
  6. * 编 译:g++ -I/usr/local/include -L/usr/local/lib ua_server.cpp -o ua_server -leXosip2 -losip2 -losipparser2 -lpthread  
  7.  
  8. */   
  9. #include <eXosip2/eXosip.h>   
  10. #include <netinet/in.h>   
  11. #include <sys/socket.h>   
  12. #include <sys/types.h>   
  13. #include <iostream>   
  14. #include <fstream>   
  15. #include <string>   
  16. using namespace std;   
  17. int main()   
  18. {   
  19.     eXosip_event_t *je = NULL;   
  20.     osip_message_t *ack = NULL;   
  21.     osip_message_t *invite = NULL;   
  22.     osip_message_t *answer = NULL;   
  23.     sdp_message_t *remote_sdp = NULL;   
  24. int call_id, dialog_id;   
  25. int i,j;   
  26. int id;   
  27. char *sour_call = "sip:136@133.37.55.136";   
  28. char *dest_call = "sip:136@133.37.55.136:5061"//client ip/port   
  29. char command;   
  30. char tmp[4096];   
  31. char localip[128];   
  32. int pos = 0;   
  33. // 初始化 sip   
  34.     i = eXosip_init ();   
  35. if (i != 0)   
  36. {   
  37. cerr << "\n\t--> Can't initialize eXosip!\n";   
  38. return -1;   
  39. }   
  40. else   
  41. {   
  42. cout << "\n\t--> eXosip_init successfully!\n";   
  43. }   
  44.     i = eXosip_listen_addr (IPPROTO_UDP, NULL, 5060, AF_INET, 0);   
  45. if (i != 0)   
  46. {   
  47.         eXosip_quit ();   
  48. cerr << "\n\t--> eXosip_listen_addr error! Couldn't initialize transport layer!\n";   
  49. }   
  50. for(;;)   
  51. {   
  52. // 侦听是否有消息到来   
  53.         je = eXosip_event_wait (0, 50);   
  54. // 协议栈带有此语句,具体作用未知   
  55.         eXosip_lock ();   
  56.         eXosip_default_action (je);   
  57.         eXosip_automatic_refresh ();   
  58.         eXosip_unlock ();   
  59. if (je == NULL) // 没有接收到消息,继续   
  60. {   
  61. continue;   
  62. }   
  63. switch (je->type)   
  64. {   
  65. case EXOSIP_MESSAGE_NEW: // 新的消息到来   
  66. cout << "\n\t*** EXOSIP_MESSAGE_NEW!\n" << endl;   
  67. if (MSG_IS_MESSAGE (je->request)) // 如果接收到的消息类型是 MESSAGE   
  68. {   
  69. {   
  70.                     osip_body_t *body;   
  71.                     osip_message_get_body (je->request, 0, &body);   
  72. cout << "I get the msg is: " << body->body << endl;   
  73. }   
  74. // 按照规则,需要回复 OK 信息   
  75.                 eXosip_message_build_answer (je->tid, 200, &answer);   
  76.                 eXosip_message_send_answer (je->tid, 200, answer);   
  77. }   
  78. break;   
  79. case EXOSIP_CALL_INVITE: // INVITE 请求消息   
  80. // 得到接收到消息的具体信息   
  81. cout << "\n\tReceived a INVITE msg from " << je->request->req_uri->host   
  82. << " : " << je->request->req_uri->port   
  83. << ", username is " << je->request->req_uri->username << endl;   
  84. // 得到消息体,认为该消息就是 SDP 格式.   
  85.             remote_sdp = eXosip_get_remote_sdp (je->did);   
  86.             call_id = je->cid;   
  87.             dialog_id = je->did;   
  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. cout << "\n\t--> This request msg is invalid! Cann't response!\n" << endl;   
  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. // 设置回复的SDP消息体,下一步计划分析消息体   
  105. // 没有分析消息体,直接回复原来的消息,这一块做的不好。   
  106.                 osip_message_set_body (answer, tmp, strlen(tmp));   
  107.                 osip_message_set_content_type (answer, "application/sdp");   
  108.                 eXosip_call_send_answer (je->tid, 200, answer);   
  109. cout << "\n\t--> send 200 over!" << endl;   
  110. }   
  111.             eXosip_unlock ();   
  112. // 显示出在 sdp 消息体中的 attribute 的内容,里面计划存放我们的信息   
  113. cout << "\n\t--> The INFO is :\n" ;   
  114. while (!osip_list_eol ( &(remote_sdp->a_attributes), pos))   
  115. {   
  116.                 sdp_attribute_t *at;   
  117. //这里解释了为什么在SDP消息体中属性a里面存放必须是两列   
  118.                 at = (sdp_attribute_t *) osip_list_get ( &remote_sdp->a_attributes, pos);   
  119. cout << "\n\t" << at->a_att_field   
  120. << " : " << at->a_att_value << endl;   
  121.                 pos ++;   
  122. }   
  123. break;   
  124. case EXOSIP_CALL_ACK:   
  125. cout << "\n\t--> ACK recieved!\n" << endl;   
  126. // printf ("the cid is %s, did is %s\n", je->did, je->cid);    
  127. break;   
  128. case EXOSIP_CALL_CLOSED:   
  129. cout << "\n\t--> the remote hold the session!\n" << endl;   
  130. // eXosip_call_build_ack(dialog_id, &ack);   
  131. // eXosip_call_send_ack(dialog_id, ack);    
  132.             i = eXosip_call_build_answer (je->tid, 200, &answer);   
  133. if (i != 0)   
  134. {   
  135. printf ("This request msg is invalid!Cann't response!\n");   
  136.                 eXosip_call_send_answer (je->tid, 400, NULL);   
  137. }   
  138. else   
  139. {   
  140.                 eXosip_call_send_answer (je->tid, 200, answer);   
  141. cout << "\n\t--> bye send 200 over!\n";   
  142. }   
  143. break;   
  144. case EXOSIP_CALL_MESSAGE_NEW:   
  145. cout << "\n\t*** EXOSIP_CALL_MESSAGE_NEW\n" << endl;   
  146. if (MSG_IS_INFO(je->request) ) // 如果传输的是 INFO 方法   
  147. {   
  148.                 eXosip_lock ();   
  149.                 i = eXosip_call_build_answer (je->tid, 200, &answer);   
  150. if (i == 0)   
  151. {   
  152.                     eXosip_call_send_answer (je->tid, 200, answer);   
  153. }   
  154.                 eXosip_unlock ();   
  155. {   
  156.                     osip_body_t *body;   
  157.                     osip_message_get_body (je->request, 0, &body);   
  158. cout << "the body is " << body->body << endl;   
  159. }   
  160. }   
  161. break;   
  162. default:   
  163. cout << "\n\t--> Could not parse the msg!\n" << endl;   
  164. }   
  165. }   
  166. return 0;   
  167. }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值