1、下载rtpproxy并安装
cd /home/hi
下载rtpproxy最新版,比如rtpproxy-2.1.0.tar.gz tar –xzvf rtpproxy-2.1.0.tar.gz cd rtpproxy-2.1.0 ./configure make make install2、启动rtpproxy
可以根据需求启动一系列rtpproxy进程,格式如下:
./rtpproxy -l 192.168.1.122 -s udp:192.168.1.122: 20000 -F3、OpenSIPS配置
## $Id$## OpenSIPS residential configuration script# by OpenSIPS Solutions# # This script was generated via "make menuconfig", from # the "Residential" scenario. # You can enable / disable more features / functionalities by # re-generating the scenario with different options.# # # Please refer to the Core CookBook at: # http://www.opensips.org/Resources/DocsCookbooks # for a explanation of possible statements, functions and parameters. # ####### Global Parameters ######### debug=2 log_stderror=no log_facility=LOG_LOCAL1 fork=yes children=4 /* uncomment the following lines to enable debugging */ #debug=6 #fork=no #log_stderror=yes /* uncomment the next line to enable the auto temporary blacklisting of not available destinations (default disabled) */ #disable_dns_blacklist=no /* uncomment the next line to enable IPv6 lookup after IPv4 dns lookup failures (default disabled) */ #dns_try_ipv6=yes /* comment the next line to enable the auto discovery of local aliases based on revers DNS on IPs */ auto_aliases=no listen=udp:192.168.1.216:5060 # CUSTOMIZE ME listen=tcp:192.168.1.122:5050 # CUSTOMIZE ME # Udp和tcp的地址填写该opensips服务器的地址 ####### Modules Section ######## #### DIALOG module loadmodule "dialog.so" modparam("dialog", "dlg_match_mode", 1) modparam("dialog", "default_timeout", 21600) # 6 hours timeout modparam("dialog", "db_mode", 2) modparam("dialog", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") # CUSTOMIZE ME #### NAT modules loadmodule "nathelper.so" modparam("nathelper", "natping_interval", 10) modparam("nathelper", "ping_nated_only", 1) modparam("nathelper", "sipping_bflag", "SIP_PING_FLAG") modparam("nathelper", "sipping_from", "sip:pinger@127.0.0.1") #CUSTOMIZE ME modparam("nathelper", "received_avp", "$avp(received_nh)") loadmodule "rtpproxy.so" modparam("rtpproxy", "rtpproxy_sock", "udp:192.168.1.122:20000") # CUSTOMIZE ME
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
4、参考资料:
rtpproxy 初始化代码分析
rtpproxy启动
./rtpproxy -A 110.172.192.68 -l 0.0.0.0 -s udp:localhost:7890 -n tcp:localhost:7890 -F -d DBUG -m 50002 -M 50020 -d
- 1
log_level:log_facility
参数解释如下: -A 本机外网地址 -l 本机内网侦听地址 -s 本机侦听opensips通知端口 -n 超时通知接收端口 -F 不检查是否为超级用户模式 -d 调试消息输出级别 -m rtp最小端口 -M rtp最大端口-d
log_level为日志级别,值如下 DBUG INFO WARN ERR CRIT log_facility为日志输出到哪,利用的系统日志{ "LOG_AUTH", LOG_AUTH}, { "LOG_CRON", LOG_CRON}, { "LOG_DAEMON", LOG_DAEMON}, { "LOG_KERN", LOG_KERN}, { "LOG_LOCAL0", LOG_LOCAL0}, { "LOG_LOCAL1", LOG_LOCAL1}, { "LOG_LOCAL2", LOG_LOCAL2}, { "LOG_LOCAL3", LOG_LOCAL3}, { "LOG_LOCAL4", LOG_LOCAL4}, { "LOG_LOCAL5", LOG_LOCAL5}, { "LOG_LOCAL6", LOG_LOCAL6}, { "LOG_LOCAL7", LOG_LOCAL7}, { "LOG_LPR", LOG_LPR}, { "LOG_MAIL", LOG_MAIL}, { "LOG_NEWS", LOG_NEWS}, { "LOG_USER", LOG_USER}, { "LOG_UUCP", LOG_UUCP}, #if !defined(__solaris__) && !defined(__sun) && !defined(__svr4__) { "LOG_AUTHPRIV", LOG_AUTHPRIV}, { "LOG_FTP", LOG_FTP}, { "LOG_SYSLOG", LOG_SYSLOG}, #endif {NULL, 0}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
入口:main.c
int main(int argc, char **argv){int i, len, timeout, controlfd, alarm_tick;double sptime, eptime, last_tick_time; unsigned long delay; struct cfg cf; char buf[256]; //初始化配置,将启动时传入的参数保存到cf结构体中 init_config(&cf, argc, argv); //将1~255数随机存储在cf.stable.rand_table[256]数组中 init_hash_table(&cf.stable); //初始化媒体流端口,-m 50002 -M 50020端口范围用于媒体流中转,并且成对使用 //此函数将指定的端口范围保存在cf.stable.port_table[65536]数组中,保存端口对中的一个. 并将对port_table[]下标查找的最大值保存在cf.port_table_idx init_port_table(&cf); //创建与opensips命令交互的socket,并进行端口绑定,绑定的端口为 -s 传进来的参数 controlfd = init_controlfd(&cf); //日志初始化,利用的是系统日志,在启动参数中配置 glog = cf.stable.glog = rtpp_log_open(&cf.stable, "rtpproxy", NULL, LF_REOPEN); //创建一个超时通知线程rtpp_notify_queue_run,绑定的socket端口为 -n传进来的参数 if (cf.timeout_socket != NULL) { cf.timeout_handler = rtpp_notify_init(glog, cf.timeout_socket); } //写pid到/var/run/rtpproxy.pid文件中 i = open(pid_file, O_WRONLY | O_CREAT | O_TRUNC, DEFFILEMODE); len = sprintf(buf, "%u\n", (unsigned int)getpid()); write(i, buf, len); close(i); //设置此进程的user ID和group ID,对应配置参数为-u uname:gname if (cf.stable.run_uname != NULL || cf.stable.run_gname != NULL) drop_privileges(&cf); cf.stable.controlfd = controlfd; cf.sessinfo.sessions[0] = NULL; cf.sessinfo.nsessions = 0; cf.rtp_nsessions = 0; //创建rtpp_cmd_queue_run线程监听和处理controlfd的数据 rtpp_command_async_init(&cf); sptime = 0; eptime = getdtime(); last_tick_time = 0; timeout = 1000 / POLL_RATE; for (;;) { delay = (eptime - sptime) * 1000000.0; if (delay <= 0) { sptime = eptime; last_tick_time = 0; } else if (delay < (1000000 / POLL_RATE)) { sptime += 1.0 / (double)POLL_RATE; usleep((1000000 / POLL_RATE) - delay); } else { sptime = eptime; } pthread_mutex_lock(&cf.sessinfo.lock); if (cf.sessinfo.nsessions > 0) { i = poll(cf.sessinfo.pfds, cf.sessinfo.nsessions, timeout); pthread_mutex_unlock(&cf.sessinfo.lock); if (i < 0 && errno == EINTR) continue; } else { pthread_mutex_unlock(&cf.sessinfo.lock); usleep(timeout * 1000); } eptime = getdtime(); if (eptime > last_tick_time + TIMETICK) { alarm_tick = 1; last_tick_time = eptime; } else { alarm_tick = 0; } pthread_mutex_lock(&cf.glock); process_rtp(&cf, eptime, alarm_tick); if (cf.rtp_nsessions > 0) { process_rtp_servers(&cf, eptime); } pthread_mutex_unlock(&cf.glock); } exit(0); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
初始化较为简洁,主要做了如下事项:
1. 启动参数的处理 2. log日志初始化 3. 创建两个线程,一个处理超时通知(socket端口为-s传进来的),一个监听控制命令(socket端口为-n传进来的) 4. 主程序处理循环