diff --git a/autoload_configs/acl.conf.xml b/autoload_configs/acl.conf.xml index 4e820d0..8f0e317 100644 --- a/autoload_configs/acl.conf.xml +++ b/autoload_configs/acl.conf.xml @@ -1,6 +1,18 @@ - + + + + + + + + + + + + + diff --git a/autoload_configs/conference.conf.xml b/autoload_configs/conference.conf.xml index 8b119dd..8add428 100644 --- a/autoload_configs/conference.conf.xml +++ b/autoload_configs/conference.conf.xml @@ -1,174 +1,118 @@ - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - \ No newline at end of file + diff --git a/autoload_configs/directory.conf.xml b/autoload_configs/directory.conf.xml deleted file mode 100644 index 1704d16..0000000 --- a/autoload_configs/directory.conf.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/autoload_configs/event_multicast.conf.xml b/autoload_configs/event_multicast.conf.xml deleted file mode 100644 index 846dbc2..0000000 --- a/autoload_configs/event_multicast.conf.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/autoload_configs/fifo.conf.xml b/autoload_configs/fifo.conf.xml deleted file mode 100644 index c20b6a4..0000000 --- a/autoload_configs/fifo.conf.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/autoload_configs/ivr.conf.xml b/autoload_configs/ivr.conf.xml deleted file mode 100644 index 93a4ad3..0000000 --- a/autoload_configs/ivr.conf.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/autoload_configs/modules.conf.xml b/autoload_configs/modules.conf.xml index dea1ca9..9656049 100644 --- a/autoload_configs/modules.conf.xml +++ b/autoload_configs/modules.conf.xml @@ -10,7 +10,6 @@ - @@ -25,40 +24,35 @@ - - - - - - + + - - + - + + + - - diff --git a/autoload_configs/shout.conf.xml b/autoload_configs/shout.conf.xml new file mode 100644 index 0000000..a90bebf --- /dev/null +++ b/autoload_configs/shout.conf.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/autoload_configs/switch.conf.xml b/autoload_configs/switch.conf.xml index 36cfed8..ad2e5d4 100644 --- a/autoload_configs/switch.conf.xml +++ b/autoload_configs/switch.conf.xml @@ -26,8 +26,8 @@ - - + + @@ -45,4 +45,4 @@ - \ No newline at end of file + diff --git a/autoload_configs/voicemail.conf.xml b/autoload_configs/voicemail.conf.xml deleted file mode 100644 index de8f6f2..0000000 --- a/autoload_configs/voicemail.conf.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/freeswitch.limits.conf b/freeswitch.limits.conf new file mode 100644 index 0000000..02d3dff --- /dev/null +++ b/freeswitch.limits.conf @@ -0,0 +1,15 @@ +freeswitch soft core unlimit +freeswitch soft data unlimit +freeswitch soft fsize unlimit +freeswitch soft memlock unlimit +freeswitch soft nofile 999999 +freeswitch soft rss unlimit +freeswitch hard stack 240 +freeswitch soft cpu unlimit +freeswitch soft nproc unlimit +freeswitch soft as unlimit +freeswitch soft priority -11 +freeswitch soft locks unlimit +freeswitch soft sigpending unlimit +freeswitch soft msgqueue unlimit +freeswitch soft nice -11 diff --git a/freeswitch.xml b/freeswitch.xml index 720124a..86a9db1 100644 --- a/freeswitch.xml +++ b/freeswitch.xml @@ -1,14 +1,43 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + +
@@ -29,4 +58,5 @@ +
diff --git a/ivr_menus/empty.xml b/ivr_menus/empty.xml deleted file mode 100644 index dd68d75..0000000 --- a/ivr_menus/empty.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/opensips/dispatcher.sh b/opensips/dispatcher.sh new file mode 100755 index 0000000..50ae2ee --- /dev/null +++ b/opensips/dispatcher.sh @@ -0,0 +1,56 @@ +#!/bin/bash +DISPATCHER_FILE="/usr/local/etc/opensips/dispatcher.list" +OSIP_CTL="/usr/local/etc/opensips/opensipsctl" + +fUsage () { + echo "Usage: $0 [-r reload] [-f flush] [Media Server IP] [-a active] [-i inactive] [-p probing]" + exit 1 +} + +cd `dirname $0` + +[[ ! $1 == -* ]] && server=$1 && shift + +while [ -n "$*" ]; do + case "x$1" in + x-a) + action="a" + ;; + x-i) + action="i" + ;; + x-p) + action="p" + ;; + x-r) + action="r" + ;; + x-f) + action="f" + ;; + x--help) + fUsage + ;; + *) + fUsage + ;; + esac + shift +done + +if [ -z $action ]; then + echo "# $OSIP_CTL fifo ds_list" + $OSIP_CTL fifo ds_list + exit 0 +elif [ $action == "r" ]; then + echo "# $OSIP_CTL fifo ds_reload" + $OSIP_CTL fifo ds_reload + exit 0 +elif grep -q $server $DISPATCHER_FILE; then + echo "# $OSIP_CTL fifo ds_set_state $action `grep $server $DISPATCHER_FILE | cut -d' ' -f 1` `grep $server $DISPATCHER_FILE | cut -d' ' -f 2`" + $OSIP_CTL fifo ds_set_state $action `grep $server $DISPATCHER_FILE | cut -d' ' -f 1` `grep $server $DISPATCHER_FILE | cut -d' ' -f 2` + exit 0 +else + echo "ERROR: Could not locate $server in $DISPATCHER_FILE" + exit 1 +fi diff --git a/opensips/opensips.tmp b/opensips/opensips.tmp new file mode 100644 index 0000000..b1aee30 --- /dev/null +++ b/opensips/opensips.tmp @@ -0,0 +1,842 @@ +## TEMPLATE RENDER CMD: sed "s|{{SIP_IP}}|184.106.171.135|g;s|{{SIP_PORT}}|5060|g;s|{{SIP_TLS_PORT}}|5061|g" opensips.tmp > opensips.cfg +###################################################################### +## Core Parameters +###################################################################### +# chroot= +# group="opensips" +# user="opensips" +# dbversion_table= +disable_core_dump=no +max_while_loops=100 +maxbuffer=262144 +memdump=3 +memlog=2 +# open_files_limit=2048 +server_signature=no +server_header="Server: 2600hz" +user_agent_header="User-Agent: 2600hz" + +###################################################################### +## Core Fork Parameters +###################################################################### +fork=yes +children=8 +tcp_children=8 + +###################################################################### +## Core Logging Parameters +###################################################################### +debug=3 +sip_warning=0 +log_stderror=no +log_facility=LOG_LOCAL0 +log_name="opensips" + +###################################################################### +## Aliases +###################################################################### +auto_aliases=yes +alias=localhost +alias=localhost.localdomain + +###################################################################### +## Connectivity +###################################################################### +listen=udp:eth0:{{SIP_PORT}} +listen=udp:eth0:7000 +listen=tcp:eth0:{{SIP_PORT}} +listen=tcp:eth0:7000 +tos=IPTOS_LOWDELAY +# advertised_address={{SIP_IP}} +# advertised_port={{SIP_PORT}} +mcast_loopback=no +mcast_ttl=1 +mhomed=0 +# tcp_accept_aliases +tcp_connect_timeout=3 +tcp_connection_lifetime=120 +tcp_max_connections=2048 +# tcp_poll_method=select + +###################################################################### +## DNS +###################################################################### +dns=no +dns_retr_time=1 +dns_retr_no=3 +# dns_servers_no=2 +dns_try_ipv6=no +disable_dns_blacklist=yes +disable_dns_failover=no +dns_use_search_list=no +rev_dns=no + +###################################################################### +## SIP +###################################################################### +check_via=0 +#! disable_503_translation=no +disable_stateless_fwd=no +disable_tcp=no +# disable_tls=no +#! reply_to_via=1 + +###################################################################### +## TLS +###################################################################### +# disable_tls=no +# listen=tls:{{SIP_IP}}:{{SIP_TLS_PORT}} +# tls_verify_server=1 +# tls_verify_client=1 +# tls_require_client_certificate=0 +# tls_method=TLSv1 +# tls_certificate="/usr/local/etc/opensips/tls/user/user-cert.pem" +# tls_private_key="/usr/local/etc/opensips/tls/user/user-privkey.pem" +# tls_ca_list="/usr/local/etc/opensips/tls/user/user-calist.pem" + +###################################################################### +## Destination Blacklist +###################################################################### +# dst_blacklist=gw:{( tcp , 192.168.2.100 , 5060 , "" ),( any , 192.168.2.101 , 0 , "" )} +# dst_blacklist=net_filter2:{ !( any , 192.168.30.0/255.255.255.0 , 0 , "" )} + +###################################################################### +## Attribute Value Pairs +###################################################################### +# avp_aliases="uuid=I:660;email=s:email_addr;fwd=i:753" + +###################################################################### +## Module Loading +###################################################################### +mpath="/usr/lib64/opensips/modules/" +loadmodule "localcache.so" +loadmodule "signaling.so" +loadmodule "sl.so" +loadmodule "tm.so" +loadmodule "dialog.so" +loadmodule "maxfwd.so" +loadmodule "rr.so" +loadmodule "path.so" +loadmodule "uri.so" +loadmodule "textops.so" +loadmodule "usrloc.so" +loadmodule "nathelper.so" +loadmodule "nat_traversal.so" +loadmodule "uac_redirect.so" +loadmodule "dispatcher.so" +loadmodule "mi_fifo.so" +# loadmodule "mi_datagram.so" +# loadmodule "xlog.so" + +###################################################################### +## Localcache Module Parameters +###################################################################### +modparam("localcache", "cache_table_size", 10) +modparam("localcache", "cache_clean_period", 120) + +###################################################################### +## Stateless UA Module Parameters +###################################################################### +modparam("sl", "enable_stats", 1) + +###################################################################### +## SIP Transaction UA Module Parameters +###################################################################### +modparam("tm", "fr_timer", 2) +modparam("tm", "fr_inv_timer", 120) +# modparam("tm", "wt_timer", 5) +# modparam("tm", "delete_timer", 2) +# modparam("tm", "T1_timer", 500) +# modparam("tm", "T2_timer", 4000) +# modparam("tm", "ruri_matching", 1) +# modparam("tm", "via1_matching", 1) +# modparam("tm", "unix_tx_timeout", 2) +# modparam("tm", "restart_fr_on_each_reply", 1) +modparam("tm", "fr_timer_avp", "$avp(s:final_reply_timer)") +# modparam("tm", "fr_inv_timer_avp", "$avp(s:final_reply_prov)") +# modparam("tm", "tw_append", +# "test: ua=$hdr(User-Agent) ;avp=$avp(i:10);$rb;time=$Ts") +modparam("tm", "pass_provisional_replies", 1) +# modparam("tm", "syn_branch", 1) +# modparam("tm", "onreply_avp_mode", 0) +# modparam("tm", "disable_6xx_block", 0) +# modparam("tm", "enable_stats", 1) +# modparam("tm", "minor_branch_flag", 3) + +###################################################################### +## Max Forward Module Parameters +###################################################################### +modparam("maxfwd", "max_limit", 30) + +###################################################################### +## Record Route Module Parameters +###################################################################### +modparam("rr", "enable_full_lr", 1) +modparam("rr", "append_fromtag", 1) +modparam("rr", "enable_double_rr", 0) +modparam("rr", "add_username", 0) + +###################################################################### +## Path Module Parameters +###################################################################### +modparam("path", "use_received", 1) + +###################################################################### +## URI Module Parameters +###################################################################### +# modparam("uri", "aaa_url", "radius:/etc/radiusclient-ng/radiusclient.conf") +modparam("uri", "use_sip_uri_host", 0) +modparam("uri", "use_uri_table", 0) +modparam("uri", "service_type", 10) +modparam("uri", "use_domain", 1) +modparam("uri", "use_uri_table", 0) +# modparam("uri", "db_url", "mysql://username:password@localhost/opensips") +# modparam("uri", "db_table", "uri") +# modparam("uri", "user_column", "username") +# modparam("uri", "domain_column", "domain") +# modparam("uri", "uriuser_column", "uri_user") + +###################################################################### +## User Location Module Parameters +###################################################################### +modparam("usrloc", "nat_bflag", 6) +modparam("usrloc", "use_domain", 1) +modparam("usrloc", "desc_time_order", 0) +modparam("usrloc", "timer_interval", 60) +modparam("usrloc", "matching_mode", 0) +modparam("usrloc", "cseq_delay", 20) +modparam("usrloc", "hash_size", 9) +modparam("usrloc", "db_mode", 0) +# modparam("usrloc", "db_url", "dbdriver://username:password@dbhost/dbname") +modparam("usrloc", "fetch_rows", 2000) +modparam("usrloc", "user_column", "username") +modparam("usrloc", "domain_column", "domain") +modparam("usrloc", "contact_column", "contact") +modparam("usrloc", "expires_column", "expires") +modparam("usrloc", "q_column", "q") +modparam("usrloc", "callid_column", "callid") +modparam("usrloc", "cseq_column", "cseq") +modparam("usrloc", "methods_column", "methods") +modparam("usrloc", "flags_column", "flags") +modparam("usrloc", "cflags_column", "cflags") +modparam("usrloc", "user_agent_column", "user_agent") +modparam("usrloc", "received_column", "received") +modparam("usrloc", "socket_column", "socket") +modparam("usrloc", "path_column", "path") + +###################################################################### +## Nathelper Module Parameters +###################################################################### +# modparam("nathelper", "rtpproxy_sock", "udp:127.0.0.1:7890") +# modparam("nathelper", "natping_interval", 30) +# modparam("nathelper", "ping_nated_only", 1) +# modparam("nathelper", "natping_processes", 3) +# modparam("nathelper", "sipping_bflag", 7) +# modparam("nathelper", "sipping_from", "sip:sipcheck@{{SIP_IP}}:{{SIP_PORT}}") +# modparam("nathelper", "sipping_method", "INFO") + +###################################################################### +## NAT Traversal Module Parameters +###################################################################### +modparam("nat_traversal", "keepalive_interval", 60) +modparam("nat_traversal", "keepalive_method", "OPTIONS") +modparam("nat_traversal", "keepalive_from", "sip:keepalive@{{SIP_IP}}:{{SIP_PORT}}") +modparam("nat_traversal", "keepalive_state_file", "/tmp/opensips_keepalive_state") + +###################################################################### +## UAC Redirect Module Parameters +###################################################################### +modparam("uac_redirect", "default_filter", "accept") +# modparam("uac_redirect", "deny_filter", NULL) +# modparam("uac_redirect", "accept_filter", NULL) +# modparam("uac_redirect", "acc_function", "acc_log_request") +# modparam("uac_redirect", "acc_db_table", "acc") + +###################################################################### +## Dispatcher Module Parameters +###################################################################### +modparam("dispatcher", "list_file", "/etc/opensips/dispatcher.list") +modparam("dispatcher", "flags", 2) +modparam("dispatcher", "use_default", 0) +modparam("dispatcher", "force_dst", 1) +modparam("dispatcher", "dst_avp", "$avp(i:271)") +modparam("dispatcher", "attrs_avp", "$avp(i:272)") +modparam("dispatcher", "grp_avp", "$avp(i:273)") +modparam("dispatcher", "cnt_avp", "$avp(i:274)") +modparam("dispatcher", "hash_pvar", "$avp(i:273)") +# modparam("dispatcher", "setid_pvar", "$var(setid)") +modparam("dispatcher", "ds_ping_method", "OPTIONS") +modparam("dispatcher", "ds_ping_from", "sip:sipcheck@{{SIP_IP}}:{{SIP_PORT}}") +modparam("dispatcher", "ds_ping_interval", 10) +# modparam("dispatcher", "ds_ping_sock", "udp:{{SIP_IP}}:{{SIP_PORT}}") +modparam("dispatcher", "ds_probing_threshhold", 3) +modparam("dispatcher", "ds_probing_mode", 0) +modparam("dispatcher", "options_reply_codes", "501, 403, 404, 400") + +###################################################################### +## MI-FIFO Module Parameters +###################################################################### +modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo") + +###################################################################### +## MI-Datagram Module Parameters +###################################################################### +# modparam("mi_datagram", "socket_name", "udp:127.0.0.1:8889") +# modparam("mi_datagram", "children_count", 1) +# modparam("mi_datagram", "unix_socket_mode", 0600) +# modparam("mi_datagram", "unix_socket_group", "root") +# modparam("mi_datagram", "unix_socket_user", "root") +# modparam("mi_datagram", "socket_timeout", 2000) +# modparam("mi_datagram", "reply_indent", "\t") + +###################################################################### +## XLog Module Parameters +###################################################################### +# modparam("xlog", "buf_size", 4096) +# modparam("xlog", "force_color", 0) + +###################################################################### +## Multiple Module Parameters +###################################################################### + + +###################################################################### +## Main Request Routing +###################################################################### +route +{ + # log the basic info regarding this call + xlog("L_INFO", "$ci|start|recieved $oP request $rm $ou"); + xlog("L_INFO", "$ci|log|source $si:$sp"); + xlog("L_INFO", "$ci|log|from $fu"); + xlog("L_INFO", "$ci|log|to $tu"); + + # check that hop cound for this request and make sure it is under 10 + # to prevent endless loops + if (!mf_process_maxfwd_header("10")) + { + xlog("L_WARN", "$ci|end|to many hops"); + + sl_send_reply("483", "We refuse to process this endless imbroglio"); + + exit; + } + + # this check detemines if the opensips has routed the request to itself, + # this happens because the server is the destination of the request but + # we mangle it to send it else where. When that mangeling fails and we + # still relay it then it just comes right back to us... + if (src_ip==myself) + { + xlog("L_WARN", "$ci|end|sourced from this server"); + + exit; + } + + # currently we dont support subscribe in whistle so to keep the noise down + # just end the request here. For options just end the request here as well. + if (is_method("OPTIONS|SUBSCRIBE")) + { + xlog("L_NOTICE", "$ci|end|unsupported method"); + + sl_send_reply("503", "Rawr!!"); + + exit; + } + + # if the source IP/port are in one of the server dispatch lists + # then this request originated from one of our media servers, mark it + # as such by setting flag 26 + if (ds_is_in_list("$si", "", "1")) + { + xlog("L_INFO", "$ci|log|internal inception (from media server)"); + + # Flag 26 marks the source as a on-net server + setflag(26); + + setbflag(26); + } + # if the request source IP/port was not in any dispatcher lists + # this this originated outside our equipment (carrier, client, ect) + else + { + xlog("L_INFO", "$ci|log|external inception"); + } + + # if the to header has a tag attached then it implies this request + # has been processed by us before (IE: a media server has added + # its tag on the to header in prior messages) + if (has_totag()) + { + # sequential request within a dialog should + # take the path determined by record-routing + if (loose_route()) + { + append_hf("P-hint: rr-enforced\r\n"); + + # if the request is an ACK from our media servers with a IP in the from domain + # then bump the association + #if ($(fd{ip.isip}) && isflagset(26) && is_method("ACK")) + #{ + #cache_store("local", "$tU", "$fd", 3600); + + #xlog("L_INFO", "$ci|log|maintaining contact association to media server $fd"); + #} + + xlog("L_INFO", "$ci|log|forwarding based on the route set"); + + route(correct_transmit_and_die); + } + else if ( is_method("ACK") ) + { + if ( t_check_trans() ) + { + # non loose-route, but stateful ACK; must be an ACK after + # a 487 or e.g. 404 from upstream server + xlog("L_INFO", "$ci|log|in dialog request belongs to a known transaction"); + + route(correct_transmit_and_die); + } + else + { + # ACK without matching transaction -> + # ignore and discard + xlog("L_NOTICE", "$ci|end|no matching transaction"); + + exit; + } + } + + # request with a to tag that cant be routed loosly and is not an ACK + # ignor eand discard + xlog("L_WARN", "$ci|end|could not route in dialog"); + + sl_send_reply("486", "PC Load Letter"); + + exit; + } + + # if the request is to cancel a transaction process it now + if (is_method("CANCEL")) + { + # If this cancel is part of a transaction + # then pass it along to concerned parties + if (t_check_trans()) + { + xlog("L_INFO", "$ci|log|request belogs to a known transaction"); + + route(correct_transmit_and_die); + } + # if the cancel does not belong to a known transaction or a + # request that has not progressed outside this server dont relay it + else + { + xlog("L_NOTICE", "$ci|end|no matching transaction"); + } + + exit; + } + + # If this is a retransmission it will break/stop the script + # and do standard processing of the message + t_check_trans(); + + # Except for an ACK no request should have a route set with no to tag, this would + # indicate that the intial request has the Route headers and is likely someone trying + # to get us to send the request were they want + if (loose_route()) + { + if (!is_method("ACK")) + { + xlog("L_WARN", "$ci|end|initial request contained a preloaded route set"); + + sl_send_reply("403", "Please leave the routing up to us"); + + exit; + } + } + + # If the request is a register we will pass it along but we need + # to add the path header (along with the received IP/port info) + if (is_method("REGISTER")) + { + # if we fail to add the path header then dont let it + # register because it will cause issues later... + if (!add_path_received()) + { + xlog("L_ERR", "$ci|end|unable to add path"); + + sl_send_reply("503", "Internal path befuddlement"); + + exit; + } + + xlog("L_INFO", "$ci|log|added path"); + } + + # if the request is not from a media server it must be for one, load a list of + # currently active servers + if (!isflagset(26)) + { + if (ds_select_domain("1", "4")) + { + xlog("L_INFO", "$ci|log|loaded media server list"); + } + # if no media server could be set with ds_select_domain then there are no + # active servers, no need to conitnue + else + { + xlog("L_ERR", "$ci|end|no servers avaliable"); + + sl_send_reply("503", "The cake is a lie!"); + + exit; + } + } + + # if the request is not from our media severs but has a contact uri in localcache + # then change the routing to go to the server previously associated with it. + if ($ct.fields(uri) && cache_fetch("local", "$(ct.fields(uri){uri.user})", $avp(i:55))) + { + xlog("L_INFO", "$ci|log|contact $(ct.fields(uri){uri.user}) is associated with media server $avp(i:55)"); + + # if the dispatcher list (in 271) does not start with + # the request domain/port that we are sending this call + # to, re-order the list so that it does + if($(avp(i:271)[0]) != $avp(i:55)) + { + # create a index var for our loop (arrays are start at 0 and this is a count) + $var(i) = $avp(i:274) - 1; + + # loop over the dispatcher list + while($var(i) > 0) + { + # if this element in the dispatch list is the same + # as the call destination + if($(avp(i:271)[$var(i)]) == $avp(i:55)) + { + # replace it with the first element of the list + $(avp(i:271)[$(var(i))]) = $(avp(i:271)[0]); + + # break out of the loop + $var(i) = -1; + } + + $var(i) = $var(i) - 1; + } + + # handles the case were we only have two servers + # and the one that we are locked to has failed + if ($var(i) >= 0) + { + xlog("L_INFO", "$ci|log|associated media server is inactive, moving to $rd"); + + # leave the randomly choosen server as the destination and + # overwrite the cache + cache_store("local", "$(ct.fields(uri){uri.user})", "sip:$rd:$rp", 3600); + + cache_store("local", "$ci", "sip:$rd:$rp", 3600); + } + # the server we are locked to is in the active server list from then + # dispatcher so re-arrange the list to try it first + else + { + xlog("L_INFO", "$ci|log|re-ordering the dispatcher list to keep associated server first"); + + # set the first element of the list to the destination + $(avp(i:271)[0]) = $avp(i:55); + + # set the domain for this request (server IP to route to) + $rd = $(avp(i:55){uri.host}); + + # set the port for this request (server IP to route to) + $rp = $(avp(i:55){uri.port}); + } + } + } + # if the request is not from our media severs but has a call-id in localcache + # then change the routing to go to the server previously associated with it. + else if (cache_fetch("local", "$ci", $avp(i:55))) + { + xlog("L_INFO", "$ci|log|call-id is associated with media server $avp(i:55)"); + + # if the dispatcher list (in 271) does not start with + # the request domain/port that we are sending this call + # to, re-order the list so that it does + if($(avp(i:271)[0]) != $avp(i:55)) + { + # create a index var for our loop (arrays are start at 0 and this is a count) + $var(i) = $avp(i:274) - 1; + + # loop over the dispatcher list + while($var(i) > 0) + { + # if this element in the dispatch list is the same + # as the call destination + if($(avp(i:271)[$var(i)]) == $avp(i:55)) + { + # replace it with the first element of the list + $(avp(i:271)[$(var(i))]) = $(avp(i:271)[0]); + + # break out of the loop + $var(i) = -1; + } + + $var(i) = $var(i) - 1; + } + + # handles the case were we only have two servers + # and the one that we are locked to has failed + if ($var(i) >= 0) + { + xlog("L_INFO", "$ci|log|associated media server is inactive, moving to $rd"); + + # leave the randomly choosen server as the destination and + # overwrite the cache + cache_store("local", "$(ct.fields(uri){uri.user})", "sip:$rd:$rp", 3600); + + cache_store("local", "$ci", "sip:$rd:$rp", 3600); + } + # the server we are locked to is in the active server list from then + # dispatcher so re-arrange the list to try it first + else + { + xlog("L_INFO", "$ci|log|re-ordering the dispatcher list to keep associated server first"); + + # set the first element of the list to the destination + $(avp(i:271)[0]) = $avp(i:55); + + # set the domain for this request (server IP to route to) + $rd = $(avp(i:55){uri.host}); + + # set the port for this request (server IP to route to) + $rp = $(avp(i:55){uri.port}); + } + } + + if ($ct.fields(uri) && is_method("INVITE")) + { + cache_store("local", "$(ct.fields(uri){uri.user})", "sip:$rd:$rp", 3600); + + xlog("L_INFO", "$ci|log|associated contact $(ct.fields(uri){uri.user}) with media server sip:$rd:$rp"); + } + } + # if the request is not from our media servers and no associations in localcache + # then used the distribute list as is + else if (!isflagset(26)) + { + xlog("L_INFO", "$ci|log|routing call to arbitrary media server $rd:$rp"); + } + + # for all initial request (not having been processed above in the has_totag) + # that are not a register or message add this sever to the route set on the + # request so subsequent messages come through this server + if (!is_method("REGISTER|MESSAGE")) + { + # Record the route that this request has taken + # so we remain in the signaling path + record_route(); + + xlog("L_INFO", "$ci|log|added this server to the route set"); + } + + route(correct_transmit_and_die); +} + +route[correct_transmit_and_die] +{ + # if the request is from a media server then assume it is going somewhere + # outside our control and give that equipment longer to respond. + # Also arm a branch to log the replies + if (isflagset(26) || isbflagset(26)) + { + xlog("L_INFO", "$ci|log|provisional reply required in 6 seconds"); + + $avp(s:final_reply_timer) = 6; + + t_on_reply("external_reply"); + } + # otherwise the request must be for a media server + # 1. remove any X-AUTH-IP headers so we will be the only one to set it + # 2. set the X-AUTH-IP header for freeswitch ACLs + # 3. set the final reply timer to two seconds, so we failover faster + # 4. arm a logging branch for replies + # 5. arm a failure branch that will try another one of our media servers when possible + else + { + route("nat_test_and_correct"); + + remove_hf("X-AUTH-IP"); + + xlog("L_INFO", "$ci|log|X-AUTH-IP: $si"); + + append_hf("X-AUTH-IP: $si\r\n"); + + xlog("L_INFO", "$ci|log|provisional reply required in 2 seconds"); + + $avp(s:final_reply_timer) = 2; + + t_on_reply("internal_reply"); + + t_on_failure("internal_fault"); + } + + route("logged_relay"); + + exit; +} + +route[logged_relay] +{ + # try to send the request on its way, if it fails send back a + # stateless error to the requestor + if (t_relay()) + { + xlog("L_INFO", "$ci|pass|$rd:$rp"); + } + else + { + xlog("L_ERR", "$ci|end|unable to relay message"); + + sl_reply_error(); + } +} + +route[nat_test_and_correct] +{ + # check if the request is from a client behind NAT, and fix if so... + # this check looks at: + # 1. if client has a private IP address (as defined by RFC1918) in the Contact field of the SIP message + # 2. if client has contacted OpenSIPS from an address that is different from the one in the Via field + if (client_nat_test("3")) + { + xlog("L_INFO", "$ci|log|via address differs from source or RFC1918 address in contact"); + + # adds the rport parameter to the first Via header + force_rport(); + + # will replace the IP and port in the Contact header with the IP and port + # the SIP message was received from + fix_contact(); + } + + # if the request has a body see if it needs NAT corrections as well, + # this check looks at: + # 8. SDP is searched for occurrence of RFC1918 addresses + if (has_body("application/sdp") && nat_uac_test("8")) + { + xlog("L_INFO", "$ci|log|SDP contains a RFC1918 address"); + + # alters the SDP information in order to facilitate NAT traversal. + # 2. rewrite media IP address (c=) with source IP + # 8. rewrite IP from origin description (o=) with source IP + fix_nated_sdp("10"); + } +} + +onreply_route[external_reply] +{ + # this branch handles replies that are comming from equipment + # outside our control, just logging and NAT corrections + xlog("L_INFO", "$ci|start|recieved external reply $rs $rr"); + xlog("L_INFO", "$ci|log|source $si:$sp"); + + route("nat_test_and_correct"); + + xlog("L_INFO", "$ci|pass|$(si):$(sp)"); + + # if the reply is not dropped (only provisional replies can be), + # it will be injected and processed by the transaction engine. +} + +onreply_route[internal_reply] +{ + # this branch handles replies that are comming from our + # media server, just logging and NAT corrections + xlog("L_INFO", "$ci|start|recieved internal reply $rs $rr"); + xlog("L_INFO", "$ci|log|source $si:$sp"); + + # if one of our media servers has replied with a 407 or 401 associate + # this call-id with that media server so the next "initial" requests + # go to it (IE: the reply to the challenge) + if (t_check_status("(407)|(401)") && $(si{ip.isip}) && ds_is_in_list("$si", "", "1")) + { + cache_store("local", "$ci", "sip:$si:$sp", 3600); + + xlog("L_INFO", "$ci|log|associated call-id with media server sip:$si:$sp"); + } + + xlog("L_INFO", "$ci|pass|$(si):$(sp)"); + + # if the reply is not dropped (only provisional replies can be), + # it will be injected and processed by the transaction engine. +} + +failure_route[internal_fault] +{ + # if the failure cause was due to the transaction being + # cancelled then we are complete + if (t_was_cancelled()) + { + xlog("L_INFO", "$ci|end|transaction was cancelled"); + + exit; + } + + # if the failure case was soemthing that we should recover + # from then try to find a new media server + if (t_check_status("(408)|(5[0-9][0-9])")) + { + xlog("L_INFO", "$ci|start|recieved or generated negative reply (>=300)"); + xlog("L_INFO", "$ci|log|source $si:$sp"); + + xlog("L_ERR", "$ci|log|moving media server $rd:$rp to probing mode"); + + # flag the media server that failed and start sending SIP pings + # when it begins responding put it back in the lsit + ds_mark_dst("p"); + + # ensure the endpoint is not locked to a failed server + cache_remove("local", "$(ct.fields(uri){uri.user})"); + cache_remove("local", "$ci"); + + # try to find a new media server to send the call to + if(ds_next_domain()) + { + xlog("L_INFO", "$ci|log|routing call to next media server $rd:$rp"); + + # store the new callid association + cache_store("local", "$ci", "sip:$rd:$rp", 3600); + + # if the request has a contact and is an INVITE then store the new + # association + if ($ct.fields(uri) && is_method("INVITE")) + { + cache_store("local", "$(ct.fields(uri){uri.user})", "sip:$rd:$rp", 3600); + + xlog("L_INFO", "$ci|log|associated contact $(ct.fields(uri){uri.user}) with media server sip:$rd:$rp"); + } + + xlog("L_INFO", "$ci|pass|$rd:$rp"); + + # reset the final reply timer + $avp(s:final_reply_timer) = 2; + + t_on_reply("internal_reply"); + + t_on_failure("internal_fault"); + + # relay the request to the new media server + t_relay(); + + exit(); + } + else + { + xlog("L_ERR", "$ci|end|no other media servers avaliable"); + } + } + + # if no new branch is generated or no reply is forced over, by default, + # the winning reply will be sent back to UAC. +} \ No newline at end of file diff --git a/sip_profiles/sipinterface_1.xml b/sip_profiles/sipinterface_1.xml index 46bab36..0ea6450 100644 --- a/sip_profiles/sipinterface_1.xml +++ b/sip_profiles/sipinterface_1.xml @@ -5,7 +5,7 @@ - + @@ -44,7 +44,7 @@ - + @@ -65,11 +65,11 @@ - + - + @@ -97,11 +97,13 @@ - + - + + +