| @ -0,0 +1,469 @@ | |||
| ## NOTE: DO NOT CHANGE THIS FILE, EDIT local.cfg ## | |||
| #### Preprocessor Directives ######### | |||
| #!define L_ALERT -5 | |||
| #!define L_BUG -4 | |||
| #!define L_CRIT2 -3 | |||
| #!define L_CRIT -2 | |||
| #!define L_ERR -1 | |||
| #!define L_WARN 0 | |||
| #!define L_NOTICE 1 | |||
| #!define L_INFO 2 | |||
| #!define L_DBG 3 | |||
| #!define AVP_RECV_PARAM "recv_param" | |||
| #!define AVP_LOG_LEVEL "log_level" | |||
| #!define AVP_ROUTE_CNT "route_cnt" | |||
| #!define AVP_ASSOCIATED_SERVER "associated_server" | |||
| #!define AVP_ASSOCIATE_CONTACT "associate_contact" | |||
| ####### Flags ####### | |||
| flags | |||
| FLAG_INTERNALLY_SOURCED: 1, | |||
| FLAG_ASSOCIATE_SERVER: 2, | |||
| FLAG_SKIP_NAT_CORRECTION: 3, | |||
| FLAG_ASSOCIATE_USER: 4; | |||
| #!define FLB_NATB 1 | |||
| #!define FLB_NATSIPPING 2 | |||
| #!define FLB_UAC_REDIRECT 3 | |||
| ####### 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 = 500 | |||
| ####### Logging Parameters ######### | |||
| debug = L_INFO | |||
| memdbg = 10 | |||
| memlog = 10 | |||
| corelog = L_ERR | |||
| 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 = 4096 | |||
| tcp_send_timeout = 10 | |||
| tcp_wq_blk_size = 2100 | |||
| tcp_wq_max = 10485760 | |||
| ####### UDP Parameters ######### | |||
| udp4_raw = -1 | |||
| ####### DNS Parameters ######### | |||
| dns = no | |||
| rev_dns = no | |||
| dns_try_ipv6 = no | |||
| use_dns_cache = on | |||
| dns_cache_del_nonexp = no | |||
| dns_cache_flags = 1 | |||
| dns_cache_gc_interval = 120 | |||
| dns_cache_init = 1 | |||
| dns_cache_mem = 1000 | |||
| dns_cache_negative_ttl = 60 | |||
| dns_try_naptr = no | |||
| use_dns_failover = off | |||
| dns_srv_lb = off | |||
| ####### TLS Parameters ######### | |||
| enable_tls = yes | |||
| ####### SCTP Parameters ######### | |||
| disable_sctp = yes | |||
| ####### Custom Parameters ######### | |||
| ####### Modules Section ######## | |||
| mpath="/usr/lib64/kamailio/modules/" | |||
| ######## 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", 0) | |||
| ######## Max-Forward processor module ######## | |||
| loadmodule "maxfwd.so" | |||
| ######## SIP utilities [requires sl] ######## | |||
| loadmodule "siputils.so" | |||
| ######## SIP message formatting sanity checks [requires sl] ######## | |||
| loadmodule "sanity.so" | |||
| # sip_version, scheme, req_headers, cseq_method/value | |||
| # content_length, parse_uri, digest | |||
| modparam("sanity", "default_checks", 3303) | |||
| modparam("sanity", "uri_checks", 3) | |||
| 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") | |||
| ######## Pseudo-Variables module ######## | |||
| loadmodule "pv.so" | |||
| ######## Advanced logger module ######## | |||
| loadmodule "xlog.so" | |||
| ####### FIFO support for Management Interface ######## | |||
| loadmodule "mi_fifo.so" | |||
| modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo") | |||
| ######## UAC Redirection module ######## | |||
| loadmodule "uac_redirect.so" | |||
| ####### 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 NAT-TRAVERSAL-ROLE | |||
| include_file "nat-traversal-role.cfg" | |||
| #!endif | |||
| ####### Kazoo Integration module ########## | |||
| #!ifdef INCLUDE-DB-KAZOO | |||
| loadmodule "db_kazoo.so" | |||
| #!endif | |||
| ####### Routing Logic ######## | |||
| 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"); | |||
| route(SANITY_CHECK); | |||
| #!ifdef DISPATCHER-ROLE | |||
| route(DISPATCHER_CLASSIFY_SOURCE); | |||
| #!endif | |||
| route(HANDLE_OPTIONS); | |||
| route(HANDLE_MOVE_REQUEST); | |||
| #!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); | |||
| if (isflagset(FLAG_INTERNALLY_SOURCED)) { | |||
| route(INTERNAL_TO_EXTERNAL_RELAY); | |||
| exit(); | |||
| } | |||
| #!ifdef DISPATCHER-ROLE | |||
| route(DISPATCHER_FIND_ROUTES); | |||
| #!endif | |||
| route(EXTERNAL_TO_INTERNAL_RELAY); | |||
| } | |||
| route[SANITY_CHECK] | |||
| { | |||
| if (!mf_process_maxfwd_header("10")) { | |||
| xlog("L_WARN", "$ci|end|Too much hops, not enough barley"); | |||
| sl_send_reply("483", "Too Many Hops"); | |||
| exit; | |||
| } | |||
| if (!sanity_check()) { | |||
| xlog("L_WARN", "$ci|end|message is insane"); | |||
| exit; | |||
| } | |||
| } | |||
| route[HANDLE_OPTIONS] | |||
| { | |||
| if (is_method("OPTIONS")) { | |||
| if (isflagset(FLAG_INTERNALLY_SOURCED)) { | |||
| route(INTERNAL_TO_EXTERNAL_RELAY); | |||
| } else { | |||
| sl_send_reply("200", "Rawr!!"); | |||
| } | |||
| exit; | |||
| } | |||
| } | |||
| route[HANDLE_MOVE_REQUEST] | |||
| { | |||
| if (is_method("INVITE") && $rU == "*6683*") { | |||
| $var(contact_uri) = $(ct{tobody.user}) + "@" + $(ct{tobody.host}); | |||
| $var(from_uri) = @from.uri.user + "@" + @from.uri.host; | |||
| if ($sht(associations=>$var(contact_uri)) != $null) { | |||
| $sht(associations=>$var(contact_uri)) = $null; | |||
| xlog("L_INFO", "$ci|log|removed contact association for $var(contact_uri) | |||
| with media server $sht(associations=>$var(contact_uri))\n"); | |||
| } | |||
| if ($sht(associations=>$var(from_uri)) != $null) { | |||
| $sht(associations=>$var(from_uri)) = $null; | |||
| xlog("L_INFO", "$ci|log|removed from association for $var(from_uri) | |||
| with media server $sht(associations=>$var(from_uri))\n"); | |||
| } | |||
| send_reply("503", "Removed association"); | |||
| exit; | |||
| } | |||
| } | |||
| route[HANDLE_IN_DIALOG_REQUESTS] | |||
| { | |||
| if (has_totag()) { | |||
| if (loose_route()) { | |||
| xlog("L_INFO", "$ci|log|loose_route in-dialog message"); | |||
| # 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"); | |||
| route(RELAY); | |||
| } else if (t_check_trans()) { | |||
| xlog("L_INFO", "$ci|log|allow message for a known transaction"); | |||
| route(RELAY); | |||
| } else { | |||
| xlog("L_INFO", "$ci|log|message had a to-tag but can't be loose routed"); | |||
| 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(); | |||
| } | |||
| t_check_trans(); | |||
| if (loose_route()) { | |||
| sl_send_reply("403", "No pre-loaded routes"); | |||
| exit(); | |||
| } | |||
| if (!is_method("MESSAGE")) { | |||
| 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] | |||
| { | |||
| remove_hf("X-AUTH-IP"); | |||
| t_on_reply("EXTERNAL_REPLY"); | |||
| t_set_fr(0, 10000); | |||
| t_relay(); | |||
| } | |||
| route[EXTERNAL_TO_INTERNAL_RELAY] | |||
| { | |||
| #!ifdef NAT-TRAVERSAL-ROLE | |||
| if (!isflagset(FLAG_INTERNALLY_SOURCED)) { | |||
| route(NAT_TEST_AND_CORRECT); | |||
| } | |||
| #!endif | |||
| remove_hf("X-AUTH-IP"); | |||
| append_hf("X-AUTH-IP: $si\r\n"); | |||
| 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"); | |||
| #!ifdef NAT-TRAVERSAL-ROLE | |||
| route(NAT_TEST_AND_CORRECT); | |||
| #!endif | |||
| } | |||
| onreply_route[INTERNAL_REPLY] | |||
| { | |||
| # this route handles replies that are comming from our media server | |||
| xlog("L_INFO", "$ci|start|recieved internal reply $T_reply_code $rr"); | |||
| xlog("L_INFO", "$ci|log|source $si:$sp"); | |||
| if ($rs < 300) { | |||
| xlog("L_INFO", "$ci|pass|$T_req($si):$T_req($sp)"); | |||
| } | |||
| # change 6xx to 4xx | |||
| if (t_check_status("6[0-9][0-9]")) { | |||
| $var(new_code) = "4" + $(T_reply_code{s.substr,1,0}); | |||
| change_reply_status("$var(new_code)", "$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"); | |||
| exit; | |||
| } | |||
| # if the failure case was something that we should recover | |||
| # from then try to find a new media server | |||
| if (t_check_status("302")) { | |||
| ## TODO - test this | |||
| ## get_redirects("*"); | |||
| if($T_rpl($hdr(X-Redirect-Server)) != $null) { | |||
| $var(contact_uri) = @from.uri.user + "@" + @from.uri.host; | |||
| $sht(associations=>$var(contact_uri)) = $T_rpl($hdr(X-Redirect-Server)); | |||
| xlog("L_INFO", "$ci|log|stored redirect mapping for $var(contact_uri) to $T_rpl($hdr(X-Redirect-Server))"); | |||
| remove_hf("X-Redirect-Server"); | |||
| } | |||
| } else if (t_check_status("(401)|(407)")) { | |||
| xlog("L_INFO", "$ci|log|failure route ignoring auth reply $T_reply_code $rr"); | |||
| exit; | |||
| } else if (t_check_status("402")) { | |||
| xlog("L_INFO", "$ci|log|failure route overriding reply code 402 with 486"); | |||
| xlog("L_INFO", "$ci|pass|$si:$sp"); | |||
| send_reply("486", "Insufficient Funds"); | |||
| 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"); | |||
| #!ifdef DISPATCHER-ROLE | |||
| route(DISPATCHER_NEXT_ROUTE); | |||
| #!endif | |||
| send_reply("486", "Unable to Comply"); | |||
| exit; | |||
| } else { | |||
| xlog("L_INFO", "$ci|log|failure route ignoring reply $T_reply_code $rr"); | |||
| exit; | |||
| } | |||
| } | |||
| 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)"); | |||
| } | |||
| ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||
| @ -0,0 +1,142 @@ | |||
| ######## Generic Hash Table container in shared memory ######## | |||
| modparam("htable", "htable", "failover=>size=16;autoexpire=120") | |||
| ####### Dispatcher module ######## | |||
| loadmodule "dispatcher.so" | |||
| modparam("dispatcher", "list_file", "/etc/kazoo/kamailio/dispatcher.list") | |||
| modparam("dispatcher", "flags", 2) | |||
| modparam("dispatcher", "use_default", 0) | |||
| modparam("dispatcher", "force_dst", 1) | |||
| modparam("dispatcher", "dst_avp", "$avp(ds_dst)") | |||
| modparam("dispatcher", "attrs_avp", "$avp(ds_attrs)") | |||
| modparam("dispatcher", "grp_avp", "$avp(ds_grp)") | |||
| modparam("dispatcher", "cnt_avp", "$avp(ds_cnt)") | |||
| modparam("dispatcher", "hash_pvar", "$avp(ds_grp)") | |||
| # modparam("dispatcher", "setid_pvar", "$var(setid)") | |||
| modparam("dispatcher", "ds_ping_method", "OPTIONS") | |||
| modparam("dispatcher", "ds_ping_interval", 10) | |||
| modparam("dispatcher", "ds_probing_threshhold", 3) | |||
| modparam("dispatcher", "ds_probing_mode", 1) | |||
| modparam("dispatcher", "ds_ping_reply_codes", "501,403,404,400,200") | |||
| ####### Dispatcher Logic ######## | |||
| route[DISPATCHER_CLASSIFY_SOURCE] | |||
| { | |||
| if (ds_is_from_list("1", "1") || ds_is_from_list("3", "1")) { | |||
| xlog("L_INFO", "$ci|log|originated from internal sources"); | |||
| setflag(FLAG_INTERNALLY_SOURCED); | |||
| } else { | |||
| xlog("L_INFO", "$ci|log|originated from external sources"); | |||
| } | |||
| } | |||
| # Take the routes from dispatcher - hash over callid | |||
| # If prefered route defined, reorder the destionations | |||
| route[DISPATCHER_FIND_ROUTES] | |||
| { | |||
| if ($sht(failover=>$ci::current) != $null) { | |||
| $du = $sht(failover=>$ci::current); | |||
| return; | |||
| } | |||
| if (!ds_select_dst("1", "0")) { | |||
| xlog("L_ERR", "$ci|end|no servers avaliable"); | |||
| sl_send_reply("480", "All servers busy"); | |||
| exit; | |||
| } | |||
| $var(contact_uri) = $(ct{tobody.user}) + "@" + $(ct{tobody.host}); | |||
| $var(from_uri) = @from.uri.user + "@" + @from.uri.host; | |||
| if ($sht(associations=>$var(from_uri)) != $null) { | |||
| $var(association) = $var(from_uri); | |||
| route(DISPATCHER_REORDER_ROUTES); | |||
| } else if ($sht(associations=>$var(contact_uri)) != $null) { | |||
| $var(association) = $var(contact_uri); | |||
| route(DISPATCHER_REORDER_ROUTES); | |||
| } | |||
| } | |||
| route[DISPATCHER_REORDER_ROUTES] | |||
| { | |||
| $var(i) = 0; | |||
| $var(found) = 0; | |||
| while($(avp(ds_dst)[$var(i)]) != $null) { | |||
| if($(avp(ds_dst)[$var(i)]) != $var(prefered_route)) { | |||
| $avp(tmp_ds_dst) = $(avp(ds_dst)[$var(i)]); | |||
| } else { | |||
| $var(found) = 1; | |||
| } | |||
| $var(i) = $var(i) + 1; | |||
| } | |||
| if ($var(found)) { | |||
| xlog("L_INFO", "$ci|log|re-ordering the dispatcher list to keep associated server first"); | |||
| $(avp(ds_dst)[*]) = $null; | |||
| $var(i) = 0; | |||
| while($(avp(tmp_ds_dst)[$var(i)]) != $null) { | |||
| $avp(ds_dst) = $(avp(tmp_ds_dst)[$var(i)]); | |||
| $var(i) = $var(i) + 1; | |||
| } | |||
| $avp(ds_dst) = $var(prefered_route); | |||
| $du = $var(prefered_route); | |||
| $(avp(tmp_ds_dst)[*]) = $null; | |||
| } else { | |||
| xlog("L_INFO", "$ci|log|associated media server is inactive, moving to $rd"); | |||
| $sht(associations=>$var(contact_uri)) = $null; | |||
| } | |||
| } | |||
| route[DISPATCHER_NEXT_ROUTE] | |||
| { | |||
| $var(failover_count) = $sht(failover=>$ci::counts); | |||
| if ($sht(failover=>$ci::counts) == $null) { | |||
| $var(i) = 0; | |||
| while($(avp(ds_dst)[$var(i)]) != $null) { | |||
| $sht(failover=>$ci[$var(i)]) = $(avp(ds_dst)[$var(i)]); | |||
| $var(i) = $var(i) + 1; | |||
| if ($var(i) >= 3) { | |||
| break; | |||
| } | |||
| } | |||
| $sht(failover=>$ci::counts) = $var(i); | |||
| $var(failover_count) = $var(i); | |||
| } | |||
| # try to find a new media server to send the call to | |||
| if ($var(failover_count) > 1) { | |||
| $var(failover_count) = $var(failover_count) - 1; | |||
| $du = $sht(failover=>$ci[$var(failover_count)]); | |||
| $sht(failover=>$ci::counts) = $var(failover_count); | |||
| $sht(failover=>$ci::current) = $du; | |||
| xlog("L_INFO", "$ci|log|remaining failed retry attempts: $var(failover_count)"); | |||
| xlog("L_INFO", "$ci|log|routing call to next media server $du"); | |||
| setflag(FLAG_SKIP_NAT_CORRECTION); | |||
| # reset the final reply timer | |||
| $avp(final_reply_timer) = 3; | |||
| t_on_reply("INTERNAL_REPLY"); | |||
| t_on_failure("INTERNAL_FAULT"); | |||
| # relay the request to the new media server | |||
| route(EXTERNAL_TO_INTERNAL_RELAY); | |||
| exit(); | |||
| } | |||
| } | |||
| ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||
| @ -1,723 +1,12 @@ | |||
| #### Preprocessor Directives ######### | |||
| #!define L_ALERT -5 | |||
| #!define L_BUG -4 | |||
| #!define L_CRIT2 -3 | |||
| #!define L_CRIT -2 | |||
| #!define L_ERR -1 | |||
| #!define L_WARN 0 | |||
| #!define L_NOTICE 1 | |||
| #!define L_INFO 2 | |||
| #!define L_DBG 3 | |||
| ## NOTE: DO NOT CHANGE THIS FILE, EDIT local.cfg ## | |||
| #!define AVP_RECV_PARAM "recv_param" | |||
| #!define AVP_LOG_LEVEL "log_level" | |||
| #!define AVP_ROUTE_CNT "route_cnt" | |||
| #!define AVP_ASSOCIATED_SERVER "associated_server" | |||
| #!define AVP_ASSOCIATE_CONTACT "associate_contact" | |||
| ####### Roles Configuration ###### | |||
| include_file "roles.cfg" | |||
| ####### 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 = 500 | |||
| ####### Default Configuration ###### | |||
| include_file "default.cfg" | |||
| ####### Logging Parameters ######### | |||
| debug = L_INFO | |||
| memdbg = 10 | |||
| memlog = 10 | |||
| corelog = L_ERR | |||
| log_stderror = no | |||
| log_facility = LOG_LOCAL0 | |||
| log_name="kamailio" | |||
| ####### Alias Parameters ######### | |||
| auto_aliases = yes | |||
| # alias = "mydomain.net" | |||
| ####### Binding Parameters ######### | |||
| listen = tcp:127.0.0.1:5060 | |||
| listen = udp:127.0.0.1:5060 | |||
| listen = tcp:127.0.0.1:5080 | |||
| listen = udp:127.0.0.1:5080 | |||
| listen = tcp:127.0.0.1:7000 | |||
| listen = udp:127.0.0.1:7000 | |||
| tos = IPTOS_LOWDELAY | |||
| ## NOTE: Uncomment on a multihomed host | |||
| # mhomed = 1 | |||
| ####### 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 = 4096 | |||
| tcp_send_timeout = 10 | |||
| tcp_wq_blk_size = 2100 | |||
| tcp_wq_max = 10485760 | |||
| ####### UDP Parameters ######### | |||
| udp4_raw = -1 | |||
| ## NOTE: You must MATCH this to your network adapter!! | |||
| ## If they do not match, all UDP packets over | |||
| ## this limit WILL FAIL! | |||
| ## E.g.: Add MTU=1472 to the /etc/sysconfig/network-scripts/XXX | |||
| # udp4_raw_mtu = 1472 | |||
| ####### DNS Parameters ######### | |||
| dns = no | |||
| rev_dns = no | |||
| dns_try_ipv6 = no | |||
| use_dns_cache = on | |||
| dns_cache_del_nonexp = no | |||
| dns_cache_flags = 1 | |||
| dns_cache_gc_interval = 120 | |||
| dns_cache_init = 1 | |||
| dns_cache_mem = 1000 | |||
| dns_cache_negative_ttl = 60 | |||
| dns_try_naptr = no | |||
| use_dns_failover = off | |||
| dns_srv_lb = off | |||
| ####### TLS Parameters ######### | |||
| enable_tls = yes | |||
| ####### SCTP Parameters ######### | |||
| disable_sctp = yes | |||
| ####### Custom Parameters ######### | |||
| ####### Modules Section ######## | |||
| mpath="/usr/lib64/kamailio/modules/" | |||
| ####### Flags ####### | |||
| flags | |||
| FLAG_INTERNALLY_SOURCED: 1, | |||
| FLAG_ASSOCIATE_SERVER: 2, | |||
| FLAG_SKIP_NAT_CORRECTION: 3, | |||
| FLAG_ASSOCIATE_USER: 4; | |||
| #!define FLB_NATB 1 | |||
| #!define FLB_NATSIPPING 2 | |||
| #!define FLB_UAC_REDIRECT 3 | |||
| ######## 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) | |||
| ######## Max-Forward processor module ######## | |||
| loadmodule "maxfwd.so" | |||
| ######## SIP utilities [requires sl] ######## | |||
| loadmodule "siputils.so" | |||
| ######## SIP message formatting sanity checks [requires sl] ######## | |||
| loadmodule "sanity.so" | |||
| # sip_version, scheme, req_headers, cseq_method/value | |||
| # content_length, parse_uri, digest | |||
| modparam("sanity", "default_checks", 3303) | |||
| modparam("sanity", "uri_checks", 3) | |||
| 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=10;") | |||
| modparam("htable", "htable", "auth_cache=>size=10;") | |||
| modparam("htable", "htable", "dbkp=>size=4;autoexpire=7200") | |||
| ######## Pseudo-Variables module ######## | |||
| loadmodule "pv.so" | |||
| ######## Advanced logger module ######## | |||
| loadmodule "xlog.so" | |||
| ####### FIFO support for Management Interface ######## | |||
| loadmodule "mi_fifo.so" | |||
| modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo") | |||
| ####### Dispatcher module ######## | |||
| loadmodule "dispatcher.so" | |||
| modparam("dispatcher", "list_file", "/etc/kazoo/kamailio/dispatcher.list") | |||
| modparam("dispatcher", "flags", 2) | |||
| modparam("dispatcher", "use_default", 0) | |||
| modparam("dispatcher", "force_dst", 1) | |||
| modparam("dispatcher", "dst_avp", "$avp(ds_dst)") | |||
| modparam("dispatcher", "attrs_avp", "$avp(ds_attrs)") | |||
| modparam("dispatcher", "grp_avp", "$avp(ds_grp)") | |||
| modparam("dispatcher", "cnt_avp", "$avp(ds_cnt)") | |||
| modparam("dispatcher", "hash_pvar", "$avp(ds_grp)") | |||
| # modparam("dispatcher", "setid_pvar", "$var(setid)") | |||
| modparam("dispatcher", "ds_ping_method", "OPTIONS") | |||
| modparam("dispatcher", "ds_ping_from", "sip:sipcheck@127.0.0.1") | |||
| 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", "ds_ping_reply_codes", "501,403,404,400,200") | |||
| ######## UAC Redirection module ######## | |||
| loadmodule "uac_redirect.so" | |||
| ####### Authentication Interface module ########## | |||
| loadmodule "auth.so" | |||
| loadmodule "auth_db.so" | |||
| modparam("auth_db", "use_domain", 1) | |||
| modparam("auth_db", "version_table", 0) | |||
| modparam("auth_db", "calculate_ha1", 1) | |||
| modparam("auth_db", "password_column", "password") | |||
| modparam("auth_db", "load_credentials", "$avp(password)=password") | |||
| ####### User Location Implementation module ########## | |||
| loadmodule "usrloc.so" | |||
| modparam("usrloc", "db_mode", 1) | |||
| modparam("usrloc", "db_update_as_insert", 1) | |||
| modparam("usrloc", "use_domain", 1) | |||
| modparam("usrloc", "nat_bflag", FLB_NATB) | |||
| ####### SIP Registrar implementation module ########## | |||
| loadmodule "registrar.so" | |||
| ######## NAT Traversal module - signaling functions ######## | |||
| loadmodule "nathelper.so" | |||
| modparam("nathelper|registrar", "received_avp", "$avp(AVP_RECV_PARAM)") | |||
| modparam("nathelper", "natping_interval", 30) | |||
| modparam("nathelper", "ping_nated_only", 1) | |||
| modparam("nathelper", "natping_processes", 5) | |||
| modparam("nathelper", "sipping_bflag", FLB_NATSIPPING) | |||
| modparam("nathelper", "sipping_from", "sip:sipcheck@127.0.0.1") | |||
| # modparam("nathelper", "natping_socket", "127.0.0.1:5060") | |||
| ######## Presence User Agent module ######## | |||
| loadmodule "pua_dialoginfo.so" | |||
| modparam("pua_dialoginfo", "library_mode", 1) | |||
| ######## Presence server module ######## | |||
| loadmodule "presence.so" | |||
| loadmodule "presence_dialoginfo.so" | |||
| modparam("presence", "subs_db_mode", 1) | |||
| modparam("presence", "expires_offset", 60) | |||
| modparam("presence", "publ_cache", 0) | |||
| ####### Kazoo Integration module ########## | |||
| loadmodule "db_kazoo.so" | |||
| # NOTE: The hostname that should be advertised to Kazoo | |||
| modparam("db_kazoo", "node_hostname", "kamailio.2600hz.com") | |||
| # If you want a certain fs_path to be sent Kazoo, uncomment the next line and set the right value | |||
| # modparam("db_kazoo", "register_fs_path", "127.0.0.1:5060") | |||
| ####### Common Module Parameters ########## | |||
| modparam("auth_db|usrloc", "db_url", "kazoo://guest:guest@127.0.0.1:5672/callmgr") | |||
| modparam("presence", "db_url", "kazoo://guest:guest@127.0.0.1:5672/dialoginfo") | |||
| ####### Routing Logic ######## | |||
| 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"); | |||
| route(SANITY_CHECK); | |||
| route(CLASSIFY_SOURCE); | |||
| route(HANDLE_OPTIONS); | |||
| route(HANDLE_PRESENCE); | |||
| route(HANDLE_IN_DIALOG_REQUESTS); | |||
| route(PREPARE_INITIAL_REQUESTS); | |||
| if (isflagset(FLAG_INTERNALLY_SOURCED)) { | |||
| route(INTERNAL_TO_EXTERNAL_RELAY); | |||
| exit(); | |||
| } | |||
| route(HANDLE_MOVE_REQUEST); | |||
| route(FIND_ROUTES); | |||
| $avp(route_attempts) = 1; | |||
| route(EXTERNAL_TO_INTERNAL_RELAY); | |||
| } | |||
| route[SANITY_CHECK] | |||
| { | |||
| if (!mf_process_maxfwd_header("10")) { | |||
| xlog("L_WARN", "$ci|end|max-forward limit reached"); | |||
| sl_send_reply("483", "Too Many Hops"); | |||
| exit; | |||
| } | |||
| if (!sanity_check()) { | |||
| xlog("L_WARN", "$ci|end|message is insane"); | |||
| exit; | |||
| } | |||
| } | |||
| route[CLASSIFY_SOURCE] | |||
| { | |||
| if (ds_is_from_list("1", "1") || ds_is_from_list("3", "1")) { | |||
| xlog("L_INFO", "$ci|log|originated from internal sources"); | |||
| setflag(FLAG_INTERNALLY_SOURCED); | |||
| } else { | |||
| xlog("L_INFO", "$ci|log|originated from external sources"); | |||
| } | |||
| } | |||
| route[HANDLE_OPTIONS] | |||
| { | |||
| if (is_method("OPTIONS")) { | |||
| if (isflagset(FLAG_INTERNALLY_SOURCED)) { | |||
| route(INTERNAL_TO_EXTERNAL_RELAY); | |||
| } else { | |||
| sl_send_reply("200", "Rawr!!"); | |||
| } | |||
| exit; | |||
| } | |||
| } | |||
| route[HANDLE_PRESENCE] | |||
| { | |||
| if (is_method("SUBSCRIBE")) { | |||
| if (!t_newtran()) { | |||
| sl_reply_error(); | |||
| exit; | |||
| } | |||
| handle_subscribe(); | |||
| t_release(); | |||
| exit; | |||
| } | |||
| if (is_method("PUBLISH")) { | |||
| if (!t_newtran()) { | |||
| sl_reply_error(); | |||
| exit; | |||
| } | |||
| handle_publish(); | |||
| t_release(); | |||
| exit; | |||
| } | |||
| } | |||
| route[HANDLE_IN_DIALOG_REQUESTS] | |||
| { | |||
| if (has_totag()) { | |||
| if (loose_route()) { | |||
| xlog("L_INFO", "$ci|log|loose_route in-dialog message"); | |||
| # 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"); | |||
| route(RELAY); | |||
| } else if (t_check_trans()) { | |||
| xlog("L_INFO", "$ci|log|allow message for a known transaction"); | |||
| route(RELAY); | |||
| } else { | |||
| xlog("L_INFO", "$ci|log|message had a to-tag but can't be loose routed"); | |||
| 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(); | |||
| } | |||
| t_check_trans(); | |||
| if (loose_route()) { | |||
| sl_send_reply("403", "No pre-loaded routes"); | |||
| exit(); | |||
| } | |||
| if (is_method("REGISTER")) { | |||
| if (nat_uac_test("3")) { | |||
| xlog("L_INFO", "$ci|log|Correcting NATed contact in registration\n"); | |||
| force_rport(); | |||
| setbflag(FLB_NATB); | |||
| setbflag(FLB_NATSIPPING); | |||
| fix_nated_register(); | |||
| } | |||
| if (is_present_hf("Authorization")) { | |||
| if ($sht(auth_cache=>$Au) != $null && pv_auth_check("$fd", "$sht(auth_cache=>$Au)", "0", "0")) { | |||
| xlog("L_INFO", "$ci|log|Authenticated $Au via cached SIP creds\n"); | |||
| } else { | |||
| ## RABBITMQ - Credentials fetch | |||
| if (!auth_check("$fd", "subscriber", "1")) { | |||
| auth_challenge("$fd", "0"); | |||
| xlog("L_INFO", "$ci|log|Issued new auth challenge to failed registration attempt\n"); | |||
| exit; | |||
| } else { | |||
| xlog("L_INFO", "$ci|log|Caching SIP credentials for $Au\n"); | |||
| $sht(auth_cache=>$Au) = $avp(password); | |||
| } | |||
| } | |||
| } else { | |||
| auth_challenge("$fd", "0"); | |||
| xlog("L_INFO", "$ci|log|Issued new auth challenge to new registration attempt\n"); | |||
| exit; | |||
| } | |||
| # user authenticated - remove auth header | |||
| consume_credentials(); | |||
| save("location"); | |||
| exit; | |||
| } else if (!is_method("MESSAGE")) { | |||
| record_route(); | |||
| } | |||
| } | |||
| # Take the routes from dispatcher - hash over callid | |||
| # If prefered route defined, reorder the destionations | |||
| route[FIND_ROUTES] | |||
| { | |||
| # alg 0 = hash(Callid) | |||
| if (!ds_select_dst("1", "0")) { | |||
| xlog("L_ERR", "$ci|end|no servers avaliable"); | |||
| sl_send_reply("480", "All servers busy"); | |||
| exit; | |||
| } | |||
| # Handle the case when a prefered route is set | |||
| $var(contact_uri) = $(ct{tobody.user}) + "@" + $(ct{tobody.host}); | |||
| if ($sht(associations=>$var(contact_uri)) != $null) { | |||
| $var(prefered_route) = $sht(associations=>$var(contact_uri)); | |||
| xlog("L_INFO", "$ci|log|should route to $var(prefered_route)"); | |||
| route(REORDER_ROUTES); | |||
| } | |||
| } | |||
| route[REORDER_ROUTES] | |||
| { | |||
| $var(i) = 0; | |||
| $var(found) = 0; | |||
| while($(avp(ds_dst)[$var(i)]) != $null) { | |||
| if($(avp(ds_dst)[$var(i)]) != $var(prefered_route)) { | |||
| $avp(tmp_ds_dst) = $(avp(ds_dst)[$var(i)]); | |||
| } else { | |||
| $var(found) = 1; | |||
| } | |||
| $var(i) = $var(i) + 1; | |||
| } | |||
| if ($var(found)) { | |||
| xlog("L_INFO", "$ci|log|re-ordering the dispatcher list to keep associated server first"); | |||
| $(avp(ds_dst)[*]) = $null; | |||
| $var(i) = 0; | |||
| while($(avp(tmp_ds_dst)[$var(i)]) != $null) { | |||
| $avp(ds_dst) = $(avp(tmp_ds_dst)[$var(i)]); | |||
| $var(i) = $var(i) + 1; | |||
| } | |||
| $avp(ds_dst) = $var(prefered_route); | |||
| $du = $var(prefered_route); | |||
| $(avp(tmp_ds_dst)[*]) = $null; | |||
| } else { | |||
| xlog("L_INFO", "$ci|log|associated media server is inactive, moving to $rd"); | |||
| $sht(associations=>$var(contact_uri)) = $null; | |||
| } | |||
| } | |||
| route[HANDLE_MOVE_REQUEST] | |||
| { | |||
| if (is_method("INVITE") && $rU == "*6683*") { | |||
| $var(contact_uri) = @from.uri.user + "@" + @from.uri.host; | |||
| if ($sht(associations=>$var(contact_uri)) != $null) { | |||
| xlog("L_INFO", "$ci|log|remove association for user $var(contact_uri) | |||
| with media server $sht(associations=>$var(contact_uri))\n"); | |||
| $sht(associations=>$var(contact_uri)) = $null; | |||
| } | |||
| send_reply("503", "Removed association"); | |||
| xlog("L_INFO", "$ci|log|removed association for user $var(contact_uri) | |||
| with media server $sht(associations=>$var(contact_uri))\n"); | |||
| exit; | |||
| } | |||
| } | |||
| route[RELAY] | |||
| { | |||
| if (isflagset(FLAG_INTERNALLY_SOURCED)) { | |||
| route(INTERNAL_TO_EXTERNAL_RELAY); | |||
| } else { | |||
| route(EXTERNAL_TO_INTERNAL_RELAY); | |||
| } | |||
| exit(); | |||
| } | |||
| route[INTERNAL_TO_EXTERNAL_RELAY] | |||
| { | |||
| remove_hf("X-AUTH-IP"); | |||
| t_on_reply("EXTERNAL_REPLY"); | |||
| t_set_fr(0, 10000); | |||
| t_relay(); | |||
| } | |||
| route[EXTERNAL_TO_INTERNAL_RELAY] | |||
| { | |||
| if (!isflagset(FLAG_INTERNALLY_SOURCED)) { | |||
| route(NAT_TEST_AND_CORRECT); | |||
| } | |||
| remove_hf("X-AUTH-IP"); | |||
| append_hf("X-AUTH-IP: $si\r\n"); | |||
| t_on_reply("INTERNAL_REPLY"); | |||
| t_on_failure("INTERNAL_FAULT"); | |||
| t_set_fr(0, 1000); | |||
| t_relay(); | |||
| } | |||
| route[LOG_DESTINATION] | |||
| { | |||
| if (isdsturiset()) { | |||
| $var(port) = $dp; | |||
| $var(domain) = $dd; | |||
| } else { | |||
| $var(port) = $rp; | |||
| $var(domain) = $rd; | |||
| } | |||
| if ($(var(port){s.len}) <= 0) { | |||
| $var(port) = "5060"; | |||
| } | |||
| xlog("L_INFO", "$ci|pass|$var(domain):$var(port)"); | |||
| } | |||
| route[NAT_TEST_AND_CORRECT] | |||
| { | |||
| if (is_present_hf("Record-Route")) { | |||
| $var(i) = $rr_count; | |||
| while($var(i) > 0) { | |||
| $var(i) = $var(i) - 1; | |||
| $var(rr) = $(hdr(Record-Route)[$var(i)]); | |||
| if (!is_myself("$(var(rr){nameaddr.uri})")) { | |||
| setflag(FLAG_SKIP_NAT_CORRECTION); | |||
| } | |||
| } | |||
| } else if ($Rp == "5080") { | |||
| setflag(FLAG_SKIP_NAT_CORRECTION); | |||
| } | |||
| if (isflagset(FLAG_SKIP_NAT_CORRECTION)) { | |||
| return(); | |||
| } | |||
| if (nat_uac_test("3")) { | |||
| force_rport(); | |||
| fix_nated_contact(); | |||
| } | |||
| if (has_body("application/sdp") && nat_uac_test("8")) { | |||
| fix_nated_sdp("10"); | |||
| } | |||
| } | |||
| onreply_route[EXTERNAL_REPLY] | |||
| { | |||
| xlog("L_INFO", "$ci|log|external reply $T_reply_code"); | |||
| route(NAT_TEST_AND_CORRECT); | |||
| } | |||
| onreply_route[INTERNAL_REPLY] | |||
| { | |||
| # this route handles replies that are comming from our media server | |||
| xlog("L_INFO", "$ci|start|recieved internal reply $T_reply_code $rr"); | |||
| xlog("L_INFO", "$ci|log|source $si:$sp"); | |||
| if ($rs < 300) { | |||
| xlog("L_INFO", "$ci|pass|$T_req($si):$T_req($sp)"); | |||
| } | |||
| # change 6xx to 4xx | |||
| if (t_check_status("6[0-9][0-9]")) { | |||
| $var(new_code) = "4" + $(T_reply_code{s.substr,1,0}); | |||
| change_reply_status("$var(new_code)", "$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"); | |||
| exit; | |||
| } | |||
| # if the failure case was something that we should recover | |||
| # from then try to find a new media server | |||
| if (t_check_status("(401)|(407)")) { | |||
| xlog("L_INFO", "$ci|log|failure route ignoring auth reply $T_reply_code $rr"); | |||
| exit; | |||
| } else if (t_check_status("403")) { | |||
| xlog("L_INFO", "$ci|log|failure route overriding reply code 403 with 503"); | |||
| xlog("L_INFO", "$ci|pass|$si:$sp"); | |||
| send_reply("503", "Error: Services Unavailable. Try Later"); | |||
| exit; | |||
| } else if (t_check_status("402")) { | |||
| xlog("L_INFO", "$ci|log|failure route overriding reply code 402 with 486"); | |||
| xlog("L_INFO", "$ci|pass|$si:$sp"); | |||
| send_reply("486", "Insufficient Funds"); | |||
| 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"); | |||
| # try to find a new media server to send the call to | |||
| if ($avp(route_attempts) < 3 && ds_next_domain()) { | |||
| xlog("L_INFO", "$ci|log|attempting retry $avp(route_attempts) of failed request"); | |||
| xlog("L_INFO", "$ci|log|routing call to next media server $rd:$rp"); | |||
| # reset the final reply timer | |||
| $avp(final_reply_timer) = 3; | |||
| t_on_reply("INTERNAL_REPLY"); | |||
| t_on_failure("INTERNAL_FAULT"); | |||
| # relay the request to the new media server | |||
| route(EXTERNAL_TO_INTERNAL_RELAY); | |||
| $avp(route_attempts) = $avp(route_attempts) + 1; | |||
| } else if (t_check_status("404")) { | |||
| xlog("L_ERR", "$ci|log|no other media servers avaliable, sending 486"); | |||
| send_reply("486", "Not found"); | |||
| exit; | |||
| } else { | |||
| xlog("L_ERR", "$ci|log|no other media servers avaliable"); | |||
| exit; | |||
| } | |||
| } else if (t_check_status("302")) { | |||
| ## TODO - test this | |||
| ## get_redirects("*"); | |||
| if($T_rpl($hdr(X-Redirect-Server)) != $null) { | |||
| $var(contact_uri) = @from.uri.user + "@" + @from.uri.host; | |||
| $sht(associations=>$var(contact_uri)) = $T_rpl($hdr(X-Redirect-Server)); | |||
| xlog("L_INFO", "$ci|log|stored redirect mapping for $var(contact_uri) to $T_rpl($hdr(X-Redirect-Server))"); | |||
| remove_hf("X-Redirect-Server"); | |||
| } | |||
| } else { | |||
| xlog("L_INFO", "$ci|log|failure route ignoring reply $T_reply_code $rr"); | |||
| exit; | |||
| } | |||
| route(LOG_DESTINATION); | |||
| } | |||
| 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)"); | |||
| } | |||
| ####### Local Configuration ######## | |||
| include_file "local.cfg" | |||
| ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||
| @ -0,0 +1,50 @@ | |||
| ####### Logging Parameters ######### | |||
| debug = L_INFO | |||
| ####### Alias Parameters ######### | |||
| # alias = "mydomain.net" | |||
| ####### UDP Parameters ######### | |||
| ## NOTE: You must MATCH this to your network adapter!! | |||
| ## If they do not match, all UDP packets over | |||
| ## this limit WILL FAIL! | |||
| ## E.g.: Add MTU=1472 to the /etc/sysconfig/network-scripts/XXX | |||
| # udp4_raw_mtu = 1472 | |||
| ####### Binding Parameters ######### | |||
| # mhomed=1 | |||
| listen = tcp:127.0.0.1:5060 | |||
| listen = udp:127.0.0.1:5060 | |||
| listen = tcp:127.0.0.1:7000 | |||
| listen = udp:127.0.0.1:7000 | |||
| ####### Dispatcher module ######## | |||
| #!ifdef DISPATCHER-ROLE | |||
| modparam("dispatcher", "ds_ping_from", "sip:sipcheck@127.0.0.1") | |||
| # modparam("dispatcher", "ds_ping_sock", "udp:127.0.0.1:5060") | |||
| #!endif | |||
| ######## NAT Traversal module - signaling functions ######## | |||
| #!ifdef NAT-TRAVERSAL-ROLE | |||
| modparam("nathelper", "sipping_from", "sip:sipcheck@127.0.0.1") | |||
| # modparam("nathelper", "natping_socket", "127.0.0.1:5060") | |||
| #!endif | |||
| ####### Kazoo Integration module ########## | |||
| #!ifdef INCLUDE-DB-KAZOO | |||
| ## NOTE: The hostname that should be advertised to Kazoo | |||
| modparam("db_kazoo", "node_hostname", "kamailio.2600hz.com") | |||
| ## NOTE: If you want a certain fs_path to be sent Kazoo, | |||
| ## uncomment the next line and set the right value | |||
| # modparam("db_kazoo", "register_fs_path", "127.0.0.1:5060") | |||
| #!endif | |||
| ####### Common Module Parameters ########## | |||
| #!ifdef REGISTRAR-ROLE | |||
| modparam("auth_db|usrloc", "db_url", "kazoo://guest:guest@127.0.0.1:5672/callmgr") | |||
| #!endif | |||
| #!ifdef PRESENCE-ROLE | |||
| modparam("presence", "db_url", "kazoo://guest:guest@127.0.0.1:5672/dialoginfo") | |||
| #!endif | |||
| ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||
| @ -0,0 +1,41 @@ | |||
| ######## NAT Traversal module - signaling functions ######## | |||
| #!ifndef NATHELPER-LOADED | |||
| loadmodule "nathelper.so" | |||
| #!endif | |||
| modparam("nathelper", "received_avp", "$avp(AVP_RECV_PARAM)") | |||
| modparam("nathelper", "natping_interval", 30) | |||
| modparam("nathelper", "ping_nated_only", 1) | |||
| modparam("nathelper", "natping_processes", 5) | |||
| modparam("nathelper", "sipping_bflag", FLB_NATSIPPING) | |||
| ####### NAT Traversal Logic ######## | |||
| route[NAT_TEST_AND_CORRECT] | |||
| { | |||
| if (is_present_hf("Record-Route")) { | |||
| $var(i) = $rr_count; | |||
| while($var(i) > 0) { | |||
| $var(i) = $var(i) - 1; | |||
| $var(rr) = $(hdr(Record-Route)[$var(i)]); | |||
| if (!is_myself("$(var(rr){nameaddr.uri})")) { | |||
| setflag(FLAG_SKIP_NAT_CORRECTION); | |||
| } | |||
| } | |||
| } else if ($Rp == "5080") { | |||
| setflag(FLAG_SKIP_NAT_CORRECTION); | |||
| } | |||
| if (isflagset(FLAG_SKIP_NAT_CORRECTION)) { | |||
| return(); | |||
| } | |||
| if (nat_uac_test("3")) { | |||
| force_rport(); | |||
| fix_nated_contact(); | |||
| } | |||
| if (has_body("application/sdp") && nat_uac_test("8")) { | |||
| fix_nated_sdp("10"); | |||
| } | |||
| } | |||
| ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||
| @ -0,0 +1,48 @@ | |||
| #!trydef INCLUDE-DB-KAZOO | |||
| ######## Generic Hash Table container in shared memory ######## | |||
| modparam("htable", "htable", "dbkp=>size=16;autoexpire=7200") | |||
| ######## Presence User Agent module ######## | |||
| loadmodule "pua_dialoginfo.so" | |||
| modparam("pua_dialoginfo", "library_mode", 1) | |||
| ######## Presence server module ######## | |||
| loadmodule "presence.so" | |||
| loadmodule "presence_dialoginfo.so" | |||
| modparam("presence", "subs_db_mode", 1) | |||
| modparam("presence", "expires_offset", 60) | |||
| modparam("presence", "publ_cache", 0) | |||
| ####### Presence Logic ######## | |||
| route[HANDLE_SUBSCRIBE] | |||
| { | |||
| if (is_method("SUBSCRIBE")) { | |||
| #!ifdef NAT-TRAVERSAL-ROLE | |||
| route(NAT_TEST_AND_CORRECT); | |||
| #!endif | |||
| if (!t_newtran()) { | |||
| sl_reply_error(); | |||
| exit; | |||
| } | |||
| handle_subscribe(); | |||
| t_release(); | |||
| exit; | |||
| } | |||
| } | |||
| route[HANDLE_PUBLISH] | |||
| { | |||
| if (is_method("PUBLISH")) { | |||
| if (!t_newtran()) { | |||
| sl_reply_error(); | |||
| exit; | |||
| } | |||
| handle_publish(); | |||
| t_release(); | |||
| exit; | |||
| } | |||
| } | |||
| ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||
| @ -0,0 +1,76 @@ | |||
| #!trydef INCLUDE-DB-KAZOO | |||
| ######## Generic Hash Table container in shared memory ######## | |||
| modparam("htable", "htable", "auth_cache=>size=16;autoexpire=7200") | |||
| ####### Authentication Interface module ########## | |||
| loadmodule "auth.so" | |||
| loadmodule "auth_db.so" | |||
| modparam("auth_db", "use_domain", 1) | |||
| modparam("auth_db", "version_table", 0) | |||
| modparam("auth_db", "calculate_ha1", 1) | |||
| modparam("auth_db", "password_column", "password") | |||
| modparam("auth_db", "load_credentials", "$avp(password)=password") | |||
| ####### User Location Implementation module ########## | |||
| loadmodule "usrloc.so" | |||
| modparam("usrloc", "db_mode", 1) | |||
| modparam("usrloc", "db_update_as_insert", 1) | |||
| modparam("usrloc", "use_domain", 1) | |||
| modparam("usrloc", "nat_bflag", FLB_NATB) | |||
| ######## NAT Traversal module - signaling functions ######## | |||
| #!ifdef NAT-TRAVERSAL-ROLE | |||
| #!trydef NATHELPER-LOADED | |||
| loadmodule "nathelper.so" | |||
| #!endif | |||
| ####### SIP Registrar implementation module ########## | |||
| loadmodule "registrar.so" | |||
| modparam("registrar", "received_avp", "$avp(AVP_RECV_PARAM)") | |||
| ####### Registrar Logic ######## | |||
| route[HANDLE_REGISTER] | |||
| { | |||
| if (is_method("REGISTER")) { | |||
| #!ifdef NAT-TRAVERSAL-ROLE | |||
| if (nat_uac_test("3")) { | |||
| xlog("L_INFO", "$ci|log|Correcting NATed contact in registration\n"); | |||
| force_rport(); | |||
| setbflag(FLB_NATB); | |||
| setbflag(FLB_NATSIPPING); | |||
| fix_nated_register(); | |||
| } | |||
| #!endif | |||
| if (is_present_hf("Authorization")) { | |||
| if ($sht(auth_cache=>$Au) != $null && pv_auth_check("$fd", "$sht(auth_cache=>$Au)", "0", "0")) { | |||
| xlog("L_INFO", "$ci|log|Authenticated $Au via cached SIP creds\n"); | |||
| } else { | |||
| ## RABBITMQ - Credentials fetch | |||
| if (!auth_check("$fd", "subscriber", "1")) { | |||
| auth_challenge("$fd", "0"); | |||
| xlog("L_INFO", "$ci|log|Issued new auth challenge to failed registration attempt\n"); | |||
| exit; | |||
| } else { | |||
| xlog("L_INFO", "$ci|log|Caching SIP credentials for $Au\n"); | |||
| $sht(auth_cache=>$Au) = $avp(password); | |||
| } | |||
| } | |||
| } else { | |||
| auth_challenge("$fd", "0"); | |||
| xlog("L_INFO", "$ci|log|Issued new auth challenge to new registration attempt\n"); | |||
| exit; | |||
| } | |||
| # user authenticated - remove auth header | |||
| consume_credentials(); | |||
| save("location"); | |||
| exit; | |||
| } | |||
| } | |||
| ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||
| @ -0,0 +1,7 @@ | |||
| ####### Roles ######## | |||
| #!trydef DISPATCHER-ROLE | |||
| #!trydef NAT-TRAVERSAL-ROLE | |||
| #!trydef REGISTRAR-ROLE | |||
| #!trydef PRESENCE-ROLE | |||
| ## vim:set tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||