eXosip实现sip uac
- 格式:docx
- 大小:17.86 KB
- 文档页数:8
VOLTE-SIP完整信令解析1.主叫与被之间的SIPSIPSIP呼叫业务流程如下:呼叫业务流程如下:2. SIP信令完整解析:(1). 用户 A ,摘机对用户 B 发起呼叫,用户 A 首先向 AS 服务器发起 INVITE 请求。
(2). AS 服务器回复 100 Trying 给用户 A 说明收到 INVITE 请求。
(3). AS 服务器通过认证确认用户认证已通过后,向被叫终端 B 转送 INVITE 请求。
(4). 用户 B 向 AS 服务器送呼叫处理中的应答消息, 100 Trying 。
(5). 用户 B 向 AS 服务器送 183 Session Progress 消息,提示建立对话的进度信息。
(此时被叫 QCI1 专用承载建立)(6). AS 服务器向主叫终端 A 转送 183 Session Progress 消息,终端 A 了解到整个 Session 的建立进度消息。
(7). 终端A 向AS 服务器回复临时应答消息PRACK ,表示收到183 Session Progress 消息。
(此时主叫 QCI1 专用承载建立)(8). AS 服务器向被叫终端 B 转送临时应答消息 PRACK ,终端 B 了解到终端 A 收到 183 Session Progress 消息。
(9). 被叫终端B 向AS 服务器发送200 OK 消息,表示183 Session Progress 请求已经处理成功。
(10). AS 服务器向主叫终端 A 转送 200 OK 消息。
(11). 主叫终端 A 向 AS 服务器发送 UPDATE 消息,意在与被叫终端 B 协商相关 SDP 信息。
(12). AS 服务器向被叫终端 B 转送 UPDATE 消息。
(13). 被叫终端 B 向 AS 服务器发送 200 OK 消息,表示 UPDATE 请求已经处理成功。
( 14). AS 服务器向主叫用户 A 转送 200 OK 消息,通知用户 AUPDATE 请求已经处理成功。
一个基于exosip的软电话例子exosip针对UA是对osip进行扩展,oSIP不提供任何快速产生请求消息和响应消息的方法,所有请求消息和响应消息的形成必须调用一组sip message api来手动组装完成,所以作者在osip上基础上开发了exosip,用exosip开发软电话非常方便,仅需几个API就可以完成.exosip 中附带一个例子:josua,不过josua相对复杂了点,下面给出一个最简单的例子供大家参考,因为例子实在太简单所以没有给出注释,用到exosip的API的参数请参看exosip源代码,看懂这个例子再研究josua就很简单了.我使用的是osip 2.0.9+exosip 0.77.#include "assert.h"#include <conio.h>#include <iostream>#include <osip2/osip_mt.h>#include <eXosip/eXosip.h>#include <eXosip/eXosip_cfg.h>using namespace std;class jcall;class jcall {public:int cid;int did;char reason_phrase[50];int status_code;char textinfo[256];char req_uri[256];char local_uri[256];char remote_uri[256];char subject[256];char remote_sdp_audio_ip[50];int remote_sdp_audio_port;int payload;char payload_name[50];int state;jcall() {}int build(eXosip_event_t *je){jcall *ca = this;ca->cid = je->cid;ca->did = je->did;if (ca->did<1 && ca->cid<1){assert(0);return -1; /* not enough information for this event?? */}osip_strncpy(ca->textinfo, je->textinfo, 255);osip_strncpy(ca->req_uri, je->req_uri, 255);osip_strncpy(ca->local_uri, je->local_uri, 255);osip_strncpy(ca->remote_uri, je->remote_uri, 255);osip_strncpy(ca->subject, je->subject, 255);if (ca->remote_sdp_audio_ip[0]=='\0'){osip_strncpy(ca->remote_sdp_audio_ip, je->remote_sdp_audio_ip, 49); ca->remote_sdp_audio_port = je->remote_sdp_audio_port;ca->payload = je->payload;osip_strncpy(ca->payload_name, je->payload_name, 49);}if (je->reason_phrase[0]!='\0'){osip_strncpy(ca->reason_phrase, je->reason_phrase, 49);ca->status_code = je->status_code;}ca->state = je->type;return 0;}};jcall call;void __exit( int r ){char line[256];gets( line );exit( r );}void josua_printf(char* buf){printf( "\n" );}int josua_event_get(){int counter =0;/* use events to print some info */eXosip_event_t *je;for (;;){char buf[100];je = eXosip_event_wait(0,50);if (je==NULL)break;counter++;if (je->type==EXOSIP_CALL_NEW){printf( "<- (%i %i) INVITE from: %s",je->cid, je->did,je->remote_uri);josua_printf(buf);call.build(je);}else if (je->type==EXOSIP_CALL_ANSWERED) {printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_CALL_PROCEEDING) {printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,josua_printf(buf);}else if (je->type==EXOSIP_CALL_RINGING){printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_CALL_REDIRECTED){printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_CALL_REQUESTFAILURE) {printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_CALL_SERVERFAILURE) {printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_CALL_GLOBALFAILURE) {printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_CALL_CLOSED){printf( "<- (%i %i) BYE from: %s",je->cid, je->did, je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_CALL_HOLD){printf( "<- (%i %i) INVITE (On Hold) from: %s",je->cid, je->did, je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_CALL_OFFHOLD){printf( "<- (%i %i) INVITE (Off Hold) from: %s",je->cid, je->did, je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_REGISTRATION_SUCCESS) {printf( "<- (%i) [%i %s] %s for REGISTER %s",je->rid,je->status_code,je->reason_phrase,je->remote_uri,je->req_uri);josua_printf(buf);}else if (je->type==EXOSIP_REGISTRATION_FAILURE) {printf( "<- (%i) [%i %s] %s for REGISTER %s",je->rid,je->status_code,je->reason_phrase,je->remote_uri,je->req_uri);josua_printf(buf);}else if (je->type==EXOSIP_OPTIONS_NEW){printf( "<- (%i %i) OPTIONS from: %s",je->cid, je->did,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_OPTIONS_ANSWERED){printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_OPTIONS_PROCEEDING){printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_OPTIONS_REDIRECTED){printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_OPTIONS_REQUESTFAILURE) {printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_OPTIONS_SERVERFAILURE) {printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_OPTIONS_GLOBALFAILURE) {printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_INFO_NEW){printf( "<- (%i %i) INFO from: %s",je->cid, je->did,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_INFO_ANSWERED){printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_INFO_PROCEEDING){printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_INFO_REDIRECTED)printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_INFO_REQUESTFAILURE){printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_INFO_SERVERFAILURE){printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_INFO_GLOBALFAILURE){printf( "<- (%i %i) [%i %s] %s",je->cid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_SUBSCRIPTION_ANSWERED) {printf( "<- (%i %i) [%i %s] %s for SUBSCRIBE",je->sid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);printf( "<- (%i %i) online=%i [status: %i reason:%i]",je->sid, je->did,je->online_status,je->ss_status,je->ss_reason);josua_printf(buf);}else if (je->type==EXOSIP_SUBSCRIPTION_PROCEEDING){printf( "<- (%i %i) [%i %s] %s for SUBSCRIBE",je->sid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_SUBSCRIPTION_REDIRECTED){printf( "<- (%i %i) [%i %s] %s for SUBSCRIBE",je->sid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_SUBSCRIPTION_REQUESTFAILURE) {printf( "<- (%i %i) [%i %s] %s for SUBSCRIBE",je->sid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_SUBSCRIPTION_SERVERFAILURE) {printf( "<- (%i %i) [%i %s] %s for SUBSCRIBE",je->sid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_SUBSCRIPTION_GLOBALFAILURE){printf( "<- (%i %i) [%i %s] %s for SUBSCRIBE",je->sid, je->did,je->status_code,je->reason_phrase,je->remote_uri);josua_printf(buf);}else if (je->type==EXOSIP_SUBSCRIPTION_NOTIFY){printf( "<- (%i %i) NOTIFY from: %s",je->sid, je->did,je->remote_uri);josua_printf(buf);printf( "<- (%i %i) online=%i [status: %i reason:%i]",je->sid, je->did,je->online_status,je->ss_status,je->ss_reason);josua_printf(buf);}else if (je->type==EXOSIP_IN_SUBSCRIPTION_NEW){printf( "<- (%i %i) SUBSCRIBE from: %s",je->nid, je->did,je->remote_uri);josua_printf(buf);/* search for the user to see if he has beenpreviously accepted or not! */eXosip_notify(je->did, EXOSIP_SUBCRSTATE_PENDING,EXOSIP_NOTIFY_AWAY);}else if (je->textinfo[0]!='\0'){printf( "(%i %i %i %i) %s", je->cid, je->sid, je->nid, je->did, je->textinfo); josua_printf(buf);}eXosip_event_free(je);}if (counter>0)return 0;return -1;}int main(int argc, char* argv[]){int i;memset( &call, 0, sizeof(call) );cout << "Usage:"<< endl;cout << "a - answering call"<< endl;cout << "h - hangup"<< endl;cout << "r - ringing"<< endl;cout << "c - call"<< endl;cout << "q - quit"<< endl;FILE* logfile = fopen( "logfile.txt", "w");// osip_trace_initialize( (_trace_level)0, logfile );// osip_trace_initialize( (_trace_level)8, stdout );i = eXosip_init(stdin, stdout, 5060);if (i!=0){fprintf (stderr, "test: could not initialize eXosip\n"); __exit(0);}eXosip_sdp_negotiation_remove_audio_payloads(); eXosip_sdp_negotiation_add_codec(osip_strdup("0"), NULL,osip_strdup("RTP/AVP"),NULL, NULL, NULL,NULL,NULL,osip_strdup("0 PCMU/8000"));eXosip_sdp_negotiation_add_codec(osip_strdup("8"), NULL,osip_strdup("RTP/AVP"),NULL, NULL, NULL,NULL,NULL,osip_strdup("8 PCMA/8000"));/* register callbacks? */eXosip_set_mode(EVENT_MODE);osip_message_t *invite;i = eXosip_build_initial_invite(&invite,"sip:192.168.197.5:5060", //被叫对IP"sip:192.168.197.254:5060", //自己IPNULL,"oSIP phone");if (i!=0){fprintf (stderr, "eXosip_build_initial_invite failed\n"); __exit(0);}cout << "oSIP>";bool run = true;while( run ){josua_event_get();if ( _kbhit() ){switch ( _getch() ){case 'a':cout << "answer"<< endl;eXosip_lock();eXosip_answer_call(call.did, 200, 0);eXosip_unlock();break;case 'h':cout << "hangup"<< endl;eXosip_lock();eXosip_terminate_call( call.cid, call.did );eXosip_unlock();break;case 'r':cout << "ringing"<< endl;eXosip_lock();eXosip_answer_call(call.did, 180, 0);eXosip_unlock();break;case 'c':cout << "call"<< endl;eXosip_lock();eXosip_initiate_call(invite, NULL, NULL, "10500"); eXosip_unlock();break;case 'q':cout << "quit"<< endl;run = false;break;default :cout << "\noSIP>";}}}return 0;}。
一个用eXosip实现的UAC和UAS的例子经过一段时间的学习,对sip总算有了一点认识,在学习过程中,遇到了太多的问题,郁闷过,惆怅过,但是一咬牙,还是过来了。
令我感动的是,在网上遇到一些很热心的朋友,不厌其烦地给我以解惑,感谢他们,尤其是友善的大狗,呵呵,希望将来有一天他能看到这篇文章。
我是利用eXosip协议栈进行开发的,网上有一篇<一个简单的sip呼叫例子>,写的不错,但是好像有一些问题,而对于初学者来说,能拿到一个好的例子,对sip的理解可以到达事半功倍的效果。
于是便把自己的写的例子拿出来,让大家参考一下,若有问题,欢迎指正。
只需把里面的IP地址改正、编译即可使用。
/******************************************编译方法:gcc xxx.c -o xxx -leXosip2****************************************//*******************UAS*****************************************************本文可以任意转载,但必须保留出处作者:rainfish网址:/bat603/测试环境:eXosip3.0.1/redhat AS 4***************************************************************************/#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>intmain (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:133@192.168.0.133";char *dest_call = "sip:140@192.168.0.140:5060";char command;char tmp[4096];char localip[128];int pos = 0;//初始化sipi = 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);}//按照规则,需要回复200 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消息体,下一步计划分析消息体//没有分析消息体,直接回复原来的消息,这一块做的不好。
exosip2 交叉编译
exosip2 是一个基于SIP 协议的开源库,用于实现SIP 客户端和服务器端应用程序的开发。
交叉编译(Cross-compilation)是指在一种平台上生成另一种平台的可执行代码,比如在一台操作系统上生成另一种操作系统的可执行文件。
针对exosip2 进行交叉编译的步骤可能会因为环境和目标平台而有所不同,以下是一般情况下的基本步骤:
步骤概述:
准备交叉编译工具链:首先要获取针对目标平台的交叉编译工具链,这包括交叉编译器、交叉编译时所需的库和头文件等。
配置exosip2:在交叉编译环境中,使用配置工具或手动配置,设置exosip2 库的构建选项和参数,指定交叉编译工具链。
生成Makefile 或构建脚本:针对所配置的交叉编译环境,生成适用于交叉编译的Makefile 或构建脚本。
执行编译:运行Makefile 或构建脚本,执行编译过程。
这将使用交叉编译工具链生成适用于目标平台的可执行文件或库。
注意事项:
交叉编译工具链:确保选择正确的交叉编译工具链,与目标平台的架构和操作系统间相匹配。
配置选项:在配置exosip2 时,需要确保设置了正确的交叉编译工具链路径和其他必要的选项。
环境依赖:确保交叉编译环境中已经安装了目标平台所需的库和依赖项。
这些步骤只是一个大致的指导,具体的步骤和命令可能会因为具体环境和目标平台而有所不同。
在进行交叉编译前,最好查阅exosip2的官方文档或相关的交叉编译指南,以获得更详细和准确的步骤。
exosip和osip是两种常用于SIP(会话初始协议)协议栈实现的开源软件库,它们可以帮助开发人员在其应用程序中实现基于SIP协议的通信功能。
在某些情况下,由于开发环境的限制,我们可能需要进行交叉编译来将这些库移植到不同的评台上,本文将重点介绍如何使用交叉编译工具来将exosip和osip库移植到目标评台上。
1. 了解交叉编译的基本概念在开始介绍如何进行exosip和osip库的交叉编译之前,我们首先需要了解一些基本的概念。
交叉编译是指在一种评台上开发、编译出在另一种不同的评台上运行的应用程序的过程。
在实际应用中,我们可能需要在PC机上编译出在嵌入式评台上运行的程序,这就需要用到交叉编译工具链。
2. 准备交叉编译工具链在进行交叉编译之前,我们需要先准备好交叉编译工具链。
交叉编译工具链包括交叉编译器、交叉连接器、交叉汇编器等,它们用于将源代码编译成目标评台上可执行的程序。
可以从官方全球信息湾或者第三方渠道下载已经编译好的交叉编译工具链,也可以自行编译搭建交叉编译环境。
3. 配置编译环境在准备好交叉编译工具链之后,我们需要配置编译环境,以便将exosip和osip库移植到目标评台上。
配置编译环境包括设置交叉编译器的路径、指定目标评台的系统类型、设置编译选项等。
具体的配置步骤和方法可以参考官方文档或者相关的教程。
4. 下载源代码在配置好编译环境之后,我们需要下载exosip和osip库的源代码,这些源代码通常是以压缩包的形式发布在官方全球信息湾上,也可以从版本控制系统如Git、SVN等获取最新的源代码。
下载源代码后,我们需要解压缩并进行一些基本的配置。
5. 编译和安装在下载和配置完源代码之后,我们可以使用交叉编译工具链来编译和安装exosip和osip库。
编译和安装过程通常包括配置编译选项、执行编译命令、进行单元测试、安装到目标系统等步骤。
在编译和安装过程中可能会遇到一些依赖库缺失、编译错误等问题,这就需要我们根据具体情况进行调试和解决。
SIP:exosip前几天编程虽然一直都成功,但是有个问题就是我们总是在重复开启eXosip_event_wait(0,50)函数,现在打算围绕eXosip_event_wait展开,即eXosip_event_wait一直处以循环跑。
--------海xx程序研究--------参看下海xx的程序,是如下所示的,在imsUA.c中的main函数中有如下函数:g_timeout_add (200, get_exosip_events, imsUA);解释如下:g_timeout_add (guint interval,GSourceFunc function,gpointer data);第一个参数是间隔的毫秒数,第二个参数是定时后的callback,第三个是传递给callback的数据。
海xx的程序是指每隔200ms进行如下流程,对不同的事件进行不同的响应。
int get_exosip_events(gpointer main_window){eXosip_event_t *je;char display[500] = "";eXosip_lock();eXosip_unlock();if((je = eXosip_event_wait(0,50)) != NULL){// fprintf(stderr, "Event type: %d %s\n", je->type, je->textinfo);imsua_display_event_info(je);if (je->type == EXOSIP_CALL_INVITE){ims_process_incoming_invite(je);}else if (je->type == EXOSIP_CALL_REINVITE){ims_process_incoming_reinvite(je);}else if (je->type == EXOSIP_CALL_RINGING){ims_process_18x(je);}else if (je->type == EXOSIP_CALL_GLOBALFAILURE){ims_process_released_call(je);}else if (je->type == EXOSIP_CALL_CLOSED){ims_process_released_call(je);}else if (je->type == EXOSIP_CALL_ANSWERED){ims_process_200ok(je);}else if (je->type == EXOSIP_CALL_RELEASED){ims_process_released_call(je);}else if (je->type == EXOSIP_CALL_CANCELLED){ims_process_released_call(je);}else if (je->type == EXOSIP_CALL_ACK){ims_process_ack(je);}else if (je->type == EXOSIP_CALL_MESSAGE_REQUESTFAILURE){ims_process_released_call(je);}else if (je->type == EXOSIP_CALL_REQUESTFAILURE){set_display("Call released");}else if (je->type == EXOSIP_CALL_SERVERFAILURE){set_display("Call released by server");}else if (je->type == EXOSIP_CALL_MESSAGE_NEW){if (MSG_IS_PRACK(je->request))ims_process_prack(je);else if (MSG_IS_UPDATE(je->request))ims_process_update(je);else if (MSG_IS_INFO(je->request))common_process_info(je);}else if (je->type == EXOSIP_CALL_MESSAGE_ANSWERED){if (MSG_IS_BYE(je->request))ims_process_released_call(je);else if (MSG_IS_UPDATE(je->request) || MSG_IS_PRACK(je->request))ims_process_2xx(je);}else if (je->type == EXOSIP_MESSAGE_NEW){if (MSG_IS_MESSAGE(je->request)){char sending_ui[50];strcpy(sending_ui,(((je->request)->to)->url)->username);strcat(sending_ui,"@");strcat(sending_ui,(((je->request)->to)->url)->host);char *temp;temp = strstr(pref->impu,":") + 1;if(strcmp(sending_ui,temp)==0){ims_start_im_session(je);}}else if (MSG_IS_BYE(je->request)){set_display("Call ended");}}else if(je->type == EXOSIP_MESSAGE_REQUESTFAILURE) {}else if(je->type == EXOSIP_MESSAGE_ANSWERED) {}else if(je->type == EXOSIP_REGISTRATION_SUCCESS) {if(is_message_deregister == 1){registered = NOT_REGISTERED;is_message_deregister = 0;sprintf(display, "Deregistered with %s",pref->realm);set_display(display);sprintf(display,"Not registered");set_status_bar(display);watchers_remove_all_watchers();num_associated_uris = 0;}else{registered = REGISTERED;ims_process_registration_200ok(je);}}else if(je->type == EXOSIP_REGISTRATION_FAILURE){if((je->response)== NULL){set_display("Registration failed for unknown reason\nMost probably incorrect credentials\n\nCheck Preferences");}else if(((je->response)->status_code == 403)){set_display("Invalid user name\n\nCheck Preferences");}else if(((je->response)->status_code == 401)){ims_process_401(je);}else if(((je->response)->status_code == 404) || ((je->response)->status_code == 407)){set_display("Error with credentials\n\nCheck Preferences");}else{set_display("Registration failed for unknown reason\n\nMost probably incorrect credentials\nCheck Preferences");}}else if(je->type == EXOSIP_REGISTRATION_REFRESHED){set_display("Regsitration Refreshed");registered = REGISTERED;}else if(je->type == EXOSIP_REGISTRATION_TERMINATED) {}else if(je->type == EXOSIP_SUBSCRIPTION_ANSWERED){}else if (je->type == EXOSIP_SUBSCRIPTION_NOTIFY){ims_process_notify(je);}else if (je->type == EXOSIP_SUBSCRIPTION_REQUESTFAILURE){}else if(((je->response)->status_code == 302)){ims_process_302(je);}else{}return TRUE;}----------------------------好了,GTK有上述函数,那现在需要在VC++上实现需要使用线程函数,孙鑫教程中使用了CreateThread函数,但是网上更加推荐_beginthreadex,函数,使用起来也非常简单,由于这个日志也算是回炒了,现在看起来也没什么,但是当时没有涉猎线程的概念,成功的意义倒是非常大。
2. SIP信令完整解析:(1).用户A ,摘机对用户B发起呼叫,用户A首先向AS服务器发起INVITE请求。
(2). AS服务器回复100 Trying给用户A说明收到INVITE请求。
(3). AS服务器通过认证确认用户认证已通过后,向被叫终端B转送INVITE请求。
(4).用户B向AS服务器送呼叫处理中的应答消息, 100 Trying。
(5).用户B向AS服务器送183 Session Progress消息,提示建立对话的进度信息。
(此时被叫QCI1专用承载建立)(6). AS服务器向主叫终端A转送183 Session Progress消息,终端A了解到整个Session的建立进度消息。
(7).终端A向AS服务器回复临时应答消息PRACK ,表示收到183 Session Progress消息。
(此时主叫QCI1专用承载建立)(8). AS服务器向被叫终端B转送临时应答消息PRACK ,终端B了解到终端A收到183 Session Progress消息。
(9).被叫终端B向AS服务器发送200OK消息,表示183SessionProgress请求已经处理成功。
(10). AS服务器向主叫终端A转送200 OK消息。
(11).主叫终端A向AS服务器发送UPDATE消息,意在与被叫终端B协商相关SDP信息。
(12). AS服务器向被叫终端B转送UPDATE消息。
(13).被叫终端B向AS服务器发送200 OK消息,表示UPDATE请求已经处理成功。
(14).AS服务器向主叫用户A转送200 OK消息,通知用户A UPDATE请求已经处理成功。
(15).被叫用户B振铃,用户振铃后,向AS服务器发送180 Ringing振铃信息。
(16).AS服务器向主叫终端A转送180 Ringing振铃信息。
(17).被叫终端B向AS服务器发送200 OK消息,表明主叫最初的INVITE请求已经处理成功。
exosip2 原理exosip2是一种用于实现SIP(会话初始协议)的开源库,它提供了一系列的API函数,使开发者能够轻松地构建基于SIP的应用程序。
本文将详细介绍exosip2的原理及其在通信领域的应用。
exosip2库是基于osip(开源SIP协议栈)库开发的,它提供了更高级别的抽象和功能,可以简化SIP应用程序的开发过程。
exosip2库的核心原理是对SIP协议进行封装和解析,以便于应用程序进行SIP消息的发送和接收。
exosip2库的主要功能包括SIP会话的建立、终止和管理,SIP消息的发送和接收,以及SIP协议的解析和处理。
它提供了一组API函数,使开发者可以方便地创建SIP会话、发送SIP消息,并处理收到的SIP消息。
exosip2库的使用流程一般分为以下几个步骤:1. 初始化:首先需要调用exosip_init函数进行库的初始化,该函数将建立与SIP服务器的连接并初始化相关资源。
2. 注册:通过调用exosip_register函数,可以向SIP服务器注册用户,以便接收来自其他用户的呼叫请求。
3. 呼叫:通过调用exosip_call函数,可以向其他用户发起呼叫请求。
在呼叫请求中需要指定被叫方的SIP地址。
4. 接听:当收到其他用户的呼叫请求时,exosip2库将自动触发一个事件,应用程序可以通过注册相应的回调函数来处理此事件。
在呼叫请求事件中,应用程序可以选择接听呼叫或拒绝呼叫。
5. 通话:一旦呼叫被接听,应用程序可以通过exosip_call_ack函数发送一个ACK消息,表示通话已建立。
在通话过程中,应用程序可以通过exosip_call_send_request函数发送音频数据,并通过exosip_call_recv_request函数接收对方发送的音频数据。
6. 结束:通话结束后,需要调用exosip_call_end函数来终止通话并释放相关资源。
exosip2库的使用可以帮助开发者快速构建基于SIP的应用程序,例如VoIP(网络电话)、实时视频通话、即时消息等。
#include <stdio.h>#include <stdlib.h>#include <netdb.h>#define ENABLE_TRACE //打开log用的#include <eXosip2/eXosip.h>#include <osip2/osip_mt.h>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,flag1=1;char command;char tmp[4096];char *localip="192.168.247.130";char *serverip="192.168.247.130";char *username="8001";char *passwd="8001";char *realm="\"asterisk\"";//这个字段可以不用char *dial="8006";int localport=15061;int serverport=5061;char from[50];sprintf(from,"sip:%s@%s:%d",username,serverip,serverport);char to[50];sprintf(to,"sip:%s@%s:%d",dial,serverip,serverport);char registrar[50];sprintf(registrar,"sip:%s:%d",serverip,serverport);char contact[50];sprintf(contact,"sip:%s@%s:%d",username,localip,localport);int ring_timeout = 20;//20秒是振铃超时printf("r 注册\n");printf("u 注销\n");printf("i 发起呼叫请求\n");printf("h 挂断\n");printf("q 退出程序\n");printf("s 显示各种id\n");TRACE_INITIALIZE(8, NULL); //打开log用的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,localport,AF_INET,0);if(i!=0){eXosip_quit();fprintf(stderr,"Couldn't initialize transport layer!\n");return -1;}flag=1;while(flag){printf("will eXosip_event_wait 2\n");je=eXosip_event_wait(0,10);printf("after eXosip_event_wait 2\n");eXosip_lock();eXosip_default_action(je);eXosip_unlock();printf("Please input the command:\n");scanf("%c",&command);getchar();switch(command){case 'r':{eXosip_clear_authentication_info();if (eXosip_add_authentication_info(username, username, passwd, NULL, NULL/*realm*/)){printf("Add_authentication_info failed\n");return -4;}int i=eXosip_register_build_initial_register (from,registrar,contact,120,®);if(i<0){printf("Register failed!\n");sleep(10);return -4;}eXosip_register_send_register(i,reg);je=eXosip_event_wait(1,0);eXosip_lock();eXosip_default_action(je);eXosip_unlock();}break;case 'u':{eXosip_clear_authentication_info();if (eXosip_add_authentication_info(username, username, passwd, NULL, NULL/*realm*/)){printf("Add_authentication_info failed\n");return -4;}int i=eXosip_register_build_initial_register (from,registrar,contact,0,®);if(i<0){printf("unregister failed!\n");sleep(10);return -4;eXosip_register_send_register(i,reg);je=eXosip_event_wait(1,0);eXosip_lock();eXosip_default_action(je);eXosip_unlock();}break;case 'i':i=eXosip_call_build_initial_invite(&invite,to,from,NULL,"This is a call for conversation");if(i!=0){printf("Initial INVITE failed!\n");break;}snprintf(tmp,4096,"v=0\r\n""o=wangpeng 0 2 IN IP4 %s\r\n""s=xxxx\r\n""c=IN IP4 %s\r\n""t=0 0\r\n""m=audio 12000 RTP/AVP 0 8\r\n""a=rtpmap:8 PCMA/8000\r\n""a=rtpmap:0 PCMU/8000\r\n""a=ptime:20\r\n""a=sendrecv",localip,localip);osip_message_set_body(invite,tmp,strlen(tmp));osip_message_set_content_type(invite,"application/sdp");eXosip_lock();eXosip_call_send_initial_invite(invite); //invite SIP INVITE message to sendeXosip_unlock();flag1=1;while(flag1){printf("will eXosip_event_wait 3\n");je=eXosip_event_wait(ring_timeout,0);printf("after eXosip_event_wait 3\n");if(je!=NULL);//printEventType(je);elseprintf("No response or the time is over!\n");break;}eXosip_lock();eXosip_default_action(je);eXosip_automatic_refresh();eXosip_unlock();switch(je->type){case EXOSIP_CALL_INVITE:printf("###### A new invite received!\n");break;case EXOSIP_CALL_PROCEEDING: //收到100tryprintf("###### Proceeding!\n");break;case EXOSIP_CALL_RINGING:printf("###### Ringing!\n");break;case EXOSIP_CALL_ANSWERED:printf("###### OK! Connected!\n");call_id=je->cid;dialog_id=je->did;eXosip_lock();eXosip_call_build_ack(je->did,&ack);eXosip_call_send_ack(je->did,ack);eXosip_unlock();flag1=0;break;case EXOSIP_CALL_CLOSED: //a BYE was received for this call printf("###### the other sid closed!\n");break;case EXOSIP_CALL_ACK:printf("###### ACK received!\n");break;default:printf("###### other msg!\n");if(je->response && (je->response->status_code==486)){osip_header_t* retryafter = NULL;osip_message_get_retry_after(je->response, 0, &retryafter);printf("###### *** %s ***\n", retryafter->hvalue?retryafter->hvalue:"null");flag1=0;//eXosip_event_free(je);}break;} //end switch//eXosip_event_free(je);} //end whilebreak;case 'h':eXosip_lock();i=eXosip_call_terminate(call_id,dialog_id);if(i<0){printf("call terminate failed!\n");}eXosip_unlock();je=eXosip_event_wait(1,0);if(je!=NULL);//printEventType(je);eXosip_lock();eXosip_default_action(je);eXosip_unlock();break;case 'q':eXosip_quit();printf("Exit the setup!\n");flag=0;break;case 's':if(je != NULL)printf("tid = %d,did = %d,cid = %d \n",je->tid,je->did,je->cid);break;case 'm':i=eXosip_message_build_request(&message,"MESSAGE",to,from,NULL);if(i==0)printf("build message ok");snprintf(tmp,4096,"This is a sip message(Method:MESSAGE)");osip_message_set_body(message,tmp,strlen(tmp));osip_message_set_content_type(message,"text/plain");i=eXosip_message_send_request(message);if(i==0)printf("send message ok");je=eXosip_event_wait(10,0);if(je!=NULL);//printEventType(je);eXosip_lock();eXosip_default_action(je);eXosip_unlock();break;default:printf("no %c option\n",command);break;}}return(0);}PWD=$(shell pwd)LIBCODEPATH=/usr/srcLIBPATH=/usr/localosip2:@echo "will make osip2";echo;echo@cd $(LIBCODEPATH)/libosip2-3.6.0;echo "pwd is: ";pwd;echo;echo;make;make install;cd $(PWD)eXosip2:@echo "will make eXosip2";echo;echo@cd $(LIBCODEPATH)/libeXosip2-3.5.0;echo "pwd is: ";pwd;echo;echo;make;make install;cd $(PWD)myproj:@echo "will make myproj";echo;echorm -f sipuacgcc -o sipuac sipuac.c -I$(LIBPATH)/include -L$(LIBPATH)/lib -losip2 -losipparser2 -leXosip2all:@echo "pwd is $(shell pwd)"@echo "will make osip2"@echo@cd $(LIBCODEPATH)/libosip2-3.6.0;echo "pwd is: ";pwd;echo;echo;make;make install;cd $(PWD)@echo "pwd is $(shell pwd)"@echo@echo@echo "will make eXosip2"@echo@cd $(LIBCODEPATH)/libeXosip2-3.5.0;echo "pwd is: ";pwd;echo;echo;make;make install;cd $(PWD)@echo "pwd is $(shell pwd)"@echo@echo@echo "will make myproj"rm -f sipuacgcc -o sipuac sipuac.c -I$(LIBPATH)/include -L$(LIBPATH)/lib -losip2 -losipparser2 -leXosip2clean:@echo "will clean osip2";echo;echo@cd $(LIBCODEPATH)/libosip2-3.6.0;echo "pwd is: ";pwd;echo;echo;make clean;cd $(PWD) @echo "will clean eXosip2";echo;echo@cd $(LIBCODEPATH)/libeXosip2-3.5.0;echo "pwd is: ";pwd;echo;echo;make clean;cd $(PWD)@echo "will clean myproj";echo;echorm -f sipuac。