Ignore:
Timestamp:
Oct 3, 2011 2:04:36 AM (9 years ago)
Author:
ming
Message:

Closed #1266:
Handle incoming calls when media transport is created asynchronously.

File:
1 edited

Legend:

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

    r3775 r3777  
    332332*/ 
    333333 
     334/* Outgoing call callback when media transport creation is completed. */ 
    334335static pj_status_t 
    335336on_make_call_med_tp_complete(pjsua_call_id call_id, 
     
    612613    call->user_data = user_data; 
    613614     
     615    /* Store variables required for the callback after the async 
     616     * media transport creation is completed. 
     617     */ 
    614618    call->async_call.call_var.out_call.options = options; 
    615619    if (msg_data) { 
     
    686690 
    687691 
     692/* Incoming call callback when media transport creation is completed. */ 
     693static pj_status_t 
     694on_incoming_call_med_tp_complete(pjsua_call_id call_id, 
     695                                 const pjsua_med_tp_state_info *info) 
     696{ 
     697    pjsua_call *call = &pjsua_var.calls[call_id]; 
     698    const pjmedia_sdp_session *offer=NULL; 
     699    pjmedia_sdp_session *answer; 
     700    pjsip_tx_data *response = NULL; 
     701    unsigned options = 0; 
     702    int sip_err_code = (info? info->sip_err_code: 0); 
     703    pj_status_t status = (info? info->status: PJ_SUCCESS); 
     704 
     705    PJSUA_LOCK(); 
     706 
     707    if (status != PJ_SUCCESS) { 
     708        pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
     709        goto on_return; 
     710    } 
     711     
     712    /* Get remote SDP offer (if any). */ 
     713    if (call->inv->neg) 
     714        pjmedia_sdp_neg_get_neg_remote(call->inv->neg, &offer); 
     715 
     716    status = pjsua_media_channel_create_sdp(call_id, 
     717                                            call->async_call.dlg->pool,  
     718                                            offer, &answer, &sip_err_code); 
     719    if (status != PJ_SUCCESS) { 
     720        pjsua_perror(THIS_FILE, "Error creating SDP answer", status); 
     721        goto on_return; 
     722    } 
     723 
     724    status = pjsip_inv_set_local_sdp(call->inv, answer); 
     725    if (status != PJ_SUCCESS) { 
     726        pjsua_perror(THIS_FILE, "Error setting local SDP", status); 
     727        sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE; 
     728        goto on_return; 
     729    } 
     730 
     731    /* Verify that we can handle the request. */ 
     732    status = pjsip_inv_verify_request3(NULL, 
     733                                       call->inv->pool_prov, &options, offer, 
     734                                       answer, NULL, pjsua_var.endpt, &response); 
     735    if (status != PJ_SUCCESS) { 
     736        /* 
     737         * No we can't handle the incoming INVITE request. 
     738         */ 
     739        goto on_return; 
     740    }  
     741 
     742on_return: 
     743    if (status != PJ_SUCCESS) { 
     744        pjsip_tx_data *tdata; 
     745        pj_status_t status_; 
     746 
     747        status_ = pjsip_inv_end_session(call->inv, sip_err_code, NULL, &tdata); 
     748        if (status_ == PJ_SUCCESS && tdata) 
     749            status_ = pjsip_inv_send_msg(call->inv, tdata); 
     750 
     751        pjsua_media_channel_deinit(call->index); 
     752    } 
     753 
     754    /* Set the callback to NULL to indicate that the async operation 
     755     * has completed. 
     756     */ 
     757    call->med_ch_cb = NULL; 
     758 
     759    if (status == PJ_SUCCESS && 
     760        !pj_list_empty(&call->async_call.call_var.inc_call.answers)) 
     761    { 
     762        struct call_answer *answer, *next; 
     763         
     764        answer = call->async_call.call_var.inc_call.answers.next; 
     765        while (answer != &call->async_call.call_var.inc_call.answers) { 
     766            next = answer->next; 
     767            pjsua_call_answer(call_id, answer->code, answer->reason, 
     768                              answer->msg_data); 
     769            pj_list_erase(answer); 
     770            answer = next; 
     771        } 
     772    } 
     773 
     774    PJSUA_UNLOCK(); 
     775    return status; 
     776} 
     777 
     778 
    688779/** 
    689780 * Handle incoming INVITE request. 
     
    704795    int call_id = -1; 
    705796    int sip_err_code; 
    706     pjmedia_sdp_session *offer=NULL, *answer; 
     797    pjmedia_sdp_session *offer=NULL; 
    707798    pj_status_t status; 
    708799 
     
    865956    } else { 
    866957        offer = NULL; 
    867     } 
    868  
    869     /* Init media channel */ 
    870     status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS,  
    871                                       call->secure_level,  
    872                                       rdata->tp_info.pool, 
    873                                       offer, 
    874                                       &sip_err_code, PJ_FALSE, 
    875                                       NULL); 
    876     if (status != PJ_SUCCESS) { 
    877         pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
    878         pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 
    879                             sip_err_code, NULL, NULL, NULL, NULL); 
    880         goto on_return; 
    881     } 
    882  
    883     /* Create answer */ 
    884     status = pjsua_media_channel_create_sdp(call->index, rdata->tp_info.pool,  
    885                                             offer, &answer, &sip_err_code); 
    886     if (status != PJ_SUCCESS) { 
    887         pjsua_perror(THIS_FILE, "Error creating SDP answer", status); 
    888         pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 
    889                             sip_err_code, NULL, NULL, NULL, NULL); 
    890         goto on_return; 
    891958    } 
    892959 
     
    903970        options |= PJSIP_INV_ALWAYS_USE_TIMER; 
    904971 
    905     status = pjsip_inv_verify_request2(rdata, &options, offer, answer, NULL, 
     972    status = pjsip_inv_verify_request2(rdata, &options, offer, NULL, NULL, 
    906973                                       pjsua_var.endpt, &response); 
    907974    if (status != PJ_SUCCESS) { 
     
    923990        } 
    924991 
    925         pjsua_media_channel_deinit(call->index); 
    926992        goto on_return; 
    927993    }  
    928  
    929994 
    930995    /* Get suitable Contact header */ 
     
    9391004            pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL, 
    9401005                                          NULL, NULL); 
    941             pjsua_media_channel_deinit(call->index); 
    9421006            goto on_return; 
    9431007        } 
     
    9501014        pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL, 
    9511015                                      NULL, NULL); 
    952         pjsua_media_channel_deinit(call->index); 
    9531016        goto on_return; 
    9541017    } 
     
    9751038 
    9761039    /* Create invite session: */ 
    977     status = pjsip_inv_create_uas( dlg, rdata, answer, options, &inv); 
     1040    status = pjsip_inv_create_uas( dlg, rdata, NULL, options, &inv); 
    9781041    if (status != PJ_SUCCESS) { 
    9791042        pjsip_hdr hdr_list; 
     
    9951058    } 
    9961059 
     1060    /* Create and attach pjsua_var data to the dialog: */ 
     1061    call->inv = inv; 
     1062    dlg->mod_data[pjsua_var.mod.id] = call; 
     1063    inv->mod_data[pjsua_var.mod.id] = call; 
     1064 
     1065    /* Store variables required for the callback after the async 
     1066     * media transport creation is completed. 
     1067     */ 
     1068    call->async_call.dlg = dlg; 
     1069    pj_list_init(&call->async_call.call_var.inc_call.answers); 
     1070 
     1071    /* Init media channel */ 
     1072    status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS,  
     1073                                      call->secure_level,  
     1074                                      rdata->tp_info.pool, 
     1075                                      offer, 
     1076                                      &sip_err_code, PJ_TRUE, 
     1077                                      (pjsua_med_tp_state_cb) 
     1078                                      &on_incoming_call_med_tp_complete); 
     1079    if (status == PJ_SUCCESS) { 
     1080        status = on_incoming_call_med_tp_complete(call_id, NULL); 
     1081        if (status != PJ_SUCCESS) { 
     1082            sip_err_code = PJSIP_SC_NOT_ACCEPTABLE; 
     1083            pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL); 
     1084            goto on_return; 
     1085        } 
     1086    } else if (status != PJ_EPENDING) { 
     1087        pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
     1088        pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL); 
     1089        goto on_return; 
     1090    } 
     1091 
     1092    /* Create answer */ 
     1093/*   
     1094    status = pjsua_media_channel_create_sdp(call->index, rdata->tp_info.pool,  
     1095                                            offer, &answer, &sip_err_code); 
     1096    if (status != PJ_SUCCESS) { 
     1097        pjsua_perror(THIS_FILE, "Error creating SDP answer", status); 
     1098        pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 
     1099                            sip_err_code, NULL, NULL, NULL, NULL); 
     1100        goto on_return; 
     1101    } 
     1102*/ 
     1103 
    9971104    /* Init Session Timers */ 
    9981105    status = pjsip_timer_init_session(inv,  
     
    10131120     * incoming INVITE!  
    10141121     */ 
    1015     if (pjsua_var.ua_cfg.nat_type_in_sdp && 
     1122    if (pjsua_var.ua_cfg.nat_type_in_sdp && inv->neg && 
    10161123        pjmedia_sdp_neg_get_state(inv->neg) > PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER)  
    10171124    { 
     
    10631170        } 
    10641171    } 
    1065  
    1066     /* Create and attach pjsua_var data to the dialog: */ 
    1067     call->inv = inv; 
    1068  
    1069     dlg->mod_data[pjsua_var.mod.id] = call; 
    1070     inv->mod_data[pjsua_var.mod.id] = call; 
    10711172 
    10721173    ++pjsua_var.call_cnt; 
     
    16371738    if (status != PJ_SUCCESS) 
    16381739        goto on_return; 
     1740 
     1741    PJSUA_LOCK(); 
     1742    /* If media transport creation is not yet completed, we will answer 
     1743     * the call in the media transport creation callback instead. 
     1744     */ 
     1745    if (call->med_ch_cb) { 
     1746        struct call_answer *answer; 
     1747         
     1748        PJ_LOG(4,(THIS_FILE, "Pending answering call %d upon completion " 
     1749                             "of media transport", call_id)); 
     1750 
     1751        answer = PJ_POOL_ZALLOC_T(call->inv->pool_prov, struct call_answer); 
     1752        answer->code = code; 
     1753        if (reason) { 
     1754            pj_strdup(call->inv->pool_prov, answer->reason, reason); 
     1755        } 
     1756        if (msg_data) { 
     1757            answer->msg_data = pjsua_msg_data_clone(call->inv->pool_prov, 
     1758                                                    msg_data); 
     1759        } 
     1760        pj_list_push_back(&call->async_call.call_var.inc_call.answers, 
     1761                          answer); 
     1762 
     1763        PJSUA_UNLOCK(); 
     1764        if (dlg) pjsip_dlg_dec_lock(dlg); 
     1765        pj_log_pop_indent(); 
     1766        return status; 
     1767    } 
     1768    PJSUA_UNLOCK(); 
    16391769 
    16401770    if (call->res_time.sec == 0) 
Note: See TracChangeset for help on using the changeset viewer.