⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uas.c

📁 user agent server源代码,
💻 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 + -