Hi,
I've been using SER (0.9.6) as a Proxy doing Loose Routing between 2 endpoints.
If I place a call I can see how the ACK for the 2XX response to the INVITE is properly handled (Route header removed, Record-Route inserted).
Now with the call still up, I do a re-INVITE which is rejected with a 415. The re-INVITE request sent by UAC contained a Route header, as it was an in-dialog request in a record-routed dialog. Now as per RFC3261 section 17.1.1.3:
If the INVITE request whose response is being acknowledged had Route header fields, those header fields MUST appear in the ACK. This is to ensure that the ACK can be routed properly through any downstream stateless proxies.
My UAC complied with the above, but SER seemed to choke on this:
whereas the ACK for 2XX was successfully routed by SER in the original INVITE, the ACK for non-2XX (looking exactly the same: same Request URI, same IP destination, same Route header, ... different Via branch of course) is not handled properly: yes the ACK reaches UAS but it still has the Route header in it, and no Record-Route was added. And I'm guessing that if there had been another proxy in the Route Set on the way to the UAS it would have been bypassed.
SER traces for ACK-2XX:
0(13574) ===> Loose Routing logic... 0(13574) parse_headers: flags=-1 0(13574) DEBUG: t_newtran: msg id=89 , global msg id=88 , T on entrance=0xffffffff 0(13574) parse_headers: flags=-1 0(13574) parse_headers: flags=60 0(13574) t_lookup_request: start searching: hash=41794, isACK=1 0(13574) parse_headers: flags=28 0(13574) DEBUG: t_lookup_request: e2e proxy ACK found 0(13574) parse_headers: flags=4 0(13574) DEBUG: totag for e2e ACK found: 0 0(13574) SER: forwarding ACK statelessly
SER traces for ACK-non-2XX:
0(13574) ===> Loose Routing logic... 0(13574) parse_headers: flags=-1 0(13574) DEBUG: t_newtran: msg id=92 , global msg id=91 , T on entrance=0xffffffff 0(13574) parse_headers: flags=-1 0(13574) parse_headers: flags=60 0(13574) t_lookup_request: start searching: hash=41807, isACK=1 0(13574) DEBUG: RFC3261 transaction matched, tid=007d7195499e33a1 0(13574) DEBUG: t_lookup_request: transaction found (T=0xb616ae48) 0(13574) DEBUG: cleanup_uac_timers: RETR/FR timers reset 0(13574) DEBUG: add_to_tail_of_timer[2]: 0xb616ae90 0(13574) DEBUG:destroy_avp_list: destroying list (nil) 0(13574) receive_msg: cleaning up
This doesn't seem right, am I missing something here?
Thanks,
Emmanuel.
I'm not sure that I understand what you mean is wrong. It would be easier to follow if you include the ACKs. And non-2xxs, what is exactly the exchange? A full SIP trace would help... g-)
Emmanuel Hislen wrote:
Hi,
I've been using SER (0.9.6) as a Proxy doing Loose Routing between 2 endpoints.
If I place a call I can see how the ACK for the 2XX response to the INVITE is properly handled (Route header removed, Record-Route inserted).
Now with the call still up, I do a re-INVITE which is rejected with a 415. The re-INVITE request sent by UAC contained a Route header, as it was an in-dialog request in a record-routed dialog. Now as per RFC3261 section 17.1.1.3:
If the INVITE request whose response is being acknowledged had Route header fields, those header fields MUST appear in the ACK. This is to ensure that the ACK can be routed properly through any downstream stateless proxies.
My UAC complied with the above, but SER seemed to choke on this:
whereas the ACK for 2XX was successfully routed by SER in the original INVITE, the ACK for non-2XX (looking exactly the same: same Request URI, same IP destination, same Route header, ... different Via branch of course) is not handled properly: yes the ACK reaches UAS but it still has the Route header in it, and no Record-Route was added. And I'm guessing that if there had been another proxy in the Route Set on the way to the UAS it would have been bypassed.
SER traces for ACK-2XX:
0(13574) ===> Loose Routing logic... 0(13574) parse_headers: flags=-1 0(13574) DEBUG: t_newtran: msg id=89 , global msg id=88 , T on entrance=0xffffffff 0(13574) parse_headers: flags=-1 0(13574) parse_headers: flags=60 0(13574) t_lookup_request: start searching: hash=41794, isACK=1 0(13574) parse_headers: flags=28 0(13574) DEBUG: t_lookup_request: e2e proxy ACK found 0(13574) parse_headers: flags=4 0(13574) DEBUG: totag for e2e ACK found: 0 0(13574) SER: forwarding ACK statelessly
SER traces for ACK-non-2XX:
0(13574) ===> Loose Routing logic... 0(13574) parse_headers: flags=-1 0(13574) DEBUG: t_newtran: msg id=92 , global msg id=91 , T on entrance=0xffffffff 0(13574) parse_headers: flags=-1 0(13574) parse_headers: flags=60 0(13574) t_lookup_request: start searching: hash=41807, isACK=1 0(13574) DEBUG: RFC3261 transaction matched, tid=007d7195499e33a1 0(13574) DEBUG: t_lookup_request: transaction found (T=0xb616ae48) 0(13574) DEBUG: cleanup_uac_timers: RETR/FR timers reset 0(13574) DEBUG: add_to_tail_of_timer[2]: 0xb616ae90 0(13574) DEBUG:destroy_avp_list: destroying list (nil) 0(13574) receive_msg: cleaning up
This doesn't seem right, am I missing something here?
Thanks,
Emmanuel. _______________________________________________ Serusers mailing list Serusers@lists.iptel.org http://lists.iptel.org/mailman/listinfo/serusers
Hello,
comments inline
On 03/20/2007 09:52 AM, Greger V. Teigre wrote:
I'm not sure that I understand what you mean is wrong. It would be easier to follow if you include the ACKs. And non-2xxs, what is exactly the exchange? A full SIP trace would help... g-)
Emmanuel Hislen wrote:
Hi,
I've been using SER (0.9.6) as a Proxy doing Loose Routing between 2 endpoints.
If I place a call I can see how the ACK for the 2XX response to the INVITE is properly handled (Route header removed, Record-Route inserted).
Now with the call still up, I do a re-INVITE which is rejected with a 415. The re-INVITE request sent by UAC contained a Route header, as it was an in-dialog request in a record-routed dialog. Now as per RFC3261 section 17.1.1.3:
If the INVITE request whose response is being acknowledged had Route header fields, those header fields MUST appear in the ACK. This is to ensure that the ACK can be routed properly through any downstream stateless proxies.
My UAC complied with the above, but SER seemed to choke on this:
whereas the ACK for 2XX was successfully routed by SER in the original INVITE, the ACK for non-2XX (looking exactly the same: same Request URI, same IP destination, same Route header, ... different Via branch of course) is not handled properly: yes the ACK reaches UAS but it still has the Route header in it, and no Record-Route was added. And I'm guessing that if there had been another proxy in the Route Set on the way to the UAS it would have been bypassed.
just to make some definition clear: Route set is the collection of Route headers, the Record-route headers are used only to learn the route-set. So the missing Record-route header does not have any impact of the ACK routing, however could have an impact of routing the BYE for example in your case. But the RFC says that the in-dialog requests do not modify the previously learned route-set:
"12.2 Requests within a Dialog ... Requests within a dialog MAY contain Record-Route and Contact header fields. However, these requests do not cause the dialog's route set to be modified, although they may modify the remote target URI. Specifically, requests that are not target refresh requests do not modify the dialog's remote target URI, and requests that are target refresh requests do. For dialogs that have been established with an INVITE, the only target refresh request defined is re-INVITE (see Section 14). Other extensions may define different target refresh requests for dialogs established in other ways.
Note that an ACK is NOT a target refresh request."
But be careful with modifying the route-set in SER (not with record-routeing but with modifying the route headers directly)! More info: http://tracker.iptel.org/browse/SER-212?page=all
Regards, Miklos
SER traces for ACK-2XX:
0(13574) ===> Loose Routing logic... 0(13574) parse_headers: flags=-1 0(13574) DEBUG: t_newtran: msg id=89 , global msg id=88 , T on entrance=0xffffffff 0(13574) parse_headers: flags=-1 0(13574) parse_headers: flags=60 0(13574) t_lookup_request: start searching: hash=41794, isACK=1 0(13574) parse_headers: flags=28 0(13574) DEBUG: t_lookup_request: e2e proxy ACK found 0(13574) parse_headers: flags=4 0(13574) DEBUG: totag for e2e ACK found: 0 0(13574) SER: forwarding ACK statelessly
SER traces for ACK-non-2XX:
0(13574) ===> Loose Routing logic... 0(13574) parse_headers: flags=-1 0(13574) DEBUG: t_newtran: msg id=92 , global msg id=91 , T on entrance=0xffffffff 0(13574) parse_headers: flags=-1 0(13574) parse_headers: flags=60 0(13574) t_lookup_request: start searching: hash=41807, isACK=1 0(13574) DEBUG: RFC3261 transaction matched, tid=007d7195499e33a1 0(13574) DEBUG: t_lookup_request: transaction found (T=0xb616ae48) 0(13574) DEBUG: cleanup_uac_timers: RETR/FR timers reset 0(13574) DEBUG: add_to_tail_of_timer[2]: 0xb616ae90 0(13574) DEBUG:destroy_avp_list: destroying list (nil) 0(13574) receive_msg: cleaning up
This doesn't seem right, am I missing something here?
Thanks,
Emmanuel. _______________________________________________ Serusers mailing list Serusers@lists.iptel.org http://lists.iptel.org/mailman/listinfo/serusers
Serusers mailing list Serusers@lists.iptel.org http://lists.iptel.org/mailman/listinfo/serusers
Hi,
Agreed on the definition of Route Set, and I have no intention to modify it in-dialog. I'm just worried by the fact that SER doesn't remove the Route header from a request that was record-routed to it before sending it to the next hop.
Here are the SIP messages to illustrate what I mean...
Setup:
UA A ------> SER ------> UA B
A is 192.168.1.236 SER is 192.168.1.77 B is 192.168.1.239
Here is the body of my simple ser.cfg for completeness:
********** # ------------------------- request routing logic -------------------
# main routing logic
route{
# initial sanity checks -- messages with # max_forwards==0, or excessively long requests if (!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many Hops"); break; }; if (msg:len >= 2048 ) { sl_send_reply("513", "Message too big"); break; };
xlog("L_DBG","===> Main Route logic...\n");
# we record-route all messages -- to make sure that # subsequent messages will go through our proxy; that's # particularly good if upstream and downstream entities # use different transport protocol if (!method=="REGISTER") { xlog("L_DBG","===> Doing Record Route...\n"); record_route(); }
# subsequent messages withing a dialog should take the # path determined by record-routing if (loose_route()) { xlog("L_DBG","===> Loose Routing logic...\n"); if ((method=="INVITE" || method=="REFER") && !has_totag()) { sl_send_reply("403", "Forbidden"); break; };
# mark routing logic in request append_hf("P-hint: rr-enforced\r\n"); route(1); break; };
xlog("L_DBG","===> No Loose Routing involved...\n");
if (uri!=myself) { xlog("L_DBG","===> NOT for ME...\n"); # mark routing logic in request append_hf("P-hint: outbound\r\n"); route(1); break; };
if (uri==myself) {
xlog("L_DBG","===> for ME...[method <%rm> r-uri <%ru>]\n");
if (method=="ACK") { route(1); break; } else if (method=="CANCEL") { route(1); break; } else if (method=="INVITE" || method=="OPTIONS") { route(3); break; } else if (method=="REGISTER") { route(2); break; }; };
route(1); }
route[1] { # send it out now; use stateful forwarding as it works reliably # even for UDP2TCP if (!t_relay()) { sl_reply_error(); }; }
route[2] { # ----------------------------------------------------------------- # REGISTER Message Handler # ----------------------------------------------------------------- # we don't expect ANY Register in this setup... sl_send_reply("401", "Unauthorized"); break; }
route[3] { # ----------------------------------------------------------------- # INVITE Message Handler # -----------------------------------------------------------------
if (uri=~"^sip:[0-9]*@") { # PSTN xlog("L_DBG","===> for PSTN...\n");
rewritehost("192.168.1.239"); # PSTN GW avp_write("i:45", "inv_timeout"); route(1); break; } else { xlog("L_DBG","===> NOT for PSTN...\n");
sl_send_reply("404", "User Not Found"); break; } } **********
Now A calls B, call successful. This shows handling of an ACK to a 2XX response.
(I'm removing SDP bodies to keep it short)
INVITE captured on A:
********** 181742.720: SENDING to 192.168.1.77:5060 ----------------------------------------------------------------------------- INVITE sip:85307@192.168.1.77:5060;user=phone SIP/2.0 To: sip:85307@192.168.1.77:5060;user=phone From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 INVITE Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115514019052115 Max-Forwards: 70 Allow: REFER,OPTIONS,BYE,CANCEL,ACK,INVITE Supported: replaces Contact: sip:192.168.1.236:5060 Content-Type: application/sdp Accept: application/sdp Accept-Encoding: Accept-Language: en User-Agent: Foo-Bar Content-Length: 205 **********
INVITE captured on B, has Record-Route from SER:
********** 181747.640: RECEIVED from 192.168.1.77:5060 ----------------------------------------------------------------------------- INVITE sip:85307@192.168.1.239:5060;user=phone SIP/2.0 Record-Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr To: sip:85307@192.168.1.77:5060;user=phone From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 INVITE Via: SIP/2.0/UDP 192.168.1.77;branch=z9hG4bK4014.1299ece.0 Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115514019052115 Max-Forwards: 16 Allow: REFER,OPTIONS,BYE,CANCEL,ACK,INVITE Supported: replaces Contact: sip:192.168.1.236:5060 Content-Type: application/sdp Accept: application/sdp Accept-Encoding: Accept-Language: en User-Agent: Foo-Bar Content-Length: 205 **********
--------------------
200 OK captured on B, has Record-Route:
********** 181749.780: SENDING to 192.168.1.77:5060 ----------------------------------------------------------------------------- SIP/2.0 200 OK Via: SIP/2.0/UDP 192.168.1.77;branch=z9hG4bK4014.1299ece.0 Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115514019052115 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 INVITE Allow: REFER,OPTIONS,BYE,CANCEL,ACK,INVITE Supported: replaces Record-Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr Contact: sip:85307@192.168.1.239:5060;user=phone Accept: application/sdp Accept-Encoding: Accept-Language: en Content-Type: application/sdp Server: Foo-Bar User-Agent: Foo-Bar Content-Length: 204 **********
200 OK captured on A, has Record-Route:
********** 181744.870: RECEIVED from 192.168.1.77:5060 ----------------------------------------------------------------------------- SIP/2.0 200 OK Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115514019052115 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 INVITE Allow: REFER,OPTIONS,BYE,CANCEL,ACK,INVITE Supported: replaces Record-Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr Contact: sip:85307@192.168.1.239:5060;user=phone Accept: application/sdp Accept-Encoding: Accept-Language: en Content-Type: application/sdp Server: Foo-Bar User-Agent: Foo-Bar Content-Length: 204 **********
--------------------
ACK captured on A, has Route header:
********** 181744.880: SENDING to 192.168.1.77:5060 ----------------------------------------------------------------------------- ACK sip:85307@192.168.1.239:5060;user=phone SIP/2.0 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 ACK Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115521825db60f5 Max-Forwards: 70 Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr User-Agent: Foo-Bar Content-Length: 0 **********
ACK captured on B, has NO Route header, has Record-Route header:
********** 181749.800: RECEIVED from 192.168.1.77:5060 ----------------------------------------------------------------------------- ACK sip:85307@192.168.1.239:5060;user=phone SIP/2.0 Record-Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 ACK Via: SIP/2.0/UDP 192.168.1.77;branch=0 Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115521825db60f5 Max-Forwards: 16 User-Agent: Foo-Bar Content-Length: 0 P-hint: rr-enforced **********
-------------------- --------------------
Now A re-INVITEs B, B rejects with 415, this shows handling of an ACK to a non-2XX response.
re-INVITE captured on A, has Route header
********** 181775.580: SENDING to 192.168.1.77:5060 ----------------------------------------------------------------------------- INVITE sip:85307@192.168.1.239:5060;user=phone SIP/2.0 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817362 INVITE Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK01155e16dc5473f3 Max-Forwards: 70 Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr Contact: sip:192.168.1.236:5060 Content-Type: application/sdp Accept: application/sdp Accept-Encoding: Accept-Language: en User-Agent: Foo-Bar Content-Length: 200 **********
re-INVITE captured on B, has NO Route header, has Record-Route header:
********** 181780.500: RECEIVED from 192.168.1.77:5060 ----------------------------------------------------------------------------- INVITE sip:85307@192.168.1.239:5060;user=phone SIP/2.0 Record-Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817362 INVITE Via: SIP/2.0/UDP 192.168.1.77;branch=z9hG4bK1014.fff3b3e5.0 Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK01155e16dc5473f3 Max-Forwards: 16 Contact: sip:192.168.1.236:5060 Content-Type: application/sdp Accept: application/sdp Accept-Encoding: Accept-Language: en User-Agent: Foo-Bar Content-Length: 200 P-hint: rr-enforced **********
--------------------
415 captured on B:
********** 181780.510: SENDING to 192.168.1.77:5060 ----------------------------------------------------------------------------- SIP/2.0 415 Unsupported Media Type Via: SIP/2.0/UDP 192.168.1.77;branch=z9hG4bK1014.fff3b3e5.0 Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK01155e16dc5473f3 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817362 INVITE Accept: application/sdp Accept-Encoding: Accept-Language: en Server: Foo-Bar User-Agent: Foo-Bar Content-Length: 0 **********
415 captured on A:
********** 181775.600: RECEIVED from 192.168.1.77:5060 ----------------------------------------------------------------------------- SIP/2.0 415 Unsupported Media Type Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK01155e16dc5473f3 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817362 INVITE Accept: application/sdp Accept-Encoding: Accept-Language: en Server: Foo-Bar User-Agent: Foo-Bar Content-Length: 0 **********
--------------------
ACK captured on A, has same Route header as re-INVITE as per RFC3261 section 17.1.1.3:
********** 181775.600: SENDING to 192.168.1.77:5060 ----------------------------------------------------------------------------- ACK sip:85307@192.168.1.239:5060;user=phone SIP/2.0 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817362 ACK Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK01155e16dc5473f3 Max-Forwards: 70 Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr User-Agent: Foo-Bar Content-Length: 0 **********
ACK captured on B, still has Route Header !?!?!?!:
********** 181780.510: RECEIVED from 192.168.1.77:5060 ----------------------------------------------------------------------------- ACK sip:85307@192.168.1.239:5060;user=phone SIP/2.0 Via: SIP/2.0/UDP 192.168.1.77;branch=z9hG4bK1014.fff3b3e5.0 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 CSeq: 1817362 ACK Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr User-Agent: Sip EXpress router(0.9.6 (i386/linux)) Content-Length: 0 **********
--------------------
I'm under the impression that SER handles the second ACK as if it was the ACK for a non-2XX response to an initial INVITE (reasonably assuming initial INVITES have usually no Route header). In other words SER assumes that this ACK is not supposed to be Record Routed and therefore does not remove the Route header. Something like that...
Let me know what you think.
Thanks,
Emmanuel.
Miklos Tirpak wrote:
Hello,
comments inline
On 03/20/2007 09:52 AM, Greger V. Teigre wrote:
I'm not sure that I understand what you mean is wrong. It would be easier to follow if you include the ACKs. And non-2xxs, what is exactly the exchange? A full SIP trace would help... g-)
Emmanuel Hislen wrote:
Hi,
I've been using SER (0.9.6) as a Proxy doing Loose Routing between 2 endpoints.
If I place a call I can see how the ACK for the 2XX response to the INVITE is properly handled (Route header removed, Record-Route inserted).
Now with the call still up, I do a re-INVITE which is rejected with a 415. The re-INVITE request sent by UAC contained a Route header, as it was an in-dialog request in a record-routed dialog. Now as per RFC3261 section 17.1.1.3:
If the INVITE request whose response is being acknowledged had Route header fields, those header fields MUST appear in the ACK. This is to ensure that the ACK can be routed properly through any downstream stateless proxies.
My UAC complied with the above, but SER seemed to choke on this:
whereas the ACK for 2XX was successfully routed by SER in the original INVITE, the ACK for non-2XX (looking exactly the same: same Request URI, same IP destination, same Route header, ... different Via branch of course) is not handled properly: yes the ACK reaches UAS but it still has the Route header in it, and no Record-Route was added. And I'm guessing that if there had been another proxy in the Route Set on the way to the UAS it would have been bypassed.
just to make some definition clear: Route set is the collection of Route headers, the Record-route headers are used only to learn the route-set. So the missing Record-route header does not have any impact of the ACK routing, however could have an impact of routing the BYE for example in your case. But the RFC says that the in-dialog requests do not modify the previously learned route-set:
"12.2 Requests within a Dialog ... Requests within a dialog MAY contain Record-Route and Contact header fields. However, these requests do not cause the dialog's route set to be modified, although they may modify the remote target URI. Specifically, requests that are not target refresh requests do not modify the dialog's remote target URI, and requests that are target refresh requests do. For dialogs that have been established with an INVITE, the only target refresh request defined is re-INVITE (see Section 14). Other extensions may define different target refresh requests for dialogs established in other ways.
Note that an ACK is NOT a target refresh request."
But be careful with modifying the route-set in SER (not with record-routeing but with modifying the route headers directly)! More info: http://tracker.iptel.org/browse/SER-212?page=all
Regards, Miklos
SER traces for ACK-2XX:
0(13574) ===> Loose Routing logic... 0(13574) parse_headers: flags=-1 0(13574) DEBUG: t_newtran: msg id=89 , global msg id=88 , T on entrance=0xffffffff 0(13574) parse_headers: flags=-1 0(13574) parse_headers: flags=60 0(13574) t_lookup_request: start searching: hash=41794, isACK=1 0(13574) parse_headers: flags=28 0(13574) DEBUG: t_lookup_request: e2e proxy ACK found 0(13574) parse_headers: flags=4 0(13574) DEBUG: totag for e2e ACK found: 0 0(13574) SER: forwarding ACK statelessly
SER traces for ACK-non-2XX:
0(13574) ===> Loose Routing logic... 0(13574) parse_headers: flags=-1 0(13574) DEBUG: t_newtran: msg id=92 , global msg id=91 , T on entrance=0xffffffff 0(13574) parse_headers: flags=-1 0(13574) parse_headers: flags=60 0(13574) t_lookup_request: start searching: hash=41807, isACK=1 0(13574) DEBUG: RFC3261 transaction matched, tid=007d7195499e33a1 0(13574) DEBUG: t_lookup_request: transaction found (T=0xb616ae48) 0(13574) DEBUG: cleanup_uac_timers: RETR/FR timers reset 0(13574) DEBUG: add_to_tail_of_timer[2]: 0xb616ae90 0(13574) DEBUG:destroy_avp_list: destroying list (nil) 0(13574) receive_msg: cleaning up
This doesn't seem right, am I missing something here?
Thanks,
Emmanuel. _______________________________________________ Serusers mailing list Serusers@lists.iptel.org http://lists.iptel.org/mailman/listinfo/serusers
Serusers mailing list Serusers@lists.iptel.org http://lists.iptel.org/mailman/listinfo/serusers
ok, I agree, this is a bug. I tried to explain it in the description of SER-212, but probably it is not enough detailed.
The problem is basically that loose_route() removes the route HF from the INVITE, so the locally generated ACK for non-2xx final response (and local CANCEL as well!) should remove the same route HF. But tm module does not know that the route HF was removed when it builds the ACK, because it is working with the incoming INVITE message buffer instead of the outgoing one.
We have changed SER-212 in the bug tracker from "bug" to "wishlist", because folks claimed that nobody reported this problem, so the patch is not urgent. Until now!!! You are the one who has reported it :)
Anyway, Andrei said that there may be a better way to implement the same which does not require message parsing, so this is the reason why the patch is in on-hold state. If you problem is urgent, use the patch, or vote for changing it back from "wishlist" to "bug".
Regards, Miklos
On 03/22/2007 12:50 AM, Emmanuel Hislen wrote:
Hi,
Agreed on the definition of Route Set, and I have no intention to modify it in-dialog. I'm just worried by the fact that SER doesn't remove the Route header from a request that was record-routed to it before sending it to the next hop.
Here are the SIP messages to illustrate what I mean...
Setup:
UA A ------> SER ------> UA B
A is 192.168.1.236 SER is 192.168.1.77 B is 192.168.1.239
Here is the body of my simple ser.cfg for completeness:
# ------------------------- request routing logic -------------------
# main routing logic
route{
# initial sanity checks -- messages with # max_forwards==0, or excessively long requests if (!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many Hops"); break; }; if (msg:len >= 2048 ) { sl_send_reply("513", "Message too big"); break; }; xlog("L_DBG","===> Main Route logic...\n"); # we record-route all messages -- to make sure that # subsequent messages will go through our proxy; that's # particularly good if upstream and downstream entities # use different transport protocol if (!method=="REGISTER") { xlog("L_DBG","===> Doing Record Route...\n"); record_route(); } # subsequent messages withing a dialog should take the # path determined by record-routing if (loose_route()) { xlog("L_DBG","===> Loose Routing logic...\n"); if ((method=="INVITE" || method=="REFER") &&
!has_totag()) { sl_send_reply("403", "Forbidden"); break; };
# mark routing logic in request append_hf("P-hint: rr-enforced\r\n"); route(1); break; }; xlog("L_DBG","===> No Loose Routing involved...\n"); if (uri!=myself) { xlog("L_DBG","===> NOT for ME...\n"); # mark routing logic in request append_hf("P-hint: outbound\r\n"); route(1); break; }; if (uri==myself) { xlog("L_DBG","===> for ME...[method <%rm> r-uri <%ru>]\n"); if (method=="ACK") { route(1); break; } else if (method=="CANCEL") { route(1); break; } else if (method=="INVITE" || method=="OPTIONS") { route(3); break; } else if (method=="REGISTER") { route(2); break; }; }; route(1);
}
route[1] { # send it out now; use stateful forwarding as it works reliably # even for UDP2TCP if (!t_relay()) { sl_reply_error(); }; }
route[2] { # ----------------------------------------------------------------- # REGISTER Message Handler # ----------------------------------------------------------------- # we don't expect ANY Register in this setup... sl_send_reply("401", "Unauthorized"); break; }
route[3] { # ----------------------------------------------------------------- # INVITE Message Handler # -----------------------------------------------------------------
if (uri=~"^sip:[0-9]*@") { # PSTN xlog("L_DBG","===> for PSTN...\n"); rewritehost("192.168.1.239"); # PSTN GW avp_write("i:45", "inv_timeout"); route(1); break; } else { xlog("L_DBG","===> NOT for PSTN...\n"); sl_send_reply("404", "User Not Found"); break; }
}
Now A calls B, call successful. This shows handling of an ACK to a 2XX response.
(I'm removing SDP bodies to keep it short)
INVITE captured on A:
181742.720: SENDING to 192.168.1.77:5060
INVITE sip:85307@192.168.1.77:5060;user=phone SIP/2.0 To: sip:85307@192.168.1.77:5060;user=phone From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 INVITE Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115514019052115 Max-Forwards: 70 Allow: REFER,OPTIONS,BYE,CANCEL,ACK,INVITE Supported: replaces Contact: sip:192.168.1.236:5060 Content-Type: application/sdp Accept: application/sdp Accept-Encoding: Accept-Language: en User-Agent: Foo-Bar Content-Length: 205
INVITE captured on B, has Record-Route from SER:
181747.640: RECEIVED from 192.168.1.77:5060
INVITE sip:85307@192.168.1.239:5060;user=phone SIP/2.0 Record-Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr To: sip:85307@192.168.1.77:5060;user=phone From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 INVITE Via: SIP/2.0/UDP 192.168.1.77;branch=z9hG4bK4014.1299ece.0 Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115514019052115 Max-Forwards: 16 Allow: REFER,OPTIONS,BYE,CANCEL,ACK,INVITE Supported: replaces Contact: sip:192.168.1.236:5060 Content-Type: application/sdp Accept: application/sdp Accept-Encoding: Accept-Language: en User-Agent: Foo-Bar Content-Length: 205
200 OK captured on B, has Record-Route:
181749.780: SENDING to 192.168.1.77:5060
SIP/2.0 200 OK Via: SIP/2.0/UDP 192.168.1.77;branch=z9hG4bK4014.1299ece.0 Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115514019052115 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 INVITE Allow: REFER,OPTIONS,BYE,CANCEL,ACK,INVITE Supported: replaces Record-Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr Contact: sip:85307@192.168.1.239:5060;user=phone Accept: application/sdp Accept-Encoding: Accept-Language: en Content-Type: application/sdp Server: Foo-Bar User-Agent: Foo-Bar Content-Length: 204
200 OK captured on A, has Record-Route:
181744.870: RECEIVED from 192.168.1.77:5060
SIP/2.0 200 OK Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115514019052115 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 INVITE Allow: REFER,OPTIONS,BYE,CANCEL,ACK,INVITE Supported: replaces Record-Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr Contact: sip:85307@192.168.1.239:5060;user=phone Accept: application/sdp Accept-Encoding: Accept-Language: en Content-Type: application/sdp Server: Foo-Bar User-Agent: Foo-Bar Content-Length: 204
ACK captured on A, has Route header:
181744.880: SENDING to 192.168.1.77:5060
ACK sip:85307@192.168.1.239:5060;user=phone SIP/2.0 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 ACK Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115521825db60f5 Max-Forwards: 70 Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr User-Agent: Foo-Bar Content-Length: 0
ACK captured on B, has NO Route header, has Record-Route header:
181749.800: RECEIVED from 192.168.1.77:5060
ACK sip:85307@192.168.1.239:5060;user=phone SIP/2.0 Record-Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 ACK Via: SIP/2.0/UDP 192.168.1.77;branch=0 Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115521825db60f5 Max-Forwards: 16 User-Agent: Foo-Bar Content-Length: 0 P-hint: rr-enforced
Now A re-INVITEs B, B rejects with 415, this shows handling of an ACK to a non-2XX response.
re-INVITE captured on A, has Route header
181775.580: SENDING to 192.168.1.77:5060
INVITE sip:85307@192.168.1.239:5060;user=phone SIP/2.0 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817362 INVITE Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK01155e16dc5473f3 Max-Forwards: 70 Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr Contact: sip:192.168.1.236:5060 Content-Type: application/sdp Accept: application/sdp Accept-Encoding: Accept-Language: en User-Agent: Foo-Bar Content-Length: 200
re-INVITE captured on B, has NO Route header, has Record-Route header:
181780.500: RECEIVED from 192.168.1.77:5060
INVITE sip:85307@192.168.1.239:5060;user=phone SIP/2.0 Record-Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817362 INVITE Via: SIP/2.0/UDP 192.168.1.77;branch=z9hG4bK1014.fff3b3e5.0 Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK01155e16dc5473f3 Max-Forwards: 16 Contact: sip:192.168.1.236:5060 Content-Type: application/sdp Accept: application/sdp Accept-Encoding: Accept-Language: en User-Agent: Foo-Bar Content-Length: 200 P-hint: rr-enforced
415 captured on B:
181780.510: SENDING to 192.168.1.77:5060
SIP/2.0 415 Unsupported Media Type Via: SIP/2.0/UDP 192.168.1.77;branch=z9hG4bK1014.fff3b3e5.0 Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK01155e16dc5473f3 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817362 INVITE Accept: application/sdp Accept-Encoding: Accept-Language: en Server: Foo-Bar User-Agent: Foo-Bar Content-Length: 0
415 captured on A:
181775.600: RECEIVED from 192.168.1.77:5060
SIP/2.0 415 Unsupported Media Type Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK01155e16dc5473f3 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817362 INVITE Accept: application/sdp Accept-Encoding: Accept-Language: en Server: Foo-Bar User-Agent: Foo-Bar Content-Length: 0
ACK captured on A, has same Route header as re-INVITE as per RFC3261 section 17.1.1.3:
181775.600: SENDING to 192.168.1.77:5060
ACK sip:85307@192.168.1.239:5060;user=phone SIP/2.0 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817362 ACK Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK01155e16dc5473f3 Max-Forwards: 70 Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr User-Agent: Foo-Bar Content-Length: 0
ACK captured on B, still has Route Header !?!?!?!:
181780.510: RECEIVED from 192.168.1.77:5060
ACK sip:85307@192.168.1.239:5060;user=phone SIP/2.0 Via: SIP/2.0/UDP 192.168.1.77;branch=z9hG4bK1014.fff3b3e5.0 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 CSeq: 1817362 ACK Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr User-Agent: Sip EXpress router(0.9.6 (i386/linux)) Content-Length: 0
I'm under the impression that SER handles the second ACK as if it was the ACK for a non-2XX response to an initial INVITE (reasonably assuming initial INVITES have usually no Route header). In other words SER assumes that this ACK is not supposed to be Record Routed and therefore does not remove the Route header. Something like that...
Let me know what you think.
Thanks,
Emmanuel.
Miklos Tirpak wrote:
Hello,
comments inline
On 03/20/2007 09:52 AM, Greger V. Teigre wrote:
I'm not sure that I understand what you mean is wrong. It would be easier to follow if you include the ACKs. And non-2xxs, what is exactly the exchange? A full SIP trace would help... g-)
Emmanuel Hislen wrote:
Hi,
I've been using SER (0.9.6) as a Proxy doing Loose Routing between 2 endpoints.
If I place a call I can see how the ACK for the 2XX response to the INVITE is properly handled (Route header removed, Record-Route inserted).
Now with the call still up, I do a re-INVITE which is rejected with a 415. The re-INVITE request sent by UAC contained a Route header, as it was an in-dialog request in a record-routed dialog. Now as per RFC3261 section 17.1.1.3:
If the INVITE request whose response is being acknowledged had Route header fields, those header fields MUST appear in the ACK. This is to ensure that the ACK can be routed properly through any downstream stateless proxies.
My UAC complied with the above, but SER seemed to choke on this:
whereas the ACK for 2XX was successfully routed by SER in the original INVITE, the ACK for non-2XX (looking exactly the same: same Request URI, same IP destination, same Route header, ... different Via branch of course) is not handled properly: yes the ACK reaches UAS but it still has the Route header in it, and no Record-Route was added. And I'm guessing that if there had been another proxy in the Route Set on the way to the UAS it would have been bypassed.
just to make some definition clear: Route set is the collection of Route headers, the Record-route headers are used only to learn the route-set. So the missing Record-route header does not have any impact of the ACK routing, however could have an impact of routing the BYE for example in your case. But the RFC says that the in-dialog requests do not modify the previously learned route-set:
"12.2 Requests within a Dialog ... Requests within a dialog MAY contain Record-Route and Contact header fields. However, these requests do not cause the dialog's route set to be modified, although they may modify the remote target URI. Specifically, requests that are not target refresh requests do not modify the dialog's remote target URI, and requests that are target refresh requests do. For dialogs that have been established with an INVITE, the only target refresh request defined is re-INVITE (see Section 14). Other extensions may define different target refresh requests for dialogs established in other ways.
Note that an ACK is NOT a target refresh request."
But be careful with modifying the route-set in SER (not with record-routeing but with modifying the route headers directly)! More info: http://tracker.iptel.org/browse/SER-212?page=all
Regards, Miklos
SER traces for ACK-2XX:
0(13574) ===> Loose Routing logic... 0(13574) parse_headers: flags=-1 0(13574) DEBUG: t_newtran: msg id=89 , global msg id=88 , T on entrance=0xffffffff 0(13574) parse_headers: flags=-1 0(13574) parse_headers: flags=60 0(13574) t_lookup_request: start searching: hash=41794, isACK=1 0(13574) parse_headers: flags=28 0(13574) DEBUG: t_lookup_request: e2e proxy ACK found 0(13574) parse_headers: flags=4 0(13574) DEBUG: totag for e2e ACK found: 0 0(13574) SER: forwarding ACK statelessly
SER traces for ACK-non-2XX:
0(13574) ===> Loose Routing logic... 0(13574) parse_headers: flags=-1 0(13574) DEBUG: t_newtran: msg id=92 , global msg id=91 , T on entrance=0xffffffff 0(13574) parse_headers: flags=-1 0(13574) parse_headers: flags=60 0(13574) t_lookup_request: start searching: hash=41807, isACK=1 0(13574) DEBUG: RFC3261 transaction matched, tid=007d7195499e33a1 0(13574) DEBUG: t_lookup_request: transaction found (T=0xb616ae48) 0(13574) DEBUG: cleanup_uac_timers: RETR/FR timers reset 0(13574) DEBUG: add_to_tail_of_timer[2]: 0xb616ae90 0(13574) DEBUG:destroy_avp_list: destroying list (nil) 0(13574) receive_msg: cleaning up
This doesn't seem right, am I missing something here?
Thanks,
Emmanuel. _______________________________________________ Serusers mailing list Serusers@lists.iptel.org http://lists.iptel.org/mailman/listinfo/serusers
Serusers mailing list Serusers@lists.iptel.org http://lists.iptel.org/mailman/listinfo/serusers
OK thanks!
No this is not urgent, I mostly wanted to know if I was missing something or not since I'm rather new to Record Routing. I just found by chance the other day that my ACK (from A) was misssing the Route header in this scenario, so I added it and I was just looking for a way to test my change. I don't expect this scenario to be used too often either.
I might give the patch a try though.
Regards,
Emmanuel.
Miklos Tirpak wrote:
ok, I agree, this is a bug. I tried to explain it in the description of SER-212, but probably it is not enough detailed.
The problem is basically that loose_route() removes the route HF from the INVITE, so the locally generated ACK for non-2xx final response (and local CANCEL as well!) should remove the same route HF. But tm module does not know that the route HF was removed when it builds the ACK, because it is working with the incoming INVITE message buffer instead of the outgoing one.
We have changed SER-212 in the bug tracker from "bug" to "wishlist", because folks claimed that nobody reported this problem, so the patch is not urgent. Until now!!! You are the one who has reported it :)
Anyway, Andrei said that there may be a better way to implement the same which does not require message parsing, so this is the reason why the patch is in on-hold state. If you problem is urgent, use the patch, or vote for changing it back from "wishlist" to "bug".
Regards, Miklos
On 03/22/2007 12:50 AM, Emmanuel Hislen wrote:
Hi,
Agreed on the definition of Route Set, and I have no intention to modify it in-dialog. I'm just worried by the fact that SER doesn't remove the Route header from a request that was record-routed to it before sending it to the next hop.
Here are the SIP messages to illustrate what I mean...
Setup:
UA A ------> SER ------> UA B
A is 192.168.1.236 SER is 192.168.1.77 B is 192.168.1.239
Here is the body of my simple ser.cfg for completeness:
# ------------------------- request routing logic -------------------
# main routing logic
route{
# initial sanity checks -- messages with # max_forwards==0, or excessively long requests if (!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many Hops"); break; }; if (msg:len >= 2048 ) { sl_send_reply("513", "Message too big"); break; }; xlog("L_DBG","===> Main Route logic...\n"); # we record-route all messages -- to make sure that # subsequent messages will go through our proxy; that's # particularly good if upstream and downstream entities # use different transport protocol if (!method=="REGISTER") { xlog("L_DBG","===> Doing Record Route...\n"); record_route(); } # subsequent messages withing a dialog should take the # path determined by record-routing if (loose_route()) { xlog("L_DBG","===> Loose Routing logic...\n"); if ((method=="INVITE" || method=="REFER") &&
!has_totag()) { sl_send_reply("403", "Forbidden"); break; };
# mark routing logic in request append_hf("P-hint: rr-enforced\r\n"); route(1); break; }; xlog("L_DBG","===> No Loose Routing involved...\n"); if (uri!=myself) { xlog("L_DBG","===> NOT for ME...\n"); # mark routing logic in request append_hf("P-hint: outbound\r\n"); route(1); break; }; if (uri==myself) { xlog("L_DBG","===> for ME...[method <%rm> r-uri
<%ru>]\n");
if (method=="ACK") { route(1); break; } else if (method=="CANCEL") { route(1); break; } else if (method=="INVITE" || method=="OPTIONS") { route(3); break; } else if (method=="REGISTER") { route(2); break; }; }; route(1);
}
route[1] { # send it out now; use stateful forwarding as it works reliably # even for UDP2TCP if (!t_relay()) { sl_reply_error(); }; }
route[2] { #
# REGISTER Message Handler #
# we don't expect ANY Register in this setup... sl_send_reply("401", "Unauthorized"); break;
}
route[3] { #
# INVITE Message Handler #
if (uri=~"^sip:[0-9]*@") { # PSTN xlog("L_DBG","===> for PSTN...\n"); rewritehost("192.168.1.239"); # PSTN GW avp_write("i:45", "inv_timeout"); route(1); break; } else { xlog("L_DBG","===> NOT for PSTN...\n"); sl_send_reply("404", "User Not Found"); break; }
}
Now A calls B, call successful. This shows handling of an ACK to a 2XX response.
(I'm removing SDP bodies to keep it short)
INVITE captured on A:
181742.720: SENDING to 192.168.1.77:5060
INVITE sip:85307@192.168.1.77:5060;user=phone SIP/2.0 To: sip:85307@192.168.1.77:5060;user=phone From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 INVITE Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115514019052115 Max-Forwards: 70 Allow: REFER,OPTIONS,BYE,CANCEL,ACK,INVITE Supported: replaces Contact: sip:192.168.1.236:5060 Content-Type: application/sdp Accept: application/sdp Accept-Encoding: Accept-Language: en User-Agent: Foo-Bar Content-Length: 205
INVITE captured on B, has Record-Route from SER:
181747.640: RECEIVED from 192.168.1.77:5060
INVITE sip:85307@192.168.1.239:5060;user=phone SIP/2.0 Record-Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr To: sip:85307@192.168.1.77:5060;user=phone From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 INVITE Via: SIP/2.0/UDP 192.168.1.77;branch=z9hG4bK4014.1299ece.0 Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115514019052115 Max-Forwards: 16 Allow: REFER,OPTIONS,BYE,CANCEL,ACK,INVITE Supported: replaces Contact: sip:192.168.1.236:5060 Content-Type: application/sdp Accept: application/sdp Accept-Encoding: Accept-Language: en User-Agent: Foo-Bar Content-Length: 205
200 OK captured on B, has Record-Route:
181749.780: SENDING to 192.168.1.77:5060
SIP/2.0 200 OK Via: SIP/2.0/UDP 192.168.1.77;branch=z9hG4bK4014.1299ece.0 Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115514019052115 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 INVITE Allow: REFER,OPTIONS,BYE,CANCEL,ACK,INVITE Supported: replaces Record-Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr Contact: sip:85307@192.168.1.239:5060;user=phone Accept: application/sdp Accept-Encoding: Accept-Language: en Content-Type: application/sdp Server: Foo-Bar User-Agent: Foo-Bar Content-Length: 204
200 OK captured on A, has Record-Route:
181744.870: RECEIVED from 192.168.1.77:5060
SIP/2.0 200 OK Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115514019052115 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 INVITE Allow: REFER,OPTIONS,BYE,CANCEL,ACK,INVITE Supported: replaces Record-Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr Contact: sip:85307@192.168.1.239:5060;user=phone Accept: application/sdp Accept-Encoding: Accept-Language: en Content-Type: application/sdp Server: Foo-Bar User-Agent: Foo-Bar Content-Length: 204
ACK captured on A, has Route header:
181744.880: SENDING to 192.168.1.77:5060
ACK sip:85307@192.168.1.239:5060;user=phone SIP/2.0 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 ACK Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115521825db60f5 Max-Forwards: 70 Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr User-Agent: Foo-Bar Content-Length: 0
ACK captured on B, has NO Route header, has Record-Route header:
181749.800: RECEIVED from 192.168.1.77:5060
ACK sip:85307@192.168.1.239:5060;user=phone SIP/2.0 Record-Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817361 ACK Via: SIP/2.0/UDP 192.168.1.77;branch=0 Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK0115521825db60f5 Max-Forwards: 16 User-Agent: Foo-Bar Content-Length: 0 P-hint: rr-enforced
Now A re-INVITEs B, B rejects with 415, this shows handling of an ACK to a non-2XX response.
re-INVITE captured on A, has Route header
181775.580: SENDING to 192.168.1.77:5060
INVITE sip:85307@192.168.1.239:5060;user=phone SIP/2.0 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817362 INVITE Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK01155e16dc5473f3 Max-Forwards: 70 Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr Contact: sip:192.168.1.236:5060 Content-Type: application/sdp Accept: application/sdp Accept-Encoding: Accept-Language: en User-Agent: Foo-Bar Content-Length: 200
re-INVITE captured on B, has NO Route header, has Record-Route header:
181780.500: RECEIVED from 192.168.1.77:5060
INVITE sip:85307@192.168.1.239:5060;user=phone SIP/2.0 Record-Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817362 INVITE Via: SIP/2.0/UDP 192.168.1.77;branch=z9hG4bK1014.fff3b3e5.0 Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK01155e16dc5473f3 Max-Forwards: 16 Contact: sip:192.168.1.236:5060 Content-Type: application/sdp Accept: application/sdp Accept-Encoding: Accept-Language: en User-Agent: Foo-Bar Content-Length: 200 P-hint: rr-enforced
415 captured on B:
181780.510: SENDING to 192.168.1.77:5060
SIP/2.0 415 Unsupported Media Type Via: SIP/2.0/UDP 192.168.1.77;branch=z9hG4bK1014.fff3b3e5.0 Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK01155e16dc5473f3 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817362 INVITE Accept: application/sdp Accept-Encoding: Accept-Language: en Server: Foo-Bar User-Agent: Foo-Bar Content-Length: 0
415 captured on A:
181775.600: RECEIVED from 192.168.1.77:5060
SIP/2.0 415 Unsupported Media Type Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK01155e16dc5473f3 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817362 INVITE Accept: application/sdp Accept-Encoding: Accept-Language: en Server: Foo-Bar User-Agent: Foo-Bar Content-Length: 0
ACK captured on A, has same Route header as re-INVITE as per RFC3261 section 17.1.1.3:
181775.600: SENDING to 192.168.1.77:5060
ACK sip:85307@192.168.1.239:5060;user=phone SIP/2.0 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 CSeq: 1817362 ACK Via: SIP/2.0/UDP 192.168.1.236:5060;branch=z9hG4bK01155e16dc5473f3 Max-Forwards: 70 Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr User-Agent: Foo-Bar Content-Length: 0
ACK captured on B, still has Route Header !?!?!?!:
181780.510: RECEIVED from 192.168.1.77:5060
ACK sip:85307@192.168.1.239:5060;user=phone SIP/2.0 Via: SIP/2.0/UDP 192.168.1.77;branch=z9hG4bK1014.fff3b3e5.0 From: sip:192.168.1.236:5060;tag=b2ce30d4-2062aaaa-ec187086 Call-ID: f40a387b-3-2062aaaa@192.168.1.236 To: sip:85307@192.168.1.77:5060;user=phone;tag=d85b805d-2062aaaa-ef187086 CSeq: 1817362 ACK Route: sip:192.168.1.77;ftag=b2ce30d4-2062aaaa-ec187086;lr User-Agent: Sip EXpress router(0.9.6 (i386/linux)) Content-Length: 0
I'm under the impression that SER handles the second ACK as if it was the ACK for a non-2XX response to an initial INVITE (reasonably assuming initial INVITES have usually no Route header). In other words SER assumes that this ACK is not supposed to be Record Routed and therefore does not remove the Route header. Something like that...
Let me know what you think.
Thanks,
Emmanuel.
Miklos Tirpak wrote:
Hello,
comments inline
On 03/20/2007 09:52 AM, Greger V. Teigre wrote:
I'm not sure that I understand what you mean is wrong. It would be easier to follow if you include the ACKs. And non-2xxs, what is exactly the exchange? A full SIP trace would help... g-)
Emmanuel Hislen wrote:
Hi,
I've been using SER (0.9.6) as a Proxy doing Loose Routing between 2 endpoints.
If I place a call I can see how the ACK for the 2XX response to the INVITE is properly handled (Route header removed, Record-Route inserted).
Now with the call still up, I do a re-INVITE which is rejected with a 415. The re-INVITE request sent by UAC contained a Route header, as it was an in-dialog request in a record-routed dialog. Now as per RFC3261 section 17.1.1.3:
If the INVITE request whose response is being acknowledged had Route header fields, those header fields MUST appear in the ACK. This is to ensure that the ACK can be routed properly through any downstream stateless proxies.
My UAC complied with the above, but SER seemed to choke on this:
whereas the ACK for 2XX was successfully routed by SER in the original INVITE, the ACK for non-2XX (looking exactly the same: same Request URI, same IP destination, same Route header, ... different Via branch of course) is not handled properly: yes the ACK reaches UAS but it still has the Route header in it, and no Record-Route was added. And I'm guessing that if there had been another proxy in the Route Set on the way to the UAS it would have been bypassed.
just to make some definition clear: Route set is the collection of Route headers, the Record-route headers are used only to learn the route-set. So the missing Record-route header does not have any impact of the ACK routing, however could have an impact of routing the BYE for example in your case. But the RFC says that the in-dialog requests do not modify the previously learned route-set:
"12.2 Requests within a Dialog ... Requests within a dialog MAY contain Record-Route and Contact header fields. However, these requests do not cause the dialog's route set to be modified, although they may modify the remote target URI. Specifically, requests that are not target refresh requests do not modify the dialog's remote target URI, and requests that are target refresh requests do. For dialogs that have been established with an INVITE, the only target refresh request defined is re-INVITE (see Section 14). Other extensions may define different target refresh requests for dialogs established in other ways.
Note that an ACK is NOT a target refresh request."
But be careful with modifying the route-set in SER (not with record-routeing but with modifying the route headers directly)! More info: http://tracker.iptel.org/browse/SER-212?page=all
Regards, Miklos
SER traces for ACK-2XX:
0(13574) ===> Loose Routing logic... 0(13574) parse_headers: flags=-1 0(13574) DEBUG: t_newtran: msg id=89 , global msg id=88 , T on entrance=0xffffffff 0(13574) parse_headers: flags=-1 0(13574) parse_headers: flags=60 0(13574) t_lookup_request: start searching: hash=41794, isACK=1 0(13574) parse_headers: flags=28 0(13574) DEBUG: t_lookup_request: e2e proxy ACK found 0(13574) parse_headers: flags=4 0(13574) DEBUG: totag for e2e ACK found: 0 0(13574) SER: forwarding ACK statelessly
SER traces for ACK-non-2XX:
0(13574) ===> Loose Routing logic... 0(13574) parse_headers: flags=-1 0(13574) DEBUG: t_newtran: msg id=92 , global msg id=91 , T on entrance=0xffffffff 0(13574) parse_headers: flags=-1 0(13574) parse_headers: flags=60 0(13574) t_lookup_request: start searching: hash=41807, isACK=1 0(13574) DEBUG: RFC3261 transaction matched, tid=007d7195499e33a1 0(13574) DEBUG: t_lookup_request: transaction found (T=0xb616ae48) 0(13574) DEBUG: cleanup_uac_timers: RETR/FR timers reset 0(13574) DEBUG: add_to_tail_of_timer[2]: 0xb616ae90 0(13574) DEBUG:destroy_avp_list: destroying list (nil) 0(13574) receive_msg: cleaning up
This doesn't seem right, am I missing something here?
Thanks,
Emmanuel. _______________________________________________ Serusers mailing list Serusers@lists.iptel.org http://lists.iptel.org/mailman/listinfo/serusers
Serusers mailing list Serusers@lists.iptel.org http://lists.iptel.org/mailman/listinfo/serusers