Module: sip-router Branch: master Commit: b7a1ea4c8a88eea873bf6b4bfac5e1f477a19073 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=b7a1ea4c...
Author: Juha Heinanen jh@tutpro.com Committer: Juha Heinanen jh@tutpro.com Date: Mon Dec 31 15:51:53 2012 +0200
parser/sdp: added partial parsing of a=candidate attributes
---
parser/sdp/sdp.c | 20 +++++++++++- parser/sdp/sdp.h | 14 ++++++++ parser/sdp/sdp_helpr_funcs.c | 74 ++++++++++++++++++++++++++++++++++++++++++ parser/sdp/sdp_helpr_funcs.h | 2 + 4 files changed, 109 insertions(+), 1 deletions(-)
diff --git a/parser/sdp/sdp.c b/parser/sdp/sdp.c index df017be..ab04d60 100644 --- a/parser/sdp/sdp.c +++ b/parser/sdp/sdp.c @@ -161,6 +161,7 @@ static inline sdp_payload_attr_t *add_sdp_payload(sdp_stream_cell_t* _stream, in return payload_attr; }
+ /** * Initialize fast access pointers. */ @@ -550,6 +551,8 @@ static int parse_sdp_session(str *sdp_body, int session_num, str *cnt_disp, sdp_ a1p = fmtp_string.s + fmtp_string.len; payload_attr = (sdp_payload_attr_t*)get_sdp_payload4payload(stream, &rtp_payload); set_sdp_payload_fmtp(payload_attr, &fmtp_string); + } else if (parse_payload_attr && extract_candidate(&tmpstr1, stream) == 0) { + a1p += 2; } else if (extract_accept_types(&tmpstr1, &stream->accept_types) == 0) { a1p = stream->accept_types.s + stream->accept_types.len; } else if (extract_accept_wrapped_types(&tmpstr1, &stream->accept_wrapped_types) == 0) { @@ -777,6 +780,7 @@ void free_sdp(sdp_info_t** _sdp) sdp_session_cell_t *session, *l_session; sdp_stream_cell_t *stream, *l_stream; sdp_payload_attr_t *payload, *l_payload; + sdp_ice_attr_t *tmp;
LM_DBG("_sdp = %p\n", _sdp); if (sdp == NULL) return; @@ -799,6 +803,11 @@ void free_sdp(sdp_info_t** _sdp) if (l_stream->p_payload_attr) { pkg_free(l_stream->p_payload_attr); } + while (l_stream->ice_attr) { + tmp = l_stream->ice_attr->next; + pkg_free(l_stream->ice_attr); + l_stream->ice_attr->next = tmp; + } pkg_free(l_stream); } pkg_free(l_session); @@ -811,8 +820,9 @@ void free_sdp(sdp_info_t** _sdp) void print_sdp_stream(sdp_stream_cell_t *stream, int log_level) { sdp_payload_attr_t *payload; + sdp_ice_attr_t *ice_attr;
- LOG(log_level , "....stream[%d]:%p=>%p {%p} '%.*s' '%.*s:%.*s:%.*s' '%.*s' [%d] '%.*s' '%.*s:%.*s' (%d)=>%p '%.*s' '%.*s' '%.*s' '%.*s' '%.*s' '%.*s'\n", + LOG(log_level , "....stream[%d]:%p=>%p {%p} '%.*s' '%.*s:%.*s:%.*s' '%.*s' [%d] '%.*s' '%.*s:%.*s' (%d)=>%p (%d)=>%p '%.*s' '%.*s' '%.*s' '%.*s' '%.*s' '%.*s'\n", stream->stream_num, stream, stream->next, stream->p_payload_attr, stream->media.len, stream->media.s, @@ -822,6 +832,7 @@ void print_sdp_stream(sdp_stream_cell_t *stream, int log_level) stream->payloads.len, stream->payloads.s, stream->bw_type.len, stream->bw_type.s, stream->bw_width.len, stream->bw_width.s, stream->payloads_num, stream->payload_attr, + stream->ice_attrs_num, stream->ice_attr, stream->sendrecv_mode.len, stream->sendrecv_mode.s, stream->ptime.len, stream->ptime.s, stream->path.len, stream->path.s, @@ -840,6 +851,13 @@ void print_sdp_stream(sdp_stream_cell_t *stream, int log_level) payload->fmtp_string.len, payload->fmtp_string.s); payload=payload->next; } + ice_attr = stream->ice_attr; + while (ice_attr) { + LOG(log_level, "......'%.*s' %u\n", + ice_attr->foundation.len, ice_attr->foundation.s, + ice_attr->component_id); + ice_attr = ice_attr->next; + } }
void print_sdp_session(sdp_session_cell_t *session, int log_level) diff --git a/parser/sdp/sdp.h b/parser/sdp/sdp.h index 464c835..dc0dede 100644 --- a/parser/sdp/sdp.h +++ b/parser/sdp/sdp.h @@ -42,6 +42,17 @@ typedef struct sdp_payload_attr { str fmtp_string; } sdp_payload_attr_t;
+typedef struct sdp_ice_attr { + struct sdp_ice_attr *next; + str foundation; + unsigned int component_id; + str transport; + str connection_addr; + str port; + str candidate_type; + int candidateType; /* ICE_HOST/ICE_SRFLX/ICE_PRFLX/ICE_RELAY/ICE_UNKNOWN */ +} sdp_ice_attr_t; + typedef struct sdp_stream_cell { struct sdp_stream_cell *next; /* c=<network type> <address type> <connection address> */ @@ -72,6 +83,9 @@ typedef struct sdp_stream_cell { str accept_wrapped_types; /**< RFC4975: accept-wrapped-types attribute */ struct sdp_payload_attr **p_payload_attr; /**< fast access pointers to payloads */ struct sdp_payload_attr *payload_attr; + int ice_attrs_num; /**< number of ICE attrs inside a stream */ + /* add fast access pointers to ice attributes if you need them */ + sdp_ice_attr_t *ice_attr; } sdp_stream_cell_t;
typedef struct sdp_session_cell { diff --git a/parser/sdp/sdp_helpr_funcs.c b/parser/sdp/sdp_helpr_funcs.c index 9fed80b..0b04530 100644 --- a/parser/sdp/sdp_helpr_funcs.c +++ b/parser/sdp/sdp_helpr_funcs.c @@ -27,10 +27,12 @@ */
+#include <stdlib.h> #include "../../ut.h" #include "../msg_parser.h" #include "../parser_f.h" #include "../parse_hname2.h" +#include "sdp.h"
static struct { @@ -309,6 +311,78 @@ int extract_fmtp( str *body, str *fmtp_payload, str *fmtp_string ) return 0; }
+ +/** + * Allocate a new ice attribute + */ +static inline sdp_ice_attr_t *add_sdp_ice(sdp_stream_cell_t* _stream) +{ + sdp_ice_attr_t *ice_attr; + int len; + + len = sizeof(sdp_ice_attr_t); + ice_attr = (sdp_ice_attr_t *)pkg_malloc(len); + if (ice_attr == NULL) { + LM_ERR("No memory left\n"); + return NULL; + } + memset( ice_attr, 0, len); + + /* Insert the new ice attribute */ + ice_attr->next = _stream->ice_attr; + _stream->ice_attr = ice_attr; + _stream->ice_attrs_num++; + + return ice_attr; +} + + +int extract_candidate(str *body, sdp_stream_cell_t *stream) +{ + char *space, *start; + int len, fl; + sdp_ice_attr_t *ice_attr; + + if (strncasecmp(body->s, "a=candidate:", 12) != 0) { + /*LM_DBG("We are not pointing to an a=candidate: attribute =>`%.*s'\n", body->len, body->s); */ + return -1; + } + + start = body->s + 12; + len = body->len - 12; + + space = memchr(start, 32, len); + if ((space == NULL) || (space - start + 3 > len) || !isdigit(*(space + 1))) { + LM_ERR("no component in `a=candidate'\n"); + return -1; + } + + fl = space - start; + + start = space + 1; + len = len - (space - start + 1); + space = memchr(start, 32, len); + if (space == NULL) { + LM_ERR("no component in `a=candidate'\n"); + return -1; + } + + ice_attr = add_sdp_ice(stream); + if (ice_attr == NULL) { + LM_ERR("failed to add ice attribute\n"); + return -1; + } + + /* currently only foundation and component-id are parsed */ + /* if needed, parse more */ + ice_attr->foundation.s = body->s + 12; + ice_attr->foundation.len = fl; + ice_attr->component_id = strtol(start, (char **)NULL, 10); + + return 0; +} + + /* generic method for attribute extraction * field must has format "a=attrname:" */ int extract_field(str *body, str *value, str field) diff --git a/parser/sdp/sdp_helpr_funcs.h b/parser/sdp/sdp_helpr_funcs.h index 2456cee..cc46375 100644 --- a/parser/sdp/sdp_helpr_funcs.h +++ b/parser/sdp/sdp_helpr_funcs.h @@ -33,6 +33,7 @@
#include "../../str.h" #include "../msg_parser.h" +#include "sdp.h"
/** * Detect the mixed part delimiter. @@ -50,6 +51,7 @@ int extract_sendrecv_mode(str *body, str *sendrecv_mode, int *is_on_hold); int extract_mediaip(str *body, str *mediaip, int *pf, char *line); int extract_media_attr(str *body, str *mediamedia, str *mediaport, str *mediatransport, str *mediapayload, int *is_rtp); int extract_bwidth(str *body, str *bwtype, str *bwwitdth); +int extract_candidate(str *body, sdp_stream_cell_t *stream);
/* RFC3605 attributes */ int extract_rtcp(str *body, str *rtcp);