sipot eX.osip3.0.1在Windows下编译方法及简单UA示例

来源:互联网 发布:dnf端口破解 编辑:程序博客网 时间:2024/04/29 05:33

http://blog.csdn.net/lb_zhao/archive/2007/02/23/1513030.aspx

 

eX.osip3.0.1在Windows下编译方法及简单UA示例
[ 2007-2-3 9:37:00 | By: sipot ]

说明:
1.以下文章中的osip版本为3.0.1
2.eXosip版本为3.0.1
3.编译环境为:Windows XP 专业版本+VS 2005
4.示例程序是在http://blog.csdn.net/bat603/中下载,修改而成(原来是在linux下的示例)
5.如要转载此文章,请说明出处
6.本人也是才接触SIP(呵呵,不到一周),其中一定有很多不对之处,请指正。
第一步,下载:
到http://www.gnu.org/software/osip/下载最新的osip库并解压
到http://savannah.gnu.org/projects/exosip/下载最新的eXsoip库并解压
第二步,编译osip3.0.1:
1.用VS2005打开libosip2-3.0.1/platform/vsnet/osip.sln
2.对osip2和osipparser2项目生成Release DLL
3.其生成的LIB/DLL 位于:libosip2-3.0.1/platform/vsnet/Release DLL/下
第三步,编译eXosip3.0.1:
1.用VS2005打开libeXosip2-3.0.1/platform/vsnet/eXosip.sln
2.将libosip2-3.0.1/include/osip2目录COPY到libeXosip2-3.0.1/include/下
3.将libosip2-3.0.1/include/osipparser2目录COPY到libeXosip2-3.0.1/include/下
4.在libeXosip2-3.0.1目录下新建lib目录
5.将“第二步”中生成的libosip2-3.0.1/platform/vsnet/Release DLL/osip2.lib文件COPY到libeXosip2-3.0.1/lib目录下
6.将“第二步”中生成的libosip2-3.0.1/platform/vsnet/Release DLL/osipparser2.lib文件COPY到libeXosip2-3.0.1/lib目录下
7.修改项目属性,新增Dnsapi.lib Iphlpapi.lib Ws2_32.lib osip2.lib osipparser2.lib库输入
8.修改项目属性,新增库目录../../lib
9.修改项目的输出为.DLL,默认为.lib
10.编译Relase DLL
11.其生成的LIB/DLL 位于:libeXosip2-3.0.1/platform/vsnet/Release/下
第四步,编译示例程序:
将以下程序作为UAS.CPP保存

[Copy to clipboard]
CODE:
// UAS.cpp : 定义控制台应用程序的入口点。
//
#i nclude <eXosip2/eXosip.h>
#i nclude <stdio.h>
#i nclude <stdlib.h>
#i nclude <Winsock2.h>
/*
#i nclude <netinet/in.h>
#i nclude <sys/socket.h>
#i nclude <sys/types.h>*/
#pragma comment(lib, "osip2.lib")
#pragma comment(lib, "osipparser2.lib")
#pragma comment(lib, "eXosip.lib")
#pragma comment(lib, "Iphlpapi.lib")
#pragma comment(lib, "Dnsapi.lib")
#pragma comment(lib, "ws2_32.lib")
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:24@10.16.79.24";
char *dest_call = "sip:24@10.16.79.24:5061";//client ip
char command;
char tmp[4096];
char localip[128];
int pos = 0;
//初始化sip
i = eXosip_init ();
if (i != 0)
{
printf ("Can't initialize eXosip!/n");
return -1;
}
else
{
printf ("eXosip_init successfully!/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");
}
for(;;)
{
//侦听是否有消息到来
je = eXosip_event_wait (0,50);
//协议栈带有此语句,具体作用未知
eXosip_lock ();
eXosip_default_action (je);
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://新的消息到来
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 (je->tid, 200,&answer);
eXosip_message_send_answer (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 (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 ("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: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 (je->tid, 200, answer);
printf ("send 200 over!/n");
}
eXosip_unlock ();

//显示出在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 (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!/n");
}
}
}

将以下程序作为UAC.CPP保存

