The configuration of OpenSER (212.249.15.4) connected to Verizon
Emin Gabrielyan
2007-06-17
The main changes in this version [cfg] are the following:
- The Unix timestamp is included in all log records
- Answer/disconnect records are logged specifically (with Call-ID) for call monitoring
- Non-loose-route ACK and CANCEL requests are relayed if they belong to a transaction and are abandoned otherwise (the OpenSER SIP server now properly closes a cancelled outgoing call-setup transaction upon reception of an ACK from PortaSIP)
- All replies (all means all matched and all unmatched stateless replies) are handled by a separate handler; the Record-Route corrections are carried in this handler (thus replies which are unmatched for some reason are corrected as well and non-matching does not cause serious troubles)
- The call answer and call disconnect events are generated by the handler of all replies (thus if the reply is unmatched the event is not lost)
- The configuration file uses regular expressions for local interface IP addresses so the same file can be used by both redundant servers
1. Setting script variables for received messages
3. Treating CANCEL and ACK requests
3.1. A case when ACK belonging to a transaction is not t_relay() -ed
3.2. The case when transactional ACK is t_relay() -ed
4. The configuration file with comments
The most important improvements are achieved by properly treating the CANCEL and ACK requests (see section 3) and by transforming the Record-Route headers of Verizon’s replies in the stateless reply handler processing absolutely all replies (see section 5). First two sections address only the formatting and the logging aspects of message records (if you are interested in message processing only go directly to section 3).
In route[10] subroutine we prepare several message variables used later for logging the records. These are the $var(peers), $var(hosts), $var(sz), and $var(rr) script variables (the last one is valid only for replies).
route[10]
{
$var(fU)="_empty";
$var(tU)="_empty";
if($fU!="")
$var(fU)=$fU;
if($tU!="")
$var(tU)=$tU;
$var(peers)=$var(fU)+"="+$var(tU);
$var(hosts)=$si+"="+$Ri;
if($cl=="")
$var(sz)="("+$ml+" bytes)";
else if($cl=="0")
$var(sz)="("+$ml+" bytes)";
else
$var(sz)="("+$ml+"-"+$cl+" bytes)";
if($var(msg_type)=="reply")
{
if($(rr{s.len})>12)
$var(rr)=$(rr{s.substr,0,10})+"..";
else
$var(rr)=$rr;
}
}
Variable $var(peers) contains the phone numbers of the calling and called parties. It may look like "+41215501126=+18095498641". Variable $var(hosts) contains the source and destination IP addresses of the message. The destination IP address is one of the interfaces of the OpenSER. The variable may look like "128.179.67.35=212.249.15.4". Variable $var(sz) contains the size of the message and of the message body payload (if any) and may look like "(856-280 bytes)".
Here is an example of a log record for a call setup INVITE request:
+41215501126=+18095498641 Conn. INVITE sip:+18095498641@212.249.15.4:5060 128.179.67.35=212.249.15.4 (856-280 bytes)
For replies $var(rr) contains a truncated reply reason text. This variable may contains a shortened reply-reason text. For example it may look like "Session Pr..".
Belos is an example of a log line for a 183-Session-Progress reply:
+41215501776=+14352154352 ReplSL. 183 (Session Pr..) for INVITE 212.190.89.137=195.129.125.74 (1164-217 bytes)
The subroutine route(10) is called from the main route handler and from two reply route handlers:
route
{
$var(msg_type)="request";
route(10);
...
}
onreply_route[1]
{
$var(msg_type)="reply";
route(10);
...
}
onreply_route
{
$var(msg_type)="reply";
route(10);
...
}
The $var(msg_type) script variable must be set before the subroutine route(10) is called. It tells the subroutine whether it is called for a request message or for a reply message.
Subroutine route(11) is used for printing the log records (usually via syslog service). It is called from main routing block and from two reply handlers. The subroutine route(10) (see section 1) must be called before route(11) which uses the script variables $var(peers), $var(hosts), $var(sz), and $var(rr) in logged records.
route
{
...
}
onreply_route[1]
{
...
$var(comm)="ReplTr.";
route(11);
}
onreply_route
{
...
$var(comm)="ReplSL.";
route(11);
...
}
The script variable $var(comm) passes to route(11) the scope of the message. For replies matched with an on-going transaction $var(comm) is set to ReplTr, for replies which are unmatched for some reason $var(comm) is set to ReplSL (SL stands for stateless).
There are seven other scope types: ErrHops, ErrBig, LooseR, Trans, Aband, Loop, Conn:
ErrHops and ErrBig are used for errors (too many hops and too big). LooseR is used for in-call loose-routed requests (such as ACK of a connected call, re-INVITEs, INFO messages, or BYEs). Trans is used for requests belonging to an ongoing transaction (CANCEL or ACK of a cancelled attempt). Aband is used for non-loose-route ACK and CANCEL requests which do not belong to a transaction (these requests should be abandoned). Loop is used when the request is transmitted by our server to itself (must be abandoned). Finally Conn is used for the first call-setup INVITE.
route[11]
{
switch($var(comm))
{
case "ErrHops.":
case "ErrBig.":
xlog("L_NOTICE","$Ts $var(peers) $var(comm) $rm $ou $var(hosts) $var(sz)\n");
break;
case "LooseR.":
xlog("L_NOTICE","$Ts $var(peers) $var(comm) $rm $var(hosts)\n");
if($rm=="BYE")
xlog("L_NOTICE","$Ts $var(peers) CallBye. $ci $si\n");
break;
case "Trans.":
xlog("L_NOTICE","$Ts $var(peers) $var(comm) $rm $var(hosts) $var(sz)\n");
break;
case "Aband.":
xlog("L_NOTICE","$Ts $var(peers) $var(comm) $rm $var(hosts)\n");
break;
case "Loop.":
xlog("L_NOTICE","$Ts $var(peers) $var(comm) $rm $ou $var(hosts) $var(sz)\n");
break;
case "Conn.":
xlog("L_NOTICE","$Ts $var(peers) $var(comm) $rm $ou $var(hosts) $var(sz)\n");
break;
case "ReplTr.":
xlog("L_NOTICE","$Ts $var(peers) $var(comm) $rs ($var(rr)) for $rm $var(hosts) $var(sz)\n");
break;
case "ReplSL.":
xlog("L_NOTICE","$Ts $var(peers) $var(comm) $rs ($var(rr)) for $rm $var(hosts) $var(sz)\n");
if($rs=="200")
{
switch($rm)
{
case "INVITE":
xlog("L_NOTICE","$Ts $var(peers) CallAnsw. $ci $si\n");
break;
case "BYE":
xlog("L_NOTICE","$Ts $var(peers) CallDisc. $ci $si\n");
break;
}
}
break;
default:
xlog("L_NOTICE","$Ts $var(peers) ScriptErr. $rm $ou $var(hosts) $var(sz)\n");
}
}
When handling 200-OK stateless replies of INVITE and BYE requests, we generate CallAnsw and CallDisc log records needed for call monitoring. All replies are first handled in the ReplSL section. If reply is matched it will be treated additionally also in the ReplTr section. CallBye events (which for call monitoring tool are considered as equivalents of CallDisc event) are logged when BYE requests are transmitted via the LooseR section.
We include in all records the $Ts variable, the Unix time stamp (in seconds). It is especially needed for computing the durations of on-going and finished calls.
A short example of a log file is provided [log].
The CANCEL and ACK requests not belonging to loose-route section are treated specially:
if(method=="CANCEL" || method=="ACK")
{
if($si=~"^212.249.15.[34]$" || $si=~"^195.129.125.7[34]$")
{
$var(comm)="Loop.";
route(11);
}
if(t_check_trans())
{
$var(comm)="Trans.";
route(11);
t_relay();
exit;
}
else
{
$var(comm)="Aband.";
route(11);
exit;
}
}
First we check if the message is originated by ourselves. If yes we log this fact. Then we check if the ACK or CANCEL belongs to an ongoing transaction. Normally all ACKs and CANCELs treated in this section (after the loose-route check is done) must belong to a transaction (except the ACKs sent in response to locally generated 200-OK replies for re-INVITEs).
If ACK or CANCEL belong to an ongoing transaction, we log this fact, we t_relay() the request and we exit the message handling routine. Note that t_relay() does not retransmit such ACK request, but closes the transaction of the cancelled call attempt and OpenSER stops retransmission of the last reply (for example 486-Busy, or 487- Request-Cancelled).
In case ACK and CANCEL are not matched, we abandon them and we stop processing the handling of the current request.
The flowchart below shows a cancelled call attempt from 128.179.67.81 to OpenSER (212.249.15.3, 195.129.125.73). This is an example where OpenSER does not t_relay() the ACK from 128.179.67.81 (which is sent in response to 487 reply). The transaction module of OpenSER does not consider the ACK message (since this event is not parsed by t_relay()) and the OpenSER SIP server keeps transmitting the 487 replies as if ACK is never received:
[png]
On the other hand, since the transaction is not terminated OpenSER matches all 487 replies received from Verizon with the ongoing transaction and sends ACK messages back to Verizon. Verizon has a problem on its own. Their server does not recognize our ACKs and keeps sending us 487 replies (they probably do not t_relay() our ACK).
Since the transaction is not closed and all 487 replies received from Verizon are matched with that transaction that is kept active, we will see all these 487 replies in the transactional reply handler of the initial INVITE request:
openser:~/configs#
2(28611) +41215509999=+41216939262 Init. INVITE sip:+41216939262@212.249.15.3 128.179.67.81=212.249.15.3 (745-236 bytes)
2(28611) +41215509999=+41216939262 ==> OUTGOING CALL to +41216939262
6(28615) +41215509999=+41216939262 100 (trying fast) for INVITE 212.190.89.137=195.129.125.73 (587 bytes)
7(28616) +41215509999=+41216939262 100 (trying -- ..) for INVITE 212.190.89.137=195.129.125.73 (623 bytes)
8(28617) +41215509999=+41216939262 183 (Session Pr..) for INVITE 212.190.89.137=195.129.125.73 (979-217 bytes)
4(28613) +41215509999=+41216939262 Trans. CANCEL 128.179.67.81=212.249.15.3 (433 bytes)
6(28615) +41215509999=+41216939262 200 (canceling) for CANCEL 212.190.89.137=195.129.125.73 (637 bytes)
7(28616) +41215509999=+41216939262 487 (Request Ca..) for INVITE 212.190.89.137=195.129.125.73 (450 bytes)
3(28612) +41215509999=+41216939262 Trans. ACK 128.179.67.81=212.249.15.3 (466 bytes)
4(28613) +41215509999=+41216939262 Trans. CANCEL 128.179.67.81=212.249.15.3 (450 bytes)
5(28614) +41215509999=+41216939262 487 (Request Ca..) for INVITE 212.190.89.137=195.129.125.73 (450 bytes)
8(28617) +41215509999=+41216939262 487 (Request Ca..) for INVITE 212.190.89.137=195.129.125.73 (450 bytes)
6(28615) +41215509999=+41216939262 487 (Request Ca..) for INVITE 212.190.89.137=195.129.125.73 (450 bytes)
8(28617) +41215509999=+41216939262 487 (Request Ca..) for INVITE 212.190.89.137=195.129.125.73 (450 bytes)
5(28614) +41215509999=+41216939262 487 (Request Ca..) for INVITE 212.190.89.137=195.129.125.73 (450 bytes)
8(28617) +41215509999=+41216939262 487 (Request Ca..) for INVITE 212.190.89.137=195.129.125.73 (450 bytes)
5(28614) +41215509999=+41216939262 487 (Request Ca..) for INVITE 212.190.89.137=195.129.125.73 (450 bytes)
8(28617) +41215509999=+41216939262 487 (Request Ca..) for INVITE 212.190.89.137=195.129.125.73 (450 bytes)
openser:~/configs#
[txt]
The printout shows that when ACK of 128.179.67.81 is not t_relay() -ed and the transaction is not closed, we see all nine 487 replies of Verizon. As said, Verizon has an error on its own and sends 487-Request-Cancelled nine times, without understanding our ACK messages (probably they in their turn do not t_relay() our ACKs).
The following flowchart demonstrates the scenario where ACKs of 128.179.67.81 are t_relay() -ed. The OpenSER server does not send 487 replies to 128.179.67.81 as soon as an ACK is received from 128.179.67.81. This scenario corresponds to our current configuration file [cfg].
[png]
The first few 487 replies of Verizon are replied by ACKs, but since the transaction is closed by an ACK of 128.179.67.81, OpenSER does not match the further 487 replies of Verizon with an existing transaction and routes them to 128.179.67.81 according to Via header fields. The six unmatched 487 replies are not seen by the transactional reply handler.
openser:~/configs#
1(28584) INFO:mi_fifo:mi_child_init(1): extra fifo listener processes created
1(28584) +41215509999=+41216939262 Init. INVITE sip:+41216939262@212.249.15.3 128.179.67.81=212.249.15.3 (745-236 bytes)
1(28584) +41215509999=+41216939262 ==> OUTGOING CALL to +41216939262
6(28590) +41215509999=+41216939262 100 (trying -- ..) for INVITE 212.190.89.137=195.129.125.73 (622 bytes)
7(28591) +41215509999=+41216939262 183 (Session Pr..) for INVITE 212.190.89.137=195.129.125.73 (978-216 bytes)
4(28588) +41215509999=+41216939262 Trans. CANCEL 128.179.67.81=212.249.15.3 (433 bytes)
5(28589) +41215509999=+41216939262 200 (canceling) for CANCEL 212.190.89.137=195.129.125.73 (636 bytes)
6(28590) +41215509999=+41216939262 487 (Request Ca..) for INVITE 212.190.89.137=195.129.125.73 (450 bytes)
3(28587) +41215509999=+41216939262 Trans. ACK 128.179.67.81=212.249.15.3 (467 bytes)
4(28588) +41215509999=+41216939262 Trans. CANCEL 128.179.67.81=212.249.15.3 (451 bytes)
8(28592) +41215509999=+41216939262 487 (Request Ca..) for INVITE 212.190.89.137=195.129.125.73 (450 bytes)
6(28590) +41215509999=+41216939262 487 (Request Ca..) for INVITE 212.190.89.137=195.129.125.73 (450 bytes)
openser:~/configs#
[txt]
The printout above shows that when the ACK of 128.179.67.81 is t_relay() -ed, we see only three 487 replies (matched with transaction) of Verizon:
The re-INVITEs are replied locally. If in the loose-route section, the request is INVITE, then we send an 200-OK back to the sender. PortaSIP sends re-INVITEs every 30 seconds and we do not forward them to Verizon. If re-INVITE is not answered PortaSIP will terminate a call.
if(loose_route())
{
$var(comm)="LooseR.";
route(11);
if(method=="INVITE")
{
sl_send_reply("100","Your Re-INVITE is received");
sl_send_reply("200","OK");
exit;
}
t_relay();
exit;
}
Upon the reception of 200-OK PortaSIP sends an ACK (currently PortaSIP has a sort of a bug and ACK is sent only for outgoing calls while the re-INVITEs are generated every 30 second regardless whether the call is incoming or outgoing). Such ACK, sent in response to the 200-OK reply of our OpenSER SIP server, does not belong to an ongoing transaction of PortaSIP. The ACK will be treated as abandoned and will not be processed (which is the right behaviour with respect to such ACKs).
The graph shows the flow of re-INVITEs and the associated 100-Received, 200-OK, and ACK messages:
[png]
Code |
Comments |
debug=3 memlog=2 fork=yes log_stderror=no log_facility=LOG_LOCAL0 log_name="SER" children=4
check_via=no dns=no rev_dns=no
mhomed=1 listen=212.249.15.4 listen=195.129.125.74 port=5060 server_signature=yes sip_warning=1
mpath="/usr/lib/openser/modules/"
loadmodule "sl.so" loadmodule "tm.so" loadmodule "rr.so" loadmodule "maxfwd.so" loadmodule "usrloc.so" loadmodule "registrar.so" loadmodule "textops.so" loadmodule "xlog.so" loadmodule "statistics.so" loadmodule "mi_fifo.so"
#modparam("tm", "fr_timer",120) modparam("usrloc", "db_mode", 0) modparam("rr", "enable_full_lr", 1) modparam("mi_fifo", "fifo_name", "/tmp/openser_fifo")
|
Parameter memlog specifies the memory debug log level.
If server_signature is enabled the "Server" header is generated.
If sip_warning is set to 1 a "Warning" header is added to each reply generated by OpenSER. The header contains several details that help troubleshooting using the network traffic dumps. |
route[10] { $var(fU)="_empty"; $var(tU)="_empty"; if($fU!="") $var(fU)=$fU; if($tU!="") $var(tU)=$tU; $var(peers)=$var(fU)+"="+$var(tU);
$var(hosts)=$si+"="+$Ri;
if($cl=="") $var(sz)="("+$ml+" bytes)"; else if($cl=="0") $var(sz)="("+$ml+" bytes)"; else $var(sz)="("+$ml+"-"+$cl+" bytes)";
if($var(msg_type)=="reply") { if($(rr{s.len})>12) $var(rr)=$(rr{s.substr,0,10})+".."; else $var(rr)=$rr; } }
|
This subroutine prepares several script variables needed for logging the request and reply messages.
$var(peers) contains the phone numbers of calling and called parties.
$var(sz) contains the size of the message and the size of the message body payload if any.
|
route[11] { switch($var(comm)) { case "ErrHops.": case "ErrBig.": xlog("L_NOTICE","$Ts $var(peers) $var(comm) $rm $ou $var(hosts) $var(sz)\n"); break; case "LooseR.": xlog("L_NOTICE","$Ts $var(peers) $var(comm) $rm $var(hosts)\n"); if($rm=="BYE") xlog("L_NOTICE","$Ts $var(peers) CallBye. $ci $si\n"); break; case "Trans.": xlog("L_NOTICE","$Ts $var(peers) $var(comm) $rm $var(hosts) $var(sz)\n"); break; case "Aband.": xlog("L_NOTICE","$Ts $var(peers) $var(comm) $rm $var(hosts)\n"); break; case "Loop.": xlog("L_NOTICE","$Ts $var(peers) $var(comm) $rm $ou $var(hosts) $var(sz)\n"); break; case "Conn.": xlog("L_NOTICE","$Ts $var(peers) $var(comm) $rm $ou $var(hosts) $var(sz)\n"); break; case "ReplTr.": xlog("L_NOTICE","$Ts $var(peers) $var(comm) $rs ($var(rr)) for $rm $var(hosts) $var(sz)\n"); break; case "ReplSL.": xlog("L_NOTICE","$Ts $var(peers) $var(comm) $rs ($var(rr)) for $rm $var(hosts) $var(sz)\n"); if($rs=="200") { switch($rm) { case "INVITE": xlog("L_NOTICE","$Ts $var(peers) CallAnsw. $ci $si\n"); break; case "BYE": xlog("L_NOTICE","$Ts $var(peers) CallDisc. $ci $si\n"); break; } } break; default: xlog("L_NOTICE","$Ts $var(peers) ScriptErr. $rm $ou $var(hosts) $var(sz)\n"); } }
|
This subroutine creates and logs record(s) for the current message.
The previously defined subroutine route(10) should be called before this subroutine.
In case the message is BYE and belongs to LooseR. section, a call STOP event is recorded.
In case of a 200-OK reply for INVITE or for BYE in the ReplSL. section (meaning all replies irrespectively whether the reply is matched to a transaction or not) we log a call START or STOP events correspondingly.
All records include the unix timestamp $Ts.
Call START and STOP records contain also the Call-ID for matching purposes in a call monitor tool. |
route { $var(msg_type)="request"; route(10);
t_on_reply("1");
if(!mf_process_maxfwd_header("10")) { $var(comm)="ErrHops."; route(11); sl_send_reply("483","Too Many Hops"); exit; }
if(msg:len>=2048) { $var(comm)="ErrBig."; route(11); sl_send_reply("513", "Message too big"); exit; }
|
The main routing block.
The parameter $var(msg_type) tells the subroutine route(10) that the message is a request.
Checking for eventual errors.
|
if(loose_route()) { $var(comm)="LooseR."; route(11); if(method=="INVITE") { sl_send_reply("100","Your Re-INVITE is received"); sl_send_reply("200","OK"); exit; } t_relay(); exit; }
|
In-call messages routed according to Route header fields.
Re-INVITEs are captured and are replied locally. |
if(method=="CANCEL" || method=="ACK") { if($si=~"^212.249.15.[34]$" || $si=~"^195.129.125.7[34]$") { $var(comm)="Loop."; route(11); } if(t_check_trans()) { $var(comm)="Trans."; route(11); t_relay(); exit; } else { $var(comm)="Aband."; route(11); exit; } }
|
If we arrive here, then the message is either a new message or it belongs to a transaction.
In case of ACK and CANCEL, the messages are abandoned if they do not belong to an ongoing transaction (e.g. ACK of a re-INVITE replied locally or an erroneous ACK/CANCEL request). |
$var(comm)="Conn."; route(11);
if(method=="INVITE") { record_route(); if($oU=~"^\+412[12]550.{4}$") { if($Ri=~"^195.129.125.7[34]$") { xlog("L_INFO","$Ts $var(peers) ==> INCOMING $oU\n"); subst_uri("/^sip:\+/sip:/i"); rewritehost("128.179.67.35"); } else { xlog("L_INFO","$Ts $var(peers) ==> Unassigned Number $oU\n"); sl_send_reply("404","Unassigned Number"); exit; } } else { if($Ri=~"^195.129.125.7[34]$") { xlog("L_INFO","$Ts $var(peers) ==> Wrong Number $oU\n"); sl_send_reply("406","Not Acceptable: relaying only 021550 or 022550"); exit; } else { xlog("L_INFO","$Ts $var(peers) ==> OUTGOING $oU\n"); append_hf("Remote-Party-ID: <sip:$fU@$fd>;privacy=off;screen=yes\r\n"); if($var(dst)=="1") { rewritehost("62.189.34.7"); $var(dst)="2"; } else { rewritehost("212.190.89.137"); $var(dst)="1"; } } } }
|
If we are here, then the message must be a call setup INVITE.
We record the route (requesting the edges to keep us in the signalling path).
All routing is implemented here. If the number belongs to our blocks 021-550 or 022-550 and the INVITE hits our Verizon side interface (195.129.125.73 or 195.129.125.74) then we are dealing with an incoming call from PSTN and the call must be routed to PortaSIP 128.179.67.35 (our registrar).
If the call is routed to PortaSIP, and no account exists, it should return back to OpenSER server (hitting the server at its public interface 212.249.15.3 or 212.249.15.4). In such case we reply 404-Unassigned-Number, which will propagate back to Swisscom and a message “This is an invalid number” will be played in three languages.
In case of an outgoing call from PortaSIP, we do a load balance across two SIP servers of Verizon. We use variable $var(dst) to switch from one server to another.
We use regular expressions for IP addresses of local interfaces, such that the same configuration file can be used by both redundant servers. |
t_relay(); }
|
Closing the main routing block. |
route[20] { if($hdr(Record-Route[0])!="") $var(rr0)=$hdr(Record-Route[0]); else $var(rr0)="0"; if($hdr(Record-Route[1])!="") $var(rr1)=$hdr(Record-Route[1]); else $var(rr1)="0"; if($hdr(Record-Route[2])!="") $var(rr2)=$hdr(Record-Route[2]); else $var(rr2)="0"; if($hdr(Record-Route[3])!="") $var(rr3)=$hdr(Record-Route[3]); else $var(rr3)="0"; if($hdr(Record-Route[4])!="") $var(rr4)=$hdr(Record-Route[4]); else $var(rr4)="0";
if( $var(rr0)!="0" && $var(rr1)=="0" ) { $var(rr00)=$(var(rr0){s.select,0,,}); $var(rr01)=$(var(rr0){s.select,1,,}); $var(rr02)=$(var(rr0){s.select,2,,}); $var(rr03)=$(var(rr0){s.select,3,,}); $var(rr04)=$(var(rr0){s.select,4,,}); remove_hf("Record-Route"); if($var(rr00)!="") append_hf("Record-Route: $var(rr00)\r\n"); if($var(rr01)!="") append_hf("Record-Route: $var(rr01)\r\n"); if($var(rr02)!="") append_hf("Record-Route: $var(rr02)\r\n"); if($var(rr03)!="") append_hf("Record-Route: $var(rr03)\r\n"); if($var(rr04)!="") append_hf("Record-Route: $var(rr04)\r\n"); } }
|
This is a very important subroutine. PortaSIP does not understand single-lined Record-Route header field, replied by Verizon’s media gateway (despite the fact that this is an RFC 3261 compliant format).
With this subroutine we reformat the replies of Verizon before sending them to PortaSIP.
Without such reformatting the 200-OK and 183-Session-Progress are not understood by PortaSIP.
Since 200-OK is not understood, ACK is not transmitted. As a result Verizon terminates the call within a short time. |
onreply_route[1] { $var(msg_type)="reply"; route(10);
$var(comm)="ReplTr."; route(11); }
|
Since in the main routing block we invoked: t_on_reply("1"), this handler is called for all matched replies. |
onreply_route { $var(msg_type)="reply"; route(10);
$var(comm)="ReplSL."; route(11);
route(20); }
|
Due to an unknown error in OpenSER, the onreply_route[1] handler is not called always. But this one is called for all replies. It is much safer to correct the replies in this handler (with route(20)) than in the previous one. |
The current version [cfg], upgrade notes [ab72], [ab88], [ab92]
- More appropriate name is $var(comm_scope) instead of $var(comm)
- No t_relay() is needed at the end of the main routing block (REGISTERs may need handling)
- Access list can be added and the unauthorized attempts can be logged
- Codec information should be logged with answer records
- This document [doc], [htm]: Transactional ACKs and correcting Recor-Route headers in all replies
- The problem of unmatched replies
- OpenSER memory leak error report
- Unprocessed ACK messages at Verizon
* * *