Esempio n. 1
0
PJ_DEF(pj_status_t) pjmedia_sdp_attr_get_rtcp(const pjmedia_sdp_attr *attr,
					      pjmedia_sdp_rtcp_attr *rtcp)
{
    pj_scanner scanner;
    pj_str_t token;
    pj_status_t status = -1;
    PJ_USE_EXCEPTION;

    PJ_ASSERT_RETURN(pj_strcmp2(&attr->name, "rtcp")==0, PJ_EINVALIDOP);

    init_sdp_parser();

    /* fmtp BNF:
     *	a=rtcp:<port> [nettype addrtype address]
     */

    pj_scan_init(&scanner, (char*)attr->value.ptr, attr->value.slen,
		 PJ_SCAN_AUTOSKIP_WS, &on_scanner_error);

    /* Init */
    rtcp->net_type.slen = rtcp->addr_type.slen = rtcp->addr.slen = 0;

    /* Parse */
    PJ_TRY {

	/* Get the port */
	pj_scan_get(&scanner, &cs_token, &token);
	rtcp->port = pj_strtoul(&token);

	/* Have address? */
	if (!pj_scan_is_eof(&scanner)) {

	    /* Get network type */
	    pj_scan_get(&scanner, &cs_token, &rtcp->net_type);

	    /* Get address type */
	    pj_scan_get(&scanner, &cs_token, &rtcp->addr_type);

	    /* Get the address */
	    pj_scan_get(&scanner, &cs_token, &rtcp->addr);

	}

	status = PJ_SUCCESS;

    }
    PJ_CATCH_ANY {
	status = PJMEDIA_SDP_EINRTCP;
    }
    PJ_END;

    pj_scan_fini(&scanner);
    return status;
}
Esempio n. 2
0
/*
 * Parse SDP message.
 */