[Copy to clipboard]
CODE:
// UAC.cpp : 定义控制台应用程序的入口点。
//
#i nclude <eXosip2/eXosip.h>
#i nclude <stdio.h>
#i nclude <stdlib.h>
#i nclude <Winsock2.h>
/*
#i nclude <netinet/in.h>
#i nclude <sys/socket.h>
#i nclude <sys/types.h>*/
#pragma comment(lib, "osip2.lib")
#pragma comment(lib, "osipparser2.lib")
#pragma comment(lib, "eXosip.lib")
#pragma comment(lib, "Iphlpapi.lib")
#pragma comment(lib, "Dnsapi.lib")

#pragma comment(lib, "ws2_32.lib")
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 = "sip:24@10.16.79.24";
char *registerer = "sip:10.16.79.24:5060";//server ip
char *source_call = "sip:24@10.16.79.24";
char *dest_call = "sip:24@10.16.79.24:5060";//server ip

char command;
char tmp[4096];
char localip[128];
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");
//初始化
i = eXosip_init ();
if (i != 0)
{
printf ("Couldn't initialize eXosip!/n");
return -1;
}
else
{
printf ("eXosip_init successfully!/n");
}
i = eXosip_listen_addr (IPPROTO_UDP, NULL, 5061, AF_INET, 0);
if (i != 0)
{
eXosip_quit ();
fprintf (stderr, "Couldn't initialize transport layer!/n");
return -1;
}
flag = 1;
while (flag)
{
printf ("please input the comand:/n");

scanf ("%c", &command);
getchar ();

switch (command)
{
case 'r':
printf ("This modal isn't commpleted!/n");
break;
case 'i':/* INVITE */
i = eXosip_call_build_initial_invite (&invite, dest_call, source_call, NULL, "This si a call for a conversation");
if (i != 0)
{
printf ("Intial INVITE failed!/n");
break;
}
//符合SDP格式,其中属性a是自定义格式,也就是说可以存放自己的信息,但是只能是两列,比如帐户信息
//但是经测试,格式:v o t必不可少,原因未知,估计是协议栈在传输时需要检查的
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 ();
i = eXosip_call_send_initial_invite (invite);
eXosip_unlock ();
flag1 = 1;
while (flag1)
{
je = eXosip_event_wait (0, 200);

if (je == NULL)
{
printf ("No response or the time is over!/n");
break;
}

switch (je->type)
{
case EXOSIP_CALL_INVITE:
printf ("a new invite reveived!/n");
break;
case EXOSIP_CALL_PROCEEDING:
printf ("proceeding!/n");
break;
case EXOSIP_CALL_RINGING:
printf ("ringing!/n");
// call_id = je->cid;
// dialog_id = je->did;
printf ("call_id is %d, dialog_id is %d /n", je->cid, je->did);
break;
case EXOSIP_CALL_ANSWERED:
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);
eXosip_call_build_ack (je->did, &ack);
eXosip_call_send_ack (je->did, ack);
flag1 = 0;
break;
case EXOSIP_CALL_CLOSED:
printf ("the other sid closed!/n");
break;
case EXOSIP_CALL_ACK:
printf ("ACK received!/n");
break;
default:
printf ("other response!/n");
break;
}
eXosip_event_free (je);

}
break;
case 'h':
printf ("Holded !/n");

eXosip_lock ();
eXosip_call_terminate (call_id, dialog_id);
eXosip_unlock ();
break;
case 'c':
printf ("This modal isn't commpleted!/n");
break;
case 's':
//传输INFO方法
eXosip_call_build_info (dialog_id, &info);
snprintf (tmp , 4096,
"hello,rainfish");
osip_message_set_body (info, tmp, strlen(tmp));
//格式可以任意设定,text/plain代表文本信息
osip_message_set_content_type (info, "text/plain");
eXosip_call_send_request (dialog_id, info);
break;
case 'm':
//传输MESSAGE方法,也就是即时消息,和INFO方法相比,我认为主要区别,是MESSAGE不用建立连接,直接传输信息,而INFO必须
//在建立INVITE的基础上传输。
printf ("the mothed :MESSAGE/n");
eXosip_message_build_request (&message, "MESSAGE", dest_call, source_call, NULL);
snprintf (tmp, 4096,
"hellor rainfish");
osip_message_set_body (message, tmp, strlen(tmp));
//假设格式是xml
osip_message_set_content_type (message, "text/xml");
eXosip_message_send_request (message);
break;
case 'q':
eXosip_quit ();
printf ("Exit the setup!/n");
flag = 0;
break;
}
}
return (0);
}

