Ticket #539: ticket539.patch

File ticket539.patch, 34.7 KB (added by bennylp, 16 years ago)

The work so far, still uncompileable, just for future reference.

  • pjsip/include/pjsua-lib/pjsua_internal.h

     
    2626 
    2727PJ_BEGIN_DECL 
    2828 
     29/** 
     30 * Structure to be attached to media transport. 
     31 */ 
     32typedef struct pjsua_med_tp_data 
     33{ 
     34    pjmedia_transport   *tp;        /**< The media transport                */ 
     35    pjsua_call_id        cid;       /**< Call-ID (may be -1)                */ 
     36    pjsip_dialog        *dlg;       /**< SIP dialog (useful when cid is -1) */ 
     37    pj_status_t          status;    /**< Transport status.                  */ 
     38 
     39    /** Incoming call data */ 
     40    struct in { 
     41        pjmedia_sdp_session *rem_sdp;   /**< Cached remote SDP      */ 
     42        pjsip_dialog        *replaced_dlg;/**< call xfer                    */ 
     43        pjsip_rx_data       *rdata;     /**< rdata                  */ 
     44        pj_bool_t            rdata_copy;        /**< was rdata copied?      */ 
     45    } in; 
     46 
     47    /** Outgoing call data */ 
     48    struct out { 
     49        pjsua_msg_data      *msg_data;  /**< Saved outgoing msg_data        */ 
     50    } out; 
     51 
     52 
     53} pjsua_med_tp_data; 
     54 
     55 
    2956/**  
    3057 * Structure to be attached to invite dialog.  
    3158 * Given a dialog "dlg", application can retrieve this structure 
     
    5178    int                  conf_slot; /**< Slot # in conference bridge.       */ 
    5279    pjsip_evsub         *xfer_sub;  /**< Xfer server subscription, if this 
    5380                                         call was triggered by xfer.        */ 
    54     pjmedia_transport   *med_tp;    /**< Current media transport.           */ 
    55     pj_status_t          med_tp_st; /**< Media transport status.            */ 
    56     pjmedia_transport   *med_orig;  /**< Original media transport           */ 
     81     
     82    pjsua_med_tp_data    med_tp_data;/**< Media transport data              */ 
     83    pjsua_msg_data      *inv_msg_data;/**< Saved make_call() msg_data       */ 
     84 
    5785    pj_timer_entry       refresh_tm;/**< Timer to send re-INVITE.           */ 
    5886    pj_timer_entry       hangup_tm; /**< Timer to hangup call.              */ 
    5987    pj_stun_nat_type     rem_nat_type; /**< NAT type of remote endpoint.    */ 
     
    316344/* 
    317345 * Media channel. 
    318346 */ 
    319 pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, 
    320                                      pjsip_role_e role, 
    321                                      int security_level, 
    322                                      int *sip_err_code); 
     347 
     348/* Create. This may return PJ_EPENDING if transport creation can't  
     349 * complete immediately (e.g. STUN, ICE) */ 
     350pj_status_t pjsua_media_channel_create(pjsua_call_id call_id, 
     351                                       pjsip_role_e role, 
     352                                       int security_level, 
     353                                       const pjmedia_sdp_session *rem_sdp, 
     354                                       int *sip_err_code); 
    323355pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id,  
    324356                                           pj_pool_t *pool, 
    325357                                           const pjmedia_sdp_session *rem_sdp, 
     
    330362                                       const pjmedia_sdp_session *remote_sdp); 
    331363pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id); 
    332364 
     365void        pjsua_on_media_channel_created(pjsua_call_id call_id, 
     366                                           pj_status_t status); 
    333367 
     368 
    334369/** 
    335370 * Init presence. 
    336371 */ 
     
    422457 */ 
    423458pjsip_accept_hdr* pjsua_im_create_accept(pj_pool_t *pool); 
    424459 
     460/* Duplicate msg_data */ 
     461void pjsua_msg_data_dup(pj_pool_t *pool, pjsua_msg_data *dst,  
     462                        const pjsua_msg_data *src); 
     463 
    425464/* 
    426465 * Add additional headers etc in msg_data specified by application 
    427466 * when sending requests. 
  • pjsip/include/pjsip-ua/sip_inv.h

     
    554554 
    555555 
    556556/** 
     557 * Set local offer to be carried by subsequent response (or request). 
     558 * 
     559 * @param inv           The invite session. 
     560 * @param sdp           The SDP offer. 
     561 * 
     562 * @return              PJ_SUCCESS if local offer can be accepted by 
     563 *                      SDP negotiator. 
     564 */ 
     565PJ_DECL(pj_status_t) pjsip_inv_set_sdp_offer(pjsip_inv_session *inv, 
     566                                             const pjmedia_sdp_session *sdp ); 
     567 
     568 
     569/** 
    557570 * Create a SIP message to initiate invite session termination. Depending on  
    558571 * the state of the session, this function may return CANCEL request,  
    559572 * a non-2xx final response, or a BYE request. If the session has not answered 
  • pjsip/src/pjsua-lib/pjsua_core.c

     
    5656    for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.tpdata); ++i) 
    5757        pjsua_var.tpdata[i].index = i; 
    5858 
     59    for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.calls); ++i) { 
     60        pjsua_var.calls[i].med_tp_data.cid = PJSUA_INVALID_ID; 
     61    } 
     62 
    5963    pjsua_var.stun_status = PJ_EUNKNOWN; 
    6064    pjsua_var.nat_status = PJ_EPENDING; 
    6165} 
     
    526530 
    527531    /* Add hostname */ 
    528532    hostname = pj_gethostname(); 
    529     seed = pj_hash_calc(seed, hostname->ptr, (int)hostname->slen); 
     533    if (hostname) 
     534        seed = pj_hash_calc(seed, hostname->ptr, (int)hostname->slen); 
    530535 
    531     /* Add primary IP address */ 
     536    /* Add primary IPv4 address, if any */ 
    532537    if (pj_gethostip(pj_AF_INET(), &addr)==PJ_SUCCESS) 
    533         seed = pj_hash_calc(seed, &addr.ipv4.sin_addr, 4); 
     538        seed = pj_hash_calc(seed, &addr, pj_sockaddr_get_len(&addr)); 
    534539 
     540    /* Add primary IPv6 address, if any */ 
     541#if PJ_HAS_IPV6 
     542    if (pj_gethostip(pj_AF_INET6(), &addr)==PJ_SUCCESS) 
     543        seed = pj_hash_calc(seed, &addr, pj_sockaddr_get_len(&addr)); 
     544#endif 
     545 
    535546    /* Get timeofday */ 
    536547    pj_gettimeofday(&t); 
    537548    seed = pj_hash_calc(seed, &t, sizeof(t)); 
     
    18191830} 
    18201831 
    18211832 
     1833/* Duplicate msg_data */ 
     1834void pjsua_msg_data_dup(pj_pool_t *pool, pjsua_msg_data *dst,  
     1835                        const pjsua_msg_data *src) 
     1836{ 
     1837    const pjsip_hdr *hsrc; 
     1838 
     1839    pjsua_msg_data_init(dst); 
     1840 
     1841    /* Duplicate headers */ 
     1842    hsrc = src->hdr_list.next; 
     1843    while (hsrc != &src->hdr_list) { 
     1844        pjsip_hdr *hdst = (pjsip_hdr*) pjsip_hdr_clone(pool, hsrc); 
     1845        pj_list_push_back(&dst->hdr_list, hdst); 
     1846        hsrc = hsrc->next; 
     1847    } 
     1848 
     1849    /* Duplicate mime types and body */ 
     1850    pj_strdup(pool, &dst->content_type, &src->content_type); 
     1851    pj_strdup(pool, &dst->msg_body, &src->msg_body); 
     1852} 
     1853 
    18221854/* 
    18231855 * Add additional headers etc in msg_data specified by application 
    18241856 * when sending requests. 
  • pjsip/src/pjsua-lib/pjsua_call.c

     
    7171static pj_status_t create_inactive_sdp(pjsua_call *call, 
    7272                                       pjmedia_sdp_session **p_answer); 
    7373 
     74/* Disconnect call */ 
     75static void call_disconnect(pjsip_inv_session *inv, int code, 
     76                            const char *reason, const char *warn_text, 
     77                            pj_status_t warn_status); 
     78 
    7479/* Update SDP version in the offer */ 
    7580static void update_sdp_version(pjsua_call *call, 
    7681                               pjmedia_sdp_session *sdp) 
     
    115120    call->res_time.sec = 0; 
    116121    call->res_time.msec = 0; 
    117122    call->rem_nat_type = PJ_STUN_NAT_TYPE_UNKNOWN; 
     123 
     124    pj_bzero(&call->med_tp_data, sizeof(call->med_tp_data)); 
     125    call->med_tp_data.status = PJ_EPENDING; 
     126    call->med_tp_data.cid = PJSUA_INVALID_ID; 
    118127} 
    119128 
    120129 
     
    329338                                          pjsua_call_id *p_call_id) 
    330339{ 
    331340    pjsip_dialog *dlg = NULL; 
    332     pjmedia_sdp_session *offer; 
    333341    pjsip_inv_session *inv = NULL; 
    334342    pjsua_acc *acc; 
    335343    pjsua_call *call; 
    336344    int call_id = -1; 
    337345    pj_str_t contact; 
    338     pjsip_tx_data *tdata; 
    339346    pj_status_t status; 
    340347 
    341348 
     
    366373    } 
    367374 
    368375    call = &pjsua_var.calls[call_id]; 
     376    reset_call(call_id); 
    369377 
    370378    /* Verify that destination URI is valid before calling  
    371379     * pjsua_acc_create_uac_contact, or otherwise there   
     
    426434                                   &acc->cfg.id, &contact, 
    427435                                   dest_uri, dest_uri, &dlg); 
    428436    if (status != PJ_SUCCESS) { 
     437        PJSUA_UNLOCK(); 
    429438        pjsua_perror(THIS_FILE, "Dialog creation failed", status); 
    430         PJSUA_UNLOCK(); 
    431439        return status; 
    432440    } 
    433441 
    434     /* Calculate call's secure level */ 
    435     call->secure_level = get_secure_level(acc_id, dest_uri); 
    436442 
    437     /* Init media channel */ 
    438     status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC,  
    439                                       call->secure_level, NULL); 
    440     if (status != PJ_SUCCESS) { 
    441         pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
    442         goto on_error; 
    443     } 
    444  
    445     /* Create SDP offer */ 
    446 #if LATE_SDP 
    447     offer = NULL; 
    448 #else 
    449     status = pjsua_media_channel_create_sdp(call->index, dlg->pool, NULL,  
    450                                             &offer, NULL); 
    451     if (status != PJ_SUCCESS) { 
    452         pjsua_perror(THIS_FILE, "pjmedia unable to create SDP", status); 
    453         goto on_error; 
    454     } 
    455 #endif 
    456  
    457443    /* Create the INVITE session: */ 
    458444    options |= PJSIP_INV_SUPPORT_100REL; 
    459445    if (acc->cfg.require_100rel) 
    460446        options |= PJSIP_INV_REQUIRE_100REL; 
    461447 
    462     status = pjsip_inv_create_uac( dlg, offer, options, &inv); 
     448    status = pjsip_inv_create_uac( dlg, NULL, options, &inv); 
    463449    if (status != PJ_SUCCESS) { 
     450        pjsip_dlg_terminate(dlg); 
     451        PJSUA_UNLOCK(); 
    464452        pjsua_perror(THIS_FILE, "Invite session creation failed", status); 
    465         goto on_error; 
     453        return status; 
    466454    } 
    467455 
    468  
    469456    /* Create and associate our data in the session. */ 
    470457    call->acc_id = acc_id; 
    471458    call->inv = inv; 
     
    500487    /* Set authentication preference */ 
    501488    pjsip_auth_clt_set_prefs(&dlg->auth_sess, &acc->cfg.auth_pref); 
    502489 
    503     /* Create initial INVITE: */ 
    504  
    505     status = pjsip_inv_invite(inv, &tdata); 
    506     if (status != PJ_SUCCESS) { 
    507         pjsua_perror(THIS_FILE, "Unable to create initial INVITE request",  
    508                      status); 
    509         goto on_error; 
     490    /* Save msg_data for later, if any */ 
     491    if (msg_data) { 
     492        call->med_tp_data.out.msg_data = PJ_POOL_ALLOC_T(dlg->pool, 
     493                                                         pjsua_msg_data); 
     494        pjsua_msg_data_dup(inv->pool, call->med_tp_data.out.msg_data,  
     495                           msg_data); 
     496    } else { 
     497        call->med_tp_data.out.msg_data = NULL; 
    510498    } 
    511499 
    512500 
    513     /* Add additional headers etc */ 
     501    /* Calculate call's secure level */ 
     502    call->secure_level = get_secure_level(acc_id, dest_uri); 
    514503 
    515     pjsua_process_msg_data( tdata, msg_data); 
     504    /* Create the media channel. Further processing to this call will 
     505     * be done in pjsua_on_media_channel_created() when media channel  
     506     * creation completes. 
     507     */ 
     508    call->med_tp_data.status = PJ_EPENDING; 
     509    status = pjsua_media_channel_create(call->index, PJSIP_ROLE_UAC,  
     510                                        call->secure_level, NULL, NULL); 
     511    if (status != PJ_SUCCESS && status != PJ_EPENDING) { 
     512        if (call->inv != NULL) { 
     513            pjsip_inv_terminate(call->inv, PJSIP_SC_OK, PJ_FALSE); 
     514        } 
     515        reset_call(call_id); 
     516        PJSUA_UNLOCK(); 
     517        pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
     518        return status; 
     519    } 
    516520 
    517     /* Must increment call counter now */ 
     521    /* Increment call counter */ 
    518522    ++pjsua_var.call_cnt; 
    519523 
    520     /* Send initial INVITE: */ 
     524    if (p_call_id) 
     525        *p_call_id = call_id; 
    521526 
    522     status = pjsip_inv_send_msg(inv, tdata); 
     527    PJSUA_UNLOCK(); 
     528 
     529    return PJ_SUCCESS; 
     530} 
     531 
     532 
     533void pjsua_on_media_channel_created(pjsua_call_id call_id, 
     534                                    pj_status_t med_status) 
     535{ 
     536    pjsua_call *call; 
     537    pjsip_dialog *dlg; 
     538    pjsip_inv_session *inv; 
     539    pj_status_t status; 
     540 
     541    status = acquire_call("pjsua_on_media_channel_created", call_id,  
     542                          &call, &dlg); 
    523543    if (status != PJ_SUCCESS) { 
    524         pjsua_perror(THIS_FILE, "Unable to send initial INVITE request",  
    525                      status); 
     544        pj_assert(!"Unexpected!"); 
     545        return; 
     546    } 
    526547 
    527         /* Upon failure to send first request, both dialog and invite  
    528          * session would have been cleared. 
     548    call->med_tp_data.status = med_status; 
     549    inv = call->inv; 
     550 
     551    if (inv->role == PJSIP_ROLE_UAC) { 
     552        /* 
     553         * Outgoing call 
    529554         */ 
    530         inv = NULL; 
    531         dlg = NULL; 
    532         goto on_error; 
    533     } 
     555        pjmedia_sdp_session *offer; 
     556        pjsip_tx_data *tdata; 
    534557 
    535     /* Done. */ 
     558        /* Handle failure to start media channel */ 
     559        if (med_status != PJ_SUCCESS) { 
     560            pjsip_inv_terminate(call->inv, PJSIP_SC_OK, PJ_FALSE); 
     561            reset_call(call->index); 
     562            goto on_return; 
     563        } 
    536564 
    537     if (p_call_id) 
    538         *p_call_id = call_id; 
     565        /* Create SDP offer */ 
     566#if LATE_SDP 
     567        offer = NULL; 
     568#else 
     569        status = pjsua_media_channel_create_sdp(call->index, dlg->pool, NULL,  
     570                                                &offer, NULL); 
     571        if (status != PJ_SUCCESS) { 
     572            pjsip_inv_terminate(call->inv, PJSIP_SC_OK, PJ_FALSE); 
     573            reset_call(call->index); 
     574            pjsua_perror(THIS_FILE, "pjmedia unable to create SDP", status); 
     575            goto on_return; 
     576        } 
    539577 
    540     PJSUA_UNLOCK(); 
     578        status = pjsip_inv_set_sdp_offer(inv, offer); 
     579#endif 
    541580 
    542     return PJ_SUCCESS; 
     581        /* Create initial INVITE: */ 
     582        status = pjsip_inv_invite(inv, &tdata); 
     583        if (status != PJ_SUCCESS) { 
     584            pjsip_inv_terminate(call->inv, PJSIP_SC_OK, PJ_FALSE); 
     585            reset_call(call->index); 
     586            pjsua_perror(THIS_FILE, "Unable to create initial INVITE request", 
     587                         status); 
     588            goto on_return; 
     589        } 
    543590 
     591        /* Add additional headers etc */ 
     592        pjsua_process_msg_data(tdata, call->med_tp_data.out.msg_data); 
    544593 
    545 on_error: 
    546     if (inv != NULL) { 
    547         pjsip_inv_terminate(inv, PJSIP_SC_OK, PJ_FALSE); 
    548     } else if (dlg) { 
    549         pjsip_dlg_terminate(dlg); 
    550     } 
     594        /* Send initial INVITE: */ 
     595        status = pjsip_inv_send_msg(inv, tdata); 
     596        if (status != PJ_SUCCESS) { 
     597            pjsua_perror(THIS_FILE, "Unable to send initial INVITE request", 
     598                         status); 
    551599 
    552     if (call_id != -1) { 
    553         reset_call(call_id); 
    554         pjsua_media_channel_deinit(call_id); 
     600            /* Upon failure to send first request, both dialog and invite  
     601             * session would have been cleared. 
     602             */ 
     603            inv = NULL; 
     604            dlg = NULL; 
     605            goto on_return; 
     606        } 
     607 
     608    } else { 
     609        /* 
     610         * Incoming call 
     611         */ 
     612        pjmedia_sdp_session *answer; 
     613        int sip_err_code; 
     614 
     615        /* Handle failure to start media channel */ 
     616        if (med_status != PJ_SUCCESS) { 
     617            call_disconnect(inv, 500, "Media Error", NULL,  
     618                            med_status); 
     619            goto on_return; 
     620        } 
     621 
     622        /* Get media channel's SDP */ 
     623        status = pjsua_media_channel_create_sdp(call_id, inv->pool,  
     624                                                call->med_tp_data.in.rem_sdp,  
     625                                                &answer, &sip_err_code); 
     626        if (status != PJ_SUCCESS) { 
     627            call_disconnect(inv, sip_err_code, NULL,  
     628                            "SDP creation/negotiation failed", status); 
     629            goto on_return; 
     630        } 
     631 
     632        /* Set SDP to the invite session */ 
     633        if (inv->neg) { 
     634            status = pjsip_inv_set_sdp_answer(inv, answer); 
     635        } else { 
     636            status = pjsip_inv_set_sdp_offer(inv, answer); 
     637        } 
     638 
     639        if (status != PJ_SUCCESS) { 
     640            call_disconnect(inv, sip_err_code, NULL, "Unable to set SDP", 
     641                            status); 
     642            goto on_return; 
     643        } 
     644 
     645        /* Check if this request should replace existing call */ 
     646        if (call->med_tp_data.in.replaced_dlg) { 
     647            pjsip_dialog *replaced_dlg = call->med_tp_data.in.replaced_dlg; 
     648            pjsip_inv_session *replaced_inv; 
     649            struct pjsua_call *replaced_call; 
     650            pjsip_tx_data *tdata; 
     651 
     652            /* Get the invite session in the dialog */ 
     653            replaced_inv = pjsip_dlg_get_inv_session(replaced_dlg); 
     654 
     655            /* Get the replaced call instance */ 
     656            replaced_call = (pjsua_call*) replaced_dlg->mod_data[pjsua_var.mod.id]; 
     657 
     658            /* Notify application */ 
     659            if (pjsua_var.ua_cfg.cb.on_call_replaced) 
     660                pjsua_var.ua_cfg.cb.on_call_replaced(replaced_call->index, 
     661                                                     call_id); 
     662 
     663            PJ_LOG(4,(THIS_FILE, "Answering replacement call %d with 200/OK", 
     664                                 call_id)); 
     665 
     666            /* Answer the new call with 200 response */ 
     667            status = pjsip_inv_answer(inv, 200, NULL, NULL, &tdata); 
     668            if (status == PJ_SUCCESS) 
     669                status = pjsip_inv_send_msg(inv, tdata); 
     670 
     671            if (status != PJ_SUCCESS) 
     672                pjsua_perror(THIS_FILE, "Error answering session", status); 
     673 
     674            /* Note that inv may be invalid if 200/OK has caused error in 
     675             * starting the media. 
     676             */ 
     677 
     678            PJ_LOG(4,(THIS_FILE, "Disconnecting replaced call %d", 
     679                                 replaced_call->index)); 
     680 
     681            /* Disconnect replaced invite session */ 
     682            status = pjsip_inv_end_session(replaced_inv, PJSIP_SC_GONE, NULL, 
     683                                           &tdata); 
     684            if (status == PJ_SUCCESS && tdata) 
     685                status = pjsip_inv_send_msg(replaced_inv, tdata); 
     686 
     687            if (status != PJ_SUCCESS) 
     688                pjsua_perror(THIS_FILE, "Error terminating session", status); 
     689 
     690 
     691        } else { 
     692 
     693            /* Notify application if on_incoming_call() is overriden,  
     694             * otherwise hangup the call with 480 
     695             */ 
     696            if (pjsua_var.ua_cfg.cb.on_incoming_call) { 
     697                pjsua_var.ua_cfg.cb.on_incoming_call(call->acc_id, call_id,  
     698                                                     rdata); 
     699            } else { 
     700                pjsua_call_hangup(call_id, PJSIP_SC_TEMPORARILY_UNAVAILABLE,  
     701                                  NULL, NULL); 
     702            } 
     703        } 
     704 
    555705    } 
    556706 
    557     PJSUA_UNLOCK(); 
    558     return status; 
     707on_return: 
     708    pjsip_dlg_dec_lock(dlg); 
     709    return; 
    559710} 
    560711 
    561712 
     
    595746    pjsua_call *call; 
    596747    int call_id = -1; 
    597748    int sip_err_code; 
    598     pjmedia_sdp_session *offer, *answer; 
     749    pjmedia_sdp_session *offer, *test_answer = NULL; 
    599750    pj_status_t status; 
    600751 
    601752    /* Don't want to handle anything but INVITE */ 
     
    658809        return PJ_TRUE; 
    659810    } 
    660811 
     812    call->med_tp_data.in.replaced_dlg = replaced_dlg; 
     813 
    661814    /* If this INVITE request contains Replaces header, notify application 
    662815     * about the request so that application can do subsequent checking 
    663816     * if it wants to. 
     
    697850     */ 
    698851    acc_id = call->acc_id = pjsua_acc_find_for_incoming(rdata); 
    699852 
    700     /* Get call's secure level */ 
    701     if (PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri)) 
    702         call->secure_level = 2; 
    703     else if (PJSIP_TRANSPORT_IS_SECURE(rdata->tp_info.transport)) 
    704         call->secure_level = 1; 
    705     else 
    706         call->secure_level = 0; 
    707  
    708     /* Init media channel */ 
    709     status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS,  
    710                                       call->secure_level, &sip_err_code); 
    711     if (status != PJ_SUCCESS) { 
    712         pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
    713         pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,  
    714                                       sip_err_code, NULL, 
    715                                       NULL, NULL); 
    716         PJSUA_UNLOCK(); 
    717         return PJ_TRUE; 
    718     } 
    719  
    720853    /* Parse SDP from incoming request */ 
    721854    if (rdata->msg_info.msg->body) { 
     855        pjmedia_sock_info sock_info; 
     856 
    722857        status = pjmedia_sdp_parse(rdata->tp_info.pool,  
    723858                                   (char*)rdata->msg_info.msg->body->data, 
    724859                                   rdata->msg_info.msg->body->len, &offer); 
     
    744879            return PJ_TRUE; 
    745880        } 
    746881 
     882        /* Create a template SDP answer to verify incoming SDP */ 
     883        pj_bzero(&sock_info, sizeof(sock_info)); 
     884        pj_sockaddr_in_init(&sock_info.rtp_addr_name.ipv4, NULL, 4000); 
     885        pj_sockaddr_in_init(&sock_info.rtcp_addr_name.ipv4, NULL, 4001); 
     886        status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt,  
     887                                          rdata->tp_info.pool, 
     888                                          1, &sock_info, &test_answer); 
    747889    } else { 
    748890        offer = NULL; 
     891        test_answer = NULL; 
    749892    } 
    750893 
    751     /* Get media capability from media endpoint: */ 
    752     status = pjsua_media_channel_create_sdp(call->index, rdata->tp_info.pool,  
    753                                             offer, &answer, &sip_err_code); 
    754     if (status != PJ_SUCCESS) { 
    755         pjsua_perror(THIS_FILE, "Error creating SDP answer", status); 
    756         pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,  
    757                                       sip_err_code, NULL, 
    758                                       NULL, NULL); 
    759         pjsua_media_channel_deinit(call->index); 
    760         PJSUA_UNLOCK(); 
    761         return PJ_TRUE; 
    762     } 
    763  
    764894    /* Verify that we can handle the request. */ 
    765895    options |= PJSIP_INV_SUPPORT_100REL; 
    766896    if (pjsua_var.acc[acc_id].cfg.require_100rel) 
    767897        options |= PJSIP_INV_REQUIRE_100REL; 
    768898 
    769     status = pjsip_inv_verify_request2(rdata, &options, offer, answer, NULL, 
    770                                        pjsua_var.endpt, &response); 
     899    status = pjsip_inv_verify_request2(rdata, &options, offer, test_answer, 
     900                                       NULL, pjsua_var.endpt, &response); 
    771901    if (status != PJ_SUCCESS) { 
    772902 
    773903        /* 
     
    792922        return PJ_TRUE; 
    793923    }  
    794924 
    795  
    796925    /* Get suitable Contact header */ 
    797926    if (pjsua_var.acc[acc_id].contact.slen) { 
    798927        contact = pjsua_var.acc[acc_id].contact; 
     
    833962                             &pjsua_var.acc[acc_id].cfg.auth_pref); 
    834963 
    835964    /* Create invite session: */ 
    836     status = pjsip_inv_create_uas( dlg, rdata, answer, options, &inv); 
     965    status = pjsip_inv_create_uas( dlg, rdata, NULL, options, &inv); 
    837966    if (status != PJ_SUCCESS) { 
    838967        pjsip_hdr hdr_list; 
    839968        pjsip_warning_hdr *w; 
     
    857986    /* Update NAT type of remote endpoint, only when there is SDP in 
    858987     * incoming INVITE!  
    859988     */ 
    860     if (pjsua_var.ua_cfg.nat_type_in_sdp && 
    861         pjmedia_sdp_neg_get_state(inv->neg) > PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER)  
    862     { 
    863         const pjmedia_sdp_session *remote_sdp; 
    864  
    865         if (pjmedia_sdp_neg_get_neg_remote(inv->neg, &remote_sdp)==PJ_SUCCESS) 
    866             update_remote_nat_type(call, remote_sdp); 
     989    if (pjsua_var.ua_cfg.nat_type_in_sdp && offer != NULL) { 
     990        update_remote_nat_type(call, offer); 
    867991    } 
    868992 
    869993    /* Create and attach pjsua_var data to the dialog: */ 
     
    9031027        } 
    9041028    } 
    9051029 
    906     ++pjsua_var.call_cnt; 
     1030    /* Save state */ 
     1031    call->med_tp_data.status = PJ_EPENDING; 
     1032    if (offer) { 
     1033        call->med_tp_data.in.rem_sdp =  
     1034                pjmedia_sdp_session_clone(inv->pool, offer); 
     1035    } 
    9071036 
     1037    /* Get call's secure level */ 
     1038    if (PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri)) 
     1039        call->secure_level = 2; 
     1040    else if (PJSIP_TRANSPORT_IS_SECURE(rdata->tp_info.transport)) 
     1041        call->secure_level = 1; 
     1042    else 
     1043        call->secure_level = 0; 
    9081044 
    909     /* Check if this request should replace existing call */ 
    910     if (replaced_dlg) { 
    911         pjsip_inv_session *replaced_inv; 
    912         struct pjsua_call *replaced_call; 
    913         pjsip_tx_data *tdata; 
    9141045 
    915         /* Get the invite session in the dialog */ 
    916         replaced_inv = pjsip_dlg_get_inv_session(replaced_dlg); 
    917  
    918         /* Get the replaced call instance */ 
    919         replaced_call = (pjsua_call*) replaced_dlg->mod_data[pjsua_var.mod.id]; 
    920  
    921         /* Notify application */ 
    922         if (pjsua_var.ua_cfg.cb.on_call_replaced) 
    923             pjsua_var.ua_cfg.cb.on_call_replaced(replaced_call->index, 
    924                                                  call_id); 
    925  
    926         PJ_LOG(4,(THIS_FILE, "Answering replacement call %d with 200/OK", 
    927                              call_id)); 
    928  
    929         /* Answer the new call with 200 response */ 
    930         status = pjsip_inv_answer(inv, 200, NULL, NULL, &tdata); 
    931         if (status == PJ_SUCCESS) 
    932             status = pjsip_inv_send_msg(inv, tdata); 
    933  
    934         if (status != PJ_SUCCESS) 
    935             pjsua_perror(THIS_FILE, "Error answering session", status); 
    936  
    937         /* Note that inv may be invalid if 200/OK has caused error in 
    938          * starting the media. 
    939          */ 
    940  
    941         PJ_LOG(4,(THIS_FILE, "Disconnecting replaced call %d", 
    942                              replaced_call->index)); 
    943  
    944         /* Disconnect replaced invite session */ 
    945         status = pjsip_inv_end_session(replaced_inv, PJSIP_SC_GONE, NULL, 
    946                                        &tdata); 
    947         if (status == PJ_SUCCESS && tdata) 
    948             status = pjsip_inv_send_msg(replaced_inv, tdata); 
    949  
    950         if (status != PJ_SUCCESS) 
    951             pjsua_perror(THIS_FILE, "Error terminating session", status); 
    952  
    953  
    954     } else { 
    955  
    956         /* Notify application if on_incoming_call() is overriden,  
    957          * otherwise hangup the call with 480 
    958          */ 
    959         if (pjsua_var.ua_cfg.cb.on_incoming_call) { 
    960             pjsua_var.ua_cfg.cb.on_incoming_call(acc_id, call_id, rdata); 
    961         } else { 
    962             pjsua_call_hangup(call_id, PJSIP_SC_TEMPORARILY_UNAVAILABLE,  
    963                               NULL, NULL); 
    964         } 
     1046    /* Create the media channel. Further processing to this call will 
     1047     * be done in pjsua_on_media_channel_created() when media channel  
     1048     * creation completes. 
     1049     */ 
     1050    status = pjsua_media_channel_create(call->index, PJSIP_ROLE_UAS,  
     1051                                        call->secure_level, &sip_err_code); 
     1052    if (status != PJ_SUCCESS) { 
     1053        pjsua_perror(THIS_FILE, "Error initializing media channel", status); 
     1054        pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,  
     1055                                      sip_err_code, NULL, 
     1056                                      NULL, NULL); 
     1057        PJSUA_UNLOCK(); 
     1058        return PJ_TRUE; 
    9651059    } 
    9661060 
     1061    ++pjsua_var.call_cnt; 
    9671062 
    9681063    /* This INVITE request has been handled. */ 
    9691064    PJSUA_UNLOCK(); 
     
    22902385        *p = '\0'; 
    22912386    } 
    22922387 
     2388    /* Only print media when media channel/transport is ready */ 
     2389    if (call->med_tp_data.tp==NULL || call->med_tp_data.status!=PJ_SUCCESS) 
     2390        return PJ_SUCCESS; 
     2391 
    22932392    /* Get SRTP status */ 
    22942393    pjmedia_transport_info_init(&tp_info); 
    22952394    pjmedia_transport_get_info(call->med_tp, &tp_info); 
     
    24822581/* 
    24832582 * Disconnect call upon error. 
    24842583 */ 
    2485 static void call_disconnect( pjsip_inv_session *inv,  
    2486                              int code ) 
     2584static void call_disconnect(pjsip_inv_session *inv, int code, 
     2585                            const char *res, const char *warn_text, 
     2586                            pj_status_t warn_status) 
    24872587{ 
    24882588    pjsua_call *call; 
     2589    pj_str_t str; 
    24892590    pjsip_tx_data *tdata; 
    24902591    pj_status_t status; 
    24912592 
    24922593    call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id]; 
    24932594 
    2494     status = pjsip_inv_end_session(inv, code, NULL, &tdata); 
     2595    status = pjsip_inv_end_session(inv, code, res ? pj_cstr(&str, res) : NULL, 
     2596                                   &tdata); 
    24952597    if (status != PJ_SUCCESS) 
    24962598        return; 
    24972599 
     2600    if (warn_text) { 
     2601        pjsip_warning_hdr *whdr; 
     2602        whdr = pjsip_warning_hdr_create(tdata->pool, 399,  
     2603                                        pjsip_endpt_name(pjsua_var.endpt), 
     2604                                        pj_cstr(&str, warn_text)); 
     2605        pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) whdr); 
     2606    } 
     2607 
     2608    if (warn_status) { 
     2609        pjsip_warning_hdr *whdr; 
     2610        whdr = pjsip_warning_hdr_create_from_status( 
     2611                    tdata->pool,  
     2612                    pjsip_endpt_name(pjsua_var.endpt), 
     2613                    warn_status); 
     2614        pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) whdr); 
     2615    } 
     2616 
    24982617    /* Add SDP in 488 status */ 
    24992618    if (call && call->med_tp && tdata->msg->type==PJSIP_RESPONSE_MSG &&  
    25002619        code==PJSIP_SC_NOT_ACCEPTABLE_HERE)  
     
    25452664        if (inv->state != PJSIP_INV_STATE_NULL && 
    25462665            inv->state != PJSIP_INV_STATE_CONFIRMED)  
    25472666        { 
    2548             call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 
     2667            call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE,  
     2668                            NULL, NULL, status); 
    25492669        } 
    25502670 
    25512671        PJSUA_UNLOCK(); 
     
    25852705    if (status != PJ_SUCCESS) { 
    25862706        pjsua_perror(THIS_FILE, "Unable to create media session",  
    25872707                     status); 
    2588         call_disconnect(inv, PJSIP_SC_NOT_ACCEPTABLE_HERE); 
     2708        call_disconnect(inv, PJSIP_SC_NOT_ACCEPTABLE_HERE, NULL, NULL,  
     2709                        status); 
    25892710        pjsua_media_channel_deinit(call->index); 
    25902711        PJSUA_UNLOCK(); 
    25912712        return; 
  • pjsip/src/pjsip-ua/sip_inv.c

     
    17261726    pj_status_t status; 
    17271727 
    17281728    PJ_ASSERT_RETURN(inv && sdp, PJ_EINVAL); 
     1729    PJ_ASSERT_RETURN(inv->neg, PJ_EINVALIDOP); 
     1730    PJ_ASSERT_RETURN(pjmedia_sdp_neg_get_state(inv->neg) == 
     1731                        PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER,  
     1732                     PJ_EINVALIDOP); 
    17291733 
    17301734    pjsip_dlg_inc_lock(inv->dlg); 
    17311735    status = pjmedia_sdp_neg_set_local_answer( inv->pool, inv->neg, sdp); 
     
    17361740 
    17371741 
    17381742/* 
     1743 * Set SDP offer.  
     1744 */ 
     1745PJ_DEF(pj_status_t) pjsip_inv_set_sdp_offer(pjsip_inv_session *inv, 
     1746                                            const pjmedia_sdp_session *sdp) 
     1747{ 
     1748    pj_status_t status; 
     1749 
     1750    PJ_ASSERT_RETURN(inv && sdp, PJ_EINVAL); 
     1751 
     1752    pjsip_dlg_inc_lock(inv->dlg); 
     1753    if (inv->neg == NULL) { 
     1754        status = pjmedia_sdp_neg_create_w_local_offer(inv->pool, sdp, 
     1755                                                      &inv->neg); 
     1756    } else { 
     1757        PJ_ASSERT_ON_FAIL(pjmedia_sdp_neg_get_state(inv->neg) == 
     1758                            PJMEDIA_SDP_NEG_STATE_DONE, 
     1759                          {pjsip_dlg_dec_lock(inv->dlg);  
     1760                           return PJ_EINVALIDOP; }); 
     1761 
     1762        status = pjmedia_sdp_neg_modify_local_offer(inv->pool, inv->neg, 
     1763                                                    sdp); 
     1764    } 
     1765    pjsip_dlg_dec_lock(inv->dlg); 
     1766 
     1767    return status; 
     1768} 
     1769 
     1770/* 
    17391771 * End session. 
    17401772 */ 
    17411773PJ_DEF(pj_status_t) pjsip_inv_end_session(  pjsip_inv_session *inv, 
  • pjmedia/include/pjmedia/transport.h

     
    249249                            pjmedia_transport_info *info); 
    250250 
    251251    /** 
     252     * Manage the application data. Application should use  
     253     * #pjmedia_transport_get_app_data() and #pjmedia_transport_set_app_data() 
     254     * instead. 
     255     * 
     256     * This function returns the old application data in the transport. 
     257     * If \a set argument is non-zero, new application data will be set 
     258     * from \a app_data argument, otherwise the app_data will not be 
     259     * changed. 
     260     */ 
     261    void* (*set_app_data)(pjmedia_transport *tp, pj_bool_t set,  
     262                          void *app_data); 
     263 
     264    /** 
    252265     * This function is called by the stream when the transport is about 
    253266     * to be used by the stream for the first time, and it tells the transport 
    254267     * about remote RTP address to send the packet and some callbacks to be  
     
    396409     * stacked with other transport to enable encryption on the underlying 
    397410     * transport. 
    398411     */ 
    399     PJMEDIA_TRANSPORT_TYPE_SRTP 
     412    PJMEDIA_TRANSPORT_TYPE_SRTP, 
    400413 
     414    /** Start of user defined transport type */ 
     415    PJMEDIA_TRANSPORT_TYPE_USER = 16 
     416 
    401417} pjmedia_transport_type; 
    402418 
    403419 
     
    504520 
    505521 
    506522/** 
     523 * Get the application data attached to the transport. The application data 
     524 * is set when the transport is created and it can be changed by using 
     525 * #pjmedia_transport_set_app_data(). 
     526 * 
     527 * @param tp        The media transport. 
     528 * 
     529 * @return          The application data. 
     530 */ 
     531PJ_INLINE(void*) pjmedia_transport_get_app_data(pjmedia_transport *tp) 
     532{ 
     533    return tp->op->set_app_data(tp, PJ_FALSE, NULL); 
     534} 
     535 
     536 
     537/** 
     538 * Set new application data value to the media transport. 
     539 * 
     540 * @param tp        The media transport. 
     541 * @param app_data  New application data. 
     542 * 
     543 * @return          The old application data. 
     544 */ 
     545PJ_INLINE(void*) pjmedia_transport_set_app_data(pjmedia_transport *tp, 
     546                                                void *app_data) 
     547{ 
     548    return tp->op->set_app_data(tp, PJ_TRUE, app_data); 
     549} 
     550 
     551 
     552/** 
    507553 * Attach callbacks to be called on receipt of incoming RTP/RTCP packets. 
    508554 * This is just a simple wrapper which calls <tt>attach()</tt> member of  
    509555 * the transport. 
  • pjmedia/include/pjmedia/transport_ice.h

     
    6666 * @param comp_cnt      Number of components to be created. 
    6767 * @param cfg           Pointer to configuration settings. 
    6868 * @param cb            Optional callbacks. 
     69 * @param app_data      Optional application data. 
    6970 * @param p_tp          Pointer to receive the media transport instance. 
    7071 * 
    7172 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     
    7576                                        unsigned comp_cnt, 
    7677                                        const pj_ice_strans_cfg *cfg, 
    7778                                        const pjmedia_ice_cb *cb, 
     79                                        void *app_data, 
    7880                                        pjmedia_transport **p_tp); 
    7981 
    8082PJ_END_DECL 
  • pjmedia/src/pjmedia/transport_udp.c

     
    5151 
    5252    pj_pool_t          *pool;           /**< Memory pool                    */ 
    5353    unsigned            options;        /**< Transport options.             */ 
     54    void               *app_data;       /**< Application data.              */ 
    5455    unsigned            media_options;  /**< Transport media options.       */ 
    5556    void               *user_data;      /**< Only valid when attached       */ 
    5657    pj_bool_t           attached;       /**< Has attachment?                */ 
     
    102103 */ 
    103104static pj_status_t transport_get_info (pjmedia_transport *tp, 
    104105                                       pjmedia_transport_info *info); 
     106static void*       transport_set_app_data(pjmedia_transport *tp,  
     107                                          pj_bool_t set, void *app_data); 
    105108static pj_status_t transport_attach   (pjmedia_transport *tp, 
    106109                                       void *user_data, 
    107110                                       const pj_sockaddr_t *rem_addr, 
     
    147150static pjmedia_transport_op transport_udp_op =  
    148151{ 
    149152    &transport_get_info, 
     153    &transport_set_app_data, 
    150154    &transport_attach, 
    151155    &transport_detach, 
    152156    &transport_send_rtp, 
     
    604608} 
    605609 
    606610 
     611/* Get/set application data */ 
     612static void* transport_set_app_data(pjmedia_transport *tp,  
     613                                    pj_bool_t set, void *app_data) 
     614{ 
     615    struct transport_udp *udp = (struct transport_udp*)tp; 
     616    void *old_app_data; 
     617 
     618    PJ_ASSERT_RETURN(tp, NULL); 
     619 
     620    old_app_data = udp->app_data; 
     621    if (set) 
     622        udp->app_data = app_data; 
     623 
     624    return old_app_data; 
     625} 
     626 
    607627/* Called by application to initialize the transport */ 
    608628static pj_status_t transport_attach(   pjmedia_transport *tp, 
    609629                                       void *user_data, 
  • pjmedia/src/pjmedia/transport_ice.c

     
    3030{ 
    3131    pjmedia_transport    base; 
    3232    pj_pool_t           *pool; 
     33    void                *app_data; 
    3334    int                  af; 
    3435    unsigned             comp_cnt; 
    3536    pj_ice_strans       *ice_st; 
     
    5758 */ 
    5859static pj_status_t transport_get_info (pjmedia_transport *tp, 
    5960                                       pjmedia_transport_info *info); 
     61static void*       transport_set_app_data(pjmedia_transport *tp, 
     62                                          pj_bool_t set, void *app_data); 
    6063static pj_status_t transport_attach   (pjmedia_transport *tp, 
    6164                                       void *user_data, 
    6265                                       const pj_sockaddr_t *rem_addr, 
     
    114117static pjmedia_transport_op transport_ice_op =  
    115118{ 
    116119    &transport_get_info, 
     120    &transport_set_app_data, 
    117121    &transport_attach, 
    118122    &transport_detach, 
    119123    &transport_send_rtp, 
     
    139143                                       unsigned comp_cnt, 
    140144                                       const pj_ice_strans_cfg *cfg, 
    141145                                       const pjmedia_ice_cb *cb, 
     146                                       void *app_data, 
    142147                                       pjmedia_transport **p_tp) 
    143148{ 
    144149    pj_pool_t *pool; 
     
    154159    tp_ice->pool = pool; 
    155160    tp_ice->af = cfg->af; 
    156161    tp_ice->comp_cnt = comp_cnt; 
     162    tp_ice->app_data = app_data; 
    157163    pj_ansi_strcpy(tp_ice->base.name, pool->obj_name); 
    158164    tp_ice->base.op = &transport_ice_op; 
    159165    tp_ice->base.type = PJMEDIA_TRANSPORT_TYPE_ICE; 
     
    675681} 
    676682 
    677683 
     684static void* transport_set_app_data(pjmedia_transport *tp,  
     685                                    pj_bool_t set, void *app_data) 
     686{ 
     687    struct transport_ice *tp_ice = (struct transport_ice*)tp; 
     688    void *old_app_data; 
     689 
     690    PJ_ASSERT_RETURN(tp, NULL); 
     691 
     692    old_app_data = tp_ice->app_data; 
     693    if (set) 
     694        tp_ice->app_data = app_data; 
     695 
     696    return old_app_data; 
     697} 
     698 
     699 
    678700static pj_status_t transport_attach  (pjmedia_transport *tp, 
    679701                                      void *stream, 
    680702                                      const pj_sockaddr_t *rem_addr, 
  • pjmedia/src/pjmedia/transport_srtp.c

     
    7878    pjmedia_transport    base;      /**< Base transport interface. */ 
    7979    pj_pool_t           *pool; 
    8080    pj_lock_t           *mutex; 
     81    void                *app_data; 
    8182    char                 tx_buffer[MAX_BUFFER_LEN]; 
    8283    pjmedia_srtp_setting setting; 
    8384    unsigned             media_option; 
     
    126127 */ 
    127128static pj_status_t transport_get_info (pjmedia_transport *tp, 
    128129                                       pjmedia_transport_info *info); 
     130static void*       transport_set_app_data(pjmedia_transport *tp,  
     131                                          pj_bool_t set, void *app_data); 
    129132static pj_status_t transport_attach   (pjmedia_transport *tp, 
    130133                                       void *user_data, 
    131134                                       const pj_sockaddr_t *rem_addr, 
     
    172175static pjmedia_transport_op transport_srtp_op =  
    173176{ 
    174177    &transport_get_info, 
     178    &transport_set_app_data, 
    175179    &transport_attach, 
    176180    &transport_detach, 
    177181    &transport_send_rtp, 
     
    582586    return pjmedia_transport_get_info(srtp->real_tp, info); 
    583587} 
    584588 
     589static void* transport_set_app_data(pjmedia_transport *tp,  
     590                                    pj_bool_t set, void *app_data) 
     591{ 
     592    struct transport_srtp *srtp = (struct transport_srtp*)tp; 
     593    void *old_app_data; 
     594 
     595    PJ_ASSERT_RETURN(tp, NULL); 
     596 
     597    old_app_data = srtp->app_data; 
     598    if (set) 
     599        srtp->app_data = app_data; 
     600 
     601    return old_app_data; 
     602} 
     603 
    585604static pj_status_t transport_attach(pjmedia_transport *tp, 
    586605                                    void *user_data, 
    587606                                    const pj_sockaddr_t *rem_addr,