diff --git a/config.ini b/config.ini index c052afa..f957b5b 100644 --- a/config.ini +++ b/config.ini @@ -1,53 +1,25 @@ ; section are between [] = [section] ; key = value ; to comment add ";" in front of the line -; -; -; NOTE: You must add all your FreeSWITCH servers to the trusted ACLs -; if you are using zones! -; +[amqp] +uri = "amqp://guest:guest@127.0.0.1:5672" + [bigcouch] compact_automatically = true cookie = change_me ip = "127.0.0.1" port = 15984 -;username = "kazoo" -;password = "supermegaexcellenttelephonyplatform" +; username = "kazoo" +; password = "supermegaexcellenttelephonyplatform" admin_port = 15986 -; Define your AMQPs and zones here -[zone] -name = zone_1 -amqp_uri = "amqp://guest:guest@127.0.0.1:5672" - -;[zone] -;name = zone_2 -;amqp_uri = "amqp://guest:guest@127.0.0.2:5672" - -; Define your whistles here [whistle_apps] -;host = apps001.2600hz.com -zone = zone_1 cookie = change_me -;[whistle_apps] -;host = apps002.2600hz.com -;zone = zone_2 -;cookie = change_me - -; Define your ecallmgr's here [ecallmgr] -;host = apps001.2600hz.com -zone = zone_1 cookie = change_me -;[ecallmgr] -;host = apps002.2600hz.com -;zone = zone_2 -;cookie = change_me - [log] -syslog = debug +syslog = info console = notice file = error - diff --git a/freeswitch/autoload_configs/conference.conf.xml b/freeswitch/autoload_configs/conference.conf.xml index c1831ae..379cfcb 100644 --- a/freeswitch/autoload_configs/conference.conf.xml +++ b/freeswitch/autoload_configs/conference.conf.xml @@ -26,6 +26,7 @@ + diff --git a/haproxy/haproxy.cfg b/haproxy/haproxy.cfg index 3f9ece8..a2201fc 100644 --- a/haproxy/haproxy.cfg +++ b/haproxy/haproxy.cfg @@ -1,40 +1,39 @@ global - log 127.0.0.1 local0 - log 127.0.0.1 local1 notice - maxconn 4096 - user haproxy - group haproxy - stats socket /tmp/haproxy.sock mode 777 + log 127.0.0.1 local0 + log 127.0.0.1 local1 notice + maxconn 4096 + user haproxy + group haproxy + stats socket /tmp/haproxy.sock mode 777 defaults - log global - mode http - option httplog - option dontlognull - option redispatch - option httpchk GET / - option allbackups - option http-server-close - maxconn 2000 - retries 3 - timeout connect 6000ms - timeout client 120000ms - timeout server 120000ms - + log global + mode http + option httplog + option dontlognull + option redispatch + option httpchk GET / + option allbackups + maxconn 2000 + retries 3 + timeout connect 6000ms + timeout client 12000ms + timeout server 12000ms + listen bigcouch-data 127.0.0.1:15984 - balance roundrobin + balance roundrobin server db1.zone1.mydomain.com 127.0.0.1:5984 check server db2.zone1.mydomain.com 127.0.0.2:5984 check server db3.zone2.mydomain.com 127.0.0.3:5984 check backup server db4.zone2.mydomain.com 127.0.0.4:5984 check backup listen bigcouch-mgr 127.0.0.1:15986 - balance roundrobin + balance roundrobin server db1.zone1.mydomain.com 127.0.0.1:5986 check server db2.zone1.mydomain.com 127.0.0.2:5986 check server db3.zone2.mydomain.com 127.0.0.3:5986 check backup server db4.zone2.mydomain.com 127.0.0.4:5986 check backup listen haproxy-stats 127.0.0.1:22002 - mode http - stats uri / + mode http + stats uri / diff --git a/kamailio/dbtext/active_watchers b/kamailio/dbtext/active_watchers old mode 100755 new mode 100644 diff --git a/kamailio/dbtext/location b/kamailio/dbtext/location old mode 100755 new mode 100644 diff --git a/kamailio/dbtext/location_attrs b/kamailio/dbtext/location_attrs new file mode 100644 index 0000000..4214eb6 --- /dev/null +++ b/kamailio/dbtext/location_attrs @@ -0,0 +1 @@ +id(int,auto) ruid(string) username(string) domain(string,null) aname(string) atype(int) avalue(string) last_modified(int) diff --git a/kamailio/default.cfg b/kamailio/default.cfg index e338c54..8075c5b 100644 --- a/kamailio/default.cfg +++ b/kamailio/default.cfg @@ -83,6 +83,9 @@ disable_sctp = yes ####### Modules Section ######## mpath="/usr/lib64/kamailio/modules/" +######## Kamailio control connector module ######## +loadmodule "ctl.so" + ######## Kamailio core extensions module ######## loadmodule "kex.so" @@ -137,30 +140,34 @@ loadmodule "xlog.so" loadmodule "mi_fifo.so" modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo") +######## 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) ####### Kazoo Integration module ########## -loadmodule "db_kazoo.so" -modparam("db_kazoo", "node_hostname", "MY_HOSTNAME") -modparam("db_kazoo", "amqp_connection", "MY_AMQP_URL") +loadmodule "kazoo.so" +modparam("kazoo", "node_hostname", "MY_HOSTNAME") +modparam("kazoo", "amqp_connection", "MY_AMQP_URL") #!ifdef MY_AMQP_URL_SECONDARY -modparam("db_kazoo", "amqp_connection", "MY_AMQP_URL_SECONDARY") +modparam("kazoo", "amqp_connection", "MY_AMQP_URL_SECONDARY") #!endif #!ifdef MY_AMQP_URL_TERTIARY -modparam("db_kazoo", "amqp_connection", "MY_AMQP_URL_TERTIARY") +modparam("kazoo", "amqp_connection", "MY_AMQP_URL_TERTIARY") #!endif #!ifdef MY_AMQP_MAX_CHANNELS -modparam("db_kazoo", "amqp_max_channels", MY_AMQP_MAX_CHANNELS) +modparam("kazoo", "amqp_max_channels", MY_AMQP_MAX_CHANNELS) #!else -modparam("db_kazoo", "amqp_max_channels", 100) +modparam("kazoo", "amqp_max_channels", 100) #!endif -modparam("db_kazoo", "amqp_internal_loop_count", 1); -modparam("db_kazoo", "amqp_consumer_loop_count", 4); +modparam("kazoo", "amqp_internal_loop_count", 1); +modparam("kazoo", "amqp_consumer_loop_count", 4); ####### Role Configurations ########## #!ifdef DISPATCHER-ROLE @@ -172,6 +179,9 @@ include_file "registrar-role.cfg" #!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 @@ -205,14 +215,14 @@ modparam("permissions", "db_mode", 1) ####### Routing Logic ######## route { + route(SANITY_CHECK); + # log the basic info regarding this call - xlog("L_INFO", "$ci|start|recieved $oP request $rm $ou"); + xlog("L_INFO", "$ci|start|recieved $pr 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); #!ifdef ANTIFLOOD-ROLE @@ -269,21 +279,21 @@ route route[SANITY_CHECK] { - if (!mf_process_maxfwd_header("10")) { - xlog("L_WARN", "$ci|end|too much hops, not enough barley"); - send_reply("483", "Too Many Hops"); + if (!sanity_check()) { + xlog("L_WARN", "$ci|end|message from $si:$sp is insane"); exit; } - if (!sanity_check()) { - xlog("L_WARN", "$ci|end|message is insane"); + if (!mf_process_maxfwd_header("10")) { + xlog("L_WARN", "$ci|end|too much hops, not enough barley from $si:$sp"); + 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"); + xlog("L_WARN", "$ci|end|dropping message with user-agent $ua from $si:$sp"); exit; } } @@ -320,13 +330,31 @@ route[HANDLE_NOTIFY] { if (is_method("NOTIFY")) { if (isflagset(FLAG_INTERNALLY_SOURCED)) { + if (registered("location")) { + lookup("location"); + xlog("L_INFO", "$ci|log|routing to $ruid"); + } route(INTERNAL_TO_EXTERNAL_RELAY); } else { #!ifdef TRAFFIC-FILTER-ROLE route(FILTER_REQUEST_DOMAIN); #!endif - sl_send_reply("200", "Rawr!!"); + #!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"); + sl_send_reply("405", "Stay Alive / Method Not Allowed"); + } else { + xlog("L_INFO", "$ci|stop|consuming event $hdr(Event)"); + sl_send_reply("200", "Rawr!!"); + } } exit; } @@ -334,16 +362,47 @@ route[HANDLE_NOTIFY] route[HANDLE_MESSAGE] { + #!ifdef MESSAGE-ROLE if (is_method("MESSAGE")) { - if (isflagset(FLAG_INTERNALLY_SOURCED)) { + xlog("L_INFO", "$ci|MESSAGE from $fu to $tu"); + t_on_reply("MESSAGE_REPLY"); + if (isflagset(FLAG_INTERNALLY_SOURCED) || src_ip == myself) { + xlog("L_INFO", "$ci| routing MESSAGE to external from $fu to $tu"); + if (registered("location")) { + lookup("location"); + xlog("L_INFO", "$ci|log|routing to $ruid"); + } 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"); + #!endif } else { + xlog("L_WARN", "$ci|end|MESSAGE $(hdr(Content-Type))"); + if( $hdr(Content-Type) == "application/im-iscomposing+xml" ) { + xlog("L_WARN", "$ci|end|dropping MESSAGE application/im-iscomposing+xml"); + 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; + exit(); } } + #!endif } + route[HANDLE_IN_DIALOG_REQUESTS] { if (has_totag()) { @@ -486,6 +545,13 @@ route[EXTERNAL_TO_INTERNAL_RELAY] } #!endif + ##### CALL-PARK #### + if(is_method("REFER")) { + $avp(refer_to) = $hdr(Refer-To); + $avp(refer_to_uri) = $rt; + $avp(referred_by) = $hdr(Referred-By); + } + remove_hf_re("^X-.*"); append_hf("X-AUTH-IP: $si\r\n"); @@ -541,9 +607,9 @@ onreply_route[INTERNAL_REPLY] #!endif if (is_method("INVITE") && - !isflagset(FLAG_SESSION_PROGRESS) && - t_check_status("(180)|(183)|(200)") - ) { + !isflagset(FLAG_SESSION_PROGRESS) && + t_check_status("(180)|(183)|(200)") + ) { if ($avp(AVP_REDIRECT_KEY) != $null && $sht(redirects=>$avp(AVP_REDIRECT_KEY)) != $null ) { @@ -554,6 +620,12 @@ onreply_route[INTERNAL_REPLY] setflag(FLAG_SESSION_PROGRESS); } + ##### CALL-PARK #### + if (is_method("REFER") && t_check_status("(200)|(202)") ) { + $sht(park=>$(avp(refer_to_uri){uri.user})@$(avp(refer_to_uri){uri.domain})) = "sip:" + $(ct{tobody.uri}{uri.host}) + ":" + $(ct{tobody.uri}{uri.port}); + xlog("L_INFO", "caching park info $(avp(refer_to_uri){uri.user})@$(avp(refer_to_uri){uri.domain}) = sip:$(ct{tobody.uri}{uri.host}):$(ct{tobody.uri}{uri.port})"); + } + if ($rs < 300) { xlog("L_INFO", "$ci|pass|$T_req($si):$T_req($sp)"); } @@ -575,8 +647,8 @@ failure_route[INTERNAL_FAULT] # 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})); + $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))"); @@ -595,7 +667,7 @@ failure_route[INTERNAL_FAULT] 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)"); - t_reply("$(var(new_code){s.int})", "$var(reply_reason)"); + 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 @@ -636,13 +708,13 @@ event_route[kazoo:mod-init] { #!ifdef PRESENCE-ROLE -### use this simple form of binding a listener +### 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' +### '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 @@ -651,13 +723,27 @@ event_route[kazoo:mod-init] ### pattern : ^BLF ### definition : ha-mode: all ### -### - $var(payload) = "{ 'exchange' : 'dialoginfo' , 'type' : 'direct', 'queue' : 'BLF-QUEUE-MY_HOSTNAME', 'routing' : 'BLF-MY_HOSTNAME', 'auto_delete' : 0, 'durable' : 1, 'no_ack' : 0, 'wait_for_consumer_ack' : 1 }"; - xlog("L_INFO","SUBSCRIBE $var(payload)"); +### + + $var(payload) = '{ "exchange" : "dialoginfo" , "type" : "direct", "queue" : "BLF-QUEUE-MY_HOSTNAME", "routing" : "BLF-MY_HOSTNAME", "auto_delete" : 0, "durable" : 1, "no_ack" : 0, "wait_for_consumer_ack" : 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 REGISTRAR-ROLE + + $var(payload) = "{ 'exchange' : 'callmgr' , '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 - } event_route[kazoo:consumer-event] diff --git a/kamailio/dispatcher-role.cfg b/kamailio/dispatcher-role.cfg index 5782199..9cee94e 100644 --- a/kamailio/dispatcher-role.cfg +++ b/kamailio/dispatcher-role.cfg @@ -1,5 +1,6 @@ ######## Generic Hash Table container in shared memory ######## modparam("htable", "htable", "failover=>size=16;autoexpire=120") +modparam("htable", "htable", "park=>size=4;autoexpire=600") ####### Dispatcher module ######## loadmodule "dispatcher.so" @@ -32,11 +33,11 @@ modparam("dispatcher", "ds_ping_from", "sip:sipcheck@MY_IP_ADDRESS") ####### Dispatcher Logic ######## route[DISPATCHER_CLASSIFY_SOURCE] { - if (ds_is_from_list("1", "1") || - ds_is_from_list("2", "1") || - ds_is_from_list("3", "1") || - ds_is_from_list("10", "1") || - ds_is_from_list("20", "1")) { + if (ds_is_from_list(1, 3) || + ds_is_from_list(2, 3) || + ds_is_from_list(3, 3) || + ds_is_from_list(10, 3) || + ds_is_from_list(20, 3)) { xlog("L_INFO", "$ci|log|originated from internal sources"); setflag(FLAG_INTERNALLY_SOURCED); @@ -69,6 +70,7 @@ route[DISPATCHER_FIND_ROUTES] #!endif if (is_method("INVITE")) { + if($hdr(Replaces)!= $null) { $var(replaced_call_id) = $(hdr(Replaces){s.select,0,;}); xlog("L_INFO", "$ci|log|replaces call-id $var(replaced_call_id)"); @@ -82,6 +84,15 @@ route[DISPATCHER_FIND_ROUTES] } } } + + ##### CALL-PARK #### + if($(ru{uri.user}) =~ "\*3" && $sht(park=>$(ru{uri.user})@$(ru{uri.domain})) != $null) { + $du = $sht(park=>$(ru{uri.user})@$(ruri{uri.domain})); + $sht(park=>$(ru{uri.user})@$(ruri{uri.domain})) = $null; + xlog("L_INFO", "$ci|log|redirecting park request to $du"); + return; + } + } if (!ds_select_dst("$var(ds_group)", "0") || $(avp(ds_dst)[0]) == $null) { diff --git a/kamailio/local.cfg b/kamailio/local.cfg index 7e12270..c009d23 100644 --- a/kamailio/local.cfg +++ b/kamailio/local.cfg @@ -19,6 +19,7 @@ debug = L_INFO # # #!trydef ANTIFLOOD-ROLE # # #!trydef RATE-LIMITER-ROLE # # #!trydef ACL-ROLE +# # #!trydef MESSAGE-ROLE ################################################################################ ## SERVER INFORMATION diff --git a/kamailio/message-role.cfg b/kamailio/message-role.cfg new file mode 100644 index 0000000..afa8f6a --- /dev/null +++ b/kamailio/message-role.cfg @@ -0,0 +1,55 @@ +modparam("htable", "htable", "msg=>size=32;autoexpire=60;") + + +event_route[kazoo:consumer-event-message-route] +{ + $var(uri_username) = ""; + kazoo_json($kzE, "Endpoints[0].To-Username", "$var(uri_username)"); + $var(x) = $(kzE{kz.json,Endpoints[0].To-Username}); + xlog("L_INFO", "received message route for $(kzE{kz.json,Endpoints[0].To-DID})"); + if( $var(uri_username) != "" ) { + $var(from_uri) = "sip:" + $(kzE{kz.json,Caller-ID-Number}) + "@" + $(kzE{kz.json,Endpoints[0].To-Realm}); + $var(to_uri) = "sip:" + $(kzE{kz.json,Endpoints[0].To-Username}) + "@" + $(kzE{kz.json,Endpoints[0].To-Realm}); + } else { + $var(from_uri) = "sip:" + $(kzE{kz.json,Caller-ID-Number}) + $(kzE{kz.json,Endpoints[0].To-Realm}); + $var(to_uri) = $(kzE{kz.json,Endpoints[0].Route}); + } + $sht(msg=>$(kzE{kz.json,Call-ID})) = $kzE; + $uac_req(method)="MESSAGE"; + $uac_req(body)= $(kzE{kz.json,Body}); + $uac_req(hdrs)="Content-Type: text/plain\r\n"; + $uac_req(turi) = $var(to_uri); + $uac_req(ruri) = $var(to_uri); + $uac_req(furi) = $var(from_uri); + $uac_req(ouri) = "sip:MY_IP_ADDRESS:5060"; + $uac_req(callid) = $(kzE{kz.json,Call-ID}); + xlog("L_INFO", "sending message from $var(from_uri) to $var(to_uri) "); + uac_req_send(); +} + +onreply_route[MESSAGE_REPLY] +{ + if( $(sht(msg=>$ci)) == $null) { + exit(); + } + + if($T_reply_code != 200 && $T_reply_code != 202) { + $var(Result) = "Failure"; + } else { + $var(Result) = "Success"; + } + + $var(Payload) = '{ "Event-Category" : "message", "Event-Name" : "delivery", "Call-ID" : "' + $(sht(msg=>$ci){kz.json,Call-ID}) + '", "Message-ID" : "' + $(sht(msg=>$ci){kz.json,Message-ID}) +'" , "Delivery-Result-Code" : "sip:" + $T_reply_code + '" , "Msg-ID" : "' + $(sht(msg=>$ci){kz.json,Msg-ID}) + '" , "Status" : "' + $var(Result) + '"}'; + + $var(RoutingKey) = $(sht(msg=>$ci){kz.json,Server-ID}); + $var(exchange) = "targeted"; + if($var(RoutingKey) == "") { + $var(exchange) = "sms"; + $var(RoutingKey) = "message.delivery." + $(sht(msg=>$ci){kz.json,Call-ID}{kz.encode}); + } + xlog("L_INFO", "sending delivery message for $ci"); + kazoo_publish($var(exchange), $var(RoutingKey), $var(Payload)); +} + + +# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab diff --git a/kamailio/presence-role.cfg b/kamailio/presence-role.cfg index 7589833..8c40331 100644 --- a/kamailio/presence-role.cfg +++ b/kamailio/presence-role.cfg @@ -1,37 +1,33 @@ ######## Presence server module ######## +#!trydef PRESENCE_MIN_EXPIRES 300 +#!trydef PRESENCE_MIN_EXPIRES_ACTION 1 +#!trydef PRESENCE_MAX_EXPIRES 3600 + +modparam("htable", "htable", "p=>size=32;autoexpire=600;") + loadmodule "presence.so" loadmodule "presence_dialoginfo.so" loadmodule "presence_mwi.so" loadmodule "presence_xml.so" -modparam("presence", "subs_db_mode", 1) +modparam("presence_dialoginfo", "force_dummy_dialog", 1) +modparam("presence_xml", "force_active", 1) + +modparam("presence", "subs_db_mode", 3) modparam("presence", "expires_offset", 60) -modparam("presence", "send_fast_notify", 0) +modparam("presence", "send_fast_notify", 1) modparam("presence", "clean_period", 30) modparam("presence", "publ_cache", 0) -modparam("presence", "min_expires", 0) -modparam("presence", "max_expires", 3600) - -## use this -#modparam("presence", "db_url", "MY_AMQP_URL/dialoginfo") - -## or this +modparam("presence", "min_expires_action", PRESENCE_MIN_EXPIRES_ACTION) +modparam("presence", "min_expires", PRESENCE_MIN_EXPIRES) +modparam("presence", "max_expires", PRESENCE_MAX_EXPIRES) +modparam("presence", "sip_uri_match", 1) +modparam("presence", "waitn_time", 1) +modparam("presence", "notifier_processes", 5) modparam("presence", "db_url", "text:///etc/kazoo/kamailio/dbtext") -modparam("db_kazoo", "db_url", "text:///etc/kazoo/kamailio/dbtext") -modparam("db_kazoo", "pua_mode", 1) - - -modparam("presence_xml", "force_active", 1) - - -######## Presence User Agent module ######## -#loadmodule "pua.so" -#modparam("pua", "db_mode", 0) -#modparam("pua", "db_url", "text:///etc/kazoo/kamailio/dbtext") -#modparam("pua", "update_period", 6) -#modparam("pua", "min_expires", 300) -#modparam("pua", "outbound_proxy", "sip:MY_IP_ADDRESS") +modparam("kazoo", "db_url", "text:///etc/kazoo/kamailio/dbtext") +modparam("kazoo", "pua_mode", 1) ####### Presence Logic ######## route[HANDLE_SUBSCRIBE] @@ -46,8 +42,33 @@ route[HANDLE_SUBSCRIBE] exit; } - handle_subscribe(); + if ($tU == $null) { + xlog("L_INFO", "$ci|stop|ignoring subscribe with empty TO username from a $ua"); + sl_send_reply(400, "Missing TO username"); + t_release(); + exit; + } + + if ($fU == $null) { + xlog("L_INFO", "$ci|stop|ignoring subscribe with empty FROM username from a $ua"); + sl_send_reply(400, "Missing FROM username"); + t_release(); + exit; + } + if (!handle_subscribe()) { + xlog("L_INFO", "$ci|stop|unsupported subsribe"); + t_release(); + exit; + } + + $var(Expires) = $hdr(Expires); + if($var(Expires) < PRESENCE_MIN_EXPIRES) { + $var(Expires) = PRESENCE_MIN_EXPIRES; + } else if($var(Expires) > PRESENCE_MAX_EXPIRES) { + $var(Expires) = PRESENCE_MAX_EXPIRES; + } + ##RabbitMQ $var(fs_path) = "%3C" + $rz + "%3A" + $Ri + "%3A" + $Rp + "%3Btransport=" + $proto + "%3Blr%3Breceived=" + $si+":"+$sp+"%3E"; $var(fs_contact) = "<" + $(ct{tobody.uri}) + ";fs_path=" + $var(fs_path) + ">"; @@ -55,7 +76,7 @@ route[HANDLE_SUBSCRIBE] $var(fs_contact) = $var(fs_contact) + ";" + $(ct{tobody.params}); } - $var(amqp_payload_request) = "{'Event-Category' : 'presence', 'Event-Name' : 'subscription', 'Event-Package' : '" + $hdr(event) + "', 'Expires' : " + $hdr(Expires) + ", 'Queue' : 'BLF-MY_HOSTNAME', 'Server-ID' : 'BLF-MY_HOSTNAME' ,'Contact' : '" + $var(fs_contact) + "', 'Call-ID' : '" + $ci + "', 'From' : '" + $fu +"', 'User' : '" + $tu + "', 'User-Agent' : '" + $ua + "' }"; + $var(amqp_payload_request) = '{"Event-Category" : "presence", "Event-Name" : "subscription", "Event-Package" : "$hdr(event)", "Expires" : "$var(Expires)", "Queue" : "BLF-MY_HOSTNAME", "Server-ID" : "BLF-MY_HOSTNAME" , "Contact" : "$(ct{s.escape.common})", "Call-ID" : "$ci", "From" : "$fu", "User" : "$tu", "User-Agent" : "$(ua{s.escape.common})" }'; kazoo_publish("dialoginfo_subs", "dialoginfo_subs", $var(amqp_payload_request)); @@ -82,10 +103,22 @@ route[HANDLE_PUBLISH] event_route[kazoo:consumer-event-presence-update] { - xlog("L_INFO", "received $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,From})"); - kazoo_pua_publish($kzE); - pres_refresh_watchers("$(kzE{kz.json,From})", "$(kzE{kz.json,Event-Package})", 1); - + if( $(kzE{kz.json,Event-Package}) == "dialog") { + if($sht(p=>$(kzE{kz.json,Call-ID})) != $(kzE{kz.json,State})) { + xlog("L_INFO", "received $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,From})"); + xlog("L_INFO", "payload $kzE"); + $sht(p=>$(kzE{kz.json,Call-ID})) = $(kzE{kz.json,State}); + kazoo_pua_publish($kzE); + pres_refresh_watchers("$(kzE{kz.json,From})", "$(kzE{kz.json,Event-Package})", 1); + } else { + xlog("L_INFO", "received duplicate $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,From})"); + xlog("L_INFO", "payload $kzE"); + } + } else { + xlog("L_INFO", "received $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,From}) $kzE"); + kazoo_pua_publish($kzE); + pres_refresh_watchers("$(kzE{kz.json,From})", "$(kzE{kz.json,Event-Package})", 1); + } } # vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab diff --git a/kamailio/registrar-role.cfg b/kamailio/registrar-role.cfg index 4cb2c41..d5c2c96 100644 --- a/kamailio/registrar-role.cfg +++ b/kamailio/registrar-role.cfg @@ -11,10 +11,17 @@ loadmodule "auth.so" ####### User Location Implementation module ########## loadmodule "usrloc.so" -modparam("usrloc", "db_mode", 0) -modparam("usrloc", "db_update_as_insert", 1) +modparam("usrloc", "db_update_as_insert", 0) modparam("usrloc", "use_domain", 1) modparam("usrloc", "nat_bflag", FLB_NATB) +modparam("usrloc", "db_url", "text:///etc/kazoo/kamailio/dbtext") +modparam("usrloc", "db_mode", 0) +modparam("usrloc", "handle_lost_tcp", 1) +modparam("usrloc", "xavp_contact", "ulattrs") +modparam("usrloc", "db_check_update", 1) +modparam("usrloc", "timer_interval", 30) +modparam("usrloc", "timer_procs", 1) + ######## NAT Traversal module - signaling functions ######## #!ifdef NAT-TRAVERSAL-ROLE @@ -31,6 +38,8 @@ loadmodule "registrar.so" modparam("registrar", "received_avp", "$avp(AVP_RECV_PARAM)") modparam("registrar", "min_expires", REGISTRAR_MIN_EXPIRES) modparam("registrar", "max_expires", REGISTRAR_MAX_EXPIRES) +modparam("registrar", "xavp_cfg", "regcfg") +modparam("registrar", "reg_match_flag", 1) ####### Registrar Logic ######## @@ -64,7 +73,10 @@ route[HANDLE_REGISTER] route[ATTEMPT_AUTHORIZATION] { - if ($sht(auth_cache=>$Au) != $null) { + $xavp(regcfg=>match_received) = $su; + $xavp(regcfg[0]=>match_contact) = $(ct{nameaddr.uri}); + + if ($sht(auth_cache=>$Au) != $null && registered("location", "$rz:$Au", 6) == 1)) { xlog("L_INFO", "$ci|log|authenticating $fu via cached SIP creds"); $var(password) = $sht(auth_cache=>$Au); } else { @@ -72,6 +84,7 @@ route[ATTEMPT_AUTHORIZATION] $var(amqp_routing_key) = "authn.req." + $(fd{kz.encode}); if(kazoo_query("callmgr", $var(amqp_routing_key), $var(amqp_payload_request))) { $var(password) = $(kzR{kz.json,Auth-Password}); + $xavp(ulattrs=>custom_channel_vars) = $(kzR{kz.json,Custom-Channel-Vars}); xlog("L_INFO", "$ci|log|authenticating $Au via Kazoo query response"); } else { xlog("L_INFO", "$ci|log|failed to query Kazoo for authentication credentials for $Au $si:$sp"); @@ -105,15 +118,28 @@ route[ATTEMPT_AUTHORIZATION] # user authenticated - remove auth header consume_credentials(); - save("location"); - $var(expires) = @contact.expires; - if($var(expires) == $null) { - $var(expires) = $hdr(Expires); + $var(save_result) = save("location", "0x04"); + if($var(save_result) == -1) { + auth_challenge("$fd", "0"); + xlog("L_INFO", "$ci|end|issued auth challenge after failed attempt to save contact for $Au $si:$sp"); + exit; + } else { + if($var(save_result) == 1) { + $var(new_reg) = "true"; + } else { + $var(new_reg) = "false"; + } } - if($var(expires) == $null) { - $var(expires) = REGISTRAR_MIN_EXPIRES; + if(@contact.expires) { + $var(expires) = @contact.expires; + } else { + if($hdr(Expires)) { + $var(expires) = $hdr(Expires); + } else { + $var(expires) = REGISTRAR_MIN_EXPIRES; + } } if($var(expires) == 0) { @@ -127,7 +153,7 @@ route[ATTEMPT_AUTHORIZATION] $var(return_port) = "5060"; } - $var(params) = "fs_path="; + $var(params) = "fs_path="; ## TODO: fix escaping, some phones send us -- reg-id=1;+sip.instance="urn:uuid:9b8bd513-0e6e-4660-ad5e-5e35d88cc68f"; ## and if we can store it but not use it because it looses the escapes (that weren't there...) @@ -143,9 +169,9 @@ route[ATTEMPT_AUTHORIZATION] $var(register_contants) = ' "Presence-Hosts" : "n/a", "Profile-Name" : "sipinterface_1", "Status" : "Registered", "Event-Timestamp" : "' + $TS + '", "Expires" : ' + $var(expires); - $var(amqp_payload_request) = '{"Event-Category" : "directory", "Event-Name" : "reg_success", "Contact" : "' + $var(fs_contact) + '", "Call-ID" : "' + $ci + '", "Realm" : "' + $fd + '", "Username" : "' + $fU + '", "From-User" : "' + $fU + '", "From-Host" : "' + $fd + '", "To-User" : "' + $tU + '", "To-Host" : "' + $td + '", "User-Agent" : "' + $ua + '" ,' + $var(register_contants) + ' }'; + $var(amqp_payload_request) = '{"Event-Category" : "directory", "Event-Name" : "reg_success", "First-Registration" : $var(new_reg), "Contact" : "$var(fs_contact)", "Call-ID" : "$ci", "Realm" : "$fd", "Username" : "$fU", "From-User" : "$fU", "From-Host" : "$fd", "To-User" : "$tU", "To-Host" : "$td", "User-Agent" : "$ua" , "Custom-Channel-Vars" : $xavp(ulattrs=>custom_channel_vars), $var(register_contants) }'; - $var(amqp_routing_key) = "registration.success." + $(fd{kz.encode}) + "." + $fU; + $var(amqp_routing_key) = "registration.success." + $(fd{kz.encode}) + "." + $(fU{kz.encode}); kazoo_publish("callmgr", $var(amqp_routing_key), $var(amqp_payload_request)); @@ -153,4 +179,15 @@ route[ATTEMPT_AUTHORIZATION] exit; } +## kazoo event route , {"directory", "reg_flush") => reg-flush by kamailio limitations +## when a Event-Category or Event-Name has a underscore (_) we need to declare it with a dash (-) +event_route[kazoo:consumer-event-directory-reg-flush] +{ + $var(user) = $(kzE{kz.json,Username}) + "@" + $(kzE{kz.json,Realm}); + if ($sht(auth_cache=>$var(user)) != $null) { + xlog("L_INFO", "log|removing SIP credentials cache for $var(user)"); + $sht(auth_cache=>$var(user)) = $null; + } +} + # vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab diff --git a/rabbitmq/rabbitmq.config b/rabbitmq/rabbitmq.config index fca901a..1d86f32 100644 --- a/rabbitmq/rabbitmq.config +++ b/rabbitmq/rabbitmq.config @@ -1,6 +1,6 @@ -[{rabbit, [{disk_free_limit, 5242880} +[ +{rabbit, [{disk_free_limit, 5242880} ,{vm_memory_high_watermark, 0.8} - ,{hipe_compile, true} ,{loopback_users, []} ]}, {rabbitmq_management_agent, [ {force_fine_statistics, false} ] }