Module: sip-router
Branch: master
Commit: b7a1ea4c8a88eea873bf6b4bfac5e1f477a19073
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=b7a1ea4…
Author: Juha Heinanen <jh(a)tutpro.com>
Committer: Juha Heinanen <jh(a)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);