Mercurial > mplayer.hg
comparison stream/freesdp/parser.c @ 19271:64d82a45a05d
introduce new 'stream' directory for all stream layer related components and split them from libmpdemux
author | ben |
---|---|
date | Mon, 31 Jul 2006 17:39:17 +0000 |
parents | libmpdemux/freesdp/parser.c@af9b014311a5 |
children | 8ed444639678 |
comparison
equal
deleted
inserted
replaced
19270:7d39b911f0bd | 19271:64d82a45a05d |
---|---|
1 /* | |
2 This file is part of FreeSDP | |
3 Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@altern.org> | |
4 | |
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. | |
9 | |
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. | |
14 | |
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 | |
18 | |
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. | |
22 */ | |
23 | |
24 /** | |
25 * @file parser.c | |
26 * | |
27 * @short Parsing module implementation. | |
28 * | |
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 **/ | |
35 | |
36 #include "parserpriv.h" | |
37 | |
38 /** | |
39 * Moves the <code>c<code> pointer up to the beginning of the next | |
40 * line. | |
41 * | |
42 * @param c char pointer to pointer | |
43 * @retval FSDPE_ILLEGAL_CHARACTER, when an illegal '\r' character | |
44 * (not followed by a '\n') is found, returns | |
45 */ | |
46 #define NEXT_LINE(c) \ | |
47 ({ \ | |
48 while ((*(c) != '\0') && (*(c) != '\r') && (*(c) != '\n')) { \ | |
49 (c)++; \ | |
50 } \ | |
51 if (*(c) == '\n') { \ | |
52 (c)++; \ | |
53 } else if (*(c) == '\r') { \ | |
54 (c)++; \ | |
55 if (*(c) == '\n') { \ | |
56 (c)++; \ | |
57 } else { \ | |
58 return FSDPE_ILLEGAL_CHARACTER; \ | |
59 } \ | |
60 } \ | |
61 }) | |
62 | |
63 fsdp_error_t | |
64 fsdp_parse (const char *text_description, fsdp_description_t * dsc) | |
65 { | |
66 fsdp_error_t result; | |
67 const char *p = text_description, *p2; | |
68 unsigned int index, 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]; | |
75 | |
76 if ((NULL == text_description) || (NULL == dsc)) | |
77 return FSDPE_INVALID_PARAMETER; | |
78 | |
79 /***************************************************************************/ | |
80 /* A) parse session-level description */ | |
81 /***************************************************************************/ | |
82 | |
83 /* `v=' line (protocol version) */ | |
84 /* according to the RFC, only `v=0' is valid */ | |
85 if (sscanf (p, "v=%1lu", &wuint[0])) | |
86 { | |
87 if (wuint[0] != 0) | |
88 return FSDPE_INVALID_VERSION; | |
89 } | |
90 else | |
91 { | |
92 return FSDPE_MISSING_VERSION; | |
93 } | |
94 NEXT_LINE (p); | |
95 | |
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)) | |
100 { | |
101 p += 2; | |
102 /* note that the following max lengths may vary in the future and | |
103 are quite arbitary */ | |
104 if (sscanf | |
105 (p, | |
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)) | |
114 { | |
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; | |
122 } | |
123 else | |
124 { | |
125 return FSDPE_INVALID_OWNER; | |
126 } | |
127 /* TODO? check valid unicast address/FQDN */ | |
128 dsc->o_address = strdup (fsdp_buf[5]); | |
129 } | |
130 else | |
131 { | |
132 return FSDPE_MISSING_OWNER; | |
133 } | |
134 NEXT_LINE (p); | |
135 | |
136 /* `s=' line (session name) -note that the name string cannot be empty */ | |
137 /* s=<session name> */ | |
138 if (!strncmp (p, "s=", 2)) | |
139 { | |
140 if (sscanf (p, "s=%" MLFLENS "[^\r\n]", longfsdp_buf) < 1) | |
141 return FSDPE_EMPTY_NAME; | |
142 dsc->s_name = strdup (longfsdp_buf); | |
143 } | |
144 else | |
145 { | |
146 return FSDPE_MISSING_NAME; | |
147 } | |
148 NEXT_LINE (p); | |
149 | |
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)) | |
154 { | |
155 dsc->i_information = strdup (longfsdp_buf); | |
156 NEXT_LINE (p); | |
157 } | |
158 else | |
159 { | |
160 /* (optional) information absent */ | |
161 } | |
162 | |
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)) | |
167 { | |
168 /* TODO? check valid uri */ | |
169 dsc->u_uri = strdup (longfsdp_buf); | |
170 NEXT_LINE (p); | |
171 } | |
172 else | |
173 { | |
174 /* (optional) uri absent */ | |
175 } | |
176 | |
177 /* `e=' lines (email address) [zero or more] */ | |
178 /* e=<email address> */ | |
179 p2 = p; | |
180 j = 0; | |
181 while (!strncmp (p2, "e=", 2)) | |
182 { | |
183 /* First, count how many emails are there */ | |
184 j++; | |
185 NEXT_LINE (p2); | |
186 } | |
187 dsc->emails_count = j; | |
188 if (dsc->emails_count > 0) | |
189 { | |
190 /* Then, build the array of emails */ | |
191 dsc->emails = calloc (j, sizeof (const char *)); | |
192 for (j = 0; j < dsc->emails_count; j++) | |
193 { | |
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); | |
198 } | |
199 } | |
200 | |
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)) | |
206 { | |
207 j++; | |
208 NEXT_LINE (p2); | |
209 } | |
210 dsc->phones_count = j; | |
211 if (dsc->phones_count > 0) | |
212 { | |
213 dsc->phones = calloc (j, sizeof (const char *)); | |
214 for (j = 0; j < dsc->phones_count; j++) | |
215 { | |
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); | |
220 } | |
221 } | |
222 | |
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; | |
229 | |
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; | |
236 | |
237 /* A.1) Time descriptions: */ | |
238 | |
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)) | |
244 { | |
245 j++; | |
246 NEXT_LINE (p2); | |
247 while (!strncmp (p2, "r=", 2)) | |
248 NEXT_LINE (p2); | |
249 } | |
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 index = 0; | |
256 for (j = 0; j < dsc->time_periods_count; j++) | |
257 { | |
258 unsigned int h = 0; | |
259 if (sscanf (p, "t=%10lu %10lu", &wuint[0], &wuint[1]) != 2) | |
260 { | |
261 /* not all periods have been successfully parsed */ | |
262 dsc->time_periods_count = j; | |
263 return FSDPE_INVALID_TIME; | |
264 } | |
265 dsc->time_periods[j] = calloc (1, sizeof (fsdp_time_period_t)); | |
266 | |
267 /* convert from NTP to time_t time */ | |
268 if (wuint[0] != 0) | |
269 wuint[0] -= NTP_EPOCH_OFFSET; | |
270 if (wuint[1] != 0) | |
271 wuint[1] -= NTP_EPOCH_OFFSET; | |
272 dsc->time_periods[j]->start = wuint[0]; | |
273 dsc->time_periods[j]->stop = wuint[1]; | |
274 NEXT_LINE (p); | |
275 | |
276 /* `r' lines [zero or more repeat times for each t=] */ | |
277 /*r=<repeat interval> <active duration> <list of offsets from | |
278 start-time> */ | |
279 p2 = p; | |
280 while (!strncmp (p2, "r=", 2)) | |
281 { | |
282 h++; | |
283 NEXT_LINE (p2); | |
284 } | |
285 dsc->time_periods[j]->repeats_count = h; | |
286 if (h > 0) | |
287 { | |
288 unsigned int index2 = 0; | |
289 dsc->time_periods[j]->repeats = | |
290 calloc (h, sizeof (fsdp_repeat_t *)); | |
291 for (h = 0; h < dsc->time_periods[j]->repeats_count; h++) | |
292 { | |
293 /* | |
294 get_repeat_values(p,&(dsc->time_periods[index].repeats[index2])); | |
295 fsdp_error_t get_repeat_values (const char *r, fsdp_repeat_t | |
296 *repeat); | |
297 */ | |
298 if (sscanf (p, "r=%10s %10s %" MLFLENS "[^\r\n]", | |
299 fsdp_buf[0], fsdp_buf[1], longfsdp_buf) == 3) | |
300 { | |
301 fsdp_repeat_t *repeat; | |
302 dsc->time_periods[j]->repeats[h] = | |
303 calloc (1, sizeof (fsdp_repeat_t)); | |
304 repeat = dsc->time_periods[j]->repeats[h]; | |
305 /* get interval, duration and list of offsets */ | |
306 result = | |
307 fsdp_repeat_time_to_uint (fsdp_buf[0], | |
308 &(repeat->interval)); | |
309 if (result == FSDPE_OK) | |
310 { | |
311 result = | |
312 fsdp_repeat_time_to_uint (fsdp_buf[1], | |
313 &(repeat->duration)); | |
314 if (result == FSDPE_OK) | |
315 { | |
316 unsigned int k = 1; | |
317 const char *i = longfsdp_buf; | |
318 while (NULL != (i = strchr (i, ' '))) | |
319 { | |
320 k++; | |
321 if (NULL != i) | |
322 i++; | |
323 } | |
324 repeat->offsets_count = k; | |
325 repeat->offsets = calloc (k, sizeof (time_t)); | |
326 i = longfsdp_buf; | |
327 for (k = 0; | |
328 (k < repeat->offsets_count) | |
329 && (result == FSDPE_OK); k++) | |
330 { | |
331 result = | |
332 fsdp_repeat_time_to_uint (i, | |
333 &(repeat-> | |
334 offsets[k])); | |
335 i = strchr (i, ' '); | |
336 if (NULL != i) | |
337 i++; | |
338 } | |
339 if (k < repeat->offsets_count) | |
340 { | |
341 /* there where invalid repeat offsets */ | |
342 dsc->time_periods[j]->repeats_count = k; | |
343 return FSDPE_INVALID_REPEAT; | |
344 } | |
345 } | |
346 } | |
347 if (result != FSDPE_OK) | |
348 { | |
349 /* not all repeats have been succesfully parsed */ | |
350 dsc->time_periods[j]->repeats_count = h; | |
351 return FSDPE_INVALID_REPEAT; | |
352 } | |
353 NEXT_LINE (p); | |
354 } | |
355 else | |
356 { | |
357 /* not all repeats have been succesfully parsed */ | |
358 dsc->time_periods[j]->repeats_count = h; | |
359 return FSDPE_INVALID_REPEAT; | |
360 } | |
361 index2++; | |
362 } | |
363 } | |
364 } | |
365 | |
366 /* `z=' line (time zone adjustments) [zero or more] */ | |
367 /* z=<adjustment time> <offset> <adjustment time> <offset> .... */ | |
368 if (!strncmp (p, "z=", 2)) | |
369 { | |
370 if (sscanf (p, "z=%" MLFLENS "[^\r\n]", longfsdp_buf)) | |
371 { | |
372 /* TODO: guess how many pairs are there and process them */ | |
373 dsc->timezone_adj = strdup (longfsdp_buf); | |
374 NEXT_LINE (p); | |
375 } | |
376 else | |
377 { | |
378 return FSDPE_INVALID_TIMEZONE; | |
379 } | |
380 } | |
381 | |
382 /* `k=' line (encryption key) [optional] */ | |
383 /* k=<method> | |
384 k=<method>:<encryption key> */ | |
385 result = fsdp_parse_k (&p, &(dsc->k_encryption_method), | |
386 &(dsc->k_encryption_content)); | |
387 if (result != FSDPE_OK) | |
388 return result; | |
389 | |
390 /* A.2) Attributes */ | |
391 /* `a=' lines (session attribute) [0 or more] */ | |
392 /* a=<attribute> | |
393 a=<attribute>:<value> */ | |
394 while (!strncmp (p, "a=", 2)) | |
395 { | |
396 /* The "9" lenght specifier of the first string is subject to | |
397 changes */ | |
398 if (sscanf | |
399 (p, "a=%9[^:\r\n]:%" MSFLENS "[^\r\n]", fsdp_buf[0], | |
400 fsdp_buf[1]) == 2) | |
401 { | |
402 /* session-level value attributes */ | |
403 if (!strncmp (fsdp_buf[0], "cat", 3)) | |
404 dsc->a_category = strdup (fsdp_buf[1]); | |
405 else if (!strncmp (fsdp_buf[0], "keywds", 6)) | |
406 dsc->a_keywords = strdup (fsdp_buf[1]); | |
407 else if (!strncmp (fsdp_buf[0], "tool", 4)) | |
408 dsc->a_keywords = strdup (fsdp_buf[1]); | |
409 else if (!strncmp (fsdp_buf[0], "rtpmap", 6)) | |
410 fsdp_parse_rtpmap (&(dsc->a_rtpmaps), | |
411 &(dsc->a_rtpmaps_count), fsdp_buf[1]); | |
412 else if (!strncmp (fsdp_buf[0], "type", 4)) | |
413 { | |
414 if (!strncmp (fsdp_buf[1], "broadcast", 9)) | |
415 dsc->a_type = FSDP_SESSION_TYPE_BROADCAST; | |
416 else if (!strncmp (fsdp_buf[1], "meeting", 7)) | |
417 dsc->a_type = FSDP_SESSION_TYPE_MEETING; | |
418 else if (!strncmp (fsdp_buf[1], "moderated", 9)) | |
419 dsc->a_type = FSDP_SESSION_TYPE_MODERATED; | |
420 else if (!strncmp (fsdp_buf[1], "test", 4)) | |
421 dsc->a_type = FSDP_SESSION_TYPE_TEST; | |
422 else if (!strncmp (fsdp_buf[1], "H332", 4)) | |
423 dsc->a_type = FSDP_SESSION_TYPE_H332; | |
424 else | |
425 return FSDPE_INVALID_SESSION_TYPE; | |
426 } | |
427 else if (!strncmp (fsdp_buf[0], "charset", 7)) | |
428 dsc->a_charset = strdup (fsdp_buf[1]); | |
429 else if (!strncmp (fsdp_buf[0], "sdplang", 7)) | |
430 { | |
431 if (NULL == dsc->a_sdplangs) | |
432 { | |
433 dsc->a_sdplangs_count = 0; | |
434 dsc->a_sdplangs = | |
435 calloc (SDPLANGS_MAX_COUNT, sizeof (char *)); | |
436 } | |
437 if (dsc->a_sdplangs_count < SDPLANGS_MAX_COUNT) | |
438 { | |
439 dsc->a_sdplangs[dsc->a_sdplangs_count] = | |
440 strdup (fsdp_buf[1]); | |
441 dsc->a_sdplangs_count++; | |
442 } | |
443 } | |
444 else if (!strncmp (fsdp_buf[0], "lang", 4)) | |
445 { | |
446 if (NULL == dsc->a_langs) | |
447 { | |
448 dsc->a_langs_count = 0; | |
449 dsc->a_langs = calloc (SDPLANGS_MAX_COUNT, sizeof (char *)); | |
450 } | |
451 if (dsc->a_langs_count < SDPLANGS_MAX_COUNT) | |
452 { | |
453 dsc->a_langs[dsc->a_langs_count] = strdup (fsdp_buf[1]); | |
454 dsc->a_langs_count++; | |
455 } | |
456 } | |
457 else if (!strncmp (fsdp_buf[0], "control", 7)) | |
458 { | |
459 if (NULL == dsc->a_controls) | |
460 { | |
461 dsc->a_controls_count = 0; | |
462 dsc->a_controls = | |
463 calloc (SDPCONTROLS_MAX_COUNT, sizeof (char *)); | |
464 } | |
465 if (dsc->a_controls_count < SDPCONTROLS_MAX_COUNT) | |
466 { | |
467 dsc->a_controls[dsc->a_controls_count] = | |
468 strdup (fsdp_buf[1]); | |
469 dsc->a_controls_count++; | |
470 } | |
471 } | |
472 else if (!strncmp (fsdp_buf[0], "range", 5)) | |
473 { | |
474 if (dsc->a_range) | |
475 free (dsc->a_range); | |
476 dsc->a_range = strdup (fsdp_buf[1]); | |
477 } | |
478 else | |
479 { | |
480 /* ignore unknown attributes, but provide access to them */ | |
481 *longfsdp_buf = '\0'; | |
482 strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN); | |
483 strncat (longfsdp_buf, ":", MAXLONGFIELDLEN); | |
484 strncat (longfsdp_buf, fsdp_buf[1], MAXLONGFIELDLEN); | |
485 if (NULL == dsc->unidentified_attributes) | |
486 { | |
487 dsc->unidentified_attributes_count = 0; | |
488 dsc->unidentified_attributes = | |
489 calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT, | |
490 sizeof (char *)); | |
491 } | |
492 if (dsc->unidentified_attributes_count < | |
493 UNIDENTIFIED_ATTRIBUTES_MAX_COUNT) | |
494 { | |
495 dsc->unidentified_attributes | |
496 [dsc->unidentified_attributes_count] = | |
497 strdup (longfsdp_buf); | |
498 dsc->unidentified_attributes_count++; | |
499 } | |
500 } | |
501 NEXT_LINE (p); | |
502 } | |
503 else if (sscanf (p, "a=%20s", fsdp_buf[0]) == 1) | |
504 { | |
505 /* session-level property attributes */ | |
506 if (!strncmp (fsdp_buf[0], "recvonly", 8)) | |
507 dsc->a_sendrecv_mode = FSDP_SENDRECV_RECVONLY; | |
508 else if (!strncmp (fsdp_buf[0], "sendonly", 8)) | |
509 dsc->a_sendrecv_mode = FSDP_SENDRECV_SENDONLY; | |
510 else if (!strncmp (fsdp_buf[0], "inactive", 8)) | |
511 dsc->a_sendrecv_mode = FSDP_SENDRECV_INACTIVE; | |
512 else if (!strncmp (fsdp_buf[0], "sendrecv", 8)) | |
513 dsc->a_sendrecv_mode = FSDP_SENDRECV_SENDRECV; | |
514 else | |
515 { | |
516 /* ignore unknown attributes, but provide access to them */ | |
517 *longfsdp_buf = '\0'; | |
518 strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN); | |
519 if (NULL == dsc->unidentified_attributes) | |
520 { | |
521 dsc->unidentified_attributes_count = 0; | |
522 dsc->unidentified_attributes = | |
523 calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT, | |
524 sizeof (char *)); | |
525 } | |
526 if (dsc->unidentified_attributes_count < | |
527 UNIDENTIFIED_ATTRIBUTES_MAX_COUNT) | |
528 { | |
529 dsc->unidentified_attributes | |
530 [dsc->unidentified_attributes_count] = | |
531 strdup (longfsdp_buf); | |
532 dsc->unidentified_attributes_count++; | |
533 } | |
534 } | |
535 NEXT_LINE (p); | |
536 } | |
537 else | |
538 return FSDPE_INVALID_ATTRIBUTE; | |
539 } | |
540 | |
541 /***************************************************************************/ | |
542 /* B) parse media-level descriptions */ | |
543 /***************************************************************************/ | |
544 p2 = p; | |
545 j = 0; | |
546 while ((*p2 != '\0') && !strncmp (p2, "m=", 2)) | |
547 { | |
548 char c; | |
549 j++; | |
550 NEXT_LINE (p2); | |
551 while (sscanf (p2, "%c=", &c) == 1) | |
552 { | |
553 if (c == 'i' || c == 'c' || c == 'b' || c == 'k' || c == 'a') | |
554 { | |
555 NEXT_LINE (p2); | |
556 } | |
557 else if (c == 'm') | |
558 { | |
559 break; | |
560 } | |
561 else | |
562 { | |
563 return FSDPE_INVALID_LINE; | |
564 } | |
565 } | |
566 } | |
567 dsc->media_announcements_count = j; | |
568 if (dsc->media_announcements_count == 0) | |
569 { | |
570 ; | |
571 /*return FSDPE_MISSING_MEDIA; */ | |
572 } | |
573 else | |
574 { /* dsc->media_announcements_count > 0 */ | |
575 dsc->media_announcements = | |
576 calloc (j, sizeof (fsdp_media_announcement_t *)); | |
577 for (j = 0; j < dsc->media_announcements_count; j++) | |
578 { | |
579 fsdp_media_announcement_t *media = NULL; | |
580 /* `m=' line (media name, transport address and format list) */ | |
581 /* m=<media> <port> <transport> <fmt list> */ | |
582 /* The max. string lengths are subject to change */ | |
583 if (sscanf (p, "m=%11s %8s %7s %" MLFLENS "[^\r\n]", | |
584 fsdp_buf[0], fsdp_buf[1], fsdp_buf[2], | |
585 longfsdp_buf) != 4) | |
586 { | |
587 return FSDPE_INVALID_MEDIA; | |
588 } | |
589 else | |
590 { | |
591 dsc->media_announcements[j] = | |
592 calloc (1, sizeof (fsdp_media_announcement_t)); | |
593 media = dsc->media_announcements[j]; | |
594 if (!strncmp (fsdp_buf[0], "audio", 5)) | |
595 media->media_type = FSDP_MEDIA_AUDIO; | |
596 else if (!strncmp (fsdp_buf[0], "video", 5)) | |
597 media->media_type = FSDP_MEDIA_VIDEO; | |
598 else if (!strncmp (fsdp_buf[0], "application", 11)) | |
599 media->media_type = FSDP_MEDIA_APPLICATION; | |
600 else if (!strncmp (fsdp_buf[0], "data", 4)) | |
601 media->media_type = FSDP_MEDIA_DATA; | |
602 else if (!strncmp (fsdp_buf[0], "control", 7)) | |
603 media->media_type = FSDP_MEDIA_CONTROL; | |
604 else | |
605 return FSDPE_UNKNOWN_MEDIA_TYPE; | |
606 { /* try to get port specification as port/number */ | |
607 char *slash; | |
608 if ((slash = strchr (fsdp_buf[1], '/'))) | |
609 { | |
610 *slash = '\0'; | |
611 slash++; | |
612 media->port = strtol (fsdp_buf[1], NULL, 10); | |
613 media->port_count = strtol (slash, NULL, 10); | |
614 } | |
615 else | |
616 { | |
617 media->port = strtol (fsdp_buf[1], NULL, 10); | |
618 media->port_count = 0; | |
619 } | |
620 } | |
621 if (!strncmp (fsdp_buf[2], "RTP/AVP", 7)) | |
622 media->transport = FSDP_TP_RTP_AVP; | |
623 else if (!strncmp (fsdp_buf[2], "udp", 3)) | |
624 media->transport = FSDP_TP_UDP; | |
625 else if (!strncmp (fsdp_buf[2], "TCP", 3)) | |
626 media->transport = FSDP_TP_TCP; | |
627 else if (!strncmp (fsdp_buf[2], "UDPTL", 5)) | |
628 media->transport = FSDP_TP_UDPTL; | |
629 else if (!strncmp (fsdp_buf[2], "vat", 3)) | |
630 media->transport = FSDP_TP_VAT; | |
631 else if (!strncmp (fsdp_buf[2], "rtp", 3)) | |
632 media->transport = FSDP_TP_OLD_RTP; | |
633 else | |
634 return FSDPE_UNKNOWN_MEDIA_TRANSPORT; | |
635 { | |
636 unsigned int k = 0; | |
637 char *s = longfsdp_buf; | |
638 while (NULL != (s = strchr (s, ' '))) | |
639 { | |
640 k++; | |
641 if (NULL != s) | |
642 s++; | |
643 } | |
644 k++; /* when there is no space left, count the last format */ | |
645 media->formats_count = k; | |
646 media->formats = calloc (k, sizeof (char *)); | |
647 s = longfsdp_buf; | |
648 for (k = 0; k < media->formats_count; k++) | |
649 { | |
650 char *space = strchr (s, ' '); | |
651 if (NULL != space) | |
652 *space = '\0'; | |
653 media->formats[k] = strdup (s); | |
654 s = space + 1; | |
655 } | |
656 } | |
657 NEXT_LINE (p); | |
658 } | |
659 | |
660 /* `i=' line (media title) [optional] */ | |
661 /* i=<media title> */ | |
662 if (!strncmp (p, "i=", 2) | |
663 && sscanf (p, "i=%" MLFLENS "[^\r\n]", longfsdp_buf)) | |
664 { | |
665 media->i_title = strdup (longfsdp_buf); | |
666 NEXT_LINE (p); | |
667 } | |
668 else | |
669 { | |
670 /* (optional) information absent */ | |
671 } | |
672 | |
673 /* `c=' line (connection information - overrides session-level | |
674 line) [optional if provided at session-level] */ | |
675 /* c=<network type> <address type> <connection address> */ | |
676 result = fsdp_parse_c (&p, &(media->c_network_type), | |
677 &(media->c_address_type), | |
678 &(media->c_address)); | |
679 if (result != FSDPE_OK) | |
680 return result; | |
681 | |
682 /* `b=' lines (bandwidth information) [optional] */ | |
683 /* b=<modifier>:<bandwidth-value> */ | |
684 result = fsdp_parse_b (&p, &(media->bw_modifiers), | |
685 &(media->bw_modifiers_count)); | |
686 if (FSDPE_OK != result) | |
687 return result; | |
688 | |
689 /* `k=' line (encryption key) [optional] */ | |
690 /* k=<method> | |
691 k=<method>:<encryption key> */ | |
692 result = fsdp_parse_k (&p, &(media->k_encryption_method), | |
693 &(media->k_encryption_content)); | |
694 if (result != FSDPE_OK) | |
695 return result; | |
696 | |
697 /* B.1) Attributes */ | |
698 | |
699 /* `a=' lines (zero or more media attribute lines) [optional] */ | |
700 /* a=<attribute> | |
701 a=<attribute>:<value> */ | |
702 while (!strncmp (p, "a=", 2)) | |
703 { | |
704 if (sscanf | |
705 (p, "a=%9[^:\r\n]:%" MLFLENS "[^\r\n]", fsdp_buf[0], | |
706 longfsdp_buf) == 2) | |
707 { | |
708 /* media-level value attributes */ | |
709 if (!strncmp (fsdp_buf[0], "ptime", 5)) | |
710 media->a_ptime = strtoul (longfsdp_buf, NULL, 10); | |
711 else if (!strncmp (fsdp_buf[0], "maxptime", 8)) | |
712 media->a_maxptime = strtoul (longfsdp_buf, NULL, 10); | |
713 else if (!strncmp (fsdp_buf[0], "rtpmap", 6)) | |
714 fsdp_parse_rtpmap (&(media->a_rtpmaps), | |
715 &(media->a_rtpmaps_count), | |
716 longfsdp_buf); | |
717 else if (!strncmp (fsdp_buf[0], "orient", 6)) | |
718 { | |
719 if (!strncmp (longfsdp_buf, "portrait", 8)) | |
720 media->a_orient = FSDP_ORIENT_PORTRAIT; | |
721 else if (!strncmp (longfsdp_buf, "landscape", 9)) | |
722 media->a_orient = FSDP_ORIENT_LANDSCAPE; | |
723 else if (!strncmp (longfsdp_buf, "seascape", 9)) | |
724 media->a_orient = FSDP_ORIENT_SEASCAPE; | |
725 } | |
726 else if (!strncmp (fsdp_buf[0], "sdplang", 7)) | |
727 { | |
728 if (NULL == dsc->a_sdplangs) | |
729 { | |
730 media->a_sdplangs_count = 0; | |
731 media->a_sdplangs = | |
732 calloc (SDPLANGS_MAX_COUNT, sizeof (char *)); | |
733 } | |
734 if (media->a_sdplangs_count < SDPLANGS_MAX_COUNT) | |
735 { | |
736 media->a_sdplangs[dsc->a_sdplangs_count] = | |
737 strdup (longfsdp_buf); | |
738 media->a_sdplangs_count++; | |
739 } | |
740 } | |
741 else if (!strncmp (fsdp_buf[0], "lang", 4)) | |
742 { | |
743 if (NULL == dsc->a_langs) | |
744 { | |
745 media->a_langs_count = 0; | |
746 media->a_langs = | |
747 calloc (SDPLANGS_MAX_COUNT, sizeof (char *)); | |
748 } | |
749 if (media->a_langs_count < SDPLANGS_MAX_COUNT) | |
750 { | |
751 media->a_langs[dsc->a_langs_count] = | |
752 strdup (longfsdp_buf); | |
753 media->a_langs_count++; | |
754 } | |
755 } | |
756 else if (!strncmp (fsdp_buf[0], "control", 7)) | |
757 { | |
758 if (NULL == media->a_controls) | |
759 { | |
760 media->a_controls_count = 0; | |
761 media->a_controls = | |
762 calloc (SDPCONTROLS_MAX_COUNT, sizeof (char *)); | |
763 } | |
764 if (media->a_controls_count < SDPCONTROLS_MAX_COUNT) | |
765 { | |
766 media->a_controls[media->a_controls_count] = | |
767 strdup (longfsdp_buf); | |
768 media->a_controls_count++; | |
769 } | |
770 } | |
771 else if (!strncmp (fsdp_buf[0], "range", 5)) | |
772 { | |
773 if (media->a_range) | |
774 free (media->a_range); | |
775 media->a_range = strdup (fsdp_buf[1]); | |
776 } | |
777 else if (!strncmp (fsdp_buf[0], "framerate", 9)) | |
778 media->a_framerate = strtod (longfsdp_buf, NULL); | |
779 else if (!strncmp (fsdp_buf[0], "fmtp", 4)) | |
780 { | |
781 if (NULL == media->a_fmtps) | |
782 { | |
783 media->a_fmtps_count = 0; | |
784 media->a_fmtps = | |
785 calloc (SDPLANGS_MAX_COUNT, sizeof (char *)); | |
786 } | |
787 if (media->a_fmtps_count < SDPLANGS_MAX_COUNT) | |
788 { | |
789 media->a_fmtps[media->a_fmtps_count] = | |
790 strdup (longfsdp_buf); | |
791 media->a_fmtps_count++; | |
792 } | |
793 } | |
794 else if (!strncmp (fsdp_buf[0], "rtcp", 4)) | |
795 { | |
796 int opts = 0; | |
797 /* rtcp attribute: a=rtcp:<port> <nettype> <addrtype> <address> */ | |
798 opts = | |
799 sscanf (longfsdp_buf, "%lu %2s %3s %" MSFLENS "s", | |
800 &wuint[0], fsdp_buf[0], fsdp_buf[1], | |
801 fsdp_buf[2]); | |
802 if (opts >= 1) | |
803 { | |
804 media->a_rtcp_port = wuint[0]; | |
805 if (opts >= 2) | |
806 { | |
807 if (!strncmp (fsdp_buf[0], "IN", 2)) | |
808 { | |
809 media->a_rtcp_network_type = | |
810 FSDP_NETWORK_TYPE_INET; | |
811 } /* else | |
812 ; TODO: define error code? */ | |
813 if (opts >= 3) | |
814 { | |
815 if (!strncmp (fsdp_buf[1], "IP4", 3)) | |
816 media->a_rtcp_address_type = | |
817 FSDP_ADDRESS_TYPE_IPV4; | |
818 else if (!strncmp (fsdp_buf[1], "IP6", 3)) | |
819 media->a_rtcp_address_type = | |
820 FSDP_ADDRESS_TYPE_IPV6; | |
821 else | |
822 return FSDPE_INVALID_CONNECTION_NETTYPE; | |
823 /*add specific code? */ | |
824 if (opts >= 4) | |
825 media->a_rtcp_address = | |
826 strdup (fsdp_buf[2]); | |
827 } | |
828 } | |
829 } | |
830 } | |
831 else | |
832 { | |
833 /* ignore unknown attributes, but provide access to them */ | |
834 *fsdp_buf[1] = '\0'; | |
835 strncat (fsdp_buf[1], fsdp_buf[0], MAXLONGFIELDLEN); | |
836 strncat (fsdp_buf[1], ":", MAXLONGFIELDLEN); | |
837 strncat (fsdp_buf[1], longfsdp_buf, MAXLONGFIELDLEN); | |
838 if (NULL == media->unidentified_attributes) | |
839 { | |
840 media->unidentified_attributes_count = 0; | |
841 media->unidentified_attributes = | |
842 calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT, | |
843 sizeof (char *)); | |
844 } | |
845 if (media->unidentified_attributes_count < | |
846 UNIDENTIFIED_ATTRIBUTES_MAX_COUNT) | |
847 { | |
848 media->unidentified_attributes | |
849 [media->unidentified_attributes_count] = | |
850 strdup (fsdp_buf[1]); | |
851 media->unidentified_attributes_count++; | |
852 } | |
853 } | |
854 NEXT_LINE (p); | |
855 } | |
856 else if (sscanf (p, "a=%8s", fsdp_buf[0]) == 1) | |
857 { | |
858 /* media-level property attributes */ | |
859 if (!strncmp (fsdp_buf[0], "recvonly", 8)) | |
860 media->a_sendrecv_mode = FSDP_SENDRECV_RECVONLY; | |
861 else if (!strncmp (fsdp_buf[0], "sendonly", 8)) | |
862 media->a_sendrecv_mode = FSDP_SENDRECV_SENDONLY; | |
863 else if (!strncmp (fsdp_buf[0], "inactive", 8)) | |
864 media->a_sendrecv_mode = FSDP_SENDRECV_INACTIVE; | |
865 else if (!strncmp (fsdp_buf[0], "sendrecv", 8)) | |
866 media->a_sendrecv_mode = FSDP_SENDRECV_SENDRECV; | |
867 else | |
868 { | |
869 /* ignore unknown attributes, but provide access to them */ | |
870 *longfsdp_buf = '\0'; | |
871 strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN); | |
872 if (NULL == media->unidentified_attributes) | |
873 { | |
874 media->unidentified_attributes_count = 0; | |
875 media->unidentified_attributes = | |
876 calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT, | |
877 sizeof (char *)); | |
878 } | |
879 if (media->unidentified_attributes_count < | |
880 UNIDENTIFIED_ATTRIBUTES_MAX_COUNT) | |
881 { | |
882 media->unidentified_attributes | |
883 [media->unidentified_attributes_count] = | |
884 strdup (longfsdp_buf); | |
885 media->unidentified_attributes_count++; | |
886 } | |
887 } | |
888 NEXT_LINE (p); | |
889 } | |
890 else | |
891 return FSDPE_INVALID_ATTRIBUTE; | |
892 } | |
893 } /* end of for */ | |
894 } | |
895 | |
896 /* Check c= has been given at session level or at media level for | |
897 all media */ | |
898 if (NULL == dsc->c_address.address) | |
899 { | |
900 unsigned int c; | |
901 for (c = 0; c < dsc->media_announcements_count; c++) | |
902 if (NULL == dsc->media_announcements[c]->c_address.address) | |
903 return FSDPE_MISSING_CONNECTION_INFO; | |
904 } | |
905 | |
906 /* finish */ | |
907 if (*p == '\0') | |
908 return FSDPE_OK; | |
909 else | |
910 return FSDPE_OVERFILLED; | |
911 } | |
912 | |
913 static fsdp_error_t | |
914 fsdp_parse_c (const char **p, fsdp_network_type_t * ntype, | |
915 fsdp_address_type_t * atype, | |
916 fsdp_connection_address_t * address) | |
917 { | |
918 const unsigned int TEMPCHARS = 3; | |
919 char fsdp_buf[TEMPCHARS][MAXSHORTFIELDLEN]; | |
920 | |
921 if (!strncmp (*p, "c=", 2)) | |
922 { | |
923 if (sscanf (*p, "c=%2s %3s %" MSFLENS "s", | |
924 fsdp_buf[0], fsdp_buf[1], fsdp_buf[2])) | |
925 { | |
926 if (!strncmp (fsdp_buf[0], "IN", 2)) | |
927 { | |
928 *ntype = FSDP_NETWORK_TYPE_INET; | |
929 if (!strncmp (fsdp_buf[1], "IP4", 3)) | |
930 *atype = FSDP_ADDRESS_TYPE_IPV4; | |
931 else if (!strncmp (fsdp_buf[1], "IP6", 3)) | |
932 *atype = FSDP_ADDRESS_TYPE_IPV6; | |
933 else | |
934 return FSDPE_INVALID_CONNECTION_NETTYPE; | |
935 } | |
936 else | |
937 { | |
938 return FSDPE_INVALID_CONNECTION_ADDRTYPE; | |
939 } | |
940 { | |
941 char *slash = strchr (fsdp_buf[2], '/'); | |
942 if (NULL == slash) | |
943 { | |
944 address->address = strdup (fsdp_buf[2]); | |
945 address->address_ttl = 0; | |
946 address->address_count = 0; | |
947 } | |
948 else | |
949 { | |
950 /* address is IP4 multicast */ | |
951 char *slash2; | |
952 *slash = '\0'; | |
953 slash++; | |
954 address->address = strdup (fsdp_buf[2]); | |
955 slash2 = strchr (slash + 1, '/'); | |
956 if (NULL == slash2) | |
957 { | |
958 address->address_ttl = strtol (slash, NULL, 10); | |
959 address->address_count = 0; | |
960 } | |
961 else | |
962 { | |
963 *slash2 = '\0'; | |
964 slash2++; | |
965 address->address_ttl = strtol (slash, NULL, 10); | |
966 address->address_count = strtol (slash2, NULL, 10); | |
967 } | |
968 } | |
969 } | |
970 NEXT_LINE (*p); | |
971 } | |
972 else | |
973 { | |
974 return FSDPE_INVALID_CONNECTION; | |
975 } | |
976 } | |
977 return FSDPE_OK; | |
978 } | |
979 | |
980 static fsdp_error_t | |
981 fsdp_parse_b (const char **p, fsdp_bw_modifier_t ** bw_modifiers, | |
982 unsigned int *bw_modifiers_count) | |
983 { | |
984 char fsdp_buf[MAXSHORTFIELDLEN]; | |
985 unsigned long int wuint; | |
986 unsigned int i = 0; | |
987 char *lp = (char *) *p; | |
988 | |
989 /* count b= lines */ | |
990 while (!strncmp (lp, "b=", 2)) | |
991 { | |
992 NEXT_LINE (lp); | |
993 i++; | |
994 } | |
995 *bw_modifiers = calloc (i, sizeof (fsdp_bw_modifier_t)); | |
996 *bw_modifiers_count = i; | |
997 | |
998 while (i > 0) | |
999 { | |
1000 unsigned int index = *bw_modifiers_count - i; | |
1001 if (2 == sscanf (*p, "b=%20[^:\r\n]:%lu", fsdp_buf, &wuint)) | |
1002 { | |
1003 if (!strncmp (fsdp_buf, "CT", 2)) | |
1004 (*bw_modifiers)[index].b_mod_type = | |
1005 FSDP_BW_MOD_TYPE_CONFERENCE_TOTAL; | |
1006 else if (!strncmp (fsdp_buf, "AS", 2)) | |
1007 (*bw_modifiers)[index].b_mod_type = | |
1008 FSDP_BW_MOD_TYPE_APPLICATION_SPECIFIC; | |
1009 else if (!strncmp (fsdp_buf, "RS", 2)) | |
1010 (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_RTCP_SENDERS; | |
1011 else if (!strncmp (fsdp_buf, "RR", 2)) | |
1012 (*bw_modifiers)[index].b_mod_type = | |
1013 FSDP_BW_MOD_TYPE_RTCP_RECEIVERS; | |
1014 else | |
1015 { | |
1016 (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_UNKNOWN; | |
1017 (*bw_modifiers)[index].b_unknown_bw_modt = | |
1018 (char *) strdup (fsdp_buf); | |
1019 } | |
1020 (*bw_modifiers)[index].b_value = wuint; | |
1021 NEXT_LINE (*p); | |
1022 } | |
1023 else | |
1024 { | |
1025 *bw_modifiers_count -= i; | |
1026 return FSDPE_INVALID_BANDWIDTH; | |
1027 } | |
1028 i--; | |
1029 } | |
1030 return FSDPE_OK; | |
1031 } | |
1032 | |
1033 static fsdp_error_t | |
1034 fsdp_parse_k (const char **p, fsdp_encryption_method_t * method, | |
1035 char **content) | |
1036 { | |
1037 char fsdp_buf[MAXSHORTFIELDLEN]; | |
1038 char longfsdp_buf[MAXLONGFIELDLEN]; | |
1039 | |
1040 if (!strncmp (*p, "k=", 2)) | |
1041 { | |
1042 if (sscanf (*p, "k=prompt")) | |
1043 { | |
1044 *method = FSDP_ENCRYPTION_METHOD_PROMPT; | |
1045 *content = NULL; | |
1046 NEXT_LINE (*p); | |
1047 } | |
1048 else | |
1049 { | |
1050 if (sscanf | |
1051 (*p, "k=%6[^:\r\n]:%" MLFLENS "s", fsdp_buf, longfsdp_buf)) | |
1052 { | |
1053 if (!strncmp (fsdp_buf, "clear", 5)) | |
1054 *method = FSDP_ENCRYPTION_METHOD_CLEAR; | |
1055 else if (!strncmp (fsdp_buf, "base64", 6)) | |
1056 *method = FSDP_ENCRYPTION_METHOD_BASE64; | |
1057 else if (!strncmp (fsdp_buf, "uri", 3)) | |
1058 *method = FSDP_ENCRYPTION_METHOD_URI; | |
1059 else | |
1060 return FSDPE_INVALID_ENCRYPTION_METHOD; | |
1061 *content = strdup (longfsdp_buf); | |
1062 NEXT_LINE (*p); | |
1063 } | |
1064 } | |
1065 } | |
1066 return FSDPE_OK; | |
1067 } | |
1068 | |
1069 static fsdp_error_t | |
1070 fsdp_parse_rtpmap (fsdp_rtpmap_t *** rtpmap, unsigned int *counter, | |
1071 const char *value) | |
1072 { | |
1073 fsdp_error_t result = FSDPE_OK; | |
1074 | |
1075 if (0 == *counter) | |
1076 { | |
1077 *counter = 0; | |
1078 *rtpmap = calloc (MEDIA_RTPMAPS_MAX_COUNT, sizeof (fsdp_rtpmap_t *)); | |
1079 } | |
1080 if (*counter < MEDIA_RTPMAPS_MAX_COUNT) | |
1081 { | |
1082 unsigned int c = *counter; | |
1083 fsdp_rtpmap_t **map = *rtpmap; | |
1084 char fsdp_buf[MAXSHORTFIELDLEN]; | |
1085 char longfsdp_buf[MAXLONGFIELDLEN]; | |
1086 map[c] = calloc (1, sizeof (fsdp_rtpmap_t)); | |
1087 | |
1088 /* a=rtpmap:<payload type> <encoding name>/<clock rate>[/<encoding | |
1089 parameters]> */ | |
1090 if (2 == sscanf (value, "%s %s", fsdp_buf, longfsdp_buf)) | |
1091 { | |
1092 char *slash1; | |
1093 map[c]->pt = strdup (fsdp_buf); | |
1094 /* parse <encoding name>/<clock rate>[/<encoding parameters>] */ | |
1095 slash1 = strchr (longfsdp_buf, '/'); | |
1096 if (NULL == slash1) | |
1097 { | |
1098 result = FSDPE_INVALID_ATTRIBUTE_RTPMAP; | |
1099 } | |
1100 else | |
1101 { | |
1102 char *slash2; | |
1103 *slash1 = '\0'; | |
1104 slash1++; | |
1105 map[c]->encoding_name = strdup (longfsdp_buf); | |
1106 slash2 = strchr (slash1, '/'); | |
1107 if (NULL != slash2) | |
1108 { | |
1109 *slash2 = '\0'; | |
1110 slash2++; | |
1111 map[c]->parameters = strdup (slash2); | |
1112 } | |
1113 map[c]->clock_rate = strtol (slash1, NULL, 10); | |
1114 } | |
1115 (*counter)++; | |
1116 } | |
1117 } | |
1118 return result; | |
1119 } | |
1120 | |
1121 static fsdp_error_t | |
1122 fsdp_repeat_time_to_uint (const char *time, unsigned long int *seconds) | |
1123 { | |
1124 const unsigned long SECONDS_PER_DAY = 86400; | |
1125 const unsigned long SECONDS_PER_HOUR = 3600; | |
1126 const unsigned long SECONDS_PER_MINUTE = 60; | |
1127 char c; | |
1128 unsigned long int wuint; | |
1129 | |
1130 if (sscanf (time, "%lu%c", &wuint, &c) == 2) | |
1131 { | |
1132 /* time with unit specification character */ | |
1133 switch (c) | |
1134 { | |
1135 case 'd': | |
1136 *seconds = wuint * SECONDS_PER_DAY; | |
1137 break; | |
1138 case 'h': | |
1139 *seconds = wuint * SECONDS_PER_HOUR; | |
1140 break; | |
1141 case 'm': | |
1142 *seconds = wuint * SECONDS_PER_MINUTE; | |
1143 break; | |
1144 case 's': | |
1145 *seconds = wuint; | |
1146 break; | |
1147 default: | |
1148 return FSDPE_INVALID_REPEAT; | |
1149 break; | |
1150 } | |
1151 } | |
1152 else if (sscanf (time, "%lu", &wuint) == 1) | |
1153 { | |
1154 /* time without unit specification character */ | |
1155 *seconds = wuint; | |
1156 } | |
1157 else | |
1158 { | |
1159 return FSDPE_INVALID_REPEAT; | |
1160 } | |
1161 return FSDPE_OK; | |
1162 } | |
1163 | |
1164 unsigned int | |
1165 fsdp_get_version (const fsdp_description_t * dsc) | |
1166 { | |
1167 if (!dsc) | |
1168 return 0; | |
1169 return dsc->version; | |
1170 } | |
1171 | |
1172 const char * | |
1173 fsdp_get_owner_username (const fsdp_description_t * dsc) | |
1174 { | |
1175 if (!dsc) | |
1176 return NULL; | |
1177 return dsc->o_username; | |
1178 } | |
1179 | |
1180 const char * | |
1181 fsdp_get_session_id (const fsdp_description_t * dsc) | |
1182 { | |
1183 if (!dsc) | |
1184 return NULL; | |
1185 return dsc->o_session_id; | |
1186 } | |
1187 | |
1188 const char * | |
1189 fsdp_get_announcement_version (const fsdp_description_t * dsc) | |
1190 { | |
1191 if (!dsc) | |
1192 return NULL; | |
1193 return dsc->o_announcement_version; | |
1194 } | |
1195 | |
1196 fsdp_network_type_t | |
1197 fsdp_get_owner_network_type (const fsdp_description_t * dsc) | |
1198 { | |
1199 if (!dsc) | |
1200 return FSDP_NETWORK_TYPE_UNDEFINED; | |
1201 return dsc->o_network_type; | |
1202 } | |
1203 | |
1204 fsdp_address_type_t | |
1205 fsdp_get_owner_address_type (const fsdp_description_t * dsc) | |
1206 { | |
1207 if (!dsc) | |
1208 return FSDP_ADDRESS_TYPE_UNDEFINED; | |
1209 return dsc->o_address_type; | |
1210 } | |
1211 | |
1212 const char * | |
1213 fsdp_get_owner_address (const fsdp_description_t * dsc) | |
1214 { | |
1215 if (!dsc) | |
1216 return NULL; | |
1217 return dsc->o_address; | |
1218 } | |
1219 | |
1220 const char * | |
1221 fsdp_get_name (const fsdp_description_t * dsc) | |
1222 { | |
1223 if (!dsc) | |
1224 return NULL; | |
1225 return dsc->s_name; | |
1226 } | |
1227 | |
1228 const char * | |
1229 fsdp_get_information (const fsdp_description_t * dsc) | |
1230 { | |
1231 if (!dsc) | |
1232 return NULL; | |
1233 return dsc->i_information; | |
1234 } | |
1235 | |
1236 const char * | |
1237 fsdp_get_uri (const fsdp_description_t * dsc) | |
1238 { | |
1239 if (!dsc) | |
1240 return NULL; | |
1241 return dsc->u_uri; | |
1242 } | |
1243 | |
1244 unsigned int | |
1245 fsdp_get_emails_count (const fsdp_description_t * dsc) | |
1246 { | |
1247 if (!dsc) | |
1248 return 0; | |
1249 return dsc->emails_count; | |
1250 } | |
1251 | |
1252 const char * | |
1253 fsdp_get_email (const fsdp_description_t * dsc, unsigned int index) | |
1254 { | |
1255 if ((!dsc) || (index >= dsc->emails_count)) | |
1256 return NULL; | |
1257 return dsc->emails[index]; | |
1258 } | |
1259 | |
1260 unsigned int | |
1261 fsdp_get_phones_count (const fsdp_description_t * dsc) | |
1262 { | |
1263 if (!dsc) | |
1264 return 0; | |
1265 return dsc->phones_count; | |
1266 } | |
1267 | |
1268 const char * | |
1269 fsdp_get_phone (const fsdp_description_t * dsc, unsigned int index) | |
1270 { | |
1271 if ((!dsc) || (index >= dsc->phones_count)) | |
1272 return NULL; | |
1273 return dsc->phones[index]; | |
1274 } | |
1275 | |
1276 fsdp_network_type_t | |
1277 fsdp_get_global_conn_network_type (const fsdp_description_t * dsc) | |
1278 { | |
1279 if (!dsc) | |
1280 return FSDP_NETWORK_TYPE_UNDEFINED; | |
1281 return dsc->c_network_type; | |
1282 } | |
1283 | |
1284 fsdp_address_type_t | |
1285 fsdp_get_global_conn_address_type (const fsdp_description_t * dsc) | |
1286 { | |
1287 if (!dsc) | |
1288 return FSDP_ADDRESS_TYPE_UNDEFINED; | |
1289 return dsc->c_address_type; | |
1290 } | |
1291 | |
1292 const char * | |
1293 fsdp_get_global_conn_address (const fsdp_description_t * dsc) | |
1294 { | |
1295 if (!dsc) | |
1296 return NULL; | |
1297 return dsc->c_address.address; | |
1298 } | |
1299 | |
1300 unsigned int | |
1301 fsdp_get_global_conn_address_ttl (const fsdp_description_t * dsc) | |
1302 { | |
1303 if (!dsc) | |
1304 return 0; | |
1305 return dsc->c_address.address_ttl; | |
1306 } | |
1307 | |
1308 unsigned int | |
1309 fsdp_get_global_conn_address_count (const fsdp_description_t * dsc) | |
1310 { | |
1311 if (!dsc) | |
1312 return 0; | |
1313 return dsc->c_address.address_count; | |
1314 } | |
1315 | |
1316 unsigned int | |
1317 fsdp_get_bw_modifier_count (const fsdp_description_t * dsc) | |
1318 { | |
1319 if (!dsc) | |
1320 return 0; | |
1321 return dsc->bw_modifiers_count; | |
1322 } | |
1323 | |
1324 fsdp_bw_modifier_type_t | |
1325 fsdp_get_bw_modifier_type (const fsdp_description_t * dsc, unsigned int index) | |
1326 { | |
1327 if ((!dsc) || (index >= dsc->bw_modifiers_count)) | |
1328 return FSDP_BW_MOD_TYPE_UNDEFINED; | |
1329 return dsc->bw_modifiers[index].b_mod_type; | |
1330 } | |
1331 | |
1332 const char * | |
1333 fsdp_get_bw_modifier_type_unknown (const fsdp_description_t * dsc, | |
1334 unsigned int index) | |
1335 { | |
1336 if ((!dsc) || (index >= dsc->bw_modifiers_count) || | |
1337 (dsc->bw_modifiers[index].b_mod_type != FSDP_BW_MOD_TYPE_UNKNOWN)) | |
1338 return NULL; | |
1339 return dsc->bw_modifiers[index].b_unknown_bw_modt; | |
1340 } | |
1341 | |
1342 unsigned long int | |
1343 fsdp_get_bw_value (const fsdp_description_t * dsc, unsigned int index) | |
1344 { | |
1345 if ((!dsc) || (index >= dsc->bw_modifiers_count)) | |
1346 return 0; | |
1347 return dsc->bw_modifiers[index].b_value; | |
1348 } | |
1349 | |
1350 time_t | |
1351 fsdp_get_period_start (const fsdp_description_t * dsc, unsigned int index) | |
1352 { | |
1353 if ((!dsc) || (index >= dsc->time_periods_count)) | |
1354 return 0; | |
1355 return dsc->time_periods[index]->start; | |
1356 } | |
1357 | |
1358 time_t | |
1359 fsdp_get_period_stop (const fsdp_description_t * dsc, unsigned int index) | |
1360 { | |
1361 if ((!dsc) || (index >= dsc->time_periods_count)) | |
1362 return 0; | |
1363 return dsc->time_periods[index]->stop; | |
1364 } | |
1365 | |
1366 unsigned int | |
1367 fsdp_get_period_repeats_count (const fsdp_description_t * dsc, | |
1368 unsigned int index) | |
1369 { | |
1370 if ((!dsc) || (index >= dsc->time_periods_count)) | |
1371 return 0; | |
1372 return dsc->time_periods[index]->repeats_count; | |
1373 } | |
1374 | |
1375 unsigned long int | |
1376 fsdp_get_period_repeat_interval (const fsdp_description_t * dsc, | |
1377 unsigned int index, unsigned int rindex) | |
1378 { | |
1379 if ((!dsc) || (index >= dsc->time_periods_count)) | |
1380 return 0; | |
1381 return dsc->time_periods[index]->repeats[rindex]->interval; | |
1382 } | |
1383 | |
1384 unsigned long int | |
1385 fsdp_get_period_repeat_duration (const fsdp_description_t * dsc, | |
1386 unsigned int index, unsigned int rindex) | |
1387 { | |
1388 if ((!dsc) || (index >= dsc->time_periods_count)) | |
1389 return 0; | |
1390 return dsc->time_periods[index]->repeats[rindex]->duration; | |
1391 } | |
1392 | |
1393 const unsigned long int * | |
1394 fsdp_get_period_repeat_offsets (const fsdp_description_t * dsc, | |
1395 unsigned int index, unsigned int rindex) | |
1396 { | |
1397 if ((!dsc) || (index >= dsc->time_periods_count)) | |
1398 return NULL; | |
1399 return dsc->time_periods[index]->repeats[rindex]->offsets; | |
1400 } | |
1401 | |
1402 const char * | |
1403 fsdp_get_timezone_adj (const fsdp_description_t * dsc) | |
1404 { | |
1405 if (!dsc) | |
1406 return NULL; | |
1407 return dsc->timezone_adj; | |
1408 } | |
1409 | |
1410 unsigned int | |
1411 fsdp_get_unidentified_attribute_count (const fsdp_description_t * dsc) | |
1412 { | |
1413 if (!dsc) | |
1414 return 0; | |
1415 return dsc->unidentified_attributes_count; | |
1416 } | |
1417 | |
1418 const char * | |
1419 fsdp_get_unidentified_attribute (const fsdp_description_t * dsc, | |
1420 unsigned int index) | |
1421 { | |
1422 if (!dsc || (index < dsc->unidentified_attributes_count)) | |
1423 return NULL; | |
1424 return dsc->unidentified_attributes[index]; | |
1425 } | |
1426 | |
1427 fsdp_encryption_method_t | |
1428 fsdp_get_encryption_method (const fsdp_description_t * dsc) | |
1429 { | |
1430 if (!dsc) | |
1431 return FSDP_ENCRYPTION_METHOD_UNDEFINED; | |
1432 return dsc->k_encryption_method; | |
1433 } | |
1434 | |
1435 const char * | |
1436 fsdp_get_encryption_content (const fsdp_description_t * dsc) | |
1437 { | |
1438 if (!dsc || (dsc->k_encryption_method == FSDP_ENCRYPTION_METHOD_UNDEFINED)) | |
1439 return NULL; | |
1440 return dsc->k_encryption_content; | |
1441 } | |
1442 | |
1443 unsigned int | |
1444 fsdp_get_rtpmap_count (const fsdp_description_t * dsc) | |
1445 { | |
1446 if (!dsc) | |
1447 return 0; | |
1448 return dsc->a_rtpmaps_count; | |
1449 } | |
1450 | |
1451 const char * | |
1452 fsdp_get_rtpmap_payload_type (const fsdp_description_t * dsc, | |
1453 unsigned int index) | |
1454 { | |
1455 if ((!dsc) || (index >= dsc->a_rtpmaps_count)) | |
1456 return NULL; | |
1457 return dsc->a_rtpmaps[index]->pt; | |
1458 } | |
1459 | |
1460 const char * | |
1461 fsdp_get_rtpmap_encoding_name (const fsdp_description_t * dsc, | |
1462 unsigned int index) | |
1463 { | |
1464 if ((!dsc) || (index >= dsc->a_rtpmaps_count)) | |
1465 return NULL; | |
1466 return dsc->a_rtpmaps[index]->encoding_name; | |
1467 } | |
1468 | |
1469 unsigned int | |
1470 fsdp_get_rtpmap_clock_rate (const fsdp_description_t * dsc, | |
1471 unsigned int index) | |
1472 { | |
1473 if ((!dsc) || (index >= dsc->a_rtpmaps_count)) | |
1474 return 0; | |
1475 return dsc->a_rtpmaps[index]->clock_rate; | |
1476 } | |
1477 | |
1478 const char * | |
1479 fsdp_get_rtpmap_encoding_parameters (const fsdp_description_t * dsc, | |
1480 unsigned int index) | |
1481 { | |
1482 if ((!dsc) || (index >= dsc->a_rtpmaps_count)) | |
1483 return NULL; | |
1484 return dsc->a_rtpmaps[index]->parameters; | |
1485 } | |
1486 | |
1487 const char * | |
1488 fsdp_get_str_att (const fsdp_description_t * dsc, fsdp_session_str_att_t att) | |
1489 { | |
1490 /*TODO: change these individual attributes with a table, thus | |
1491 avoiding this slow switch */ | |
1492 char *result; | |
1493 | |
1494 if (!dsc) | |
1495 return NULL; | |
1496 | |
1497 switch (att) | |
1498 { | |
1499 case FSDP_SESSION_STR_ATT_CATEGORY: | |
1500 result = dsc->a_category; | |
1501 break; | |
1502 case FSDP_SESSION_STR_ATT_KEYWORDS: | |
1503 result = dsc->a_keywords; | |
1504 break; | |
1505 case FSDP_SESSION_STR_ATT_TOOL: | |
1506 result = dsc->a_tool; | |
1507 break; | |
1508 case FSDP_SESSION_STR_ATT_CHARSET: | |
1509 result = dsc->a_charset; | |
1510 break; | |
1511 default: | |
1512 result = NULL; | |
1513 } | |
1514 return result; | |
1515 } | |
1516 | |
1517 unsigned int | |
1518 fsdp_get_sdplang_count (const fsdp_description_t * dsc) | |
1519 { | |
1520 if (!dsc) | |
1521 return 0; | |
1522 return dsc->a_sdplangs_count; | |
1523 } | |
1524 | |
1525 const char * | |
1526 fsdp_get_sdplang (const fsdp_description_t * dsc, unsigned int index) | |
1527 { | |
1528 if ((!dsc) || (index >= dsc->a_sdplangs_count)) | |
1529 return NULL; | |
1530 return dsc->a_sdplangs[index]; | |
1531 } | |
1532 | |
1533 unsigned int | |
1534 fsdp_get_lang_count (const fsdp_description_t * dsc) | |
1535 { | |
1536 if (!dsc) | |
1537 return 0; | |
1538 return dsc->a_langs_count; | |
1539 } | |
1540 | |
1541 const char * | |
1542 fsdp_get_lang (const fsdp_description_t * dsc, unsigned int index) | |
1543 { | |
1544 if ((!dsc) || (index >= dsc->a_langs_count)) | |
1545 return NULL; | |
1546 return dsc->a_langs[index]; | |
1547 } | |
1548 | |
1549 unsigned int | |
1550 fsdp_get_control_count (const fsdp_description_t * dsc) | |
1551 { | |
1552 if (!dsc) | |
1553 return 0; | |
1554 return dsc->a_controls_count; | |
1555 } | |
1556 | |
1557 const char * | |
1558 fsdp_get_control (const fsdp_description_t * dsc, unsigned int index) | |
1559 { | |
1560 if ((!dsc) || (index >= dsc->a_controls_count)) | |
1561 return NULL; | |
1562 return dsc->a_controls[index]; | |
1563 } | |
1564 | |
1565 const char * | |
1566 fsdp_get_range (const fsdp_description_t * dsc) | |
1567 { | |
1568 return dsc->a_range; | |
1569 } | |
1570 | |
1571 fsdp_sendrecv_mode_t | |
1572 fsdp_get_sendrecv_mode (const fsdp_description_t * dsc) | |
1573 { | |
1574 if (!dsc) | |
1575 return FSDP_SENDRECV_UNDEFINED; | |
1576 return dsc->a_sendrecv_mode; | |
1577 } | |
1578 | |
1579 fsdp_session_type_t | |
1580 fsdp_get_session_type (const fsdp_description_t * dsc) | |
1581 { | |
1582 if (!dsc) | |
1583 return FSDP_SESSION_TYPE_UNDEFINED; | |
1584 return dsc->a_type; | |
1585 } | |
1586 | |
1587 unsigned int | |
1588 fsdp_get_media_count (const fsdp_description_t * dsc) | |
1589 { | |
1590 if (!dsc) | |
1591 return 0; | |
1592 return dsc->media_announcements_count; | |
1593 } | |
1594 | |
1595 const fsdp_media_description_t * | |
1596 fsdp_get_media (const fsdp_description_t * dsc, unsigned int index) | |
1597 { | |
1598 if ((index >= dsc->media_announcements_count)) | |
1599 return NULL; | |
1600 return dsc->media_announcements[index]; | |
1601 } | |
1602 | |
1603 fsdp_media_t | |
1604 fsdp_get_media_type (const fsdp_media_description_t * dsc) | |
1605 { | |
1606 if (!dsc) | |
1607 return FSDP_MEDIA_UNDEFINED; | |
1608 return dsc->media_type; | |
1609 } | |
1610 | |
1611 unsigned int | |
1612 fsdp_get_media_port (const fsdp_media_description_t * dsc) | |
1613 { | |
1614 if (!dsc) | |
1615 return 0; | |
1616 return dsc->port; | |
1617 } | |
1618 | |
1619 unsigned int | |
1620 fsdp_get_media_port_count (const fsdp_media_description_t * dsc) | |
1621 { | |
1622 if (!dsc) | |
1623 return 0; | |
1624 return dsc->port_count; | |
1625 } | |
1626 | |
1627 fsdp_transport_protocol_t | |
1628 fsdp_get_media_transport_protocol (const fsdp_media_description_t * dsc) | |
1629 { | |
1630 if (!dsc) | |
1631 return FSDP_TP_UNDEFINED; | |
1632 return dsc->transport; | |
1633 } | |
1634 | |
1635 unsigned int | |
1636 fsdp_get_media_formats_count (const fsdp_media_description_t * dsc) | |
1637 { | |
1638 if (!dsc) | |
1639 return 0; | |
1640 return dsc->formats_count; | |
1641 } | |
1642 | |
1643 const char * | |
1644 fsdp_get_media_format (const fsdp_media_description_t * dsc, | |
1645 unsigned int index) | |
1646 { | |
1647 if (!dsc && (index < dsc->formats_count)) | |
1648 return NULL; | |
1649 return dsc->formats[index]; | |
1650 } | |
1651 | |
1652 const char * | |
1653 fsdp_get_media_title (const fsdp_media_description_t * dsc) | |
1654 { | |
1655 if (!dsc) | |
1656 return NULL; | |
1657 return dsc->i_title; | |
1658 } | |
1659 | |
1660 fsdp_network_type_t | |
1661 fsdp_get_media_network_type (const fsdp_media_description_t * dsc) | |
1662 { | |
1663 if (!dsc) | |
1664 return FSDP_NETWORK_TYPE_UNDEFINED; | |
1665 return dsc->c_network_type; | |
1666 } | |
1667 | |
1668 fsdp_address_type_t | |
1669 fsdp_get_media_address_type (const fsdp_media_description_t * dsc) | |
1670 { | |
1671 if (!dsc) | |
1672 return FSDP_ADDRESS_TYPE_UNDEFINED; | |
1673 return dsc->c_address_type; | |
1674 } | |
1675 | |
1676 const char * | |
1677 fsdp_get_media_address (const fsdp_media_description_t * dsc) | |
1678 { | |
1679 if (!dsc) | |
1680 return NULL; | |
1681 return dsc->c_address.address; | |
1682 } | |
1683 | |
1684 unsigned int | |
1685 fsdp_get_media_address_ttl (const fsdp_media_description_t * mdsc) | |
1686 { | |
1687 if (!mdsc) | |
1688 return 0; | |
1689 return mdsc->c_address.address_ttl; | |
1690 } | |
1691 | |
1692 unsigned int | |
1693 fsdp_get_media_address_count (const fsdp_media_description_t * mdsc) | |
1694 { | |
1695 if (!mdsc) | |
1696 return 0; | |
1697 return mdsc->c_address.address_count; | |
1698 } | |
1699 | |
1700 fsdp_bw_modifier_type_t | |
1701 fsdp_get_media_bw_modifier_type (const fsdp_media_description_t * dsc, | |
1702 unsigned int index) | |
1703 { | |
1704 if (!dsc || (index >= dsc->bw_modifiers_count)) | |
1705 return FSDP_BW_MOD_TYPE_UNDEFINED; | |
1706 return dsc->bw_modifiers[index].b_mod_type; | |
1707 } | |
1708 | |
1709 const char * | |
1710 fsdp_get_media_bw_modifier_type_unknown (const fsdp_media_description_t * dsc, | |
1711 unsigned int index) | |
1712 { | |
1713 if (!dsc || (index >= dsc->bw_modifiers_count) || | |
1714 (FSDP_BW_MOD_TYPE_UNKNOWN != dsc->bw_modifiers[index].b_mod_type)) | |
1715 return NULL; | |
1716 return dsc->bw_modifiers[index].b_unknown_bw_modt; | |
1717 } | |
1718 | |
1719 unsigned long int | |
1720 fsdp_get_media_bw_value (const fsdp_media_description_t * dsc, | |
1721 unsigned int index) | |
1722 { | |
1723 if (!dsc || (index >= dsc->bw_modifiers_count)) | |
1724 return 0; | |
1725 return dsc->bw_modifiers[index].b_value; | |
1726 } | |
1727 | |
1728 fsdp_encryption_method_t | |
1729 fsdp_get_media_encryption_method (const fsdp_media_description_t * dsc) | |
1730 { | |
1731 if (!dsc) | |
1732 return FSDP_ENCRYPTION_METHOD_UNDEFINED; | |
1733 return dsc->k_encryption_method; | |
1734 } | |
1735 | |
1736 const char * | |
1737 fsdp_get_media_encryption_content (const fsdp_media_description_t * dsc) | |
1738 { | |
1739 if (!dsc) | |
1740 return NULL; | |
1741 return dsc->k_encryption_content; | |
1742 } | |
1743 | |
1744 unsigned int | |
1745 fsdp_get_media_ptime (const fsdp_media_description_t * dsc) | |
1746 { | |
1747 if (!dsc) | |
1748 return 0; | |
1749 return dsc->a_ptime; | |
1750 } | |
1751 | |
1752 unsigned int | |
1753 fsdp_get_media_maxptime (const fsdp_media_description_t * dsc) | |
1754 { | |
1755 if (!dsc) | |
1756 return 0; | |
1757 return dsc->a_maxptime; | |
1758 } | |
1759 | |
1760 unsigned int | |
1761 fsdp_get_media_rtpmap_count (const fsdp_media_description_t * mdsc) | |
1762 { | |
1763 if (!mdsc) | |
1764 return 0; | |
1765 return mdsc->a_rtpmaps_count; | |
1766 } | |
1767 | |
1768 const char * | |
1769 fsdp_get_media_rtpmap_payload_type (const fsdp_media_description_t * mdsc, | |
1770 unsigned int index) | |
1771 { | |
1772 if (!mdsc || (index >= mdsc->a_rtpmaps_count)) | |
1773 return NULL; | |
1774 return mdsc->a_rtpmaps[index]->pt; | |
1775 } | |
1776 | |
1777 const char * | |
1778 fsdp_get_media_rtpmap_encoding_name (const fsdp_media_description_t * mdsc, | |
1779 unsigned int index) | |
1780 { | |
1781 if (!mdsc || (index >= mdsc->a_rtpmaps_count)) | |
1782 return NULL; | |
1783 return mdsc->a_rtpmaps[index]->encoding_name; | |
1784 } | |
1785 | |
1786 unsigned int | |
1787 fsdp_get_media_rtpmap_clock_rate (const fsdp_media_description_t * mdsc, | |
1788 unsigned int index) | |
1789 { | |
1790 if (!mdsc || (index >= mdsc->a_rtpmaps_count)) | |
1791 return 0; | |
1792 return mdsc->a_rtpmaps[index]->clock_rate; | |
1793 } | |
1794 | |
1795 const char * | |
1796 fsdp_get_media_rtpmap_encoding_parameters (const fsdp_description_t * mdsc, | |
1797 unsigned int index) | |
1798 { | |
1799 if (!mdsc || (index >= mdsc->a_rtpmaps_count)) | |
1800 return NULL; | |
1801 return mdsc->a_rtpmaps[index]->parameters; | |
1802 } | |
1803 | |
1804 unsigned int | |
1805 fsdp_get_media_sdplang_count (const fsdp_media_description_t * mdsc) | |
1806 { | |
1807 if (!mdsc) | |
1808 return 0; | |
1809 return mdsc->a_sdplangs_count; | |
1810 } | |
1811 | |
1812 const char * | |
1813 fsdp_get_media_sdplang (const fsdp_media_description_t * mdsc, | |
1814 unsigned int index) | |
1815 { | |
1816 if (!mdsc || (index >= mdsc->a_sdplangs_count)) | |
1817 return NULL; | |
1818 return mdsc->a_sdplangs[index]; | |
1819 } | |
1820 | |
1821 unsigned int | |
1822 fsdp_get_media_lang_count (const fsdp_media_description_t * mdsc) | |
1823 { | |
1824 if (!mdsc) | |
1825 return 0; | |
1826 return mdsc->a_langs_count; | |
1827 } | |
1828 | |
1829 const char * | |
1830 fsdp_get_media_lang (const fsdp_media_description_t * mdsc, | |
1831 unsigned int index) | |
1832 { | |
1833 if (!mdsc || (index >= mdsc->a_langs_count)) | |
1834 return NULL; | |
1835 return mdsc->a_langs[index]; | |
1836 } | |
1837 | |
1838 unsigned int | |
1839 fsdp_get_media_control_count (const fsdp_media_description_t * mdsc) | |
1840 { | |
1841 if (!mdsc) | |
1842 return 0; | |
1843 return mdsc->a_controls_count; | |
1844 } | |
1845 | |
1846 char * | |
1847 fsdp_get_media_control (const fsdp_media_description_t * mdsc, | |
1848 unsigned int index) | |
1849 { | |
1850 if (!mdsc || (index >= mdsc->a_controls_count)) | |
1851 return NULL; | |
1852 return mdsc->a_controls[index]; | |
1853 } | |
1854 | |
1855 char * | |
1856 fsdp_get_media_range (const fsdp_media_description_t * mdsc) | |
1857 { | |
1858 return mdsc->a_range; | |
1859 } | |
1860 | |
1861 unsigned int | |
1862 fsdp_get_media_fmtp_count (const fsdp_media_description_t * mdsc) | |
1863 { | |
1864 if (!mdsc) | |
1865 return 0; | |
1866 return mdsc->a_fmtps_count; | |
1867 } | |
1868 | |
1869 const char * | |
1870 fsdp_get_media_fmtp (const fsdp_media_description_t * mdsc, | |
1871 unsigned int index) | |
1872 { | |
1873 if (!mdsc || (index >= mdsc->a_fmtps_count)) | |
1874 return NULL; | |
1875 return mdsc->a_fmtps[index]; | |
1876 } | |
1877 | |
1878 fsdp_orient_t | |
1879 fsdp_get_media_orient (const fsdp_media_description_t * dsc) | |
1880 { | |
1881 if (!dsc) | |
1882 return FSDP_ORIENT_UNDEFINED; | |
1883 return dsc->a_orient; | |
1884 } | |
1885 | |
1886 fsdp_sendrecv_mode_t | |
1887 fsdp_get_media_sendrecv (const fsdp_media_description_t * dsc) | |
1888 { | |
1889 if (!dsc) | |
1890 return FSDP_SENDRECV_UNDEFINED; | |
1891 return dsc->a_sendrecv_mode; | |
1892 } | |
1893 | |
1894 float | |
1895 fsdp_get_media_framerate (const fsdp_media_description_t * dsc) | |
1896 { | |
1897 if (!dsc) | |
1898 return 0; | |
1899 return dsc->a_framerate; | |
1900 } | |
1901 | |
1902 unsigned int | |
1903 fsdp_get_media_quality (const fsdp_media_description_t * dsc) | |
1904 { | |
1905 if (!dsc) | |
1906 return 0; | |
1907 return dsc->a_quality; | |
1908 } | |
1909 | |
1910 unsigned int | |
1911 fsdp_get_media_rtcp_port (const fsdp_media_description_t * dsc) | |
1912 { | |
1913 if (!dsc) | |
1914 return 0; | |
1915 return dsc->a_rtcp_port; | |
1916 } | |
1917 | |
1918 fsdp_network_type_t | |
1919 fsdp_get_media_rtcp_network_type (const fsdp_media_description_t * dsc) | |
1920 { | |
1921 if (!dsc) | |
1922 return FSDP_NETWORK_TYPE_UNDEFINED; | |
1923 return dsc->a_rtcp_network_type; | |
1924 } | |
1925 | |
1926 fsdp_address_type_t | |
1927 fsdp_get_media_rtcp_address_type (const fsdp_media_description_t * dsc) | |
1928 { | |
1929 if (!dsc) | |
1930 return FSDP_ADDRESS_TYPE_UNDEFINED; | |
1931 return dsc->a_rtcp_address_type; | |
1932 } | |
1933 | |
1934 const char * | |
1935 fsdp_get_media_rtcp_address (const fsdp_media_description_t * dsc) | |
1936 { | |
1937 if (!dsc) | |
1938 return NULL; | |
1939 return dsc->a_rtcp_address; | |
1940 } | |
1941 | |
1942 unsigned int | |
1943 fsdp_get_media_unidentified_attribute_count (const fsdp_media_description_t | |
1944 * mdsc) | |
1945 { | |
1946 if (!mdsc) | |
1947 return 0; | |
1948 return mdsc->unidentified_attributes_count; | |
1949 } | |
1950 | |
1951 const char * | |
1952 fsdp_get_media_unidentified_attribute (const fsdp_media_description_t * mdsc, | |
1953 unsigned int index) | |
1954 { | |
1955 if (!mdsc || (index < mdsc->unidentified_attributes_count)) | |
1956 return NULL; | |
1957 return mdsc->unidentified_attributes[index]; | |
1958 } |