eXosip 软电话实现的UAC和UAS的例子

更新时间:2023-10-08 00:09:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

eXosip 学习案例

一个用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

***************************************************************************/ #include #include #include #include #include #include #include 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 = \

char *dest_call = \

char command;

eXosip 学习案例

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

int pos = 0;

//初始化sip i = eXosip_init (); if (i != 0) {

printf (\ return -1; } else {

printf (\ }

i = eXosip_listen_addr (IPPROTO_UDP, NULL, 5060, AF_INET, 0); if (i != 0) {

eXosip_quit ();

fprintf (stderr, \ }

for(;;) {

//侦听是否有消息到来

je = eXosip_event_wait (0,50);

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

eXosip_default_action (je); eXosip_automatic_refresh (); eXosip_unlock ();

if (je == NULL)//没有接收到消息 continue;

// printf (\ switch (je->type) {

case EXOSIP_MESSAGE_NEW://新的消息到来 printf (\

if (MSG_IS_MESSAGE (je->request))//如果接受到的消息类型是MESSAGE {

eXosip 学习案例

{

osip_body_t *body;

osip_message_get_body (je->request, 0, &body); printf (\

//printf (\ }

//按照规则,需要回复200 OK信息

eXosip_message_build_answer (je->tid, 200,&answer); eXosip_message_send_answer (je->tid, 200,answer); } break;

case EXOSIP_CALL_INVITE:

//得到接收到消息的具体信息

printf (\a INVITE msg from %s:%s, UserName is %s, password is %s\\n\ 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 (\ eXosip_call_send_answer (je->tid, 400, NULL); } else {

snprintf (tmp, 4096, \

\ \

\ \

//设置回复的SDP消息体,下一步计划分析消息体

//没有分析消息体,直接回复原来的消息,这一块做的不好。 osip_message_set_body (answer, tmp, strlen(tmp));

osip_message_set_content_type (answer, \

eXosip 学习案例

eXosip_call_send_answer (je->tid, 200, answer); printf (\ }

eXosip_unlock ();

//显示出在sdp消息体中的 attribute 的内容,里面计划存放我们的信息 printf (\

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 (\这里解释了为什么在SDP消息体中属性a里面存放必须是两列

pos ++; } break;

case EXOSIP_CALL_ACK: printf (\

// printf (\ break;

case EXOSIP_CALL_CLOSED:

printf (\ // 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 (\ eXosip_call_send_answer (je->tid, 400, NULL); } else {

eXosip_call_send_answer (je->tid, 200, answer); printf (\ } break;

case EXOSIP_CALL_MESSAGE_NEW://至于该类型和EXOSIP_MESSAGE_NEW的区别,源代码这么解释的 /*

/* request related events within calls (except INVITE) */

eXosip 学习案例

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(\

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 (\ } }

break; default:

printf (\ } } }

/*******************UAC***************************************************** 本文可以任意转载,但必须保留出处 作者:rainfish

网址:http://blog.csdn.net/bat603/ 测试环境:eXosip3.0.1/redhat AS 4

***************************************************************************/

#include #include #include #include #include #include

eXosip 学习案例

int

main (int argc, char *argv[]) {

eXosip_event_t *je;

osip_message_t *reg = NULL; osip_message_t *invite = NULL; osip_message_t *ack = NULL; osip_message_t *info = NULL; osip_message_t *message = NULL;

int call_id, dialog_id; int i,flag; int flag1 = 1; int id;

char *identity = \ char *registerer = \ char *source_call = \ char *dest_call = \

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

printf(\ 向服务器注册\\n\\n\ printf(\ 取消注册\\n\\n\ printf(\ 发起呼叫请求\\n\\n\ printf(\ 挂断\\n\\n\ printf(\ 退出程序\\n\\n\

printf(\ 执行方法INFO\\n\\n\

printf(\ 执行方法MESSAGE\\n\\n\ //初始化

i = eXosip_init (); if (i != 0) {

printf (\ return -1; } else {

printf (\ }

eXosip 学习案例

i = eXosip_listen_addr (IPPROTO_UDP, NULL, 5060, AF_INET, 0); if (i != 0) {

eXosip_quit ();

fprintf (stderr, \ return -1; } flag = 1; while (flag) {

printf (\

scanf (\ getchar ();

switch (command) {

case 'r':

printf (\ break;

case 'i':/* INVITE */

i = eXosip_call_build_initial_invite (&invite, dest_call, source_call, NULL, \a conversation\ if (i != 0) {

printf (\ break; }

//符合SDP格式,其中属性a是自定义格式,也就是说可以存放自己的信息,但是只能是两列,比如帐户信息

//但是经测试,格式:v o t必不可少,原因未知,估计是协议栈在传输时需要检查的 snprintf (tmp, 4096, \

\ \

\ \

osip_message_set_body (invite, tmp, strlen(tmp));

osip_message_set_content_type (invite, \

eXosip_lock ();

i = eXosip_call_send_initial_invite (invite); eXosip_unlock (); flag1 = 1;

eXosip 学习案例

while (flag1) {

je = eXosip_event_wait (0, 200);

if (je == NULL) {

printf (\ break; }

switch (je->type) {

case EXOSIP_CALL_INVITE:

printf (\ break;

case EXOSIP_CALL_PROCEEDING: printf (\ break;

case EXOSIP_CALL_RINGING: printf (\ // call_id = je->cid; // dialog_id = je->did;

printf (\ break;

case EXOSIP_CALL_ANSWERED: printf (\ call_id = je->cid; dialog_id = je->did;

printf (\

eXosip_call_build_ack (je->did, &ack); eXosip_call_send_ack (je->did, ack); flag1 = 0; break;

case EXOSIP_CALL_CLOSED:

printf (\ break;

case EXOSIP_CALL_ACK: printf (\ break; default:

printf (\ break; }

eXosip 学习案例

eXosip_event_free (je); } break; case 'h':

printf (\

eXosip_lock ();

eXosip_call_terminate (call_id, dialog_id); eXosip_unlock (); break; case 'c':

printf (\ break; case 's':

//传输INFO方法

eXosip_call_build_info (dialog_id, &info); snprintf (tmp , 4096, \

osip_message_set_body (info, tmp, strlen(tmp)); //格式可以任意设定,text/plain代表文本信息

osip_message_set_content_type (info, \ eXosip_call_send_request (dialog_id, info); break; case 'm':

//传输MESSAGE方法,也就是即时消息,和INFO方法相比,我认为主要区别,是MESSAGE不用建立连接,直接传输信息,而INFO必须 //在建立INVITE的基础上传输。 printf (\

eXosip_message_build_request (&message, \ snprintf (tmp, 4096, \

osip_message_set_body (message, tmp, strlen(tmp)); //假设格式是xml

osip_message_set_content_type (message, \ eXosip_message_send_request (message); break; case 'q':

eXosip_quit ();

printf (\ flag = 0; break; } }

eXosip 学习案例

return (0); }

本文来自CSDN博客,转载请http://blog.csdn.net/bat603/archive/2006/11/15/1386277.aspx

标明出处:

本文来源:https://www.bwwdw.com/article/kkud.html

Top