PJ_DEF(pj_status_t) pjmedia_sdp_parse( pj_pool_t *pool,
				       char *buf, pj_size_t len, 
				       pjmedia_sdp_session **p_sdp)
{
    pj_scanner scanner;
    pjmedia_sdp_session *session;
    pjmedia_sdp_media *media = NULL;
    void *attr;
    pjmedia_sdp_conn *conn;
    pj_str_t dummy;
    int cur_name = 254;
    parse_context ctx;
    PJ_USE_EXCEPTION;

    ctx.last_error = PJ_SUCCESS;

    init_sdp_parser();

    pj_scan_init(&scanner, buf, len, 0, &on_scanner_error);
    session = pj_pool_calloc(pool, 1, sizeof(pjmedia_sdp_session));
    PJ_ASSERT_RETURN(session != NULL, PJ_ENOMEM);

    PJ_TRY {
	while (!pj_scan_is_eof(&scanner)) {
		cur_name = *scanner.curptr;
		switch (cur_name) {
		case 'a':
		    attr = parse_attr(pool, &scanner, &ctx);
		    if (attr) {
			if (media) {
			    media->attr[media->attr_count++] = attr;
			} else {
			    session->attr[session->attr_count++] = attr;
			}
		    }
		    break;
		case 'o':
		    parse_origin(&scanner, session, &ctx);
		    break;
		case 's':
		    parse_generic_line(&scanner, &session->name, &ctx);
		    break;
		case 'c':
		    conn = pj_pool_calloc(pool, 1, sizeof(*conn));
		    parse_connection_info(&scanner, conn, &ctx);
		    if (media) {
			media->conn = conn;
		    } else {
			session->conn = conn;
		    }
		    break;
		case 't':
		    parse_time(&scanner, session, &ctx);
		    break;
		case 'm':
		    media = pj_pool_calloc(pool, 1, sizeof(*media));
		    parse_media(&scanner, media, &ctx);
		    session->media[ session->media_count++ ] = media;
		    break;
		case 'v':
		    parse_version(&scanner, &ctx);
		    break;
		case 13:
		    /* Allow empty newline at the end of the message */
		    pj_scan_get_char(&scanner);
		    /* Continue below */
		case 10:
		    pj_scan_get_char(&scanner);
		    if (!pj_scan_is_eof(&scanner)) {
			on_scanner_error(&scanner);
		    }
		    break;
		default:
		    if (cur_name >= 'a' && cur_name <= 'z')
			parse_generic_line(&scanner, &dummy, &ctx);
		    else  {
			ctx.last_error = PJMEDIA_SDP_EINSDP;
			on_scanner_error(&scanner);
		    }
		    break;
		}
	}

	ctx.last_error = PJ_SUCCESS;

    }
    PJ_CATCH(SYNTAX_ERROR) {
	
	char errmsg[PJ_ERR_MSG_SIZE];
	pj_strerror(ctx.last_error, errmsg, sizeof(errmsg));

	PJ_LOG(4, (THIS_FILE, "Error parsing SDP in line %d col %d: %s",
		   scanner.line, pj_scan_get_col(&scanner),
		   errmsg));

	session = NULL;

	pj_assert(ctx.last_error != PJ_SUCCESS);
    }
    PJ_END;

    pj_scan_fini(&scanner);

    *p_sdp = session;
    return ctx.last_error;
}
Esempio n. 3
0
PJ_DEF(pj_status_t) pjmedia_sdp_attr_get_rtpmap( const pjmedia_sdp_attr *attr,
						 pjmedia_sdp_rtpmap *rtpmap)
{
    pj_scanner scanner;
    pj_str_t token;
    pj_status_t status = -1;
    char term = 0;
    PJ_USE_EXCEPTION;

    PJ_ASSERT_RETURN(pj_strcmp2(&attr->name, "rtpmap")==0, PJ_EINVALIDOP);

    PJ_ASSERT_RETURN(attr->value.slen != 0, PJMEDIA_SDP_EINATTR);

    init_sdp_parser();

    /* Check if input is null terminated, and null terminate if
     * necessary. Unfortunately this may crash the application if
     * attribute was allocated from a read-only memory location.
     * But this shouldn't happen as attribute's value normally is
     * null terminated.
     */
    if (attr->value.ptr[attr->value.slen] != 0 &&
	attr->value.ptr[attr->value.slen] != '\r' &&
	attr->value.ptr[attr->value.slen] != '\n')
    {
	pj_assert(!"Shouldn't happen");
	term = attr->value.ptr[attr->value.slen];
	attr->value.ptr[attr->value.slen] = '\0';
    }

    pj_scan_init(&scanner, (char*)attr->value.ptr, attr->value.slen,
		 PJ_SCAN_AUTOSKIP_WS, &on_scanner_error);

    /* rtpmap sample:
     *	a=rtpmap:98 L16/16000/2.
     */

    /* Init */
    rtpmap->pt.slen = rtpmap->param.slen = rtpmap->enc_name.slen = 0;
    rtpmap->clock_rate = 0;

    /* Parse */
    PJ_TRY {

	/* Get payload type. */
	pj_scan_get(&scanner, &cs_token, &rtpmap->pt);


	/* Get encoding name. */
	pj_scan_get(&scanner, &cs_token, &rtpmap->enc_name);

	/* Expecting '/' after encoding name. */
	if (pj_scan_get_char(&scanner) != '/') {
	    status = PJMEDIA_SDP_EINRTPMAP;
	    goto on_return;
	}


	/* Get the clock rate. */
	pj_scan_get(&scanner, &cs_digit, &token);
	rtpmap->clock_rate = pj_strtoul(&token);

	/* Expecting either '/' or EOF */
	if (*scanner.curptr == '/') {
	    pj_scan_get_char(&scanner);
	    rtpmap->param.ptr = scanner.curptr;
	    rtpmap->param.slen = scanner.end - scanner.curptr;
	} else {
	    rtpmap->param.slen = 0;
	}

	status = PJ_SUCCESS;
    }
    PJ_CATCH_ANY {
	status = PJMEDIA_SDP_EINRTPMAP;
    }
    PJ_END;


on_return:
    pj_scan_fini(&scanner);
    if (term) {
	attr->value.ptr[attr->value.slen] = term;
    }
    return status;
}
Esempio n. 4
0
/*
 * Parse SDP message.
 */
