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

    技术2022-05-11  63

    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.现在可以运行了!   阅读全文( <script src="/count.asp?action=log&id=8988" type="text/javascript"></script> 6) | 回复(2) | 引用通告(0) | 编辑   .style3 {color: #006699}  /回复: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_quiteXosip error LNK2019: unresolved external symbol __eXosip_pub_init referenced in function _eXosip_publisheXosip error LNK2019: unresolved external symbol __eXosip_pub_find_by_aor referenced in function _eXosip_publisheXosip error LNK2019: unresolved external symbol __eXosip_pub_update referenced in function _cb_rcv2xxeXosip fatal error LNK1120: 4 unresolved externals_eXosip_pub_free等几个函数声明在eXosip2.h中,实现在jpublish.c中。但eXosip.proj没有添加这个文件。添上这个文件就OK。


    最新回复(0)