linux 2.4.0 编译,linux下编译eXosip、osip,以及UAC和UAS的例子 新版本的补充2.4.0.0以上...

参考:html

源码地址:session

SIP协议有更新后,从网上找的这个例子很差用了,依新的接口要求我对UAC.C, UAS.C作了更新:ide

UAC.C以下:测试

#include

#include

#include

#include

#include

//#include ui

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

{this

struct eXosip_t *context_eXosip;spa

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;xml

int call_id,dialog_id;

int i,flag;

int flag1=1;

char *identity="sip:140@127.0.0.1";   //UAC1,端口是15060

char *registar="sip:133@127.0.0.1:15061"; //UAS,端口是15061

char *source_call="sip:140@127.0.0.1";

char *dest_call="sip:133@127.0.0.1:15061";

//identify和register这一组地址是和source和destination地址相同的

//在这个例子中,uac和uas通讯,则source就是本身的地址,而目的地址就是uac1的地址

char command;

char tmp[4096];

printf("r   向服务器注册\n\n");

printf("c   取消注册\n\n");

printf("i   发起呼叫请求\n\n");

printf("h   挂断\n\n");

printf("q   推出程序\n\n");

printf("s   执行方法INFO\n\n");

printf("m   执行方法MESSAGE\n\n");

//初始化

struct eXosip_t *ctx;

ctx = eXosip_malloc();

if (ctx==NULL)return -1;

i=eXosip_init(ctx);

if(i!=0)

{

printf("Couldn't initialize eXosip!\n");

return -1;

}

else

{

printf("eXosip_init successfully!\n");

}

//绑定uac本身的端口15060,并进行端口监听

i=eXosip_listen_addr(ctx,IPPROTO_UDP,NULL,15060,AF_INET,0);

if(i!=0)

{

eXosip_quit(ctx);

fprintf(stderr,"Couldn't initialize transport layer!\n");

return -1;

}

flag=1;

while(flag)

{

//输入命令

printf("Please input the command:\n");

scanf("%c",&command);

getchar();

switch(command)

{

case 'r':

printf("This modal is not completed!\n");

break;

case 'i'://INVITE,发起呼叫请求

i=eXosip_call_build_initial_invite(ctx,&invite,dest_call,source_call,NULL,"This is a call for conversation");

if(i!=0)

{

printf("Initial INVITE failed!\n");

break;

}

//符合SDP格式,其中属性a是自定义格式,也就是说能够存放本身的信息,

//可是只能有两列,好比账户信息

//可是通过测试,格式vot必不可少,缘由未知,估计是协议栈在传输时须要检查的

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");

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

osip_message_set_content_type(invite,"application/sdp");

eXosip_lock(ctx);

i=eXosip_call_send_initial_invite(ctx,invite); //invite SIP INVITE message to send

eXosip_unlock(ctx);

//发送了INVITE消息,等待应答

flag1=1;

while(flag1)

{

je=eXosip_event_wait(ctx,0,200); //Wait for an eXosip event

//(超时时间秒,超时时间毫秒)

if(je==NULL)

{

printf("No response or the time is over!\n");

break;

}

switch(je->type)   //可能会到来的事件类型

{

case EXOSIP_CALL_INVITE:   //收到一个INVITE请求

printf("a new invite received!\n");

break;

case EXOSIP_CALL_PROCEEDING: //收到100 trying消息,表示请求正在处理中

printf("proceeding!\n");

break;

case EXOSIP_CALL_RINGING:   //收到180 Ringing应答,表示接收到INVITE请求的UAS正在向被叫用户振铃

printf("ringing!\n");

printf("call_id is %d,dialog_id is %d \n",je->cid,je->did);

break;

case EXOSIP_CALL_ANSWERED: //收到200 OK,表示请求已经被成功接受,用户应答

printf("ok!connected!\n");

call_id=je->cid;

dialog_id=je->did;

printf("call_id is %d,dialog_id is %d \n",je->cid,je->did);

//回送ack应答消息

eXosip_call_build_ack(ctx,je->did,&ack);

eXosip_call_send_ack(ctx,je->did,ack);

flag1=0; //推出While循环

break;

case EXOSIP_CALL_CLOSED: //a BYE was received for this call

printf("the other sid closed!\n");

break;

case EXOSIP_CALL_ACK: //ACK received for 200ok to INVITE

printf("ACK received!\n");

break;

default: //收到其余应答

printf("other response!\n");

break;

}

eXosip_event_free(je); //Free ressource in an eXosip event

}

break;

case 'h':   //挂断

printf("Holded!\n");

eXosip_lock(ctx);

eXosip_call_terminate(ctx,call_id,dialog_id);

eXosip_unlock(ctx);

break;

case 'c':

printf("This modal is not commpleted!\n");

break;

case 's': //传输INFO方法

eXosip_call_build_info(ctx,dialog_id,&info);

snprintf(tmp,4096,"\nThis is a sip message(Method:INFO)");

osip_message_set_body(info,tmp,strlen(tmp));

//格式能够任意设定,text/plain表明文本信息;

osip_message_set_content_type(info,"text/plain");

eXosip_call_send_request(ctx,dialog_id,info);

break;

case 'm':

//传输MESSAGE方法,也就是即时消息,和INFO方法相比,我认为主要区别是:

//MESSAGE不用创建链接,直接传输信息,而INFO消息必须在创建INVITE的基础上传输

printf("the method : MESSAGE\n");

eXosip_message_build_request(ctx,&message,"MESSAGE",dest_call,source_call,NULL);

//内容,方法,      to       ,from      ,route

snprintf(tmp,4096,"This is a sip message(Method:MESSAGE)");

osip_message_set_body(message,tmp,strlen(tmp));

//假设格式是xml

osip_message_set_content_type(message,"text/xml");

eXosip_message_send_request(ctx,message);

break;

case 'q':

eXosip_quit(ctx);

printf("Exit the setup!\n");

flag=0;

break;

}

}

return(0);

}

