Ignore:
Timestamp:
Aug 1, 2010 9:48:51 AM (14 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/sip_parser.c

    r3003 r3243  
    2121#include <pjsip/sip_uri.h> 
    2222#include <pjsip/sip_msg.h> 
     23#include <pjsip/sip_multipart.h> 
    2324#include <pjsip/sip_auth_parser.h> 
    2425#include <pjsip/sip_errno.h> 
     
    3435#include <pj/ctype.h> 
    3536#include <pj/assert.h> 
     37 
     38#define THIS_FILE           "sip_parser.c" 
    3639 
    3740#define ALNUM 
     
    269272} 
    270273 
    271 /* Concatenate unrecognized params into single string. */ 
    272 static void concat_param( pj_str_t *param, pj_pool_t *pool,  
    273                           const pj_str_t *pname, const pj_str_t *pvalue ) 
    274 { 
    275     pjsip_concat_param_imp(param, pool, pname, pvalue, ';'); 
    276 } 
    277  
    278274/* Initialize static properties of the parser. */ 
    279275static pj_status_t init_parser() 
     
    10531049         */ 
    10541050        if (ctype_hdr && scanner->curptr!=scanner->end) { 
    1055             pjsip_msg_body *body = PJ_POOL_ALLOC_T(pool, pjsip_msg_body); 
    1056             body->content_type.type = ctype_hdr->media.type; 
    1057             body->content_type.subtype = ctype_hdr->media.subtype; 
    1058             body->content_type.param = ctype_hdr->media.param; 
    1059  
    1060             body->data = scanner->curptr; 
    1061             body->len = scanner->end - scanner->curptr; 
    1062             body->print_body = &pjsip_print_text_body; 
    1063             body->clone_data = &pjsip_clone_text_data; 
     1051            /* New: if Content-Type indicates that this is a multipart 
     1052             * message body, parse it. 
     1053             */ 
     1054            const pj_str_t STR_MULTIPART = { "multipart", 9 }; 
     1055            pjsip_msg_body *body; 
     1056 
     1057            if (pj_stricmp(&ctype_hdr->media.type, &STR_MULTIPART)==0) { 
     1058                body = pjsip_multipart_parse(pool, scanner->curptr, 
     1059                                             scanner->end - scanner->curptr, 
     1060                                             &ctype_hdr->media, 0); 
     1061            } else { 
     1062                body = PJ_POOL_ALLOC_T(pool, pjsip_msg_body); 
     1063                body->content_type.type = ctype_hdr->media.type; 
     1064                body->content_type.subtype = ctype_hdr->media.subtype; 
     1065                body->content_type.param = ctype_hdr->media.param; 
     1066 
     1067                body->data = scanner->curptr; 
     1068                body->len = scanner->end - scanner->curptr; 
     1069                body->print_body = &pjsip_print_text_body; 
     1070                body->clone_data = &pjsip_clone_text_data; 
     1071            } 
    10641072 
    10651073            msg->body = body; 
     
    18481856    /* Parse media parameters */ 
    18491857    while (*scanner->curptr == ';') { 
    1850         pj_str_t pname, pvalue; 
    1851         int_parse_param(scanner, ctx->pool, &pname, &pvalue, 0); 
    1852         concat_param(&hdr->media.param, ctx->pool, &pname, &pvalue); 
     1858        pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param); 
     1859        int_parse_param(scanner, ctx->pool, &param->name, &param->value, 0); 
     1860        pj_list_push_back(&hdr->media.param, param); 
    18531861    } 
    18541862 
     
    22652273} 
    22662274 
     2275/* Parse multiple header lines */ 
     2276PJ_DEF(pj_status_t) pjsip_parse_headers( pj_pool_t *pool, char *input, 
     2277                                         pj_size_t size, pjsip_hdr *hlist, 
     2278                                         unsigned options) 
     2279{ 
     2280    enum { STOP_ON_ERROR = 1 }; 
     2281    pj_scanner scanner; 
     2282    pjsip_parse_ctx ctx; 
     2283    pj_str_t hname; 
     2284    PJ_USE_EXCEPTION; 
     2285 
     2286    pj_scan_init(&scanner, input, size, PJ_SCAN_AUTOSKIP_WS_HEADER, 
     2287                 &on_syntax_error); 
     2288 
     2289    pj_bzero(&ctx, sizeof(ctx)); 
     2290    ctx.scanner = &scanner; 
     2291    ctx.pool = pool; 
     2292 
     2293retry_parse: 
     2294    PJ_TRY 
     2295    { 
     2296        /* Parse headers. */ 
     2297        do { 
     2298            pjsip_parse_hdr_func * handler; 
     2299            pjsip_hdr *hdr = NULL; 
     2300 
     2301            /* Init hname just in case parsing fails. 
     2302             * Ref: PROTOS #2412 
     2303             */ 
     2304            hname.slen = 0; 
     2305 
     2306            /* Get hname. */ 
     2307            pj_scan_get( &scanner, &pconst.pjsip_TOKEN_SPEC, &hname); 
     2308            if (pj_scan_get_char( &scanner ) != ':') { 
     2309                PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); 
     2310            } 
     2311 
     2312            /* Find handler. */ 
     2313            handler = find_handler(&hname); 
     2314 
     2315            /* Call the handler if found. 
     2316             * If no handler is found, then treat the header as generic 
     2317             * hname/hvalue pair. 
     2318             */ 
     2319            if (handler) { 
     2320                hdr = (*handler)(&ctx); 
     2321            } else { 
     2322                hdr = parse_hdr_generic_string(&ctx); 
     2323                hdr->name = hdr->sname = hname; 
     2324            } 
     2325 
     2326            /* Single parse of header line can produce multiple headers. 
     2327             * For example, if one Contact: header contains Contact list 
     2328             * separated by comma, then these Contacts will be split into 
     2329             * different Contact headers. 
     2330             * So here we must insert list instead of just insert one header. 
     2331             */ 
     2332            if (hdr) 
     2333                pj_list_insert_nodes_before(hlist, hdr); 
     2334 
     2335            /* Parse until EOF or an empty line is found. */ 
     2336        } while (!pj_scan_is_eof(&scanner) && !IS_NEWLINE(*scanner.curptr)); 
     2337 
     2338        /* If empty line is found, eat it. */ 
     2339        if (!pj_scan_is_eof(&scanner)) { 
     2340            if (IS_NEWLINE(*scanner.curptr)) { 
     2341                pj_scan_get_newline(&scanner); 
     2342            } 
     2343        } 
     2344    } 
     2345    PJ_CATCH_ANY 
     2346    { 
     2347        PJ_LOG(4,(THIS_FILE, "Error parsing header: '%.*s' line %d col %d", 
     2348                  (int)hname.slen, hname.ptr, scanner.line, 
     2349                  pj_scan_get_col(&scanner))); 
     2350 
     2351        /* Exception was thrown during parsing. */ 
     2352        if ((options & STOP_ON_ERROR) == STOP_ON_ERROR) { 
     2353            pj_scan_fini(&scanner); 
     2354            return PJSIP_EINVALIDHDR; 
     2355        } 
     2356 
     2357        /* Skip until newline, and parse next header. */ 
     2358        if (!pj_scan_is_eof(&scanner)) { 
     2359            /* Skip until next line. 
     2360             * Watch for header continuation. 
     2361             */ 
     2362            do { 
     2363                pj_scan_skip_line(&scanner); 
     2364            } while (IS_SPACE(*scanner.curptr)); 
     2365        } 
     2366 
     2367        /* Restore flag. Flag may be set in int_parse_sip_url() */ 
     2368        scanner.skip_ws = PJ_SCAN_AUTOSKIP_WS_HEADER; 
     2369 
     2370        /* Continue parse next header, if any. */ 
     2371        if (!pj_scan_is_eof(&scanner) && !IS_NEWLINE(*scanner.curptr)) { 
     2372            goto retry_parse; 
     2373        } 
     2374 
     2375    } 
     2376    PJ_END; 
     2377 
     2378    return PJ_SUCCESS; 
     2379} 
     2380 
Note: See TracChangeset for help on using the changeset viewer.