If the caller wants to hang up a call, but hasn't yet received a final response, it can send a CANCEL or a BYE. Sending a BYE would seem easiest, but there are issues. First off, you won't have gotten a tag yet from the UAS, nor will you have received Record-Route or Contact headers (obtained in the 200 OK response). This means the BYE will be routed "afresh" by proxies. Its possible that routing logic may have changed (perhaps there was some time of day routing or randomized routing), in which case the BYE may reach a different set of participants than reached by the original INVITE. So, if the original INVITE forked, and reached A and B, and the BYE reaches B and C, B will send a 200 OK, and C a 481. The forking proxy forwards the 200 OK upstream, and the caller gets the 200 OK. However, A is still ringing, and might later send a 200 OK. This yield inconsistent call state, which will persist until the UAS times out, as it will never get an ACK.
Sending CANCEL helps solve many of these problems. CANCEL will reach the same set of recipients as the original INVITE, and it doesn't need a REcord-Route or tag in it. The drawback, however, is that the CANCEL and a 200 OK from one of the UAS might pass on the wire. Thus, the UAC may still need to ACK the 200 OK, and then send BYE. The other drawback is that you wouldn't send CANCEL if the call was already established, you'd send BYE. Folks complained they didn't want to have state-dependent mechanisms for hanging up. Given the unlikelihood of the problems with sending BYE, it seems reasonable to allow it.
|