diff options
author | Benny Prijono <bennylp@teluu.com> | 2010-02-23 11:03:07 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2010-02-23 11:03:07 +0000 |
commit | df622f00fa10e2cbcde9df6169ad628fe3e72226 (patch) | |
tree | 880d29fbe8e66d583d17768cf169068d1b89071f /pjsip/src/pjsip-ua | |
parent | bc8de1cca14dc2a09c570af759f6782aa9802158 (diff) |
Ticket #1031: Automatically handle 423 (Interval Too Brief) response in SIP registration (thanks Tomáš Valenta for the suggestion)
- implemented in sip_reg.c instead of in PJSUA-LIB, so that the functionality can be reused by non-PJSUA-LIB applications
- also added several Python test scripts
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3105 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip/src/pjsip-ua')
-rw-r--r-- | pjsip/src/pjsip-ua/sip_reg.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/pjsip/src/pjsip-ua/sip_reg.c b/pjsip/src/pjsip-ua/sip_reg.c index ecba264b..3975028f 100644 --- a/pjsip/src/pjsip-ua/sip_reg.c +++ b/pjsip/src/pjsip-ua/sip_reg.c @@ -934,6 +934,7 @@ static void tsx_callback(void *token, pjsip_event *event) pj_status_t status; pjsip_regc *regc = (pjsip_regc*) token; pjsip_transaction *tsx = event->body.tsx_state.tsx; + pj_bool_t handled = PJ_TRUE; pj_atomic_inc(regc->busy_ctr); pj_lock_acquire(regc->lock); @@ -1000,7 +1001,92 @@ static void tsx_callback(void *token, pjsip_event *event) /* Just reset current op */ regc->current_op = REGC_IDLE; + } else if (tsx->status_code == PJSIP_SC_INTERVAL_TOO_BRIEF && + regc->current_op == REGC_REGISTERING) + { + /* Handle 423 response automatically: + * - set requested expiration to Min-Expires header, ONLY IF + * the original request is a registration (as opposed to + * unregistration) and the requested expiration was indeed + * lower than Min-Expires) + * - resend the request + */ + pjsip_rx_data *rdata = event->body.tsx_state.src.rdata; + pjsip_min_expires_hdr *me_hdr; + pjsip_tx_data *tdata; + pj_int32_t min_exp; + + /* reset current op */ + regc->current_op = REGC_IDLE; + + /* Update requested expiration */ + me_hdr = (pjsip_min_expires_hdr*) + pjsip_msg_find_hdr(rdata->msg_info.msg, + PJSIP_H_MIN_EXPIRES, NULL); + if (me_hdr) { + min_exp = me_hdr->ivalue; + } else { + /* Broken server, Min-Expires doesn't exist. + * Just guestimate then, BUT ONLY if if this is the + * first time we received such response. + */ + enum { + /* Note: changing this value would require changing couple of + * Python test scripts. + */ + UNSPECIFIED_MIN_EXPIRES = 3601 + }; + if (!regc->expires_hdr || + regc->expires_hdr->ivalue != UNSPECIFIED_MIN_EXPIRES) + { + min_exp = UNSPECIFIED_MIN_EXPIRES; + } else { + handled = PJ_FALSE; + PJ_LOG(4,(THIS_FILE, "Registration failed: 423 response " + "without Min-Expires header is invalid")); + goto handle_err; + } + } + + if (regc->expires_hdr && regc->expires_hdr->ivalue >= min_exp) { + /* But we already send with greater expiration time, why does + * the server send us with 423? Oh well, just fail the request. + */ + handled = PJ_FALSE; + PJ_LOG(4,(THIS_FILE, "Registration failed: invalid " + "Min-Expires header value in response")); + goto handle_err; + } + + set_expires(regc, min_exp); + + status = pjsip_regc_register(regc, regc->auto_reg, &tdata); + if (status == PJ_SUCCESS) { + status = pjsip_regc_send(regc, tdata); + } + + if (status != PJ_SUCCESS) { + /* Only call callback if application is still interested + * in it. + */ + if (!regc->_delete_flag) { + /* Should be safe to release the lock temporarily. + * We do this to avoid deadlock. + */ + pj_lock_release(regc->lock); + call_callback(regc, status, tsx->status_code, + &rdata->msg_info.msg->line.status.reason, + rdata, -1, 0, NULL); + pj_lock_acquire(regc->lock); + } + } + } else { + handled = PJ_FALSE; + } + +handle_err: + if (!handled) { pjsip_rx_data *rdata; pj_int32_t expiration = NOEXP; unsigned contact_cnt = 0; |