编译libeXosip以及向代理服务器注册

时间:2022-09-13 21:30:55

测试 Linux linux

编译 libeXosip2说明

浏览编译说明 libeXosip2-4.1.0/help/INSTALL.linux

Common Install process for linux/UNIX.

1: compile/install libosip first.

$> tar -xvzf libosip2-x.x.x.tar.gz
$> CFLAGS="-I/usr/local/include/" ../configure
$> make
$> make install (as root...)

2: compile/install eXosip

$> tar -xvzf libeXosip2-x.x.x.tar.gz
$> CFLAGS="-I/usr/local/include/" ../configure
$> make
$> make install (as root...)

所以编译libeXosip2-4.1.0 ,需要先编译 libosip2-4.1.0 (保持版本的一致)

第一步,编译libosip2

编译libosip2-4.1.0
编译:

$ ./configure --prefix=$PWD/_install & make & make install
$ ./configure --prefix=$PWD/_install --host=arm-none-linux-gnueabi & make & make install

顺利产生以下文件
libosip2-4.1.0/_install/lib/
|-libosip2.a
|-libosip2.so
|-libosipparser2.a
|-libosipparser2.so

第二步,编译libeXosip2

编译 libeXosip2-4.1.0
但是使用 ./configure –prefix=$PWD/_install & make & make install
编译阶段报错
/usr/local/lib/libosipparser2.so: could not read symbols: File in wrong format
collect2: ld returned 1 exit status
make: *** [libeXosip2.la] Error 1

显然是configure配置阶段就出现了配置不完整的情况。
网上的资料基本上只讲到把相关的文件拷贝到 /usr/local/ 目录下面;
比如
cp libosip2-3.0.1/src/osip2/.libs/libosip2.a /usr/lib
cp libosip2-3.0.1/src/osipparser2/.libs/libosipparser2.a /usr/lib

但是显然这是需要root权限的,所以希望在不影响其他用户的其他下,在自己的权限目录下进行编译。
则需要配置相关的目录。

./configure --prefix=$PWD/_install LDFLAGS="-L/home/zzy/project/wrtWgServerlib/debug/libosip2-4.1.0/_install/lib" \
LIBS="-losipparser2 -losip2" --host=x84_64-unknown-linux-gnu

配置成这样,虽然configure可以配置通过,但是仍然没有通过make;
报错依旧;
下面需要怎么样的配置呢,但是 configure help 的时候已经说到配置 LIBS 以及 LDFLAGS 了
没有讲到更多的配置方式,网上的资料也是少之又少;
编译动态库的时候仍然无法实现,所以屏蔽编译动态库后:

#
# build.sh
#
echo "BUILD libeXosip2-4.1.0"
./configure --prefix=$PWD/_install \
CC=gcc \
--host=x84_64-unknown-linux-gnu \
--disable-tools \
--disable-debug \
--disable-trace \
--disable-shared \
--enable-openssl \
--enable-static \
CFLAGS='-I/home/admin/project/demo/osip_demo/libosip2-4.1.0/_install/lib/include' \
LDFLAGS='-L/home/admin/project/demo/osip_demo/libosip2-4.1.0/_install/lib' \
LIBS='-losipparser2 -losip2' \
SIP_CFLAGS='-I/home/admin/project/demo/osip_demo/libosip2-4.1.0/_install/lib/include' \
OSIP_LIBS='-L/home/admin/project/demo/osip_demo/libosip2-4.1.0/_install/lib -losipparser2 -losip2'

如果配置嵌入式环境 :
CC=arm-none-linux-gnueabi-gcc
–host=arm-none-linux-gnueabi

配置成功后可以生成:
libeXosip2-4.1.0/_install
|-include
|-lib
|-lib/libeXosip2.a
|-lib/libeXosip2.la
这是在屏蔽生成动态库的时候,如果需要生成动态库,估计依然报错;

生成动态库的方法了:
configure 的时候除了生成Makefile之外,还生成了libtool文件,需要修改libtool文件:

