📄 uas.c
字号:
/******************************************
编译方法:
gcc xxx.c -o xxx -leXosip2
****************************************/
/*******************UAS*****************************************************
本文可以任意转载,但必须保留出处
作者:rainfish
网址:http://blog.csdn.net/bat603/
测试环境:eXosip3.0.1/redhat AS 4
***************************************************************************/
//#include </root/libeXosip2-3.0.2/include/eXosip2/eXosip.h>
//#include </root/libosip2-3.0.1/include/osip2/osip_mt.h>
#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>
#define PORT 40000
char *sour_call = "sip:36@192.168.1.16";
char *dest_call = "sip:36@192.168.1.16:40000"; //client ip
eXosip_event_t *je = NULL;
int mInviteResponse(void);
int mRegisterResponse( void );
int mIniteXosip(void);
int main (int argc, char *argv[])
{
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 command;
char tmp[4096];
char localip[128];
int pos = 0;
//initialize SIP
if ( mIniteXosip()==-1 ) return -1;
for(;;)
{
//侦听是否有消息到来
je = eXosip_event_wait(0, 50);
//协议栈带有此语句,具体作用未知
eXosip_lock();
// Retry with credentials upon reception of 401/407.
// Retry with Contact header upon reception of 3xx request.
eXosip_default_action(je);
// Refresh REGISTER and SUBSCRIBE before the expiration delay.
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: //新的消息到来
mRegisterResponse();
break;
case EXOSIP_REGISTRATION_NEW:/**< announce new registration.*/
eXosip_message_build_answer(je->tid, 200,&answer);
eXosip_call_send_answer(je->tid, 200, answer);
printf("register successfully.\n");
break;
case EXOSIP_REGISTRATION_SUCCESS://success to register
printf("register success.\n");
break;
case EXOSIP_REGISTRATION_FAILURE://failure to register
printf("register failure.\n");
break;
case EXOSIP_CALL_INVITE:
mInviteResponse();
break;
case EXOSIP_CALL_ACK:
printf("ACK recieved!\n\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: %d!\n", je->type);
}
eXosip_event_free(je);
}
return 0;
}
int mInviteResponse(void)
{
osip_message_t *ack = NULL;
sdp_message_t *remote_sdp = NULL;
osip_message_t *answer = NULL;
sdp_attribute_t*at;
int call_id, dialog_id;
int i;
char tmp[4096];
int pos = 0;
printf("recieve invite.\n");
//得到接收到消息的具体信息
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 );
call_id = je->cid;
dialog_id = je->did;
printf( "call_id is %d, dialog_id is %d, tid is %d\n",
call_id,
dialog_id,
je->tid );
eXosip_lock();
printf("Send 180......\n");
eXosip_call_send_answer(je->tid, 180, NULL);
printf("Bind answer(200)......\n");
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:server: rainfish\r\n"
"a=password:server: 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格式.
remote_sdp = eXosip_get_remote_sdp(je->did);
//显示出在sdp消息体中的 attribute 的内容,里面计划存放我们的信息
printf("the INFO is :\n");
while( !osip_list_eol(&remote_sdp->a_attributes, pos) )//modified by xulan
{
at = (sdp_attribute_t *)osip_list_get(&remote_sdp->a_attributes, pos);
//这里解释了为什么在SDP消息体中属性a里面存放必须是两列
printf("%s : %s\n", at->a_att_field, at->a_att_value);
pos ++;
}
}
int mRegisterResponse( void )
{
osip_body_t *body;
osip_message_t *answer = NULL;
printf("EXOSIP_MESSAGE_NEW!\n");
if(MSG_IS_MESSAGE(je->request)) //如果接受到的消息类型是MESSAGE
{
osip_message_get_body(je->request, 0, &body);
printf("I get the msg is: %s\n", body->body);
//按照规则,需要回复200 OK信息
printf("begin to send message 200\n");
eXosip_lock();
eXosip_message_build_answer(je->tid, 200,&answer);
eXosip_message_send_answer(je->tid, 200,answer);
eXosip_unlock();
printf("send end.\n");
}
else if(MSG_IS_REGISTER(je->request)) //判断是否是注册信息
{
printf("username = %s, password = %s\n",
je->request->req_uri->username, je->request->req_uri->password);
printf("binld answer(200)...\n");
eXosip_message_build_answer(je->tid, 200, &answer);
printf("send answer(200)...\n");
eXosip_message_send_answer(je->tid, 200, answer);
}
return 0;
}
int mIniteXosip(void)
{
int i;
i = eXosip_init();
if (i != 0)
{
printf("Can't initialize eXosip!\n");
return -1;
}
else
{
printf("eXosip_init successfully!\n===============================\n");
}
i = eXosip_listen_addr(IPPROTO_UDP, NULL, 5060, AF_INET, 0);
if (i != 0)
{
eXosip_quit();
fprintf(stderr, "eXosip_listen_addr error!\nCouldn't initialize transport layer!\n");
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -