From 3faa9f8a8f5bbe109cbb6c3d1369879edc32680f Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Tue, 26 Feb 2013 12:07:34 -0500 Subject: [PATCH] parse out rtcp attribute --- daemon/sdp.c | 106 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 23 deletions(-) diff --git a/daemon/sdp.c b/daemon/sdp.c index 0b15ecd..da3a772 100644 --- a/daemon/sdp.c +++ b/daemon/sdp.c @@ -56,6 +56,11 @@ struct sdp_media { struct sdp_attributes attributes; }; +struct attribute_rtcp { + long int port_num; + struct network_address address; +}; + struct sdp_attribute { str full_line, /* including a= and \r\n */ line_value, /* without a= and without \r\n */ @@ -63,6 +68,15 @@ struct sdp_attribute { value, /* just "8 PCMA/8000" */ key, /* "rtpmap:8" */ param; /* "PCMA/8000" */ + + enum { + ATTR_OTHER = 0, + ATTR_RTCP, + } attr; + + union { + struct attribute_rtcp rtcp; + } u; }; @@ -138,7 +152,7 @@ static inline int extract_token(char **sp, char *end, str *out) { EXTRACT_TOKEN(field.network_type); \ EXTRACT_TOKEN(field.address_type); \ EXTRACT_TOKEN(field.address); \ - if (parse_address(&output->address)) return -1 + if (parse_address(&output->field)) return -1 static int parse_origin(char *start, char *end, struct sdp_origin *output) { if (output->parsed) @@ -194,6 +208,62 @@ static void attrs_init(struct sdp_attributes *a) { a->hash = g_hash_table_new(str_hash, str_equal); } +static int parse_attribute_rtcp(struct sdp_attribute *output) { + char *ep, *start, *end; + + end = output->value.s + output->value.len; + output->attr = ATTR_RTCP; + output->u.rtcp.port_num = strtol(output->value.s, &ep, 10); + if (ep == output->value.s) + return -1; + if (output->u.rtcp.port_num <= 0 || output->u.rtcp.port_num > 0xffff) { + output->u.rtcp.port_num = 0; + return -1; + } + if (*ep != ' ') + return 0; + ep++; + if (ep >= end) + return 0; + + start = ep; + EXTRACT_NETWORK_ADDRESS(u.rtcp.address); + + return 0; +} + +static void parse_attribute(struct sdp_attribute *a) { + a->name = a->line_value; + str_chr_str(&a->value, &a->name, ':'); + if (a->value.s) { + a->name.len -= a->value.len; + a->value.s++; + a->value.len--; + + a->key = a->name; + str_chr_str(&a->param, &a->value, ' '); + if (a->param.s) { + a->key.len += 1 + + (a->value.len - a->param.len); + + a->param.s++; + a->param.len--; + + if (!a->param.len) + a->param.s = NULL; + } + else + a->key.len += 1 + a->value.len; + } + + switch (a->name.len) { + case 4: + if (!str_cmp(&a->name, "rtcp")) + parse_attribute_rtcp(a); + break; + } +} + int sdp_parse(str *body, GQueue *sessions) { char *b, *end, *value, *line_end, *next_line; struct sdp_session *session = NULL; @@ -279,28 +349,7 @@ int sdp_parse(str *body, GQueue *sessions) { attr->line_value.s = value; attr->line_value.len = line_end - value; - attr->name = attr->line_value; - str_chr_str(&attr->value, &attr->name, ':'); - if (attr->value.s) { - attr->name.len -= attr->value.len; - attr->value.s++; - attr->value.len--; - - attr->key = attr->name; - str_chr_str(&attr->param, &attr->value, ' '); - if (attr->param.s) { - attr->key.len += 1 + - (attr->value.len - attr->param.len); - - attr->param.s++; - attr->param.len--; - - if (!attr->param.len) - attr->param.s = NULL; - } - else - attr->key.len += 1 + attr->value.len; - } + parse_attribute(attr); attrs = media ? &media->attributes : &session->attributes; g_queue_push_tail(&attrs->list, attr); @@ -385,6 +434,8 @@ int sdp_streams(const GQueue *sessions, GQueue *streams, GHashTable *streamhash) GList *l, *k; const char *errstr; int i, num; + str s; + struct sdp_attribute *attr; num = 0; for (l = sessions->head; l; l = l->next) { @@ -393,6 +444,7 @@ int sdp_streams(const GQueue *sessions, GQueue *streams, GHashTable *streamhash) for (k = session->media_streams.head; k; k = k->next) { media = k->data; + si = NULL; for (i = 0; i < media->port_count; i++) { si = g_slice_alloc0(sizeof(*si)); @@ -411,6 +463,13 @@ int sdp_streams(const GQueue *sessions, GQueue *streams, GHashTable *streamhash) g_hash_table_insert(streamhash, si, si); g_queue_push_tail(streams, si); } + + if (!si || media->port_count != 1) + continue; + str_init(&s, "rtcp"); + attr = g_hash_table_lookup(media->attributes.hash, &s); + if (!attr) + continue; } } @@ -762,6 +821,7 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call, chopper_append_c(chop, " 2 UDP 2130706430 "); insert_ice_address(chop, m, off, flags, 1); chopper_append_c(chop, " typ host\r\n"); + /* XXX handle rtcp here too */ } } }