Changeset 3105


Ignore:
Timestamp:
Feb 23, 2010 11:03:07 AM (14 years ago)
Author:
bennylp
Message:

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
Location:
pjproject/trunk
Files:
3 added
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_reg.c

    r2855 r3105  
    935935    pjsip_regc *regc = (pjsip_regc*) token; 
    936936    pjsip_transaction *tsx = event->body.tsx_state.tsx; 
     937    pj_bool_t handled = PJ_TRUE; 
    937938 
    938939    pj_atomic_inc(regc->busy_ctr); 
     
    10011002        regc->current_op = REGC_IDLE; 
    10021003 
     1004    } else if (tsx->status_code == PJSIP_SC_INTERVAL_TOO_BRIEF && 
     1005               regc->current_op == REGC_REGISTERING) 
     1006    { 
     1007        /* Handle 423 response automatically: 
     1008         *  - set requested expiration to Min-Expires header, ONLY IF 
     1009         *    the original request is a registration (as opposed to 
     1010         *    unregistration) and the requested expiration was indeed 
     1011         *    lower than Min-Expires) 
     1012         *  - resend the request 
     1013         */ 
     1014        pjsip_rx_data *rdata = event->body.tsx_state.src.rdata; 
     1015        pjsip_min_expires_hdr *me_hdr; 
     1016        pjsip_tx_data *tdata; 
     1017        pj_int32_t min_exp; 
     1018 
     1019        /* reset current op */ 
     1020        regc->current_op = REGC_IDLE; 
     1021 
     1022        /* Update requested expiration */ 
     1023        me_hdr = (pjsip_min_expires_hdr*) 
     1024                 pjsip_msg_find_hdr(rdata->msg_info.msg, 
     1025                                    PJSIP_H_MIN_EXPIRES, NULL); 
     1026        if (me_hdr) { 
     1027            min_exp = me_hdr->ivalue; 
     1028        } else { 
     1029            /* Broken server, Min-Expires doesn't exist. 
     1030             * Just guestimate then, BUT ONLY if if this is the 
     1031             * first time we received such response. 
     1032             */ 
     1033            enum { 
     1034                /* Note: changing this value would require changing couple of 
     1035                 *       Python test scripts. 
     1036                 */ 
     1037                UNSPECIFIED_MIN_EXPIRES = 3601 
     1038            }; 
     1039            if (!regc->expires_hdr || 
     1040                 regc->expires_hdr->ivalue != UNSPECIFIED_MIN_EXPIRES) 
     1041            { 
     1042                min_exp = UNSPECIFIED_MIN_EXPIRES; 
     1043            } else { 
     1044                handled = PJ_FALSE; 
     1045                PJ_LOG(4,(THIS_FILE, "Registration failed: 423 response " 
     1046                                     "without Min-Expires header is invalid")); 
     1047                goto handle_err; 
     1048            } 
     1049        } 
     1050 
     1051        if (regc->expires_hdr && regc->expires_hdr->ivalue >= min_exp) { 
     1052            /* But we already send with greater expiration time, why does 
     1053             * the server send us with 423? Oh well, just fail the request. 
     1054             */ 
     1055            handled = PJ_FALSE; 
     1056            PJ_LOG(4,(THIS_FILE, "Registration failed: invalid " 
     1057                                 "Min-Expires header value in response")); 
     1058            goto handle_err; 
     1059        } 
     1060 
     1061        set_expires(regc, min_exp); 
     1062 
     1063        status = pjsip_regc_register(regc, regc->auto_reg, &tdata); 
     1064        if (status == PJ_SUCCESS) { 
     1065            status = pjsip_regc_send(regc, tdata); 
     1066        } 
     1067 
     1068        if (status != PJ_SUCCESS) { 
     1069            /* Only call callback if application is still interested 
     1070             * in it. 
     1071             */ 
     1072            if (!regc->_delete_flag) { 
     1073                /* Should be safe to release the lock temporarily. 
     1074                 * We do this to avoid deadlock. 
     1075                 */ 
     1076                pj_lock_release(regc->lock); 
     1077                call_callback(regc, status, tsx->status_code, 
     1078                              &rdata->msg_info.msg->line.status.reason, 
     1079                              rdata, -1, 0, NULL); 
     1080                pj_lock_acquire(regc->lock); 
     1081            } 
     1082        } 
     1083 
    10031084    } else { 
     1085        handled = PJ_FALSE; 
     1086    } 
     1087 
     1088handle_err: 
     1089    if (!handled) { 
    10041090        pjsip_rx_data *rdata; 
    10051091        pj_int32_t expiration = NOEXP; 
Note: See TracChangeset for help on using the changeset viewer.