Ignore:
Timestamp:
Oct 3, 2007 6:28:49 PM (17 years ago)
Author:
bennylp
Message:

Ticket 5: Support for SIP UPDATE (RFC 3311) and fix the offer/answer negotiation

File:
1 edited

Legend:

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

    r1463 r1469  
    3232#include <pj/log.h> 
    3333 
     34/*  
     35 * Note on offer/answer: 
     36 * 
     37 * The offer/answer framework in this implementation assumes the occurence 
     38 * of SDP in a particular request/response according to this table: 
     39 
     40                  offer   answer    Note: 
     41    ======================================================================== 
     42    INVITE          X               INVITE may contain offer 
     43    18x/INVITE      X       X       Response may contain offer or answer 
     44    2xx/INVITE      X       X       Response may contain offer or answer 
     45    ACK                     X       ACK may contain answer 
     46 
     47    PRACK                   X       PRACK can only contain answer 
     48    2xx/PRACK                       Response may not have offer nor answer 
     49 
     50    UPDATE          X               UPDATE may only contain offer 
     51    2xx/UPDATE              X       Response may only contain answer 
     52    ======================================================================== 
     53 
     54  * 
     55  */ 
    3456 
    3557#define THIS_FILE       "sip_inv.c" 
     
    4769}; 
    4870 
     71/* UPDATE method */ 
     72const pjsip_method pjsip_update_method = 
     73{ 
     74    PJSIP_OTHER_METHOD, 
     75    { "UPDATE", 6 } 
     76}; 
     77 
    4978/* 
    5079 * Static prototypes. 
     
    6796                                                  pjsip_transaction *tsx, 
    6897                                                  pjsip_rx_data *rdata); 
     98static pj_status_t inv_negotiate_sdp( pjsip_inv_session *inv ); 
     99static pjsip_msg_body *create_sdp_body(pj_pool_t *pool, 
     100                                       const pjmedia_sdp_session *c_sdp); 
    69101static pj_status_t process_answer( pjsip_inv_session *inv, 
    70102                                   int st_code, 
     
    120152static pj_status_t mod_inv_load(pjsip_endpoint *endpt) 
    121153{ 
    122     pj_str_t allowed[] = {{"INVITE", 6}, {"ACK",3}, {"BYE",3}, {"CANCEL",6}}; 
     154    pj_str_t allowed[] = {{"INVITE", 6}, {"ACK",3}, {"BYE",3}, {"CANCEL",6}, 
     155                            { "UPDATE", 6}}; 
    123156    pj_str_t accepted = { "application/sdp", 15 }; 
    124157 
    125     /* Register supported methods: INVITE, ACK, BYE, CANCEL */ 
     158    /* Register supported methods: INVITE, ACK, BYE, CANCEL, UPDATE */ 
    126159    pjsip_endpt_add_capability(endpt, &mod_inv.mod, PJSIP_H_ALLOW, NULL, 
    127160                               PJ_ARRAY_SIZE(allowed), allowed); 
     
    187220        prev_state != PJSIP_INV_STATE_DISCONNECTED)  
    188221    { 
     222        if (inv->last_ack) { 
     223            pjsip_tx_data_dec_ref(inv->last_ack); 
     224            inv->last_ack = NULL; 
     225        } 
     226        pjsip_100rel_end_session(inv); 
    189227        pjsip_dlg_dec_session(inv->dlg, &mod_inv.mod); 
    190228    } 
     
    210248 
    211249 
     250/* 
     251 * Check if outgoing request needs to have SDP answer. 
     252 * This applies for both ACK and PRACK requests. 
     253 */ 
     254static pjmedia_sdp_session *inv_has_pending_answer(pjsip_inv_session *inv, 
     255                                                   pjsip_transaction *tsx) 
     256{ 
     257    pjmedia_sdp_neg_state neg_state; 
     258    pjmedia_sdp_session *sdp = NULL; 
     259    pj_status_t status; 
     260 
     261    /* If SDP negotiator is ready, start negotiation. */ 
     262 
     263    /* Start nego when appropriate. */ 
     264    neg_state = inv->neg ? pjmedia_sdp_neg_get_state(inv->neg) : 
     265                PJMEDIA_SDP_NEG_STATE_NULL; 
     266 
     267    if (neg_state == PJMEDIA_SDP_NEG_STATE_DONE) { 
     268 
     269        /* Nothing to do */ 
     270 
     271    } else if (neg_state == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO && 
     272               pjmedia_sdp_neg_has_local_answer(inv->neg) ) 
     273    { 
     274        struct tsx_inv_data *tsx_inv_data; 
     275 
     276        /* Get invite session's transaction data */ 
     277        tsx_inv_data = (struct tsx_inv_data*) tsx->mod_data[mod_inv.mod.id]; 
     278 
     279        status = inv_negotiate_sdp(inv); 
     280        if (status != PJ_SUCCESS) 
     281            return NULL; 
     282         
     283        /* Mark this transaction has having SDP offer/answer done. */ 
     284        tsx_inv_data->sdp_done = 1; 
     285 
     286        status = pjmedia_sdp_neg_get_active_local(inv->neg, &sdp); 
     287 
     288    } else { 
     289        /* This remark is only valid for ACK. 
     290        PJ_LOG(4,(inv->dlg->obj_name, 
     291                  "FYI, the SDP negotiator state (%s) is in a mess " 
     292                  "when sending this ACK/PRACK request", 
     293                  pjmedia_sdp_neg_state_str(neg_state))); 
     294         */ 
     295    } 
     296 
     297    return sdp; 
     298} 
     299 
    212300 
    213301/* 
     
    216304static pj_status_t inv_send_ack(pjsip_inv_session *inv, pjsip_rx_data *rdata) 
    217305{ 
    218     pjsip_tx_data *tdata; 
    219306    pj_status_t status; 
    220307 
     
    222309              pjsip_rx_data_get_info(rdata))); 
    223310 
    224     status = pjsip_dlg_create_request(inv->dlg, pjsip_get_ack_method(),  
    225                                       rdata->msg_info.cseq->cseq, &tdata); 
    226     if (status != PJ_SUCCESS) { 
    227         /* Better luck next time */ 
    228         pj_assert(!"Unable to create ACK!"); 
    229         return status; 
    230     } 
    231  
    232     status = pjsip_dlg_send_request(inv->dlg, tdata, -1, NULL); 
     311    /* Check if we have cached ACK request */ 
     312    if (inv->last_ack && rdata->msg_info.cseq->cseq == inv->last_ack_cseq) { 
     313        pjsip_tx_data_add_ref(inv->last_ack); 
     314    } else { 
     315        pjmedia_sdp_session *sdp = NULL; 
     316 
     317        /* Destroy last_ack */ 
     318        if (inv->last_ack) { 
     319            pjsip_tx_data_dec_ref(inv->last_ack); 
     320            inv->last_ack = NULL; 
     321        } 
     322 
     323        /* Create new ACK request */ 
     324        status = pjsip_dlg_create_request(inv->dlg, pjsip_get_ack_method(),  
     325                                          rdata->msg_info.cseq->cseq,  
     326                                          &inv->last_ack); 
     327        if (status != PJ_SUCCESS) { 
     328            /* Better luck next time */ 
     329            pj_assert(!"Unable to create ACK!"); 
     330            return status; 
     331        } 
     332 
     333        /* See if we have pending SDP answer to send */ 
     334        sdp = inv_has_pending_answer(inv, inv->invite_tsx); 
     335        if (sdp) { 
     336            inv->last_ack->msg->body=create_sdp_body(inv->last_ack->pool, sdp); 
     337        } 
     338 
     339 
     340        /* Keep this for subsequent response retransmission */ 
     341        inv->last_ack_cseq = rdata->msg_info.cseq->cseq; 
     342        pjsip_tx_data_add_ref(inv->last_ack); 
     343    } 
     344 
     345    /* Send ACK */ 
     346    status = pjsip_dlg_send_request(inv->dlg, inv->last_ack, -1, NULL); 
    233347    if (status != PJ_SUCCESS) { 
    234348        /* Better luck next time */ 
     
    493607        options |= PJSIP_INV_SUPPORT_100REL; 
    494608 
    495 #if !PJSIP_HAS_100REL 
    496     /* options cannot specify 100rel if 100rel is disabled */ 
    497     PJ_ASSERT_RETURN( 
    498         (options & (PJSIP_INV_REQUIRE_100REL | PJSIP_INV_SUPPORT_100REL))==0, 
    499         PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_EXTENSION)); 
    500      
    501 #endif 
    502  
    503609    if (options & PJSIP_INV_REQUIRE_TIMER) 
    504610        options |= PJSIP_INV_SUPPORT_TIMER; 
     
    539645    pjsip_dlg_inc_session(dlg, &mod_inv.mod); 
    540646 
    541 #if PJSIP_HAS_100REL 
    542647    /* Create 100rel handler */ 
    543648    pjsip_100rel_attach(inv); 
    544 #endif 
    545649 
    546650    /* Done */ 
     
    9441048        options |= PJSIP_INV_SUPPORT_100REL; 
    9451049 
    946 #if !PJSIP_HAS_100REL 
    947     /* options cannot specify 100rel if 100rel is disabled */ 
    948     PJ_ASSERT_RETURN( 
    949         (options & (PJSIP_INV_REQUIRE_100REL | PJSIP_INV_SUPPORT_100REL))==0, 
    950         PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_EXTENSION)); 
    951      
    952 #endif 
    953  
    9541050    if (options & PJSIP_INV_REQUIRE_TIMER) 
    9551051        options |= PJSIP_INV_SUPPORT_TIMER; 
     
    10211117    inv->invite_tsx->mod_data[mod_inv.mod.id] = tsx_inv_data; 
    10221118 
    1023 #if PJSIP_HAS_100REL 
    10241119    /* Create 100rel handler */ 
    10251120    if (inv->options & PJSIP_INV_REQUIRE_100REL) { 
    10261121            pjsip_100rel_attach(inv); 
    10271122    } 
    1028 #endif 
    10291123 
    10301124    /* Done */ 
     
    12401334 
    12411335/* 
    1242  * Negotiate SDP. 
     1336 * Initiate SDP negotiation in the SDP negotiator. 
    12431337 */ 
    12441338static pj_status_t inv_negotiate_sdp( pjsip_inv_session *inv ) 
     
    17821876PJ_DEF(pj_status_t) pjsip_inv_update (  pjsip_inv_session *inv, 
    17831877                                        const pj_str_t *new_contact, 
    1784                                         const pjmedia_sdp_session *new_offer, 
     1878                                        const pjmedia_sdp_session *offer, 
    17851879                                        pjsip_tx_data **p_tdata ) 
    17861880{ 
    1787     PJ_UNUSED_ARG(inv); 
    1788     PJ_UNUSED_ARG(new_contact); 
    1789     PJ_UNUSED_ARG(new_offer); 
    1790     PJ_UNUSED_ARG(p_tdata); 
    1791  
    1792     PJ_TODO(CREATE_UPDATE_REQUEST); 
    1793     return PJ_ENOTSUP; 
     1881    pjsip_contact_hdr *contact_hdr = NULL; 
     1882    pjsip_tx_data *tdata = NULL; 
     1883    pjmedia_sdp_session *sdp_copy; 
     1884    pj_status_t status = PJ_SUCCESS; 
     1885 
     1886    /* Verify arguments. */ 
     1887    PJ_ASSERT_RETURN(inv && p_tdata && offer, PJ_EINVAL); 
     1888 
     1889    /* Dialog must have been established */ 
     1890    PJ_ASSERT_RETURN(inv->dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED, 
     1891                     PJ_EINVALIDOP); 
     1892 
     1893    /* Invite session must not have been disconnected */ 
     1894    PJ_ASSERT_RETURN(inv->state < PJSIP_INV_STATE_DISCONNECTED, 
     1895                     PJ_EINVALIDOP); 
     1896 
     1897    /* Lock dialog. */ 
     1898    pjsip_dlg_inc_lock(inv->dlg); 
     1899 
     1900    /* Process offer */ 
     1901    if (pjmedia_sdp_neg_get_state(inv->neg)!=PJMEDIA_SDP_NEG_STATE_DONE) { 
     1902        PJ_LOG(4,(inv->dlg->obj_name,  
     1903                  "Invalid SDP offer/answer state for UPDATE")); 
     1904        status = PJ_EINVALIDOP; 
     1905        goto on_error; 
     1906    } 
     1907 
     1908    status = pjmedia_sdp_neg_modify_local_offer(inv->pool,inv->neg, 
     1909                                                offer); 
     1910    if (status != PJ_SUCCESS) 
     1911        goto on_error; 
     1912 
     1913 
     1914    /* Update Contact if required */ 
     1915    if (new_contact) { 
     1916        pj_str_t tmp; 
     1917        const pj_str_t STR_CONTACT = { "Contact", 7 }; 
     1918 
     1919        pj_strdup_with_null(inv->dlg->pool, &tmp, new_contact); 
     1920        contact_hdr = (pjsip_contact_hdr*) 
     1921                      pjsip_parse_hdr(inv->dlg->pool, &STR_CONTACT,  
     1922                                      tmp.ptr, tmp.slen, NULL); 
     1923        if (!contact_hdr) { 
     1924            status = PJSIP_EINVALIDURI; 
     1925            goto on_error; 
     1926        } 
     1927 
     1928        inv->dlg->local.contact = contact_hdr; 
     1929    } 
     1930 
     1931    /* Create request */ 
     1932    status = pjsip_dlg_create_request(inv->dlg, &pjsip_update_method, 
     1933                                      -1, &tdata); 
     1934    if (status != PJ_SUCCESS) 
     1935            goto on_error; 
     1936 
     1937    /* Attach SDP body */ 
     1938    sdp_copy = pjmedia_sdp_session_clone(tdata->pool, offer); 
     1939    pjsip_create_sdp_body(tdata->pool, sdp_copy, &tdata->msg->body); 
     1940 
     1941    /* Unlock dialog. */ 
     1942    pjsip_dlg_dec_lock(inv->dlg); 
     1943 
     1944    *p_tdata = tdata; 
     1945 
     1946    return PJ_SUCCESS; 
     1947 
     1948on_error: 
     1949    if (tdata) 
     1950        pjsip_tx_data_dec_ref(tdata); 
     1951 
     1952    /* Unlock dialog. */ 
     1953    pjsip_dlg_dec_lock(inv->dlg); 
     1954 
     1955    return status; 
    17941956} 
    17951957 
     
    18331995                         PJ_EINVALIDOP); 
    18341996 
    1835 #if PJSIP_HAS_100REL 
    18361997        if (inv->options & PJSIP_INV_REQUIRE_100REL) { 
    1837                 status = pjsip_100rel_tx_response(inv, tdata); 
     1998            status = pjsip_100rel_tx_response(inv, tdata); 
    18381999        } else  
    1839 #endif 
    18402000        { 
    1841                 status = pjsip_dlg_send_response(inv->dlg, inv->invite_tsx, tdata); 
     2001            status = pjsip_dlg_send_response(inv->dlg, inv->invite_tsx, tdata); 
    18422002        } 
    18432003 
     
    19882148 
    19892149/* 
     2150 * Respond to incoming UPDATE request. 
     2151 */ 
     2152static void inv_respond_incoming_update(pjsip_inv_session *inv, 
     2153                                        pjsip_rx_data *rdata) 
     2154{ 
     2155    pjmedia_sdp_neg_state neg_state; 
     2156    pj_status_t status; 
     2157    pjsip_tx_data *tdata = NULL; 
     2158 
     2159    neg_state = pjmedia_sdp_neg_get_state(inv->neg); 
     2160 
     2161    /* Send 491 if we receive UPDATE while we're waiting for an answer */ 
     2162    if (neg_state == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) { 
     2163        status = pjsip_dlg_create_response(inv->dlg, rdata,  
     2164                                           PJSIP_SC_REQUEST_PENDING, NULL, 
     2165                                           &tdata); 
     2166    } 
     2167    /* Send 500 with Retry-After header set randomly between 0 and 10 if we  
     2168     * receive UPDATE while we haven't sent answer. 
     2169     */ 
     2170    else if (neg_state == PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER || 
     2171             neg_state == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO) { 
     2172        status = pjsip_dlg_create_response(inv->dlg, rdata,  
     2173                                           PJSIP_SC_INTERNAL_SERVER_ERROR, 
     2174                                           NULL, &tdata); 
     2175 
     2176    } else { 
     2177        /* We receive new offer from remote */ 
     2178        inv_check_sdp_in_incoming_msg(inv, pjsip_rdata_get_tsx(rdata), rdata); 
     2179 
     2180        /* Application MUST have supplied the answer by now. 
     2181         * If so, negotiate the SDP. 
     2182         */ 
     2183        neg_state = pjmedia_sdp_neg_get_state(inv->neg); 
     2184        if (neg_state != PJMEDIA_SDP_NEG_STATE_WAIT_NEGO || 
     2185            (status=inv_negotiate_sdp(inv)) != PJ_SUCCESS) 
     2186        { 
     2187            /* Negotiation has failed */ 
     2188            status = pjsip_dlg_create_response(inv->dlg, rdata,  
     2189                                               PJSIP_SC_NOT_ACCEPTABLE_HERE, 
     2190                                               NULL, &tdata); 
     2191        } else { 
     2192            /* New media has been negotiated successfully, send 200/OK */ 
     2193            status = pjsip_dlg_create_response(inv->dlg, rdata,  
     2194                                               PJSIP_SC_OK, NULL, &tdata); 
     2195            if (status == PJ_SUCCESS) { 
     2196                pjmedia_sdp_session *sdp; 
     2197                status = pjmedia_sdp_neg_get_active_local(inv->neg, &sdp); 
     2198                if (status == PJ_SUCCESS) 
     2199                    tdata->msg->body = create_sdp_body(tdata->pool, sdp); 
     2200            } 
     2201        } 
     2202    } 
     2203 
     2204    if (status != PJ_SUCCESS) { 
     2205        if (tdata != NULL) { 
     2206            pjsip_tx_data_dec_ref(tdata); 
     2207            tdata = NULL; 
     2208        } 
     2209        return; 
     2210    } 
     2211 
     2212    pjsip_dlg_send_response(inv->dlg, pjsip_rdata_get_tsx(rdata), tdata); 
     2213} 
     2214 
     2215 
     2216/* 
     2217 * Handle incoming response to UAC UPDATE request. 
     2218 */ 
     2219static void inv_handle_update_response( pjsip_inv_session *inv, 
     2220                                        pjsip_event *e) 
     2221{ 
     2222    pjsip_transaction *tsx = e->body.tsx_state.tsx; 
     2223    struct tsx_inv_data *tsx_inv_data = NULL; 
     2224    pj_status_t status = -1; 
     2225 
     2226    /* Process 2xx response */ 
     2227    if (tsx->state == PJSIP_TSX_STATE_COMPLETED && 
     2228        tsx->status_code/100 == 2 && 
     2229        e->body.tsx_state.src.rdata->msg_info.msg->body) 
     2230    { 
     2231        status = inv_check_sdp_in_incoming_msg(inv, tsx,  
     2232                                            e->body.tsx_state.src.rdata); 
     2233 
     2234    } else { 
     2235        /* Get/attach invite session's transaction data */ 
     2236        tsx_inv_data = (struct tsx_inv_data*)tsx->mod_data[mod_inv.mod.id]; 
     2237        if (tsx_inv_data == NULL) { 
     2238            tsx_inv_data=PJ_POOL_ZALLOC_T(tsx->pool, struct tsx_inv_data); 
     2239            tsx_inv_data->inv = inv; 
     2240            tsx->mod_data[mod_inv.mod.id] = tsx_inv_data; 
     2241        } 
     2242    } 
     2243 
     2244    /* Otherwise if we don't get successful response, cancel 
     2245     * our negotiator. 
     2246     */ 
     2247    if (status != PJ_SUCCESS && 
     2248        pjmedia_sdp_neg_get_state(inv->neg)==PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER && 
     2249        tsx_inv_data && tsx_inv_data->sdp_done == PJ_FALSE)  
     2250    { 
     2251        pjmedia_sdp_neg_cancel_offer(inv->neg); 
     2252 
     2253        /* Prevent from us cancelling different offer! */ 
     2254        tsx_inv_data->sdp_done = PJ_TRUE; 
     2255    } 
     2256} 
     2257 
     2258 
     2259/* 
     2260 * Handle incoming reliable response. 
     2261 */ 
     2262static void inv_handle_incoming_reliable_response(pjsip_inv_session *inv, 
     2263                                                  pjsip_rx_data *rdata) 
     2264{ 
     2265    pjsip_tx_data *tdata; 
     2266    pjmedia_sdp_session *sdp; 
     2267    pj_status_t status; 
     2268 
     2269    /* Create PRACK */ 
     2270    status = pjsip_100rel_create_prack(inv, rdata, &tdata); 
     2271    if (status != PJ_SUCCESS) 
     2272        return; 
     2273 
     2274    /* See if we need to attach SDP answer on the PRACK request */ 
     2275    sdp = inv_has_pending_answer(inv, pjsip_rdata_get_tsx(rdata)); 
     2276    if (sdp) { 
     2277        tdata->msg->body = create_sdp_body(tdata->pool, sdp); 
     2278    } 
     2279 
     2280    /* Send PRACK (must be using 100rel module!) */ 
     2281    pjsip_100rel_send_prack(inv, tdata); 
     2282} 
     2283 
     2284 
     2285/* 
     2286 * Handle incoming PRACK. 
     2287 */ 
     2288static void inv_respond_incoming_prack(pjsip_inv_session *inv, 
     2289                                       pjsip_rx_data *rdata) 
     2290{ 
     2291    pj_status_t status; 
     2292 
     2293    /* Run through 100rel module to see if we can accept this 
     2294     * PRACK request. The 100rel will send 200/OK to PRACK request. 
     2295     */ 
     2296    status = pjsip_100rel_on_rx_prack(inv, rdata); 
     2297    if (status != PJ_SUCCESS) 
     2298        return; 
     2299 
     2300    /* Now check for SDP answer in the PRACK request */ 
     2301    if (rdata->msg_info.msg->body) { 
     2302        status = inv_check_sdp_in_incoming_msg(inv,  
     2303                                        pjsip_rdata_get_tsx(rdata), rdata); 
     2304    } else { 
     2305        /* No SDP body */ 
     2306        status = -1; 
     2307    } 
     2308 
     2309    /* If SDP negotiation has been successful, also mark the 
     2310     * SDP negotiation flag in the invite transaction to be 
     2311     * done too. 
     2312     */ 
     2313    if (status == PJ_SUCCESS && inv->invite_tsx) { 
     2314        struct tsx_inv_data *tsx_inv_data; 
     2315 
     2316        /* Get/attach invite session's transaction data */ 
     2317        tsx_inv_data = (struct tsx_inv_data*)  
     2318                       inv->invite_tsx->mod_data[mod_inv.mod.id]; 
     2319        if (tsx_inv_data == NULL) { 
     2320            tsx_inv_data = PJ_POOL_ZALLOC_T(inv->invite_tsx->pool,  
     2321                                            struct tsx_inv_data); 
     2322            tsx_inv_data->inv = inv; 
     2323            inv->invite_tsx->mod_data[mod_inv.mod.id] = tsx_inv_data; 
     2324        } 
     2325         
     2326        tsx_inv_data->sdp_done = PJ_TRUE; 
     2327    } 
     2328} 
     2329 
     2330 
     2331/* 
    19902332 * State NULL is before anything is sent/received. 
    19912333 */ 
     
    20732415                                              e->body.tsx_state.src.rdata); 
    20742416 
     2417                if (pjsip_100rel_is_reliable(e->body.tsx_state.src.rdata)) { 
     2418                    inv_handle_incoming_reliable_response( 
     2419                        inv, e->body.tsx_state.src.rdata); 
     2420                } 
     2421 
    20752422            } else { 
    20762423                /* Ignore 100 (Trying) response, as it doesn't change 
     
    21672514        } 
    21682515 
    2169     } else if (inv->role == PJSIP_ROLE_UAC && 
    2170                tsx->role == PJSIP_ROLE_UAC && 
    2171                tsx->method.id == PJSIP_CANCEL_METHOD) 
    2172     { 
     2516    } else if (tsx->role == PJSIP_ROLE_UAC) { 
    21732517        /* 
    2174          * Handle case when outgoing CANCEL is answered with 481 (Call/ 
     2518         * Handle case when outgoing request is answered with 481 (Call/ 
    21752519         * Transaction Does Not Exist), 408, or when it's timed out. In these 
    21762520         * cases, disconnect session (i.e. dialog usage only). 
     
    22852629                inv_check_sdp_in_incoming_msg(inv, tsx,  
    22862630                                              e->body.tsx_state.src.rdata); 
     2631 
     2632                if (pjsip_100rel_is_reliable(e->body.tsx_state.src.rdata)) { 
     2633                    inv_handle_incoming_reliable_response( 
     2634                        inv, e->body.tsx_state.src.rdata); 
     2635                } 
    22872636            } 
    22882637            break; 
     
    23542703        inv_respond_incoming_cancel(inv, tsx, e->body.tsx_state.src.rdata); 
    23552704 
    2356     } else if (inv->role == PJSIP_ROLE_UAC && 
    2357                tsx->role == PJSIP_ROLE_UAC && 
    2358                tsx->method.id == PJSIP_CANCEL_METHOD) 
     2705    } else if (tsx->role == PJSIP_ROLE_UAS && 
     2706               tsx->state == PJSIP_TSX_STATE_TRYING && 
     2707               pjsip_method_cmp(&tsx->method, &pjsip_update_method)==0) 
    23592708    { 
    23602709        /* 
    2361          * Handle case when outgoing CANCEL is answered with 481 (Call/ 
     2710         * Handle incoming UPDATE 
     2711         */ 
     2712        inv_respond_incoming_update(inv, e->body.tsx_state.src.rdata); 
     2713 
     2714 
     2715    } else if (tsx->role == PJSIP_ROLE_UAC && 
     2716               (tsx->state == PJSIP_TSX_STATE_COMPLETED || 
     2717                tsx->state == PJSIP_TSX_STATE_TERMINATED) && 
     2718               pjsip_method_cmp(&tsx->method, &pjsip_update_method)==0) 
     2719    { 
     2720        /* 
     2721         * Handle response to outgoing UPDATE request. 
     2722         */ 
     2723        inv_handle_update_response(inv, e); 
     2724 
     2725    } else if (tsx->role == PJSIP_ROLE_UAS && 
     2726               tsx->state == PJSIP_TSX_STATE_TRYING && 
     2727               pjsip_method_cmp(&tsx->method, &pjsip_prack_method)==0) 
     2728    { 
     2729        /* 
     2730         * Handle incoming PRACK 
     2731         */ 
     2732        inv_respond_incoming_prack(inv, e->body.tsx_state.src.rdata); 
     2733 
     2734    } else if (tsx->role == PJSIP_ROLE_UAC) { 
     2735        /* 
     2736         * Handle case when outgoing request is answered with 481 (Call/ 
    23622737         * Transaction Does Not Exist), 408, or when it's timed out. In these 
    23632738         * cases, disconnect session (i.e. dialog usage only). 
     
    24672842        if (status != PJ_SUCCESS) return; 
    24682843 
    2469     } 
     2844    } else if (tsx->role == PJSIP_ROLE_UAS && 
     2845               tsx->state == PJSIP_TSX_STATE_TRYING && 
     2846               pjsip_method_cmp(&tsx->method, &pjsip_update_method)==0) 
     2847    { 
     2848        /* 
     2849         * Handle incoming UPDATE 
     2850         */ 
     2851        inv_respond_incoming_update(inv, e->body.tsx_state.src.rdata); 
     2852 
     2853 
     2854    } else if (tsx->role == PJSIP_ROLE_UAC && 
     2855               (tsx->state == PJSIP_TSX_STATE_COMPLETED || 
     2856                tsx->state == PJSIP_TSX_STATE_TERMINATED) && 
     2857               pjsip_method_cmp(&tsx->method, &pjsip_update_method)==0) 
     2858    { 
     2859        /* 
     2860         * Handle response to outgoing UPDATE request. 
     2861         */ 
     2862        inv_handle_update_response(inv, e); 
     2863 
     2864    } else if (tsx->role == PJSIP_ROLE_UAS && 
     2865               tsx->state == PJSIP_TSX_STATE_TRYING && 
     2866               pjsip_method_cmp(&tsx->method, &pjsip_prack_method)==0) 
     2867    { 
     2868        /* 
     2869         * Handle incoming PRACK 
     2870         */ 
     2871        inv_respond_incoming_prack(inv, e->body.tsx_state.src.rdata); 
     2872 
     2873    } else if (tsx->role == PJSIP_ROLE_UAC) { 
     2874        /* 
     2875         * Handle case when outgoing request is answered with 481 (Call/ 
     2876         * Transaction Does Not Exist), 408, or when it's timed out. In these 
     2877         * cases, disconnect session (i.e. dialog usage only). 
     2878         */ 
     2879        if (tsx->status_code == PJSIP_SC_CALL_TSX_DOES_NOT_EXIST || 
     2880            tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT || 
     2881            tsx->status_code == PJSIP_SC_TSX_TIMEOUT || 
     2882            tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR) 
     2883        { 
     2884            inv_set_cause(inv, tsx->status_code, &tsx->status_text); 
     2885            inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
     2886        } 
     2887    } 
     2888 
    24702889} 
    24712890 
     
    27313150            } 
    27323151        } 
    2733     } 
     3152 
     3153    } else if (tsx->role == PJSIP_ROLE_UAS && 
     3154               tsx->state == PJSIP_TSX_STATE_TRYING && 
     3155               pjsip_method_cmp(&tsx->method, &pjsip_update_method)==0) 
     3156    { 
     3157        /* 
     3158         * Handle incoming UPDATE 
     3159         */ 
     3160        inv_respond_incoming_update(inv, e->body.tsx_state.src.rdata); 
     3161 
     3162    } else if (tsx->role == PJSIP_ROLE_UAC && 
     3163               (tsx->state == PJSIP_TSX_STATE_COMPLETED || 
     3164                tsx->state == PJSIP_TSX_STATE_TERMINATED) && 
     3165               pjsip_method_cmp(&tsx->method, &pjsip_update_method)==0) 
     3166    { 
     3167        /* 
     3168         * Handle response to outgoing UPDATE request. 
     3169         */ 
     3170        inv_handle_update_response(inv, e); 
     3171 
     3172    } else if (tsx->role == PJSIP_ROLE_UAS && 
     3173               tsx->state == PJSIP_TSX_STATE_TRYING && 
     3174               pjsip_method_cmp(&tsx->method, &pjsip_prack_method)==0) 
     3175    { 
     3176        /* 
     3177         * Handle strandled incoming PRACK 
     3178         */ 
     3179        inv_respond_incoming_prack(inv, e->body.tsx_state.src.rdata); 
     3180 
     3181    } else if (tsx->role == PJSIP_ROLE_UAC) { 
     3182        /* 
     3183         * Handle case when outgoing request is answered with 481 (Call/ 
     3184         * Transaction Does Not Exist), 408, or when it's timed out. In these 
     3185         * cases, disconnect session (i.e. dialog usage only). 
     3186         */ 
     3187        if (tsx->status_code == PJSIP_SC_CALL_TSX_DOES_NOT_EXIST || 
     3188            tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT || 
     3189            tsx->status_code == PJSIP_SC_TSX_TIMEOUT || 
     3190            tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR) 
     3191        { 
     3192            inv_set_cause(inv, tsx->status_code, &tsx->status_text); 
     3193            inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
     3194        } 
     3195    } 
     3196 
    27343197} 
    27353198 
Note: See TracChangeset for help on using the changeset viewer.