编译这两个程序,需要注意的是:osip/eXosip的头文件路径和第二步/第三步生成出来的LIB库路径应设置对,就OK
第五步,运行示例程序:
1.将第二步/第三步生成出来的三个DLL文件COPY到程序运行目录
2.现在可以运行了!

阅读全文( < src="/count.asp?action=log&id=8988" type="text/javascript"> 6) | 回复(2) | 引用通告(0) | 编辑


/回复:eX.osip3.0.1在Windows下编译方法及简单UA示例
[ 2007-2-3 10:49:00 | By: sipot ]

vc编译及引用osip库
2007-01-22 13:26
本人采用libosip2-2.2.0,vc6.0,Windows xp sp2
因为libosip2-3.x版本文件结构有了一些改变。

解压libosip2-2.2.0.tar到C:/libosip;
在My Project下新建文件夹osip,拷贝C:/libosip/include 文件夹到osip;
在osip下新建Win32 Dynamic-Link Library工程osipparser2,选择An empty DLL project;
退出osipparse2 project;
拷贝C:/libosip/src/osipparse2/文件夹下所有文件到osip/osipparse2/;
拷贝C:/libosip/platform/windows/osipparser2.def文件到osip/osipparse2/;
拷贝C:/libosip/platform/windows/osipparser2.dsp到osip/osipparse2/;
写字板打开osipparse2.dsp,修改所有文件路径:
SOURCE=../../src/osipparser2/ --> SOURCE=./
SOURCE=../../include/osipparser2/ --> SOURCE=../include/osipparser2/
用VC打开osipparse2.dsp,编译生成osipparse2.dll等库文件,在.libs文件夹下。

在osip下新建Win32 Dynamic-Link Library工程osip2,选择An empty DLL project;
tools->option->directories->Library files下添加osipparse2生成的.libs文件夹;
(project->settings->Link->library Modules下添加osipparse2.lib)--应该默认添加了;
退出osip2 project;
拷贝C:/libosip/src/osip2/文件夹下所有文件到osip/osip2/;
拷贝C:/libosip/platform/windows/osip2.def文件到osip/osip2/;
拷贝C:/libosip/platform/windows/osip2.dsp到osip/osip2/;
写字板打开osipparse2.dsp,修改所有文件路径:
SOURCE=../../src/osip2/ --> SOURCE=./
SOURCE=../../include/osip2/ --> SOURCE=../include/osip2/
用VC打开osip2.dsp,编译生成osip2.dll等库文件,在.libs文件夹下。

要使用osip2库需要tools->option->directories->Library files下添加osip2和osipparse2生成的.libs文件夹;
project->settings->Link->library Modules下添加osipparse2.lib, osip2.lib。

编译eXosip.lib是最麻烦的。在VC6下如果没有Platform SDK编译不下去。推荐在VC7下编译。
和上边方法相同。编译完后产生如下链接错误:
eXosip error LNK2019: unresolved external symbol __eXosip_pub_free referenced in function _eXosip_quit
eXosip error LNK2019: unresolved external symbol __eXosip_pub_init referenced in function _eXosip_publish
eXosip error LNK2019: unresolved external symbol __eXosip_pub_find_by_aor referenced in function _eXosip_publish
eXosip error LNK2019: unresolved external symbol __eXosip_pub_update referenced in function _cb_rcv2xx
eXosip fatal error LNK1120: 4 unresolved externals
_eXosip_pub_free等几个函数声明在eXosip2.h中,实现在jpublish.c中。但eXosip.proj没有添加这个文件。添上这个文件就OK。





