Ignore:
Timestamp:
Aug 1, 2010 9:48:51 AM (12 years ago)
Author:
bennylp
Message:

Implemented core multipart support and support in the invite session (re #1070)

  • incoming multipart message will be handled automatically
  • for testing, enable HAVE_MULTIPART_TEST in pjsua_app.c
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c

    r3222 r3243  
    2424#include <pjsip/sip_endpoint.h> 
    2525#include <pjsip/sip_event.h> 
     26#include <pjsip/sip_multipart.h> 
    2627#include <pjsip/sip_transaction.h> 
    2728#include <pjmedia/sdp.h> 
     
    746747} 
    747748 
     749PJ_DEF(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info(pjsip_rx_data *rdata) 
     750{ 
     751    pjsip_rdata_sdp_info *sdp_info; 
     752    pjsip_msg_body *body = rdata->msg_info.msg->body; 
     753    pjsip_ctype_hdr *ctype_hdr = rdata->msg_info.ctype; 
     754    pjsip_media_type app_sdp; 
     755 
     756    sdp_info = (pjsip_rdata_sdp_info*) 
     757               rdata->endpt_info.mod_data[mod_inv.mod.id]; 
     758    if (sdp_info) 
     759        return sdp_info; 
     760 
     761    sdp_info = PJ_POOL_ZALLOC_T(rdata->tp_info.pool, 
     762                                pjsip_rdata_sdp_info); 
     763    PJ_ASSERT_RETURN(mod_inv.mod.id >= 0, sdp_info); 
     764    rdata->endpt_info.mod_data[mod_inv.mod.id] = sdp_info; 
     765 
     766    pjsip_media_type_init2(&app_sdp, "application", "sdp"); 
     767 
     768    if (body && ctype_hdr && 
     769        pj_stricmp(&ctype_hdr->media.type, &app_sdp.type)==0 && 
     770        pj_stricmp(&ctype_hdr->media.subtype, &app_sdp.subtype)==0) 
     771    { 
     772        sdp_info->body.ptr = (char*)body->data; 
     773        sdp_info->body.slen = body->len; 
     774    } else if  (body && ctype_hdr && 
     775                pj_stricmp2(&ctype_hdr->media.type, "multipart")==0 && 
     776                (pj_stricmp2(&ctype_hdr->media.subtype, "mixed")==0 || 
     777                 pj_stricmp2(&ctype_hdr->media.subtype, "alternative")==0)) 
     778    { 
     779        pjsip_multipart_part *part; 
     780 
     781        part = pjsip_multipart_find_part(body, &app_sdp, NULL); 
     782        if (part) { 
     783            sdp_info->body.ptr = (char*)part->body->data; 
     784            sdp_info->body.slen = part->body->len; 
     785        } 
     786    } 
     787 
     788    if (sdp_info->body.ptr) { 
     789        pj_status_t status; 
     790        status = pjmedia_sdp_parse(rdata->tp_info.pool, 
     791                                   sdp_info->body.ptr, 
     792                                   sdp_info->body.slen, 
     793                                   &sdp_info->sdp); 
     794        if (status == PJ_SUCCESS) 
     795            status = pjmedia_sdp_validate(sdp_info->sdp); 
     796 
     797        if (status != PJ_SUCCESS) { 
     798            sdp_info->sdp = NULL; 
     799            PJ_PERROR(1,(THIS_FILE, status, 
     800                         "Error parsing/validating SDP body")); 
     801        } 
     802 
     803        sdp_info->sdp_err = status; 
     804    } 
     805 
     806    return sdp_info; 
     807} 
     808 
     809 
    748810/* 
    749811 * Verify incoming INVITE request. 
     
    766828    pj_status_t status = PJ_SUCCESS; 
    767829    pjsip_hdr res_hdr_list; 
     830    pjsip_rdata_sdp_info *sdp_info; 
    768831 
    769832    /* Init return arguments. */ 
     
    822885     * only when the body hasn't been parsed before. 
    823886     */ 
     887    if (r_sdp == NULL) { 
     888        sdp_info = pjsip_rdata_get_sdp_info(rdata); 
     889    } else { 
     890        sdp_info = NULL; 
     891    } 
     892 
    824893    if (r_sdp==NULL && msg->body) { 
    825         pjsip_msg_body *body = msg->body; 
    826         pj_str_t str_application = {"application", 11}; 
    827         pj_str_t str_sdp = { "sdp", 3 }; 
    828         pjmedia_sdp_session *sdp; 
    829  
    830         /* Check content type. */ 
    831         if (pj_stricmp(&body->content_type.type, &str_application) != 0 || 
    832             pj_stricmp(&body->content_type.subtype, &str_sdp) != 0) 
    833         { 
    834             /* Not "application/sdp" */ 
     894 
     895        /* Check if body really contains SDP. */ 
     896        if (sdp_info->body.ptr == NULL) { 
     897            /* Couldn't find "application/sdp" */ 
    835898            code = PJSIP_SC_UNSUPPORTED_MEDIA_TYPE; 
    836899            status = PJSIP_ERRNO_FROM_SIP_STATUS(code); 
     
    849912        } 
    850913 
    851         /* Parse and validate SDP */ 
    852         status = pjmedia_sdp_parse(rdata->tp_info.pool,  
    853                                    (char*)body->data, body->len, &sdp); 
    854         if (status == PJ_SUCCESS) 
    855             status = pjmedia_sdp_validate(sdp); 
    856  
    857         if (status != PJ_SUCCESS) { 
     914        if (sdp_info->sdp_err != PJ_SUCCESS) { 
    858915            /* Unparseable or invalid SDP */ 
    859916            code = PJSIP_SC_BAD_REQUEST; 
     
    865922                w = pjsip_warning_hdr_create_from_status(rdata->tp_info.pool, 
    866923                                                         pjsip_endpt_name(endpt), 
    867                                                          status); 
     924                                                         sdp_info->sdp_err); 
    868925                PJ_ASSERT_RETURN(w, PJ_ENOMEM); 
    869926 
     
    874931        } 
    875932 
    876         r_sdp = sdp; 
     933        r_sdp = sdp_info->sdp; 
    877934    } 
    878935 
     
    11641221    struct tsx_inv_data *tsx_inv_data; 
    11651222    pjsip_msg *msg; 
    1166     pjmedia_sdp_session *rem_sdp = NULL; 
     1223    pjsip_rdata_sdp_info *sdp_info; 
    11671224    pj_status_t status; 
    11681225 
     
    12121269    pj_ansi_snprintf(inv->obj_name, PJ_MAX_OBJ_NAME, "inv%p", dlg); 
    12131270 
    1214     /* Parse SDP in message body, if present. */ 
    1215     if (msg->body) { 
    1216         pjsip_msg_body *body = msg->body; 
    1217  
    1218         /* Parse and validate SDP */ 
    1219         status = pjmedia_sdp_parse(inv->pool, (char*)body->data, body->len, 
    1220                                    &rem_sdp); 
    1221         if (status == PJ_SUCCESS) 
    1222             status = pjmedia_sdp_validate(rem_sdp); 
    1223  
    1224         if (status != PJ_SUCCESS) { 
    1225             pjsip_dlg_dec_lock(dlg); 
    1226             return status; 
    1227         } 
     1271    /* Process SDP in message body, if present. */ 
     1272    sdp_info = pjsip_rdata_get_sdp_info(rdata); 
     1273    if (sdp_info->sdp_err) { 
     1274        pjsip_dlg_dec_lock(dlg); 
     1275        return sdp_info->sdp_err; 
    12281276    } 
    12291277 
    12301278    /* Create negotiator. */ 
    1231     if (rem_sdp) { 
    1232         status = pjmedia_sdp_neg_create_w_remote_offer(inv->pool,  
    1233                                                        local_sdp, rem_sdp,  
     1279    if (sdp_info->sdp) { 
     1280        status = pjmedia_sdp_neg_create_w_remote_offer(inv->pool, local_sdp, 
     1281                                                       sdp_info->sdp, 
    12341282                                                       &inv->neg); 
    12351283                                                 
     
    13751423    PJ_ASSERT_RETURN(body != NULL, PJ_ENOMEM); 
    13761424 
    1377     body->content_type.type = STR_APPLICATION; 
    1378     body->content_type.subtype = STR_SDP; 
     1425    pjsip_media_type_init(&body->content_type, (pj_str_t*)&STR_APPLICATION, 
     1426                          (pj_str_t*)&STR_SDP); 
    13791427    body->data = sdp; 
    13801428    body->len = 0; 
     
    15281576} 
    15291577 
     1578 
    15301579/* 
    15311580 * Initiate SDP negotiation in the SDP negotiator. 
     
    15761625{ 
    15771626    struct tsx_inv_data *tsx_inv_data; 
    1578     static const pj_str_t str_application = { "application", 11 }; 
    1579     static const pj_str_t str_sdp = { "sdp", 3 }; 
    15801627    pj_status_t status; 
    15811628    pjsip_msg *msg; 
    1582     pjmedia_sdp_session *rem_sdp; 
     1629    pjsip_rdata_sdp_info *sdp_info; 
    15831630 
    15841631    /* Check if SDP is present in the message. */ 
     
    15901637    } 
    15911638 
    1592     if (pj_stricmp(&msg->body->content_type.type, &str_application) || 
    1593         pj_stricmp(&msg->body->content_type.subtype, &str_sdp)) 
    1594     { 
     1639    sdp_info = pjsip_rdata_get_sdp_info(rdata); 
     1640    if (sdp_info->body.ptr == NULL) { 
    15951641        /* Message body is not "application/sdp" */ 
    15961642        return PJMEDIA_SDP_EINSDP; 
     
    16611707    } 
    16621708 
    1663     /* Parse the SDP body. */ 
    1664  
    1665     status = pjmedia_sdp_parse(rdata->tp_info.pool,  
    1666                                (char*)msg->body->data, 
    1667                                msg->body->len, &rem_sdp); 
    1668     if (status == PJ_SUCCESS) 
    1669         status = pjmedia_sdp_validate(rem_sdp); 
    1670  
    1671     if (status != PJ_SUCCESS) { 
    1672         char errmsg[PJ_ERR_MSG_SIZE]; 
    1673         pj_strerror(status, errmsg, sizeof(errmsg)); 
    1674         PJ_LOG(4,(THIS_FILE, "Error parsing SDP in %s: %s", 
    1675                   pjsip_rx_data_get_info(rdata), errmsg)); 
     1709    /* Process the SDP body. */ 
     1710    if (sdp_info->sdp_err) { 
     1711        PJ_PERROR(4,(THIS_FILE, sdp_info->sdp_err, 
     1712                     "Error parsing SDP in %s", 
     1713                     pjsip_rx_data_get_info(rdata))); 
    16761714        return PJMEDIA_SDP_EINSDP; 
    16771715    } 
     1716 
     1717    pj_assert(sdp_info->sdp != NULL); 
    16781718 
    16791719    /* The SDP can be an offer or answer, depending on negotiator's state */ 
     
    16901730        if (inv->neg == NULL) { 
    16911731            status=pjmedia_sdp_neg_create_w_remote_offer(inv->pool, NULL, 
    1692                                                          rem_sdp, &inv->neg); 
     1732                                                         sdp_info->sdp, 
     1733                                                         &inv->neg); 
    16931734        } else { 
    16941735            status=pjmedia_sdp_neg_set_remote_offer(inv->pool_prov, inv->neg,  
    1695                                                     rem_sdp); 
     1736                                                    sdp_info->sdp); 
    16961737        } 
    16971738 
    16981739        if (status != PJ_SUCCESS) { 
    1699             char errmsg[PJ_ERR_MSG_SIZE]; 
    1700             pj_strerror(status, errmsg, sizeof(errmsg)); 
    1701             PJ_LOG(4,(THIS_FILE, "Error processing SDP offer in %s: %s", 
    1702                       pjsip_rx_data_get_info(rdata), errmsg)); 
     1740            PJ_PERROR(4,(THIS_FILE, status, "Error processing SDP offer in %", 
     1741                      pjsip_rx_data_get_info(rdata))); 
    17031742            return PJMEDIA_SDP_EINSDP; 
    17041743        } 
     
    17081747        if (mod_inv.cb.on_rx_offer && inv->notify) { 
    17091748 
    1710             (*mod_inv.cb.on_rx_offer)(inv, rem_sdp); 
     1749            (*mod_inv.cb.on_rx_offer)(inv, sdp_info->sdp); 
    17111750 
    17121751        } 
     
    17251764 
    17261765        status = pjmedia_sdp_neg_set_remote_answer(inv->pool_prov, inv->neg, 
    1727                                                    rem_sdp); 
     1766                                                   sdp_info->sdp); 
    17281767 
    17291768        if (status != PJ_SUCCESS) { 
    1730             char errmsg[PJ_ERR_MSG_SIZE]; 
    1731             pj_strerror(status, errmsg, sizeof(errmsg)); 
    1732             PJ_LOG(4,(THIS_FILE, "Error processing SDP answer in %s: %s", 
    1733                       pjsip_rx_data_get_info(rdata), errmsg)); 
     1769            PJ_PERROR(4,(THIS_FILE, status, "Error processing SDP answer in %s", 
     1770                      pjsip_rx_data_get_info(rdata))); 
    17341771            return PJMEDIA_SDP_EINSDP; 
    17351772        } 
     
    38563893            pjsip_tx_data *tdata; 
    38573894            pj_status_t status; 
     3895            pjsip_rdata_sdp_info *sdp_info; 
    38583896            pjsip_status_code st_code; 
    38593897 
     
    39263964             * Otherwise generate offer from local active SDP. 
    39273965             */ 
    3928             if (rdata->msg_info.msg->body != NULL) { 
     3966            sdp_info = pjsip_rdata_get_sdp_info(rdata); 
     3967            if (sdp_info->sdp != NULL) { 
    39293968                status = process_answer(inv, 200, tdata, NULL); 
    39303969            } else { 
Note: See TracChangeset for help on using the changeset viewer.