<div dir="ltr"><div>Folks,</div><div><br></div><div>I'm trying to narrow down a 482 Merged Request problem on calls from one SIP device to another via OpenSIPS 2.4.1. Yealink T41P SIP device (A-party), calls via OpenSIPS, to another AOR owned by a Zoiper5 device (B-party).</div><div>The intent is to ensure that when the B-party rejects the call with a 486 Busy Here, that the response code gets sent through to A-party. However what I'm seeing is the 486 gets sent to OpenSIPS which ACK's it, but doesn't go anywhere from there, and then something causes a second invite to be sent from OpenSIPS to the B-party which then responds of course with 482 Merged Request.</div><div>The call as it is progressing through the call flow seems to be starting a second branch to the AOR (only one SIP device registered using UDP per AOR).</div><div><br></div><div>What would be causing that second call so that I can eliminate it and get to the behaviour I'm expecting. Just using a slightly modified residential default config template with websocket support (the problem was noticed using SIP.JS but exists also in generic SIP device to SIP device calls).</div><div><br></div><div>Image containing sngrep of call: <a href="https://imgur.com/RCZXkO6">https://imgur.com/RCZXkO6</a></div><div><br></div><div>Subscribers are in the form of <username>@<domain><br>With an alias setup for an extension number.</div><div><br></div><div>ie.<br> alfred.anderson@... = 552<br></div><div><div style="font-size:small;text-decoration-style:initial;text-decoration-color:initial"> alice.bell@... = 553</div><br></div><div>excerpt from opensips.cfg<br></div><div><br></div><font face="monospace, monospace"> if ($rU==NULL) {<br> # request with no Username in RURI<br> send_reply("484","Address Incomplete");<br> exit;<br> }<br><br> $acc_extra(src_ip) = $si; # source IP of the request<br> $acc_leg(caller) = $fu;<br> $acc_leg(callee) = $ru;<br><br> # apply DB based aliases<br> if (alias_db_lookup("dbaliases")) {<br> xlog("Alias lookup success [$fu/$tu/$ru/$ci]");<br> }<br> else { <br> xlog("Alias lookup failure [$fu/$tu/$ru/$ci]");<br> }<br><br> # do blind callforward lookup<br> if (avp_db_load("rU", "$avp(callfwd)")) {<br> t_reply("181", "Call Is Being Forwarded");<br> $ru = $avp(callfwd);<br> xlog("forwarded call to: $avp(callfwd)");<br> route(relay);<br> exit;<br> }<br><br> # apply transformations from dialplan table<br> dp_translate("0", "$rU/$rU");<br><br> # check if the call needs to be routed to freeswitch<br> route(freeswitch);<br><br> # here we would set the redirect URI if it had one<br> route(lookup);<br>}<br><br>route[lookup] {<br><span style="font-size:small;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"> script_trace(1, "$rm from $si, rur=$ru", "me");</span><br style="font-size:small;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial"> xlog("route:lookup");<br> # do lookup with method filtering<br> if (!lookup("location","m")) {<br> xlog("lookup failure");<br> t_newtran();<br> if (!db_does_uri_exist()) {<br> xlog("$cfg_line: URI doesn't exist");<br> send_reply("420", "Bad Extension");<br> exit;<br> }<br> t_reply("404", "Not Found");<br> exit;<br> }<br><br> # when routing via usrloc, log the missed calls also<br> do_accounting("db","missed");<br><br> route(relay);<br>}<br><br>route[freeswitch] {<br> xlog("route:freeswitch");<br> if (!is_method("INVITE")) {<br> return;<br> }<br><br> # if the called number begins with the right dialplan redirect it to freeswitch<br> # here we take everythign prefixed with a *, strip it, and send it to freeswitch<br> if ($rU=~"^\*") {<br> strip(1);<br> $du = "sip:<a href="http://10.23.4.192:50600">10.23.4.192:50600</a>";<br> route(relay);<br> }<br>}<br><br><br>route[relay] {<br> xlog("route:relay: Relaying: method=$rm");<br> # for INVITEs enable some additional helper routes<br> if (is_method("INVITE")) {<br> t_on_branch("per_branch_ops");<br> t_on_reply("handle_nat");<br> t_on_failure("missed_call");<br> }<br> else if (is_method("BYE|CANCEL")) {<br> # cancel the rtpengine transcoding<br> rtpengine_delete();<br> }<br><br> if (!t_relay()) {<br> send_reply("500","Internal Error");<br> }<br> exit;<br>}<br><br><br>branch_route[per_branch_ops] {<br> script_trace(1, "$rm from $si, rur=$ru", "me");<br> xlog("[$ci/$T_branch_idx] branch_route:per_branch_ops: new branch at $ru\n");<br><br> # WebSocket specific handling with NORMAL SDP negotiation<br> # assumes SDP offer in the INVITE from the UAC, and SDP<br> # answer is in 200 OK from the UAS<br> if (!is_method("INVITE") || !has_body("application/sdp"))<br> return;<br><br> if (isflagset(SRC_WS) && isbflagset(DST_WS))<br> $var(rtpengine_flags) = "ICE=force-relay DTLS=passive";<br> else if (isflagset(SRC_WS) && !isbflagset(DST_WS))<br> $var(rtpengine_flags) = "RTP/AVP replace-session-connection replace-origin ICE=remove";<br> else if (!isflagset(SRC_WS) && isbflagset(DST_WS))<br> $var(rtpengine_flags) = "UDP/TLS/RTP/SAVPF ICE=force";<br> else if (!isflagset(SRC_WS) && !isbflagset(DST_WS))<br> $var(rtpengine_flags) = "RTP/AVP replace-session-connection replace-origin ICE=remove";<br><br> # only enable transcoding if websocket call for now<br> if (isflagset(SRC_WS) || isbflagset(DST_WS)) {<br> rtpengine_offer("$var(rtpengine_flags)");<br> }<br>}<br><br>onreply_route[handle_nat] {<br> script_trace(1, "$rm from $si, rur=$ru", "me");<br> xlog("[$ci/$T_branch_idx] onreply_route:handle_nat: $ru\n");<br><br> # WebSocket specific handling with NORMAL SDP negotiation<br> # assumes SDP offer in the INVITE from the UAC, and SDP<br> # answer is in 200 OK from the UAS<br> if (!has_body("application/sdp"))<br> return;<br><br> if (isflagset(SRC_WS) && isbflagset(DST_WS))<br> $var(rtpengine_flags) = "ICE=force-relay DTLS=passive";<br> else if (isflagset(SRC_WS) && !isbflagset(DST_WS))<br> $var(rtpengine_flags) = "UDP/TLS/RTP/SAVPF ICE=force";<br> else if (!isflagset(SRC_WS) && isbflagset(DST_WS))<br> $var(rtpengine_flags) = "RTP/AVP replace-session-connection replace-origin ICE=remove";<br> else if (!isflagset(SRC_WS) && !isbflagset(DST_WS))<br> $var(rtpengine_flags) = "RTP/AVP replace-session-connection replace-origin ICE=remove";<br><br> # only enable transcoding if websocket call for now<br> if (isflagset(SRC_WS) || isbflagset(DST_WS)) {<br> rtpengine_answer("$var(rtpengine_flags)");<br> }<br>}<br><br>failure_route[missed_call] {<br> script_trace(1, "$rm from $si, rur=$ru", "me");<br> xlog("[$ci/$T_branch_idx] failure_route:missed_call: incoming failure response to $rm <- $T_reply_code/$T_ruri");<br> if (t_was_cancelled()) {<br> xlog("[$ci/$T_branch_idx] was cancelled");<br> exit;<br> }<br> do_accounting("db", "missed");<br><br> if (!t_relay()) {<br> send_reply("500","Internal Error");<br> }<br> else {<br> xlog("[$ci/$T_branch_idx] Relay success $rm/$T_reply_code");<br> }<br>}</font><div><font face="monospace, monospace"><br></font></div><div><br></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"><br></font></div><br>Cheers,<br> Gerwin<div><div><span style="font-family:monospace"><span>
<br></span><br></span><br></div></div></div>