发表于 @ 2007年02月23日 16:34:00 | 评论( 5 ) | 举报| 收藏
旧一篇:VOIP开源项目源码地址 | 新一篇:犯了一个低级的错误,唉,老了吗?


查看最新精华文章 请访问博客首页
相关文章
timeGetTime
盗取QQ密码
精确时间
写个如何判断IP在某个IP范围的示例代码
eX.osip3.0.1在Windows下编译方法及简单UA示例
osip及eXosip的编译方法
eX.osip3.0.1在Windows下编译方法及简单UA示例
eX.osip3.0.1在Windows下编译方法及简单UA示例(http://blog.csdn.net/lb_zhao/archive/2007/02/23/1513030.aspx)
xiandehai 发表于2007-7-14 19:51:48 举报回复
你好,我(xp+vc2005)按照你的方法进行了osip的安装,但是出现了如下的问题:
osip_port.obj : error LNK2019: 无法解析的外部符号 __imp__CryptReleaseContext@8,该符号在函数 _osip_build_random_number 中被引用
osip_port.obj : error LNK2019: 无法解析的外部符号 __imp__CryptGenRandom@12,该符号在函数 _osip_build_random_number 中被引用
osip_port.obj : error LNK2019: 无法解析的外部符号 __imp__CryptAcquireContextA@20,该符号在函数 _osip_build_random_number 中被引用
Release DLL/osipparser2.dll : fatal error LNK1120: 3 个无法解析的外部命令
你碰过这种情况吗?我在网上没找到解决的办法.
chinajaderiver 发表于2007-7-26 14:48:06 举报回复
望指教!
我按照您的方法尝试了很多遍!
出现的错误情况是:
../../src/eXtl_tls.c(30) : fatal error C1083: 无法打开包括文件:“openssl/ssl.h”: No such file or directory
...
../../src/eXtl_dtls.c(30) : fatal error C1083: 无法打开包括文件:“openssl/ssl.h”: No such file or directory
也就是无法加载<openssl>下的所有“*.h”文件!这是什么原因呢?!我编译osip的时候并没有生成这样的一个文件夹啊!
而Studio中也没有这样的文件!这是怎么回事呢?这个文件的用处又是什么呢?
我是用的是WindowsXP-Visual Studio 2005
使用libosip2-3.0.3和libeXosip2-3.0.3
我刚开始接触sip,是非常新的新手...郁闷中!
希望您能够不吝赐教!感激万分!
myearth 发表于2007-8-23 17:42:44 举报回复
望指教!
我按照您的方法尝试了很多遍!
错误 7 error LNK2019: 无法解析的外部符号 __snprintf,该符号在函数 _main 中被引用 uas.obj
错误 8 error LNK2019: 无法解析的外部符号 _eXosip_call_build_answer,该符号在函数 _main 中被引用 uas.obj
错误 9 error LNK2019: 无法解析的外部符号 _eXosip_call_send_answer,该符号在函数 _main 中被引用 uas.obj
错误 10 error LNK2019: 无法解析的外部符号 _eXosip_get_remote_sdp,该符号在函数 _main 中被引用 uas.obj
错误 11 error LNK2019: 无法解析的外部符号 _eXosip_message_send_answer,该符号在函数 _main 中被引用 uas.obj
错误 12 error LNK2019: 无法解析的外部符号 _eXosip_message_build_answer,该符号在函数 _main 中被引用 uas.obj

等20个错误,什么原因,请指教!
zhejichensha 发表于2007-8-29 10:26:13 举报回复
我也碰到了楼上一样的错误
关键原因可能是eXosip2.def
中没有导出eXosip_call_build_answer
eXosip_call_send_answer等函数,可以尝试敢下eXosip2.def
在库中包含eXosip_call_send_answer等函数!
wuyu637 发表于2007-9-28 10:45:22 举报回复
openssl/ssl.h是用了加密的一个安全库,如果操作系统中没有安转就会出现这样的警告,可以在头文件中加上一个
#undef HAVE_OPENSSL_SSL_H
就可以编译通过了,

link2019这种错误大部分是因为没有找到需要的连接文件导致的,其实楼主已经说得很清楚了。

原创粉丝点击