From 5758f8c6d367ce503d09d4f9aa077cdaa56216ac Mon Sep 17 00:00:00 2001 From: lazedo Date: Mon, 11 Mar 2019 13:17:31 +0000 Subject: [PATCH] add keepalive --- kamailio/keepalive.cfg | 167 ++++++++++++++++++++++++++++++++ kamailio/nat-traversal-role.cfg | 2 + kamailio/presence-nat.cfg | 136 -------------------------- kamailio/presence-notify.cfg | 2 +- kamailio/presence-role.cfg | 10 +- kamailio/registrar-role.cfg | 41 +++++--- 6 files changed, 198 insertions(+), 160 deletions(-) create mode 100644 kamailio/keepalive.cfg delete mode 100644 kamailio/presence-nat.cfg diff --git a/kamailio/keepalive.cfg b/kamailio/keepalive.cfg new file mode 100644 index 0000000..dfa02b1 --- /dev/null +++ b/kamailio/keepalive.cfg @@ -0,0 +1,167 @@ +######## KEEPALIVE PINGING ######## + +#!trydef KEEPALIVE_NAT_ONLY 0 +#!trydef KEEPALIVE_UDP_ONLY 0 +#!trydef KEEPALIVE_TIMERS 7 +#!trydef KEEPALIVE_INTERVAL 30 +#!trydef KEEPALIVE_TIMEOUT 3500 + +#!substdef "!KEEPALIVE_S_FROM_URI!sip:keepalive@MY_HOSTNAME!g" +#!substdef "!KEEPALIVE_S_TIMERS!$def(KEEPALIVE_TIMERS)!g" + +kazoo.keepalive_udp_only = KEEPALIVE_UDP_ONLY descr "should we send keepalive for udp only" +kazoo.keepalive_nat_only = KEEPALIVE_NAT_ONLY descr "should we send keepalive for nat phones only" + +modparam("rtimer", "timer", "name=keepalive_timer;interval=1;mode=KEEPALIVE_S_TIMERS;") +modparam("rtimer", "exec", "timer=keepalive_timer;route=KEEPALIVE_TIMER") + +modparam("rtimer", "timer", "name=keepalive_db_timer;interval=250000u;mode=1;") +modparam("rtimer", "exec", "timer=keepalive_db_timer;route=KEEPALIVE_DB_TIMER") + +modparam("mqueue","mqueue", "name=keepalive_db_queue") + +route[KEEPALIVE_DB_TIMER] +{ + $var(runloop) = 1; + while(mq_fetch("keepalive_db_queue") == 1 && $var(runloop) < MAX_WHILE_LOOPS) { + $var(ci) = $mqk(keepalive_db_queue); + xlog("L_DEBUG", "Query : $mqv(keepalive_db_queue)\n"); + $var(sqlres) = sql_query("cb", "$mqv(keepalive_db_queue)"); + xlog("L_DEBUG", "Query result : $var(sqlres)\n"); + if($var(sqlres) < 0) { + xlog("L_ERROR", "$var(ci)|log|error running query : $mqv(keepalive_db_queue)\n"); + } else { + $var(nrows) = $sqlrows(cb); + xlog("L_DEBUG", "$var(ci)|log|end UPDATED $var(nrows)\n"); + if($var(nrows) == 0) { + xlog("L_DEBUG", "$var(ci)|log|error no rows affected when running query\n"); + } + } + $var(runloop) = $var(runloop) + 1; + } +} + +route[KEEPALIVE_TIMER] +{ + $var(Query) = $_s(UPDATE keepalive SET selected = 1 WHERE slot = $rtimer_worker AND selected = 0 AND time_sent < datetime('now', '-$def(KEEPALIVE_INTERVAL) seconds')); + $var(sqlres) = sql_query("cb", "$var(Query)"); + if($var(sqlres) < 0) { + xlog("L_ERROR", "$rtimer_worker|log|error running query : $var(Query)\n"); + } else { + $var(nrows) = $sqlrows(cb); + xlog("L_DEBUG", "$rtimer_worker|log|selected $var(nrows) endpoints to ping\n"); + } + + $var(Query) = $_s(SELECT id, contact, sockinfo from keepalive WHERE slot = $rtimer_worker AND selected = 1); + xlog("L_DEBUG", "$rtimer_worker|timer|SQL => $var(Query)\n"); + if (sql_xquery("cb", "$var(Query)", "ra") == 1) + { + while($xavp(ra) != $null) { + $var(loop) = 0; + while($xavp(ra) != $null && $var(loop) < MAX_WHILE_LOOPS) { + route(KEEPALIVE_SEND_PING); + pv_unset("$xavp(ra)"); + $var(loop) = $var(loop) + 1; + } + } + } + + $var(Query) = $_s(UPDATE keepalive SET selected = 2 WHERE slot = $rtimer_worker AND selected = 1); + $var(sqlres) = sql_query("cb", "$var(Query)"); + if($var(sqlres) < 0) { + xlog("L_ERROR", "$rtimer_worker|log|error running query : $var(Query)\n"); + } + +} + +route[KEEPALIVE_SEND_PING] +{ + $var(CallId) = $uuid(g); + xlog("L_DEBUG", "$var(CallId)|$rtimer_worker|timer|SENDING PING FROM $xavp(ra=>local_contact) TO => $xavp(ra=>contact)\n"); + + $uac_req(method)="OPTIONS"; + $uac_req(hdrs) = "X-TM-Local: KEEPALIVE_PING\r\nX-TM-SockInfo: " + $xavp(ra=>sockinfo) + "\r\n"; + $uac_req(turi) = $xavp(ra=>contact); + $uac_req(ruri) = $xavp(ra=>contact); + $uac_req(furi) = $_s(KEEPALIVE_S_FROM_URI;nat_id=$xavp(ra=>id)); + $uac_req(ouri) = "sip:127.0.0.1:5090;transport=tcp"; + $uac_req(callid) = $var(CallId); + uac_req_send(); + +} + +onreply_route[KEEPALIVE_REPLY] +{ + xlog("L_DEBUG", "$ci|keepalive|KEEPALIVE REPLY $(tu{nameaddr.uri})\n"); + $var(Query) = $_s(UPDATE keepalive SET selected = 0, failed = 0, time_sent = datetime('now') WHERE id = $(fu{uri.param,nat_id});); + xlog("L_DEBUG", "$ci|keepalive|KEEPALIVE UPDATE SQL => '$var(Query)'\n"); + mq_add("keepalive_db_queue", "$uuid(g)", "$var(Query)"); + t_drop(); +} + +failure_route[KEEPALIVE_FAULT] +{ + xlog("L_WARNING", "$ci|keepalive|received error $T_reply_code $T_reply_reason from $(tu{nameaddr.uri})\n"); + $var(Query) = $_s(UPDATE keepalive SET selected = 0, failed = failed + 1, time_sent = datetime('now') WHERE id = $(fu{uri.param,nat_id});); + xlog("L_DEBUG", "$ci|keepalive|KEEPALIVE REMOVE SQL => '$var(Query)'\n"); + mq_add("keepalive_db_queue", "$uuid(g)", "$var(Query)"); + t_drop(); +} + +route[KEEPALIVE_PING] +{ + $fs = $hdr(X-TM-SockInfo); + remove_hf_re("^X-TM-SockInfo"); + + force_rport(); + handle_ruri_alias(); + record_route(); + xlog("L_DEBUG", "$ci|local|sending $proto keepalive using $fs to $ru => $du => $tu\n"); + + t_on_reply("KEEPALIVE_REPLY"); + t_on_failure("KEEPALIVE_FAULT"); + t_set_fr(0, KEEPALIVE_TIMEOUT); + + t_relay(); +} + +route[KEEPALIVE_ON_REGISTRATION] +{ + + if($proto == "ws" || $proto == "wss") { + return; + } + + if (isbflagset(FLB_NATB)) { + if(!isbflagset(FLB_NATSIPPING)) { + return; + } + } else { + if($sel(cfg_get.kazoo.keepalive_nat_only) == 1) { + return; + } + } + + $var(alias) = $(avp(AVP_RECV_PARAM){uri.host}) + "~" + $(avp(AVP_RECV_PARAM){uri.port}) + "~" + $prid; + $var(contact) = $(ct{nameaddr.uri}) + ";alias=" + $var(alias); + $var(local_contact) = "sip:" + $Ri + ":" + $Rp + ";transport=" + $proto; + xlog("L_DEBUG", "$ci|keepalive|KEEPALIVE ON REG $var(save_result) $proto $RAut $var(contact) $var(alias) $(ct{nameaddr.uri}) $ct $avp(AVP_RECV_PARAM) $tu $xavp(ulrcd=>ruid) , $xavp(ulrcd=>contact) , $xavp(ulrcd=>expires)\n"); + + $var(slot) = $(var(contact){s.corehash, KEEPALIVE_S_TIMERS}); + $var(sql) = $_s(INSERT OR IGNORE INTO keepalive (contact, sockinfo, slot) values("$var(contact)", "$(RAut{uri.tosocket})", $var(slot))); + mq_add("keepalive_db_queue", "$ci", "$var(sql)"); + + return; +} + +route[KEEPALIVE_ON_SUBSCRIBE] +{ + if(!( ($sel(cfg_get.kazoo.keepalive_udp_only) == 1 && $proto != "udp") + || (!isflagset(FLT_NATS) && $sel(cfg_get.kazoo.keepalive_nat_only) == 1) + || ($proto == "ws" || $proto == "wss") + )) { + $var(slot) = $(subs(contact){s.corehash, KEEPALIVE_S_TIMERS}); + $var(sql) = $_s(INSERT OR IGNORE INTO keepalive (contact, sockinfo, slot) values("$subs(contact)", "$subs(sockinfo)", $var(slot))); + mq_add("keepalive_db_queue", "$ci", "$var(sql)"); + } +} diff --git a/kamailio/nat-traversal-role.cfg b/kamailio/nat-traversal-role.cfg index 6d62690..9d9451f 100644 --- a/kamailio/nat-traversal-role.cfg +++ b/kamailio/nat-traversal-role.cfg @@ -113,4 +113,6 @@ route[NAT_MANAGE] } +#!include_file "keepalive.cfg" + # vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab diff --git a/kamailio/presence-nat.cfg b/kamailio/presence-nat.cfg deleted file mode 100644 index a78ddfd..0000000 --- a/kamailio/presence-nat.cfg +++ /dev/null @@ -1,136 +0,0 @@ -######## Presence NAT ######## - -modparam("htable", "htable", "keepalive=>size=32;autoexpire=3600;initval=0;") - -#!trydef KZ_PRESENCE_KEEPALIVE_UDP_ONLY 0 -#!trydef PRESENCE_NAT_TIMERS 4 -#!trydef PRESENCE_NAT_INTERVAL 30 -#!trydef PRESENCE_NAT_SKIP_REGISTERED 1 -#!trydef PRESENCE_NAT_FROM_URI sip:keepalive@MY_HOSTNAME -#!trydef PRESENCE_NAT_TIMEOUT 3500 - -#!substdef "!PRESENCE_NAT_S_FROM_URI!sip:keepalive@MY_HOSTNAME!g" -#!substdef "!PRESENCE_NAT_S_TIMERS!$def(PRESENCE_NAT_TIMERS)!g" - -kazoo.presence_keepalive_udp_only = KZ_PRESENCE_KEEPALIVE_UDP_ONLY descr "should we keepalive nat phones for udp only" -kazoo.presence_keepalive_skip_registered = PRESENCE_NAT_SKIP_REGISTERED descr "skip if there's a registered contact from same ip/port (avoids multiple pings)" - -modparam("rtimer", "timer", "name=presence_nat_timer;interval=1;mode=PRESENCE_NAT_S_TIMERS;") -modparam("rtimer", "exec", "timer=presence_nat_timer;route=PRESENCE_NAT_TIMER") - -####### Presence Logic ######## - -route[PRESENCE_NAT] -{ - #!ifdef NAT_TRAVERSAL_ROLE - if (isflagset(FLT_NATS)) { - $xavp(regcfg=>match_received) = $su; - if(!( ($sel(cfg_get.kazoo.presence_keepalive_udp_only) == 1 && $proto != "udp") - || ($proto == "ws" || $proto == "wss") -#!ifdef REGISTRAR_ROLE - || ($sel(cfg_get.kazoo.presence_keepalive_skip_registered) == 1 && registered("location", "$rz:$Au", 2, 1) == 1) -#!endif - )) { - $var(slot) = $(subs(contact){s.corehash, PRESENCE_NAT_S_TIMERS}); - $var(sql) = $_s(INSERT OR IGNORE INTO presence_nat (contact, local_contact, slot) values("$subs(contact)", "$subs(local_contact)", $var(slot))); - mq_add("presence_last_notity", "$ci", "$var(sql)"); - } - } - #!endif - - return; -} - - -route[PRESENCE_NAT_TIMER] -{ - $var(Query) = $_s(UPDATE presence_nat SET selected = 1 WHERE slot = $rtimer_worker AND selected = 0 AND time_sent < datetime('now', '-$def(PRESENCE_NAT_INTERVAL) seconds')); - $var(sqlres) = sql_query("cb", "$var(Query)"); - if($var(sqlres) < 0) { - xlog("L_ERROR", "$rtimer_worker|log|error running query : $var(Query)\n"); - } else { - $var(nrows) = $sqlrows(cb); - xlog("L_DEBUG", "$rtimer_worker|log|selected $var(nrows) endpoints to ping\n"); - } - - $var(Query) = $_s(SELECT id, contact, local_contact from presence_nat WHERE slot = $rtimer_worker AND selected = 1); - xlog("L_DEBUG", "$rtimer_worker|timer|SQL => $var(Query)\n"); - if (sql_xquery("cb", "$var(Query)", "ra") == 1) - { - while($xavp(ra) != $null) { - $var(loop) = 0; - while($xavp(ra) != $null && $var(loop) < MAX_WHILE_LOOPS) { - route(PRESENCE_NAT_PING); - pv_unset("$xavp(ra)"); - $var(loop) = $var(loop) + 1; - } - } - } - - $var(Query) = $_s(UPDATE presence_nat SET selected = 2 WHERE slot = $rtimer_worker AND selected = 1); - $var(sqlres) = sql_query("cb", "$var(Query)"); - if($var(sqlres) < 0) { - xlog("L_ERROR", "$rtimer_worker|log|error running query : $var(Query)\n"); - } - -} - -route[PRESENCE_NAT_PING] -{ - $var(CallId) = $uuid(g); - xlog("L_DEBUG", "$var(CallId)|$rtimer_worker|timer|SENDING PING FROM $(xavp(ra=>local_contact){uri.tosocket}) TO => $xavp(ra=>contact)\n"); - - $uac_req(method)="OPTIONS"; - $uac_req(hdrs) = "X-TM-Local: PRESENCE_ROUTE_NAT_PING\r\nX-TM-Contact: " + $xavp(ra=>local_contact) + "\r\n"; - $uac_req(turi) = $xavp(ra=>contact); - $uac_req(ruri) = $xavp(ra=>contact); - $uac_req(furi) = $_s(PRESENCE_NAT_S_FROM_URI;nat_id=$xavp(ra=>id)); - $uac_req(ouri) = "sip:127.0.0.1:5090;transport=tcp"; - $uac_req(callid) = $var(CallId); - uac_req_send(); - -} - -onreply_route[PRESENCE_NAT_REPLY] -{ - xlog("L_DEBUG", "$ci|nat|NAT REPLY $(tu{nameaddr.uri})\n"); - $var(Query) = $_s(UPDATE presence_nat SET selected = 0, time_sent = datetime('now') WHERE id = $(fu{uri.param,nat_id});); - xlog("L_DEBUG", "$ci|nat|NAT UPDATE SQL => '$var(Query)'\n"); - mq_add("presence_last_notity", "$uuid(g)", "$var(Query)"); - t_drop(); -} - -failure_route[PRESENCE_NAT_FAULT] -{ - xlog("L_WARNING", "$ci|nat|received error $T_reply_code $T_reply_reason from $(tu{nameaddr.uri})\n"); - $var(Query) = $_s(DELETE FROM presence_nat WHERE id = $(fu{uri.param,nat_id});); - xlog("L_DEBUG", "$ci|nat|NAT REMOVE SQL => '$var(Query)'\n"); - mq_add("presence_last_notity", "$uuid(g)", "$var(Query)"); - t_drop(); -} - -route[PRESENCE_ROUTE_NAT_PING] -{ - $fs = $(hdr(X-TM-Contact){uri.tosocket}); - remove_hf_re("^X-TM-Contact"); - - force_rport(); - handle_ruri_alias(); - record_route(); - xlog("L_DEBUG", "$ci|local|sending nat keepalive from $fu to $ru => $du => $tu\n"); - - t_on_reply("PRESENCE_NAT_REPLY"); - t_on_failure("PRESENCE_NAT_FAULT"); - t_set_fr(0, PRESENCE_NAT_TIMEOUT); - - t_relay(); -} - -route[PRESENCE_NAT_ON_REGISTRATION] -{ - #!ifdef NAT_TRAVERSAL_ROLE - $var(Query) = $_s(DELETE FROM presence_nat WHERE contact like "$xavp(ulrcd=>contact)%";); - mq_add("presence_last_notity", "$uuid(g)", "$var(Query)"); - #!endif - return; -} diff --git a/kamailio/presence-notify.cfg b/kamailio/presence-notify.cfg index 0b9f46f..cfef4e7 100644 --- a/kamailio/presence-notify.cfg +++ b/kamailio/presence-notify.cfg @@ -1,7 +1,7 @@ #!trydef KZ_PRESENCE_REMOVE_WATCHER_ON_EXPIRED_REGISTRATION 1 kazoo.presence_notify = 1 descr "enable/disable sending notify callback to omnipresence" -kazoo.presence_notify_timeout = 3500 descr "timeout in ms waiting for notify reply" +kazoo.presence_notify_timeout = 5000 descr "timeout in ms waiting for notify reply" kazoo.presence_notify_log_body = 0 descr "logs the body sent in the notification" kazoo.presence_notify_log_resp_body = 0 descr "logs the body received from notification" kazoo.presence_notify_log_to_table = 1 descr "logs notify/reply to active_watchers_log table" diff --git a/kamailio/presence-role.cfg b/kamailio/presence-role.cfg index 83c6a01..8d405fc 100644 --- a/kamailio/presence-role.cfg +++ b/kamailio/presence-role.cfg @@ -65,7 +65,6 @@ kazoo.presence_require_authn = KZ_PRESENCE_REQUIRE_AUTHN descr "require authenti #!include_file "presence-notify.cfg" #!include_file "presence-reset.cfg" #!include_file "presence-fast-pickup.cfg" -#!include_file "presence-nat.cfg" ####### Presence Logic ######## @@ -165,7 +164,9 @@ route[HANDLE_NEW_SUBSCRIBE] route(DELETE_DUPLICATED_SUBSCRIPTIONS); route(SUBSCRIBE_AMQP); route(REQUEST_PROBE); - route(PRESENCE_NAT); + #!ifdef NAT_TRAVERSAL_ROLE + route(KEEPALIVE_ON_SUBSCRIBE); + #!endif } else { xlog("L_INFO", "$ci|stop|error $T_reply_code for new $hdr(Event) subscription from $fU to $tU in realm $fd\n"); } @@ -527,11 +528,6 @@ route[PRESENCE_LOCAL_REQUEST] route(PRESENCE_LOCAL_REQ_NOTIFY); } -route[PRESENCE_ON_REGISTRATION] -{ - route(PRESENCE_NAT_ON_REGISTRATION); -} - route[PRESENCE_AUTHN] { if($sel(cfg_get.kazoo.presence_require_authn) == 1) { diff --git a/kamailio/registrar-role.cfg b/kamailio/registrar-role.cfg index a8b9984..299234a 100644 --- a/kamailio/registrar-role.cfg +++ b/kamailio/registrar-role.cfg @@ -1,6 +1,6 @@ #### NAT PINGING PARAMS ### ## NEXT 2 SHOULD GO TOGETHER -## REGISTRAR_NAT_PING_TIMEOUT should be (REGISTRAR_NAT_PING_INTERVAL + 10) or 0 to disable +## REGISTRAR_NAT_PING_TIMEOUT should be (REGISTRAR_NAT_PING_INTERVAL * 3 + 10) or 0 to disable #!trydef REGISTRAR_NAT_PING_INTERVAL 30 #!trydef REGISTRAR_NAT_PING_TIMEOUT 100 @@ -64,17 +64,6 @@ modparam("usrloc", "fetch_rows", 400) modparam("usrloc", "handle_lost_tcp", REGISTRAR_HANDLE_LOST_TCP) modparam("usrloc", "close_expired_tcp", REGISTRAR_CLOSE_EXPIRED_TCP) -######## NAT Traversal module - signaling functions ######## -#!ifdef NAT_TRAVERSAL_ROLE -#!trydef NATHELPER_LOADED -loadmodule "nathelper.so" -modparam("nathelper", "natping_interval", REGISTRAR_NAT_PING_INTERVAL) -modparam("nathelper", "ping_nated_only", REGISTRAR_NAT_PING_NAT_ONLY) -modparam("nathelper", "natping_processes", REGISTRAR_NAT_PING_WORKERS) -modparam("nathelper", "sipping_bflag", FLB_NATSIPPING) -modparam("nathelper", "keepalive_timeout", REGISTRAR_NAT_PING_TIMEOUT) -#!endif - ####### SIP Registrar implementation module ########## loadmodule "registrar.so" modparam("registrar", "received_avp", "$avp(AVP_RECV_PARAM)") @@ -91,6 +80,24 @@ modparam("registrar", "received_param", "") modparam("registrar", "xavp_rcd", "ulrcd") modparam("registrar", "contact_max_size", REGISTRAR_CONTACT_MAX_SIZE) +####### NAT ########## +#!ifdef NAT_TRAVERSAL_ROLE +#!ifndef NATHELPER_LOADED +loadmodule "nathelper.so" +#!trydef NATHELPER_LOADED +#!endif +#!ifdef KEEPALIVE_USE_NATHELPER +modparam("nathelper", "natping_interval", REGISTRAR_NAT_PING_INTERVAL) +modparam("nathelper", "ping_nated_only", REGISTRAR_NAT_PING_NAT_ONLY) +modparam("nathelper", "natping_processes", REGISTRAR_NAT_PING_WORKERS) +modparam("nathelper", "sipping_bflag", FLB_NATSIPPING) +modparam("nathelper", "keepalive_timeout", REGISTRAR_NAT_PING_TIMEOUT) +#!else +modparam("nathelper", "natping_interval", 0) +modparam("nathelper", "natping_processes", 0) +#!endif +#!endif + ##### registrar realtime params ##### kazoo.registrar_error_min_expires = REGISTRAR_ERROR_MIN_EXPIRES descr "send error when UAS sends expires < min-expires" kazoo.registrar_error_missing_expires = REGISTRAR_ERROR_MISSING_EXPIRES descr "send error when UAS do not send expires header" @@ -107,7 +114,7 @@ kazoo.registrar_send_100 = REGISTRAR_SEND_100 descr "should we send 100 reply wh ####### Registrar Logic ######## -route[REGISTRAR_NAT] +route[REGISTRAR_NAT_FLAGS] { if (isflagset(FLT_NATS)) { xlog("L_DEBUG", "$ci|log|fixing contact for nat request\n"); @@ -275,7 +282,7 @@ route[SAVE_LOCATION] }; $sht(auth_cache=>$Au) = $var(password); - route(REGISTRAR_NAT); + route(REGISTRAR_NAT_FLAGS); $var(save_result) = save("location", "0x04"); if($var(save_result) < 0) { @@ -354,8 +361,10 @@ route[SAVE_LOCATION] route(PUSHER_ON_REGISTRATION); #!endif - #!ifdef PRESENCE_ROLE - route(PRESENCE_ON_REGISTRATION); + #!ifdef NAT_TRAVERSAL_ROLE + #!ifndef KEEPALIVE_USE_NATHELPER + route(KEEPALIVE_ON_REGISTRATION); + #!endif #!endif exit;