|
|
######## 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");
|
|
|
setflag(FLAG_LOCAL_ROUTE);
|
|
|
|
|
|
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;
|
|
|
}
|