Changeset 1598 for pjproject


Ignore:
Timestamp:
Nov 25, 2007 4:40:07 AM (17 years ago)
Author:
bennylp
Message:

Ticket #416: Allow application to handle sending ACK manually

Location:
pjproject/trunk/pjsip
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h

    r1477 r1598  
    191191    void (*on_media_update)(pjsip_inv_session *inv_ses,  
    192192                            pj_status_t status); 
     193 
     194    /** 
     195     * This callback is called when the framework needs to send 
     196     * ACK request after it receives incoming  2xx response for  
     197     * INVITE. It allows application to manually handle the  
     198     * transmission of ACK request, which is required by some 3PCC 
     199     * scenarios. If this callback is not implemented, the framework 
     200     * will handle the ACK transmission automatically. 
     201     * 
     202     * When this callback is overridden, application may delay the 
     203     * sending of the ACK request (for example, when it needs to  
     204     * wait for answer from the other call leg, in 3PCC scenarios).  
     205     * 
     206     * Application creates the ACK request 
     207     * 
     208     * Once it has sent the ACK request, the framework will keep  
     209     * this ACK request in the cache. Subsequent receipt of 2xx response 
     210     * will not cause this callback to be called, and instead automatic 
     211     * retransmission of this ACK request from the cache will be done 
     212     * by the framework. 
     213     * 
     214     * This callback is optional. 
     215     */ 
     216    void (*on_send_ack)(pjsip_inv_session *inv, pjsip_rx_data *rdata); 
    193217 
    194218} pjsip_inv_callback; 
     
    588612 
    589613/** 
     614 * Create an ACK request. Normally ACK request transmission is handled 
     615 * by the framework. Application only needs to use this function if it 
     616 * handles the ACK transmission manually, by overriding \a on_send_ack() 
     617 * callback in #pjsip_inv_callback. 
     618 * 
     619 * Note that if the invite session has a pending offer to be answered  
     620 * (for example when the last 2xx response to INVITE contains an offer),  
     621 * application MUST have set the SDP answer with #pjsip_create_sdp_body() 
     622 * prior to creating the ACK request. In this case, the ACK request 
     623 * will be added with SDP message body. 
     624 * 
     625 * @param inv           The invite session. 
     626 * @param cseq          Mandatory argument to specify the CSeq of the 
     627 *                      ACK request. This value MUST match the value 
     628 *                      of the INVITE transaction to be acknowledged. 
     629 * @param p_tdata       Pointer to receive the ACK request message to 
     630 *                      be created. 
     631 * 
     632 * @return              PJ_SUCCESS if ACK request has been created. 
     633 */ 
     634PJ_DECL(pj_status_t) pjsip_inv_create_ack(pjsip_inv_session *inv, 
     635                                          int cseq, 
     636                                          pjsip_tx_data **p_tdata); 
     637 
     638 
     639/** 
    590640 * Send request or response message in tdata.  
    591641 * 
     
    603653 
    604654 
    605  
    606655/** 
    607656 * Get the invite session for the dialog, if any. 
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c

    r1597 r1598  
    273273    { 
    274274        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]; 
     275        struct tsx_inv_data dummy; 
     276 
     277        /* Get invite session's transaction data. 
     278         * Note that tsx may be NULL, for example when application sends 
     279         * delayed ACK request (at this time, the original INVITE  
     280         * transaction may have been destroyed. 
     281         */ 
     282        if (tsx) { 
     283            tsx_inv_data = (struct tsx_inv_data*)tsx->mod_data[mod_inv.mod.id]; 
     284        } else { 
     285            tsx_inv_data = &dummy; 
     286            pj_bzero(&dummy, sizeof(dummy)); 
     287            dummy.inv = inv; 
     288        } 
    278289 
    279290        status = inv_negotiate_sdp(inv); 
     
    302313 * Send ACK for 2xx response. 
    303314 */ 
    304 static pj_status_t inv_send_ack(pjsip_inv_session *inv, pjsip_rx_data *rdata) 
    305 { 
     315static pj_status_t inv_send_ack(pjsip_inv_session *inv, pjsip_event *e) 
     316{ 
     317    pjsip_rx_data *rdata; 
    306318    pj_status_t status; 
     319 
     320    if (e->type == PJSIP_EVENT_TSX_STATE) 
     321        rdata = e->body.tsx_state.src.rdata; 
     322    else if (e->type == PJSIP_EVENT_RX_MSG) 
     323        rdata = e->body.rx_msg.rdata; 
     324    else { 
     325        pj_assert(!"Unsupported event type"); 
     326        return PJ_EBUG; 
     327    } 
    307328 
    308329    PJ_LOG(5,(inv->obj_name, "Received %s, sending ACK", 
     
    311332    /* Check if we have cached ACK request */ 
    312333    if (inv->last_ack && rdata->msg_info.cseq->cseq == inv->last_ack_cseq) { 
     334 
    313335        pjsip_tx_data_add_ref(inv->last_ack); 
     336 
     337    } else if (mod_inv.cb.on_send_ack) { 
     338        /* If application handles ACK transmission manually, just notify the 
     339         * callback 
     340         */ 
     341        PJ_LOG(5,(inv->obj_name, "Received %s, notifying application callback", 
     342                  pjsip_rx_data_get_info(rdata))); 
     343 
     344        (*mod_inv.cb.on_send_ack)(inv, rdata); 
     345        return PJ_SUCCESS; 
     346 
    314347    } else { 
    315         const 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); 
     348        status = pjsip_inv_create_ack(inv, rdata->msg_info.cseq->cseq, 
     349                                      &inv->last_ack); 
    343350    } 
    344351 
     
    349356        pj_assert(!"Unable to send ACK!"); 
    350357        return status; 
     358    } 
     359 
     360 
     361    /* Set state to CONFIRMED (if we're not in CONFIRMED yet) */ 
     362    if (inv->state != PJSIP_INV_STATE_CONFIRMED) { 
     363        inv_set_state(inv, PJSIP_INV_STATE_CONFIRMED, e); 
    351364    } 
    352365 
     
    474487        inv->invite_tsx == NULL)  
    475488    { 
    476  
    477         inv_send_ack(inv, rdata); 
     489        pjsip_event e; 
     490 
     491        PJSIP_EVENT_INIT_RX_MSG(e, rdata); 
     492        inv_send_ack(inv, &e); 
    478493        return PJ_TRUE; 
    479494 
     
    19671982 
    19681983    return status; 
     1984} 
     1985 
     1986/* 
     1987 * Create an ACK request. 
     1988 */ 
     1989PJ_DEF(pj_status_t) pjsip_inv_create_ack(pjsip_inv_session *inv, 
     1990                                         int cseq, 
     1991                                         pjsip_tx_data **p_tdata) 
     1992{ 
     1993    const pjmedia_sdp_session *sdp = NULL; 
     1994    pj_status_t status; 
     1995 
     1996    PJ_ASSERT_RETURN(inv && p_tdata, PJ_EINVAL); 
     1997 
     1998    /* Lock dialog. */ 
     1999    pjsip_dlg_inc_lock(inv->dlg); 
     2000 
     2001    /* Destroy last_ack */ 
     2002    if (inv->last_ack) { 
     2003        pjsip_tx_data_dec_ref(inv->last_ack); 
     2004        inv->last_ack = NULL; 
     2005    } 
     2006 
     2007    /* Create new ACK request */ 
     2008    status = pjsip_dlg_create_request(inv->dlg, pjsip_get_ack_method(),  
     2009                                      cseq, &inv->last_ack); 
     2010    if (status != PJ_SUCCESS) { 
     2011        pjsip_dlg_dec_lock(inv->dlg); 
     2012        return status; 
     2013    } 
     2014 
     2015    /* See if we have pending SDP answer to send */ 
     2016    sdp = inv_has_pending_answer(inv, inv->invite_tsx); 
     2017    if (sdp) { 
     2018        inv->last_ack->msg->body = create_sdp_body(inv->last_ack->pool, sdp); 
     2019    } 
     2020 
     2021    /* Keep this for subsequent response retransmission */ 
     2022    inv->last_ack_cseq = cseq; 
     2023    pjsip_tx_data_add_ref(inv->last_ack); 
     2024 
     2025    /* Done */ 
     2026    *p_tdata = inv->last_ack; 
     2027 
     2028    /* Unlock dialog. */ 
     2029    pjsip_dlg_dec_lock(inv->dlg); 
     2030 
     2031    return PJ_SUCCESS; 
    19692032} 
    19702033 
     
    25482611                pj_assert(e->body.tsx_state.type == PJSIP_EVENT_RX_MSG); 
    25492612 
    2550                 inv_send_ack(inv, e->body.tsx_state.src.rdata); 
    2551                 inv_set_state(inv, PJSIP_INV_STATE_CONFIRMED, e); 
    2552  
     2613                inv_send_ack(inv, e); 
    25532614 
    25542615            } else  { 
     
    27272788                    pj_assert(e->body.tsx_state.type == PJSIP_EVENT_RX_MSG); 
    27282789 
    2729                     inv_send_ack(inv, e->body.tsx_state.src.rdata); 
    2730                     inv_set_state(inv, PJSIP_INV_STATE_CONFIRMED, e); 
     2790                    inv_send_ack(inv, e); 
    27312791                } 
    27322792 
     
    31683228 
    31693229            /* Send ACK */ 
    3170             inv_send_ack(inv, e->body.tsx_state.src.rdata); 
     3230            inv_send_ack(inv, e); 
    31713231 
    31723232        } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED && 
Note: See TracChangeset for help on using the changeset viewer.