UAS.C以下:

# 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 = "sip:140@127.0.0.1";

char *dest_call = "sip:133@127.0.0.1:15060";//client ip

char command;

char tmp[4096];

char localip[128];

int pos = 0;

//初始化sip

struct eXosip_t *ctx;

ctx = eXosip_malloc();

if (ctx==NULL)return -1;

i=eXosip_init(ctx);

if (i != 0)

{

printf ("Can't initialize eXosip!\n");

return -1;

}

else

{

printf ("eXosip_init successfully!\n");

}

i = eXosip_listen_addr (ctx,IPPROTO_UDP, NULL, 15061, AF_INET, 0);

if (i != 0)

{

eXosip_quit (ctx);

fprintf (stderr, "eXosip_listen_addr error!\nCouldn't initialize transport layer!\n");

}

for(;;)

{

//侦听是否有消息到来

je = eXosip_event_wait (ctx,0,50);

//协议栈带有此语句,具体做用未知

eXosip_lock (ctx);

eXosip_default_action (ctx,je);

eXosip_automatic_refresh (ctx);

eXosip_unlock (ctx);

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);

}

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

eXosip_message_build_answer (ctx,je->tid, 200,&answer);

eXosip_message_send_answer (ctx,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 (ctx,je->did);

call_id = je->cid;

dialog_id = je->did;

eXosip_lock (ctx);

eXosip_call_send_answer (ctx,je->tid, 180, NULL);

i = eXosip_call_build_answer (ctx,je->tid, 200, &answer);

if (i != 0)

{

printf ("This request msg is invalid!Cann't response!\n");

eXosip_call_send_answer (ctx,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 (ctx,je->tid, 200, answer);

printf ("send 200 over!\n");

}

eXosip_unlock (ctx);

//显示出在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 (ctx,je->tid, 200, &answer);

if (i != 0)

{

printf ("This request msg is invalid!Cann't response!\n");

eXosip_call_send_answer (ctx,je->tid, 400, NULL);

}

else

{

eXosip_call_send_answer (ctx,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 (ctx);

i = eXosip_call_build_answer (ctx,je->tid, 200, &answer);

if (i == 0)

{

eXosip_call_send_answer (ctx,je->tid, 200, answer);

}

eXosip_unlock (ctx);

{

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");

}

}

}

编译时也多了一个库选项:

gcc uas.c -o uas -losip2 -leXosip2 -lpthread -losipparser2

gcc uac.c -o uac -losip2 -leXosip2 -lpthread -losipparser2

这样就又能编译过了,另外好象网上最新库源码:OSIP2与EXOSIP2不一致,都是2-4.0.0的我编译成功了,版本不一致会报一个错,我没有仔细看过。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值