Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 44365) +++ channels/chan_sip.c (working copy) @@ -3247,17 +3247,17 @@ __sip_pretend_ack(p); /* if we can't send right now, mark it pending */ - if (!ast_test_flag(&p->flags[0], SIP_CAN_BYE)) { +/* if (!ast_test_flag(&p->flags[0], SIP_CAN_BYE)) { ast_set_flag(&p->flags[0], SIP_PENDINGBYE); - /* Do we need a timer here if we don't hear from them at all? */ - } else { +*/ /* Do we need a timer here if we don't hear from them at all? */ +/* } else { */ /* Send a new request: CANCEL */ transmit_request_with_auth(p, SIP_CANCEL, p->ocseq, XMIT_RELIABLE, FALSE); /* Actually don't destroy us yet, wait for the 487 on our original INVITE, but do set an autodestruct just in case we never get it. */ needdestroy = 0; sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); - } +/* } */ if ( p->initid != -1 ) { /* channel still up - reverse dec of inUse counter only if the channel is not auto-congested */ @@ -11329,6 +11329,12 @@ (resp != 183)) resp = 183; + /* According to 12.1 of RFC3261, a dialog isn't established on a provisional, 1xx, response + unless there is a tag in the To field, ie. an "early dialog". + Furthermore, section 13.2.2.1 allows for the creation of "early dialogs" if there is a tag + in the To field. If there is no To tag, there is no dialog, and therefore + a BYE _cannot_ be sent, a CANCEL _must_ be sent instead. + */ switch (resp) { case 100: /* Trying */ if (!ast_test_flag(req, SIP_PKT_IGNORE)) @@ -11351,7 +11357,8 @@ ast_queue_control(p->owner, AST_CONTROL_PROGRESS); } } - ast_set_flag(&p->flags[0], SIP_CAN_BYE); + if (!ast_strlen_zero(p->theirtag) && !p->pendinginvite) + ast_set_flag(&p->flags[0], SIP_CAN_BYE); check_pendings(p); break; case 183: /* Session progress */ @@ -11365,7 +11372,8 @@ ast_queue_control(p->owner, AST_CONTROL_PROGRESS); } } - ast_set_flag(&p->flags[0], SIP_CAN_BYE); + if (!ast_strlen_zero(p->theirtag) && !p->pendinginvite) + ast_set_flag(&p->flags[0], SIP_CAN_BYE); check_pendings(p); break; case 200: /* 200 OK on invite - someone's answering our call */