# Compile-time system search path for libraries.
sys_lib_search_path_spec="/home/zzy/project/demo/osip_demo/libosip2-4.1.0/_install/lib \
/usr/lib/gcc/x86_64-linux-gnu/4.4.7 \
/usr/lib/x86_64-linux-gnu \
/usr/lib \
/lib/x86_64-linux-gnu /lib "

# Run-time system search path for libraries.
sys_lib_dlsearch_path_spec="/home/zzy/project/demo/osip_demo/libosip2-4.1.0/_install/lib \
/lib \
/usr/lib \
/usr/lib/i386-linux-gnu/mesa \
/lib/i386-linux-gnu /usr/lib/i386-linux-gnu \
/lib/i686-linux-gnu /usr/lib/i686-linux-gnu \
/usr/local/lib /lib/x86_64-linux-gnu \
/usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/mesa \
/lib32 \
/usr/lib32 "

在sys_lib_search_path_spec和sys_lib_dlsearch_path_spec中添加lib的搜索路径;
运行编译脚本

# build.sh
echo "BUILD libeXosip2-4.1.0"

./configure --prefix=$PWD/_install \
CC=gcc \
--host=x84_64-unknown-linux-gnu \
--disable-tools \
--disable-debug \
--disable-trace \
--enable-openssl \
--enable-static \
CFLAGS='-I/home/admin/project/demo/osip_demo/libosip2-4.1.0/_install/lib/include' \
LDFLAGS='-L/home/admin/project/demo/osip_demo/libosip2-4.1.0/_install/lib' \
LIBS='-losipparser2 -losip2' \
SIP_CFLAGS='-I/home/admin/project/demo/osip_demo/libosip2-4.1.0/_install/lib/include' \
OSIP_LIBS='-L/home/admin/project/demo/osip_demo/libosip2-4.1.0/_install/lib -losipparser2 -losip2'

_install/lib/目录下终于生成:
|-libeXosip2.a
|-libeXosip2.la
|-libeXosip2.so
|-libeXosip2.so.11
|-libeXosip2.so.11.0.0

使用libeXosip2自带的样例测试注册流程

libeXosip2-4.1.0/tools/sip_reg.c
编译:

# build.sh
gcc -O2 -I/home/admin/project/demo/osip_demo/libosip2-4.1.0/_install/include \
-L/home/admin/project/demo/osip_demo/libosip2-4.1.0/_install/lib \
-I/home/admin/project/demo/osip_demo/libeXosip2-4.1.0/_install/include \
-L/home/admin/project/demo/osip_demo/libeXosip2-4.1.0/_install/lib \
sip_reg.c \
-o sipreg \
-leXosip2 -losip2 -losipparser2 -lpthread

运行:

# reg.sh 
./sipreg \
-r sip:192.168.1.22:5060 \
-u sip:01001010101@192.168.1.22 \
-c sip:01001010101@192.168.1.22:5060 \
-U 01001010101 \
-P 01001010101 \
-p 5061 \
-e 1800 \
-d

启动服务器(192.168.1.22)后,运行客户端测试样例:

$ sh build.sh
$ sh reg.sh
username: 01001010101
password: [removed]01001010101
eXosip_add_authentication_info success
(143)eXosip_register_build_initial_register 2*expiry=3600
---------------
fromuser = sip:01001010101@192.168.1.22
proxy = sip:192.168.1.22:5060
contact = sip:01001010101@192.168.1.22:5060
---------------
(169)type=0
registrered successfully

修改注册服务器地址为192.168.1.66 则会注册失败(无代理服务器)

$ sh build.sh
$ sh reg.sh
username: 01001010101
password: [removed]01001010101
eXosip_add_authentication_info success
(143)eXosip_register_build_initial_register 2*expiry=3600
---------------
fromuser = sip:01001010101@192.168.1.66
proxy = sip:192.168.1.66:5060
contact = sip:01001010101@192.168.1.66:5060
---------------
(169)type=1
(175)(nil), Registration failed!


运行程序之后需要添加动态库的搜索路径
分别在libosip2-4.1.0/_install/lib目录,
libeXosip2-4.1.0/_install/lib目录下运行:
export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH

