# Save info for TCP connections for unregister on close/timeout/error
loadmodule "htable.so"
modparam("htable", "htable", "tcpconn=>size=15;autoexpire=7200;")
...
# Handle SIP registrations
route[REGISTRAR] {
...
save("location");
route(TRACK_TCP_STATE);
$var(processed_subscriber) = $fu;
route(TCP_REGISISTER_CLEANUP);
...
}
route[TRACK_TCP_STATE] {
if (proto == UDP) {
return;
}
xlog("[TRACK_TCP_STATE] Saving state for future disconect track of $fu\n");
$sht(tcpconn=>$conid) = $fu;
tcp_enable_closed_event();
}
# Make sure you set up $var(processed_subscriber) before calling this route
route[TCP_REGISISTER_CLEANUP] {
if ($var(processed_subscriber) == $null) {
return;
}
xlog("[TCP_REGISISTER_CLEANUP] Processing subscriber $var(processed_subscriber)\n");
# Getting registered endpoints for this AoR
if (!reg_fetch_contacts("location", "$var(processed_subscriber)", "subscriber")) {
$var(processed_subscriber) = $null;
xlog("[TCP_REGISISTER_CLEANUP] No registered contacts for $var(processed_subscriber)\n");
return;
}
$var(i) = 0;
# Loop through registered endpoints
while ($var(i) < $(ulc(subscriber=>count))) {
$var(stored_subscriber_conid) = $(ulc(subscriber=>conid)[$var(i)]);
# Make sure proto is TCP
if ($var(stored_subscriber_conid) != $null) {
# Check if entry is still active TCP connection. Unregister otherwise.
if ($var(stored_subscriber_conid) == -1 || !tcp_conid_alive("$var(stored_subscriber_conid)")) {
$var(stored_subscriber_ruid) = $(ulc(subscriber=>ruid)[$var(i)]);
$var(stored_subscriber_address) = $(ulc(subscriber=>addr)[$var(i)]);
xlog("[TCP_REGISISTER_CLEANUP]: Unregistering entry $var(i)/$var(stored_subscriber_conid) -> $var(stored_subscriber_address)\n");
if (!unregister("location", "$var(processed_subscriber)", "$var(stored_subscriber_ruid)")) {
xlog("[TCP_REGISISTER_CLEANUP]: Unregistering entry $var(i)/$var(stored_subscriber_conid) -> $var(stored_subscriber_address) FAILED!\n");
}
}
}
$var(i) = $var(i) + 1;
}
$var(processed_subscriber) = $null;
}
event_route[tcp:closed] {
xlog("[TCP:CLOSED] $proto connection closed conid=$conid\n");
$var(processed_subscriber) = $sht(tcpconn=>$conid);
if ($var(processed_subscriber) != $null) {
route(TCP_REGISISTER_CLEANUP);
$sht(tcpconn=>$conid) = $null;
}
}
event_route[tcp:timeout] {
xlog("[TCP:TIMEOUT] $proto connection timeout conid=$conid\n");
$var(processed_subscriber) = $sht(tcpconn=>$conid);
if ($var(processed_subscriber) != $null) {
route(TCP_REGISISTER_CLEANUP);
$sht(tcpconn=>$conid) = $null;
}
}
event_route[tcp:reset] {
xlog("[TCP:RESET] $proto reset closed conid=$conid\n");
$var(processed_subscriber) = $sht(tcpconn=>$conid);
if ($var(processed_subscriber) != $null) {
route(TCP_REGISISTER_CLEANUP);
$sht(tcpconn=>$conid) = $null;
}
}
Simple and efficient solution. Yes, some of "dead" endpoints would be present in table during expiration time, but I'm ok with that.