Ignore:
Timestamp:
Mar 30, 2010 11:13:59 AM (12 years ago)
Author:
nanang
Message:

Ticket #1044:

  • Added initial version of automatic re-registration after registration failure and automatic call disconnection after re-registration attempt fails.
  • Published auto re-registration setting to pjsua app.
  • Updated pjsip_regc_send() to retrieve the transport earlier (was only in tsx_callback()).
  • Fixed TCP and TLS transport to prevent transport deletion in transport disconnection callback.
  • Fixed wrong keep-alive settings used by TLS transport (was using TCP keep-alive settings).
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c

    r3096 r3128  
    2525 
    2626 
     27static void schedule_reregistration(pjsua_acc *acc); 
     28 
    2729/* 
    2830 * Get number of current accounts. 
     
    442444 
    443445    PJSUA_LOCK(); 
     446 
     447    /* Cancel any re-registration timer */ 
     448    pjsua_cancel_timer(&pjsua_var.acc[acc_id].auto_rereg.timer); 
    444449 
    445450    /* Delete registration */ 
     
    10321037    } else if (PJSIP_IS_STATUS_IN_CLASS(param->code, 200)) { 
    10331038 
     1039        /* Update auto registration flag */ 
     1040        acc->auto_rereg.active = PJ_FALSE; 
     1041        acc->auto_rereg.attempt_cnt = 0; 
     1042 
    10341043        if (param->expiration < 1) { 
    10351044            pjsip_regc_destroy(acc->regc); 
     
    10821091    if (pjsua_var.ua_cfg.cb.on_reg_state) 
    10831092        (*pjsua_var.ua_cfg.cb.on_reg_state)(acc->index); 
     1093 
     1094    /* Check if we need to auto retry registration. Basically, registration 
     1095     * failure codes triggering auto-retry are those of temporal failures 
     1096     * considered to be recoverable in relatively short term. 
     1097     */ 
     1098    if (acc->cfg.reg_retry_interval &&  
     1099        (param->code == PJSIP_SC_REQUEST_TIMEOUT || 
     1100         param->code == PJSIP_SC_INTERNAL_SERVER_ERROR || 
     1101         param->code == PJSIP_SC_BAD_GATEWAY || 
     1102         param->code == PJSIP_SC_SERVICE_UNAVAILABLE || 
     1103         param->code == PJSIP_SC_SERVER_TIMEOUT || 
     1104         PJSIP_IS_STATUS_IN_CLASS(param->code, 600))) /* Global failure */ 
     1105    { 
     1106        schedule_reregistration(acc); 
     1107    } 
    10841108 
    10851109    PJSUA_UNLOCK(); 
     
    12211245    PJSUA_LOCK(); 
    12221246 
     1247    /* Cancel any re-registration timer */ 
     1248    pjsua_cancel_timer(&pjsua_var.acc[acc_id].auto_rereg.timer); 
     1249 
     1250    /* Reset pointer to registration transport */ 
     1251    pjsua_var.acc[acc_id].auto_rereg.reg_tp = NULL; 
     1252 
    12231253    if (renew) { 
    12241254        if (pjsua_var.acc[acc_id].regc == NULL) { 
     
    12741304        //pjsua_process_msg_data(tdata, NULL); 
    12751305        status = pjsip_regc_send( pjsua_var.acc[acc_id].regc, tdata ); 
     1306    } 
     1307 
     1308    /* Update pointer to registration transport */ 
     1309    if (status == PJ_SUCCESS) { 
     1310        pjsip_regc_info reg_info; 
     1311 
     1312        pjsip_regc_get_info(pjsua_var.acc[acc_id].regc, &reg_info); 
     1313        pjsua_var.acc[acc_id].auto_rereg.reg_tp = reg_info.transport; 
    12761314    } 
    12771315 
     
    19261964} 
    19271965 
     1966 
     1967/* Auto re-registration timeout callback */ 
     1968static void auto_rereg_timer_cb(pj_timer_heap_t *th, pj_timer_entry *te) 
     1969{ 
     1970    pjsua_acc *acc; 
     1971    pj_status_t status; 
     1972 
     1973    PJ_UNUSED_ARG(th); 
     1974    acc = (pjsua_acc*) te->user_data; 
     1975    pj_assert(acc); 
     1976 
     1977    PJSUA_LOCK(); 
     1978 
     1979    if (!acc->valid || !acc->auto_rereg.active) 
     1980        goto on_return; 
     1981 
     1982    /* Start re-registration */ 
     1983    acc->auto_rereg.attempt_cnt++; 
     1984    status = pjsua_acc_set_registration(acc->index, PJ_TRUE); 
     1985    if (status != PJ_SUCCESS) 
     1986        schedule_reregistration(acc); 
     1987 
     1988    /* If configured, disconnect calls of this account after the first 
     1989     * reregistration attempt failed. 
     1990     */ 
     1991    if (acc->cfg.drop_calls_on_reg_fail && acc->auto_rereg.attempt_cnt > 1) 
     1992    { 
     1993        unsigned i, cnt; 
     1994 
     1995        for (i = 0, cnt = 0; i < pjsua_var.ua_cfg.max_calls; ++i) { 
     1996            if (pjsua_var.calls[i].acc_id == acc->index) { 
     1997                pjsua_call_hangup(i, 0, NULL, NULL); 
     1998                ++cnt; 
     1999            } 
     2000        } 
     2001 
     2002        if (cnt) { 
     2003            PJ_LOG(3, (THIS_FILE, "Disconnecting %d call(s) of account #%d " 
     2004                                  "after reregistration attempt failed", 
     2005                                  cnt, acc->index)); 
     2006        } 
     2007    } 
     2008 
     2009on_return: 
     2010 
     2011    PJSUA_UNLOCK(); 
     2012} 
     2013 
     2014 
     2015/* Schedule reregistration for specified account. Note that the first  
     2016 * re-registration after a registration failure will be done immediately. 
     2017 * Also note that this function should be called within PJSUA mutex. 
     2018 */ 
     2019static void schedule_reregistration(pjsua_acc *acc) 
     2020{ 
     2021    pj_time_val delay; 
     2022 
     2023    pj_assert(acc && acc->valid && acc->cfg.reg_retry_interval); 
     2024 
     2025    /* Cancel any re-registration timer */ 
     2026    pjsua_cancel_timer(&acc->auto_rereg.timer); 
     2027 
     2028    /* Update re-registration flag */ 
     2029    acc->auto_rereg.active = PJ_TRUE; 
     2030 
     2031    /* Set up timer for reregistration */ 
     2032    acc->auto_rereg.timer.cb = &auto_rereg_timer_cb; 
     2033    acc->auto_rereg.timer.user_data = acc; 
     2034 
     2035    /* Reregistration attempt. The first attempt will be done immediately. */ 
     2036    delay.sec = acc->auto_rereg.attempt_cnt? acc->cfg.reg_retry_interval : 0; 
     2037    delay.msec = 0; 
     2038    pjsua_schedule_timer(&acc->auto_rereg.timer, &delay); 
     2039} 
     2040 
     2041 
     2042/* Internal function to perform auto-reregistration on transport  
     2043 * connection/disconnection events. 
     2044 */ 
     2045void pjsua_acc_on_tp_state_changed(pjsip_transport *tp, 
     2046                                   pjsip_transport_state state, 
     2047                                   const pjsip_transport_state_info *info) 
     2048{ 
     2049    unsigned i; 
     2050 
     2051    PJ_UNUSED_ARG(info); 
     2052 
     2053    /* Only care for transport disconnection events */ 
     2054    if (state != PJSIP_TP_STATE_DISCONNECTED) 
     2055        return; 
     2056 
     2057    /* Shutdown this transport, to make sure that the transport manager  
     2058     * will create a new transport for reconnection. 
     2059     */ 
     2060    pjsip_transport_shutdown(tp); 
     2061 
     2062    PJSUA_LOCK(); 
     2063 
     2064    /* Enumerate accounts using this transport and perform actions 
     2065     * based on the transport state. 
     2066     */ 
     2067    for (i = 0; i < PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { 
     2068        pjsua_acc *acc = &pjsua_var.acc[i]; 
     2069 
     2070        /* Skip if this account is not valid OR auto re-registration 
     2071         * feature is disabled OR this transport is not used by this account. 
     2072         */ 
     2073        if (!acc->valid || !acc->cfg.reg_retry_interval ||  
     2074            tp != acc->auto_rereg.reg_tp) 
     2075        { 
     2076            continue; 
     2077        } 
     2078 
     2079        /* Schedule reregistration for this account */ 
     2080        schedule_reregistration(acc); 
     2081    } 
     2082 
     2083    PJSUA_UNLOCK(); 
     2084} 
Note: See TracChangeset for help on using the changeset viewer.