以上程序是修改过的sip_reg.c,也仅仅是删除掉一些多余的不影响的宏定义;
修改后的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <syslog.h>
#include <pthread.h>
#include <osip2/osip_mt.h>
#include <eXosip2/eXosip.h>

#define PROG_NAME "sipreg"
#define PROG_VER "1.0"
#define UA_STRING "SipReg v" PROG_VER
#define SYSLOG_FACILITY LOG_DAEMON

#define syslog_wrapper syslog
static void usage (void){
printf ("Usage: " PROG_NAME " [required_options] [optional_options]\n"
"\n\t[required_options]\n"
"\t-r --proxy\tsip:proxyhost[:port]\n"
"\t-u --from\tsip:user@host[:port]\n"
"\n\t[optional_options]\n"
"\t-c --contact\tsip:user@host[:port]\n"
"\t-d --debug (log to stderr and do not fork)\n"
"\t-e --expiry\tnumber (default 3600)\n"
"\t-f --firewallip\tN.N.N.N\n" "\t-h --help\n"
"\t-l --localip\tN.N.N.N (force local IP address)\n"
"\t-p --port\tnumber (default 5060)\n"
"\t-U --username\tauthentication username\n"
"\t-P --password\tauthentication password\n");
}

typedef struct regparam_t {
int regid;
int expiry;
int auth;
} regparam_t;

struct eXosip_t *context_eXosip;

static void * register_proc (void *arg) {
struct regparam_t *regparam = arg;
int reg;
for (;;) {
sleep (regparam->expiry / 2);
eXosip_lock (context_eXosip);
reg = eXosip_register_send_register (context_eXosip, regparam->regid, NULL);
printf("(%d)eXosip_register_send_register = %d\n", __LINE__, reg);
if (0 > reg) {
perror ("eXosip_register");
exit (1);
}
regparam->auth = 0;
eXosip_unlock (context_eXosip);
}
return NULL;
}

