######## 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"); t_uac_send("OPTIONS", "$xavp(ra=>contact)", "", "$(xavp(ra=>local_contact){uri.tosocket})", "CSeq: 1 OPTIONS\r\nFrom: PRESENCE_NAT_S_FROM_URI\r\nTo: $xavp(ra=>contact);nat_id=$xavp(ra=>id)\r\nContact: <$xavp(ra=>local_contact)>\r\nCall-ID: $var(CallId)\r\n", ""); } 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 = $(tu{uri.param,nat_id});); xlog("L_DEBUG", "$ci|nat|NAT UPDATE SQL => '$var(Query)'\n"); mq_add("presence_last_notity", "$uuid(g)", "$var(Query)"); } 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 = $(tu{uri.param,nat_id});); xlog("L_DEBUG", "$ci|nat|NAT REMOVE SQL => '$var(Query)'\n"); mq_add("presence_last_notity", "$uuid(g)", "$var(Query)"); } route[PRESENCE_LOCAL_REQ_NAT] { #!ifdef NAT_TRAVERSAL_ROLE if($rm == "OPTIONS" && $fu == "PRESENCE_NAT_S_FROM_URI") { t_on_reply("PRESENCE_NAT_REPLY"); t_on_failure("PRESENCE_NAT_FAULT"); t_set_fr(0, PRESENCE_NAT_TIMEOUT); handle_ruri_alias(); record_route(); } #!endif return; } 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; }