summaryrefslogtreecommitdiffstats
path: root/stream/freesdp/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'stream/freesdp/parser.c')
-rw-r--r--stream/freesdp/parser.c1890
1 files changed, 0 insertions, 1890 deletions
diff --git a/stream/freesdp/parser.c b/stream/freesdp/parser.c
deleted file mode 100644
index cb093c2bae..0000000000
--- a/stream/freesdp/parser.c
+++ /dev/null
@@ -1,1890 +0,0 @@
-/*
- This file is part of FreeSDP
- Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@altern.org>
-
- FreeSDP is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- Benjamin Zores, (C) 2006
- added support in parser for the a=control: lines.
- added support in parser for the a=range: lines.
-*/
-
-/**
- * @file parser.c
- *
- * @short Parsing module implementation.
- *
- * This file implements the parsing routine <code>fsdp_parse</code>
- * and the <code>fsdp_get_xxxx</code> routines that allow to get the
- * session properties from a session description object build through
- * the application of <code>fsdp_parse</code> to a textual SDP session
- * description.
- **/
-
-#include "parserpriv.h"
-
-/**
- * \brief find the start of the next line
- * \param c pointer to current position in string
- * \return pointer to start of next line or NULL if illegal (i.e.
- * a '\r' is not followed by a '\n'
- */
-static const char *next_line(const char *c) {
- c += strcspn(c, "\n\r");
- if (*c == 0) return c;
- if (*c == '\r') c++;
- if (*c == '\n')
- return c + 1;
- return NULL;
-}
-
-/**
- * Moves the <code>c<code> pointer up to the beginning of the next
- * line.
- *
- * @param c char pointer to pointer
- * @retval FSDPE_ILLEGAL_CHARACTER, when an illegal '\r' character
- * (not followed by a '\n') is found, returns
- */
-#define NEXT_LINE(c) do { if (!(c = next_line(c))) return FSDPE_ILLEGAL_CHARACTER; } while (0);
-
-fsdp_error_t
-fsdp_parse (const char *text_description, fsdp_description_t * dsc)
-{
- fsdp_error_t result;
- const char *p = text_description, *p2;
- unsigned int j;
- /* temps for sscanf */
- const unsigned int TEMPCHARS = 6;
- char fsdp_buf[TEMPCHARS][MAXSHORTFIELDLEN];
- char longfsdp_buf[MAXLONGFIELDLEN];
- const unsigned int TEMPINTS = 2;
- unsigned long int wuint[TEMPINTS];
-
- if ((NULL == text_description) || (NULL == dsc))
- return FSDPE_INVALID_PARAMETER;
-
- /***************************************************************************/
- /* A) parse session-level description */
- /***************************************************************************/
-
- /* `v=' line (protocol version) */
- /* according to the RFC, only `v=0' is valid */
- if (sscanf (p, "v=%1lu", &wuint[0]))
- {
- if (wuint[0] != 0)
- return FSDPE_INVALID_VERSION;
- }
- else
- {
- return FSDPE_MISSING_VERSION;
- }
- NEXT_LINE (p);
-
- /* `o=' line (owner/creator and session identifier) */
- /* o=<username> <session id> <version> <network type> <address type>
- <address> */
- if (!strncmp (p, "o=", 2))
- {
- p += 2;
- /* note that the following max lengths may vary in the future and
- are quite arbitary */
- if (sscanf
- (p,
- "%" MSFLENS "[\x21-\xFF] %" MSFLENS "[0-9] %" MSFLENS
- "[0-9] %2s %3s %" MSFLENS "s", fsdp_buf[0], fsdp_buf[1],
- fsdp_buf[2], fsdp_buf[3], fsdp_buf[4], fsdp_buf[5]) != 6)
- return FSDPE_INVALID_OWNER;
- dsc->o_username = strdup (fsdp_buf[0]);
- dsc->o_session_id = strdup (fsdp_buf[1]);
- dsc->o_announcement_version = strdup (fsdp_buf[2]);
- if (!strncmp (fsdp_buf[3], "IN", 2))
- {
- dsc->o_network_type = FSDP_NETWORK_TYPE_INET;
- if (!strncmp (fsdp_buf[4], "IP4", 3))
- dsc->o_address_type = FSDP_ADDRESS_TYPE_IPV4;
- else if (!strncmp (fsdp_buf[4], "IP6", 3))
- dsc->o_address_type = FSDP_ADDRESS_TYPE_IPV6;
- else
- return FSDPE_INVALID_OWNER;
- }
- else
- {
- return FSDPE_INVALID_OWNER;
- }
- /* TODO? check valid unicast address/FQDN */
- dsc->o_address = strdup (fsdp_buf[5]);
- }
- else
- {
- return FSDPE_MISSING_OWNER;
- }
- NEXT_LINE (p);
-
- /* `s=' line (session name) -note that the name string cannot be empty */
- /* s=<session name> */
- if (!strncmp (p, "s=", 2))
- {
- if (sscanf (p, "s=%" MLFLENS "[^\r\n]", longfsdp_buf) < 1)
- return FSDPE_EMPTY_NAME;
- dsc->s_name = strdup (longfsdp_buf);
- }
- else
- {
- return FSDPE_MISSING_NAME;
- }
- NEXT_LINE (p);
-
- /* `i=' line (session information) [optional] */
- /* i=<session description> */
- if (!strncmp (p, "i=", 2)
- && sscanf (p, "i=%" MLFLENS "[^\r\n]", longfsdp_buf))
- {
- dsc->i_information = strdup (longfsdp_buf);
- NEXT_LINE (p);
- }
- else
- {
- /* (optional) information absent */
- }
-
- /* `u=' line (URI of description) [optional] */
- /* u=<URI> */
- if (!strncmp (p, "u=", 2)
- && sscanf (p, "u=%" MLFLENS "[^\r\n]", longfsdp_buf))
- {
- /* TODO? check valid uri */
- dsc->u_uri = strdup (longfsdp_buf);
- NEXT_LINE (p);
- }
- else
- {
- /* (optional) uri absent */
- }
-
- /* `e=' lines (email address) [zero or more] */
- /* e=<email address> */
- p2 = p;
- j = 0;
- while (!strncmp (p2, "e=", 2))
- {
- /* First, count how many emails are there */
- j++;
- NEXT_LINE (p2);
- }
- dsc->emails_count = j;
- if (dsc->emails_count > 0)
- {
- /* Then, build the array of emails */
- dsc->emails = calloc (j, sizeof (const char *));
- for (j = 0; j < dsc->emails_count; j++)
- {
- sscanf (p, "e=%" MLFLENS "[^\r\n]", longfsdp_buf);
- /* TODO? check valid email-address. */
- dsc->emails[j] = strdup (longfsdp_buf);
- NEXT_LINE (p);
- }
- }
-
- /* `p=' lines (phone number) [zero or more] */
- /* p=<phone number> */
- j = 0;
- /* assert ( p2 == p ); */
- while (!strncmp (p2, "p=", 2))
- {
- j++;
- NEXT_LINE (p2);
- }
- dsc->phones_count = j;
- if (dsc->phones_count > 0)
- {
- dsc->phones = calloc (j, sizeof (const char *));
- for (j = 0; j < dsc->phones_count; j++)
- {
- sscanf (p, "p=%" MLFLENS "[^\r\n]", longfsdp_buf);
- /* TODO? check valid phone-number. */
- dsc->phones[j] = strdup (longfsdp_buf);
- NEXT_LINE (p);
- }
- }
-
- /* `c=' line (connection information - not required if included in all media) [optional] */
- /* c=<network type> <address type> <connection address> */
- result = fsdp_parse_c (&p, &(dsc->c_network_type), &(dsc->c_address_type),
- &(dsc->c_address));
- if (FSDPE_OK != result)
- return result;
-
- /* `b=' lines (bandwidth information) [optional] */
- /* b=<modifier>:<bandwidth-value> */
- result =
- fsdp_parse_b (&p, &(dsc->bw_modifiers), &(dsc->bw_modifiers_count));
- if (FSDPE_OK != result)
- return result;
-
- /* A.1) Time descriptions: */
-
- /* `t=' lines (time the session is active) [1 or more] */
- /* t=<start time> <stop time> */
- j = 0;
- p2 = p;
- while (!strncmp (p2, "t=", 2))
- {
- j++;
- NEXT_LINE (p2);
- while (!strncmp (p2, "r=", 2))
- NEXT_LINE (p2);
- }
- dsc->time_periods_count = j;
- if (dsc->time_periods_count == 0)
- return FSDPE_MISSING_TIME;
- dsc->time_periods = calloc (dsc->time_periods_count,
- sizeof (fsdp_time_period_t *));
- for (j = 0; j < dsc->time_periods_count; j++)
- {
- unsigned int h = 0;
- if (sscanf (p, "t=%10lu %10lu", &wuint[0], &wuint[1]) != 2)
- {
- /* not all periods have been successfully parsed */
- dsc->time_periods_count = j;
- return FSDPE_INVALID_TIME;
- }
- dsc->time_periods[j] = calloc (1, sizeof (fsdp_time_period_t));
-
- /* convert from NTP to time_t time */
- if (wuint[0] != 0)
- wuint[0] -= NTP_EPOCH_OFFSET;
- if (wuint[1] != 0)
- wuint[1] -= NTP_EPOCH_OFFSET;
- dsc->time_periods[j]->start = wuint[0];
- dsc->time_periods[j]->stop = wuint[1];
- NEXT_LINE (p);
-
- /* `r' lines [zero or more repeat times for each t=] */
- /*r=<repeat interval> <active duration> <list of offsets from
- start-time> */
- p2 = p;
- while (!strncmp (p2, "r=", 2))
- {
- h++;
- NEXT_LINE (p2);
- }
- dsc->time_periods[j]->repeats_count = h;
- if (h > 0)
- {
- unsigned int index2 = 0;
- dsc->time_periods[j]->repeats =
- calloc (h, sizeof (fsdp_repeat_t *));
- for (h = 0; h < dsc->time_periods[j]->repeats_count; h++)
- {
- if (sscanf (p, "r=%10s %10s %" MLFLENS "[^\r\n]",
- fsdp_buf[0], fsdp_buf[1], longfsdp_buf) == 3)
- {
- fsdp_repeat_t *repeat;
- dsc->time_periods[j]->repeats[h] =
- calloc (1, sizeof (fsdp_repeat_t));
- repeat = dsc->time_periods[j]->repeats[h];
- /* get interval, duration and list of offsets */
- result =
- fsdp_repeat_time_to_uint (fsdp_buf[0],
- &(repeat->interval));
- if (result == FSDPE_OK)
- {
- result =
- fsdp_repeat_time_to_uint (fsdp_buf[1],
- &(repeat->duration));
- if (result == FSDPE_OK)
- {
- unsigned int k = 1;
- const char *i = longfsdp_buf;
- while (NULL != (i = strchr (i, ' ')))
- {
- k++;
- if (NULL != i)
- i++;
- }
- repeat->offsets_count = k;
- repeat->offsets = calloc (k, sizeof (time_t));
- i = longfsdp_buf;
- for (k = 0;
- (k < repeat->offsets_count)
- && (result == FSDPE_OK); k++)
- {
- result =
- fsdp_repeat_time_to_uint (i,
- &(repeat->
- offsets[k]));
- i = strchr (i, ' ');
- if (NULL != i)
- i++;
- }
- if (k < repeat->offsets_count)
- {
- /* there where invalid repeat offsets */
- dsc->time_periods[j]->repeats_count = k;
- return FSDPE_INVALID_REPEAT;
- }
- }
- }
- if (result != FSDPE_OK)
- {
- /* not all repeats have been succesfully parsed */
- dsc->time_periods[j]->repeats_count = h;
- return FSDPE_INVALID_REPEAT;
- }
- NEXT_LINE (p);
- }
- else
- {
- /* not all repeats have been succesfully parsed */
- dsc->time_periods[j]->repeats_count = h;
- return FSDPE_INVALID_REPEAT;
- }
- index2++;
- }
- }
- }
-
- /* `z=' line (time zone adjustments) [zero or more] */
- /* z=<adjustment time> <offset> <adjustment time> <offset> .... */
- if (!strncmp (p, "z=", 2))
- {
- if (sscanf (p, "z=%" MLFLENS "[^\r\n]", longfsdp_buf))
- {
- /* TODO: guess how many pairs are there and process them */
- dsc->timezone_adj = strdup (longfsdp_buf);
- NEXT_LINE (p);
- }
- else
- {
- return FSDPE_INVALID_TIMEZONE;
- }
- }
-
- /* `k=' line (encryption key) [optional] */
- /* k=<method>
- k=<method>:<encryption key> */
- result = fsdp_parse_k (&p, &(dsc->k_encryption_method),
- &(dsc->k_encryption_content));
- if (result != FSDPE_OK)
- return result;
-
- /* A.2) Attributes */
- /* `a=' lines (session attribute) [0 or more] */
- /* a=<attribute>
- a=<attribute>:<value> */
- while (!strncmp (p, "a=", 2))
- {
- /* The "9" length specifier of the first string is subject to
- changes */
- if (sscanf
- (p, "a=%9[^:\r\n]:%" MSFLENS "[^\r\n]", fsdp_buf[0],
- fsdp_buf[1]) == 2)
- {
- /* session-level value attributes */
- if (!strncmp (fsdp_buf[0], "cat", 3))
- dsc->a_category = strdup (fsdp_buf[1]);
- else if (!strncmp (fsdp_buf[0], "keywds", 6))
- dsc->a_keywords = strdup (fsdp_buf[1]);
- else if (!strncmp (fsdp_buf[0], "tool", 4))
- dsc->a_keywords = strdup (fsdp_buf[1]);
- else if (!strncmp (fsdp_buf[0], "rtpmap", 6))
- fsdp_parse_rtpmap (&(dsc->a_rtpmaps),
- &(dsc->a_rtpmaps_count), fsdp_buf[1]);
- else if (!strncmp (fsdp_buf[0], "type", 4))
- {
- if (!strncmp (fsdp_buf[1], "broadcast", 9))
- dsc->a_type = FSDP_SESSION_TYPE_BROADCAST;
- else if (!strncmp (fsdp_buf[1], "meeting", 7))
- dsc->a_type = FSDP_SESSION_TYPE_MEETING;
- else if (!strncmp (fsdp_buf[1], "moderated", 9))
- dsc->a_type = FSDP_SESSION_TYPE_MODERATED;
- else if (!strncmp (fsdp_buf[1], "test", 4))
- dsc->a_type = FSDP_SESSION_TYPE_TEST;
- else if (!strncmp (fsdp_buf[1], "H332", 4))
- dsc->a_type = FSDP_SESSION_TYPE_H332;
- else
- return FSDPE_INVALID_SESSION_TYPE;
- }
- else if (!strncmp (fsdp_buf[0], "charset", 7))
- dsc->a_charset = strdup (fsdp_buf[1]);
- else if (!strncmp (fsdp_buf[0], "sdplang", 7))
- {
- if (NULL == dsc->a_sdplangs)
- {
- dsc->a_sdplangs_count = 0;
- dsc->a_sdplangs =
- calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
- }
- if (dsc->a_sdplangs_count < SDPLANGS_MAX_COUNT)
- {
- dsc->a_sdplangs[dsc->a_sdplangs_count] =
- strdup (fsdp_buf[1]);
- dsc->a_sdplangs_count++;
- }
- }
- else if (!strncmp (fsdp_buf[0], "lang", 4))
- {
- if (NULL == dsc->a_langs)
- {
- dsc->a_langs_count = 0;
- dsc->a_langs = calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
- }
- if (dsc->a_langs_count < SDPLANGS_MAX_COUNT)
- {
- dsc->a_langs[dsc->a_langs_count] = strdup (fsdp_buf[1]);
- dsc->a_langs_count++;
- }
- }
- else if (!strncmp (fsdp_buf[0], "control", 7))
- {
- if (NULL == dsc->a_controls)
- {
- dsc->a_controls_count = 0;
- dsc->a_controls =
- calloc (SDPCONTROLS_MAX_COUNT, sizeof (char *));
- }
- if (dsc->a_controls_count < SDPCONTROLS_MAX_COUNT)
- {
- dsc->a_controls[dsc->a_controls_count] =
- strdup (fsdp_buf[1]);
- dsc->a_controls_count++;
- }
- }
- else if (!strncmp (fsdp_buf[0], "range", 5))
- {
- free (dsc->a_range);
- dsc->a_range = strdup (fsdp_buf[1]);
- }
- else
- {
- /* ignore unknown attributes, but provide access to them */
- *longfsdp_buf = '\0';
- strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN-1);
- strncat (longfsdp_buf, ":", MAXLONGFIELDLEN-strlen(longfsdp_buf)-1);
- strncat (longfsdp_buf, fsdp_buf[1], MAXLONGFIELDLEN-strlen(longfsdp_buf)-1);
- if (NULL == dsc->unidentified_attributes)
- {
- dsc->unidentified_attributes_count = 0;
- dsc->unidentified_attributes =
- calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,
- sizeof (char *));
- }
- if (dsc->unidentified_attributes_count <
- UNIDENTIFIED_ATTRIBUTES_MAX_COUNT)
- {
- dsc->unidentified_attributes
- [dsc->unidentified_attributes_count] =
- strdup (longfsdp_buf);
- dsc->unidentified_attributes_count++;
- }
- }
- NEXT_LINE (p);
- }
- else if (sscanf (p, "a=%20s", fsdp_buf[0]) == 1)
- {
- /* session-level property attributes */
- if (!strncmp (fsdp_buf[0], "recvonly", 8))
- dsc->a_sendrecv_mode = FSDP_SENDRECV_RECVONLY;
- else if (!strncmp (fsdp_buf[0], "sendonly", 8))
- dsc->a_sendrecv_mode = FSDP_SENDRECV_SENDONLY;
- else if (!strncmp (fsdp_buf[0], "inactive", 8))
- dsc->a_sendrecv_mode = FSDP_SENDRECV_INACTIVE;
- else if (!strncmp (fsdp_buf[0], "sendrecv", 8))
- dsc->a_sendrecv_mode = FSDP_SENDRECV_SENDRECV;
- else
- {
- /* ignore unknown attributes, but provide access to them */
- *longfsdp_buf = '\0';
- strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN-1);
- if (NULL == dsc->unidentified_attributes)
- {
- dsc->unidentified_attributes_count = 0;
- dsc->unidentified_attributes =
- calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,
- sizeof (char *));
- }
- if (dsc->unidentified_attributes_count <
- UNIDENTIFIED_ATTRIBUTES_MAX_COUNT)
- {
- dsc->unidentified_attributes
- [dsc->unidentified_attributes_count] =
- strdup (longfsdp_buf);
- dsc->unidentified_attributes_count++;
- }
- }
- NEXT_LINE (p);
- }
- else
- return FSDPE_INVALID_ATTRIBUTE;
- }
-
- /***************************************************************************/
- /* B) parse media-level descriptions */
- /***************************************************************************/
- p2 = p;
- j = 0;
- while ((*p2 != '\0') && !strncmp (p2, "m=", 2))
- {
- char c;
- j++;
- NEXT_LINE (p2);
- while (sscanf (p2, "%c=", &c) == 1)
- {
- if (c == 'i' || c == 'c' || c == 'b' || c == 'k' || c == 'a')
- {
- NEXT_LINE (p2);
- }
- else if (c == 'm')
- {
- break;
- }
- else
- {
- return FSDPE_INVALID_LINE;
- }
- }
- }
- dsc->media_announcements_count = j;
- if (dsc->media_announcements_count == 0)
- {
- ;
- /*return FSDPE_MISSING_MEDIA; */
- }
- else
- { /* dsc->media_announcements_count > 0 */
- dsc->media_announcements =
- calloc (j, sizeof (fsdp_media_announcement_t *));
- for (j = 0; j < dsc->media_announcements_count; j++)
- {
- fsdp_media_announcement_t *media = NULL;
- /* `m=' line (media name, transport address and format list) */
- /* m=<media> <port> <transport> <fmt list> */
- /* The max. string lengths are subject to change */
- if (sscanf (p, "m=%11s %8s %7s %" MLFLENS "[^\r\n]",
- fsdp_buf[0], fsdp_buf[1], fsdp_buf[2],
- longfsdp_buf) != 4)
- {
- return FSDPE_INVALID_MEDIA;
- }
- else
- {
- dsc->media_announcements[j] =
- calloc (1, sizeof (fsdp_media_announcement_t));
- media = dsc->media_announcements[j];
- if (!strncmp (fsdp_buf[0], "audio", 5))
- media->media_type = FSDP_MEDIA_AUDIO;
- else if (!strncmp (fsdp_buf[0], "video", 5))
- media->media_type = FSDP_MEDIA_VIDEO;
- else if (!strncmp (fsdp_buf[0], "application", 11))
- media->media_type = FSDP_MEDIA_APPLICATION;
- else if (!strncmp (fsdp_buf[0], "data", 4))
- media->media_type = FSDP_MEDIA_DATA;
- else if (!strncmp (fsdp_buf[0], "control", 7))
- media->media_type = FSDP_MEDIA_CONTROL;
- else
- return FSDPE_UNKNOWN_MEDIA_TYPE;
- { /* try to get port specification as port/number */
- char *slash;
- if ((slash = strchr (fsdp_buf[1], '/')))
- {
- *slash = '\0';
- slash++;
- media->port = strtol (fsdp_buf[1], NULL, 10);
- media->port_count = strtol (slash, NULL, 10);
- }
- else
- {
- media->port = strtol (fsdp_buf[1], NULL, 10);
- media->port_count = 0;
- }
- }
- if (!strncmp (fsdp_buf[2], "RTP/AVP", 7))
- media->transport = FSDP_TP_RTP_AVP;
- else if (!strncmp (fsdp_buf[2], "udp", 3))
- media->transport = FSDP_TP_UDP;
- else if (!strncmp (fsdp_buf[2], "TCP", 3))
- media->transport = FSDP_TP_TCP;
- else if (!strncmp (fsdp_buf[2], "UDPTL", 5))
- media->transport = FSDP_TP_UDPTL;
- else if (!strncmp (fsdp_buf[2], "vat", 3))
- media->transport = FSDP_TP_VAT;
- else if (!strncmp (fsdp_buf[2], "rtp", 3))
- media->transport = FSDP_TP_OLD_RTP;
- else
- return FSDPE_UNKNOWN_MEDIA_TRANSPORT;
- {
- unsigned int k = 0;
- char *s = longfsdp_buf;
- while (NULL != (s = strchr (s, ' ')))
- {
- k++;
- if (NULL != s)
- s++;
- }
- k++; /* when there is no space left, count the last format */
- media->formats_count = k;
- media->formats = calloc (k, sizeof (char *));
- s = longfsdp_buf;
- for (k = 0; k < media->formats_count; k++)
- {
- char *space = strchr (s, ' ');
- if (NULL != space)
- *space = '\0';
- media->formats[k] = strdup (s);
- s = space + 1;
- }
- }
- NEXT_LINE (p);
- }
-
- /* `i=' line (media title) [optional] */
- /* i=<media title> */
- if (!strncmp (p, "i=", 2)
- && sscanf (p, "i=%" MLFLENS "[^\r\n]", longfsdp_buf))
- {
- media->i_title = strdup (longfsdp_buf);
- NEXT_LINE (p);
- }
- else
- {
- /* (optional) information absent */
- }
-
- /* `c=' line (connection information - overrides session-level
- line) [optional if provided at session-level] */
- /* c=<network type> <address type> <connection address> */
- result = fsdp_parse_c (&p, &(media->c_network_type),
- &(media->c_address_type),
- &(media->c_address));
- if (result != FSDPE_OK)
- return result;
-
- /* `b=' lines (bandwidth information) [optional] */
- /* b=<modifier>:<bandwidth-value> */
- result = fsdp_parse_b (&p, &(media->bw_modifiers),
- &(media->bw_modifiers_count));
- if (FSDPE_OK != result)
- return result;
-
- /* `k=' line (encryption key) [optional] */
- /* k=<method>
- k=<method>:<encryption key> */
- result = fsdp_parse_k (&p, &(media->k_encryption_method),
- &(media->k_encryption_content));
- if (result != FSDPE_OK)
- return result;
-
- /* B.1) Attributes */
-
- /* `a=' lines (zero or more media attribute lines) [optional] */
- /* a=<attribute>
- a=<attribute>:<value> */
- while (!strncmp (p, "a=", 2))
- {
- if (sscanf
- (p, "a=%9[^:\r\n]:%" MLFLENS "[^\r\n]", fsdp_buf[0],
- longfsdp_buf) == 2)
- {
- /* media-level value attributes */
- if (!strncmp (fsdp_buf[0], "ptime", 5))
- media->a_ptime = strtoul (longfsdp_buf, NULL, 10);
- else if (!strncmp (fsdp_buf[0], "maxptime", 8))
- media->a_maxptime = strtoul (longfsdp_buf, NULL, 10);
- else if (!strncmp (fsdp_buf[0], "rtpmap", 6))
- fsdp_parse_rtpmap (&(media->a_rtpmaps),
- &(media->a_rtpmaps_count),
- longfsdp_buf);
- else if (!strncmp (fsdp_buf[0], "orient", 6))
- {
- if (!strncmp (longfsdp_buf, "portrait", 8))
- media->a_orient = FSDP_ORIENT_PORTRAIT;
- else if (!strncmp (longfsdp_buf, "landscape", 9))
- media->a_orient = FSDP_ORIENT_LANDSCAPE;
- else if (!strncmp (longfsdp_buf, "seascape", 9))
- media->a_orient = FSDP_ORIENT_SEASCAPE;
- }
- else if (!strncmp (fsdp_buf[0], "sdplang", 7))
- {
- if (NULL == dsc->a_sdplangs)
- {
- media->a_sdplangs_count = 0;
- media->a_sdplangs =
- calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
- }
- if (media->a_sdplangs_count < SDPLANGS_MAX_COUNT)
- {
- media->a_sdplangs[dsc->a_sdplangs_count] =
- strdup (longfsdp_buf);
- media->a_sdplangs_count++;
- }
- }
- else if (!strncmp (fsdp_buf[0], "lang", 4))
- {
- if (NULL == dsc->a_langs)
- {
- media->a_langs_count = 0;
- media->a_langs =
- calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
- }
- if (media->a_langs_count < SDPLANGS_MAX_COUNT)
- {
- media->a_langs[dsc->a_langs_count] =
- strdup (longfsdp_buf);
- media->a_langs_count++;
- }
- }
- else if (!strncmp (fsdp_buf[0], "control", 7))
- {
- if (NULL == media->a_controls)
- {
- media->a_controls_count = 0;
- media->a_controls =
- calloc (SDPCONTROLS_MAX_COUNT, sizeof (char *));
- }
- if (media->a_controls_count < SDPCONTROLS_MAX_COUNT)
- {
- media->a_controls[media->a_controls_count] =
- strdup (longfsdp_buf);
- media->a_controls_count++;
- }
- }
- else if (!strncmp (fsdp_buf[0], "range", 5))
- {
- free (media->a_range);
- media->a_range = strdup (fsdp_buf[1]);
- }
- else if (!strncmp (fsdp_buf[0], "framerate", 9))
- media->a_framerate = strtod (longfsdp_buf, NULL);
- else if (!strncmp (fsdp_buf[0], "fmtp", 4))
- {
- if (NULL == media->a_fmtps)
- {
- media->a_fmtps_count = 0;
- media->a_fmtps =
- calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
- }
- if (media->a_fmtps_count < SDPLANGS_MAX_COUNT)
- {
- media->a_fmtps[media->a_fmtps_count] =
- strdup (longfsdp_buf);
- media->a_fmtps_count++;
- }
- }
- else if (!strncmp (fsdp_buf[0], "rtcp", 4))
- {
- int opts = 0;
- /* rtcp attribute: a=rtcp:<port> <nettype> <addrtype> <address> */
- opts =
- sscanf (longfsdp_buf, "%lu %2s %3s %" MSFLENS "s",
- &wuint[0], fsdp_buf[0], fsdp_buf[1],
- fsdp_buf[2]);
- if (opts >= 1)
- {
- media->a_rtcp_port = wuint[0];
- if (opts >= 2)
- {
- if (!strncmp (fsdp_buf[0], "IN", 2))
- {
- media->a_rtcp_network_type =
- FSDP_NETWORK_TYPE_INET;
- } /* else
- ; TODO: define error code? */
- if (opts >= 3)
- {
- if (!strncmp (fsdp_buf[1], "IP4", 3))
- media->a_rtcp_address_type =
- FSDP_ADDRESS_TYPE_IPV4;
- else if (!strncmp (fsdp_buf[1], "IP6", 3))
- media->a_rtcp_address_type =
- FSDP_ADDRESS_TYPE_IPV6;
- else
- return FSDPE_INVALID_CONNECTION_NETTYPE;
- /*add specific code? */
- if (opts >= 4)
- media->a_rtcp_address =
- strdup (fsdp_buf[2]);
- }
- }
- }
- }
- else
- {
- /* ignore unknown attributes, but provide access to them */
- *fsdp_buf[1] = '\0';
- strncat (fsdp_buf[1], fsdp_buf[0], MAXSHORTFIELDLEN-1);
- strncat (fsdp_buf[1], ":", MAXSHORTFIELDLEN-strlen(fsdp_buf[1])-1);
- strncat (fsdp_buf[1], longfsdp_buf, MAXSHORTFIELDLEN-strlen(fsdp_buf[1])-1);
- if (NULL == media->unidentified_attributes)
- {
- media->unidentified_attributes_count = 0;
- media->unidentified_attributes =
- calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,
- sizeof (char *));
- }
- if (media->unidentified_attributes_count <
- UNIDENTIFIED_ATTRIBUTES_MAX_COUNT)
- {
- media->unidentified_attributes
- [media->unidentified_attributes_count] =
- strdup (fsdp_buf[1]);
- media->unidentified_attributes_count++;
- }
- }
- NEXT_LINE (p);
- }
- else if (sscanf (p, "a=%8s", fsdp_buf[0]) == 1)
- {
- /* media-level property attributes */
- if (!strncmp (fsdp_buf[0], "recvonly", 8))
- media->a_sendrecv_mode = FSDP_SENDRECV_RECVONLY;
- else if (!strncmp (fsdp_buf[0], "sendonly", 8))
- media->a_sendrecv_mode = FSDP_SENDRECV_SENDONLY;
- else if (!strncmp (fsdp_buf[0], "inactive", 8))
- media->a_sendrecv_mode = FSDP_SENDRECV_INACTIVE;
- else if (!strncmp (fsdp_buf[0], "sendrecv", 8))
- media->a_sendrecv_mode = FSDP_SENDRECV_SENDRECV;
- else
- {
- /* ignore unknown attributes, but provide access to them */
- *longfsdp_buf = '\0';
- strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN-1);
- if (NULL == media->unidentified_attributes)
- {
- media->unidentified_attributes_count = 0;
- media->unidentified_attributes =
- calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,
- sizeof (char *));
- }
- if (media->unidentified_attributes_count <
- UNIDENTIFIED_ATTRIBUTES_MAX_COUNT)
- {
- media->unidentified_attributes
- [media->unidentified_attributes_count] =
- strdup (longfsdp_buf);
- media->unidentified_attributes_count++;
- }
- }
- NEXT_LINE (p);
- }
- else
- return FSDPE_INVALID_ATTRIBUTE;
- }
- } /* end of for */
- }
-
- /* Check c= has been given at session level or at media level for
- all media */
- if (NULL == dsc->c_address.address)
- {
- unsigned int c;
- for (c = 0; c < dsc->media_announcements_count; c++)
- if (NULL == dsc->media_announcements[c]->c_address.address)
- return FSDPE_MISSING_CONNECTION_INFO;
- }
-
- /* finish */
- if (*p == '\0')
- return FSDPE_OK;
- else
- return FSDPE_OVERFILLED;
-}
-
-static fsdp_error_t
-fsdp_parse_c (const char **p, fsdp_network_type_t * ntype,
- fsdp_address_type_t * atype,
- fsdp_connection_address_t * address)
-{
- const unsigned int TEMPCHARS = 3;
- char fsdp_buf[TEMPCHARS][MAXSHORTFIELDLEN];
-
- if (!strncmp (*p, "c=", 2))
- {
- if (sscanf (*p, "c=%2s %3s %" MSFLENS "s",
- fsdp_buf[0], fsdp_buf[1], fsdp_buf[2]))
- {
- if (!strncmp (fsdp_buf[0], "IN", 2))
- {
- *ntype = FSDP_NETWORK_TYPE_INET;
- if (!strncmp (fsdp_buf[1], "IP4", 3))
- *atype = FSDP_ADDRESS_TYPE_IPV4;
- else if (!strncmp (fsdp_buf[1], "IP6", 3))
- *atype = FSDP_ADDRESS_TYPE_IPV6;
- else
- return FSDPE_INVALID_CONNECTION_NETTYPE;
- }
- else
- {
- return FSDPE_INVALID_CONNECTION_ADDRTYPE;
- }
- {
- char *slash = strchr (fsdp_buf[2], '/');
- if (NULL == slash)
- {
- address->address = strdup (fsdp_buf[2]);
- address->address_ttl = 0;
- address->address_count = 0;
- }
- else
- {
- /* address is IP4 multicast */
- char *slash2;
- *slash = '\0';
- slash++;
- address->address = strdup (fsdp_buf[2]);
- slash2 = strchr (slash + 1, '/');
- if (NULL == slash2)
- {
- address->address_ttl = strtol (slash, NULL, 10);
- address->address_count = 0;
- }
- else
- {
- *slash2 = '\0';
- slash2++;
- address->address_ttl = strtol (slash, NULL, 10);
- address->address_count = strtol (slash2, NULL, 10);
- }
- }
- }
- NEXT_LINE (*p);
- }
- else
- {
- return FSDPE_INVALID_CONNECTION;
- }
- }
- return FSDPE_OK;
-}
-
-static fsdp_error_t
-fsdp_parse_b (const char **p, fsdp_bw_modifier_t ** bw_modifiers,
- unsigned int *bw_modifiers_count)
-{
- char fsdp_buf[MAXSHORTFIELDLEN];
- unsigned long int wuint;
- unsigned int i = 0;
- const char *lp = *p;
-
- /* count b= lines */
- while (!strncmp (lp, "b=", 2))
- {
- NEXT_LINE (lp);
- i++;
- }
- *bw_modifiers = calloc (i, sizeof (fsdp_bw_modifier_t));
- *bw_modifiers_count = i;
-
- while (i > 0)
- {
- unsigned int index = *bw_modifiers_count - i;
- if (2 == sscanf (*p, "b=%20[^:\r\n]:%lu", fsdp_buf, &wuint))
- {
- if (!strncmp (fsdp_buf, "CT", 2))
- (*bw_modifiers)[index].b_mod_type =
- FSDP_BW_MOD_TYPE_CONFERENCE_TOTAL;
- else if (!strncmp (fsdp_buf, "AS", 2))
- (*bw_modifiers)[index].b_mod_type =
- FSDP_BW_MOD_TYPE_APPLICATION_SPECIFIC;
- else if (!strncmp (fsdp_buf, "RS", 2))
- (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_RTCP_SENDERS;
- else if (!strncmp (fsdp_buf, "RR", 2))
- (*bw_modifiers)[index].b_mod_type =
- FSDP_BW_MOD_TYPE_RTCP_RECEIVERS;
- else
- {
- (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_UNKNOWN;
- (*bw_modifiers)[index].b_unknown_bw_modt =
- (char *) strdup (fsdp_buf);
- }
- (*bw_modifiers)[index].b_value = wuint;
- NEXT_LINE (*p);
- }
- else
- {
- *bw_modifiers_count -= i;
- return FSDPE_INVALID_BANDWIDTH;
- }
- i--;
- }
- return FSDPE_OK;
-}
-
-static fsdp_error_t
-fsdp_parse_k (const char **p, fsdp_encryption_method_t * method,
- char **content)
-{
- char fsdp_buf[MAXSHORTFIELDLEN];
- char longfsdp_buf[MAXLONGFIELDLEN];