Changeset 1189


Ignore:
Timestamp:
Apr 11, 2007 6:30:31 PM (17 years ago)
Author:
bennylp
Message:

Fixed ticket #220: Bug in retransmission of non-INVITE SIP requests in UAC transaction (thanks Martin Peterzon)

Location:
pjproject/branches/pjproject-0.5-stable/pjsip
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/pjproject-0.5-stable/pjsip/include/pjsip/sip_transaction.h

    r974 r1189  
    7575 
    7676/** 
    77  * Transaction timeout timer policy, to control the UAC transaction timeout 
    78  * scheduling (see #pjsip_tsx_set_uac_timeout()). 
    79  */ 
    80 typedef 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 /** 
    9277 * This structure describes SIP transaction object. The transaction object 
    9378 * is used to handle both UAS and UAC transaction. 
     
    146131    pj_timer_entry              timeout_timer;  /**< Timeout timer.         */ 
    147132 
    148     unsigned                    msec_timeout;   /**< User set timeout.      */ 
    149     pjsip_tsx_timeout_policy    timeout_policy; /**< Timeout policy.        */ 
    150  
    151133    /** Module specific data. */ 
    152134    void                       *mod_data[PJSIP_MAX_MODULE]; 
     
    249231                                             const pjsip_tpselector *sel); 
    250232 
    251  
    252 /** 
    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  */ 
    287 PJ_DECL(pj_status_t) pjsip_tsx_set_uac_timeout(pjsip_transaction *tsx, 
    288                                                unsigned msec_time, 
    289                                                pjsip_tsx_timeout_policy flag); 
    290  
    291  
    292233/** 
    293234 * Call this function to manually feed a message to the transaction. 
  • pjproject/branches/pjproject-0.5-stable/pjsip/src/pjsip/sip_transaction.c

    r1077 r1189  
    133133static const pj_time_val t1_timer_val = { PJSIP_T1_TIMEOUT/1000,  
    134134                                          PJSIP_T1_TIMEOUT%1000 }; 
     135static const pj_time_val t2_timer_val = { PJSIP_T2_TIMEOUT/1000,  
     136                                          PJSIP_T2_TIMEOUT%1000 }; 
    135137static const pj_time_val t4_timer_val = { PJSIP_T4_TIMEOUT/1000,  
    136138                                          PJSIP_T4_TIMEOUT%1000 }; 
     
    13971399 
    13981400/* 
    1399  * Set the UAC absolute transaction timeout. 
    1400  */ 
    1401 PJ_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 /* 
    14161401 * Set transaction status code and reason. 
    14171402 */ 
     
    18101795    pj_assert((tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) == 0); 
    18111796 
    1812     msec_time = (1 << (tsx->retransmit_count)) * PJSIP_T1_TIMEOUT; 
     1797    pj_assert(tsx->status_code < 200); 
     1798 
     1799    if (tsx->status_code >= 100) 
     1800        msec_time = PJSIP_T2_TIMEOUT; 
     1801    else 
     1802        msec_time = (1 << (tsx->retransmit_count)) * PJSIP_T1_TIMEOUT; 
    18131803 
    18141804    if (tsx->role == PJSIP_ROLE_UAC) { 
     
    19141904 
    19151905        /* Start Timer B (or called timer F for non-INVITE) for transaction  
    1916          * timeout. If user has configured the timeout value with  
    1917          * pjsip_tsx_set_uac_timeout(), use the timeout value there. 
     1906         * timeout. 
    19181907         */ 
    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         } 
     1908        pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer,  
     1909                                    &timeout_timer_val); 
    19321910 
    19331911        /* Start Timer A (or timer E) for retransmission only if unreliable  
     
    20061984            return PJSIP_ENOTRESPONSEMSG; 
    20071985 
    2008         /* Cancel retransmission timer A. */ 
    2009         if (tsx->retransmit_timer._timer_id != -1) { 
    2010             pjsip_endpt_cancel_timer(tsx->endpt, &tsx->retransmit_timer); 
    2011             tsx->retransmit_timer._timer_id = -1; 
    2012         } 
     1986        code = msg->line.status.code; 
     1987 
     1988        /* If the response is final, cancel both retransmission and timeout 
     1989         * timer. 
     1990         */ 
     1991        if (code >= 200) { 
     1992            if (tsx->retransmit_timer._timer_id != -1) { 
     1993                pjsip_endpt_cancel_timer(tsx->endpt, &tsx->retransmit_timer); 
     1994                tsx->retransmit_timer._timer_id = -1; 
     1995            } 
     1996 
     1997            if (tsx->timeout_timer._timer_id != -1) { 
     1998                pjsip_endpt_cancel_timer(tsx->endpt, &tsx->timeout_timer); 
     1999                tsx->timeout_timer._timer_id = -1; 
     2000            } 
     2001 
     2002        } else { 
     2003            /* Cancel retransmit timer (for non-INVITE transaction, the 
     2004             * retransmit timer will be rescheduled at T2. 
     2005             */ 
     2006            if (tsx->retransmit_timer._timer_id != -1) { 
     2007                pjsip_endpt_cancel_timer(tsx->endpt, &tsx->retransmit_timer); 
     2008                tsx->retransmit_timer._timer_id = -1; 
     2009            } 
     2010 
     2011            /* For provisional response, only cancel retransmit when this 
     2012             * is an INVITE transaction. For non-INVITE, section 17.1.2.1 
     2013             * of RFC 3261 says that: 
     2014             *  - retransmit timer is set to T2 
     2015             *  - timeout timer F is not deleted. 
     2016             */ 
     2017            if (tsx->method.id == PJSIP_INVITE_METHOD) { 
     2018 
     2019                /* Cancel timeout timer */ 
     2020                pjsip_endpt_cancel_timer(tsx->endpt, &tsx->timeout_timer); 
     2021 
     2022            } else { 
     2023                if (!tsx->is_reliable) { 
     2024                    pjsip_endpt_schedule_timer(tsx->endpt,  
     2025                                               &tsx->retransmit_timer, 
     2026                                               &t2_timer_val); 
     2027                } 
     2028            } 
     2029        } 
     2030          
    20132031        tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED); 
    20142032 
    2015  
    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         } 
    20282033 
    20292034        /* Discard retransmission message if it is not INVITE. 
     
    23682373 
    23692374    } else { 
    2370         tsx_set_status_code(tsx, PJSIP_SC_TSX_TIMEOUT, NULL); 
     2375        if (event->body.timer.entry == &tsx->retransmit_timer) { 
     2376            /* Retransmit message. */ 
     2377            pj_status_t status; 
     2378 
     2379            status = tsx_retransmit( tsx, 1 ); 
     2380             
     2381            return status; 
     2382 
     2383        } else { 
     2384            tsx_set_status_code(tsx, PJSIP_SC_TSX_TIMEOUT, NULL); 
     2385        } 
    23712386    } 
    23722387 
  • pjproject/branches/pjproject-0.5-stable/pjsip/src/pjsip/sip_util_statefull.c

    r974 r1189  
    9595    PJ_ASSERT_RETURN(mod_stateful_util.id != -1, PJ_EINVALIDOP); 
    9696 
     97    PJ_UNUSED_ARG(timeout); 
    9798 
    9899    status = pjsip_tsx_create_uac(&mod_stateful_util, tdata, &tsx); 
     
    105106    tsx_data->token = token; 
    106107    tsx_data->cb = cb; 
    107  
    108     if (timeout >= 0) { 
    109         status = pjsip_tsx_set_uac_timeout(tsx, timeout, PJSIP_TSX_IGNORE_1xx); 
    110         pj_assert(status == PJ_SUCCESS); 
    111     } 
    112108 
    113109    tsx->mod_data[mod_stateful_util.id] = tsx_data; 
Note: See TracChangeset for help on using the changeset viewer.