Changeset 942


Ignore:
Timestamp:
Feb 13, 2007 2:52:37 AM (17 years ago)
Author:
bennylp
Message:

Implement ticket #99: a more generic mechanism to implement UAC transaction timeout after provisional response is received

Location:
pjproject/trunk/pjsip
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/include/pjsip/sip_transaction.h

    r882 r942  
    7575 
    7676/** 
     77 * Transaction timeout timer policy, to control the UAC transaction timeout 
     78 * scheduling (see #pjsip_tsx_set_uac_timeout()). 
     79 */ 
     80typedef enum pjsip_tsx_timeout_policy 
     81{ 
     82    PJSIP_TSX_IGNORE_100 = 1,   /**< To make the UAC transaction NOT to cancel 
     83                                     the timeout timer when 100 response is  
     84                                     received.*/ 
     85    PJSIP_TSX_IGNORE_1xx = 3    /**< To make the UAC transaction NOT to cancel 
     86                                     the timeout timer when any 1xx responses  
     87                                     are received. */ 
     88} pjsip_tsx_timeout_policy; 
     89 
     90 
     91/** 
    7792 * This structure describes SIP transaction object. The transaction object 
    7893 * is used to handle both UAS and UAC transaction. 
     
    131146    pj_timer_entry              timeout_timer;  /**< Timeout timer.         */ 
    132147 
     148    unsigned                    msec_timeout;   /**< User set timeout.      */ 
     149    pjsip_tsx_timeout_policy    timeout_policy; /**< Timeout policy.        */ 
     150 
    133151    /** Module specific data. */ 
    134152    void                       *mod_data[PJSIP_MAX_MODULE]; 
     
    233251 
    234252/** 
     253 * Set the UAC absolute transaction timeout. Normally UAC transaction will 
     254 * stop its timeout timer (timer B for INVITE and timer F for non-INVITE 
     255 * transactions) after a provisional response is received. 
     256 * 
     257 * When this timer is set, the transaction's timer B and F will use this 
     258 * value, and if the \a flag flag is set, the transaction will continue 
     259 * the scheduling of the timeout timer even when provisional response has 
     260 * been received. 
     261 * 
     262 * Note that this function MUST be called AFTER the transaction has been 
     263 * created AND BEFORE any request is transmitted. 
     264 * 
     265 * @param tsx       The client/UAC transaction. 
     266 * @param msec_time The timeout value, in miliseconds. Currently this 
     267 *                  value must be non-zero (value zero is reserved for 
     268 *                  future use). 
     269 * @param flag      Option flags to control whether the transaction should 
     270 *                  cancel the timeout timer on arrival of provisional 
     271 *                  responses (which is yes according to RFC 3261). 
     272 *                  The valid values are: 
     273 *                  - PJSIP_TSX_IGNORE_100, to make the UAC transaction 
     274 *                    NOT to cancel the timeout timer when 100 response 
     275 *                    is received. 
     276 *                  - PJSIP_TSX_IGNORE_1xx, to make the UAC transaction 
     277 *                    NOT to cancel the timeout timer when any 1xx  
     278 *                    responses are received. 
     279 * 
     280 *                  Note that regardless of the values in the \a flag  
     281 *                  argument, the provisional response would still be 
     282 *                  delivered to transaction user and it will still 
     283 *                  affect the transaction state. The \a flag flag only 
     284 *                  changes the behavior of the timeout timer of the 
     285 *                  transaction. 
     286 */ 
     287PJ_DECL(pj_status_t) pjsip_tsx_set_uac_timeout(pjsip_transaction *tsx, 
     288                                               unsigned msec_time, 
     289                                               pjsip_tsx_timeout_policy flag); 
     290 
     291 
     292/** 
    235293 * Call this function to manually feed a message to the transaction. 
    236294 * For UAS transaction, application MUST call this function after 
  • pjproject/trunk/pjsip/src/pjsip/sip_transaction.c

    r882 r942  
    13971397 
    13981398/* 
     1399 * Set the UAC absolute transaction timeout. 
     1400 */ 
     1401PJ_DEF(pj_status_t) pjsip_tsx_set_uac_timeout(pjsip_transaction *tsx, 
     1402                                              unsigned msec_time, 
     1403                                              pjsip_tsx_timeout_policy policy) 
     1404{ 
     1405    PJ_ASSERT_RETURN(tsx && tsx->role==PJSIP_ROLE_UAC && 
     1406                     tsx->state==PJSIP_TSX_STATE_NULL, PJ_EINVALIDOP); 
     1407 
     1408    tsx->msec_timeout = msec_time; 
     1409    tsx->timeout_policy = policy; 
     1410 
     1411    return PJ_SUCCESS; 
     1412} 
     1413 
     1414 
     1415/* 
    13991416 * Set transaction status code and reason. 
    14001417 */ 
     
    18971914 
    18981915        /* Start Timer B (or called timer F for non-INVITE) for transaction  
    1899          * timeout. 
     1916         * timeout. If user has configured the timeout value with  
     1917         * pjsip_tsx_set_uac_timeout(), use the timeout value there. 
    19001918         */ 
    1901         pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer,  
    1902                                     &timeout_timer_val); 
     1919        if (tsx->msec_timeout > 0) { 
     1920            pj_time_val timeout; 
     1921 
     1922            timeout.sec = tsx->msec_timeout / 1000; 
     1923            timeout.msec = tsx->msec_timeout % 1000; 
     1924 
     1925            pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer,  
     1926                                        &timeout); 
     1927 
     1928        } else { 
     1929            pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer,  
     1930                                        &timeout_timer_val); 
     1931        } 
    19031932 
    19041933        /* Start Timer A (or timer E) for retransmission only if unreliable  
     
    19681997    } else if (event->type == PJSIP_EVENT_RX_MSG) { 
    19691998        pjsip_msg *msg; 
    1970         //int code; 
     1999        int code; 
    19712000 
    19722001        /* Get message instance */ 
     
    19852014 
    19862015 
    1987         /* Cancel timer B (transaction timeout) */ 
    1988         pjsip_endpt_cancel_timer(tsx->endpt, &tsx->timeout_timer); 
     2016        /* Cancel timer B (transaction timeout) but look at the timeout policy 
     2017         * as set by pjsip_tsx_set_uac_timeout(). 
     2018         */ 
     2019        code = msg->line.status.code; 
     2020        if ((code==100 && tsx->timeout_policy==PJSIP_TSX_IGNORE_100) || 
     2021            (code<200 && tsx->timeout_policy==PJSIP_TSX_IGNORE_1xx)) 
     2022        { 
     2023            /* Don't cancel the timeout timer */ 
     2024        } 
     2025        else { 
     2026            pjsip_endpt_cancel_timer(tsx->endpt, &tsx->timeout_timer); 
     2027        } 
    19892028 
    19902029        /* Discard retransmission message if it is not INVITE. 
     
    23732412        } 
    23742413 
     2414    } else if (event->type == PJSIP_EVENT_TIMER && 
     2415               event->body.timer.entry == &tsx->timeout_timer) { 
     2416 
     2417        /* Inform TU. */ 
     2418        tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,  
     2419                       PJSIP_EVENT_TIMER, &tsx->timeout_timer); 
     2420 
     2421 
    23752422    } else if (tsx->status_code >= 300 && tsx->status_code <= 699) { 
    23762423 
  • pjproject/trunk/pjsip/src/pjsip/sip_util_statefull.c

    r932 r942  
    3030struct tsx_data 
    3131{ 
    32     pj_time_val     delay; 
    33     pj_timer_entry  timeout_timer; 
    34  
    3532    void *token; 
    3633    void (*cb)(void*, pjsip_event*); 
     
    7269        return; 
    7370 
    74     /* Cancel timer if any */ 
    75     if (tsx_data->timeout_timer.id != 0) { 
    76         tsx_data->timeout_timer.id = 0; 
    77         pjsip_endpt_cancel_timer(tsx->endpt, &tsx_data->timeout_timer); 
    78     } 
    79  
    8071    /* Call the callback, if any, and prevent the callback to be called again 
    8172     * by clearing the transaction's module_data. 
     
    8677        (*tsx_data->cb)(tsx_data->token, event); 
    8778    } 
    88 } 
    89  
    90  
    91 static void mod_util_on_timeout(pj_timer_heap_t *th, pj_timer_entry *te) 
    92 { 
    93     pjsip_transaction *tsx = (pjsip_transaction*) te->user_data; 
    94     struct tsx_data *tsx_data; 
    95  
    96     PJ_UNUSED_ARG(th); 
    97  
    98     tsx_data = tsx->mod_data[mod_stateful_util.id]; 
    99     if (tsx_data == NULL) { 
    100         pj_assert(!"Shouldn't happen"); 
    101         return; 
    102     } 
    103  
    104     tsx_data->timeout_timer.id = 0; 
    105  
    106     PJ_LOG(4,(tsx->obj_name, "Transaction timed out by user timer (%d.%d sec)", 
    107               (int)tsx_data->delay.sec, (int)tsx_data->delay.msec)); 
    108  
    109     /* Terminate the transaction. This will call mod_util_on_tsx_state() */ 
    110     pjsip_tsx_terminate(tsx, PJSIP_SC_TSX_TIMEOUT); 
    11179} 
    11280 
     
    134102    } 
    135103 
    136     tsx_data = pj_pool_zalloc(tsx->pool, sizeof(struct tsx_data)); 
     104    tsx_data = pj_pool_alloc(tsx->pool, sizeof(struct tsx_data)); 
    137105    tsx_data->token = token; 
    138106    tsx_data->cb = cb; 
    139107 
    140108    if (timeout >= 0) { 
    141         tsx_data->delay.sec = 0; 
    142         tsx_data->delay.msec = timeout; 
    143         pj_time_val_normalize(&tsx_data->delay); 
    144  
    145         tsx_data->timeout_timer.id = PJ_TRUE; 
    146         tsx_data->timeout_timer.user_data = tsx; 
    147         tsx_data->timeout_timer.cb = &mod_util_on_timeout; 
    148          
    149         status = pjsip_endpt_schedule_timer(endpt, &tsx_data->timeout_timer,  
    150                                             &tsx_data->delay); 
    151         if (status != PJ_SUCCESS) { 
    152             pjsip_tsx_terminate(tsx, PJSIP_SC_INTERNAL_SERVER_ERROR); 
    153             pjsip_tx_data_dec_ref(tdata); 
    154             return status; 
    155         } 
     109        status = pjsip_tsx_set_uac_timeout(tsx, timeout, PJSIP_TSX_IGNORE_1xx); 
     110        pj_assert(status == PJ_SUCCESS); 
    156111    } 
    157112 
     
    159114 
    160115    status = pjsip_tsx_send_msg(tsx, NULL); 
    161     if (status != PJ_SUCCESS) { 
    162         if (tsx_data->timeout_timer.id != 0) { 
    163             pjsip_endpt_cancel_timer(endpt, &tsx_data->timeout_timer); 
    164             tsx_data->timeout_timer.id = PJ_FALSE; 
    165         } 
     116    if (status != PJ_SUCCESS) 
    166117        pjsip_tx_data_dec_ref(tdata); 
    167     } 
    168118 
    169119    return status; 
Note: See TracChangeset for help on using the changeset viewer.