linux下編譯eXosip、osip,以及UAC和UAS的例子

從網站上看到了這樣的一篇博文 :Windows下編譯eXosip、osip,以及UAC和UAS的例子  (連接:http://www.cnblogs.com/dyllove98/archive/2013/06/25/3155427.html)html

以爲對學習sip的初學者,包括我,都是頗有幫助的。可是那是在window下的編譯,我在這裏稍微改了一下,讓它支持在linux下編譯測試運行經過。linux

咱們這裏使用庫的版本:libosip2-3.6.0.tar,libeXosip2-3.6.0.tar,你們能夠本身進入正面的連接去下載。shell

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
服務器

  一、解壓libosip2-3.6.0.tar ,好比解壓目錄爲 /usr/local/src/,
        #tar zxvf libosip2-3.6.0.tar -C /usr/local/srcsession

        編譯該lib庫:
        #./configure
        #make
        #make installapp

  二、同理編譯libeXosip2
      注意最後要更新庫,不然在程序執行時,可能會提示找不到庫,編譯後的庫文件及頭文件會默認放在/usr/local目錄下:
      #ldconfigide

  三、編譯代碼uac.c 和 uas.c
       #gcc uac.c -o uac -losip2 -leXosip2 -lpthread
       #gcc uas.c -o uas -losip2 -leXosip2 -lpthreadpost

  四、測試運行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:140@127.0.0.1";   //UAC1,端口是15060
 25     char *registar="sip:133@127.0.0.1:15061"; //UAS,端口是15061
 26     char *source_call="sip:140@127.0.0.1";
 27     char *dest_call="sip:133@127.0.0.1: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:140@127.0.0.1";
 21     char *dest_call = "sip:133@127.0.0.1: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運行結果:

相關文章
相關標籤/搜索