Changeset 3128


Ignore:
Timestamp:
Mar 30, 2010 11:13:59 AM (14 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).
Location:
pjproject/trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c

    r3119 r3128  
    190190    puts  ("                      May be specified multiple times"); 
    191191    puts  ("  --reg-timeout=SEC   Optional registration interval (default 55)"); 
     192    puts  ("  --rereg-delay=SEC   Optional auto retry registration interval (default 300)"); 
    192193    puts  ("  --realm=string      Set realm"); 
    193194    puts  ("  --username=string   Set authentication username"); 
     
    485486           OPT_BOUND_ADDR, OPT_CONTACT_PARAMS, OPT_CONTACT_URI_PARAMS, 
    486487           OPT_100REL, OPT_USE_IMS, OPT_REALM, OPT_USERNAME, OPT_PASSWORD, 
     488           OPT_REG_RETRY_INTERVAL, 
    487489           OPT_MWI, OPT_NAMESERVER, OPT_STUN_SRV, 
    488490           OPT_ADD_BUDDY, OPT_OFFER_X_MS_MSG, OPT_NO_PRESENCE, 
     
    551553        { "username",   1, 0, OPT_USERNAME}, 
    552554        { "password",   1, 0, OPT_PASSWORD}, 
     555        { "rereg-delay",1, 0, OPT_REG_RETRY_INTERVAL}, 
    553556        { "nameserver", 1, 0, OPT_NAMESERVER}, 
    554557        { "stun-srv",   1, 0, OPT_STUN_SRV}, 
     
    960963            break; 
    961964 
     965        case OPT_REG_RETRY_INTERVAL: 
     966            cur_acc->reg_retry_interval = pj_strtoul(pj_cstr(&tmp, pj_optarg)); 
     967            break; 
     968 
    962969        case OPT_NEXT_CRED: /* next credential */ 
    963970            cur_acc->cred_count++; 
  • pjproject/trunk/pjsip/include/pjsip-ua/sip_regc.h

    r2855 r3128  
    9595    int         interval;   /**< Registration interval (seconds).           */ 
    9696    int         next_reg;   /**< Time until next registration (seconds).    */ 
     97    pjsip_transport *transport; /**< Last transport used.                   */ 
    9798}; 
    9899 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r3110 r3128  
    18661866 
    18671867/** 
     1868 * Default auto retry re-registration interval, in seconds. Set to 0 
     1869 * to disable this. Application can set the timer on per account basis  
     1870 * by setting the pjsua_acc_config.reg_retry_interval field instead. 
     1871 * 
     1872 * Default: 300 (5 minutes) 
     1873 */ 
     1874#ifndef PJSUA_REG_RETRY_INTERVAL 
     1875#   define PJSUA_REG_RETRY_INTERVAL     300 
     1876#endif 
     1877 
     1878 
     1879/** 
    18681880 * This structure describes account configuration to be specified when 
    18691881 * adding a new account with #pjsua_acc_add(). Application MUST initialize 
     
    21162128    int              srtp_secure_signaling; 
    21172129#endif 
     2130 
     2131    /** 
     2132     * Specify interval of auto registration retry upon registration failure 
     2133     * (including caused by transport problem), in second. Set to 0 to 
     2134     * disable auto re-registration. 
     2135     * 
     2136     * Default: #PJSUA_REG_RETRY_INTERVAL 
     2137     */ 
     2138    unsigned         reg_retry_interval; 
     2139 
     2140    /** 
     2141     * Specify whether calls of the configured account should be dropped 
     2142     * after registration failure and an attempt of re-registration has  
     2143     * also failed. 
     2144     * 
     2145     * Default: PJ_FALSE (disabled) 
     2146     */ 
     2147    pj_bool_t        drop_calls_on_reg_fail; 
    21182148 
    21192149} pjsua_acc_config; 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h

    r3119 r3128  
    129129    int              reg_last_code; /**< Last status last register.     */ 
    130130 
     131    struct { 
     132        pj_bool_t        active;    /**< Flag of reregister status.     */ 
     133        pj_timer_entry   timer;     /**< Timer for reregistration.      */ 
     134        void            *reg_tp;    /**< Transport for registration.    */ 
     135        unsigned         attempt_cnt; /**< Attempt counter.             */ 
     136    } auto_rereg;                   /**< Reregister/reconnect data.     */ 
     137 
    131138    pj_timer_entry   ka_timer;      /**< Keep-alive timer for UDP.      */ 
    132139    pjsip_transport *ka_transport;  /**< Transport for keep-alive.      */ 
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_reg.c

    r3105 r3128  
    204204    info->auto_reg = regc->auto_reg; 
    205205    info->interval = regc->expires; 
     206    info->transport = regc->last_transport; 
    206207     
    207208    if (regc->has_tsx) 
     
    12031204        regc->current_op = REGC_REGISTERING; 
    12041205 
     1206    /* Prevent deletion of tdata, e.g: when something wrong in sending, 
     1207     * we need tdata to retrieve the transport. 
     1208     */ 
     1209    pjsip_tx_data_add_ref(tdata); 
     1210 
    12051211    status = pjsip_endpt_send_request(regc->endpt, tdata, REGC_TSX_TIMEOUT, 
    12061212                                      regc, &tsx_callback); 
     
    12091215    } 
    12101216 
     1217    /* Get last transport used and add reference to it */ 
     1218    if (tdata->tp_info.transport != regc->last_transport) { 
     1219        if (regc->last_transport) { 
     1220            pjsip_transport_dec_ref(regc->last_transport); 
     1221            regc->last_transport = NULL; 
     1222        } 
     1223 
     1224        if (tdata->tp_info.transport) { 
     1225            regc->last_transport = tdata->tp_info.transport; 
     1226            pjsip_transport_add_ref(regc->last_transport); 
     1227        } 
     1228    } 
     1229 
     1230    /* Release tdata */ 
     1231    pjsip_tx_data_dec_ref(tdata); 
     1232 
    12111233    pj_lock_release(regc->lock); 
    12121234 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c

    r3119 r3128  
    178178        return; 
    179179 
     180    /* Prevent immediate transport destroy by application, as transport 
     181     * state notification callback may be stacked and transport instance 
     182     * must remain valid at any point in the callback. 
     183     */ 
     184    pjsip_transport_add_ref(&tcp->base); 
     185 
    180186    /* Notify application of transport disconnected state */ 
    181187    state_cb = pjsip_tpmgr_get_status_cb(tcp->base.tpmgr); 
     
    194200     */ 
    195201    pjsip_transport_shutdown(&tcp->base); 
     202 
     203    /* Now, it is ok to destroy the transport. */ 
     204    pjsip_transport_dec_ref(&tcp->base); 
    196205} 
    197206 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c

    r3119 r3128  
    185185        return; 
    186186 
     187    /* Prevent immediate transport destroy by application, as transport 
     188     * state notification callback may be stacked and transport instance 
     189     * must remain valid at any point in the callback. 
     190     */ 
     191    pjsip_transport_add_ref(&tls->base); 
     192 
    187193    /* Notify application of transport disconnected state */ 
    188194    state_cb = pjsip_tpmgr_get_status_cb(tls->base.tpmgr); 
     
    201207     */ 
    202208    pjsip_transport_shutdown(&tls->base); 
     209 
     210    /* Now, it is ok to destroy the transport. */ 
     211    pjsip_transport_dec_ref(&tls->base); 
    203212} 
    204213 
     
    518527{ 
    519528    struct tls_transport *tls; 
    520     const pj_str_t ka_pkt = PJSIP_TCP_KEEP_ALIVE_DATA; 
     529    const pj_str_t ka_pkt = PJSIP_TLS_KEEP_ALIVE_DATA; 
    521530    pj_status_t status; 
    522531     
     
    579588    sockaddr_to_host_port(pool, &tls->base.local_name,  
    580589                          (pj_sockaddr_in*)&tls->base.local_addr); 
    581     sockaddr_to_host_port(pool, &tls->base.remote_name, remote); 
     590    if (tls->remote_name.slen) { 
     591        tls->base.remote_name.host = tls->remote_name; 
     592        tls->base.remote_name.port = pj_sockaddr_in_get_port(remote); 
     593    } else { 
     594        sockaddr_to_host_port(pool, &tls->base.remote_name, remote); 
     595    } 
    582596 
    583597    tls->base.endpt = listener->endpt; 
     
    10761090    } else { 
    10771091        /* Start keep-alive timer */ 
    1078         if (PJSIP_TCP_KEEP_ALIVE_INTERVAL) { 
    1079             pj_time_val delay = {PJSIP_TCP_KEEP_ALIVE_INTERVAL, 0}; 
     1092        if (PJSIP_TLS_KEEP_ALIVE_INTERVAL) { 
     1093            pj_time_val delay = {PJSIP_TLS_KEEP_ALIVE_INTERVAL, 0}; 
    10801094            pjsip_endpt_schedule_timer(listener->endpt,  
    10811095                                       &tls->ka_timer,  
     
    15081522 
    15091523    /* Start keep-alive timer */ 
    1510     if (PJSIP_TCP_KEEP_ALIVE_INTERVAL) { 
    1511         pj_time_val delay = { PJSIP_TCP_KEEP_ALIVE_INTERVAL, 0 }; 
     1524    if (PJSIP_TLS_KEEP_ALIVE_INTERVAL) { 
     1525        pj_time_val delay = { PJSIP_TLS_KEEP_ALIVE_INTERVAL, 0 }; 
    15121526        pjsip_endpt_schedule_timer(tls->base.endpt, &tls->ka_timer,  
    15131527                                   &delay); 
     
    15411555    PJ_TIME_VAL_SUB(now, tls->last_activity); 
    15421556 
    1543     if (now.sec > 0 && now.sec < PJSIP_TCP_KEEP_ALIVE_INTERVAL) { 
     1557    if (now.sec > 0 && now.sec < PJSIP_TLS_KEEP_ALIVE_INTERVAL) { 
    15441558        /* There has been activity, so don't send keep-alive */ 
    1545         delay.sec = PJSIP_TCP_KEEP_ALIVE_INTERVAL - now.sec; 
     1559        delay.sec = PJSIP_TLS_KEEP_ALIVE_INTERVAL - now.sec; 
    15461560        delay.msec = 0; 
    15471561 
     
    15711585 
    15721586    /* Register next keep-alive */ 
    1573     delay.sec = PJSIP_TCP_KEEP_ALIVE_INTERVAL; 
     1587    delay.sec = PJSIP_TLS_KEEP_ALIVE_INTERVAL; 
    15741588    delay.msec = 0; 
    15751589 
  • 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} 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r3119 r3128  
    177177    cfg->srtp_secure_signaling = pjsua_var.ua_cfg.srtp_secure_signaling; 
    178178#endif 
     179    cfg->reg_retry_interval = PJSUA_REG_RETRY_INTERVAL; 
    179180} 
    180181 
     
    15261527} 
    15271528 
     1529void pjsua_acc_on_tp_state_changed(pjsip_transport *tp, 
     1530                                   pjsip_transport_state state, 
     1531                                   const pjsip_transport_state_info *info); 
     1532 
    15281533/* Callback to receive transport state notifications */ 
    15291534static void on_tp_state_callback(pjsip_transport *tp, 
     
    15371542        (*pjsua_var.old_tp_cb)(tp, state, info); 
    15381543    } 
     1544    pjsua_acc_on_tp_state_changed(tp, state, info); 
    15391545} 
    15401546 
Note: See TracChangeset for help on using the changeset viewer.