diff options
author | Benny Prijono <bennylp@teluu.com> | 2008-02-21 19:28:21 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2008-02-21 19:28:21 +0000 |
commit | 9dafbac6b6e70d84ed1f925c1ec1ee00b5c4411d (patch) | |
tree | f1252b89503165c3f94ad3b275ffd604532035be /pjsip/src/pjsip-ua | |
parent | eb85ed9665fbcf4fa5a500e67fb4e7865ba79aa9 (diff) |
Ticket #488: When outgoing request within dialog is responded with 481 or 408, should send BYE after terminating dialog (thanks Philippe Leuba)
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1814 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip/src/pjsip-ua')
-rw-r--r-- | pjsip/src/pjsip-ua/sip_inv.c | 109 |
1 files changed, 67 insertions, 42 deletions
diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c index ee5274fd..8b813fa2 100644 --- a/pjsip/src/pjsip-ua/sip_inv.c +++ b/pjsip/src/pjsip-ua/sip_inv.c @@ -2883,6 +2883,60 @@ static void inv_on_state_early( pjsip_inv_session *inv, pjsip_event *e) } /* + * Handle 408, 481, or any other responses that terminates dialog. + */ +static pj_bool_t handle_408_481_response(pjsip_inv_session *inv, + pjsip_event *e) +{ + /* RFC 3261 Section 12.2.1.2: + * If the response for a request within a dialog is a 481 + * (Call/Transaction Does Not Exist) or a 408 (Request Timeout), the UAC + * SHOULD terminate the dialog. A UAC SHOULD also terminate a dialog if + * no response at all is received for the request (the client + * transaction would inform the TU about the timeout.) + * + * For INVITE initiated dialogs, terminating the dialog consists of + * sending a BYE. + * + * Note: + * according to X, this should terminate dialog usage only, not the + * dialog. + */ + pjsip_transaction *tsx = e->body.tsx_state.tsx; + + pj_assert(tsx->role == PJSIP_UAC_ROLE); + + /* Note that 481 response to CANCEL does not terminate dialog usage, + * but only the transaction. + */ + if ((tsx->status_code == PJSIP_SC_CALL_TSX_DOES_NOT_EXIST && + tsx->method.id != PJSIP_CANCEL_METHOD) || + tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT || + tsx->status_code == PJSIP_SC_TSX_TIMEOUT || + tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR) + { + pjsip_tx_data *bye; + pj_status_t status; + + inv_set_cause(inv, tsx->status_code, &tsx->status_text); + inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); + + /* Send BYE */ + status = pjsip_dlg_create_request(inv->dlg, pjsip_get_bye_method(), + -1, &bye); + if (status == PJ_SUCCESS) { + pjsip_inv_send_msg(inv, bye); + } + + return PJ_TRUE; /* Handled */ + + } else { + return PJ_FALSE; /* Unhandled */ + } +} + + +/* * State CONNECTING is after 2xx response to INVITE is sent/received. */ static void inv_on_state_connecting( pjsip_inv_session *inv, pjsip_event *e) @@ -2993,7 +3047,8 @@ static void inv_on_state_connecting( pjsip_inv_session *inv, pjsip_event *e) /* * Handle response to outgoing UPDATE request. */ - inv_handle_update_response(inv, e); + if (handle_408_481_response(inv, e) == PJ_FALSE) + inv_handle_update_response(inv, e); } else if (tsx->role == PJSIP_ROLE_UAS && tsx->state == PJSIP_TSX_STATE_TRYING && @@ -3005,22 +3060,8 @@ static void inv_on_state_connecting( pjsip_inv_session *inv, pjsip_event *e) inv_respond_incoming_prack(inv, e->body.tsx_state.src.rdata); } else if (tsx->role == PJSIP_ROLE_UAC) { - /* - * Handle case when outgoing request is answered with 481 (Call/ - * Transaction Does Not Exist), 408, or when it's timed out. In these - * cases, disconnect session (i.e. dialog usage only). - * Note that 481 response to CANCEL does not terminate dialog usage, - * but only the transaction. - */ - if ((tsx->status_code == PJSIP_SC_CALL_TSX_DOES_NOT_EXIST && - tsx->method.id != PJSIP_CANCEL_METHOD) || - tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT || - tsx->status_code == PJSIP_SC_TSX_TIMEOUT || - tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR) - { - inv_set_cause(inv, tsx->status_code, &tsx->status_text); - inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); - } + + handle_408_481_response(inv, e); } } @@ -3249,6 +3290,11 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e) /* Send ACK */ inv_send_ack(inv, e); + } else if (handle_408_481_response(inv, e)) { + + /* Handle response that terminates dialog */ + /* Nothing to do (already handled) */ + } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED && (tsx->status_code==401 || tsx->status_code==407)) { @@ -3266,16 +3312,6 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e) /* Send re-INVITE */ status = pjsip_inv_send_msg( inv, tdata); - } else if (tsx->status_code==PJSIP_SC_CALL_TSX_DOES_NOT_EXIST || - tsx->status_code==PJSIP_SC_REQUEST_TIMEOUT || - tsx->status_code >= 700) - { - /* - * Handle responses that terminates dialog. - */ - inv_set_cause(inv, tsx->status_code, &tsx->status_text); - inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); - } else if (tsx->status_code >= 300 && tsx->status_code < 700) { pjmedia_sdp_neg_state neg_state; @@ -3304,7 +3340,8 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e) /* * Handle response to outgoing UPDATE request. */ - inv_handle_update_response(inv, e); + if (handle_408_481_response(inv, e) == PJ_FALSE) + inv_handle_update_response(inv, e); } else if (tsx->role == PJSIP_ROLE_UAS && tsx->state == PJSIP_TSX_STATE_TRYING && @@ -3317,21 +3354,9 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e) } else if (tsx->role == PJSIP_ROLE_UAC) { /* - * Handle case when outgoing request is answered with 481 (Call/ - * Transaction Does Not Exist), 408, or when it's timed out. In these - * cases, disconnect session (i.e. dialog usage only). - * Note that 481 response to CANCEL does not terminate dialog usage, - * but only the transaction. + * Handle 408/481 response */ - if ((tsx->status_code == PJSIP_SC_CALL_TSX_DOES_NOT_EXIST && - tsx->method.id != PJSIP_CANCEL_METHOD) || - tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT || - tsx->status_code == PJSIP_SC_TSX_TIMEOUT || - tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR) - { - inv_set_cause(inv, tsx->status_code, &tsx->status_text); - inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); - } + handle_408_481_response(inv, e); } } |