## 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=yes
|
|
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", 1)
|
|
modparam("dispatcher", "options_reply_codes", "501,403,404,400,200")
|
|
|
|
######################################################################
|
|
## 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;
|
|
}
|
|
|
|
# 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|originated from internal sources");
|
|
|
|
# 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|originated from external sources");
|
|
}
|
|
|
|
# we must forward SIP OPTIONS pings from FreeSWITCH to registered devices to keep NAT
|
|
# pinholes open. Someday we need to move this somewhere more reliable but this will
|
|
# do for now.
|
|
if (is_method("OPTIONS"))
|
|
{
|
|
if (isflagset(26))
|
|
{
|
|
xlog("L_INFO", "$ci|log|forwarding OPTIONS ping to endpoint");
|
|
|
|
route(internal_to_external_relay);
|
|
} else {
|
|
# this request came from an external device to us. Reject it
|
|
xlog("L_NOTICE", "$ci|end|unsupported method");
|
|
|
|
sl_send_reply("503", "Rawr!!");
|
|
|
|
}
|
|
|
|
exit;
|
|
}
|
|
|
|
# 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 we have locked this call to a media server then
|
|
# maintain that association
|
|
if (cache_fetch("local", "$ci", $avp(i:55)))
|
|
{
|
|
if (is_method("BYE"))
|
|
{
|
|
# remove the association between the call-id and the media server (if one)
|
|
# but leave the contact user and server to support transfers
|
|
cache_remove("local", "$ci");
|
|
|
|
xlog("L_INFO", "$ci|log|cleaned up call id from cache");
|
|
}
|
|
else if (isflagset(26))
|
|
{
|
|
cache_store("local", "$tU", "$avp(i:55)", 3600);
|
|
|
|
xlog("L_INFO", "$ci|log|maintaining associated $tU with media server $avp(i:55)");
|
|
}
|
|
else if ($ct.fields(uri))
|
|
{
|
|
cache_store("local", "$(ct.fields(uri){uri.user})", "$avp(i:55)", 3600);
|
|
|
|
xlog("L_INFO", "$ci|log|maintaining associated $(ct.fields(uri){uri.user}) with media server $avp(i:55)");
|
|
}
|
|
|
|
cache_store("local", "$ci", "$avp(i:55)", 3600);
|
|
}
|
|
|
|
xlog("L_INFO", "$ci|log|forwarding based on the route set");
|
|
|
|
if (isflagset(26))
|
|
{
|
|
route(internal_to_external_relay);
|
|
}
|
|
else
|
|
{
|
|
route(external_to_internal_relay);
|
|
}
|
|
|
|
exit();
|
|
}
|
|
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(logged_relay);
|
|
}
|
|
else
|
|
{
|
|
# ACK without matching transaction ->
|
|
# ignore and discard
|
|
xlog("L_NOTICE", "$ci|end|no matching transaction");
|
|
}
|
|
|
|
exit();
|
|
}
|
|
else if ( is_method("NOTIFY") )
|
|
{
|
|
route(logged_relay);
|
|
|
|
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(logged_relay);
|
|
}
|
|
# 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");
|
|
}
|
|
|
|
# remove the association between the call-id and the media server (if one)
|
|
# but leave the contact user and server to support transfers
|
|
cache_remove("local", "$ci");
|
|
|
|
xlog("L_INFO", "$ci|log|cleaned up call id from cache");
|
|
|
|
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", "The only winning move it not to play");
|
|
|
|
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|log|unable to add path");
|
|
|
|
sl_send_reply("503", "Internal path befuddlement");
|
|
|
|
# remove the association between the call-id and the media server (if one)
|
|
# but leave the contact user and server to support transfers
|
|
cache_remove("local", "$ci");
|
|
|
|
xlog("L_INFO", "$ci|end|cleaned up call id from cache");
|
|
|
|
exit;
|
|
}
|
|
|
|
xlog("L_INFO", "$ci|log|added path");
|
|
}
|
|
|
|
# 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");
|
|
}
|
|
|
|
# if the request is from a media server send it out
|
|
if (isflagset(26))
|
|
{
|
|
route(internal_to_external_relay);
|
|
|
|
exit();
|
|
}
|
|
|
|
# if the request is not from a media server it must be for one,
|
|
# there is much work to do!
|
|
|
|
# load a list of currently active media servers
|
|
# if no media server could be set with ds_select_domain then there are no
|
|
# active servers, no need to conitnue
|
|
if (!ds_select_domain("1", "4"))
|
|
{
|
|
xlog("L_ERR", "$ci|end|no servers avaliable");
|
|
|
|
sl_send_reply("480", "The cake is a lie!");
|
|
|
|
exit;
|
|
}
|
|
|
|
if (cache_fetch("local", "$ou", $avp(i:55)))
|
|
{
|
|
xlog("L_INFO", "$ci|log|request $ou is associated with media server $avp(i:55)");
|
|
|
|
cache_remove("local", "$ou");
|
|
|
|
cache_store("local", "$ci", "$avp(i:55)", 3600);
|
|
}
|
|
# 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)))
|
|
{
|
|
cache_store("local", "$ci", "$avp(i:55)", 3600);
|
|
|
|
xlog("L_INFO", "$ci|log|call-id is associated with media server $avp(i:55)");
|
|
}
|
|
# 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.
|
|
else if ($ct.fields(uri) && cache_fetch("local", "$(ct.fields(uri){uri.user})", $avp(i:55)))
|
|
{
|
|
cache_store("local", "$(ct.fields(uri){uri.user})", "$avp(i:55)", 3600);
|
|
|
|
xlog("L_INFO", "$ci|log|contact $(ct.fields(uri){uri.user}) is associated with media server $avp(i:55)");
|
|
}
|
|
# if the request is not from our media servers and no associations in localcache
|
|
# then use the distribute list as is
|
|
else
|
|
{
|
|
xlog("L_INFO", "$ci|log|routing call to arbitrary media server $rd:$rp");
|
|
}
|
|
|
|
# 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:55) && $(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");
|
|
|
|
if ($ct.fields(uri) && cache_fetch("local", "$ci", $avp(i:56)))
|
|
{
|
|
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");
|
|
}
|
|
|
|
# update the callid cache
|
|
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});
|
|
}
|
|
}
|
|
|
|
route(external_to_internal_relay);
|
|
}
|
|
|
|
route[external_to_internal_relay]
|
|
{
|
|
# 1. correct any nat issues
|
|
# 2. remove any X-AUTH-IP headers so we will be the only one to set it
|
|
# 3. set the X-AUTH-IP header for freeswitch ACLs
|
|
# 4. set the final reply timer to two seconds, so we failover faster
|
|
# 5. arm a logging branch for replies
|
|
# 6. arm a failure branch that will try another one of our media servers when possible
|
|
|
|
route("nat_test_and_correct");
|
|
|
|
remove_hf("X-AUTH-IP");
|
|
|
|
append_hf("X-AUTH-IP: $si\r\n");
|
|
|
|
xlog("L_INFO", "$ci|log|X-AUTH-IP: $si");
|
|
|
|
$avp(s:final_reply_timer) = 2;
|
|
|
|
t_on_reply("internal_reply");
|
|
|
|
t_on_failure("internal_fault");
|
|
|
|
route("logged_relay");
|
|
|
|
exit;
|
|
}
|
|
|
|
route[internal_to_external_relay]
|
|
{
|
|
# 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
|
|
|
|
$avp(s:final_reply_timer) = 6;
|
|
|
|
t_on_reply("external_reply");
|
|
|
|
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]
|
|
{
|
|
# 1. Contact header field is searched for occurrence of RFC1918 addresses
|
|
# if (nat_uac_test("1"))
|
|
# {
|
|
# xlog("L_INFO", "$ci|log|contact header field contains a RFC1918 address");
|
|
#
|
|
# fix_contact();
|
|
# }
|
|
|
|
# 2 - the "received" test is used: address in Via is compared against source IP address of signaling
|
|
if (nat_uac_test("2"))
|
|
{
|
|
xlog("L_INFO", "$ci|log|address in Via differs from source IP");
|
|
|
|
# adds the rport parameter to the first Via header
|
|
force_rport();
|
|
|
|
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
|
|
|
|
xlog("L_INFO", "$ci|start|recieved external reply $rs $rr");
|
|
xlog("L_INFO", "$ci|log|source $si:$sp");
|
|
|
|
# This ensures that if a endpoint recieves a call they can properly
|
|
# transfer that call
|
|
# TODO: this will track calls made to carriers when we start sending carrier
|
|
# traffic through opensips
|
|
# Target: A endpoint answering a call made from one of our media
|
|
# servers should lock that endpoint to the server
|
|
if (t_check_status("200") && is_method("INVITE") && $(fd{ip.isip}) && ds_is_in_list("$fd", "", "1"))
|
|
{
|
|
$var(d) = $(fu{uri.host});
|
|
|
|
if ($(fu{uri.port}) == 0)
|
|
{
|
|
$var(p) = 5060;
|
|
}
|
|
else
|
|
{
|
|
$var(p) = $(fu{uri.port});
|
|
}
|
|
|
|
if ($ct.fields(uri))
|
|
{
|
|
cache_store("local", "$(ct.fields(uri){uri.user})", "sip:$var(d):$var(p)", 3600);
|
|
|
|
xlog("L_INFO", "$ci|log|associated $(ct.fields(uri){uri.user}) with media server sip:$var(d):$var(p)");
|
|
}
|
|
|
|
cache_store("local", "$ci", "sip:$var(d):$var(p)", 3600);
|
|
|
|
xlog("L_INFO", "$ci|log|associated call-id with media server sip:$var(d):$var(p)");
|
|
}
|
|
|
|
if (is_method("BYE"))
|
|
{
|
|
# remove the association between the call-id and the media server (if one)
|
|
# but leave the contact user and server to support transfers
|
|
cache_remove("local", "$ci");
|
|
|
|
xlog("L_INFO", "$ci|log|cleaned up call id from cache");
|
|
}
|
|
|
|
route("nat_test_and_correct");
|
|
|
|
xlog("L_INFO", "$ci|pass|$(<request>si):$(<request>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
|
|
if(t_local_replied("last"))
|
|
{
|
|
xlog("L_INFO", "$ci|start|recieved local internal reply $T_reply_code $rr");
|
|
}
|
|
else
|
|
{
|
|
xlog("L_INFO", "$ci|start|recieved internal reply $T_reply_code $rr");
|
|
xlog("L_INFO", "$ci|log|source $si:$sp");
|
|
}
|
|
|
|
# Ensure that if we challenge an endpoint its response is not round-robin'd
|
|
# We have to do it in the reply so we have the correct call id
|
|
# Target: Endpoint intiated a request that was challenged, lock that
|
|
# call id to the challenging server so it recieves the reply
|
|
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");
|
|
}
|
|
|
|
if (is_method("BYE"))
|
|
{
|
|
# remove the association between the call-id and the media server (if one)
|
|
# but leave the contact user and server to support transfers
|
|
cache_store("local", "$ci", "sip:$si:$sp", 360);
|
|
|
|
xlog("L_INFO", "$ci|log|cleaned up call id from cache");
|
|
}
|
|
|
|
if ($rs < 300)
|
|
{
|
|
xlog("L_INFO", "$ci|pass|$(<request>si):$(<request>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]
|
|
{
|
|
# this branch handles failures (>=300) to our media servers,
|
|
# which we can sometimes overcome by routing to another server
|
|
|
|
# if the failure cause was due to the transaction being
|
|
# cancelled then we are complete
|
|
if (t_was_cancelled())
|
|
{
|
|
xlog("L_INFO", "$ci|log|transaction was cancelled");
|
|
|
|
# remove the association between the call-id and the media server (if one)
|
|
# but leave the contact user and server to support transfers
|
|
cache_remove("local", "$ci");
|
|
|
|
xlog("L_INFO", "$ci|end|cleaned up call id from cache");
|
|
|
|
exit;
|
|
}
|
|
|
|
# if the failure case was soemthing that we should recover
|
|
# from then try to find a new media server
|
|
if (t_check_status("(401)|(407)|(403)"))
|
|
{
|
|
xlog("L_INFO", "$ci|log|failure route ignoring auth reply $T_reply_code $rr");
|
|
}
|
|
else if (t_check_status("402"))
|
|
{
|
|
send_reply("486", "More money please");
|
|
|
|
exit();
|
|
}
|
|
else if (t_check_status("(4[0-9][0-9])|(5[0-9][0-9])"))
|
|
{
|
|
xlog("L_INFO", "$ci|start|received failure reply $T_reply_code $rr");
|
|
|
|
if (cache_fetch("local", "$ci-failure", $avp(i:55)))
|
|
{
|
|
$avp(i:55) = $(avp(i:55){s.int});
|
|
}
|
|
else
|
|
{
|
|
$avp(i:55) = 0;
|
|
}
|
|
|
|
xlog("L_INFO", "$ci|log|attempting retry $avp(i:55) of failed request");
|
|
|
|
# try to find a new media server to send the call to
|
|
if($avp(i:55) < 3 && 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");
|
|
}
|
|
|
|
# reset the final reply timer
|
|
$avp(s:final_reply_timer) = 2;
|
|
|
|
t_on_reply("internal_reply");
|
|
|
|
t_on_failure("internal_fault");
|
|
|
|
xlog("L_INFO", "$ci|pass|$rd:$rp");
|
|
|
|
# relay the request to the new media server
|
|
t_relay();
|
|
|
|
$avp(i:55) = $avp(i:55) + 1;
|
|
|
|
cache_store("local", "$ci-failure", "$avp(i:55)", 60);
|
|
|
|
exit();
|
|
}
|
|
else
|
|
{
|
|
cache_remove("local", "$ci-failure");
|
|
|
|
xlog("L_ERR", "$ci|log|no other media servers avaliable");
|
|
}
|
|
}
|
|
else if (t_check_status("302"))
|
|
{
|
|
if( $(<reply>hdr(X-Redirect-Server)) && $(<reply>ct.fields(uri)) )
|
|
{
|
|
$var(redirect_host) = $(<reply>hdr(X-Redirect-Server){uri.host});
|
|
|
|
$var(redirect_port) = $(<reply>hdr(X-Redirect-Server){uri.port});
|
|
|
|
cache_store("local", "$(<reply>ct.fields(uri))", "sip:$var(redirect_host):$var(redirect_port)", 60);
|
|
|
|
xlog("L_INFO", "$ci|log|stored redirect mapping for $(<reply>ct.fields(uri)) to sip:$var(redirect_host):$var(redirect_port)");
|
|
|
|
remove_hf("X-Redirect-Server");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xlog("L_INFO", "$ci|log|failure route ignoring reply $T_reply_code $rr");
|
|
}
|
|
|
|
if (!t_check_status("(407)|(401)|(302)"))
|
|
{
|
|
# remove the association between the call-id and the media server (if one)
|
|
# but leave the contact user and server to support transfers
|
|
cache_remove("local", "$ci");
|
|
|
|
xlog("L_INFO", "$ci|log|cleaned up call id from cache");
|
|
}
|
|
|
|
xlog("L_INFO", "$ci|pass|$(<request>si):$(<request>sp)");
|
|
|
|
# if no new branch is generated or no reply is forced over, by default,
|
|
# the winning reply will be sent back to UAC.
|
|
}
|
|
|
|
|
|
# For VIM:
|
|
# vim: set expandtab softtabstop=4 shiftwidth=2 tabstop=2:
|