PJ_DEF(pj_status_t) pjmedia_sdp_parse( pj_pool_t *pool,
				       char *buf, pj_size_t len, 
				       pjmedia_sdp_session **p_sdp)
{
    pj_scanner scanner;
    pjmedia_sdp_session *session;
    pjmedia_sdp_media *media = NULL;
    pjmedia_sdp_attr *attr;
    pjmedia_sdp_conn *conn;
    pjmedia_sdp_bandw *bandw;
    pj_str_t dummy;
    int cur_name = 254;
    parse_context ctx;
    PJ_USE_EXCEPTION;

    ctx.last_error = PJ_SUCCESS;

    init_sdp_parser();

    pj_scan_init(&scanner, buf, len, 0, &on_scanner_error);
    session = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_session);
    PJ_ASSERT_RETURN(session != NULL, PJ_ENOMEM);

    /* Ignore leading newlines */
    while (*scanner.curptr=='\r' || *scanner.curptr=='\n')
	pj_scan_get_char(&scanner);

    PJ_TRY {
	while (!pj_scan_is_eof(&scanner)) {
		cur_name = *scanner.curptr;
		switch (cur_name) {
		case 'a':
		    attr = parse_attr(pool, &scanner, &ctx);
		    if (attr) {
			if (media) {
			    if (media->attr_count < PJMEDIA_MAX_SDP_ATTR)
				pjmedia_sdp_media_add_attr(media, attr);
			    else
				PJ_PERROR(2, (THIS_FILE, PJ_ETOOMANY,
					      "Error adding media attribute, "
					      "attribute is ignored"));
			} else {
			    if (session->attr_count < PJMEDIA_MAX_SDP_ATTR)
				pjmedia_sdp_session_add_attr(session, attr);
			    else
				PJ_PERROR(2, (THIS_FILE, PJ_ETOOMANY,
					      "Error adding session attribute"
					      ", attribute is ignored"));
			}
		    }
		    break;
		case 'o':
		    parse_origin(&scanner, session, &ctx);
		    break;
		case 's':
		    parse_generic_line(&scanner, &session->name, &ctx);
		    break;
		case 'c':
		    conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn);
		    parse_connection_info(&scanner, conn, &ctx);
		    if (media) {
			media->conn = conn;
		    } else {
			session->conn = conn;
		    }
		    break;
		case 't':
		    parse_time(&scanner, session, &ctx);
		    break;
		case 'm':
		    media = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media);
		    parse_media(&scanner, media, &ctx);
		    if (session->media_count < PJMEDIA_MAX_SDP_MEDIA)
			session->media[ session->media_count++ ] = media;
		    else
			PJ_PERROR(2,(THIS_FILE, PJ_ETOOMANY,
				     "Error adding media, media is ignored"));
		    break;
		case 'v':
		    parse_version(&scanner, &ctx);
		    break;
		case 13:
		case 10:
		    pj_scan_get_char(&scanner);
		    /* Allow empty newlines at the end of the message */
		    while (!pj_scan_is_eof(&scanner)) {
			if (*scanner.curptr != 13 && *scanner.curptr != 10) {
			    ctx.last_error = PJMEDIA_SDP_EINSDP;
			    on_scanner_error(&scanner);
			}
			pj_scan_get_char(&scanner);
		    }
		    break;
		case 'b':
		    bandw = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_bandw);
		    parse_bandwidth_info(&scanner, bandw, &ctx);
		    if (media) {
			if (media->bandw_count < PJMEDIA_MAX_SDP_BANDW)
			    media->bandw[media->bandw_count++] = bandw;
			else
			    PJ_PERROR(2, (THIS_FILE, PJ_ETOOMANY,
					  "Error adding media bandwidth "
					  "info, info is ignored"));
		    } else {
			if (session->bandw_count < PJMEDIA_MAX_SDP_BANDW)
			    session->bandw[session->bandw_count++] = bandw;
			else
			    PJ_PERROR(2, (THIS_FILE, PJ_ETOOMANY,
					  "Error adding session bandwidth "
					  "info, info is ignored"));
		    }
		    break;
		default:
		    if (cur_name >= 'a' && cur_name <= 'z')
			parse_generic_line(&scanner, &dummy, &ctx);
		    else  {
			ctx.last_error = PJMEDIA_SDP_EINSDP;
			on_scanner_error(&scanner);
		    }
		    break;
		}
	}

	ctx.last_error = PJ_SUCCESS;

    }
    PJ_CATCH_ANY {
	
	char errmsg[PJ_ERR_MSG_SIZE];
	pj_strerror(ctx.last_error, errmsg, sizeof(errmsg));

	PJ_LOG(4, (THIS_FILE, "Error parsing SDP in line %d col %d: %s",
		   scanner.line, pj_scan_get_col(&scanner),
		   errmsg));

	session = NULL;

	pj_assert(ctx.last_error != PJ_SUCCESS);
    }
    PJ_END;

    pj_scan_fini(&scanner);

    if (session)
	apply_media_direction(session);

    *p_sdp = session;
    return ctx.last_error;
}