linux下编译eXosip、osip,以及UAC和UAS的例子

从网站上看到了这样的一篇博文 :Windows下编译eXosip、osip,以及UAC和UAS的例子  (链接:http://www.cnblogs.com/dyllove98/archive/2013/06/25/3155427.html)

觉得对学习sip的初学者,包括我,都是很有帮助的。但是那是在window下的编译,我在这里稍微改了一下,让它支持在linux下编译测试运行通过。

我们这里使用库的版本:libosip2-3.6.0.tar,libeXosip2-3.6.0.tar,大家可以自己进入正面的链接去下载。

osip:   http://ftp.twaren.net/Unix/NonGNU//osip/libosip2-3.6.0.tar.gz
eXosip: http://download.savannah.gnu.org/releases/exosip/libeXosip2-3.6.0.tar.gz

  1、解压libosip2-3.6.0.tar ,比如解压目录为 /usr/local/src/,
        #tar zxvf libosip2-3.6.0.tar -C /usr/local/src

        编译该lib库:
        #./configure
        #make
        #make install

  2、同理编译libeXosip2
      注意最后要更新库,否则在程序执行时,可能会提示找不到库,编译后的库文件及头文件会默认放在/usr/local目录下:
      #ldconfig

  3、编译代码uac.c 和 uas.c
       #gcc uac.c -o uac -losip2 -leXosip2 -lpthread
       #gcc uas.c -o uas -losip2 -leXosip2 -lpthread

  4、测试运行uas 和 uac,最好打开两个shell来运行
       #./uas
       #./uac
       注意:如果在运行过程中提示找不到libosip2.so.6等类似的提示,说明osip动态库的路径可能还没有包含进去,可以使用下面的命令手动包含动态库的路径
       #export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

代码uac.c

  1 #include <eXosip2/eXosip.h>

  2 #include <stdio.h>

  3 #include <stdlib.h>

  4 #include <stdarg.h>

  5 #include <netinet/in.h>

  6 //#include <winsock2.h>

  7 

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

  9 {

 10 

 11     struct eXosip_t *context_eXosip;

 12 

 13     eXosip_event_t *je;

 14     osip_message_t *reg=NULL;

 15     osip_message_t *invite=NULL;

 16     osip_message_t *ack=NULL;

 17     osip_message_t *info=NULL;

 18     osip_message_t *message=NULL;

 19 

 20     int call_id,dialog_id;

 21     int i,flag;

 22     int flag1=1;

 23 

 24     char *identity="sip:[email protected]";   //UAC1,端口是15060

 25     char *registar="sip:[email protected]:15061"; //UAS,端口是15061

 26     char *source_call="sip:[email protected]";

 27     char *dest_call="sip:[email protected]:15061";

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

 29     //在这个例子中,uac和uas通信,则source就是自己的地址,而目的地址就是uac1的地址

 30     char command;

 31     char tmp[4096];

 32 

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

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

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

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

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

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

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

 40 

 41     //初始化

 42     i=eXosip_init();

 43 

 44     if(i!=0)

 45     {

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

 47         return -1;

 48     }

 49     else

 50     {

 51         printf("eXosip_init successfully!\n");

 52     }

 53 

 54     //绑定uac自己的端口15060,并进行端口监听

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

 56     if(i!=0)

 57     {

 58         eXosip_quit();

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

 60         return -1;

 61     }

 62     flag=1;

 63 

 64     while(flag)

 65     {

 66         //输入命令

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

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

 69         getchar();

 70 

 71         switch(command)

 72         {

 73         case 'r':

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

 75             break;

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

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

 78             if(i!=0)

 79             {

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

 81                 break;

 82             }

 83             //符合SDP格式,其中属性a是自定义格式,也就是说可以存放自己的信息,

 84             //但是只能有两列,比如帐户信息

 85             //但是经过测试,格式vot必不可少,原因未知,估计是协议栈在传输时需要检查的

 86             snprintf(tmp,4096,

 87                       "v=0\r\n"

 88                       "o=anonymous 0 0 IN IP4 0.0.0.0\r\n"

 89                       "t=1 10\r\n"

 90                       "a=username:rainfish\r\n"

 91                       "a=password:123\r\n");

 92 

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

 94             osip_message_set_content_type(invite,"application/sdp");

 95 

 96             eXosip_lock();

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

 98             eXosip_unlock();

 99 

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

101             flag1=1;

102             while(flag1)

103             {

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

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

106                 if(je==NULL)

107                 {

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

109                     break;

110                 }

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

112                 {

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

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

115                     break;

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

117                     printf("proceeding!\n");

118                     break;

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

120                     printf("ringing!\n");

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

122                     break;

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

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

125                     call_id=je->cid;

126                     dialog_id=je->did;

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

128 

129                     //回送ack应答消息

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

131                     eXosip_call_send_ack(je->did,ack);

132                     flag1=0; //推出While循环

133                     break;

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

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

136                     break;

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

138                     printf("ACK received!\n");

139                     break;

140                 default: //收到其他应答

141                     printf("other response!\n");

142                     break;

143                 }

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

145             }

146             break;

147 

148         case 'h':   //挂断

149             printf("Holded!\n");

150 

151             eXosip_lock();

152             eXosip_call_terminate(call_id,dialog_id);

153             eXosip_unlock();

154             break;

155 

156         case 'c':

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

158             break;

159 

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

161             eXosip_call_build_info(dialog_id,&info);

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

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

164             //格式可以任意设定,text/plain代表文本信息;

165             osip_message_set_content_type(info,"text/plain");

166             eXosip_call_send_request(dialog_id,info);

167             break;

168 

169         case 'm':

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

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

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

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

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

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

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

177             //假设格式是xml

178             osip_message_set_content_type(message,"text/xml");

179             eXosip_message_send_request(message);

180             break;

181 

182         case 'q':

183             eXosip_quit();

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

185             flag=0;

186             break;

187         }

188     }

189 

190     return(0);

191 }

代码uas.c

  1 # include <eXosip2/eXosip.h>

  2 # include <stdio.h>

  3 # include <stdlib.h>

  4 # include <stdarg.h>

  5 # include <netinet/in.h>

  6 

  7 //# include <Winsock2.h>

  8 

  9 

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

 11 {

 12     eXosip_event_t *je = NULL;

 13     osip_message_t *ack = NULL;

 14     osip_message_t *invite = NULL;

 15     osip_message_t *answer = NULL;

 16     sdp_message_t *remote_sdp = NULL;

 17     int call_id, dialog_id;

 18     int i,j;

 19     int id;

 20     char *sour_call = "sip:[email protected]";

 21     char *dest_call = "sip:[email protected]:15060";//client ip

 22     char command;

 23     char tmp[4096];

 24     char localip[128];

 25     int pos = 0;

 26     //初始化sip

 27     i = eXosip_init ();

 28     if (i != 0)

 29     {

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

 31         return -1;

 32     }

 33     else

 34     {

 35         printf ("eXosip_init successfully!\n");

 36     }

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

 38     if (i != 0)

 39     {

 40         eXosip_quit ();

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

 42     }

 43     for(;;)

 44     {

 45         //侦听是否有消息到来

 46         je = eXosip_event_wait (0,50);

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

 48         eXosip_lock ();

 49         eXosip_default_action (je);

 50         eXosip_automatic_refresh ();

 51         eXosip_unlock ();

 52         if (je == NULL)//没有接收到消息

 53             continue;

 54         // printf ("the cid is %s, did is %s/n", je->did, je->cid);

 55         switch (je->type)

 56         {

 57         case EXOSIP_MESSAGE_NEW://新的消息到来

 58             printf (" EXOSIP_MESSAGE_NEW!\n");

 59             if (MSG_IS_MESSAGE (je->request))//如果接受到的消息类型是MESSAGE

 60             {

 61                 {

 62                     osip_body_t *body;

 63                     osip_message_get_body (je->request, 0, &body);

 64                     printf ("I get the msg is: %s\n", body->body);

 65                     //printf ("the cid is %s, did is %s/n", je->did, je->cid);

 66                 }

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

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

 69                 eXosip_message_send_answer (je->tid, 200,answer);

 70             }

 71             break;

 72         case EXOSIP_CALL_INVITE:

 73             //得到接收到消息的具体信息

 74             printf ("Received a INVITE msg from %s:%s, UserName is %s, password is %s\n",je->request->req_uri->host,

 75                     je->request->req_uri->port, je->request->req_uri->username, je->request->req_uri->password);

 76             //得到消息体,认为该消息就是SDP格式.

 77             remote_sdp = eXosip_get_remote_sdp (je->did);

 78             call_id = je->cid;

 79             dialog_id = je->did;

 80 

 81             eXosip_lock ();

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

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

 84             if (i != 0)

 85             {

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

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

 88             }

 89             else

 90             {

 91                 snprintf (tmp, 4096,

 92                           "v=0\r\n"

 93                           "o=anonymous 0 0 IN IP4 0.0.0.0\r\n"

 94                           "t=1 10\r\n"

 95                           "a=username:rainfish\r\n"

 96                           "a=password:123\r\n");

 97 

 98                 //设置回复的SDP消息体,下一步计划分析消息体

 99                 //没有分析消息体,直接回复原来的消息,这一块做的不好。

100                 osip_message_set_body (answer, tmp, strlen(tmp));

101                 osip_message_set_content_type (answer, "application/sdp");

102 

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

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

105             }

106             eXosip_unlock ();

107 

108             //显示出在sdp消息体中的attribute 的内容,里面计划存放我们的信息

109             printf ("the INFO is :\n");

110             while (!osip_list_eol ( &(remote_sdp->a_attributes), pos))

111             {

112                 sdp_attribute_t *at;

113 

114                 at = (sdp_attribute_t *) osip_list_get ( &remote_sdp->a_attributes, pos);

115                 printf ("%s : %s\n", at->a_att_field, at->a_att_value);//这里解释了为什么在SDP消息体中属性a里面存放必须是两列

116 

117                 pos ++;

118             }

119             break;

120         case EXOSIP_CALL_ACK:

121             printf ("ACK recieved!\n");

122             // printf ("the cid is %s, did is %s/n", je->did, je->cid);

123             break;

124         case EXOSIP_CALL_CLOSED:

125             printf ("the remote hold the session!\n");

126             // eXosip_call_build_ack(dialog_id, &ack);

127             //eXosip_call_send_ack(dialog_id, ack);

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

129             if (i != 0)

130             {

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

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

133 

134             }

135             else

136             {

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

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

139             }

140             break;

141         case EXOSIP_CALL_MESSAGE_NEW://至于该类型和EXOSIP_MESSAGE_NEW的区别,源代码这么解释的

142             /*

143             // request related events within calls (except INVITE)

144                   EXOSIP_CALL_MESSAGE_NEW,          < announce new incoming request.

145             // response received for request outside calls

146                      EXOSIP_MESSAGE_NEW,          < announce new incoming request.

147                      我也不是很明白,理解是:EXOSIP_CALL_MESSAGE_NEW是一个呼叫中的新的消息到来,比如ring trying都算,所以在接受到后必须判断

148                      该消息类型,EXOSIP_MESSAGE_NEW而是表示不是呼叫内的消息到来。

149                      该解释有不妥地方,仅供参考。

150             */

151             printf(" EXOSIP_CALL_MESSAGE_NEW\n");

152             if (MSG_IS_INFO(je->request) ) //如果传输的是INFO方法

153             {

154                 eXosip_lock ();

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

156                 if (i == 0)

157                 {

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

159                 }

160                 eXosip_unlock ();

161                 {

162                     osip_body_t *body;

163                     osip_message_get_body (je->request, 0, &body);

164                     printf ("the body is %s\n", body->body);

165                 }

166             }

167             break;

168         default:

169             printf ("Could not parse the msg!\n");

170         }

171     }

172 }

运行截图:

uac运行结果:

uas运行结果:

你可能感兴趣的:(linux)