Hi, I saw this scenario before. The B sip device was VOS which it is a popular but not good implemented soft switch. I found that call was disconnected at side B when it sent back CANCEL 200 OK response. And if A sent out BYE to clear the dialog, the response from B was 481. I don't think B is following RFC 3261 well. For better implementation, B should response 4xx rather than 200 because related dialog already connected before CANCLE arrived. And for A, normally we need a timer to wait for DISCONNECTED event call back from pjsip-ua to make sure related dialog resource is released. Then we could easy detect this race condition at there when that timer timeout. regards, Gang On Fri, Feb 24, 2012 at 6:28 AM, Steve King <sking at zetron.com> wrote: > Hi Alan, > > Thanks for the email. > > In this instance, PJSIP is acting as UAC, not UAS so Rule 9.2 does not apply to it. > At B, 9.2 rule is followed correctly. > The standard does not seem to mention this particular scenario. > > Logically, as the app, I have requested PJSIP end that session, however PJ does not do that and allows the session to be established. > > In effect, *all* PJSIP based applications are then forced to perform a check if the session is being ended when the session is reported as established/confirmed. Does pjsua handle this scenario? > > Imho, I think its sensible for PJSIP to take about this. > > Steve > >> -----Original Message----- >> From: pjsip-bounces@xxxxxxxxxxxxxxx [mailto:pjsip- >> bounces at lists.pjsip.org] On Behalf Of Alain Totouom >> Sent: Thursday, 23 February 2012 07:51 PM >> To: pjsip list >> Subject: Re: CANCEL and final INVITE response glare ("crosses >> the wire") >> >> Hi Steve, >> >> On 02/23/2012 08:36 AM, Steve King wrote: >> > Hi Benny, >> > >> > >> > >> > The scenario is: >> > >> > >> > >> > A ? ? ? ? ? ? ? ?B >> > >> > 1. =====> INVITE >> > >> > 2. <==== ? 100 Trying >> > >> > 3. =====> CANCEL >> > >> > 4. <===== 200 OK (INVITE w SDP) >> > >> > 5. =====> ACK >> > >> > 6. <===== 200 OK (CANCEL) >> > >> > >> > >> > In this case, B sends final INVITE response(4) before receiving >> > CANCEL(3), PJSIP receives the response, ACKs it and indicates up to >> > the application that the call is connected and its media available >> > (not good). The 200 response to the CANCEL is according to spec and >> > terminates the tsx for the CANCEL. >> > >> > >> > >> > This has been touched on before in a previous thread: >> > http://lists.pjsip.org/pipermail/pjsip_lists.pjsip.org/2009- >> September/ >> > 00 >> > 8945.html >> > >> > But no real conclusion was reached. >> > >> > >> > >> > I think this case can/should be handled in the SIP stack, rather than >> > at the application layer. >> > >> >> We are definitively missing one part of the conversation here: what >> does the calleR do, when it ends up with an established dialog, despite >> the succeful completion of the CANCEL-Transaction it has previously >> issued?!? >> At application level is easier to catch and resolve that conflict by >> sending a BYE/UAC... >> >> Here is what the standard says about this hop-by-hop request as far as >> the UAS is concerned... >> >> 9.2 Server Behavior >> "If the transaction for the original request still exists, the behavior >> of the UAS on receiving a CANCEL request depends on whether it has >> already sent a final response for the original request. ?If it has, the >> CANCEL request has no effect on the processing of the original request, >> no effect on any session state, and no effect on the responses >> generated for the original request." >> >> IMHO PJSIP is strictly following the 9.2 rule... >> >> The best place to solve this race condition and be fully #3261 ?9 >> compliant should/would definitively be at the application level. >> >> Best regards, >> Alain >> >> >> > >> > >> > I propose a change to sip_inv.c, in inv_send_ack(). See below: >> > >> > >> > >> > ? ? /* Send ACK */ >> > >> > ? ? status = pjsip_dlg_send_request(inv->dlg, inv->last_ack, -1, >> > NULL); >> > >> > ? ? if (status != PJ_SUCCESS) { >> > >> > ? ? ?/* Better luck next time */ >> > >> > ? ? ?pj_assert(!"Unable to send ACK!"); >> > >> > ? ? ?return status; >> > >> > ? ? } >> > >> > >> > >> > >> > >> > ? ? /* Set state to CONFIRMED (if we're not in CONFIRMED yet). >> > >> > ? ? ?* But don't set it to CONFIRMED if we're already DISCONNECTED >> > >> > ? ? ?* (this may have been a late 200/OK response. >> > >> > ? ? ?*/ >> > >> > ? ? if (inv->state < PJSIP_INV_STATE_CONFIRMED) { >> > >> > >> > >> > ? ? ? ? /* Bug: PJSIP does not handle a glare of rx final INVITE >> > >> > ? ? ? ? ?* ? ? ?response and tx CANCEL (when in early state) >> > >> > ? ? ? ? ?* >> > >> > ? ? ? ? ?* The ACK may be set in response to final INVITE >> > >> > ? ? ? ? ?* response, but CANCEL may have been sent prior. >> > >> > ? ? ? ? ?* We check here for cancelling inv session, if set, >> > >> > ? ? ? ? ?* we end the session and suppress state notification >> > >> > ? ? ? ? ?* for confirmed state. >> > >> > ? ? ? ? ?*/ >> > >> > ? ? ? ? if(inv->cancelling) { >> > >> > ? ? ? ? ? ? PJ_LOG(5,(inv->obj_name, "Suppressing %s notification, >> > because cancellation in progress", >> > >> > ? ? ? ? ? ? ? ? ? ? inv_state_names[PJSIP_INV_STATE_CONFIRMED])); >> > >> > >> > >> > ? ? ? ? ? ? notify = inv->notify; >> > >> > ? ? ? ? ? ? inv->notify = PJ_FALSE; >> > >> > ? ? ? ? ? ? inv_set_state(inv, PJSIP_INV_STATE_CONFIRMED, e); >> > >> > ? ? ? ? ? ? inv->notify = notify; >> > >> > >> > >> > ? ? ? ? ? ? status = pjsip_inv_end_session(inv, PJSIP_SC_GONE, NULL, >> > &tdata); >> > >> > ? ? ? ? ? ? if( status == PJ_SUCCESS) { >> > >> > ? ? ? ? ? ? ? ? status = pjsip_dlg_send_request(inv->dlg, tdata, -1, >> > NULL); >> > >> > ? ? ? ? ? ? ? ? if (status != PJ_SUCCESS) { >> > >> > ? ? ? ? ? ? ? ? ? ? /* Better luck next time */ >> > >> > ? ? ? ? ? ? ? ? ? ? pj_assert(!"Unable to send BYE!"); >> > >> > ? ? ? ? ? ? ? ? ? ? return status; >> > >> > ? ? ? ? ? ? ? ? } >> > >> > ? ? ? ? ? ? } >> > >> > ? ? ? ? } >> > >> > ? ? ? ? else { >> > >> > ? ? ? ? ? ? inv_set_state(inv, PJSIP_INV_STATE_CONFIRMED, e); >> > >> > ? ? ? ? } >> > >> > ? ? } >> > >> > >> > >> > ? ? return PJ_SUCCESS; >> > >> > >> > >> > Is this a bad idea? What are your thoughts? >> > >> > >> > >> > Steve >> > >> > >> > >> > >> > >> > >> > >> > _______________________________________________ >> > Visit our blog: http://blog.pjsip.org >> > >> > pjsip mailing list >> > pjsip at lists.pjsip.org >> > http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org >> >> -- >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? "" >> ? ? ? ? ? ? ? ? ? ? ? ? ? (o)(o) >> ? ? ? ? ? ? ? ? _____o00o__(__)__o00o_____ >> 3072D/146D10DE 2011-09-29 ? ?Alain Totouom ?<totouom at gmx.de> >> PGP Fingerprint 39A4F092 FFA7C746 CC305CB0 69091911 146D10DE >> >> _______________________________________________ >> Visit our blog: http://blog.pjsip.org >> >> pjsip mailing list >> pjsip at lists.pjsip.org >> http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org > > _______________________________________________ > Visit our blog: http://blog.pjsip.org > > pjsip mailing list > pjsip at lists.pjsip.org > http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org