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} ] }