From bd40ac64debd6bfc58e152c5471c0194d51a75e7 Mon Sep 17 00:00:00 2001 From: lazedo Date: Wed, 4 Apr 2018 11:41:41 +0100 Subject: [PATCH 1/8] pusher can send kazoo invite format --- kamailio/default.cfg | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/kamailio/default.cfg b/kamailio/default.cfg index 1d248a7..15a117f 100644 --- a/kamailio/default.cfg +++ b/kamailio/default.cfg @@ -652,18 +652,16 @@ route[INTERNAL_TO_EXTERNAL_RELAY] #!ifdef REGISTRAR_ROLE if ($hdr(X-KAZOO-AOR) != $null) { xlog("L_INFO", "$ci|log|using AOR $hdr(X-KAZOO-AOR)\n"); - if ($hdr(X-KAZOO-INVITE-FORMAT) == "contact") { - if(lookup("location", "$hdr(X-KAZOO-AOR)") > 0){ + if (lookup("location", "$hdr(X-KAZOO-AOR)") > 0) { + if ($hdr(X-KAZOO-INVITE-FORMAT) == "contact") { xlog("L_INFO", "$ci|end|routing to contact $ru\n"); } else { - xlog("L_INFO", "$ci|end|lookup for AOR $hdr(X-KAZOO-AOR) failed\n"); - sl_send_reply("404", "Not registered"); - exit; - } - } else if (reg_fetch_contacts("location", "$hdr(X-KAZOO-AOR)", "callee")) { - $du = $(ulc(callee=>received)); - $fs = $(ulc(callee=>socket)); - xlog("L_INFO", "$ci|log|routing $hdr(X-KAZOO-AOR) to $du via $fs\n"); + reg_fetch_contacts("location", "$hdr(X-KAZOO-AOR)", "callee"); + $du = $(ulc(callee=>received)); + $fs = $(ulc(callee=>socket)); + reg_free_contacts("callee"); + xlog("L_INFO", "$ci|log|routing $hdr(X-KAZOO-AOR) to $du via $fs\n"); + } } else if ($hdr(X-KAZOO-PUSHER-Token-ID) != $null) { xlog("L_INFO", "$ci|log|ignoring missing registration while waiting for push notification response\n"); t_on_reply("EXTERNAL_REPLY"); From 5fefde69655a5acfd1c9b0bb3d0d793f42c86ec2 Mon Sep 17 00:00:00 2001 From: lazedo Date: Fri, 22 Jun 2018 14:13:32 +0100 Subject: [PATCH 2/8] do not process pusher in default --- kamailio/default.cfg | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/kamailio/default.cfg b/kamailio/default.cfg index 15a117f..df1e3e6 100644 --- a/kamailio/default.cfg +++ b/kamailio/default.cfg @@ -652,7 +652,7 @@ route[INTERNAL_TO_EXTERNAL_RELAY] #!ifdef REGISTRAR_ROLE if ($hdr(X-KAZOO-AOR) != $null) { xlog("L_INFO", "$ci|log|using AOR $hdr(X-KAZOO-AOR)\n"); - if (lookup("location", "$hdr(X-KAZOO-AOR)") > 0) { + if(lookup("location", "$hdr(X-KAZOO-AOR)") > 0) { if ($hdr(X-KAZOO-INVITE-FORMAT) == "contact") { xlog("L_INFO", "$ci|end|routing to contact $ru\n"); } else { @@ -661,13 +661,7 @@ route[INTERNAL_TO_EXTERNAL_RELAY] $fs = $(ulc(callee=>socket)); reg_free_contacts("callee"); xlog("L_INFO", "$ci|log|routing $hdr(X-KAZOO-AOR) to $du via $fs\n"); - } - } else if ($hdr(X-KAZOO-PUSHER-Token-ID) != $null) { - xlog("L_INFO", "$ci|log|ignoring missing registration while waiting for push notification response\n"); - t_on_reply("EXTERNAL_REPLY"); - t_set_fr(0, 10000); - t_release(); - exit; + } } else { xlog("L_INFO", "$ci|end|user is not registered\n"); sl_send_reply("404", "Not registered"); From 10c8290fc336d47166d1a5e8beb8286a8ad80b99 Mon Sep 17 00:00:00 2001 From: lazedo Date: Fri, 22 Jun 2018 14:16:35 +0100 Subject: [PATCH 3/8] handle variations of push notification * invite only * push_and_invite * push_only (by exclusion) --- kamailio/pusher-role.cfg | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/kamailio/pusher-role.cfg b/kamailio/pusher-role.cfg index 1b57d8f..cb49a73 100644 --- a/kamailio/pusher-role.cfg +++ b/kamailio/pusher-role.cfg @@ -12,20 +12,28 @@ route[PUSHER_ROUTE] if ( (!is_method("INVITE")) || (!isflagset(FLAG_INTERNALLY_SOURCED)) || $hdr(X-KAZOO-PUSHER-Token-ID) == $null) return; - if(registered("location") && $hdr(X-KAZOO-PUSHER-Invite-Format) != "push_and_invite") { + if(registered("location") && $hdr(X-KAZOO-PUSHER-Invite-Format) == "invite_only") { return; } - xlog("L_INFO", "$ci| pusher received request to wakeup $tu\n"); + xlog("L_INFO", "$ci|pusher received request to wakeup $(tu{s.tolower})\n"); sl_send_reply(180, "waking the dead guy"); + t_set_fr(0, 20000); if (t_newtran()) { route(SEND_PUSH_NOTIFICATION); remove_hf_re("^X-.*"); t_save_lumps(); ts_store("$(tu{s.tolower})"); + t_suspend(); } else { sl_send_reply(500, "error creating transaction for waking the dead guy"); } + + if($hdr(X-KAZOO-PUSHER-Invite-Format) == "push_and_invite") { + return; + } + + exit(); } route[SEND_PUSH_NOTIFICATION] From 88150db771708eabf3f3c578546fd2ea3c12c9bc Mon Sep 17 00:00:00 2001 From: lazedo Date: Wed, 27 Jun 2018 12:55:03 +0100 Subject: [PATCH 4/8] check X-KAZOO-INVITE-FORMAT before lookup --- kamailio/default.cfg | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/kamailio/default.cfg b/kamailio/default.cfg index df1e3e6..1fff271 100644 --- a/kamailio/default.cfg +++ b/kamailio/default.cfg @@ -652,19 +652,21 @@ route[INTERNAL_TO_EXTERNAL_RELAY] #!ifdef REGISTRAR_ROLE if ($hdr(X-KAZOO-AOR) != $null) { xlog("L_INFO", "$ci|log|using AOR $hdr(X-KAZOO-AOR)\n"); - if(lookup("location", "$hdr(X-KAZOO-AOR)") > 0) { - if ($hdr(X-KAZOO-INVITE-FORMAT) == "contact") { + if ($hdr(X-KAZOO-INVITE-FORMAT) == "contact") { + if(lookup("location", "$hdr(X-KAZOO-AOR)") > 0){ xlog("L_INFO", "$ci|end|routing to contact $ru\n"); } else { - reg_fetch_contacts("location", "$hdr(X-KAZOO-AOR)", "callee"); - $du = $(ulc(callee=>received)); - $fs = $(ulc(callee=>socket)); - reg_free_contacts("callee"); - xlog("L_INFO", "$ci|log|routing $hdr(X-KAZOO-AOR) to $du via $fs\n"); + xlog("L_INFO", "$ci|end|lookup for AOR $hdr(X-KAZOO-AOR) failed\n"); + sl_send_reply("410", "Not registered"); + exit; } + } else if (reg_fetch_contacts("location", "$hdr(X-KAZOO-AOR)", "callee")) { + $du = $(ulc(callee=>received)); + $fs = $(ulc(callee=>socket)); + xlog("L_INFO", "$ci|log|routing $hdr(X-KAZOO-AOR) to $du via $fs\n"); } else { xlog("L_INFO", "$ci|end|user is not registered\n"); - sl_send_reply("404", "Not registered"); + sl_send_reply("410", "Not registered"); exit; } } From 5e0de685973b2073b0403e5a8b2f17f9d829c58d Mon Sep 17 00:00:00 2001 From: lazedo Date: Wed, 27 Jun 2018 12:56:29 +0100 Subject: [PATCH 5/8] set reply route --- kamailio/pusher-role.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/kamailio/pusher-role.cfg b/kamailio/pusher-role.cfg index cb49a73..e9fb626 100644 --- a/kamailio/pusher-role.cfg +++ b/kamailio/pusher-role.cfg @@ -22,6 +22,7 @@ route[PUSHER_ROUTE] if (t_newtran()) { route(SEND_PUSH_NOTIFICATION); remove_hf_re("^X-.*"); + t_on_reply("EXTERNAL_REPLY"); t_save_lumps(); ts_store("$(tu{s.tolower})"); t_suspend(); From da3fafc37dc4ef86c70617582aaec177ddf924ea Mon Sep 17 00:00:00 2001 From: lazedo Date: Wed, 27 Jun 2018 17:16:06 +0100 Subject: [PATCH 6/8] 100 "waking the dead guy" --- kamailio/pusher-role.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kamailio/pusher-role.cfg b/kamailio/pusher-role.cfg index e9fb626..4944365 100644 --- a/kamailio/pusher-role.cfg +++ b/kamailio/pusher-role.cfg @@ -17,7 +17,7 @@ route[PUSHER_ROUTE] } xlog("L_INFO", "$ci|pusher received request to wakeup $(tu{s.tolower})\n"); - sl_send_reply(180, "waking the dead guy"); + sl_send_reply(100, "waking the dead guy"); t_set_fr(0, 20000); if (t_newtran()) { route(SEND_PUSH_NOTIFICATION); From df59cbb3227e75106e99b33bd28960cc1acf9873 Mon Sep 17 00:00:00 2001 From: lazedo Date: Wed, 27 Jun 2018 18:48:40 +0100 Subject: [PATCH 7/8] do not send 100 twice --- kamailio/pusher-role.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kamailio/pusher-role.cfg b/kamailio/pusher-role.cfg index 4944365..8bcef14 100644 --- a/kamailio/pusher-role.cfg +++ b/kamailio/pusher-role.cfg @@ -17,7 +17,7 @@ route[PUSHER_ROUTE] } xlog("L_INFO", "$ci|pusher received request to wakeup $(tu{s.tolower})\n"); - sl_send_reply(100, "waking the dead guy"); + send_reply(100, "waking the dead guy"); t_set_fr(0, 20000); if (t_newtran()) { route(SEND_PUSH_NOTIFICATION); @@ -25,6 +25,7 @@ route[PUSHER_ROUTE] t_on_reply("EXTERNAL_REPLY"); t_save_lumps(); ts_store("$(tu{s.tolower})"); + t_set_auto_inv_100(0); t_suspend(); } else { sl_send_reply(500, "error creating transaction for waking the dead guy"); From e9ba2230819eabee23c64775cf6c8a8fb1ba5a62 Mon Sep 17 00:00:00 2001 From: lazedo Date: Mon, 2 Jul 2018 09:49:54 +0100 Subject: [PATCH 8/8] handle push failover on kamailio --- kamailio/pusher-role.cfg | 145 +++++++++++++++++++++++++++++++-------- 1 file changed, 116 insertions(+), 29 deletions(-) diff --git a/kamailio/pusher-role.cfg b/kamailio/pusher-role.cfg index 8bcef14..b93de7f 100644 --- a/kamailio/pusher-role.cfg +++ b/kamailio/pusher-role.cfg @@ -1,60 +1,147 @@ ## PUSHER ROLE -####### SQL OPS module ########## -#!ifndef TSILO_LOADED -loadmodule "tsilo.so" -modparam("tsilo", "use_domain", 1) -#!trydef TSILO_LOADED -#!endif +######## Generic Hash Table container in shared memory ######## +modparam("htable", "htable", "push_cache=>autoexpire=60;") route[PUSHER_ROUTE] { if ( (!is_method("INVITE")) || (!isflagset(FLAG_INTERNALLY_SOURCED)) || $hdr(X-KAZOO-PUSHER-Token-ID) == $null) return; - if(registered("location") && $hdr(X-KAZOO-PUSHER-Invite-Format) == "invite_only") { - return; + xlog("L_INFO", "$ci|pusher|start deliver call to $hdr(X-KAZOO-PUSHER-Token-ID)\n"); + if(route(PUSHER_PREPARE_PUSH)) { + if(lookup("location", "$hdr(X-KAZOO-AOR)") > 0) { + send_reply(100, "calling a push device"); + route(PUSHER_TO_EXTERNAL_RELAY); + } else { + send_reply(100, "waking the push device"); + route(PUSHER_SEND_PUSH_NOTIFICATION); + } + } + exit(); +} + +route[PUSHER_TO_EXTERNAL_RELAY] +{ + remove_hf_re("^X-.*"); + t_set_fr(0, 2000); + t_relay(); +} + +failure_route[PUSHER_EXTERNAL_FAULT] +{ + xlog("L_INFO", "$ci|pusher|fault reply $T_reply_code\n"); + if (!t_check_status("486|603") && $avp(push_sent) != 1) { + send_reply(182, "waking the dead guy"); + route(PUSHER_SEND_PUSH_NOTIFICATION); + } else { + t_reply("$T_reply_code", "Pusher Failed"); } +} - xlog("L_INFO", "$ci|pusher received request to wakeup $(tu{s.tolower})\n"); - send_reply(100, "waking the dead guy"); - t_set_fr(0, 20000); +route[PUSHER_PREPARE_PUSH] +{ if (t_newtran()) { - route(SEND_PUSH_NOTIFICATION); + t_set_fr(20000, 20000); + route(PUSHER_PREPARE_PUSH_PAYLOAD); remove_hf_re("^X-.*"); t_on_reply("EXTERNAL_REPLY"); + t_on_failure("PUSHER_EXTERNAL_FAULT"); t_save_lumps(); - ts_store("$(tu{s.tolower})"); t_set_auto_inv_100(0); - t_suspend(); - } else { + return 1; + } else { sl_send_reply(500, "error creating transaction for waking the dead guy"); + return 0; } - - if($hdr(X-KAZOO-PUSHER-Invite-Format) == "push_and_invite") { - return; - } - - exit(); } -route[SEND_PUSH_NOTIFICATION] +route[PUSHER_PREPARE_PUSH_PAYLOAD] { + $var(TokenID) = $hdr(X-KAZOO-PUSHER-Token-ID); $var(TokenType) = $hdr(X-KAZOO-PUSHER-Token-Type); $var(TokenApp) = $hdr(X-KAZOO-PUSHER-Token-App); + $var(TokenProxy) = $hdr(X-KAZOO-PUSHER-Token-Proxy); + + ### token for fast reg ### + $var(TokenReg) = $uuid(g); + $sht(push_cache=>$var(TokenReg)) = 1; + + ### caller-id ### $var(rp) = $hdr(Remote-Party-ID); - $var(from) = $(var(rp){tobody.user}) + " - " + $(var(rp){tobody.display}{s.escape.common}); - $var(Payload) = '{ "Event-Category" : "notification", "Event-Name" : "push_req", "Call-ID" : "$ci", "Token-ID" : "$var(TokenID)", "Token-Type" : "$var(TokenType)", "Token-App" : "$var(TokenApp)", "Alert-Body" : "$var(from)" }'; - $var(RoutingKey) = "notification.push." + $var(TokenType) + "." + $var(TokenID); - $var(exchange) = "pushes"; - kazoo_publish($var(exchange), $var(RoutingKey), $var(Payload)); + $var(from_user) = $(var(rp){tobody.user}); + $var(from_name) = $(var(rp){tobody.display}{re.subst,/"//g}); + $var(from) = $_s($var(from_user) - $var(from_name)); + + + $var(PushPayload) = $_s({"call-id" : "$ci", "proxy" : "$var(TokenProxy)", "caller-id-number" : "$var(from_user)", "caller-id-name" : "$var(from_name)", "registration-token" : "$var(TokenReg)"}); + $var(Payload) = $_s({ "Event-Category" : "notification", "Event-Name" : "push_req", "Call-ID" : "$ci", "Token-ID" : "$var(TokenID)", "Token-Type" : "$var(TokenType)", "Token-App" : "$var(TokenApp)", "Alert-Key" : "IC_MSG", "Alert-Params" : ["$var(from)"], "Sound" : "ring.caf", "Payload" : $var(PushPayload) }); + + $avp(push_routing_key) = "notification.push." + $var(TokenType) + "." + $var(TokenID); + $avp(push_payload) = $var(Payload); +} + +route[PUSHER_SEND_PUSH_NOTIFICATION] +{ + xlog("L_INFO", "$ci|pusher|sending push notification request\n"); + xlog("L_DEBUG", "$ci|pusher|pushing to $avp(push_routing_key) : $avp(push_payload)\n"); + t_set_fr(20000, 20000); + $avp(push_sent) = 1; + t_suspend(); + $sht(push_cache=>$(tu{s.tolower})) = $_s(a=0;index=$T(id_index);label=$T(id_label)); + kazoo_publish("pushes", $avp(push_routing_key), $avp(push_payload)); +} + +route[PUSHER_ATTEMPT_REGISTRATION] +{ + if (!is_method("REGISTER")) { + return; + } + + if($hdr(X-Token-Reg) != $null) { + if($sht(push_cache=>$hdr(X-Token-Reg)) != $null) { + $var(password) = $null; + $sht(push_cache=>$hdr(X-Token-Reg)) = $null; + xlog("L_INFO", "$ci|pusher|registration with x-token-reg\n"); + route(SAVE_LOCATION); + } else { + xlog("L_INFO", "$ci|pusher|registration x-token-reg '$hdr(X-Token-Reg)' from header was not found\n"); + } + } + + if($(sel(contact.uri){uri.param,x-token-reg}) != "") { + if($sht(push_cache=>$(sel(contact.uri){uri.param,x-token-reg})) != $null) { + $var(password) = $null; + $sht(push_cache=>$(sel(contact.uri){uri.param,x-token-reg})) = $null; + xlog("L_INFO", "$ci|pusher|registration with x-token-reg\n"); + route(SAVE_LOCATION); + } else { + xlog("L_INFO", "$ci|pusher|registration x-token-reg from contact '$(sel(contact.uri){uri.param,x-token-reg})' was not found\n"); + } + } + } route[PUSHER_ON_REGISTRATION] { if($(xavp(ulattrs=>custom_channel_vars){kz.json,Pusher-Application}{s.len}) > 0 && $var(Status) == "Registered") { - xlog("L_INFO", "$ci| pusher ON_REGISTRATION - $(xavp(ulattrs=>custom_channel_vars){kz.json,Pusher-Application})\n"); - ts_append("location", "$tu"); + if($sht(push_cache=>$(tu{s.tolower})) != $null) { + xlog("L_INFO", "$ci|pusher|device registered, delivering the call\n"); + $var(ref) = $sht(push_cache=>$(tu{s.tolower})); + $sht(push_cache=>$(tu{s.tolower})) = $null; + $var(t_index) = $(var(ref){param.value,index}{s.int}); + $var(t_label) = $(var(ref){param.value,label}{s.int}); + t_continue("$var(t_index)", "$var(t_label)", "PUSHER_DELIVER_CALL"); + } + } +} + +route[PUSHER_DELIVER_CALL] +{ + if(lookup("location", "$hdr(X-KAZOO-AOR)") > 0) { + route(PUSHER_TO_EXTERNAL_RELAY); + } else { + t_reply(486, "Failed to lookup after resume"); } }