int main (int argc, char *argv[]) {
int c;
int port = 5060;
char *contact = NULL;
char *fromuser = NULL;
const char *localip = NULL;
const char *firewallip = NULL;
char *proxy = NULL;
char *username = NULL;
char *password = NULL;
struct regparam_t regparam = { 0, 3600, 0 };
struct osip_thread *register_thread;
int debug = 0;
int nofork = 0;
for (;;) {
#define short_options "c:de:f:hl:p:r:u:U:P:"
c = getopt (argc, argv, short_options);
if (c == -1){
break;
}
switch (c) {
case 'c':contact = optarg;break;
case 'd':nofork = 1;break;
case 'e':regparam.expiry = atoi (optarg);break;
case 'f':firewallip = optarg;break;
case 'h':usage ();exit (0);
case 'l':localip = optarg;break;
case 'p':port = atoi (optarg);break;
case 'r':proxy = optarg;break;
case 'u':fromuser = optarg;break;
case 'U':username = optarg;break;
case 'P':password = optarg;break;
default:break;
}
}
if (!proxy || !fromuser) {
usage ();
exit (1);
}
if (!nofork) {
printf("%d\n", daemon (1, 0));
}

if (debug > 0){
TRACE_INITIALIZE (6, NULL);
}

context_eXosip = eXosip_malloc ();
if (eXosip_init (context_eXosip)) { // 初始化eXosip和osip协议栈
syslog_wrapper (LOG_ERR, "eXosip_init failed");
exit (1);
}
if (eXosip_listen_addr (context_eXosip, IPPROTO_UDP, NULL, port, AF_INET, 0)) {
// 打开信号socket 传输层初始化失败
printf("(%d)eXosip_listen_addr failed, port=%d\n", __LINE__, port);
syslog_wrapper (LOG_ERR, "eXosip_listen_addr failed");
exit (1);
}
if (localip) {
syslog_wrapper (LOG_INFO, "local address: %s", localip);
eXosip_masquerade_contact (context_eXosip, localip, port);
}
if (firewallip) {
syslog_wrapper (LOG_INFO, "firewall address: %s:%i", firewallip, port);
eXosip_masquerade_contact (context_eXosip, firewallip, port);
}
eXosip_set_user_agent (context_eXosip, UA_STRING);
if (username && password) {
printf("username: %s\n", username);
printf("password: [removed]%s\n", password);
if (eXosip_add_authentication_info (context_eXosip, username, username, password, NULL, NULL)) {
printf ("eXosip_add_authentication_info failed");
exit (1);
}else{
printf("eXosip_add_authentication_info success\n");
}
}

{
osip_message_t *reg = NULL;
int i;
printf("(%d)eXosip_register_build_initial_register 2*expiry=%d\n",
__LINE__, regparam.expiry * 2);
printf("---------------\n");
printf("%8s = %s\n", "fromuser", fromuser);
printf("%8s = %s\n", "proxy", proxy);
printf("%8s = %s\n", "contact", contact);
printf("---------------\n");
// 使用参数进行注册初始化
regparam.regid = eXosip_register_build_initial_register (context_eXosip,
fromuser, proxy, contact, regparam.expiry * 2, &reg);
if (regparam.regid < 1) {
syslog_wrapper (LOG_ERR, "eXosip_register_build_initial_register failed");
exit (1);
}
// 初始化成功后,发起注册
i = eXosip_register_send_register (context_eXosip, regparam.regid, reg);
if (i != 0) {
syslog_wrapper (LOG_ERR, "eXosip_register_send_register failed");
exit (1);
}
}
for (;;) {
eXosip_event_t *event;
if (!(event = eXosip_event_wait (context_eXosip, 0, 1))) {
osip_usleep (10000);
continue;
}
eXosip_automatic_action (context_eXosip);
printf("(%d)type=%d\n", __LINE__, event->type);
switch (event->type) {
case EXOSIP_REGISTRATION_SUCCESS:
printf("registrered successfully\n");
break;
case EXOSIP_REGISTRATION_FAILURE:
printf("(%d)%p, %s\n", __LINE__, event->response, event->textinfo);
regparam.auth = 1;
break;
default:
break;
}
eXosip_event_free (event);
}
}

参考 http://blog.chinaunix.net/uid-7684977-id-2569711.html

样例中使用的是基于oSIP开源库的SIP代理服务器PartySIP

添加注册成功后进行呼出

switch (event->type) {
case EXOSIP_REGISTRATION_SUCCESS:
printf("registrered successfully\n");
// 初始化成功后发起呼叫
char strMsg[256];
// username=本机账号,password=密码
sprintf(strMsg, "v=0\r\n"\
"o=anonymous 0 0 IN IP4 0.0.0.0\r\n"\
"t=1 10\r\n"\
"a=username:01001010101\r\n"\
"a=password:01001010101\r\n");
char* strSrcCall = "sip:01001010101@192.168.1.66";// 呼出方(本机账号)
char* strDestCall = "sip:01001010102@192.168.1.66:5060"; // 被叫账号
osip_message_t *invite = NULL;
eXosip_call_build_initial_invite (context_eXosip, &invite,
strDestCall,
strSrcCall,
NULL,
"This is a call for a conversation");
osip_message_set_body (invite, strMsg, strlen(strMsg));
osip_message_set_content_type (invite, "application/sdp");

eXosip_call_build_initial_invite (context_eXosip, &invite,
strDestCall,
strSrcCall,
NULL,
"This is a call for a conversation");
eXosip_call_send_initial_invite (context_eXosip, invite);
break;
case EXOSIP_REGISTRATION_FAILURE:
printf("(%d)%p, %s\n", __LINE__, event->response, event->textinfo);
regparam.auth = 1;
break;
case EXOSIP_CALL_PROCEEDING:
printf("Processing\n"); // 对方(01001010102)正在进行处理
break;
case EXOSIP_CALL_RINGING:
printf("Ringing\n");// 对方(01001010102)振铃
break;
default:
break;
}

嗯,是的,需要两次调用eXosip_call_build_initial_invite