## NOTE: DO NOT CHANGE THIS FILE, EDIT local.cfg ##
|
|
|
|
####### Flags #######
|
|
flags
|
|
FLAG_INTERNALLY_SOURCED: 1,
|
|
FLAG_ASSOCIATE_SERVER: 2,
|
|
FLAG_SKIP_NAT_CORRECTION: 3,
|
|
FLAG_ASSOCIATE_USER: 4,
|
|
FLAG_TRUSTED_SOURCE: 5,
|
|
FLAG_SESSION_PROGRESS: 6,
|
|
FLAG_IS_REPLY: 7;
|
|
|
|
####### Global Parameters #########
|
|
fork = yes
|
|
children = 25
|
|
server_signature = no
|
|
server_header = "Server: Kazoo"
|
|
user_agent_header = "User-Agent: Kazoo"
|
|
shm_force_alloc = yes
|
|
mlock_pages = yes
|
|
phone2tel = 1
|
|
max_while_loops = MAX_WHILE_LOOPS
|
|
|
|
pv_buffer_size=65536
|
|
mem_join=1
|
|
|
|
####### Logging Parameters #########
|
|
debug = KAZOO_LOG_LEVEL
|
|
memdbg = 10
|
|
memlog = L_INFO
|
|
corelog = L_ERR
|
|
mem_summary = 12
|
|
log_stderror = no
|
|
log_facility = LOG_LOCAL0
|
|
log_name="kamailio"
|
|
|
|
####### Alias Parameters #########
|
|
auto_aliases = yes
|
|
|
|
####### Binding Parameters #########
|
|
tos = IPTOS_LOWDELAY
|
|
|
|
####### TCP Parameters #########
|
|
tcp_children = 25
|
|
disable_tcp = no
|
|
tcp_max_connections = 4096
|
|
tcp_connection_lifetime = 3605
|
|
tcp_accept_aliases = no
|
|
tcp_async = yes
|
|
tcp_connect_timeout = 10
|
|
tcp_conn_wq_max = 65536
|
|
tcp_crlf_ping = yes
|
|
tcp_delayed_ack = yes
|
|
tcp_fd_cache = yes
|
|
tcp_keepalive = yes
|
|
tcp_keepcnt = 3
|
|
tcp_keepidle = 30
|
|
tcp_keepintvl = 10
|
|
tcp_linger2 = 30
|
|
tcp_rd_buf_size = 80000
|
|
tcp_send_timeout = 10
|
|
tcp_wq_blk_size = 2100
|
|
tcp_wq_max = 10485760
|
|
|
|
####### UDP Parameters #########
|
|
udp4_raw = 0
|
|
#udp4_raw_mtu = 800
|
|
# # pmtu_discovery = no
|
|
#udp_mtu = 800
|
|
# #udp_mtu_try_proto = TCP
|
|
|
|
####### DNS Parameters #########
|
|
dns = no
|
|
rev_dns = no
|
|
dns_try_ipv6 = no
|
|
use_dns_cache = on
|
|
dns_cache_del_nonexp = yes
|
|
dns_cache_flags = 1
|
|
dns_cache_gc_interval = 120
|
|
dns_cache_init = 0
|
|
dns_cache_mem = 1000
|
|
dns_cache_negative_ttl = 60
|
|
dns_try_naptr = no
|
|
use_dns_failover = off
|
|
dns_srv_lb = off
|
|
|
|
####### SCTP Parameters #########
|
|
disable_sctp = yes
|
|
|
|
####### Modules Section ########
|
|
mpath="/usr/lib64/kamailio/modules/:/usr/lib/x86_64-linux-gnu/kamailio/modules/"
|
|
|
|
######## Kamailio outbound module ########
|
|
loadmodule "outbound.so"
|
|
|
|
######## Kamailio stun module ########
|
|
loadmodule "stun.so"
|
|
|
|
######## Kamailio path module ########
|
|
loadmodule "path.so"
|
|
|
|
######## Kamailio control connector module ########
|
|
loadmodule "ctl.so"
|
|
modparam("ctl", "binrpc_buffer_size", 4096)
|
|
loadmodule "cfg_rpc.so"
|
|
loadmodule "cfgutils.so"
|
|
loadmodule "corex.so"
|
|
|
|
######## Kamailio uuid module ########
|
|
loadmodule "uuid.so"
|
|
|
|
######## Kamailio core extensions module ########
|
|
loadmodule "kex.so"
|
|
|
|
######## Transaction (stateful) module ########
|
|
loadmodule "tm.so"
|
|
loadmodule "tmx.so"
|
|
modparam("tm", "auto_inv_100", 1)
|
|
modparam("tm", "auto_inv_100_reason", "Attempting to connect your call")
|
|
modparam("tm", "cancel_b_method", 2)
|
|
modparam("tm", "ruri_matching", 0)
|
|
modparam("tm", "failure_reply_mode", 3)
|
|
# modparam("tm", "fr_timer", 30000)
|
|
# modparam("tm", "fr_inv_timer", 120000)
|
|
|
|
######## Stateless replier module ########
|
|
loadmodule "sl.so"
|
|
|
|
######## Record-Route and Route module ########
|
|
loadmodule "rr.so"
|
|
modparam("rr", "enable_full_lr", 1)
|
|
modparam("rr", "enable_double_rr", 1)
|
|
|
|
######## Max-Forward processor module ########
|
|
loadmodule "maxfwd.so"
|
|
modparam("maxfwd", "max_limit", 50)
|
|
|
|
######## SIP utilities [requires sl] ########
|
|
loadmodule "siputils.so"
|
|
|
|
######## SIP message formatting sanity checks [requires sl] ########
|
|
loadmodule "sanity.so"
|
|
modparam("sanity", "default_checks", 1511)
|
|
modparam("sanity", "uri_checks", 7)
|
|
modparam("sanity", "autodrop", 0)
|
|
|
|
######## Text operations module ########
|
|
loadmodule "textops.so"
|
|
loadmodule "textopsx.so"
|
|
|
|
######## Generic Hash Table container in shared memory ########
|
|
loadmodule "htable.so"
|
|
modparam("htable", "htable", "associations=>size=16;autoexpire=7200")
|
|
modparam("htable", "htable", "redirects=>size=16;autoexpire=5")
|
|
|
|
######## Pseudo-Variables module ########
|
|
loadmodule "pv.so"
|
|
|
|
######## Advanced logger module ########
|
|
loadmodule "xlog.so"
|
|
|
|
####### FIFO support for Management Interface ########
|
|
loadmodule "mi_fifo.so"
|
|
|
|
######## UAC ########
|
|
loadmodule "uac.so"
|
|
|
|
######## UAC Redirection module ########
|
|
loadmodule "uac_redirect.so"
|
|
|
|
####### DB Text module ##########
|
|
loadmodule "db_text.so"
|
|
modparam("db_text", "db_mode", 1)
|
|
modparam("db_text", "emptystring", 1)
|
|
modparam("db_text", "default_connection", "KAZOO_DB_URL")
|
|
|
|
|
|
####### Kazoo Integration module ##########
|
|
loadmodule "kazoo.so"
|
|
modparam("kazoo", "node_hostname", "MY_HOSTNAME")
|
|
modparam("kazoo", "amqp_connection", "MY_AMQP_URL")
|
|
#!ifdef MY_AMQP_SECONDARY_URL
|
|
modparam("kazoo", "amqp_connection", "MY_AMQP_SECONDARY_URL")
|
|
#!endif
|
|
#!ifdef MY_AMQP_TERTIARY_URL
|
|
modparam("kazoo", "amqp_connection", "MY_AMQP_TERTIARY_URL")
|
|
#!endif
|
|
#!ifdef MY_AMQP_MAX_CHANNELS
|
|
modparam("kazoo", "amqp_max_channels", MY_AMQP_MAX_CHANNELS)
|
|
#!else
|
|
modparam("kazoo", "amqp_max_channels", 100)
|
|
#!endif
|
|
modparam("kazoo", "amqp_query_timeout_avp", "$avp(kz_timeout)");
|
|
modparam("kazoo", "amqp_consumer_processes", 4);
|
|
modparam("kazoo", "amqp_consumer_workers", 16);
|
|
modparam("kazoo", "amqp_heartbeats", 5);
|
|
|
|
####### Role Configurations ##########
|
|
#!ifdef DISPATCHER_ROLE
|
|
include_file "dispatcher-role.cfg"
|
|
#!endif
|
|
#!ifdef REGISTRAR_ROLE
|
|
include_file "registrar-role.cfg"
|
|
#!endif
|
|
#!ifdef PRESENCE_ROLE
|
|
include_file "presence-role.cfg"
|
|
#!endif
|
|
#!ifdef MESSAGE_ROLE
|
|
include_file "message-role.cfg"
|
|
#!endif
|
|
#!ifdef NAT_TRAVERSAL_ROLE
|
|
include_file "nat-traversal-role.cfg"
|
|
#!endif
|
|
#!ifdef WEBSOCKETS_ROLE
|
|
include_file "websockets-role.cfg"
|
|
#!endif
|
|
#!ifdef TLS_ROLE
|
|
include_file "tls-role.cfg"
|
|
#!endif
|
|
#!ifdef ACCOUNTING_ROLE
|
|
include_file "accounting-role.cfg"
|
|
#!endif
|
|
#!ifdef ANTIFLOOD_ROLE
|
|
include_file "antiflood-role.cfg"
|
|
#!endif
|
|
#!ifdef TRAFFIC_FILTER_ROLE
|
|
include_file "traffic-filter-role.cfg"
|
|
#!endif
|
|
#!ifdef ACL_ROLE
|
|
include_file "acl-role.cfg"
|
|
#!endif
|
|
#!ifdef RATE_LIMITER_ROLE
|
|
include_file "rate-limiter-role.cfg"
|
|
#!endif
|
|
#!ifdef PUSHER_ROLE
|
|
include_file "pusher-role.cfg"
|
|
#!endif
|
|
#!ifdef RESPONDER_ROLE
|
|
include_file "responder-role.cfg"
|
|
#!endif
|
|
#!ifdef NODES_ROLE
|
|
include_file "nodes-role.cfg"
|
|
#!endif
|
|
#!ifdef REGISTRAR_SYNC_ROLE
|
|
include_file "registrar-sync-role.cfg"
|
|
#!endif
|
|
#!ifdef FAST_PICKUP_ROLE
|
|
include_file "fast-pickup-role.cfg"
|
|
#!endif
|
|
#!ifdef PRESENCE_SYNC_ROLE
|
|
include_file "presence_sync-role.cfg"
|
|
#!endif
|
|
#!ifdef PRESENCE_QUERY_ROLE
|
|
include_file "presence_query-role.cfg"
|
|
#!endif
|
|
#!ifdef PRESENCE_NOTIFY_SYNC_ROLE
|
|
include_file "presence_notify_sync-role.cfg"
|
|
#!endif
|
|
|
|
|
|
####### Permissions module ##########
|
|
loadmodule "permissions.so"
|
|
modparam("permissions", "db_url", "KAZOO_DB_URL")
|
|
modparam("permissions", "db_mode", 1)
|
|
|
|
####### Routing Logic ########
|
|
route
|
|
{
|
|
route(SANITY_CHECK);
|
|
|
|
route(CHECK_RETRANS);
|
|
|
|
# log the basic info regarding this call
|
|
xlog("L_INFO", "$ci|start|received $pr request $rm $ou\n");
|
|
xlog("L_INFO", "$ci|log|source $si:$sp -> $Ri:$Rp\n");
|
|
xlog("L_INFO", "$ci|log|from $fu\n");
|
|
xlog("L_INFO", "$ci|log|to $tu\n");
|
|
|
|
route(CLASSIFY_SOURCE);
|
|
|
|
#!ifdef ANTIFLOOD_ROLE
|
|
route(ANTIFLOOD_RATE_LIMIT);
|
|
route(ANITFLOOD_AUTH_LIMIT);
|
|
#!endif
|
|
|
|
#!ifdef TRAFFIC_FILTER_ROLE
|
|
route(FILTER_REQUEST);
|
|
#!endif
|
|
|
|
#!ifdef ACL_ROLE
|
|
route(ACL_CHECK);
|
|
#!endif
|
|
|
|
#!ifdef RATE_LIMITER_ROLE
|
|
route(DOS_PREVENTION);
|
|
#!endif
|
|
|
|
#!ifdef WEBSOCKETS_ROLE
|
|
route(HANDLE_WEBSOCKETS);
|
|
#!endif
|
|
|
|
route(HANDLE_OPTIONS);
|
|
|
|
route(HANDLE_NOTIFY);
|
|
|
|
#!ifdef AUTHORIZATION_ROLE
|
|
route(AUTHORIZATION_CHECK);
|
|
#!endif
|
|
|
|
route(HANDLE_MESSAGE);
|
|
|
|
#!ifdef PRESENCE_ROLE
|
|
route(HANDLE_SUBSCRIBE);
|
|
route(HANDLE_PUBLISH);
|
|
#!endif
|
|
|
|
#!ifdef REGISTRAR_ROLE
|
|
route(HANDLE_REGISTER);
|
|
#!endif
|
|
|
|
route(HANDLE_IN_DIALOG_REQUESTS);
|
|
|
|
route(PREPARE_INITIAL_REQUESTS);
|
|
|
|
#!ifdef PUSHER_ROLE
|
|
route(PUSHER_ROUTE);
|
|
#!endif
|
|
|
|
if (isflagset(FLAG_INTERNALLY_SOURCED)) {
|
|
#!ifdef RESPONDER_ROLE
|
|
route(HANDLE_RESPOND);
|
|
#!endif
|
|
route(INTERNAL_TO_EXTERNAL_RELAY);
|
|
exit();
|
|
}
|
|
|
|
#!ifdef DISPATCHER_ROLE
|
|
route(DISPATCHER_FIND_ROUTES);
|
|
#!endif
|
|
|
|
route(EXTERNAL_TO_INTERNAL_RELAY);
|
|
}
|
|
|
|
route[CHECK_RETRANS]
|
|
{
|
|
# handle retransmissions
|
|
if(t_precheck_trans()) {
|
|
t_check_trans();
|
|
exit;
|
|
}
|
|
}
|
|
|
|
route[SANITY_CHECK]
|
|
{
|
|
if (!sanity_check()) {
|
|
xlog("L_WARN", "$ci|end|message from $si:$sp is insane\n");
|
|
exit;
|
|
}
|
|
|
|
if (!mf_process_maxfwd_header("10")) {
|
|
xlog("L_WARN", "$ci|end|too much hops, not enough barley from $si:$sp\n");
|
|
send_reply("483", "Too Many Hops");
|
|
exit;
|
|
}
|
|
|
|
if ($ua == "friendly-scanner" ||
|
|
$ua == "sundayddr" ||
|
|
$ua =~ "sipcli" ) {
|
|
xlog("L_WARN", "$ci|end|dropping message with user-agent $ua from $si:$sp\n");
|
|
exit;
|
|
}
|
|
}
|
|
|
|
route[CLASSIFY_SOURCE]
|
|
{
|
|
if (isflagset(FLAG_INTERNALLY_SOURCED) || allow_source_address(TRUSTED_ADR_GROUP) || is_myself($si)) {
|
|
xlog("L_INFO", "$ci|log|request from trusted IP\n");
|
|
setflag(FLAG_TRUSTED_SOURCE);
|
|
}
|
|
|
|
#!ifdef DISPATCHER_ROLE
|
|
route(DISPATCHER_CLASSIFY_SOURCE);
|
|
#!endif
|
|
}
|
|
|
|
route[HANDLE_OPTIONS]
|
|
{
|
|
if (is_method("OPTIONS")) {
|
|
if (isflagset(FLAG_INTERNALLY_SOURCED)) {
|
|
route(INTERNAL_TO_EXTERNAL_RELAY);
|
|
} else {
|
|
#!ifdef TRAFFIC_FILTER_ROLE
|
|
if (!isflagset(FLAG_TRUSTED_SOURCE)) {
|
|
route(FILTER_REQUEST_DOMAIN);
|
|
}
|
|
#!endif
|
|
|
|
#!ifdef NAT_TRAVERSAL_ROLE
|
|
route(NAT_TEST_AND_CORRECT);
|
|
#!endif
|
|
|
|
sl_send_reply("200", "Rawr!!");
|
|
}
|
|
exit;
|
|
}
|
|
}
|
|
|
|
route[HANDLE_NOTIFY]
|
|
{
|
|
if (is_method("NOTIFY")) {
|
|
if (isflagset(FLAG_INTERNALLY_SOURCED)) {
|
|
if (loose_route()) {
|
|
xlog("L_INFO", "$ci|log|Able to loose-route. Cool beans!\n");
|
|
}
|
|
|
|
if (registered("location")) {
|
|
lookup("location");
|
|
xlog("L_INFO", "$ci|log|routing to $ruid\n");
|
|
}
|
|
route(INTERNAL_TO_EXTERNAL_RELAY);
|
|
} else {
|
|
#!ifdef TRAFFIC_FILTER_ROLE
|
|
if (!isflagset(FLAG_TRUSTED_SOURCE)) {
|
|
route(FILTER_REQUEST_DOMAIN);
|
|
}
|
|
#!endif
|
|
|
|
#!ifdef WEBSOCKETS_ROLE
|
|
route(NAT_WEBSOCKETS_CORRECT);
|
|
#!endif
|
|
|
|
#!ifdef NAT_TRAVERSAL_ROLE
|
|
route(NAT_TEST_AND_CORRECT);
|
|
#!endif
|
|
|
|
if($hdr(Event) == "keep-alive") {
|
|
xlog("L_INFO", "$ci|stop|replying to keep alive\n");
|
|
sl_send_reply("405", "Stay Alive / Method Not Allowed");
|
|
} else {
|
|
xlog("L_INFO", "$ci|stop|consuming event $hdr(Event)\n");
|
|
sl_send_reply("200", "Rawr!!");
|
|
}
|
|
}
|
|
exit;
|
|
}
|
|
}
|
|
|
|
route[HANDLE_MESSAGE]
|
|
{
|
|
#!ifdef MESSAGE_ROLE
|
|
if (is_method("MESSAGE")) {
|
|
xlog("L_INFO", "$ci|MESSAGE from $fu to $tu\n");
|
|
if (isflagset(FLAG_INTERNALLY_SOURCED) || src_ip == myself) {
|
|
xlog("L_INFO", "$ci| routing MESSAGE to external from $fu to $tu\n");
|
|
if (registered("location")) {
|
|
lookup("location");
|
|
xlog("L_INFO", "$ci|log|routing to $ruid\n");
|
|
}
|
|
route(INTERNAL_TO_EXTERNAL_RELAY);
|
|
#!ifdef TRAFFIC_FILTER_ROLE
|
|
} else if (!isflagset(FLAG_TRUSTED_SOURCE)
|
|
&& $rd =~ "[0-9]{1,3}\.[0-9]{1,3}.[0-9]{1,3}\.[0-9]{1,3}") {
|
|
xlog("L_WARN", "$ci|end|dropping MESSAGE request with IP domain\n");
|
|
#!endif
|
|
} else {
|
|
xlog("L_WARN", "$ci|end|MESSAGE $(hdr(Content-Type))\n");
|
|
if( $hdr(Content-Type) == "application/im-iscomposing+xml" ) {
|
|
xlog("L_WARN", "$ci|end|dropping MESSAGE application/im-iscomposing+xml\n");
|
|
sl_send_reply("200", "OK");
|
|
} else {
|
|
route(DISPATCHER_FIND_ROUTES);
|
|
route(EXTERNAL_TO_INTERNAL_RELAY);
|
|
}
|
|
}
|
|
exit();
|
|
}
|
|
#!else
|
|
if (is_method("MESSAGE")) {
|
|
if (isflagset(FLAG_INTERNALLY_SOURCED)) {
|
|
route(INTERNAL_TO_EXTERNAL_RELAY);
|
|
} else {
|
|
sl_send_reply("202", "delivered to /dev/null");
|
|
exit();
|
|
}
|
|
}
|
|
#!endif
|
|
}
|
|
|
|
|
|
route[HANDLE_IN_DIALOG_REQUESTS]
|
|
{
|
|
if (has_totag()) {
|
|
if (is_method("INVITE")) {
|
|
setflag(FLAG_SESSION_PROGRESS);
|
|
record_route();
|
|
}
|
|
if (loose_route()) {
|
|
|
|
#!ifdef ACCOUNTING_ROLE
|
|
if (is_method("BYE")) {
|
|
setflag(FLAG_ACC);
|
|
setflag(FLAG_ACCFAILED);
|
|
}
|
|
#!endif
|
|
|
|
if(!isdsturiset()) {
|
|
handle_ruri_alias();
|
|
}
|
|
|
|
xlog("L_INFO", "$ci|log|loose_route in-dialog message\n");
|
|
# Called on in-dialog requests
|
|
# If the request in an Invite for on hold from external to internal,
|
|
# associate the contact with the media server
|
|
# if Invite for on hold, we need to associate the contact URI with the next hop
|
|
if (is_method("INVITE") && !isflagset(FLAG_INTERNALLY_SOURCED) && is_audio_on_hold()) {
|
|
setflag(FLAG_ASSOCIATE_USER);
|
|
}
|
|
route(RELAY);
|
|
} else if (isflagset(FLAG_INTERNALLY_SOURCED)) {
|
|
xlog("L_INFO", "$ci|log|relay internally sourced in-dialog message without loose_route\n");
|
|
route(RELAY);
|
|
} else if (t_check_trans()) {
|
|
xlog("L_INFO", "$ci|log|allow message for a known transaction\n");
|
|
route(RELAY);
|
|
} else {
|
|
xlog("L_INFO", "$ci|log|message had a to-tag but can't be loose routed\n");
|
|
sl_send_reply("481", "Call Leg/Transaction Does Not Exist");
|
|
}
|
|
exit();
|
|
}
|
|
}
|
|
|
|
route[PREPARE_INITIAL_REQUESTS]
|
|
{
|
|
if (is_method("CANCEL")) {
|
|
if (t_check_trans()) {
|
|
route(RELAY);
|
|
} else {
|
|
sl_send_reply("481", "Call leg/transaction does not exist");
|
|
}
|
|
exit();
|
|
} else if (is_method("ACK")) {
|
|
if (t_check_trans()) {
|
|
route(RELAY);
|
|
}
|
|
exit();
|
|
}
|
|
|
|
if (is_method("UPDATE")) {
|
|
xlog("L_WARN", "$ci|end|update outside dialog not allowed\n");
|
|
send_reply("403", "Dialog does not exist");
|
|
break;
|
|
}
|
|
|
|
if (is_method("BYE|PRACK")) {
|
|
xlog("L_WARN", "$ci|end|originating subsequent requests outside dialog not allowed\n");
|
|
send_reply("403", "Dialog does not exist");
|
|
break;
|
|
}
|
|
|
|
if (loose_route()) {
|
|
$xavp(regcfg=>match_received) = $su;
|
|
if(registered("location", "$rz:$Au", 2) == 1) {
|
|
xlog("L_INFO", "$ci|log|allowing initial route-set for $Au\n");
|
|
} else {
|
|
xlog("L_WARN", "$ci|end|dropping initial request with route-set\n");
|
|
sl_send_reply("403", "No pre-loaded routes");
|
|
exit();
|
|
}
|
|
}
|
|
|
|
record_route();
|
|
}
|
|
|
|
route[RELAY]
|
|
{
|
|
if (isflagset(FLAG_INTERNALLY_SOURCED)) {
|
|
route(INTERNAL_TO_EXTERNAL_RELAY);
|
|
} else {
|
|
route(EXTERNAL_TO_INTERNAL_RELAY);
|
|
}
|
|
|
|
exit();
|
|
}
|
|
|
|
route[INTERNAL_TO_EXTERNAL_RELAY]
|
|
{
|
|
#!ifdef ACCOUNTING_ROLE
|
|
if (is_method("INVITE")) {
|
|
setflag(FLAG_ACC);
|
|
setflag(FLAG_ACCFAILED);
|
|
}
|
|
#!endif
|
|
|
|
if ($hdr(X-KAZOO-AOR) != $null) {
|
|
xlog("L_INFO", "$ci|log|using AOR $hdr(X-KAZOO-AOR)\n");
|
|
if (reg_fetch_contacts("location", "$hdr(X-KAZOO-AOR)", "callee")) {
|
|
$du = $(ulc(callee=>received));
|
|
$fs = $(ulc(callee=>socket));
|
|
xlog("L_INFO", "$ci|log|routing $hdr(X-KAZOO-AOR) to $du via $fs\n");
|
|
} else {
|
|
xlog("L_INFO", "$ci|end|user is not registered\n");
|
|
sl_send_reply("404", "Not registered");
|
|
exit;
|
|
}
|
|
}
|
|
|
|
remove_hf_re("^X-.*");
|
|
|
|
if( $avp(kazoo_aor) != $null)
|
|
{
|
|
$du = $avp(kazoo_du);
|
|
xlog("L_INFO", "$ci|end|routing to $ruid : AOR : $avp(kazoo_aor)\n");
|
|
}
|
|
|
|
|
|
t_on_reply("EXTERNAL_REPLY");
|
|
|
|
t_set_fr(0, 10000);
|
|
|
|
t_relay();
|
|
}
|
|
|
|
route[EXTERNAL_TO_INTERNAL_RELAY]
|
|
{
|
|
#!ifdef ACCOUNTING_ROLE
|
|
if (is_method("INVITE") && is_present_hf("Proxy-Authorization")) {
|
|
setflag(FLAG_ACC);
|
|
setflag(FLAG_ACCFAILED);
|
|
}
|
|
#!endif
|
|
|
|
#!ifdef NAT_TRAVERSAL_ROLE
|
|
if (!isflagset(FLAG_INTERNALLY_SOURCED)) {
|
|
route(NAT_TEST_AND_CORRECT);
|
|
}
|
|
#!endif
|
|
|
|
#!ifdef FAST_PICKUP_ROLE
|
|
route(FAST_PICKUP_REFER);
|
|
#!endif
|
|
|
|
remove_hf_re("^X-.*");
|
|
append_hf("X-AUTH-IP: $si\r\n");
|
|
append_hf("X-AUTH-PORT: $sp\r\n");
|
|
|
|
route(ADD_AUTHORIZATION_HEADERS);
|
|
|
|
t_on_reply("INTERNAL_REPLY");
|
|
t_on_failure("INTERNAL_FAULT");
|
|
|
|
t_set_fr(0, 1000);
|
|
|
|
t_relay();
|
|
}
|
|
|
|
onreply_route[EXTERNAL_REPLY]
|
|
{
|
|
xlog("L_INFO", "$ci|log|external reply $T_reply_code\n");
|
|
|
|
#!ifdef WEBSOCKETS_ROLE
|
|
route(NAT_WEBSOCKETS_CORRECT);
|
|
#!endif
|
|
|
|
#!ifdef NAT_TRAVERSAL_ROLE
|
|
route(NAT_TEST_AND_CORRECT);
|
|
#!endif
|
|
|
|
#!ifdef ACL_ROLE
|
|
setflag(FLAG_IS_REPLY);
|
|
route(ACL_CHECK);
|
|
#!endif
|
|
|
|
#!ifdef RATE_LIMITER_ROLE
|
|
setflag(FLAG_IS_REPLY);
|
|
route(DOS_PREVENTION);
|
|
#!endif
|
|
|
|
#!ifdef MESSAGE_ROLE
|
|
if (is_method("MESSAGE")) {
|
|
route(MESSAGE_REPLY);
|
|
}
|
|
#!endif
|
|
}
|
|
|
|
onreply_route[INTERNAL_REPLY]
|
|
{
|
|
# this route handles replies that are comming from our media server
|
|
xlog("L_INFO", "$ci|start|received internal reply $T_reply_code $rr\n");
|
|
xlog("L_INFO", "$ci|log|source $si:$sp\n");
|
|
|
|
#!ifdef WEBSOCKETS_ROLE
|
|
route(NAT_WEBSOCKETS_CORRECT);
|
|
#!endif
|
|
|
|
#!ifdef ACL_ROLE
|
|
setflag(FLAG_IS_REPLY);
|
|
route(ACL_CHECK);
|
|
#!endif
|
|
|
|
#!ifdef RATE_LIMITER_ROLE
|
|
setflag(FLAG_IS_REPLY);
|
|
route(DOS_PREVENTION);
|
|
#!endif
|
|
|
|
#!ifdef FAST_PICKUP_ROLE
|
|
route(FAST_PICKUP_REPLY);
|
|
#!endif
|
|
|
|
if (is_method("INVITE") &&
|
|
!isflagset(FLAG_SESSION_PROGRESS) &&
|
|
t_check_status("(180)|(183)|(200)")
|
|
) {
|
|
if ($avp(AVP_REDIRECT_KEY) != $null &&
|
|
$sht(redirects=>$avp(AVP_REDIRECT_KEY)) != $null
|
|
) {
|
|
xlog("L_INFO", "$ci|log|removing redirect mapping $avp(AVP_REDIRECT_KEY)\n");
|
|
$sht(redirects=>$avp(AVP_REDIRECT_KEY)) = $null;
|
|
}
|
|
xlog("L_INFO", "$ci|log|call setup, now ignoring abnormal termination\n");
|
|
setflag(FLAG_SESSION_PROGRESS);
|
|
}
|
|
|
|
if ($rs < 300) {
|
|
xlog("L_INFO", "$ci|pass|$T_req($si):$T_req($sp)\n");
|
|
}
|
|
|
|
$var(reply_reason) = $rr;
|
|
}
|
|
|
|
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_is_canceled()) {
|
|
xlog("L_INFO", "$ci|log|transaction was cancelled\n");
|
|
exit;
|
|
}
|
|
|
|
# Handle redirects
|
|
if (t_check_status("302")) {
|
|
$var(redirect) = @from.uri.user + "@" + @from.uri.host + "->"
|
|
+ $T_rpl($(ct{tobody.user})) + "@" + $T_rpl($(ct{tobody.host}));
|
|
if($T_rpl($hdr(X-Redirect-Server)) != $null) {
|
|
$sht(redirects=>$var(redirect)) = $T_rpl($hdr(X-Redirect-Server));
|
|
xlog("L_INFO", "$ci|log|stored redirect mapping $var(redirect) to $T_rpl($hdr(X-Redirect-Server))\n");
|
|
}
|
|
route(DISPATCHER_REDIRECT);
|
|
} else if (!t_check_status("407") &&
|
|
$avp(AVP_REDIRECT_KEY) != $null &&
|
|
$sht(redirects=>$avp(AVP_REDIRECT_KEY)) != $null
|
|
) {
|
|
xlog("L_INFO", "$ci|log|removing redirect mapping $avp(AVP_REDIRECT_KEY)\n");
|
|
$sht(redirects=>$avp(AVP_REDIRECT_KEY)) = $null;
|
|
}
|
|
|
|
remove_hf_re("^X-.*");
|
|
|
|
# change 6xx to 4xx
|
|
if (t_check_status("6[0-9][0-9]") && !t_check_status("600|603|604|606")) {
|
|
$var(new_code) = "4" + $(T_reply_code{s.substr,1,0});
|
|
xlog("L_INFO", "$ci|log|sending 6XX reply as $var(new_code) $var(reply_reason)\n");
|
|
t_reply("$(var(new_code){s.int})", "$var(reply_reason)");
|
|
|
|
# if the failure case was something that we should recover
|
|
# from then try to find a new media server
|
|
} else if ($var(reply_reason) =~ "call barred") {
|
|
xlog("L_INFO", "$ci|log|failure route ignoring call barred\n");
|
|
} else if (isflagset(FLAG_SESSION_PROGRESS)) {
|
|
xlog("L_INFO", "$ci|log|failure route ignoring failure after session progress\n");
|
|
} else if (t_check_status("(401)|(407)|(486)|(403)")) {
|
|
xlog("L_INFO", "$ci|log|failure route ignoring auth reply $T_reply_code $var(reply_reason)\n");
|
|
} else if (t_check_status("402")) {
|
|
xlog("L_INFO", "$ci|log|failure route overriding reply code 402 with 486\n");
|
|
send_reply("486", "Insufficient Funds");
|
|
} 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\n");
|
|
|
|
#!ifdef DISPATCHER_ROLE
|
|
route(DISPATCHER_NEXT_ROUTE);
|
|
#!endif
|
|
|
|
send_reply("486", "Unable to Comply");
|
|
} else {
|
|
xlog("L_INFO", "$ci|log|failure route ignoring reply $T_reply_code $rr\n");
|
|
}
|
|
xlog("L_INFO", "$ci|pass|$si:$sp\n");
|
|
}
|
|
|
|
onsend_route {
|
|
if (isflagset(FLAG_ASSOCIATE_USER)) {
|
|
$var(contact_uri) = $(ct{tobody.user}) + "@" + $(ct{tobody.host});
|
|
xlog("L_INFO", "$ci|log|associate user $var(contact_uri) with media server sip:$sndto(ip):$sndto(port)\n");
|
|
$sht(associations=>$var(contact_uri))= "sip:" + $sndto(ip) + ":" + $sndto(port);
|
|
}
|
|
|
|
xlog("L_INFO", "$ci|pass|$sndfrom(ip):$sndfrom(port) -> $sndto(ip):$sndto(port)\n");
|
|
}
|
|
|
|
event_route[kazoo:mod-init]
|
|
{
|
|
|
|
### use this simple form of binding a listener
|
|
### kazoo_subscribe("dialoginfo", "direct", "BLF-QUEUE-MY_HOSTNAME", "BLF-MY_HOSTNAME");
|
|
###
|
|
### or unleash the power of rabbit to kazoo-blf
|
|
###
|
|
### 'no_ack' : 1 => needs ack,
|
|
### 'wait_for_consumer_ack'
|
|
### : 1 => when it receives, it processses on the AMQP Worker ad after that it confirms
|
|
### : 0 => when it receives, it acks then processes in the AMQP Worker
|
|
### only works if no_ack : 0
|
|
###
|
|
### Rabbit Policy for ha-mode
|
|
### pattern : ^BLF
|
|
### definition : ha-mode: all
|
|
###
|
|
###
|
|
|
|
#!ifdef PRESENCE_ROLE
|
|
|
|
$var(payload) = "{ 'exchange' : 'presence' , 'queue' : 'presence-dialog-MY_HOSTNAME', 'exclusive' : 0 ,'type' : 'topic', 'routing' : 'dialog.*.*', 'federate' : 1 }";
|
|
kazoo_subscribe("$var(payload)");
|
|
|
|
$var(payload) = "{ 'exchange' : 'presence' , 'queue' : 'presence-presence-MY_HOSTNAME', 'exclusive' : 0 ,'type' : 'topic', 'routing' : 'update.*.*', 'federate' : 1 }";
|
|
kazoo_subscribe("$var(payload)");
|
|
|
|
$var(payload) = "{ 'exchange' : 'presence' , 'queue' : 'presence-mwi-MY_HOSTNAME', 'exclusive' : 0 ,'type' : 'topic', 'routing' : 'mwi_updates.*', 'federate' : 1 }";
|
|
kazoo_subscribe("$var(payload)");
|
|
|
|
#!endif
|
|
|
|
#!ifdef MESSAGE_ROLE
|
|
|
|
$var(key) = "kamailio@MY_HOSTNAME";
|
|
$var(payload) = '{ "exchange" : "sms" , "type" : "topic", "queue" : "MSG-QUEUE-MY_HOSTNAME", "routing" : "message.route.' + $(var(key){kz.encode}) + '.*", "auto_delete" : 1, "durable" : 0, "no_ack" : 0, "wait_for_consumer_ack" : 1 }';
|
|
kazoo_subscribe("$var(payload)");
|
|
|
|
#!endif
|
|
|
|
#!ifdef DISPATCHER_ROLE
|
|
|
|
$var(payload) = "{ 'exchange' : 'registrar' , 'type' : 'topic', 'queue' : 'MSG-FLUSH-MY_HOSTNAME', 'routing' : 'registration.flush.*', 'auto_delete' : 1, 'durable' : 0, 'no_ack' : 1, 'wait_for_consumer_ack' : 0 }";
|
|
kazoo_subscribe("$var(payload)");
|
|
|
|
#!endif
|
|
|
|
#!ifdef REGISTRAR_SYNC_ROLE
|
|
|
|
$var(payload) = "{ 'exchange' : 'registrar' , 'type' : 'topic', 'queue' : 'REGISTRAR-SYNC-QUEUE-MY_HOSTNAME', 'routing' : 'registration.sync', 'auto_delete' : 1, 'durable' : 0, 'no_ack' : 1, 'wait_for_consumer_ack' : 0 }";
|
|
kazoo_subscribe("$var(payload)");
|
|
|
|
#!endif
|
|
|
|
#!ifdef PRESENCE_QUERY_ROLE
|
|
|
|
$var(payload) = "{ 'exchange' : 'presence' , 'type' : 'topic', 'queue' : 'presence-search-MY_HOSTNAME', 'exclusive' : 0, 'routing' : 'presence.search_req.*', 'federate' : 1 }";
|
|
kazoo_subscribe("$var(payload)");
|
|
|
|
#!endif
|
|
|
|
#!ifdef NODES_SYNC_ROLE
|
|
|
|
$var(payload) = "{ 'exchange' : 'nodes' , 'type' : 'fanout', 'queue' : 'NODES-MY_HOSTNAME', 'federate' : 1}";
|
|
kazoo_subscribe("$var(payload)");
|
|
|
|
#!endif
|
|
|
|
#!ifdef ACL_ROLE
|
|
|
|
$var(payload) = "{ 'exchange' : 'frontier_acl' , 'type' : 'topic', 'queue' : 'FRONTIERACL-FLUSH-MY_HOSTNAME', 'routing' : 'flush', 'auto_delete' : 1, 'durable' : 0, 'no_ack' : 1, 'wait_for_consumer_ack' : 0 }";
|
|
kazoo_subscribe("$var(payload)");
|
|
|
|
#!endif
|
|
|
|
}
|
|
|
|
event_route[kazoo:consumer-event]
|
|
{
|
|
xlog("L_INFO","unhandled AMQP event, payload: $kzE\n");
|
|
}
|
|
|
|
event_route[kazoo:consumer-event-connection-open]
|
|
{
|
|
xlog("L_INFO","connection to $(kzE{kz.json,host}) opened\n");
|
|
}
|
|
|
|
event_route[kazoo:consumer-event-connection-closed]
|
|
{
|
|
xlog("L_INFO","connection to $(kzE{kz.json,host}) closed\n");
|
|
}
|
|
|
|
route[ADD_AUTHORIZATION_HEADERS]
|
|
{
|
|
if (!is_method("INVITE|MESSAGE|REFER")) {
|
|
return;
|
|
}
|
|
|
|
$xavp(regcfg=>match_received) = $su;
|
|
if (registered("location","$fu", 2, 1) == 1) {
|
|
if($(xavp(ulattrs=>custom_channel_vars){kz.json,Account-ID}{s.len}) > 0)
|
|
append_hf("X-ecallmgr_Account-ID: $(xavp(ulattrs=>custom_channel_vars){kz.json,Account-ID})\r\n");
|
|
|
|
if($(xavp(ulattrs=>custom_channel_vars){kz.json,Authorizing-Type}{s.len}) > 0)
|
|
append_hf("X-ecallmgr_Authorizing-Type: $(xavp(ulattrs=>custom_channel_vars){kz.json,Authorizing-Type})\r\n");
|
|
|
|
if($(xavp(ulattrs=>custom_channel_vars){kz.json,Authorizing-ID}{s.len}) > 0)
|
|
append_hf("X-ecallmgr_Authorizing-ID: $(xavp(ulattrs=>custom_channel_vars){kz.json,Authorizing-ID})\r\n");
|
|
|
|
if($(xavp(ulattrs=>custom_channel_vars){kz.json,Username}{s.len}) > 0)
|
|
append_hf("X-ecallmgr_Username: $(xavp(ulattrs=>custom_channel_vars){kz.json,Username})\r\n");
|
|
|
|
if($(xavp(ulattrs=>custom_channel_vars){kz.json,Realm}{s.len}) > 0)
|
|
append_hf("X-ecallmgr_Realm: $(xavp(ulattrs=>custom_channel_vars){kz.json,Realm})\r\n");
|
|
|
|
if($(xavp(ulattrs=>custom_channel_vars){kz.json,Account-Realm}{s.len}) > 0)
|
|
append_hf("X-ecallmgr_Account-Realm: $(xavp(ulattrs=>custom_channel_vars){kz.json,Account-Realm})\r\n");
|
|
|
|
if($(xavp(ulattrs=>custom_channel_vars){kz.json,Account-Name}{s.len}) > 0)
|
|
append_hf("X-ecallmgr_Account-Name: $(xavp(ulattrs=>custom_channel_vars){kz.json,Account-Name})\r\n");
|
|
|
|
if($(xavp(ulattrs=>custom_channel_vars){kz.json,Presence-ID}{s.len}) > 0)
|
|
append_hf("X-ecallmgr_Presence-ID: $(xavp(ulattrs=>custom_channel_vars){kz.json,Presence-ID})\r\n");
|
|
|
|
if($(xavp(ulattrs=>custom_channel_vars){kz.json,Owner-ID}{s.len}) > 0)
|
|
append_hf("X-ecallmgr_Owner-ID: $(xavp(ulattrs=>custom_channel_vars){kz.json,Owner-ID})\r\n");
|
|
}
|
|
}
|
|
|
|
#!ifdef PRESENCE_NOTIFY_INIT
|
|
event_route[tm:local-request]
|
|
{
|
|
route(PRESENCE_LOCAL_NOTIFY);
|
|
}
|
|
#!endif
|
|
|
|
# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
|