Changeset 1379


Ignore:
Timestamp:
Jun 20, 2007 10:03:46 AM (17 years ago)
Author:
bennylp
Message:

More on ticket #399: a)send full offer on 200/OK response when re-INVITE does not have SDP, b) added on_create_offer() callback, c) handle some error cases

Location:
pjproject/trunk
Files:
1 added
5 edited

Legend:

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

    r1072 r1379  
    5151 *     create_w_local_offer()  +-------------+  send_local_offer() 
    5252 *     ----------------------->| LOCAL_OFFER |<----------------------- 
    53  *    |                        +-------------+                        | 
    54  *    |                               |                               | 
    55  *    |           set_remote_answer() |                               | 
    56  *    |                               V                               | 
    57  * +--+---+                     +-----------+     negotiate()     +------+ 
     53 *    |                        +-------------+______                  | 
     54 *    |                               |             \______ cancel()  | 
     55 *    |           set_remote_answer() |                    \______    | 
     56 *    |                               V                            \  | 
     57 * +--+---+                     +-----------+     negotiate()     +-~----+ 
    5858 * | NULL |                     | WAIT_NEGO |-------------------->| DONE | 
    5959 * +------+                     +-----------+                     +------+ 
     
    173173 * the negotiator state will move to PJMEDIA_SDP_NEG_STATE_DONE. 
    174174 *  
     175 * 
     176 * \subsection sdpneg_cancel_offer Cancelling an Offer 
     177 * 
     178 * In other case, after an offer is generated (negotiator state is in 
     179 * PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER), the answer may not be received, and 
     180 * application wants the negotiator to reset itself to its previous state. 
     181 * Consider this example: 
     182 * 
     183 *  - media has been established, and negotiator state is 
     184 *    PJMEDIA_SDP_NEG_STATE_DONE. 
     185 *  - application generates a new offer for re-INVITE, so in this case 
     186 *    it would either call #pjmedia_sdp_neg_send_local_offer() or 
     187 *    #pjmedia_sdp_neg_modify_local_offer() 
     188 *  - the negotiator state moves to PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER 
     189 *  - the re-INVITE was rejected with an error 
     190 * 
     191 * Since an answer is not received, it is necessary to reset the negotiator 
     192 * state back to PJMEDIA_SDP_NEG_STATE_DONE so that the negotiator can 
     193 * create or receive new offer. 
     194 * 
     195 * This can be accomplished by calling #pjmedia_sdp_neg_cancel_offer(), 
     196 * to reset the negotiator state back to PJMEDIA_SDP_NEG_STATE_DONE. In 
     197 * this case, both active local and active remote will not be modified. 
    175198 * 
    176199 * \subsection sdpneg_create_answer Generating SDP Answer 
     
    599622 
    600623/** 
     624 * Cancel previously sent offer, and move negotiator state back to 
     625 * previous stable state (PJMEDIA_SDP_NEG_STATE_DONE). The negotiator 
     626 * must be in PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER state. 
     627 * 
     628 * @param neg           The negotiator. 
     629 * 
     630 * @return              PJ_SUCCESS or the appropriate error code. 
     631 */ 
     632PJ_DECL(pj_status_t) pjmedia_sdp_neg_cancel_offer(pjmedia_sdp_neg *neg); 
     633 
     634 
     635/** 
    601636 * Negotiate local and remote answer. Before calling this function, the 
    602637 * SDP negotiator must be in PJMEDIA_SDP_NEG_STATE_WAIT_NEGO state. 
  • pjproject/trunk/pjmedia/src/pjmedia/sdp_neg.c

    r1266 r1379  
    986986} 
    987987 
     988/* Cancel offer */ 
     989PJ_DEF(pj_status_t) pjmedia_sdp_neg_cancel_offer(pjmedia_sdp_neg *neg) 
     990{ 
     991    PJ_ASSERT_RETURN(neg, PJ_EINVAL); 
     992 
     993    /* Must be in LOCAL_OFFER state. */ 
     994    PJ_ASSERT_RETURN(neg->state == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER, 
     995                     PJMEDIA_SDPNEG_EINSTATE); 
     996 
     997    /* Reset state to done */ 
     998    neg->state = PJMEDIA_SDP_NEG_STATE_DONE; 
     999 
     1000    /* Clear temporary SDP */ 
     1001    neg->neg_local_sdp = neg->neg_remote_sdp = NULL; 
     1002    neg->has_remote_answer = PJ_FALSE; 
     1003 
     1004    return PJ_SUCCESS; 
     1005} 
     1006 
     1007 
    9881008/* The best bit: SDP negotiation function! */ 
    9891009PJ_DEF(pj_status_t) pjmedia_sdp_neg_negotiate( pj_pool_t *pool, 
  • pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h

    r1319 r1379  
    150150     * This callback is called when the invite session has received  
    151151     * new offer from peer. Application can inspect the remote offer  
    152      * in "offer".  
     152     * in "offer", and set the SDP answer with #pjsip_inv_set_sdp_answer(). 
     153     * When the application sends a SIP message to send the answer,  
     154     * this SDP answer will be negotiated with the offer, and the result 
     155     * will be sent with the SIP message. 
    153156     * 
    154157     * @param inv       The invite session. 
     
    157160    void (*on_rx_offer)(pjsip_inv_session *inv, 
    158161                        const pjmedia_sdp_session *offer); 
     162 
     163    /** 
     164     * This callback is optional, and it is used to ask the application 
     165     * to create a fresh offer, when the invite session has received  
     166     * re-INVITE without offer. This offer then will be sent in the 
     167     * 200/OK response to the re-INVITE request. 
     168     * 
     169     * If application doesn't implement this callback, the invite session 
     170     * will send the currently active SDP as the offer. 
     171     * 
     172     * @param inv       The invite session. 
     173     * @param p_offer   Pointer to receive the SDP offer created by 
     174     *                  application. 
     175     */ 
     176    void (*on_create_offer)(pjsip_inv_session *inv, 
     177                            pjmedia_sdp_session **p_offer); 
    159178 
    160179    /** 
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c

    r1377 r1379  
    12261226     */ 
    12271227 
    1228     if (tsx_inv_data->sdp_done) 
     1228    if (tsx_inv_data->sdp_done) { 
     1229        if (rdata->msg_info.msg->body) { 
     1230            PJ_LOG(4,(inv->obj_name, "SDP negotiation done, message " 
     1231                      "body is ignored")); 
     1232        } 
    12291233        return PJ_SUCCESS; 
     1234    } 
    12301235 
    12311236    /* Check if SDP is present in the message. */ 
     
    13841389                   pjmedia_sdp_neg_has_local_answer(inv->neg) ) 
    13851390        { 
     1391            struct tsx_inv_data *tsx_inv_data; 
     1392 
     1393            /* Get invite session's transaction data */ 
     1394            tsx_inv_data = (struct tsx_inv_data*)  
     1395                           inv->invite_tsx->mod_data[mod_inv.mod.id]; 
    13861396 
    13871397            status = inv_negotiate_sdp(inv); 
     
    13891399                return status; 
    13901400             
     1401            /* Mark this transaction has having SDP offer/answer done. */ 
     1402            tsx_inv_data->sdp_done = 1; 
     1403 
    13911404            status = pjmedia_sdp_neg_get_active_local(inv->neg, &sdp); 
    13921405        } 
     
    25042517                status = process_answer(inv, 200, tdata, NULL); 
    25052518            } else { 
    2506                 const pjmedia_sdp_session *active_sdp; 
    2507                 status = pjmedia_sdp_neg_send_local_offer(dlg->pool,  
    2508                                                           inv->neg,  
    2509                                                           &active_sdp); 
    2510                 if (status == PJ_SUCCESS) { 
    2511                     tdata->msg->body = create_sdp_body(tdata->pool, active_sdp); 
     2519                /* INVITE does not have SDP.  
     2520                 * If on_create_offer() callback is implemented, ask app. 
     2521                 * to generate an offer, otherwise just send active local 
     2522                 * SDP to signal that nothing gets modified. 
     2523                 */ 
     2524                pjmedia_sdp_session *sdp = NULL; 
     2525 
     2526                if (mod_inv.cb.on_create_offer)  { 
     2527                    (*mod_inv.cb.on_create_offer)(inv, &sdp); 
     2528                    if (sdp) { 
     2529                        status = pjmedia_sdp_neg_modify_local_offer(dlg->pool, 
     2530                                                                    inv->neg, 
     2531                                                                    sdp); 
     2532                    } 
     2533                }  
     2534                 
     2535                if (sdp == NULL) { 
     2536                    const pjmedia_sdp_session *active_sdp = NULL; 
     2537                    status = pjmedia_sdp_neg_send_local_offer(dlg->pool,  
     2538                                                              inv->neg,  
     2539                                                              &active_sdp); 
     2540                    if (status == PJ_SUCCESS) 
     2541                        sdp = (pjmedia_sdp_session*) active_sdp; 
     2542                } 
     2543 
     2544                if (sdp) { 
     2545                    tdata->msg->body = create_sdp_body(tdata->pool, sdp); 
    25122546                } 
    25132547            } 
     
    26052639            inv_set_cause(inv, tsx->status_code, &tsx->status_text); 
    26062640            inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
     2641 
     2642        } else if (tsx->status_code >= 300 && tsx->status_code < 700) { 
     2643 
     2644            pjmedia_sdp_neg_state neg_state; 
     2645 
     2646            /* Outgoing INVITE transaction has failed, cancel SDP nego */ 
     2647            neg_state = pjmedia_sdp_neg_get_state(inv->neg); 
     2648            if (neg_state == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) { 
     2649                pjmedia_sdp_neg_cancel_offer(inv->neg); 
     2650            } 
    26072651        } 
    26082652    } 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c

    r1291 r1379  
    5151 
    5252/* 
     53 * Called to generate new offer. 
     54 */ 
     55static void pjsua_call_on_create_offer(pjsip_inv_session *inv, 
     56                                       pjmedia_sdp_session **offer); 
     57 
     58/* 
    5359 * This callback is called when transaction state has changed in INVITE 
    5460 * session. We use this to trap: 
     
    119125    inv_cb.on_media_update = &pjsua_call_on_media_update; 
    120126    inv_cb.on_rx_offer = &pjsua_call_on_rx_offer; 
     127    inv_cb.on_create_offer = &pjsua_call_on_create_offer; 
    121128    inv_cb.on_tsx_state_changed = &pjsua_call_on_tsx_state_changed; 
    122129 
     
    22962303 
    22972304/* 
     2305 * Called to generate new offer. 
     2306 */ 
     2307static void pjsua_call_on_create_offer(pjsip_inv_session *inv, 
     2308                                       pjmedia_sdp_session **offer) 
     2309{ 
     2310    pjsua_call *call; 
     2311    pj_status_t status; 
     2312 
     2313    PJSUA_LOCK(); 
     2314 
     2315    call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id]; 
     2316 
     2317    /* See if we've put call on hold. */ 
     2318    if (call->media_st == PJSUA_CALL_MEDIA_LOCAL_HOLD) { 
     2319        PJ_LOG(4,(THIS_FILE,  
     2320                  "Call %d: call is on-hold locally, creating inactive SDP ", 
     2321                  call->index)); 
     2322        status = create_inactive_sdp( call, offer ); 
     2323    } else { 
     2324 
     2325        PJ_LOG(4,(THIS_FILE, "Call %d: asked to send a new offer", 
     2326                  call->index)); 
     2327 
     2328        /* Init media channel */ 
     2329        status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC); 
     2330        if (status != PJ_SUCCESS) { 
     2331            pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
     2332            PJSUA_UNLOCK(); 
     2333            return; 
     2334        } 
     2335 
     2336        status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, offer); 
     2337    } 
     2338 
     2339    if (status != PJ_SUCCESS) { 
     2340        pjsua_perror(THIS_FILE, "Unable to create local SDP", status); 
     2341        PJSUA_UNLOCK(); 
     2342        return; 
     2343    } 
     2344 
     2345 
     2346    PJSUA_UNLOCK(); 
     2347} 
     2348 
     2349 
     2350/* 
    22982351 * Callback called by event framework when the xfer subscription state 
    22992352 * has changed. 
Note: See TracChangeset for help on using the changeset viewer.