Ignore:
Timestamp:
Sep 21, 2011 10:20:01 AM (13 years ago)
Author:
ming
Message:

Re #1266: Asynchronous media transport creation

  • Add feature that allows ICE media transport to be created asynchronously.
  • Add new callback, e.g. on_call_media_transport_state(call_id, state_struct) to report media transport status.
  • Handle outgoing calls while creating media transport asynchronously.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c

    r3753 r3763  
    332332*/ 
    333333 
     334static pj_status_t 
     335on_make_call_med_tp_complete(pjsua_call_id call_id, 
     336                             const pjsua_med_tp_state_info *info) 
     337{ 
     338    pjmedia_sdp_session *offer; 
     339    pjsip_inv_session *inv = NULL; 
     340    pjsua_call *call = &pjsua_var.calls[call_id]; 
     341    pjsua_acc *acc = &pjsua_var.acc[call->acc_id]; 
     342    pjsip_dialog *dlg = call->async_call.dlg; 
     343    unsigned options = call->async_call.call_var.out_call.options; 
     344    pjsip_tx_data *tdata; 
     345    pj_status_t status = (info? info->status: PJ_SUCCESS); 
     346 
     347    PJSUA_LOCK(); 
     348 
     349    /* Increment the dialog's lock otherwise when invite session creation 
     350     * fails the dialog will be destroyed prematurely. 
     351     */ 
     352    pjsip_dlg_inc_lock(dlg); 
     353 
     354    if (status != PJ_SUCCESS) { 
     355        pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
     356        goto on_error; 
     357    } 
     358 
     359    /* Create offer */ 
     360    status = pjsua_media_channel_create_sdp(call->index, dlg->pool, NULL, 
     361                                            &offer, NULL); 
     362    if (status != PJ_SUCCESS) { 
     363        pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
     364        goto on_error; 
     365    } 
     366 
     367    /* Create the INVITE session: */ 
     368    options |= PJSIP_INV_SUPPORT_100REL; 
     369    if (acc->cfg.require_100rel) 
     370        options |= PJSIP_INV_REQUIRE_100REL; 
     371    if (acc->cfg.use_timer != PJSUA_SIP_TIMER_INACTIVE) { 
     372        options |= PJSIP_INV_SUPPORT_TIMER; 
     373        if (acc->cfg.use_timer == PJSUA_SIP_TIMER_REQUIRED) 
     374            options |= PJSIP_INV_REQUIRE_TIMER; 
     375        else if (acc->cfg.use_timer == PJSUA_SIP_TIMER_ALWAYS) 
     376            options |= PJSIP_INV_ALWAYS_USE_TIMER; 
     377    } 
     378 
     379    status = pjsip_inv_create_uac( dlg, offer, options, &inv); 
     380    if (status != PJ_SUCCESS) { 
     381        pjsua_perror(THIS_FILE, "Invite session creation failed", status); 
     382        goto on_error; 
     383    } 
     384 
     385    /* Init Session Timers */ 
     386    status = pjsip_timer_init_session(inv, &acc->cfg.timer_setting); 
     387    if (status != PJ_SUCCESS) { 
     388        pjsua_perror(THIS_FILE, "Session Timer init failed", status); 
     389        goto on_error; 
     390    } 
     391 
     392    /* Create and associate our data in the session. */ 
     393    call->inv = inv; 
     394 
     395    dlg->mod_data[pjsua_var.mod.id] = call; 
     396    inv->mod_data[pjsua_var.mod.id] = call; 
     397 
     398    /* If account is locked to specific transport, then lock dialog 
     399     * to this transport too. 
     400     */ 
     401    if (acc->cfg.transport_id != PJSUA_INVALID_ID) { 
     402        pjsip_tpselector tp_sel; 
     403 
     404        pjsua_init_tpselector(acc->cfg.transport_id, &tp_sel); 
     405        pjsip_dlg_set_transport(dlg, &tp_sel); 
     406    } 
     407 
     408    /* Set dialog Route-Set: */ 
     409    if (!pj_list_empty(&acc->route_set)) 
     410        pjsip_dlg_set_route_set(dlg, &acc->route_set); 
     411 
     412 
     413    /* Set credentials: */ 
     414    if (acc->cred_cnt) { 
     415        pjsip_auth_clt_set_credentials( &dlg->auth_sess,  
     416                                        acc->cred_cnt, acc->cred); 
     417    } 
     418 
     419    /* Set authentication preference */ 
     420    pjsip_auth_clt_set_prefs(&dlg->auth_sess, &acc->cfg.auth_pref); 
     421 
     422    /* Create initial INVITE: */ 
     423 
     424    status = pjsip_inv_invite(inv, &tdata); 
     425    if (status != PJ_SUCCESS) { 
     426        pjsua_perror(THIS_FILE, "Unable to create initial INVITE request",  
     427                     status); 
     428        goto on_error; 
     429    } 
     430 
     431 
     432    /* Add additional headers etc */ 
     433 
     434    pjsua_process_msg_data( tdata, 
     435                            call->async_call.call_var.out_call.msg_data); 
     436 
     437    /* Must increment call counter now */ 
     438    ++pjsua_var.call_cnt; 
     439 
     440    /* Send initial INVITE: */ 
     441 
     442    status = pjsip_inv_send_msg(inv, tdata); 
     443    if (status != PJ_SUCCESS) { 
     444        pjsua_perror(THIS_FILE, "Unable to send initial INVITE request",  
     445                     status); 
     446 
     447        /* Upon failure to send first request, the invite  
     448         * session would have been cleared. 
     449         */ 
     450        inv = NULL; 
     451        goto on_error; 
     452    } 
     453 
     454    /* Done. */ 
     455 
     456    pjsip_dlg_dec_lock(dlg); 
     457    PJSUA_UNLOCK(); 
     458 
     459    return PJ_SUCCESS; 
     460 
     461on_error: 
     462    if (dlg) { 
     463        /* This may destroy the dialog */ 
     464        pjsip_dlg_dec_lock(dlg); 
     465    } 
     466 
     467    if (inv != NULL) { 
     468        pjsip_inv_terminate(inv, PJSIP_SC_OK, PJ_FALSE); 
     469    } 
     470 
     471    if (call_id != -1) { 
     472        reset_call(call_id); 
     473        pjsua_media_channel_deinit(call_id); 
     474    } 
     475 
     476    PJSUA_UNLOCK(); 
     477    return status; 
     478} 
     479 
    334480 
    335481/* 
     
    345491    pj_pool_t *tmp_pool = NULL; 
    346492    pjsip_dialog *dlg = NULL; 
    347     pjmedia_sdp_session *offer; 
    348     pjsip_inv_session *inv = NULL; 
    349493    pjsua_acc *acc; 
    350494    pjsua_call *call; 
    351495    int call_id = -1; 
    352496    pj_str_t contact; 
    353     pjsip_tx_data *tdata; 
    354497    pj_status_t status; 
    355498 
     
    377520        pjsua_var.null_snd==NULL && !pjsua_var.no_snd)  
    378521    { 
    379         pj_status_t status; 
    380  
    381522        status = pjsua_set_snd_dev(pjsua_var.cap_dev, pjsua_var.play_dev); 
    382523        if (status != PJ_SUCCESS) 
     
    463604     * fails the dialog will be destroyed prematurely. 
    464605     */ 
    465     pjsip_dlg_inc_lock(dlg); 
     606//    pjsip_dlg_inc_lock(dlg); 
    466607 
    467608    /* Calculate call's secure level */ 
    468609    call->secure_level = get_secure_level(acc_id, dest_uri); 
     610 
     611    /* Attach user data */ 
     612    call->user_data = user_data; 
     613     
     614    call->async_call.call_var.out_call.options = options; 
     615    call->async_call.call_var.out_call.msg_data = pjsua_msg_data_clone( 
     616                                                      dlg->pool, msg_data); 
     617    call->async_call.dlg = dlg; 
    469618 
    470619    /* Init media channel */ 
    471620    status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC,  
    472621                                      call->secure_level, dlg->pool, 
    473                                       NULL, NULL); 
    474     if (status != PJ_SUCCESS) { 
     622                                      NULL, NULL, PJ_TRUE, 
     623                                      (pjsua_med_tp_state_cb) 
     624                                      &on_make_call_med_tp_complete); 
     625    if (status == PJ_SUCCESS) { 
     626        status = on_make_call_med_tp_complete(call->index, NULL); 
     627        if (status != PJ_SUCCESS) 
     628            goto on_error; 
     629    } else if (status != PJ_EPENDING) { 
    475630        pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
    476631        goto on_error; 
    477632    } 
    478633 
    479     /* Create offer */ 
    480     status = pjsua_media_channel_create_sdp(call->index, dlg->pool, NULL, 
    481                                             &offer, NULL); 
    482     if (status != PJ_SUCCESS) { 
    483         pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
    484         goto on_error; 
    485     } 
    486  
    487     /* Create the INVITE session: */ 
    488     options |= PJSIP_INV_SUPPORT_100REL; 
    489     if (acc->cfg.require_100rel) 
    490         options |= PJSIP_INV_REQUIRE_100REL; 
    491     if (acc->cfg.use_timer != PJSUA_SIP_TIMER_INACTIVE) { 
    492         options |= PJSIP_INV_SUPPORT_TIMER; 
    493         if (acc->cfg.use_timer == PJSUA_SIP_TIMER_REQUIRED) 
    494             options |= PJSIP_INV_REQUIRE_TIMER; 
    495         else if (acc->cfg.use_timer == PJSUA_SIP_TIMER_ALWAYS) 
    496             options |= PJSIP_INV_ALWAYS_USE_TIMER; 
    497     } 
    498  
    499     status = pjsip_inv_create_uac( dlg, offer, options, &inv); 
    500     if (status != PJ_SUCCESS) { 
    501         pjsua_perror(THIS_FILE, "Invite session creation failed", status); 
    502         goto on_error; 
    503     } 
    504  
    505     /* Init Session Timers */ 
    506     status = pjsip_timer_init_session(inv, &acc->cfg.timer_setting); 
    507     if (status != PJ_SUCCESS) { 
    508         pjsua_perror(THIS_FILE, "Session Timer init failed", status); 
    509         goto on_error; 
    510     } 
    511  
    512     /* Create and associate our data in the session. */ 
    513     call->inv = inv; 
    514  
    515     dlg->mod_data[pjsua_var.mod.id] = call; 
    516     inv->mod_data[pjsua_var.mod.id] = call; 
    517  
    518     /* Attach user data */ 
    519     call->user_data = user_data; 
    520  
    521     /* If account is locked to specific transport, then lock dialog 
    522      * to this transport too. 
    523      */ 
    524     if (acc->cfg.transport_id != PJSUA_INVALID_ID) { 
    525         pjsip_tpselector tp_sel; 
    526  
    527         pjsua_init_tpselector(acc->cfg.transport_id, &tp_sel); 
    528         pjsip_dlg_set_transport(dlg, &tp_sel); 
    529     } 
    530  
    531     /* Set dialog Route-Set: */ 
    532     if (!pj_list_empty(&acc->route_set)) 
    533         pjsip_dlg_set_route_set(dlg, &acc->route_set); 
    534  
    535  
    536     /* Set credentials: */ 
    537     if (acc->cred_cnt) { 
    538         pjsip_auth_clt_set_credentials( &dlg->auth_sess,  
    539                                         acc->cred_cnt, acc->cred); 
    540     } 
    541  
    542     /* Set authentication preference */ 
    543     pjsip_auth_clt_set_prefs(&dlg->auth_sess, &acc->cfg.auth_pref); 
    544  
    545     /* Create initial INVITE: */ 
    546  
    547     status = pjsip_inv_invite(inv, &tdata); 
    548     if (status != PJ_SUCCESS) { 
    549         pjsua_perror(THIS_FILE, "Unable to create initial INVITE request",  
    550                      status); 
    551         goto on_error; 
    552     } 
    553  
    554  
    555     /* Add additional headers etc */ 
    556  
    557     pjsua_process_msg_data( tdata, msg_data); 
    558  
    559     /* Must increment call counter now */ 
    560     ++pjsua_var.call_cnt; 
    561  
    562     /* Send initial INVITE: */ 
    563  
    564     status = pjsip_inv_send_msg(inv, tdata); 
    565     if (status != PJ_SUCCESS) { 
    566         pjsua_perror(THIS_FILE, "Unable to send initial INVITE request",  
    567                      status); 
    568  
    569         /* Upon failure to send first request, the invite  
    570          * session would have been cleared. 
    571          */ 
    572         inv = NULL; 
    573         goto on_error; 
    574     } 
    575  
    576634    /* Done. */ 
    577635 
     
    579637        *p_call_id = call_id; 
    580638 
    581     pjsip_dlg_dec_lock(dlg); 
    582639    pj_pool_release(tmp_pool); 
    583640    PJSUA_UNLOCK(); 
     
    590647on_error: 
    591648    if (dlg) { 
     649        pjsip_dlg_inc_lock(dlg); 
    592650        /* This may destroy the dialog */ 
    593651        pjsip_dlg_dec_lock(dlg); 
    594     } 
    595  
    596     if (inv != NULL) { 
    597         pjsip_inv_terminate(inv, PJSIP_SC_OK, PJ_FALSE); 
    598652    } 
    599653 
     
    816870                                      rdata->tp_info.pool, 
    817871                                      offer, 
    818                                       &sip_err_code); 
     872                                      &sip_err_code, PJ_FALSE, 
     873                                      NULL); 
    819874    if (status != PJ_SUCCESS) { 
    820875        pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
     
    833888        goto on_return; 
    834889    } 
    835  
    836890 
    837891    /* Verify that we can handle the request. */ 
     
    10151069 
    10161070    ++pjsua_var.call_cnt; 
    1017  
    10181071 
    10191072    /* Check if this request should replace existing call */ 
Note: See TracChangeset for help on using the changeset viewer.