Changeset 4562


Ignore:
Timestamp:
Jul 15, 2013 4:23:31 AM (11 years ago)
Author:
ming
Message:

Re #817: Initial work for allowing application to respond to re-INVITE manually.

Patches integrated in this fix (with some modifications for adjustment to the current trunk):

  • sip_inv-on_rx_reinvite.patch


Move the place where to call the callback so the callback will still be called when the re-invite contains no SDP

  • sdp_neg_cancel_remote_offer


pjmedia_sdp_neg_cancel_remote_offer() is no longer necessary since pjmedia_sdp_neg_cancel_offer() can already handle that. Only integrate the chart for sdp negotiation doc.

  • sip_inv-terminate-reinvite-tsx-on-cancel
  • sip_inv-cancel_sdp_neg_on_sending_negative_reply_to_reinvite
  • pjsip-allow_cancel_reinvite
Location:
pjproject/trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia/sdp_neg.h

    r4554 r4562  
    5353 *     ----------------------->| LOCAL_OFFER |<----------------------- 
    5454 *    |                        +-------------+______                  | 
    55  *    |                               |             \______ cancel()  | 
    56  *    |           set_remote_answer() |                    \______    | 
    57  *    |                               V                            \  | 
     55 *    |                               |             \_____________    | 
     56 *    |           set_remote_answer() |           cancel_offer()  \   | 
     57 *    |                               V                            v  | 
    5858 * +--+---+                     +-----------+     negotiate()     +-~----+ 
    5959 * | NULL |                     | WAIT_NEGO |-------------------->| DONE | 
    6060 * +------+                     +-----------+                     +------+ 
    61  *    |                               A                               | 
    62  *    |            set_local_answer() |                               | 
    63  *    |                               |                               | 
     61 *    |                               A      ______________________^  | 
     62 *    |            set_local_answer() |     /     cancel_offer()      | 
     63 *    |                               |    /                          | 
    6464 *    |                        +--------------+   set_remote_offer()  | 
    6565 *     ----------------------->| REMOTE_OFFER |<---------------------- 
  • pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h

    r4556 r4562  
    160160    void (*on_rx_offer)(pjsip_inv_session *inv, 
    161161                        const pjmedia_sdp_session *offer); 
     162 
     163    /** 
     164     * This callback is optional, and is called when the invite session has 
     165     * received a re-INVITE from the peer. It will be called after 
     166     * on_rx_offer() callback and works only for re-INVITEs. It allows more 
     167     * fine-grained control over the response to a re-INVITE, e.g. sending 
     168     * a provisional response first. Application can return PJ_SUCCESS and 
     169     * send a reply using the function #pjsip_inv_initial_answer() or 
     170     * #pjsip_inv_answer(), as with the initial INVITE. If application 
     171     * returns non-PJ_SUCCESS, it needs to set the SDP answer with 
     172     * #pjsip_inv_set_sdp_answer() and the re-INVITE will be answered 
     173     * automatically. 
     174     * 
     175     * @param inv       The invite session. 
     176     * @param offer     Remote offer. 
     177     * @param rdata     The received re-INVITE request. 
     178     * 
     179     * @return          - PJ_SUCCESS: application will answer the re-INVITE 
     180     *                    manually 
     181     *                  - non-PJ_SUCCESS: answer the re-INVITE automatically 
     182     *                    using the SDP set via #pjsip_inv_set_sdp_answer() 
     183     */ 
     184    pj_status_t (*on_rx_reinvite)(pjsip_inv_session *inv, 
     185                                  const pjmedia_sdp_session *offer, 
     186                                  pjsip_rx_data *rdata); 
    162187 
    163188    /** 
     
    699724 
    700725/** 
    701  * Create a response message to the initial INVITE request. This function 
    702  * can only be called for the initial INVITE request, as subsequent 
    703  * re-INVITE request will be answered automatically. 
     726 * Create a response message to an INVITE request. 
    704727 * 
    705728 * @param inv           The UAS invite session. 
     
    798821 
    799822 
     823/** 
     824 * Create a CANCEL request for an ongoing re-INVITE transaction. If no 
     825 * provisional response has been received, the function will not create 
     826 * CANCEL request (the function will return PJ_SUCCESS but the \a p_tdata 
     827 * will contain NULL) because we cannot send CANCEL before receiving 
     828 * provisional response. If then a provisional response is received, 
     829 * the invite session will send CANCEL automatically. 
     830 * 
     831 * @param inv           The invite session. 
     832 * @param p_tdata       Pointer to receive the message to be created. Note 
     833 *                      that it's possible to receive NULL here while the 
     834 *                      function returns PJ_SUCCESS, see the description. 
     835 * 
     836 * @return              PJ_SUCCESS if termination is initiated. 
     837 */ 
     838PJ_DECL(pj_status_t) pjsip_inv_cancel_reinvite( pjsip_inv_session *inv, 
     839                                                pjsip_tx_data **p_tdata ); 
     840 
    800841 
    801842/** 
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c

    r4556 r4562  
    18361836                PJMEDIA_SDP_NEG_STATE_WAIT_NEGO) 
    18371837        { 
     1838            if (mod_inv.cb.on_rx_reinvite && inv->notify && 
     1839                msg->type == PJSIP_REQUEST_MSG && 
     1840                msg->line.req.method.id == PJSIP_INVITE_METHOD) 
     1841            { 
     1842                /* Do not return failure first, allow the application 
     1843                 * to set the answer in the on_rx_reinvite() callback. 
     1844                 */ 
     1845                return PJ_SUCCESS; 
     1846            } 
    18381847            return PJ_EINVALIDOP; 
    18391848        } 
     
    19731982    } 
    19741983 
     1984    /* Cancel SDP negotiation if this is a negative reply to a re-INVITE */ 
     1985    if (st_code >= 300 && inv->neg != NULL && 
     1986        inv->state == PJSIP_INV_STATE_CONFIRMED) 
     1987    { 
     1988        pjmedia_sdp_neg_state neg_state; 
     1989        neg_state = pjmedia_sdp_neg_get_state(inv->neg); 
     1990        if (neg_state == PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER) { 
     1991            pjmedia_sdp_neg_cancel_offer(inv->neg); 
     1992        } 
     1993    } 
    19751994 
    19761995    return PJ_SUCCESS; 
     
    20532072 
    20542073/* 
    2055  * Answer initial INVITE 
    2056  * Re-INVITE will be answered automatically, and will not use this function. 
     2074 * Answer INVITE request. 
    20572075 */  
    20582076PJ_DEF(pj_status_t) pjsip_inv_answer(   pjsip_inv_session *inv, 
     
    22772295 
    22782296    pj_log_pop_indent(); 
     2297    return PJ_SUCCESS; 
     2298} 
     2299 
     2300/* 
     2301 * Cancel re-INVITE transaction. 
     2302 */ 
     2303PJ_DEF(pj_status_t) pjsip_inv_cancel_reinvite( pjsip_inv_session *inv, 
     2304                                               pjsip_tx_data **p_tdata ) 
     2305{ 
     2306    pjsip_tx_data *tdata; 
     2307    pj_status_t status; 
     2308 
     2309    /* Verify arguments. */ 
     2310    PJ_ASSERT_RETURN(inv && p_tdata, PJ_EINVAL); 
     2311     
     2312    pj_log_push_indent(); 
     2313 
     2314    /* Create appropriate message. */ 
     2315    switch (inv->state) { 
     2316    case PJSIP_INV_STATE_CONFIRMED: 
     2317        /* MUST have the original UAC INVITE transaction  */ 
     2318        PJ_ASSERT_RETURN(inv->invite_tsx != NULL, PJ_EBUG); 
     2319 
     2320        /* CANCEL should only be called when we have received a 
     2321         * provisional response. 
     2322         */ 
     2323        if (inv->invite_tsx->status_code < 100) { 
     2324            inv->cancelling = PJ_TRUE; 
     2325            inv->pending_cancel = PJ_TRUE; 
     2326            *p_tdata = NULL; 
     2327            PJ_LOG(4, (inv->obj_name, "Delaying CANCEL since no " 
     2328                       "provisional response is received yet")); 
     2329            pj_log_pop_indent(); 
     2330            return PJ_SUCCESS; 
     2331        } 
     2332 
     2333        status = pjsip_endpt_create_cancel(inv->dlg->endpt,  
     2334                                           inv->invite_tsx->last_tx, 
     2335                                           &tdata); 
     2336        if (status != PJ_SUCCESS) { 
     2337            pj_log_pop_indent(); 
     2338            return status; 
     2339        } 
     2340        break; 
     2341 
     2342    default: 
     2343        /* We cannot send CANCEL to a re-INVITE if the INVITE session is 
     2344         * not confirmed. 
     2345         */ 
     2346        pj_log_pop_indent(); 
     2347        return PJ_EINVALIDOP; 
     2348    } 
     2349 
     2350    pj_log_pop_indent(); 
     2351 
     2352    *p_tdata = tdata; 
    22792353    return PJ_SUCCESS; 
    22802354} 
     
    40834157 
    40844158        /* 
    4085          * Handle strandled incoming CANCEL. 
    4086          */ 
    4087         pjsip_rx_data *rdata = e->body.tsx_state.src.rdata; 
    4088         pjsip_tx_data *tdata; 
    4089         pj_status_t status; 
    4090  
    4091         status = pjsip_dlg_create_response(dlg, rdata, 200, NULL, &tdata); 
    4092         if (status != PJ_SUCCESS) return; 
    4093  
    4094         status = pjsip_dlg_send_response(dlg, tsx, tdata); 
    4095         if (status != PJ_SUCCESS) return; 
     4159         * Handle strandled incoming CANCEL or CANCEL for re-INVITE 
     4160         */ 
     4161        inv_respond_incoming_cancel(inv, tsx, e); 
    40964162 
    40974163    } else if (tsx->role == PJSIP_ROLE_UAS && 
     
    42294295            pjsip_tx_data *tdata; 
    42304296            pj_status_t status; 
    4231             pjsip_rdata_sdp_info *sdp_info; 
     4297            pjsip_rdata_sdp_info *sdp_info = NULL; 
    42324298            pjsip_status_code st_code; 
    42334299 
     
    43024368            status = inv_check_sdp_in_incoming_msg(inv, tsx, rdata); 
    43034369 
     4370            if (status == PJ_SUCCESS && mod_inv.cb.on_rx_reinvite && 
     4371                inv->notify) 
     4372            { 
     4373                sdp_info = pjsip_rdata_get_sdp_info(rdata); 
     4374                if ((*mod_inv.cb.on_rx_reinvite) 
     4375                        (inv, sdp_info->sdp, rdata) == PJ_SUCCESS) 
     4376                { 
     4377                    /* Application will send its own response. 
     4378                     * Our job is done. */ 
     4379                    return; 
     4380                } 
     4381 
     4382                /* If application lets us answer the re-INVITE, 
     4383                 * application must set the SDP answer with 
     4384                 * #pjsip_inv_set_sdp_answer(). 
     4385                 */ 
     4386                if (pjmedia_sdp_neg_get_state(inv->neg) != 
     4387                    PJMEDIA_SDP_NEG_STATE_WAIT_NEGO) 
     4388                { 
     4389                    status = PJ_EINVALIDOP; 
     4390                } 
     4391            } 
     4392 
    43044393            if (status != PJ_SUCCESS) { 
    43054394 
     
    43434432             * Otherwise generate offer from local active SDP. 
    43444433             */ 
    4345             sdp_info = pjsip_rdata_get_sdp_info(rdata); 
     4434            if (!sdp_info) 
     4435                sdp_info = pjsip_rdata_get_sdp_info(rdata); 
    43464436            if (sdp_info->sdp != NULL) { 
    43474437                status = process_answer(inv, 200, tdata, NULL); 
     
    44604550            inv->invite_tsx = tsx; 
    44614551 
     4552        } else if (tsx->state == PJSIP_TSX_STATE_PROCEEDING) { 
     4553             
     4554            /* CANCEL the re-INVITE if necessary */ 
     4555            if (inv->pending_cancel) { 
     4556                pj_status_t status; 
     4557                pjsip_tx_data *cancel; 
     4558 
     4559                inv->pending_cancel = PJ_FALSE; 
     4560 
     4561                status = pjsip_inv_cancel_reinvite(inv, &cancel); 
     4562                if (status == PJ_SUCCESS && cancel) 
     4563                    status = pjsip_inv_send_msg(inv, cancel); 
     4564            } 
     4565 
    44624566        } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED && 
    44634567                   tsx->status_code/100 == 2)  
Note: See TracChangeset for help on using the changeset viewer.