cocoa_common: refactor menu generation
[mplayer.git] / stream / freesdp / parser.c
blobcb093c2baeb2e9c6aafb7ee3de352055c9eb9ee8
1 /*
2 This file is part of FreeSDP
3 Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@altern.org>
5 FreeSDP is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 Benjamin Zores, (C) 2006
20 added support in parser for the a=control: lines.
21 added support in parser for the a=range: lines.
24 /**
25 * @file parser.c
27 * @short Parsing module implementation.
29 * This file implements the parsing routine <code>fsdp_parse</code>
30 * and the <code>fsdp_get_xxxx</code> routines that allow to get the
31 * session properties from a session description object build through
32 * the application of <code>fsdp_parse</code> to a textual SDP session
33 * description.
34 **/
36 #include "parserpriv.h"
38 /**
39 * \brief find the start of the next line
40 * \param c pointer to current position in string
41 * \return pointer to start of next line or NULL if illegal (i.e.
42 * a '\r' is not followed by a '\n'
44 static const char *next_line(const char *c) {
45 c += strcspn(c, "\n\r");
46 if (*c == 0) return c;
47 if (*c == '\r') c++;
48 if (*c == '\n')
49 return c + 1;
50 return NULL;
53 /**
54 * Moves the <code>c<code> pointer up to the beginning of the next
55 * line.
57 * @param c char pointer to pointer
58 * @retval FSDPE_ILLEGAL_CHARACTER, when an illegal '\r' character
59 * (not followed by a '\n') is found, returns
61 #define NEXT_LINE(c) do { if (!(c = next_line(c))) return FSDPE_ILLEGAL_CHARACTER; } while (0);
63 fsdp_error_t
64 fsdp_parse (const char *text_description, fsdp_description_t * dsc)
66 fsdp_error_t result;
67 const char *p = text_description, *p2;
68 unsigned int j;
69 /* temps for sscanf */
70 const unsigned int TEMPCHARS = 6;
71 char fsdp_buf[TEMPCHARS][MAXSHORTFIELDLEN];
72 char longfsdp_buf[MAXLONGFIELDLEN];
73 const unsigned int TEMPINTS = 2;
74 unsigned long int wuint[TEMPINTS];
76 if ((NULL == text_description) || (NULL == dsc))
77 return FSDPE_INVALID_PARAMETER;
79 /***************************************************************************/
80 /* A) parse session-level description */
81 /***************************************************************************/
83 /* `v=' line (protocol version) */
84 /* according to the RFC, only `v=0' is valid */
85 if (sscanf (p, "v=%1lu", &wuint[0]))
87 if (wuint[0] != 0)
88 return FSDPE_INVALID_VERSION;
90 else
92 return FSDPE_MISSING_VERSION;
94 NEXT_LINE (p);
96 /* `o=' line (owner/creator and session identifier) */
97 /* o=<username> <session id> <version> <network type> <address type>
98 <address> */
99 if (!strncmp (p, "o=", 2))
101 p += 2;
102 /* note that the following max lengths may vary in the future and
103 are quite arbitary */
104 if (sscanf
106 "%" MSFLENS "[\x21-\xFF] %" MSFLENS "[0-9] %" MSFLENS
107 "[0-9] %2s %3s %" MSFLENS "s", fsdp_buf[0], fsdp_buf[1],
108 fsdp_buf[2], fsdp_buf[3], fsdp_buf[4], fsdp_buf[5]) != 6)
109 return FSDPE_INVALID_OWNER;
110 dsc->o_username = strdup (fsdp_buf[0]);
111 dsc->o_session_id = strdup (fsdp_buf[1]);
112 dsc->o_announcement_version = strdup (fsdp_buf[2]);
113 if (!strncmp (fsdp_buf[3], "IN", 2))
115 dsc->o_network_type = FSDP_NETWORK_TYPE_INET;
116 if (!strncmp (fsdp_buf[4], "IP4", 3))
117 dsc->o_address_type = FSDP_ADDRESS_TYPE_IPV4;
118 else if (!strncmp (fsdp_buf[4], "IP6", 3))
119 dsc->o_address_type = FSDP_ADDRESS_TYPE_IPV6;
120 else
121 return FSDPE_INVALID_OWNER;
123 else
125 return FSDPE_INVALID_OWNER;
127 /* TODO? check valid unicast address/FQDN */
128 dsc->o_address = strdup (fsdp_buf[5]);
130 else
132 return FSDPE_MISSING_OWNER;
134 NEXT_LINE (p);
136 /* `s=' line (session name) -note that the name string cannot be empty */
137 /* s=<session name> */
138 if (!strncmp (p, "s=", 2))
140 if (sscanf (p, "s=%" MLFLENS "[^\r\n]", longfsdp_buf) < 1)
141 return FSDPE_EMPTY_NAME;
142 dsc->s_name = strdup (longfsdp_buf);
144 else
146 return FSDPE_MISSING_NAME;
148 NEXT_LINE (p);
150 /* `i=' line (session information) [optional] */
151 /* i=<session description> */
152 if (!strncmp (p, "i=", 2)
153 && sscanf (p, "i=%" MLFLENS "[^\r\n]", longfsdp_buf))
155 dsc->i_information = strdup (longfsdp_buf);
156 NEXT_LINE (p);
158 else
160 /* (optional) information absent */
163 /* `u=' line (URI of description) [optional] */
164 /* u=<URI> */
165 if (!strncmp (p, "u=", 2)
166 && sscanf (p, "u=%" MLFLENS "[^\r\n]", longfsdp_buf))
168 /* TODO? check valid uri */
169 dsc->u_uri = strdup (longfsdp_buf);
170 NEXT_LINE (p);
172 else
174 /* (optional) uri absent */
177 /* `e=' lines (email address) [zero or more] */
178 /* e=<email address> */
179 p2 = p;
180 j = 0;
181 while (!strncmp (p2, "e=", 2))
183 /* First, count how many emails are there */
184 j++;
185 NEXT_LINE (p2);
187 dsc->emails_count = j;
188 if (dsc->emails_count > 0)
190 /* Then, build the array of emails */
191 dsc->emails = calloc (j, sizeof (const char *));
192 for (j = 0; j < dsc->emails_count; j++)
194 sscanf (p, "e=%" MLFLENS "[^\r\n]", longfsdp_buf);
195 /* TODO? check valid email-address. */
196 dsc->emails[j] = strdup (longfsdp_buf);
197 NEXT_LINE (p);
201 /* `p=' lines (phone number) [zero or more] */
202 /* p=<phone number> */
203 j = 0;
204 /* assert ( p2 == p ); */
205 while (!strncmp (p2, "p=", 2))
207 j++;
208 NEXT_LINE (p2);
210 dsc->phones_count = j;
211 if (dsc->phones_count > 0)
213 dsc->phones = calloc (j, sizeof (const char *));
214 for (j = 0; j < dsc->phones_count; j++)
216 sscanf (p, "p=%" MLFLENS "[^\r\n]", longfsdp_buf);
217 /* TODO? check valid phone-number. */
218 dsc->phones[j] = strdup (longfsdp_buf);
219 NEXT_LINE (p);
223 /* `c=' line (connection information - not required if included in all media) [optional] */
224 /* c=<network type> <address type> <connection address> */
225 result = fsdp_parse_c (&p, &(dsc->c_network_type), &(dsc->c_address_type),
226 &(dsc->c_address));
227 if (FSDPE_OK != result)
228 return result;
230 /* `b=' lines (bandwidth information) [optional] */
231 /* b=<modifier>:<bandwidth-value> */
232 result =
233 fsdp_parse_b (&p, &(dsc->bw_modifiers), &(dsc->bw_modifiers_count));
234 if (FSDPE_OK != result)
235 return result;
237 /* A.1) Time descriptions: */
239 /* `t=' lines (time the session is active) [1 or more] */
240 /* t=<start time> <stop time> */
241 j = 0;
242 p2 = p;
243 while (!strncmp (p2, "t=", 2))
245 j++;
246 NEXT_LINE (p2);
247 while (!strncmp (p2, "r=", 2))
248 NEXT_LINE (p2);
250 dsc->time_periods_count = j;
251 if (dsc->time_periods_count == 0)
252 return FSDPE_MISSING_TIME;
253 dsc->time_periods = calloc (dsc->time_periods_count,
254 sizeof (fsdp_time_period_t *));
255 for (j = 0; j < dsc->time_periods_count; j++)
257 unsigned int h = 0;
258 if (sscanf (p, "t=%10lu %10lu", &wuint[0], &wuint[1]) != 2)
260 /* not all periods have been successfully parsed */
261 dsc->time_periods_count = j;
262 return FSDPE_INVALID_TIME;
264 dsc->time_periods[j] = calloc (1, sizeof (fsdp_time_period_t));
266 /* convert from NTP to time_t time */
267 if (wuint[0] != 0)
268 wuint[0] -= NTP_EPOCH_OFFSET;
269 if (wuint[1] != 0)
270 wuint[1] -= NTP_EPOCH_OFFSET;
271 dsc->time_periods[j]->start = wuint[0];
272 dsc->time_periods[j]->stop = wuint[1];
273 NEXT_LINE (p);
275 /* `r' lines [zero or more repeat times for each t=] */
276 /*r=<repeat interval> <active duration> <list of offsets from
277 start-time> */
278 p2 = p;
279 while (!strncmp (p2, "r=", 2))
281 h++;
282 NEXT_LINE (p2);
284 dsc->time_periods[j]->repeats_count = h;
285 if (h > 0)
287 unsigned int index2 = 0;
288 dsc->time_periods[j]->repeats =
289 calloc (h, sizeof (fsdp_repeat_t *));
290 for (h = 0; h < dsc->time_periods[j]->repeats_count; h++)
292 if (sscanf (p, "r=%10s %10s %" MLFLENS "[^\r\n]",
293 fsdp_buf[0], fsdp_buf[1], longfsdp_buf) == 3)
295 fsdp_repeat_t *repeat;
296 dsc->time_periods[j]->repeats[h] =
297 calloc (1, sizeof (fsdp_repeat_t));
298 repeat = dsc->time_periods[j]->repeats[h];
299 /* get interval, duration and list of offsets */
300 result =
301 fsdp_repeat_time_to_uint (fsdp_buf[0],
302 &(repeat->interval));
303 if (result == FSDPE_OK)
305 result =
306 fsdp_repeat_time_to_uint (fsdp_buf[1],
307 &(repeat->duration));
308 if (result == FSDPE_OK)
310 unsigned int k = 1;
311 const char *i = longfsdp_buf;
312 while (NULL != (i = strchr (i, ' ')))
314 k++;
315 if (NULL != i)
316 i++;
318 repeat->offsets_count = k;
319 repeat->offsets = calloc (k, sizeof (time_t));
320 i = longfsdp_buf;
321 for (k = 0;
322 (k < repeat->offsets_count)
323 && (result == FSDPE_OK); k++)
325 result =
326 fsdp_repeat_time_to_uint (i,
327 &(repeat->
328 offsets[k]));
329 i = strchr (i, ' ');
330 if (NULL != i)
331 i++;
333 if (k < repeat->offsets_count)
335 /* there where invalid repeat offsets */
336 dsc->time_periods[j]->repeats_count = k;
337 return FSDPE_INVALID_REPEAT;
341 if (result != FSDPE_OK)
343 /* not all repeats have been succesfully parsed */
344 dsc->time_periods[j]->repeats_count = h;
345 return FSDPE_INVALID_REPEAT;
347 NEXT_LINE (p);
349 else
351 /* not all repeats have been succesfully parsed */
352 dsc->time_periods[j]->repeats_count = h;
353 return FSDPE_INVALID_REPEAT;
355 index2++;
360 /* `z=' line (time zone adjustments) [zero or more] */
361 /* z=<adjustment time> <offset> <adjustment time> <offset> .... */
362 if (!strncmp (p, "z=", 2))
364 if (sscanf (p, "z=%" MLFLENS "[^\r\n]", longfsdp_buf))
366 /* TODO: guess how many pairs are there and process them */
367 dsc->timezone_adj = strdup (longfsdp_buf);
368 NEXT_LINE (p);
370 else
372 return FSDPE_INVALID_TIMEZONE;
376 /* `k=' line (encryption key) [optional] */
377 /* k=<method>
378 k=<method>:<encryption key> */
379 result = fsdp_parse_k (&p, &(dsc->k_encryption_method),
380 &(dsc->k_encryption_content));
381 if (result != FSDPE_OK)
382 return result;
384 /* A.2) Attributes */
385 /* `a=' lines (session attribute) [0 or more] */
386 /* a=<attribute>
387 a=<attribute>:<value> */
388 while (!strncmp (p, "a=", 2))
390 /* The "9" length specifier of the first string is subject to
391 changes */
392 if (sscanf
393 (p, "a=%9[^:\r\n]:%" MSFLENS "[^\r\n]", fsdp_buf[0],
394 fsdp_buf[1]) == 2)
396 /* session-level value attributes */
397 if (!strncmp (fsdp_buf[0], "cat", 3))
398 dsc->a_category = strdup (fsdp_buf[1]);
399 else if (!strncmp (fsdp_buf[0], "keywds", 6))
400 dsc->a_keywords = strdup (fsdp_buf[1]);
401 else if (!strncmp (fsdp_buf[0], "tool", 4))
402 dsc->a_keywords = strdup (fsdp_buf[1]);
403 else if (!strncmp (fsdp_buf[0], "rtpmap", 6))
404 fsdp_parse_rtpmap (&(dsc->a_rtpmaps),
405 &(dsc->a_rtpmaps_count), fsdp_buf[1]);
406 else if (!strncmp (fsdp_buf[0], "type", 4))
408 if (!strncmp (fsdp_buf[1], "broadcast", 9))
409 dsc->a_type = FSDP_SESSION_TYPE_BROADCAST;
410 else if (!strncmp (fsdp_buf[1], "meeting", 7))
411 dsc->a_type = FSDP_SESSION_TYPE_MEETING;
412 else if (!strncmp (fsdp_buf[1], "moderated", 9))
413 dsc->a_type = FSDP_SESSION_TYPE_MODERATED;
414 else if (!strncmp (fsdp_buf[1], "test", 4))
415 dsc->a_type = FSDP_SESSION_TYPE_TEST;
416 else if (!strncmp (fsdp_buf[1], "H332", 4))
417 dsc->a_type = FSDP_SESSION_TYPE_H332;
418 else
419 return FSDPE_INVALID_SESSION_TYPE;
421 else if (!strncmp (fsdp_buf[0], "charset", 7))
422 dsc->a_charset = strdup (fsdp_buf[1]);
423 else if (!strncmp (fsdp_buf[0], "sdplang", 7))
425 if (NULL == dsc->a_sdplangs)
427 dsc->a_sdplangs_count = 0;
428 dsc->a_sdplangs =
429 calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
431 if (dsc->a_sdplangs_count < SDPLANGS_MAX_COUNT)
433 dsc->a_sdplangs[dsc->a_sdplangs_count] =
434 strdup (fsdp_buf[1]);
435 dsc->a_sdplangs_count++;
438 else if (!strncmp (fsdp_buf[0], "lang", 4))
440 if (NULL == dsc->a_langs)
442 dsc->a_langs_count = 0;
443 dsc->a_langs = calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
445 if (dsc->a_langs_count < SDPLANGS_MAX_COUNT)
447 dsc->a_langs[dsc->a_langs_count] = strdup (fsdp_buf[1]);
448 dsc->a_langs_count++;
451 else if (!strncmp (fsdp_buf[0], "control", 7))
453 if (NULL == dsc->a_controls)
455 dsc->a_controls_count = 0;
456 dsc->a_controls =
457 calloc (SDPCONTROLS_MAX_COUNT, sizeof (char *));
459 if (dsc->a_controls_count < SDPCONTROLS_MAX_COUNT)
461 dsc->a_controls[dsc->a_controls_count] =
462 strdup (fsdp_buf[1]);
463 dsc->a_controls_count++;
466 else if (!strncmp (fsdp_buf[0], "range", 5))
468 free (dsc->a_range);
469 dsc->a_range = strdup (fsdp_buf[1]);
471 else
473 /* ignore unknown attributes, but provide access to them */
474 *longfsdp_buf = '\0';
475 strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN-1);
476 strncat (longfsdp_buf, ":", MAXLONGFIELDLEN-strlen(longfsdp_buf)-1);
477 strncat (longfsdp_buf, fsdp_buf[1], MAXLONGFIELDLEN-strlen(longfsdp_buf)-1);
478 if (NULL == dsc->unidentified_attributes)
480 dsc->unidentified_attributes_count = 0;
481 dsc->unidentified_attributes =
482 calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,
483 sizeof (char *));
485 if (dsc->unidentified_attributes_count <
486 UNIDENTIFIED_ATTRIBUTES_MAX_COUNT)
488 dsc->unidentified_attributes
489 [dsc->unidentified_attributes_count] =
490 strdup (longfsdp_buf);
491 dsc->unidentified_attributes_count++;
494 NEXT_LINE (p);
496 else if (sscanf (p, "a=%20s", fsdp_buf[0]) == 1)
498 /* session-level property attributes */
499 if (!strncmp (fsdp_buf[0], "recvonly", 8))
500 dsc->a_sendrecv_mode = FSDP_SENDRECV_RECVONLY;
501 else if (!strncmp (fsdp_buf[0], "sendonly", 8))
502 dsc->a_sendrecv_mode = FSDP_SENDRECV_SENDONLY;
503 else if (!strncmp (fsdp_buf[0], "inactive", 8))
504 dsc->a_sendrecv_mode = FSDP_SENDRECV_INACTIVE;
505 else if (!strncmp (fsdp_buf[0], "sendrecv", 8))
506 dsc->a_sendrecv_mode = FSDP_SENDRECV_SENDRECV;
507 else
509 /* ignore unknown attributes, but provide access to them */
510 *longfsdp_buf = '\0';
511 strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN-1);
512 if (NULL == dsc->unidentified_attributes)
514 dsc->unidentified_attributes_count = 0;
515 dsc->unidentified_attributes =
516 calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,
517 sizeof (char *));
519 if (dsc->unidentified_attributes_count <
520 UNIDENTIFIED_ATTRIBUTES_MAX_COUNT)
522 dsc->unidentified_attributes
523 [dsc->unidentified_attributes_count] =
524 strdup (longfsdp_buf);
525 dsc->unidentified_attributes_count++;
528 NEXT_LINE (p);
530 else
531 return FSDPE_INVALID_ATTRIBUTE;
534 /***************************************************************************/
535 /* B) parse media-level descriptions */
536 /***************************************************************************/
537 p2 = p;
538 j = 0;
539 while ((*p2 != '\0') && !strncmp (p2, "m=", 2))
541 char c;
542 j++;
543 NEXT_LINE (p2);
544 while (sscanf (p2, "%c=", &c) == 1)
546 if (c == 'i' || c == 'c' || c == 'b' || c == 'k' || c == 'a')
548 NEXT_LINE (p2);
550 else if (c == 'm')
552 break;
554 else
556 return FSDPE_INVALID_LINE;
560 dsc->media_announcements_count = j;
561 if (dsc->media_announcements_count == 0)
564 /*return FSDPE_MISSING_MEDIA; */
566 else
567 { /* dsc->media_announcements_count > 0 */
568 dsc->media_announcements =
569 calloc (j, sizeof (fsdp_media_announcement_t *));
570 for (j = 0; j < dsc->media_announcements_count; j++)
572 fsdp_media_announcement_t *media = NULL;
573 /* `m=' line (media name, transport address and format list) */
574 /* m=<media> <port> <transport> <fmt list> */
575 /* The max. string lengths are subject to change */
576 if (sscanf (p, "m=%11s %8s %7s %" MLFLENS "[^\r\n]",
577 fsdp_buf[0], fsdp_buf[1], fsdp_buf[2],
578 longfsdp_buf) != 4)
580 return FSDPE_INVALID_MEDIA;
582 else
584 dsc->media_announcements[j] =
585 calloc (1, sizeof (fsdp_media_announcement_t));
586 media = dsc->media_announcements[j];
587 if (!strncmp (fsdp_buf[0], "audio", 5))
588 media->media_type = FSDP_MEDIA_AUDIO;
589 else if (!strncmp (fsdp_buf[0], "video", 5))
590 media->media_type = FSDP_MEDIA_VIDEO;
591 else if (!strncmp (fsdp_buf[0], "application", 11))
592 media->media_type = FSDP_MEDIA_APPLICATION;
593 else if (!strncmp (fsdp_buf[0], "data", 4))
594 media->media_type = FSDP_MEDIA_DATA;
595 else if (!strncmp (fsdp_buf[0], "control", 7))
596 media->media_type = FSDP_MEDIA_CONTROL;
597 else
598 return FSDPE_UNKNOWN_MEDIA_TYPE;
599 { /* try to get port specification as port/number */
600 char *slash;
601 if ((slash = strchr (fsdp_buf[1], '/')))
603 *slash = '\0';
604 slash++;
605 media->port = strtol (fsdp_buf[1], NULL, 10);
606 media->port_count = strtol (slash, NULL, 10);
608 else
610 media->port = strtol (fsdp_buf[1], NULL, 10);
611 media->port_count = 0;
614 if (!strncmp (fsdp_buf[2], "RTP/AVP", 7))
615 media->transport = FSDP_TP_RTP_AVP;
616 else if (!strncmp (fsdp_buf[2], "udp", 3))
617 media->transport = FSDP_TP_UDP;
618 else if (!strncmp (fsdp_buf[2], "TCP", 3))
619 media->transport = FSDP_TP_TCP;
620 else if (!strncmp (fsdp_buf[2], "UDPTL", 5))
621 media->transport = FSDP_TP_UDPTL;
622 else if (!strncmp (fsdp_buf[2], "vat", 3))
623 media->transport = FSDP_TP_VAT;
624 else if (!strncmp (fsdp_buf[2], "rtp", 3))
625 media->transport = FSDP_TP_OLD_RTP;
626 else
627 return FSDPE_UNKNOWN_MEDIA_TRANSPORT;
629 unsigned int k = 0;
630 char *s = longfsdp_buf;
631 while (NULL != (s = strchr (s, ' ')))
633 k++;
634 if (NULL != s)
635 s++;
637 k++; /* when there is no space left, count the last format */
638 media->formats_count = k;
639 media->formats = calloc (k, sizeof (char *));
640 s = longfsdp_buf;
641 for (k = 0; k < media->formats_count; k++)
643 char *space = strchr (s, ' ');
644 if (NULL != space)
645 *space = '\0';
646 media->formats[k] = strdup (s);
647 s = space + 1;
650 NEXT_LINE (p);
653 /* `i=' line (media title) [optional] */
654 /* i=<media title> */
655 if (!strncmp (p, "i=", 2)
656 && sscanf (p, "i=%" MLFLENS "[^\r\n]", longfsdp_buf))
658 media->i_title = strdup (longfsdp_buf);
659 NEXT_LINE (p);
661 else
663 /* (optional) information absent */
666 /* `c=' line (connection information - overrides session-level
667 line) [optional if provided at session-level] */
668 /* c=<network type> <address type> <connection address> */
669 result = fsdp_parse_c (&p, &(media->c_network_type),
670 &(media->c_address_type),
671 &(media->c_address));
672 if (result != FSDPE_OK)
673 return result;
675 /* `b=' lines (bandwidth information) [optional] */
676 /* b=<modifier>:<bandwidth-value> */
677 result = fsdp_parse_b (&p, &(media->bw_modifiers),
678 &(media->bw_modifiers_count));
679 if (FSDPE_OK != result)
680 return result;
682 /* `k=' line (encryption key) [optional] */
683 /* k=<method>
684 k=<method>:<encryption key> */
685 result = fsdp_parse_k (&p, &(media->k_encryption_method),
686 &(media->k_encryption_content));
687 if (result != FSDPE_OK)
688 return result;
690 /* B.1) Attributes */
692 /* `a=' lines (zero or more media attribute lines) [optional] */
693 /* a=<attribute>
694 a=<attribute>:<value> */
695 while (!strncmp (p, "a=", 2))
697 if (sscanf
698 (p, "a=%9[^:\r\n]:%" MLFLENS "[^\r\n]", fsdp_buf[0],
699 longfsdp_buf) == 2)
701 /* media-level value attributes */
702 if (!strncmp (fsdp_buf[0], "ptime", 5))
703 media->a_ptime = strtoul (longfsdp_buf, NULL, 10);
704 else if (!strncmp (fsdp_buf[0], "maxptime", 8))
705 media->a_maxptime = strtoul (longfsdp_buf, NULL, 10);
706 else if (!strncmp (fsdp_buf[0], "rtpmap", 6))
707 fsdp_parse_rtpmap (&(media->a_rtpmaps),
708 &(media->a_rtpmaps_count),
709 longfsdp_buf);
710 else if (!strncmp (fsdp_buf[0], "orient", 6))
712 if (!strncmp (longfsdp_buf, "portrait", 8))
713 media->a_orient = FSDP_ORIENT_PORTRAIT;
714 else if (!strncmp (longfsdp_buf, "landscape", 9))
715 media->a_orient = FSDP_ORIENT_LANDSCAPE;
716 else if (!strncmp (longfsdp_buf, "seascape", 9))
717 media->a_orient = FSDP_ORIENT_SEASCAPE;
719 else if (!strncmp (fsdp_buf[0], "sdplang", 7))
721 if (NULL == dsc->a_sdplangs)
723 media->a_sdplangs_count = 0;
724 media->a_sdplangs =
725 calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
727 if (media->a_sdplangs_count < SDPLANGS_MAX_COUNT)
729 media->a_sdplangs[dsc->a_sdplangs_count] =
730 strdup (longfsdp_buf);
731 media->a_sdplangs_count++;
734 else if (!strncmp (fsdp_buf[0], "lang", 4))
736 if (NULL == dsc->a_langs)
738 media->a_langs_count = 0;
739 media->a_langs =
740 calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
742 if (media->a_langs_count < SDPLANGS_MAX_COUNT)
744 media->a_langs[dsc->a_langs_count] =
745 strdup (longfsdp_buf);
746 media->a_langs_count++;
749 else if (!strncmp (fsdp_buf[0], "control", 7))
751 if (NULL == media->a_controls)
753 media->a_controls_count = 0;
754 media->a_controls =
755 calloc (SDPCONTROLS_MAX_COUNT, sizeof (char *));
757 if (media->a_controls_count < SDPCONTROLS_MAX_COUNT)
759 media->a_controls[media->a_controls_count] =
760 strdup (longfsdp_buf);
761 media->a_controls_count++;
764 else if (!strncmp (fsdp_buf[0], "range", 5))
766 free (media->a_range);
767 media->a_range = strdup (fsdp_buf[1]);
769 else if (!strncmp (fsdp_buf[0], "framerate", 9))
770 media->a_framerate = strtod (longfsdp_buf, NULL);
771 else if (!strncmp (fsdp_buf[0], "fmtp", 4))
773 if (NULL == media->a_fmtps)
775 media->a_fmtps_count = 0;
776 media->a_fmtps =
777 calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
779 if (media->a_fmtps_count < SDPLANGS_MAX_COUNT)
781 media->a_fmtps[media->a_fmtps_count] =
782 strdup (longfsdp_buf);
783 media->a_fmtps_count++;
786 else if (!strncmp (fsdp_buf[0], "rtcp", 4))
788 int opts = 0;
789 /* rtcp attribute: a=rtcp:<port> <nettype> <addrtype> <address> */
790 opts =
791 sscanf (longfsdp_buf, "%lu %2s %3s %" MSFLENS "s",
792 &wuint[0], fsdp_buf[0], fsdp_buf[1],
793 fsdp_buf[2]);
794 if (opts >= 1)
796 media->a_rtcp_port = wuint[0];
797 if (opts >= 2)
799 if (!strncmp (fsdp_buf[0], "IN", 2))
801 media->a_rtcp_network_type =
802 FSDP_NETWORK_TYPE_INET;
803 } /* else
804 ; TODO: define error code? */
805 if (opts >= 3)
807 if (!strncmp (fsdp_buf[1], "IP4", 3))
808 media->a_rtcp_address_type =
809 FSDP_ADDRESS_TYPE_IPV4;
810 else if (!strncmp (fsdp_buf[1], "IP6", 3))
811 media->a_rtcp_address_type =
812 FSDP_ADDRESS_TYPE_IPV6;
813 else
814 return FSDPE_INVALID_CONNECTION_NETTYPE;
815 /*add specific code? */
816 if (opts >= 4)
817 media->a_rtcp_address =
818 strdup (fsdp_buf[2]);
823 else
825 /* ignore unknown attributes, but provide access to them */
826 *fsdp_buf[1] = '\0';
827 strncat (fsdp_buf[1], fsdp_buf[0], MAXSHORTFIELDLEN-1);
828 strncat (fsdp_buf[1], ":", MAXSHORTFIELDLEN-strlen(fsdp_buf[1])-1);
829 strncat (fsdp_buf[1], longfsdp_buf, MAXSHORTFIELDLEN-strlen(fsdp_buf[1])-1);
830 if (NULL == media->unidentified_attributes)
832 media->unidentified_attributes_count = 0;
833 media->unidentified_attributes =
834 calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,
835 sizeof (char *));
837 if (media->unidentified_attributes_count <
838 UNIDENTIFIED_ATTRIBUTES_MAX_COUNT)
840 media->unidentified_attributes
841 [media->unidentified_attributes_count] =
842 strdup (fsdp_buf[1]);
843 media->unidentified_attributes_count++;
846 NEXT_LINE (p);
848 else if (sscanf (p, "a=%8s", fsdp_buf[0]) == 1)
850 /* media-level property attributes */
851 if (!strncmp (fsdp_buf[0], "recvonly", 8))
852 media->a_sendrecv_mode = FSDP_SENDRECV_RECVONLY;
853 else if (!strncmp (fsdp_buf[0], "sendonly", 8))
854 media->a_sendrecv_mode = FSDP_SENDRECV_SENDONLY;
855 else if (!strncmp (fsdp_buf[0], "inactive", 8))
856 media->a_sendrecv_mode = FSDP_SENDRECV_INACTIVE;
857 else if (!strncmp (fsdp_buf[0], "sendrecv", 8))
858 media->a_sendrecv_mode = FSDP_SENDRECV_SENDRECV;
859 else
861 /* ignore unknown attributes, but provide access to them */
862 *longfsdp_buf = '\0';
863 strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN-1);
864 if (NULL == media->unidentified_attributes)
866 media->unidentified_attributes_count = 0;
867 media->unidentified_attributes =
868 calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,
869 sizeof (char *));
871 if (media->unidentified_attributes_count <
872 UNIDENTIFIED_ATTRIBUTES_MAX_COUNT)
874 media->unidentified_attributes
875 [media->unidentified_attributes_count] =
876 strdup (longfsdp_buf);
877 media->unidentified_attributes_count++;
880 NEXT_LINE (p);
882 else
883 return FSDPE_INVALID_ATTRIBUTE;
885 } /* end of for */
888 /* Check c= has been given at session level or at media level for
889 all media */
890 if (NULL == dsc->c_address.address)
892 unsigned int c;
893 for (c = 0; c < dsc->media_announcements_count; c++)
894 if (NULL == dsc->media_announcements[c]->c_address.address)
895 return FSDPE_MISSING_CONNECTION_INFO;
898 /* finish */
899 if (*p == '\0')
900 return FSDPE_OK;
901 else
902 return FSDPE_OVERFILLED;
905 static fsdp_error_t
906 fsdp_parse_c (const char **p, fsdp_network_type_t * ntype,
907 fsdp_address_type_t * atype,
908 fsdp_connection_address_t * address)
910 const unsigned int TEMPCHARS = 3;
911 char fsdp_buf[TEMPCHARS][MAXSHORTFIELDLEN];
913 if (!strncmp (*p, "c=", 2))
915 if (sscanf (*p, "c=%2s %3s %" MSFLENS "s",
916 fsdp_buf[0], fsdp_buf[1], fsdp_buf[2]))
918 if (!strncmp (fsdp_buf[0], "IN", 2))
920 *ntype = FSDP_NETWORK_TYPE_INET;
921 if (!strncmp (fsdp_buf[1], "IP4", 3))
922 *atype = FSDP_ADDRESS_TYPE_IPV4;
923 else if (!strncmp (fsdp_buf[1], "IP6", 3))
924 *atype = FSDP_ADDRESS_TYPE_IPV6;
925 else
926 return FSDPE_INVALID_CONNECTION_NETTYPE;
928 else
930 return FSDPE_INVALID_CONNECTION_ADDRTYPE;
933 char *slash = strchr (fsdp_buf[2], '/');
934 if (NULL == slash)
936 address->address = strdup (fsdp_buf[2]);
937 address->address_ttl = 0;
938 address->address_count = 0;
940 else
942 /* address is IP4 multicast */
943 char *slash2;
944 *slash = '\0';
945 slash++;
946 address->address = strdup (fsdp_buf[2]);
947 slash2 = strchr (slash + 1, '/');
948 if (NULL == slash2)
950 address->address_ttl = strtol (slash, NULL, 10);
951 address->address_count = 0;
953 else
955 *slash2 = '\0';
956 slash2++;
957 address->address_ttl = strtol (slash, NULL, 10);
958 address->address_count = strtol (slash2, NULL, 10);
962 NEXT_LINE (*p);
964 else
966 return FSDPE_INVALID_CONNECTION;
969 return FSDPE_OK;
972 static fsdp_error_t
973 fsdp_parse_b (const char **p, fsdp_bw_modifier_t ** bw_modifiers,
974 unsigned int *bw_modifiers_count)
976 char fsdp_buf[MAXSHORTFIELDLEN];
977 unsigned long int wuint;
978 unsigned int i = 0;
979 const char *lp = *p;
981 /* count b= lines */
982 while (!strncmp (lp, "b=", 2))
984 NEXT_LINE (lp);
985 i++;
987 *bw_modifiers = calloc (i, sizeof (fsdp_bw_modifier_t));
988 *bw_modifiers_count = i;
990 while (i > 0)
992 unsigned int index = *bw_modifiers_count - i;
993 if (2 == sscanf (*p, "b=%20[^:\r\n]:%lu", fsdp_buf, &wuint))
995 if (!strncmp (fsdp_buf, "CT", 2))
996 (*bw_modifiers)[index].b_mod_type =
997 FSDP_BW_MOD_TYPE_CONFERENCE_TOTAL;
998 else if (!strncmp (fsdp_buf, "AS", 2))
999 (*bw_modifiers)[index].b_mod_type =
1000 FSDP_BW_MOD_TYPE_APPLICATION_SPECIFIC;
1001 else if (!strncmp (fsdp_buf, "RS", 2))
1002 (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_RTCP_SENDERS;
1003 else if (!strncmp (fsdp_buf, "RR", 2))
1004 (*bw_modifiers)[index].b_mod_type =
1005 FSDP_BW_MOD_TYPE_RTCP_RECEIVERS;
1006 else
1008 (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_UNKNOWN;
1009 (*bw_modifiers)[index].b_unknown_bw_modt =
1010 (char *) strdup (fsdp_buf);
1012 (*bw_modifiers)[index].b_value = wuint;
1013 NEXT_LINE (*p);
1015 else
1017 *bw_modifiers_count -= i;
1018 return FSDPE_INVALID_BANDWIDTH;
1020 i--;
1022 return FSDPE_OK;
1025 static fsdp_error_t
1026 fsdp_parse_k (const char **p, fsdp_encryption_method_t * method,
1027 char **content)
1029 char fsdp_buf[MAXSHORTFIELDLEN];
1030 char longfsdp_buf[MAXLONGFIELDLEN];
1032 if (!strncmp (*p, "k=", 2))
1034 if (sscanf (*p, "k=prompt"))
1036 *method = FSDP_ENCRYPTION_METHOD_PROMPT;
1037 *content = NULL;
1038 NEXT_LINE (*p);
1040 else
1042 if (sscanf
1043 (*p, "k=%6[^:\r\n]:%" MLFLENS "s", fsdp_buf, longfsdp_buf))
1045 if (!strncmp (fsdp_buf, "clear", 5))
1046 *method = FSDP_ENCRYPTION_METHOD_CLEAR;
1047 else if (!strncmp (fsdp_buf, "base64", 6))
1048 *method = FSDP_ENCRYPTION_METHOD_BASE64;
1049 else if (!strncmp (fsdp_buf, "uri", 3))
1050 *method = FSDP_ENCRYPTION_METHOD_URI;
1051 else
1052 return FSDPE_INVALID_ENCRYPTION_METHOD;
1053 *content = strdup (longfsdp_buf);
1054 NEXT_LINE (*p);
1058 return FSDPE_OK;
1061 static fsdp_error_t
1062 fsdp_parse_rtpmap (fsdp_rtpmap_t *** rtpmap, unsigned int *counter,
1063 const char *value)
1065 fsdp_error_t result = FSDPE_OK;
1067 if (0 == *counter)
1069 *counter = 0;
1070 *rtpmap = calloc (MEDIA_RTPMAPS_MAX_COUNT, sizeof (fsdp_rtpmap_t *));
1072 if (*counter < MEDIA_RTPMAPS_MAX_COUNT)
1074 unsigned int c = *counter;
1075 fsdp_rtpmap_t **map = *rtpmap;
1076 char fsdp_buf[MAXSHORTFIELDLEN];
1077 char longfsdp_buf[MAXLONGFIELDLEN];
1078 map[c] = calloc (1, sizeof (fsdp_rtpmap_t));
1080 /* a=rtpmap:<payload type> <encoding name>/<clock rate>[/<encoding
1081 parameters]> */
1082 if (2 == sscanf (value, "%s %s", fsdp_buf, longfsdp_buf))
1084 char *slash1;
1085 map[c]->pt = strdup (fsdp_buf);
1086 /* parse <encoding name>/<clock rate>[/<encoding parameters>] */
1087 slash1 = strchr (longfsdp_buf, '/');
1088 if (NULL == slash1)
1090 result = FSDPE_INVALID_ATTRIBUTE_RTPMAP;
1092 else
1094 char *slash2;
1095 *slash1 = '\0';
1096 slash1++;
1097 map[c]->encoding_name = strdup (longfsdp_buf);
1098 slash2 = strchr (slash1, '/');
1099 if (NULL != slash2)
1101 *slash2 = '\0';
1102 slash2++;
1103 map[c]->parameters = strdup (slash2);
1105 map[c]->clock_rate = strtol (slash1, NULL, 10);
1107 (*counter)++;
1110 return result;
1113 static fsdp_error_t
1114 fsdp_repeat_time_to_uint (const char *time, unsigned long int *seconds)
1116 const unsigned long SECONDS_PER_DAY = 86400;
1117 const unsigned long SECONDS_PER_HOUR = 3600;
1118 const unsigned long SECONDS_PER_MINUTE = 60;
1119 char c;
1120 unsigned long int wuint;
1122 if (sscanf (time, "%lu%c", &wuint, &c) == 2)
1124 /* time with unit specification character */
1125 switch (c)
1127 case 'd':
1128 *seconds = wuint * SECONDS_PER_DAY;
1129 break;
1130 case 'h':
1131 *seconds = wuint * SECONDS_PER_HOUR;
1132 break;
1133 case 'm':
1134 *seconds = wuint * SECONDS_PER_MINUTE;
1135 break;
1136 case 's':
1137 *seconds = wuint;
1138 break;
1139 default:
1140 return FSDPE_INVALID_REPEAT;
1141 break;
1144 else if (sscanf (time, "%lu", &wuint) == 1)
1146 /* time without unit specification character */
1147 *seconds = wuint;
1149 else
1151 return FSDPE_INVALID_REPEAT;
1153 return FSDPE_OK;
1156 unsigned int
1157 fsdp_get_version (const fsdp_description_t * dsc)
1159 if (!dsc)
1160 return 0;
1161 return dsc->version;
1164 const char *
1165 fsdp_get_owner_username (const fsdp_description_t * dsc)
1167 if (!dsc)
1168 return NULL;
1169 return dsc->o_username;
1172 const char *
1173 fsdp_get_session_id (const fsdp_description_t * dsc)
1175 if (!dsc)
1176 return NULL;
1177 return dsc->o_session_id;
1180 const char *
1181 fsdp_get_announcement_version (const fsdp_description_t * dsc)
1183 if (!dsc)
1184 return NULL;
1185 return dsc->o_announcement_version;
1188 fsdp_network_type_t
1189 fsdp_get_owner_network_type (const fsdp_description_t * dsc)
1191 if (!dsc)
1192 return FSDP_NETWORK_TYPE_UNDEFINED;
1193 return dsc->o_network_type;
1196 fsdp_address_type_t
1197 fsdp_get_owner_address_type (const fsdp_description_t * dsc)
1199 if (!dsc)
1200 return FSDP_ADDRESS_TYPE_UNDEFINED;
1201 return dsc->o_address_type;
1204 const char *
1205 fsdp_get_owner_address (const fsdp_description_t * dsc)
1207 if (!dsc)
1208 return NULL;
1209 return dsc->o_address;
1212 const char *
1213 fsdp_get_name (const fsdp_description_t * dsc)
1215 if (!dsc)
1216 return NULL;
1217 return dsc->s_name;
1220 const char *
1221 fsdp_get_information (const fsdp_description_t * dsc)
1223 if (!dsc)
1224 return NULL;
1225 return dsc->i_information;
1228 const char *
1229 fsdp_get_uri (const fsdp_description_t * dsc)
1231 if (!dsc)
1232 return NULL;
1233 return dsc->u_uri;
1236 unsigned int
1237 fsdp_get_emails_count (const fsdp_description_t * dsc)
1239 if (!dsc)
1240 return 0;
1241 return dsc->emails_count;
1244 const char *
1245 fsdp_get_email (const fsdp_description_t * dsc, unsigned int index)
1247 if ((!dsc) || (index >= dsc->emails_count))
1248 return NULL;
1249 return dsc->emails[index];
1252 unsigned int
1253 fsdp_get_phones_count (const fsdp_description_t * dsc)
1255 if (!dsc)
1256 return 0;
1257 return dsc->phones_count;
1260 const char *
1261 fsdp_get_phone (const fsdp_description_t * dsc, unsigned int index)
1263 if ((!dsc) || (index >= dsc->phones_count))
1264 return NULL;
1265 return dsc->phones[index];
1268 fsdp_network_type_t
1269 fsdp_get_global_conn_network_type (const fsdp_description_t * dsc)
1271 if (!dsc)
1272 return FSDP_NETWORK_TYPE_UNDEFINED;
1273 return dsc->c_network_type;
1276 fsdp_address_type_t
1277 fsdp_get_global_conn_address_type (const fsdp_description_t * dsc)
1279 if (!dsc)
1280 return FSDP_ADDRESS_TYPE_UNDEFINED;
1281 return dsc->c_address_type;
1284 const char *
1285 fsdp_get_global_conn_address (const fsdp_description_t * dsc)
1287 if (!dsc)
1288 return NULL;
1289 return dsc->c_address.address;
1292 unsigned int
1293 fsdp_get_global_conn_address_ttl (const fsdp_description_t * dsc)
1295 if (!dsc)
1296 return 0;
1297 return dsc->c_address.address_ttl;
1300 unsigned int
1301 fsdp_get_global_conn_address_count (const fsdp_description_t * dsc)
1303 if (!dsc)
1304 return 0;
1305 return dsc->c_address.address_count;
1308 unsigned int
1309 fsdp_get_bw_modifier_count (const fsdp_description_t * dsc)
1311 if (!dsc)
1312 return 0;
1313 return dsc->bw_modifiers_count;
1316 fsdp_bw_modifier_type_t
1317 fsdp_get_bw_modifier_type (const fsdp_description_t * dsc, unsigned int index)
1319 if ((!dsc) || (index >= dsc->bw_modifiers_count))
1320 return FSDP_BW_MOD_TYPE_UNDEFINED;
1321 return dsc->bw_modifiers[index].b_mod_type;
1324 const char *
1325 fsdp_get_bw_modifier_type_unknown (const fsdp_description_t * dsc,
1326 unsigned int index)
1328 if ((!dsc) || (index >= dsc->bw_modifiers_count) ||
1329 (dsc->bw_modifiers[index].b_mod_type != FSDP_BW_MOD_TYPE_UNKNOWN))
1330 return NULL;
1331 return dsc->bw_modifiers[index].b_unknown_bw_modt;
1334 unsigned long int
1335 fsdp_get_bw_value (const fsdp_description_t * dsc, unsigned int index)
1337 if ((!dsc) || (index >= dsc->bw_modifiers_count))
1338 return 0;
1339 return dsc->bw_modifiers[index].b_value;
1342 time_t
1343 fsdp_get_period_start (const fsdp_description_t * dsc, unsigned int index)
1345 if ((!dsc) || (index >= dsc->time_periods_count))
1346 return 0;
1347 return dsc->time_periods[index]->start;
1350 time_t
1351 fsdp_get_period_stop (const fsdp_description_t * dsc, unsigned int index)
1353 if ((!dsc) || (index >= dsc->time_periods_count))
1354 return 0;
1355 return dsc->time_periods[index]->stop;
1358 unsigned int
1359 fsdp_get_period_repeats_count (const fsdp_description_t * dsc,
1360 unsigned int index)
1362 if ((!dsc) || (index >= dsc->time_periods_count))
1363 return 0;
1364 return dsc->time_periods[index]->repeats_count;
1367 unsigned long int
1368 fsdp_get_period_repeat_interval (const fsdp_description_t * dsc,
1369 unsigned int index, unsigned int rindex)
1371 if ((!dsc) || (index >= dsc->time_periods_count))
1372 return 0;
1373 return dsc->time_periods[index]->repeats[rindex]->interval;
1376 unsigned long int
1377 fsdp_get_period_repeat_duration (const fsdp_description_t * dsc,
1378 unsigned int index, unsigned int rindex)
1380 if ((!dsc) || (index >= dsc->time_periods_count))
1381 return 0;
1382 return dsc->time_periods[index]->repeats[rindex]->duration;
1385 const unsigned long int *
1386 fsdp_get_period_repeat_offsets (const fsdp_description_t * dsc,
1387 unsigned int index, unsigned int rindex)
1389 if ((!dsc) || (index >= dsc->time_periods_count))
1390 return NULL;
1391 return dsc->time_periods[index]->repeats[rindex]->offsets;
1394 const char *
1395 fsdp_get_timezone_adj (const fsdp_description_t * dsc)
1397 if (!dsc)
1398 return NULL;
1399 return dsc->timezone_adj;
1402 unsigned int
1403 fsdp_get_unidentified_attribute_count (const fsdp_description_t * dsc)
1405 if (!dsc)
1406 return 0;
1407 return dsc->unidentified_attributes_count;
1410 const char *
1411 fsdp_get_unidentified_attribute (const fsdp_description_t * dsc,
1412 unsigned int index)
1414 if (!dsc || (index < dsc->unidentified_attributes_count))
1415 return NULL;
1416 return dsc->unidentified_attributes[index];
1419 fsdp_encryption_method_t
1420 fsdp_get_encryption_method (const fsdp_description_t * dsc)
1422 if (!dsc)
1423 return FSDP_ENCRYPTION_METHOD_UNDEFINED;
1424 return dsc->k_encryption_method;
1427 const char *
1428 fsdp_get_encryption_content (const fsdp_description_t * dsc)
1430 if (!dsc || (dsc->k_encryption_method == FSDP_ENCRYPTION_METHOD_UNDEFINED))
1431 return NULL;
1432 return dsc->k_encryption_content;
1435 const char *
1436 fsdp_get_str_att (const fsdp_description_t * dsc, fsdp_session_str_att_t att)
1438 /*TODO: change these individual attributes with a table, thus
1439 avoiding this slow switch */
1440 char *result;
1442 if (!dsc)
1443 return NULL;
1445 switch (att)
1447 case FSDP_SESSION_STR_ATT_CATEGORY:
1448 result = dsc->a_category;
1449 break;
1450 case FSDP_SESSION_STR_ATT_KEYWORDS:
1451 result = dsc->a_keywords;
1452 break;
1453 case FSDP_SESSION_STR_ATT_TOOL:
1454 result = dsc->a_tool;
1455 break;
1456 case FSDP_SESSION_STR_ATT_CHARSET:
1457 result = dsc->a_charset;
1458 break;
1459 default:
1460 result = NULL;
1462 return result;
1465 unsigned int
1466 fsdp_get_sdplang_count (const fsdp_description_t * dsc)
1468 if (!dsc)
1469 return 0;
1470 return dsc->a_sdplangs_count;
1473 const char *
1474 fsdp_get_sdplang (const fsdp_description_t * dsc, unsigned int index)
1476 if ((!dsc) || (index >= dsc->a_sdplangs_count))
1477 return NULL;
1478 return dsc->a_sdplangs[index];
1481 unsigned int
1482 fsdp_get_control_count (const fsdp_description_t * dsc)
1484 if (!dsc)
1485 return 0;
1486 return dsc->a_controls_count;
1489 const char *
1490 fsdp_get_control (const fsdp_description_t * dsc, unsigned int index)
1492 if ((!dsc) || (index >= dsc->a_controls_count))
1493 return NULL;
1494 return dsc->a_controls[index];
1497 const char *
1498 fsdp_get_range (const fsdp_description_t * dsc)
1500 return dsc->a_range;
1503 fsdp_sendrecv_mode_t
1504 fsdp_get_sendrecv_mode (const fsdp_description_t * dsc)
1506 if (!dsc)
1507 return FSDP_SENDRECV_UNDEFINED;
1508 return dsc->a_sendrecv_mode;
1511 fsdp_session_type_t
1512 fsdp_get_session_type (const fsdp_description_t * dsc)
1514 if (!dsc)
1515 return FSDP_SESSION_TYPE_UNDEFINED;
1516 return dsc->a_type;
1519 unsigned int
1520 fsdp_get_media_count (const fsdp_description_t * dsc)
1522 if (!dsc)
1523 return 0;
1524 return dsc->media_announcements_count;
1527 const fsdp_media_description_t *
1528 fsdp_get_media (const fsdp_description_t * dsc, unsigned int index)
1530 if ((index >= dsc->media_announcements_count))
1531 return NULL;
1532 return dsc->media_announcements[index];
1535 fsdp_media_t
1536 fsdp_get_media_type (const fsdp_media_description_t * dsc)
1538 if (!dsc)
1539 return FSDP_MEDIA_UNDEFINED;
1540 return dsc->media_type;
1543 unsigned int
1544 fsdp_get_media_port (const fsdp_media_description_t * dsc)
1546 if (!dsc)
1547 return 0;
1548 return dsc->port;
1551 unsigned int
1552 fsdp_get_media_port_count (const fsdp_media_description_t * dsc)
1554 if (!dsc)
1555 return 0;
1556 return dsc->port_count;
1559 fsdp_transport_protocol_t
1560 fsdp_get_media_transport_protocol (const fsdp_media_description_t * dsc)
1562 if (!dsc)
1563 return FSDP_TP_UNDEFINED;
1564 return dsc->transport;
1567 unsigned int
1568 fsdp_get_media_formats_count (const fsdp_media_description_t * dsc)
1570 if (!dsc)
1571 return 0;
1572 return dsc->formats_count;
1575 const char *
1576 fsdp_get_media_format (const fsdp_media_description_t * dsc,
1577 unsigned int index)
1579 if (!dsc || (index < dsc->formats_count - 1))
1580 return NULL;
1581 return dsc->formats[index];
1584 const char *
1585 fsdp_get_media_title (const fsdp_media_description_t * dsc)
1587 if (!dsc)
1588 return NULL;
1589 return dsc->i_title;
1592 fsdp_network_type_t
1593 fsdp_get_media_network_type (const fsdp_media_description_t * dsc)
1595 if (!dsc)
1596 return FSDP_NETWORK_TYPE_UNDEFINED;
1597 return dsc->c_network_type;
1600 fsdp_address_type_t
1601 fsdp_get_media_address_type (const fsdp_media_description_t * dsc)
1603 if (!dsc)
1604 return FSDP_ADDRESS_TYPE_UNDEFINED;
1605 return dsc->c_address_type;
1608 const char *
1609 fsdp_get_media_address (const fsdp_media_description_t * dsc)
1611 if (!dsc)
1612 return NULL;
1613 return dsc->c_address.address;
1616 unsigned int
1617 fsdp_get_media_address_ttl (const fsdp_media_description_t * mdsc)
1619 if (!mdsc)
1620 return 0;
1621 return mdsc->c_address.address_ttl;
1624 unsigned int
1625 fsdp_get_media_address_count (const fsdp_media_description_t * mdsc)
1627 if (!mdsc)
1628 return 0;
1629 return mdsc->c_address.address_count;
1632 fsdp_bw_modifier_type_t
1633 fsdp_get_media_bw_modifier_type (const fsdp_media_description_t * dsc,
1634 unsigned int index)
1636 if (!dsc || (index >= dsc->bw_modifiers_count))
1637 return FSDP_BW_MOD_TYPE_UNDEFINED;
1638 return dsc->bw_modifiers[index].b_mod_type;
1641 const char *
1642 fsdp_get_media_bw_modifier_type_unknown (const fsdp_media_description_t * dsc,
1643 unsigned int index)
1645 if (!dsc || (index >= dsc->bw_modifiers_count) ||
1646 (FSDP_BW_MOD_TYPE_UNKNOWN != dsc->bw_modifiers[index].b_mod_type))
1647 return NULL;
1648 return dsc->bw_modifiers[index].b_unknown_bw_modt;
1651 unsigned long int
1652 fsdp_get_media_bw_value (const fsdp_media_description_t * dsc,
1653 unsigned int index)
1655 if (!dsc || (index >= dsc->bw_modifiers_count))
1656 return 0;
1657 return dsc->bw_modifiers[index].b_value;
1660 fsdp_encryption_method_t
1661 fsdp_get_media_encryption_method (const fsdp_media_description_t * dsc)
1663 if (!dsc)
1664 return FSDP_ENCRYPTION_METHOD_UNDEFINED;
1665 return dsc->k_encryption_method;
1668 const char *
1669 fsdp_get_media_encryption_content (const fsdp_media_description_t * dsc)
1671 if (!dsc)
1672 return NULL;
1673 return dsc->k_encryption_content;
1676 unsigned int
1677 fsdp_get_media_ptime (const fsdp_media_description_t * dsc)
1679 if (!dsc)
1680 return 0;
1681 return dsc->a_ptime;
1684 unsigned int
1685 fsdp_get_media_maxptime (const fsdp_media_description_t * dsc)
1687 if (!dsc)
1688 return 0;
1689 return dsc->a_maxptime;
1692 unsigned int
1693 fsdp_get_media_rtpmap_count (const fsdp_media_description_t * mdsc)
1695 if (!mdsc)
1696 return 0;
1697 return mdsc->a_rtpmaps_count;
1700 const char *
1701 fsdp_get_media_rtpmap_payload_type (const fsdp_media_description_t * mdsc,
1702 unsigned int index)
1704 if (!mdsc || (index >= mdsc->a_rtpmaps_count))
1705 return NULL;
1706 return mdsc->a_rtpmaps[index]->pt;
1709 const char *
1710 fsdp_get_media_rtpmap_encoding_name (const fsdp_media_description_t * mdsc,
1711 unsigned int index)
1713 if (!mdsc || (index >= mdsc->a_rtpmaps_count))
1714 return NULL;
1715 return mdsc->a_rtpmaps[index]->encoding_name;
1718 unsigned int
1719 fsdp_get_media_rtpmap_clock_rate (const fsdp_media_description_t * mdsc,
1720 unsigned int index)
1722 if (!mdsc || (index >= mdsc->a_rtpmaps_count))
1723 return 0;
1724 return mdsc->a_rtpmaps[index]->clock_rate;
1727 const char *
1728 fsdp_get_media_rtpmap_encoding_parameters (const fsdp_description_t * mdsc,
1729 unsigned int index)
1731 if (!mdsc || (index >= mdsc->a_rtpmaps_count))
1732 return NULL;
1733 return mdsc->a_rtpmaps[index]->parameters;
1736 unsigned int
1737 fsdp_get_media_sdplang_count (const fsdp_media_description_t * mdsc)
1739 if (!mdsc)
1740 return 0;
1741 return mdsc->a_sdplangs_count;
1744 const char *
1745 fsdp_get_media_sdplang (const fsdp_media_description_t * mdsc,
1746 unsigned int index)
1748 if (!mdsc || (index >= mdsc->a_sdplangs_count))
1749 return NULL;
1750 return mdsc->a_sdplangs[index];
1753 unsigned int
1754 fsdp_get_media_lang_count (const fsdp_media_description_t * mdsc)
1756 if (!mdsc)
1757 return 0;
1758 return mdsc->a_langs_count;
1761 const char *
1762 fsdp_get_media_lang (const fsdp_media_description_t * mdsc,
1763 unsigned int index)
1765 if (!mdsc || (index >= mdsc->a_langs_count))
1766 return NULL;
1767 return mdsc->a_langs[index];
1770 unsigned int
1771 fsdp_get_media_control_count (const fsdp_media_description_t * mdsc)
1773 if (!mdsc)
1774 return 0;
1775 return mdsc->a_controls_count;
1778 char *
1779 fsdp_get_media_control (const fsdp_media_description_t * mdsc,
1780 unsigned int index)
1782 if (!mdsc || (index >= mdsc->a_controls_count))
1783 return NULL;
1784 return mdsc->a_controls[index];
1787 char *
1788 fsdp_get_media_range (const fsdp_media_description_t * mdsc)
1790 return mdsc->a_range;
1793 unsigned int
1794 fsdp_get_media_fmtp_count (const fsdp_media_description_t * mdsc)
1796 if (!mdsc)
1797 return 0;
1798 return mdsc->a_fmtps_count;
1801 const char *
1802 fsdp_get_media_fmtp (const fsdp_media_description_t * mdsc,
1803 unsigned int index)
1805 if (!mdsc || (index >= mdsc->a_fmtps_count))
1806 return NULL;
1807 return mdsc->a_fmtps[index];
1810 fsdp_orient_t
1811 fsdp_get_media_orient (const fsdp_media_description_t * dsc)
1813 if (!dsc)
1814 return FSDP_ORIENT_UNDEFINED;
1815 return dsc->a_orient;
1818 fsdp_sendrecv_mode_t
1819 fsdp_get_media_sendrecv (const fsdp_media_description_t * dsc)
1821 if (!dsc)
1822 return FSDP_SENDRECV_UNDEFINED;
1823 return dsc->a_sendrecv_mode;
1826 float
1827 fsdp_get_media_framerate (const fsdp_media_description_t * dsc)
1829 if (!dsc)
1830 return 0;
1831 return dsc->a_framerate;
1834 unsigned int
1835 fsdp_get_media_quality (const fsdp_media_description_t * dsc)
1837 if (!dsc)
1838 return 0;
1839 return dsc->a_quality;
1842 unsigned int
1843 fsdp_get_media_rtcp_port (const fsdp_media_description_t * dsc)
1845 if (!dsc)
1846 return 0;
1847 return dsc->a_rtcp_port;
1850 fsdp_network_type_t
1851 fsdp_get_media_rtcp_network_type (const fsdp_media_description_t * dsc)
1853 if (!dsc)
1854 return FSDP_NETWORK_TYPE_UNDEFINED;
1855 return dsc->a_rtcp_network_type;
1858 fsdp_address_type_t
1859 fsdp_get_media_rtcp_address_type (const fsdp_media_description_t * dsc)
1861 if (!dsc)
1862 return FSDP_ADDRESS_TYPE_UNDEFINED;
1863 return dsc->a_rtcp_address_type;
1866 const char *
1867 fsdp_get_media_rtcp_address (const fsdp_media_description_t * dsc)
1869 if (!dsc)
1870 return NULL;
1871 return dsc->a_rtcp_address;
1874 unsigned int
1875 fsdp_get_media_unidentified_attribute_count (const fsdp_media_description_t
1876 * mdsc)
1878 if (!mdsc)
1879 return 0;
1880 return mdsc->unidentified_attributes_count;
1883 const char *
1884 fsdp_get_media_unidentified_attribute (const fsdp_media_description_t * mdsc,
1885 unsigned int index)
1887 if (!mdsc || (index < mdsc->unidentified_attributes_count))
1888 return NULL;
1889 return mdsc->unidentified_attributes[index];