测试
与上一篇《编译libeXosip以及向代理服务器注册》编译基于osip客户端程序有些相同;
编译partysip服务器端程序也是需要首先编译所需的依赖库libosip2, libosipparser2(两个库均来自于libosip2);
这次工程中使用了:
libosip2-4.0.0.tar.gz, partysip-2.2.3.tar.gz
分别下载 libosip和partysip;
http://ftp.gnu.org/gnu/osip/
http://download-mirror.savannah.gnu.org/releases/partysip/
编译libosip2
编译libosip2-4.0.0
./configure –prefix=$PWD/_install
$ make & make install
产生:
|-include
|—-include/osip2 include/osipparser2
|-lib
|—-libosip2.a libosip2.la libosip2.so libosip2.so.3 libosip2.so.3.0.0
|—-libosipparser2.a libosipparser2.la libosipparser2.so libosipparser2.so.3 libosipparser2.so.3.0.0 pkgconfig
|-share/man
编译partysip
编译partysip-2.2.3
./configure LDFLAGS='-L/home/project/demo/osip_demo/libosip2-4.0.0/_install/lib' \
CPPFLAGS='-I/home/project/demo/osip_demo/libosip2-4.0.0/_install/include' \
--prefix=$PWD/_install
问题一 undefined reference to symbol ‘osip_atoi’
/usr/bin/ld: osip_msg.o: undefined reference to symbol 'osip_atoi'
/usr/bin/ld: note: 'osip_atoi' is defined in DSO /home/project/demo/osip_demo/libosip2-4.0.0/_install/lib/libosipparser2.so.3
so try adding it to the linker command line
/home/project/demo/osip_demo/libosip2-4.0.0/_install/lib/libosipparser2.so.3: could not read symbols: Invalid operation
函数osip_atoi()在libosipparser2库中实现的;
修改文件partysip-2.2.3/src/Makefile添加库的引用
partysip_LDFLAGS = -L$(prefix)/lib -losip2 -losipparser2 -avoid-version -export-dynamic
问题二 undefined reference to ‘__dn_expand’ ‘__res_query’
../ppl/unix/.libs/libppl.so: undefined reference to `__dn_expand'
../ppl/unix/.libs/libppl.so: undefined reference to `__res_query'
collect2: ld returned 1 exit status
两个函数是在glibc下面的libresolv库中实现的。
修改两个文件 1.partysip-2.2.3/src/Makefile,2.partysip-2.2.3/tools/Makefile
所以添加库的引用;
PARTYSIP_LIB = -lnsl -ldl -lresolv
PPL_LIB = -lnsl -ldl -lresolv
问题三 ‘osip_uri_parse’ is defined in DSO
/usr/bin/ld: ../src/psp_utils.o: undefined reference to symbol 'osip_uri_parse'
/usr/bin/ld: note: 'osip_uri_parse' is defined in DSO
/home/project/demo/osip_demo/libosip2-4.0.0/_install/lib/libosipparser2.so.3
so try adding it to the linker command line
could not read symbols: Invalid operation
collect2: ld returned 1 exit status
make[2]: *** [psp_users] Error 1
修改文件 partysip-2.2.3/tools/Makefile添加库的引用
psp_users_LDFLAGS = -O -L$(prefix)/lib -losip2 -losipparser2 -module -avoid-version -export-dynamic
问题四 undefined reference to `clock_gettime’
缺少链接库 -lrt, 加到Makefile中即可;
在文件中partysip-2.2.3/src/Makefile追加库引入-lrt
partysip_LDFLAGS = -L$(prefix)/lib -losip2 -losipparser2 -lrt -avoid-version -export-dynamic
以及文件partysip-2.2.3/tools/Makefile:
PARTYSIP_LIB = -lnsl -ldl -lresolv -lrt
问题五 版本兼容性问题普通变量改指针变量
expected ‘const struct osip_list_t *’ but argument is of type ‘osip_list_t’
osip_list_eol(request->routes, i) 改成 osip_list_eol(&request->routes, i);
此类问题大概有10余处左右,根据编译提示修改即可;
编译成功
partysip-2.2.3/_install目录下
|-bin (partysip partysip-config psp_users)
|-etc (partysip)
|-include (partysip ppl)
|-lib (libppl.a libppl.la libppl.so libppl.so.2 libppl.so.2.2.3 partysip)
修改并运行自带的程序例程
添加注释并且简化一下 src/main.c
#include <stdlib.h>
#include <partysip/partysip.h>
#include <partysip/psp_config.h>
#include <psp_utils.h>
#include <ppl/ppl_init.h>
#include <ppl/ppl_getopt.h>
#include <ppl/ppl_uinfo.h>
#include <ppl/ppl_md5.h>
static const char server_built[] = "unknown";
void partysip_exit (int process_exit_value){
psp_core_free ();
psp_config_unload ();
ppl_init_close ();
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
"program has terminated.\n"));
}
// 加载所有的配置的插件
static int main_load_plugins (){
int i;
psp_plugin_t *psp_plugin;
char *plugins;
char *plugins_config;
char *next;
char *next_config;
char *result;
char *result_config;
plugins = psp_config_get_element ("plugins"); //获取需要加载的插件
if (plugins == NULL){
return -1;
}
//输出 plugins=udp syntax auth filter rgstrar ls_localdb ls_sfull
printf("plugins=%s\n", plugins);
plugins_config = psp_config_get_element ("plugins_config");
if (plugins_config == NULL){
result_config = NULL;
}
i = psp_util_get_and_set_next_token (&result, plugins, &next);
if (i != 0){
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
"failed to load plugin\n"));
return -1;
}
if (plugins_config!=NULL){
i = psp_util_get_and_set_next_token (&result_config, plugins_config, &next_config);
if (i != 0){
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
"failed to read plugins_config\n"));
return -1;
}
}
for (; result != NULL;) {
if (result_config!=NULL){
//依次输出
//udp (udp),syntax (syntax),auth (auth),filter (filter_internal),
//rgstrar (rgstrar),ls_localdb (ls_localdb),ls_sfull (ls_sfull)
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
"loading plugin: %s (%s)\n", result, result_config));
}else{
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
"loading plugin: %s\n", result));
}
i = psp_plugin_load (&psp_plugin, result, result_config);// 加载插件
if (i != 0){
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
"failed to load plugin %s\n", result));
return -1;
}
if (plugins_config!=NULL){
osip_free (result_config);
plugins_config = next_config;
}
osip_free (result);
plugins = next;
i = psp_util_get_and_set_next_token (&result, plugins, &next);
if (i != 0){
break;
}
if (plugins_config!=NULL){
i = psp_util_get_and_set_next_token (&result_config, plugins_config, &next_config);
if (i != 0) {
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
"failed to read plugins_config line\n"));
return -1;
}
}
}
return 0;
}
int main (int argc, const char *const argv[])
{
char c;
int i;
ppl_getopt_t *opt;
ppl_status_t rv;
const char *cf_config_file = CONFIG_DIR "/" PARTYSIP_CONF;
int interactive_mode = 0;
int cf_debug_level = 0;
const char *cf_log_file = NULL;
const char *optarg;
ppl_init_open ( ); // 初始化 ppl library.
ppl_getopt_init (&opt, argc, argv);//通过ppl_getopt初始化部分ppl参数,可删除(147,148行需同时删除)
cf_debug_level = 6;
i = psp_config_load ((char *) cf_config_file); //加载配置文件partysip.conf
// Config name:/project/demo/osip_demo/partysip-2.2.3/_install/etc/partysip/partysip.conf
printf ("Config name: %s\n", cf_config_file);
if (i != 0){
perror ("ERROR: Could not open config file");
}
// 获取配置文件partysip.conf相关的配置
char *serverip = psp_config_get_element ("serverip");
char *servername = psp_config_get_element ("servername");
char *serverrealm = psp_config_get_element ("serverrealm");
if (serverip == NULL){
printf ("Bad configuration: \"serverip\" is mandatory\n");
partysip_exit (1);
}
if (servername == NULL) {
printf ("Bad configuration: \"servername\" is mandatory\n");
partysip_exit (1);
}
// 配置输出日志 OSIP_TRACE (osip_trace...)
FILE *log_file;
if (cf_debug_level > 0){
if (cf_log_file != NULL){
log_file = fopen (cf_log_file, "w+");
if (NULL == log_file){
printf ("Log name: %s\n", cf_log_file);
perror ("ERROR: Could not open log file");
exit (1);
}
}else{
log_file = NULL;
}
TRACE_INITIALIZE (cf_debug_level, log_file);//配置日志输出
}
osip_free ((void *) (opt->argv));
osip_free ((void *) opt);
i = psp_core_init (); //partysip初始化
i = psp_utils_load_users (); //partysip加载用户,不做验证,所以可以不调用
i = main_load_plugins (); // 加载插件
i = psp_core_start (interactive_mode);//partysip启动
if (interactive_mode == 1)
while(1);
if (interactive_mode == 1)
partysip_exit (0); /* else, this is done somewhere else */
return 0;
main_error:
partysip_exit (0);
return -1;
}
修改配置文件
/project/demo/osip_demo/partysip-2.2.3/_install/etc/partysip/partysip.conf
使用属性:
serverip = 192.168.1.123
servername = demo-sip-server
serverport_udp = 5060
authentication = off
magicstring2 = “demo”
其中authentication属性关闭了对用户注册的验证;于是任意用户都可以注册成功;
运行程序
./partysip
如果没有修改直接运行,需要添加参数
./partysip -d 6
使用http://blog.csdn.net/dreamintheworld/article/details/72939454中的例程进行注册;
可以看到注册成功的log输出;
两台注册上来的终端设备已经经过测试,并完成呼叫测试功能,并通过音频传输测试(来自PJSIP的两个客户端,如果使用eXosip媒体协商需要进一步修改)
关于程序中加载插件
编译程序生成
partysip-2.2.3/_install/lib/目录下
libppl.a libppl.la libppl.so libppl.so.2 libppl.so.2.2.3
partysip-2.2.3/_install/lib/partysip/目录下
libpsp_auth.a libpsp_ls_localdb.a libpsp_rgstrar.a
libpsp_auth.la libpsp_ls_localdb.la libpsp_rgstrar.la
libpsp_auth.so libpsp_ls_localdb.so libpsp_rgstrar.so
libpsp_filter.a libpsp_ls_sfull.a libpsp_syntax.a
libpsp_filter.la libpsp_ls_sfull.la libpsp_syntax.la
libpsp_filter.so libpsp_ls_sfull.so libpsp_syntax.so
libpsp_groups.a libpsp_ls_static.a libpsp_udp.a
libpsp_groups.la libpsp_ls_static.la libpsp_udp.la
libpsp_groups.so libpsp_ls_static.so libpsp_udp.so
程序中通过dlopen(const char *filename, int flag)打开动态链接库文件的形式,实现插件加载;
main_load_plugins>>>psp_plugin_load>>>ppl_dso_load>>>dlopen