最近业务中需要做网络电话,在研究sip协议,借助osip2和eXosip2进行学习,
以下是初步编译和实践经验,分享在此:
使用库的版本:libosip2-3.6.0.tar,libeXosip2-3.6.0.tar
解压libosip2-3.6.0.tar ,比如解压目录为 /usr/local/libosip2-3.6.0,进入该目录,
编译该lib库:
#./configure
#make
#make install
同理编译libeXosip2
#./configure
#make
#make install
注意最后要更新库,否则在程序执行时,可能会提示找不到库,编译后的库文件及头文件会默认放在/usr/local目录下:
#ldconfig
在运行测试程序时,如果输出类似以下的提示信息时,原因可能是没有配置默认网关:
Debug=... network is unreachable
测试程序:uac.c 客户端,可以实现注册,拨号,振铃,挂机等网络电话事务, 调试已通过(sip服务器借助 mjserver6 ,我的下载资源中提供)
/*
gcc -o exosip_phone exosip_phone.c -losip2 -leXosip2 -lpthread
*/
#include <eXosip2/eXosip.h>
#include <osip2/osip_mt.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
// #include <mediastreamer2/mediastream.h>
#include <osipparser2/osip_message.h>
#include <osipparser2/osip_parser.h>
#include <pthread.h>
#define WAIT_TIMER 200
#define REG_TIMER 30*1000
int doing;
int rtp_port;
int dtmfing, calling,picked;
int call_id ,dialog_id;
char *m_strAuth;
char *dtmf_str="2002";
//CString dtmf_str;
char *server_url="192.168.1.106";
char *dest_url="192.168.1.102";
char *server_port="5060";
char *local_port="5000";
char *username="10007";
char *password="10007";
char *telNum="10008";
// AudioStream *audio = NULL;
// RtpProfile *profile = NULL;
// RtpSession *session = NULL;
// OrtpEvQueue *q = NULL;
eXosip_event_t *uac_e; /* 事件处理 */
osip_message_t *ack = NULL; /* 响应消息 */
osip_message_t *answer = NULL; /* 请求消息的回应 */
eXosip_event_t *uac_call; /* answer事件处理 */
osip_message_t *answer_call = NULL; /* answer请求消息的回应 */
int build_media(int local_port, const char *remote_ip, int remote_port, int payload, const char *fmtp, int jitter, int ec, int bitrate)
{
if(payload != 0 && payload != 8)
{
/* 目前仅支持0,8 711ulaw,711alaw */
return -1;
}
// PayloadType *pt;
// profile = rtp_profile_clone_full(&av_profile);
// q = ortp_ev_queue_new();
/*
pt = rtp_profile_get_payload(profile, payload);
if (pt==NULL)
{
printf("codec error!");
return -1;
}
*/
// if (fmtp != NULL) payload_type_set_send_fmtp(pt, fmtp);
//if (bitrate > 0) pt->normal_bitrate = bitrate;
/*
if (pt->type != PAYLOAD_VIDEO)
{
printf("audio stream start!");
audio = audio_stream_start(profile, local_port, remote_ip, remote_port, payload, jitter, ec);
if (audio)
{
session = audio->session;
}
else
{
printf("session error!");
return -1;
}
}
else
{
printf("codec select error!");
return -1;
}
rtp_session_register_event_queue(session, q);
*/
return 0;
}
int real_send_register(int expires)
{
char identity[100];
char registerer[100];
char localip[128];
int id;
int ret;
eXosip_guess_localip (AF_INET, localip, 128);
printf("%s\n",localip);
//sprintf(identity,"sip:%s@%s:%s",username,localip,local_port);
sprintf(identity,"sip:%s@%s",username,server_url);
sprintf(registerer,"sip:%s:%s",server_url,server_port);
osip_message_t *reg = NULL;
eXosip_lock ();
id = eXosip_register_build_initial_register(identity, registerer, NULL,expires, ®);
eXosip_unlock ();
if(0 > id)
{
printf("register init Failed!\n");
return -1;
}
eXosip_lock ();
eXosip_clear_authentication_info(); //去除上次加入的错误认证信息,再应用新输入的鉴权信息
eXosip_add_authentication_info(username, username,password, "md5", NULL);
ret = eXosip_register_send_register(id, reg);
eXosip_unlock ();
if(0 != ret)
{
printf("register send Failed!\n");
return -1;
}
return id;
}
int sip_ua_monitor()
{
int ret = -1;
char *payload_str; /* 服务器优先编码值 */
char localip[128];
char t