Changeset 5828


Ignore:
Timestamp:
Jul 20, 2018 2:19:41 AM (6 years ago)
Author:
ming
Message:

Fixed #2128: Add feature to allow responding incoming INVITE/re-INVITE asynchronously and set the SDP answer

Location:
pjproject/trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/sdp_neg.c

    r5756 r5828  
    511511    PJ_ASSERT_RETURN(pool && neg && local, PJ_EINVAL); 
    512512 
    513     /* Can only do this in STATE_REMOTE_OFFER. 
    514      * If we already provide local offer, then rx_remote_answer() should 
     513    /* Can only do this in STATE_REMOTE_OFFER or WAIT_NEGO. 
     514     * If we already provide local offer, then set_remote_answer() should 
    515515     * be called instead of this function. 
    516516     */ 
    517     PJ_ASSERT_RETURN(neg->state == PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER,  
     517    PJ_ASSERT_RETURN(neg->state == PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER || 
     518                     neg->state == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO,  
    518519                     PJMEDIA_SDPNEG_EINSTATE); 
    519520 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r5820 r5828  
    10921092     * current call setting. 
    10931093     * 
     1094     * Note: this callback may not be called if \a on_call_rx_reinvite() 
     1095     * is implemented. 
     1096     * 
    10941097     * @param call_id   The call index. 
    10951098     * @param offer     The new offer received. 
     
    11061109                             pjsip_status_code *code, 
    11071110                             pjsua_call_setting *opt); 
     1111 
     1112 
     1113    /** 
     1114     * Notify application when call has received a re-INVITE with offer 
     1115     * from the peer. It allows more fine-grained control over the response 
     1116     * to a re-INVITE. If application sets async to PJ_TRUE, it can send 
     1117     * the reply manually using the function #pjsua_call_answer_with_sdp(). 
     1118     * Otherwise, by default the re-INVITE will be answered automatically 
     1119     * after the callback returns. 
     1120     * 
     1121     * Currently, this callback is only called for re-INVITE with 
     1122     * SDP, but app should be prepared to handle the case of re-INVITE 
     1123     * without SDP. 
     1124     * 
     1125     * Remarks: If manually answering at a later timing, application may 
     1126     * need to monitor on_call_tsx_state() callback to check whether 
     1127     * the re-INVITE is already answered automatically with 487 due to 
     1128     * being cancelled. 
     1129     * 
     1130     * Note: on_call_rx_offer() will still be called after this callback, 
     1131     * but only if async is PJ_FALSE and code is 200.  
     1132     * 
     1133     * @param call_id   The call index. 
     1134     * @param offer     Remote offer. 
     1135     * @param rdata     The received re-INVITE request. 
     1136     * @param reserved  Reserved param, currently not used. 
     1137     * @param async     On input, it is PJ_FALSE. Set to PJ_TRUE if 
     1138     *                  app wants to manually answer the re-INVITE. 
     1139     * @param code      Status code to be returned for answering the 
     1140     *                  offer. On input, it contains status code 200. 
     1141     *                  Currently, valid values are only 200 and 488. 
     1142     * @param opt       The current call setting, application can update 
     1143     *                  this setting for answering the offer. 
     1144     */ 
     1145    void (*on_call_rx_reinvite)(pjsua_call_id call_id, 
     1146                                const pjmedia_sdp_session *offer, 
     1147                                pjsip_rx_data *rdata, 
     1148                                void *reserved, 
     1149                                pj_bool_t *async, 
     1150                                pjsip_status_code *code, 
     1151                                pjsua_call_setting *opt); 
    11081152 
    11091153 
     
    51235167 
    51245168/** 
     5169 * Same as #pjsua_call_answer2() but this function will set the SDP 
     5170 * answer first before sending the response. 
     5171 * 
     5172 * @param call_id       Incoming call identification. 
     5173 * @param sdp           SDP answer.  
     5174 * @param opt           Optional call setting. 
     5175 * @param code          Status code, (100-699). 
     5176 * @param reason        Optional reason phrase. If NULL, default text 
     5177 *                      will be used. 
     5178 * @param msg_data      Optional list of headers etc to be added to outgoing 
     5179 *                      response message. Note that this message data will 
     5180 *                      be persistent in all next answers/responses for this 
     5181 *                      INVITE request. 
     5182 * 
     5183 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     5184 */ 
     5185PJ_DECL(pj_status_t) 
     5186pjsua_call_answer_with_sdp(pjsua_call_id call_id, 
     5187                           const pjmedia_sdp_session *sdp,  
     5188                           const pjsua_call_setting *opt, 
     5189                           unsigned code, 
     5190                           const pj_str_t *reason, 
     5191                           const pjsua_msg_data *msg_data); 
     5192 
     5193 
     5194/** 
    51255195 * Hangup call by using method that is appropriate according to the 
    51265196 * call state. This function is different than answering the call with 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h

    r5788 r5828  
    193193                                            offer.                          */ 
    194194     
     195    pj_bool_t            rx_reinv_async;/**< on_call_rx_reinvite() async.   */ 
    195196    pj_timer_entry       reinv_timer;  /**< Reinvite retry timer.           */ 
    196197    pj_bool_t            reinv_pending;/**< Pending until CONFIRMED state.  */ 
  • pjproject/trunk/pjsip/include/pjsua2/call.hpp

    r5755 r5828  
    867867 
    868868/** 
     869 * This structure contains parameters for Call::onCallRxReinvite() callback. 
     870 */ 
     871struct OnCallRxReinviteParam 
     872{ 
     873    /** 
     874     * The new offer received. 
     875     */ 
     876    SdpSession          offer; 
     877 
     878    /** 
     879     * The incoming re-INVITE. 
     880     */ 
     881    SipRxData           rdata; 
     882     
     883    /** 
     884     * On input, it is false. Set to true if app wants to manually answer 
     885     * the re-INVITE. 
     886     */ 
     887    bool                async; 
     888     
     889    /** 
     890     * Status code to be returned for answering the offer. On input, 
     891     * it contains status code 200. Currently, valid values are only 
     892     * 200 and 488. 
     893     */ 
     894    pjsip_status_code   statusCode; 
     895     
     896    /** 
     897     * The current call setting, application can update this setting for 
     898     * answering the offer. 
     899     */ 
     900    CallSetting         opt; 
     901}; 
     902 
     903/** 
    869904 * This structure contains parameters for Call::onCallTxOffer() callback. 
    870905 */ 
     
    10361071     */ 
    10371072    SipTxOption         txOption; 
     1073 
     1074    /** 
     1075     * SDP answer. Currently only used for Call::answer(). 
     1076     */ 
     1077    SdpSession          sdp; 
    10381078     
    10391079public: 
     
    16581698    { PJ_UNUSED_ARG(prm); } 
    16591699     
     1700    /** 
     1701     * Notify application when call has received a re-INVITE offer from 
     1702     * the peer. It allows more fine-grained control over the response to 
     1703     * a re-INVITE. If application sets async to PJ_TRUE, it can send 
     1704     * the reply manually using the function #Call::answer() and setting 
     1705     * the SDP answer. Otherwise, by default the re-INVITE will be 
     1706     * answered automatically after the callback returns. 
     1707     * 
     1708     * Currently, this callback is only called for re-INVITE with 
     1709     * SDP, but app should be prepared to handle the case of re-INVITE 
     1710     * without SDP. 
     1711     * 
     1712     * Remarks: If manually answering at a later timing, application may 
     1713     * need to monitor onCallTsxState() callback to check whether 
     1714     * the re-INVITE is already answered automatically with 487 due to 
     1715     * being cancelled. 
     1716     * 
     1717     * Note: onCallRxOffer() will still be called after this callback, 
     1718     * but only if prm.async is false and prm.code is 200.  
     1719     */ 
     1720    virtual void onCallRxReinvite(OnCallRxReinviteParam &prm) 
     1721    { PJ_UNUSED_ARG(prm); } 
     1722 
     1723 
    16601724    /** 
    16611725     * Notify application when call has received INVITE with no SDP offer. 
     
    18061870 
    18071871private: 
     1872    friend class Endpoint; 
     1873 
    18081874    Account             &acc; 
    18091875    pjsua_call_id        id; 
    18101876    Token                userData; 
    18111877    std::vector<Media *> medias; 
     1878    pj_pool_t           *sdp_pool; 
    18121879}; 
    18131880 
  • pjproject/trunk/pjsip/include/pjsua2/endpoint.hpp

    r5755 r5828  
    17151715                                 pjsip_status_code *code, 
    17161716                                 pjsua_call_setting *opt); 
     1717    static void on_call_rx_reinvite(pjsua_call_id call_id, 
     1718                                    const pjmedia_sdp_session *offer, 
     1719                                    pjsip_rx_data *rdata, 
     1720                                    void *reserved, 
     1721                                    pj_bool_t *async, 
     1722                                    pjsip_status_code *code, 
     1723                                    pjsua_call_setting *opt); 
    17171724    static void on_call_tx_offer(pjsua_call_id call_id, 
    17181725                                 void *reserved, 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c

    r5816 r5828  
    8080 */ 
    8181static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, 
    82                                    const pjmedia_sdp_session *offer); 
     82                                struct pjsip_inv_on_rx_offer_cb_param *param); 
     83 
     84/* 
     85 * Called when receiving re-INVITE. 
     86 */ 
     87static pj_status_t pjsua_call_on_rx_reinvite(pjsip_inv_session *inv, 
     88                                             const pjmedia_sdp_session *offer, 
     89                                             pjsip_rx_data *rdata); 
    8390 
    8491/* 
     
    191198    inv_cb.on_new_session = &pjsua_call_on_forked; 
    192199    inv_cb.on_media_update = &pjsua_call_on_media_update; 
    193     inv_cb.on_rx_offer = &pjsua_call_on_rx_offer; 
     200    inv_cb.on_rx_offer2 = &pjsua_call_on_rx_offer; 
    194201    inv_cb.on_create_offer = &pjsua_call_on_create_offer; 
    195202    inv_cb.on_tsx_state_changed = &pjsua_call_on_tsx_state_changed; 
    196203    inv_cb.on_redirected = &pjsua_call_on_redirected; 
     204    if (pjsua_var.ua_cfg.cb.on_call_rx_reinvite) { 
     205        inv_cb.on_rx_reinvite = &pjsua_call_on_rx_reinvite; 
     206    } 
    197207 
    198208    /* Initialize invite session module: */ 
     
    24042414 
    24052415/* 
     2416 * Send response to incoming INVITE request. 
     2417 */ 
     2418PJ_DEF(pj_status_t) 
     2419pjsua_call_answer_with_sdp(pjsua_call_id call_id, 
     2420                           const pjmedia_sdp_session *sdp,  
     2421                           const pjsua_call_setting *opt, 
     2422                           unsigned code, 
     2423                           const pj_str_t *reason, 
     2424                           const pjsua_msg_data *msg_data) 
     2425{ 
     2426    pjsua_call *call; 
     2427    pjsip_dialog *dlg = NULL; 
     2428    pj_status_t status; 
     2429 
     2430    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     2431                     PJ_EINVAL); 
     2432 
     2433    status = acquire_call("pjsua_call_answer_with_sdp()", 
     2434                          call_id, &call, &dlg); 
     2435    if (status != PJ_SUCCESS) 
     2436        return status; 
     2437 
     2438    status = pjsip_inv_set_sdp_answer(call->inv, sdp); 
     2439 
     2440    pjsip_dlg_dec_lock(dlg); 
     2441     
     2442    if (status != PJ_SUCCESS) 
     2443        return status; 
     2444     
     2445    return pjsua_call_answer2(call_id, opt, code, reason, msg_data); 
     2446} 
     2447 
     2448 
     2449/* 
    24062450 * Hangup call by using method that is appropriate according to the 
    24072451 * call state. 
     
    42644308 */ 
    42654309static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, 
    4266                                    const pjmedia_sdp_session *offer) 
     4310                                struct pjsip_inv_on_rx_offer_cb_param *param) 
    42674311{ 
    42684312    pjsua_call *call; 
     
    42704314    unsigned i; 
    42714315    pj_status_t status; 
     4316    const pjmedia_sdp_session *offer = param->offer; 
     4317    pjsua_call_setting opt; 
     4318    pj_bool_t async = PJ_FALSE; 
    42724319 
    42734320    call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id]; 
     
    42854332 
    42864333    cleanup_call_setting_flag(&call->opt); 
    4287  
    4288     if (pjsua_var.ua_cfg.cb.on_call_rx_offer) { 
     4334    opt = call->opt; 
     4335 
     4336    if (pjsua_var.ua_cfg.cb.on_call_rx_reinvite && 
     4337        param->rdata->msg_info.msg->type == PJSIP_REQUEST_MSG && 
     4338        param->rdata->msg_info.msg->line.req.method.id == PJSIP_INVITE_METHOD) 
     4339    { 
     4340        pjsip_status_code code = PJSIP_SC_OK; 
     4341 
     4342        /* If on_call_rx_reinvite() callback is implemented, 
     4343         * call it first. 
     4344         */ 
     4345        (*pjsua_var.ua_cfg.cb.on_call_rx_reinvite)( 
     4346                                                call->index, offer, 
     4347                                                (pjsip_rx_data *)param->rdata, 
     4348                                                NULL, &async, &code, &opt); 
     4349        if (async) { 
     4350            pjsip_tx_data *response; 
     4351 
     4352            status = pjsip_inv_initial_answer(inv, 
     4353                                              (pjsip_rx_data *)param->rdata, 
     4354                                              100, NULL, NULL, &response); 
     4355            if (status != PJ_SUCCESS) { 
     4356                PJ_LOG(3, (THIS_FILE, "Failed to create initial answer"));  
     4357                goto on_return; 
     4358            } 
     4359 
     4360            status = pjsip_inv_send_msg(inv, response); 
     4361            if (status != PJ_SUCCESS) { 
     4362                PJ_LOG(3, (THIS_FILE, "Failed to send initial answer"));  
     4363                goto on_return; 
     4364            } 
     4365 
     4366            PJ_LOG(4,(THIS_FILE, "App will manually answer the re-INVITE " 
     4367                                 "on call %d", call->index)); 
     4368        } 
     4369        if (code != PJSIP_SC_OK) { 
     4370            PJ_LOG(4,(THIS_FILE, "Rejecting re-INVITE updated media offer " 
     4371                                 "on call %d", call->index)); 
     4372            goto on_return; 
     4373        } 
     4374 
     4375        call->opt = opt; 
     4376    } 
     4377 
     4378    if (pjsua_var.ua_cfg.cb.on_call_rx_offer && !async) { 
    42894379        pjsip_status_code code = PJSIP_SC_OK; 
    4290         pjsua_call_setting opt; 
    4291  
    4292         opt = call->opt; 
     4380 
    42934381        (*pjsua_var.ua_cfg.cb.on_call_rx_offer)(call->index, offer, NULL, 
    42944382                                                &code, &opt); 
     
    43134401    if (status != PJ_SUCCESS) { 
    43144402        pjsua_perror(THIS_FILE, "Unable to create local SDP", status); 
     4403        goto on_return; 
     4404    } 
     4405 
     4406    if (async) { 
     4407        call->rx_reinv_async = async; 
    43154408        goto on_return; 
    43164409    } 
     
    43614454on_return: 
    43624455    pj_log_pop_indent(); 
     4456} 
     4457 
     4458 
     4459/* 
     4460 * Called when receiving re-INVITE. 
     4461 */ 
     4462static pj_status_t pjsua_call_on_rx_reinvite(pjsip_inv_session *inv, 
     4463                                             const pjmedia_sdp_session *offer, 
     4464                                             pjsip_rx_data *rdata) 
     4465{ 
     4466    pjsua_call *call; 
     4467    pj_bool_t async; 
     4468 
     4469    PJ_UNUSED_ARG(offer); 
     4470    PJ_UNUSED_ARG(rdata); 
     4471 
     4472    call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id]; 
     4473    async = call->rx_reinv_async; 
     4474    call->rx_reinv_async = PJ_FALSE; 
     4475 
     4476    return (async? PJ_SUCCESS: !PJ_SUCCESS); 
    43634477} 
    43644478 
  • pjproject/trunk/pjsip/src/pjsua2/call.cpp

    r5645 r5828  
    161161: statusCode(pjsip_status_code(0)), reason(""), options(0) 
    162162{ 
     163    sdp.wholeSdp = ""; 
    163164    if (useDefaultCallSetting) 
    164165        opt = CallSetting(true); 
     
    329330    pj_str_t            reason; 
    330331    pj_str_t           *p_reason; 
     332    pjmedia_sdp_session *sdp; 
    331333 
    332334public: 
     
    336338    call_param(const SipTxOption &tx_option); 
    337339    call_param(const SipTxOption &tx_option, const CallSetting &setting, 
    338                const string &reason_str); 
     340               const string &reason_str, pj_pool_t *pool = NULL, 
     341               const string &sdp_str = ""); 
    339342}; 
    340343 
     
    350353    p_opt = NULL; 
    351354    p_reason = NULL; 
     355    sdp = NULL; 
    352356} 
    353357 
    354358call_param::call_param(const SipTxOption &tx_option, const CallSetting &setting, 
    355                        const string &reason_str) 
     359                       const string &reason_str, pj_pool_t *pool, 
     360                       const string &sdp_str) 
    356361{ 
    357362    if (tx_option.isEmpty()) { 
     
    371376    reason = str2Pj(reason_str); 
    372377    p_reason = (reason.slen == 0? NULL: &reason); 
     378 
     379    if (sdp_str == "") { 
     380        sdp = NULL; 
     381    } else { 
     382        pj_str_t dup_pj_sdp; 
     383        pj_str_t pj_sdp_str = {(char*)sdp_str.c_str(), 
     384                               (pj_ssize_t)sdp_str.size()}; 
     385 
     386        pj_strdup(pool, &dup_pj_sdp, &pj_sdp_str);         
     387        pjmedia_sdp_parse(pool, dup_pj_sdp.ptr, 
     388                          dup_pj_sdp.slen, &sdp); 
     389    } 
    373390} 
    374391 
     
    493510void Call::answer(const CallOpParam &prm) throw(Error) 
    494511{ 
    495     call_param param(prm.txOption, prm.opt, prm.reason); 
    496      
    497     PJSUA2_CHECK_EXPR( pjsua_call_answer2(id, param.p_opt, prm.statusCode, 
    498                                           param.p_reason, param.p_msg_data) ); 
     512    call_param param(prm.txOption, prm.opt, prm.reason, 
     513                     sdp_pool, prm.sdp.wholeSdp); 
     514     
     515    if (param.sdp) { 
     516        PJSUA2_CHECK_EXPR( pjsua_call_answer_with_sdp(id, param.sdp, param.p_opt, 
     517                                                      prm.statusCode, 
     518                                                      param.p_reason, 
     519                                                      param.p_msg_data) ); 
     520    } else { 
     521        PJSUA2_CHECK_EXPR( pjsua_call_answer2(id, param.p_opt, prm.statusCode, 
     522                                              param.p_reason, 
     523                                              param.p_msg_data) ); 
     524    } 
    499525} 
    500526 
  • pjproject/trunk/pjsip/src/pjsua2/endpoint.cpp

    r5817 r5828  
    10671067        prm.remSdp.fromPj(*rem_sdp); 
    10681068     
     1069    call->sdp_pool = pool; 
    10691070    call->onCallSdpCreated(prm); 
    10701071     
     
    12531254    call->onCallRxOffer(prm); 
    12541255     
     1256    *code = prm.statusCode; 
     1257    *opt = prm.opt.toPj(); 
     1258} 
     1259 
     1260void Endpoint::on_call_rx_reinvite(pjsua_call_id call_id, 
     1261                                   const pjmedia_sdp_session *offer, 
     1262                                   pjsip_rx_data *rdata, 
     1263                                   void *reserved, 
     1264                                   pj_bool_t *async, 
     1265                                   pjsip_status_code *code, 
     1266                                   pjsua_call_setting *opt) 
     1267{ 
     1268    PJ_UNUSED_ARG(reserved); 
     1269 
     1270    Call *call = Call::lookup(call_id); 
     1271    if (!call) { 
     1272        return; 
     1273    } 
     1274     
     1275    OnCallRxReinviteParam prm; 
     1276    prm.offer.fromPj(*offer); 
     1277    prm.rdata.fromPj(*rdata); 
     1278    prm.async = PJ2BOOL(*async); 
     1279    prm.statusCode = *code; 
     1280    prm.opt.fromPj(*opt); 
     1281     
     1282    call->onCallRxReinvite(prm); 
     1283     
     1284    *async = prm.async; 
    12551285    *code = prm.statusCode; 
    12561286    *opt = prm.opt.toPj(); 
     
    15771607    ua_cfg.cb.on_call_replaced          = &Endpoint::on_call_replaced; 
    15781608    ua_cfg.cb.on_call_rx_offer          = &Endpoint::on_call_rx_offer; 
     1609    ua_cfg.cb.on_call_rx_reinvite       = &Endpoint::on_call_rx_reinvite; 
    15791610    ua_cfg.cb.on_call_tx_offer          = &Endpoint::on_call_tx_offer; 
    15801611    ua_cfg.cb.on_call_redirected        = &Endpoint::on_call_redirected; 
Note: See TracChangeset for help on using the changeset viewer.