Line data Source code
1 : /* This Source Code Form is subject to the terms of the Mozilla Public
2 : * License, v. 2.0. If a copy of the MPL was not distributed with this
3 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 :
5 : #include "sdp_os_defs.h"
6 : #include "sdp.h"
7 : #include "sdp_private.h"
8 :
9 : #include "CSFLog.h"
10 :
11 : static const char* logTag = "sdp_main";
12 :
13 : /* Note: These *must* be in the same order as the enum types. */
14 : const sdp_tokenarray_t sdp_token[SDP_MAX_TOKENS] =
15 : {
16 : {"v=", sdp_parse_version, sdp_build_version },
17 : {"o=", sdp_parse_owner, sdp_build_owner },
18 : {"s=", sdp_parse_sessname, sdp_build_sessname },
19 : {"i=", sdp_parse_sessinfo, sdp_build_sessinfo },
20 : {"u=", sdp_parse_uri, sdp_build_uri },
21 : {"e=", sdp_parse_email, sdp_build_email },
22 : {"p=", sdp_parse_phonenum, sdp_build_phonenum },
23 : {"c=", sdp_parse_connection, sdp_build_connection },
24 : {"b=", sdp_parse_bandwidth, sdp_build_bandwidth },
25 : {"t=", sdp_parse_timespec, sdp_build_timespec },
26 : {"r=", sdp_parse_repeat_time, sdp_build_repeat_time },
27 : {"z=", sdp_parse_timezone_adj, sdp_build_timezone_adj },
28 : {"k=", sdp_parse_encryption, sdp_build_encryption },
29 : {"a=", sdp_parse_attribute, sdp_build_attribute },
30 : {"m=", sdp_parse_media, sdp_build_media }
31 : };
32 :
33 :
34 : /* Note: These *must* be in the same order as the enum types. */
35 : const sdp_attrarray_t sdp_attr[SDP_MAX_ATTR_TYPES] =
36 : {
37 : {"bearer", sizeof("bearer"),
38 : sdp_parse_attr_simple_string, sdp_build_attr_simple_string },
39 : {"called", sizeof("called"),
40 : sdp_parse_attr_simple_string, sdp_build_attr_simple_string },
41 : {"connection_type", sizeof("connection_type"),
42 : sdp_parse_attr_simple_string, sdp_build_attr_simple_string },
43 : {"dialed", sizeof("dialed"),
44 : sdp_parse_attr_simple_string, sdp_build_attr_simple_string },
45 : {"dialing", sizeof("dialing"),
46 : sdp_parse_attr_simple_string, sdp_build_attr_simple_string },
47 : {"direction", sizeof("direction"),
48 : sdp_parse_attr_comediadir, sdp_build_attr_comediadir },
49 : {"eecid", sizeof("eecid"),
50 : sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
51 : {"fmtp", sizeof("fmtp"),
52 : sdp_parse_attr_fmtp, sdp_build_attr_fmtp },
53 : {"sctpmap", sizeof("sctpmap"),
54 : sdp_parse_attr_sctpmap, sdp_build_attr_sctpmap },
55 : {"framing", sizeof("framing"),
56 : sdp_parse_attr_simple_string, sdp_build_attr_simple_string },
57 : {"inactive", sizeof("inactive"),
58 : sdp_parse_attr_direction, sdp_build_attr_direction },
59 : {"ptime", sizeof("ptime"),
60 : sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
61 : {"qos", sizeof("qos"),
62 : sdp_parse_attr_qos, sdp_build_attr_qos },
63 : {"curr", sizeof("curr"),
64 : sdp_parse_attr_curr, sdp_build_attr_curr },
65 : {"des", sizeof("des"),
66 : sdp_parse_attr_des, sdp_build_attr_des},
67 : {"conf", sizeof("conf"),
68 : sdp_parse_attr_conf, sdp_build_attr_conf},
69 : {"recvonly", sizeof("recvonly"),
70 : sdp_parse_attr_direction, sdp_build_attr_direction },
71 : {"rtpmap", sizeof("rtpmap"),
72 : sdp_parse_attr_transport_map, sdp_build_attr_transport_map },
73 : {"secure", sizeof("secure"),
74 : sdp_parse_attr_qos, sdp_build_attr_qos },
75 : {"sendonly", sizeof("sendonly"),
76 : sdp_parse_attr_direction, sdp_build_attr_direction },
77 : {"sendrecv", sizeof("sendrecv"),
78 : sdp_parse_attr_direction, sdp_build_attr_direction },
79 : {"subnet", sizeof("subnet"),
80 : sdp_parse_attr_subnet, sdp_build_attr_subnet },
81 : {"T38FaxVersion", sizeof("T38FaxVersion"),
82 : sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
83 : {"T38MaxBitRate", sizeof("T38MaxBitRate"),
84 : sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
85 : {"T38FaxFillBitRemoval", sizeof("T38FaxFillBitRemoval"),
86 : sdp_parse_attr_simple_bool, sdp_build_attr_simple_bool },
87 : {"T38FaxTranscodingMMR", sizeof("T38FaxTranscodingMMR"),
88 : sdp_parse_attr_simple_bool, sdp_build_attr_simple_bool },
89 : {"T38FaxTranscodingJBIG", sizeof("T38FaxTranscodingJBIG"),
90 : sdp_parse_attr_simple_bool, sdp_build_attr_simple_bool },
91 : {"T38FaxRateManagement", sizeof("T38FaxRateManagement"),
92 : sdp_parse_attr_t38_ratemgmt, sdp_build_attr_t38_ratemgmt },
93 : {"T38FaxMaxBuffer", sizeof("T38FaxMaxBuffer"),
94 : sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
95 : {"T38FaxMaxDatagram", sizeof("T38FaxMaxDatagram"),
96 : sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
97 : {"T38FaxUdpEC", sizeof("T38FaxUdpEC"),
98 : sdp_parse_attr_t38_udpec, sdp_build_attr_t38_udpec },
99 : {"X-cap", sizeof("X-cap"),
100 : sdp_parse_attr_cap, sdp_build_attr_cap },
101 : {"X-cpar", sizeof("X-cpar"),
102 : sdp_parse_attr_cpar, sdp_build_attr_cpar },
103 : {"X-pc-codec", sizeof("X-pc-codec"),
104 : sdp_parse_attr_pc_codec, sdp_build_attr_pc_codec },
105 : {"X-pc-qos", sizeof("X-pc-qos"),
106 : sdp_parse_attr_qos, sdp_build_attr_qos },
107 : {"X-qos", sizeof("X-qos"),
108 : sdp_parse_attr_qos, sdp_build_attr_qos },
109 : {"X-sqn", sizeof("X-sqn"),
110 : sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
111 : {"TMRGwXid", sizeof("TMRGwXid"),
112 : sdp_parse_attr_simple_bool, sdp_build_attr_simple_bool },
113 : {"TC1PayloadBytes", sizeof("TC1PayloadBytes"),
114 : sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
115 : {"TC1WindowSize", sizeof("TC1WindowSize"),
116 : sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
117 : {"TC2PayloadBytes", sizeof("TC2PayloadBytes"),
118 : sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
119 : {"TC2WindowSize", sizeof("TC2WindowSize"),
120 : sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
121 : {"rtcp", sizeof("rtcp"),
122 : sdp_parse_attr_rtcp, sdp_build_attr_rtcp },
123 : {"rtr", sizeof("rtr"),
124 : sdp_parse_attr_rtr, sdp_build_attr_rtr},
125 : {"silenceSupp", sizeof("silenceSupp"),
126 : sdp_parse_attr_silencesupp, sdp_build_attr_silencesupp },
127 : {"X-crypto", sizeof("X-crypto"),
128 : sdp_parse_attr_srtpcontext, sdp_build_attr_srtpcontext },
129 : {"mptime", sizeof("mptime"),
130 : sdp_parse_attr_mptime, sdp_build_attr_mptime },
131 : {"X-sidin", sizeof("X-sidin"),
132 : sdp_parse_attr_x_sidin, sdp_build_attr_x_sidin },
133 : {"X-sidout", sizeof("X-sidout"),
134 : sdp_parse_attr_x_sidout, sdp_build_attr_x_sidout },
135 : {"X-confid", sizeof("X-confid"),
136 : sdp_parse_attr_x_confid, sdp_build_attr_x_confid },
137 : {"group", sizeof("group"),
138 : sdp_parse_attr_group, sdp_build_attr_group },
139 : {"mid", sizeof("mid"),
140 : sdp_parse_attr_simple_string, sdp_build_attr_simple_string },
141 : {"source-filter", sizeof("source-filter"),
142 : sdp_parse_attr_source_filter, sdp_build_source_filter},
143 : {"rtcp-unicast", sizeof("rtcp-unicast"),
144 : sdp_parse_attr_rtcp_unicast, sdp_build_attr_rtcp_unicast},
145 : {"maxprate", sizeof("maxprate"),
146 : sdp_parse_attr_maxprate, sdp_build_attr_simple_string},
147 : {"sqn", sizeof("sqn"),
148 : sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
149 : {"cdsc", sizeof("cdsc"),
150 : sdp_parse_attr_cap, sdp_build_attr_cap },
151 : {"cpar", sizeof("cpar"),
152 : sdp_parse_attr_cpar, sdp_build_attr_cpar },
153 : {"sprtmap", sizeof("sprtmap"),
154 : sdp_parse_attr_transport_map, sdp_build_attr_transport_map },
155 : {"crypto", sizeof("crypto"),
156 : sdp_parse_attr_sdescriptions, sdp_build_attr_sdescriptions },
157 : {"label", sizeof("label"),
158 : sdp_parse_attr_simple_string, sdp_build_attr_simple_string },
159 : {"framerate", sizeof("framerate"),
160 : sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
161 : {"candidate", sizeof("candidate"),
162 : sdp_parse_attr_ice_attr, sdp_build_attr_ice_attr },
163 : {"ice-ufrag", sizeof("ice-ufrag"),
164 : sdp_parse_attr_ice_attr, sdp_build_attr_ice_attr },
165 : {"ice-pwd", sizeof("ice-pwd"),
166 : sdp_parse_attr_ice_attr, sdp_build_attr_ice_attr},
167 : {"ice-lite", sizeof("ice-lite"),
168 : sdp_parse_attr_simple_flag, sdp_build_attr_simple_flag},
169 : {"rtcp-mux", sizeof("rtcp-mux"),
170 : sdp_parse_attr_simple_flag, sdp_build_attr_simple_flag},
171 : {"fingerprint", sizeof("fingerprint"),
172 : sdp_parse_attr_complete_line, sdp_build_attr_simple_string},
173 : {"maxptime", sizeof("maxptime"),
174 : sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32},
175 : {"rtcp-fb", sizeof("rtcp-fb"),
176 : sdp_parse_attr_rtcp_fb, sdp_build_attr_rtcp_fb},
177 : {"setup", sizeof("setup"),
178 : sdp_parse_attr_setup, sdp_build_attr_setup},
179 : {"connection", sizeof("connection"),
180 : sdp_parse_attr_connection, sdp_build_attr_connection},
181 : {"extmap", sizeof("extmap"),
182 : sdp_parse_attr_extmap, sdp_build_attr_extmap},
183 : {"identity", sizeof("identity"),
184 : sdp_parse_attr_long_line, sdp_build_attr_long_line},
185 : {"msid", sizeof("msid"),
186 : sdp_parse_attr_msid, sdp_build_attr_msid},
187 : {"msid-semantic", sizeof("msid-semantic"),
188 : sdp_parse_attr_msid_semantic, sdp_build_attr_msid_semantic},
189 : {"bundle-only", sizeof("bundle-only"),
190 : sdp_parse_attr_simple_flag, sdp_build_attr_simple_flag},
191 : {"end-of-candidates", sizeof("end-of-candidates"),
192 : sdp_parse_attr_simple_flag, sdp_build_attr_simple_flag},
193 : {"ice-options", sizeof("ice-options"),
194 : sdp_parse_attr_complete_line, sdp_build_attr_simple_string},
195 : {"ssrc", sizeof("ssrc"),
196 : sdp_parse_attr_ssrc, sdp_build_attr_ssrc},
197 : {"imageattr", sizeof("imageattr"),
198 : sdp_parse_attr_complete_line, sdp_build_attr_simple_string},
199 : {"simulcast", sizeof("simulcast"),
200 : sdp_parse_attr_complete_line, sdp_build_attr_simple_string},
201 : {"rid", sizeof("rid"),
202 : sdp_parse_attr_complete_line, sdp_build_attr_simple_string},
203 : {"dtls-message", sizeof("dtls-message"),
204 : sdp_parse_attr_long_line, sdp_build_attr_long_line},
205 : {"sctp-port", sizeof("sctp-port"),
206 : sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32},
207 : {"max-message-size", sizeof("max-message-size"),
208 : sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32},
209 : };
210 :
211 : /* Note: These *must* be in the same order as the enum types. */
212 : const sdp_namearray_t sdp_media[SDP_MAX_MEDIA_TYPES] =
213 : {
214 : {"audio", sizeof("audio")},
215 : {"video", sizeof("video")},
216 : {"application", sizeof("application")},
217 : {"data", sizeof("data")},
218 : {"control", sizeof("control")},
219 : {"nas/radius", sizeof("nas/radius")},
220 : {"nas/tacacs", sizeof("nas/tacacs")},
221 : {"nas/diameter", sizeof("nas/diameter")},
222 : {"nas/l2tp", sizeof("nas/l2tp")},
223 : {"nas/login", sizeof("nas/login")},
224 : {"nas/none", sizeof("nas/none")},
225 : {"image", sizeof("image")},
226 : {"text", sizeof("text")}
227 : };
228 :
229 :
230 : /* Note: These *must* be in the same order as the enum types. */
231 : const sdp_namearray_t sdp_nettype[SDP_MAX_NETWORK_TYPES] =
232 : {
233 : {"IN", sizeof("IN")},
234 : {"ATM", sizeof("ATM")},
235 : {"FR", sizeof("FR")},
236 : {"LOCAL", sizeof("LOCAL")}
237 : };
238 :
239 :
240 : /* Note: These *must* be in the same order as the enum types. */
241 : const sdp_namearray_t sdp_addrtype[SDP_MAX_ADDR_TYPES] =
242 : {
243 : {"IP4", sizeof("IP4")},
244 : {"IP6", sizeof("IP6")},
245 : {"NSAP", sizeof("NSAP")},
246 : {"EPN", sizeof("EPN")},
247 : {"E164", sizeof("E164")},
248 : {"GWID", sizeof("GWID")}
249 : };
250 :
251 :
252 : /* Note: These *must* be in the same order as the enum type. */
253 : const sdp_namearray_t sdp_transport[SDP_MAX_TRANSPORT_TYPES] =
254 : {
255 : {"RTP/AVP", sizeof("RTP/AVP")},
256 : {"udp", sizeof("udp")},
257 : {"udptl", sizeof("udptl")},
258 : {"ces10", sizeof("ces10")},
259 : {"LOCAL", sizeof("LOCAL")},
260 : {"AAL2/ITU", sizeof("AAL2/ITU")},
261 : {"AAL2/ATMF", sizeof("AAL2/ATMF")},
262 : {"AAL2/custom", sizeof("AAL2/custom")},
263 : {"AAL1/AVP", sizeof("AAL1/AVP")},
264 : {"udpsprt", sizeof("udpsprt")},
265 : {"RTP/SAVP", sizeof("RTP/SAVP")},
266 : {"tcp", sizeof("tcp")},
267 : {"RTP/SAVPF", sizeof("RTP/SAVPF")},
268 : {"DTLS/SCTP", sizeof("DTLS/SCTP")},
269 : {"RTP/AVPF", sizeof("RTP/AVPF")},
270 : {"UDP/TLS/RTP/SAVP", sizeof("UDP/TLS/RTP/SAVP")},
271 : {"UDP/TLS/RTP/SAVPF", sizeof("UDP/TLS/RTP/SAVPF")},
272 : {"TCP/TLS/RTP/SAVP", sizeof("TCP/TLS/RTP/SAVP")},
273 : {"TCP/TLS/RTP/SAVPF", sizeof("TCP/TLS/RTP/SAVPF")},
274 : {"UDP/DTLS/SCTP", sizeof("UDP/DTLS/SCTP")},
275 : {"TCP/DTLS/SCTP", sizeof("TCP/DTLS/SCTP")},
276 : };
277 :
278 : /* Note: These *must* be in the same order as the enum type. */
279 : const sdp_namearray_t sdp_encrypt[SDP_MAX_ENCRYPT_TYPES] =
280 : {
281 : {"clear", sizeof("clear")},
282 : {"base64", sizeof("base64")},
283 : {"uri", sizeof("uri")},
284 : {"prompt", sizeof("prompt")}
285 : };
286 :
287 : /* Note: These *must* be in the same order as the enum type. */
288 : const sdp_namearray_t sdp_payload[SDP_MAX_STRING_PAYLOAD_TYPES] =
289 : {
290 : {"t38", sizeof("t38")},
291 : {"X-tmr", sizeof("X-tmr")},
292 : {"T120", sizeof("T120")}
293 : };
294 :
295 : /* Note: These *must* be in the same order as the enum type. */
296 : const sdp_namearray_t sdp_t38_rate[SDP_T38_MAX_RATES] =
297 : {
298 : {"localTCF", sizeof("localTCF")},
299 : {"transferredTCF", sizeof("transferredTCF")},
300 : {"unknown", sizeof("unknown")}
301 : };
302 :
303 : /* Note: These *must* be in the same order as the enum type. */
304 : const sdp_namearray_t sdp_t38_udpec[SDP_T38_MAX_UDPEC] =
305 : {
306 : {"t38UDPRedundancy", sizeof("t38UDPRedundancy")},
307 : {"t38UDPFEC", sizeof("t38UDPFEC")},
308 : {"unknown", sizeof("unknown")}
309 : };
310 :
311 : /* Note: These *must* be in the same order as the enum type. */
312 : const sdp_namearray_t sdp_qos_strength[SDP_MAX_QOS_STRENGTH] =
313 : {
314 : {"optional", sizeof("optional")},
315 : {"mandatory", sizeof("mandatory")},
316 : {"success", sizeof("success")},
317 : {"failure", sizeof("failure")},
318 : {"none", sizeof("none")}
319 : };
320 :
321 : /* Note: These *must* be in the same order as the enum type. */
322 : const sdp_namearray_t sdp_qos_status_type[SDP_MAX_QOS_STATUS_TYPES] =
323 : {
324 : {"local", sizeof("local")},
325 : {"remote", sizeof("remote")},
326 : {"e2e", sizeof("e2e")}
327 : };
328 :
329 : /* Note: These *must* be in the same order as the enum type. */
330 : const sdp_namearray_t sdp_curr_type[SDP_MAX_CURR_TYPES] =
331 : {
332 : {"qos", sizeof("qos")},
333 : {"unknown", sizeof("unknown")}
334 : };
335 :
336 : /* Note: These *must* be in the same order as the enum type. */
337 : const sdp_namearray_t sdp_des_type[SDP_MAX_DES_TYPES] =
338 : {
339 : {"qos", sizeof("qos")},
340 : {"unknown", sizeof("unknown")}
341 : };
342 :
343 : /* Note: These *must* be in the same order as the enum type. */
344 : const sdp_namearray_t sdp_conf_type[SDP_MAX_CONF_TYPES] =
345 : {
346 : {"qos", sizeof("qos")},
347 : {"unknown", sizeof("unknown")}
348 : };
349 : /* Note: These *must* be in the same order as the enum type. */
350 : const sdp_namearray_t sdp_qos_direction[SDP_MAX_QOS_DIR] =
351 : {
352 : {"send", sizeof("send")},
353 : {"recv", sizeof("recv")},
354 : {"sendrecv", sizeof("sendrecv")},
355 : {"none", sizeof("none")}
356 : };
357 :
358 : /* Note: These *must* be in the same order as the enum type. */
359 : const sdp_namearray_t sdp_silencesupp_pref[SDP_MAX_SILENCESUPP_PREF] = {
360 : {"standard", sizeof("standard")},
361 : {"custom", sizeof("custom")},
362 : {"-", sizeof("-")}
363 : };
364 :
365 : /* Note: These *must* be in the same order as the enum type. */
366 : const sdp_namearray_t sdp_silencesupp_siduse[SDP_MAX_SILENCESUPP_SIDUSE] = {
367 : {"No SID", sizeof("No SID")},
368 : {"Fixed Noise", sizeof("Fixed Noise")},
369 : {"Sampled Noise", sizeof("Sampled Noise")},
370 : {"-", sizeof("-")}
371 : };
372 :
373 : /* Note: These *must* be in the same order as the enum type. */
374 : const sdp_namearray_t sdp_mediadir_role[SDP_MAX_MEDIADIR_ROLES] =
375 : {
376 : {"passive", sizeof("passive")},
377 : {"active", sizeof("active")},
378 : {"both", sizeof("both")},
379 : {"reuse", sizeof("reuse")},
380 : {"unknown", sizeof("unknown")}
381 : };
382 :
383 : /* Note: These *must* be in the same order as the enum type. */
384 : const sdp_namearray_t sdp_fmtp_codec_param[SDP_MAX_FMTP_PARAM] =
385 : {
386 : {"annexa", sizeof("annexa")}, /* 0 */
387 : {"annexb", sizeof("annexb")}, /* 1 */
388 : {"bitrate", sizeof("bitrate")}, /* 2 */
389 : {"QCIF", sizeof("QCIF")}, /* 3 */
390 : {"CIF", sizeof("CIF")}, /* 4 */
391 : {"MAXBR", sizeof("MAXBR")}, /* 5 */
392 : {"SQCIF", sizeof("SQCIF")}, /* 6 */
393 : {"CIF4", sizeof("CIF4")}, /* 7 */
394 : {"CIF16", sizeof("CIF16")}, /* 8 */
395 : {"CUSTOM", sizeof("CUSTOM")}, /* 9 */
396 : {"PAR", sizeof("PAR")}, /* 10 */
397 : {"CPCF", sizeof("CPCF")}, /* 11 */
398 : {"BPP", sizeof("BPP")}, /* 12 */
399 : {"HRD", sizeof("HRD")}, /* 13 */
400 : {"PROFILE", sizeof("PROFILE")}, /* 14 */
401 : {"LEVEL", sizeof("LEVEL")}, /* 15 */
402 : {"INTERLACE", sizeof("INTERLACE")}, /* 16 */
403 :
404 : /* H.264 related */
405 : {"profile-level-id", sizeof("profile-level-id")}, /* 17 */
406 : {"sprop-parameter-sets", sizeof("sprop-parameter-sets")}, /* 18 */
407 : {"packetization-mode", sizeof("packetization-mode")}, /* 19 */
408 : {"sprop-interleaving-depth", sizeof("sprop-interleaving-depth")}, /* 20 */
409 : {"sprop-deint-buf-req", sizeof("sprop-deint-buf-req")}, /* 21 */
410 : {"sprop-max-don-diff", sizeof("sprop-max-don-diff")}, /* 22 */
411 : {"sprop-init-buf-time", sizeof("sprop-init-buf-time")}, /* 23 */
412 :
413 : {"max-mbps", sizeof("max-mbps")}, /* 24 */
414 : {"max-fs", sizeof("max-fs")}, /* 25 */
415 : {"max-cpb", sizeof("max-cpb")}, /* 26 */
416 : {"max-dpb", sizeof("max-dpb")}, /* 27 */
417 : {"max-br", sizeof("max-br")}, /* 28 */
418 : {"redundant-pic-cap", sizeof("redundant-pic-cap")}, /* 29 */
419 : {"deint-buf-cap", sizeof("deint-buf-cap")}, /* 30 */
420 : {"max-rcmd-nalu-size", sizeof("max-rcmd_nali-size")}, /* 31 */
421 : {"parameter-add", sizeof("parameter-add")}, /* 32 */
422 :
423 : /* Annexes - require special handling */
424 : {"D", sizeof("D")}, /* 33 */
425 : {"F", sizeof("F")}, /* 34 */
426 : {"I", sizeof("I")}, /* 35 */
427 : {"J", sizeof("J")}, /* 36 */
428 : {"T", sizeof("T")}, /* 37 */
429 : {"K", sizeof("K")}, /* 38 */
430 : {"N", sizeof("N")}, /* 39 */
431 : {"P", sizeof("P")}, /* 40 */
432 :
433 : {"mode", sizeof("mode")}, /* 41 */
434 : {"level-asymmetry-allowed", sizeof("level-asymmetry-allowed")}, /* 42 */
435 : {"maxaveragebitrate", sizeof("maxaveragebitrate")}, /* 43 */
436 : {"usedtx", sizeof("usedtx")}, /* 44 */
437 : {"stereo", sizeof("stereo")}, /* 45 */
438 : {"useinbandfec", sizeof("useinbandfec")}, /* 46 */
439 : {"maxcodedaudiobandwidth", sizeof("maxcodedaudiobandwidth")}, /* 47 */
440 : {"cbr", sizeof("cbr")}, /* 48 */
441 : {"max-fr", sizeof("max-fr")}, /* 49 */
442 : {"maxplaybackrate", sizeof("maxplaybackrate")} /* 50 */
443 : } ;
444 :
445 : /* Note: These *must* be in the same order as the enum type. */
446 : const sdp_namearray_t sdp_fmtp_codec_param_val[SDP_MAX_FMTP_PARAM_VAL] =
447 : {
448 : {"yes", sizeof("yes")},
449 : {"no", sizeof("no")}
450 : };
451 :
452 : const sdp_namearray_t sdp_bw_modifier_val[SDP_MAX_BW_MODIFIER_VAL] =
453 : {
454 : {"AS", sizeof("AS")},
455 : {"CT", sizeof("CT")},
456 : {"TIAS", sizeof("TIAS")}
457 : };
458 :
459 : const sdp_namearray_t sdp_group_attr_val[SDP_MAX_GROUP_ATTR_VAL] =
460 : {
461 : {"FID", sizeof("FID")},
462 : {"LS", sizeof("LS")},
463 : {"ANAT", sizeof("ANAT")},
464 : {"BUNDLE", sizeof("BUNDLE")}
465 : };
466 :
467 : const sdp_namearray_t sdp_srtp_context_crypto_suite[SDP_SRTP_MAX_NUM_CRYPTO_SUITES] =
468 : {
469 : {"UNKNOWN_CRYPTO_SUITE", sizeof("UNKNOWN_CRYPTO_SUITE")},
470 : {"AES_CM_128_HMAC_SHA1_32", sizeof("AES_CM_128_HMAC_SHA1_32")},
471 : {"AES_CM_128_HMAC_SHA1_80", sizeof("AES_CM_128_HMAC_SHA1_80")},
472 : {"F8_128_HMAC_SHA1_80", sizeof("F8_128_HMAC_SHA1_80")}
473 : };
474 :
475 : /* Maintain the same order as defined in typedef sdp_src_filter_mode_e */
476 : const sdp_namearray_t sdp_src_filter_mode_val[SDP_MAX_FILTER_MODE] =
477 : {
478 : {"incl", sizeof("incl")},
479 : {"excl", sizeof("excl")}
480 : };
481 :
482 : /* Maintain the same order as defined in typdef sdp_rtcp_unicast_mode_e */
483 : const sdp_namearray_t sdp_rtcp_unicast_mode_val[SDP_RTCP_MAX_UNICAST_MODE] =
484 : {
485 : {"reflection", sizeof("reflection")},
486 : {"rsi", sizeof("rsi")}
487 : };
488 :
489 : #define SDP_NAME(x) {x, sizeof(x)}
490 : /* Maintain the same order as defined in typdef sdp_rtcp_fb_type_e */
491 : const sdp_namearray_t sdp_rtcp_fb_type_val[SDP_MAX_RTCP_FB] =
492 : {
493 : SDP_NAME("ack"),
494 : SDP_NAME("ccm"),
495 : SDP_NAME("nack"),
496 : SDP_NAME("trr-int"),
497 : SDP_NAME("goog-remb")
498 : };
499 :
500 : /* Maintain the same order as defined in typdef sdp_rtcp_fb_nack_type_e */
501 : const sdp_namearray_t sdp_rtcp_fb_nack_type_val[SDP_MAX_RTCP_FB_NACK] =
502 : {
503 : SDP_NAME(""),
504 : SDP_NAME("sli"),
505 : SDP_NAME("pli"),
506 : SDP_NAME("rpsi"),
507 : SDP_NAME("app"),
508 : SDP_NAME("rai"),
509 : SDP_NAME("tllei"),
510 : SDP_NAME("pslei"),
511 : SDP_NAME("ecn")
512 : };
513 :
514 : /* Maintain the same order as defined in typdef sdp_rtcp_fb_ack_type_e */
515 : const sdp_namearray_t sdp_rtcp_fb_ack_type_val[SDP_MAX_RTCP_FB_ACK] =
516 : {
517 : SDP_NAME("rpsi"),
518 : SDP_NAME("app")
519 : };
520 :
521 : /* Maintain the same order as defined in typdef sdp_rtcp_fb_ccm_type_e */
522 : const sdp_namearray_t sdp_rtcp_fb_ccm_type_val[SDP_MAX_RTCP_FB_CCM] =
523 : {
524 : SDP_NAME("fir"),
525 : SDP_NAME("tmmbr"),
526 : SDP_NAME("tstr"),
527 : SDP_NAME("vbcm")
528 : };
529 :
530 : /* Maintain the same order as defined in typedef sdp_setup_type_e */
531 : const sdp_namearray_t sdp_setup_type_val[SDP_MAX_SETUP] =
532 : {
533 : SDP_NAME("active"),
534 : SDP_NAME("passive"),
535 : SDP_NAME("actpass"),
536 : SDP_NAME("holdconn")
537 : };
538 :
539 : /* Maintain the same order as defined in typedef sdp_connection_type_e */
540 : const sdp_namearray_t sdp_connection_type_val[SDP_MAX_CONNECTION] =
541 : {
542 : SDP_NAME("new"),
543 : SDP_NAME("existing")
544 : };
545 :
546 : /* Maintain same order as defined in typedef sdp_srtp_crypto_suite_t */
547 : const sdp_srtp_crypto_suite_list sdp_srtp_crypto_suite_array[SDP_SRTP_MAX_NUM_CRYPTO_SUITES] =
548 : {
549 : {SDP_SRTP_UNKNOWN_CRYPTO_SUITE, UNKNOWN_CRYPTO_SUITE, 0, 0},
550 : {SDP_SRTP_AES_CM_128_HMAC_SHA1_32, AES_CM_128_HMAC_SHA1_32,
551 : SDP_SRTP_AES_CM_128_HMAC_SHA1_32_KEY_BYTES,
552 : SDP_SRTP_AES_CM_128_HMAC_SHA1_32_SALT_BYTES},
553 : {SDP_SRTP_AES_CM_128_HMAC_SHA1_80, AES_CM_128_HMAC_SHA1_80,
554 : SDP_SRTP_AES_CM_128_HMAC_SHA1_80_KEY_BYTES,
555 : SDP_SRTP_AES_CM_128_HMAC_SHA1_80_SALT_BYTES},
556 : {SDP_SRTP_F8_128_HMAC_SHA1_80, F8_128_HMAC_SHA1_80,
557 : SDP_SRTP_F8_128_HMAC_SHA1_80_KEY_BYTES,
558 : SDP_SRTP_F8_128_HMAC_SHA1_80_SALT_BYTES}
559 : };
560 :
561 : const char* sdp_result_name[SDP_MAX_RC] =
562 : {"SDP_SUCCESS",
563 : "SDP_FAILURE",
564 : "SDP_INVALID_SDP_PTR",
565 : "SDP_NOT_SDP_DESCRIPTION",
566 : "SDP_INVALID_TOKEN_ORDERING",
567 : "SDP_INVALID_PARAMETER",
568 : "SDP_INVALID_MEDIA_LEVEL",
569 : "SDP_INVALID_CAPABILITY",
570 : "SDP_NO_RESOURCE",
571 : "SDP_UNRECOGNIZED_TOKEN",
572 : "SDP_NULL_BUF_PTR",
573 : "SDP_POTENTIAL_SDP_OVERFLOW",
574 : "SDP_EMPTY_TOKEN"};
575 :
576 0 : const char *sdp_get_result_name ( sdp_result_e rc )
577 : {
578 0 : if (rc >= SDP_MAX_RC) {
579 0 : return ("Invalid SDP result code");
580 : } else {
581 0 : return (sdp_result_name[rc]);
582 : }
583 : }
584 :
585 0 : const char *sdp_get_attr_name ( sdp_attr_e attr_type )
586 : {
587 0 : if (attr_type >= SDP_MAX_ATTR_TYPES) {
588 0 : return ("Invalid attribute type");
589 : } else {
590 0 : return (sdp_attr[attr_type].name);
591 : }
592 : }
593 :
594 0 : const char *sdp_get_media_name ( sdp_media_e media_type )
595 : {
596 0 : if (media_type == SDP_MEDIA_UNSUPPORTED) {
597 0 : return (SDP_UNSUPPORTED);
598 0 : } else if (media_type >= SDP_MAX_MEDIA_TYPES) {
599 0 : return ("Invalid media type");
600 : } else {
601 0 : return (sdp_media[media_type].name);
602 : }
603 : }
604 :
605 0 : const char *sdp_get_network_name ( sdp_nettype_e network_type )
606 : {
607 0 : if (network_type == SDP_NT_UNSUPPORTED) {
608 0 : return (SDP_UNSUPPORTED);
609 0 : } else if (network_type >= SDP_MAX_NETWORK_TYPES) {
610 0 : return ("Invalid network type");
611 : } else {
612 0 : return (sdp_nettype[network_type].name);
613 : }
614 : }
615 :
616 0 : const char *sdp_get_address_name ( sdp_addrtype_e addr_type )
617 : {
618 0 : if (addr_type == SDP_AT_UNSUPPORTED) {
619 0 : return (SDP_UNSUPPORTED);
620 0 : } else if (addr_type >= SDP_MAX_ADDR_TYPES) {
621 0 : if (addr_type == SDP_AT_FQDN) {
622 0 : return ("*");
623 : } else {
624 0 : return ("Invalid address type");
625 : }
626 : } else {
627 0 : return (sdp_addrtype[addr_type].name);
628 : }
629 : }
630 :
631 0 : const char *sdp_get_transport_name ( sdp_transport_e transport_type )
632 : {
633 0 : if (transport_type == SDP_TRANSPORT_UNSUPPORTED) {
634 0 : return (SDP_UNSUPPORTED);
635 0 : } else if (transport_type >= SDP_MAX_TRANSPORT_TYPES) {
636 0 : return ("Invalid transport type");
637 : } else {
638 0 : return (sdp_transport[transport_type].name);
639 : }
640 : }
641 :
642 0 : const char *sdp_get_encrypt_name ( sdp_encrypt_type_e encrypt_type )
643 : {
644 0 : if (encrypt_type == SDP_ENCRYPT_UNSUPPORTED) {
645 0 : return (SDP_UNSUPPORTED);
646 0 : } else if (encrypt_type >= SDP_MAX_ENCRYPT_TYPES) {
647 0 : return ("Invalid encryption type");
648 : } else {
649 0 : return (sdp_encrypt[encrypt_type].name);
650 : }
651 : }
652 :
653 0 : const char *sdp_get_payload_name ( sdp_payload_e payload )
654 : {
655 0 : if (payload == SDP_PAYLOAD_UNSUPPORTED) {
656 0 : return (SDP_UNSUPPORTED);
657 0 : } else if (payload >= SDP_MAX_STRING_PAYLOAD_TYPES) {
658 0 : return ("Invalid payload type");
659 : } else {
660 0 : return (sdp_payload[payload].name);
661 : }
662 : }
663 :
664 0 : const char *sdp_get_t38_ratemgmt_name ( sdp_t38_ratemgmt_e rate )
665 : {
666 0 : if (rate >= SDP_T38_MAX_RATES) {
667 0 : return ("Invalid rate");
668 : } else {
669 0 : return (sdp_t38_rate[rate].name);
670 : }
671 : }
672 :
673 0 : const char *sdp_get_t38_udpec_name ( sdp_t38_udpec_e udpec )
674 : {
675 0 : if (udpec >= SDP_T38_MAX_UDPEC) {
676 0 : return ("Invalid udpec");
677 : } else {
678 0 : return (sdp_t38_udpec[udpec].name);
679 : }
680 : }
681 :
682 0 : const char *sdp_get_qos_strength_name ( sdp_qos_strength_e strength )
683 : {
684 0 : if (strength >= SDP_MAX_QOS_STRENGTH) {
685 0 : return ("Invalid qos strength");
686 : } else {
687 0 : return (sdp_qos_strength[strength].name);
688 : }
689 : }
690 :
691 0 : const char *sdp_get_qos_direction_name ( sdp_qos_dir_e direction )
692 : {
693 0 : if (direction >= SDP_MAX_QOS_DIR) {
694 0 : return ("Invalid qos direction");
695 : } else {
696 0 : return (sdp_qos_direction[direction].name);
697 : }
698 : }
699 :
700 0 : const char *sdp_get_qos_status_type_name ( sdp_qos_status_types_e status_type )
701 : {
702 0 : if (status_type >= SDP_MAX_QOS_STATUS_TYPES) {
703 0 : return ("Invalid qos status type");
704 : } else {
705 0 : return (sdp_qos_status_type[status_type].name);
706 : }
707 : }
708 :
709 0 : const char *sdp_get_curr_type_name (sdp_curr_type_e curr_type )
710 : {
711 0 : if (curr_type >= SDP_MAX_CURR_TYPES) {
712 0 : return ("Invalid curr type");
713 : } else {
714 0 : return (sdp_curr_type[curr_type].name);
715 : }
716 : }
717 :
718 0 : const char *sdp_get_des_type_name (sdp_des_type_e des_type )
719 : {
720 0 : if (des_type >= SDP_MAX_DES_TYPES) {
721 0 : return ("Invalid des type");
722 : } else {
723 0 : return (sdp_des_type[des_type].name);
724 : }
725 : }
726 :
727 0 : const char *sdp_get_conf_type_name (sdp_conf_type_e conf_type )
728 : {
729 0 : if (conf_type >= SDP_MAX_CONF_TYPES) {
730 0 : return ("Invalid conf type");
731 : } else {
732 0 : return (sdp_conf_type[conf_type].name);
733 : }
734 : }
735 :
736 0 : const char *sdp_get_silencesupp_pref_name (sdp_silencesupp_pref_e pref)
737 : {
738 0 : if (pref >= SDP_MAX_SILENCESUPP_PREF) {
739 0 : return ("Invalid silencesupp pref");
740 : } else {
741 0 : return (sdp_silencesupp_pref[pref].name);
742 : }
743 : }
744 :
745 0 : const char *sdp_get_silencesupp_siduse_name (sdp_silencesupp_siduse_e siduse)
746 : {
747 0 : if (siduse >= SDP_MAX_SILENCESUPP_SIDUSE) {
748 0 : return ("Invalid silencesupp siduse");
749 : } else {
750 0 : return (sdp_silencesupp_siduse[siduse].name);
751 : }
752 : }
753 :
754 0 : const char *sdp_get_mediadir_role_name (sdp_mediadir_role_e role)
755 : {
756 0 : if (role >= SDP_MEDIADIR_ROLE_UNKNOWN) {
757 0 : return ("Invalid media direction role");
758 : } else {
759 0 : return (sdp_mediadir_role[role].name);
760 : }
761 : }
762 :
763 :
764 0 : const char *sdp_get_bw_modifier_name (sdp_bw_modifier_e bw_modifier_type)
765 : {
766 0 : if (bw_modifier_type == SDP_BW_MODIFIER_UNSUPPORTED) {
767 0 : return (SDP_UNSUPPORTED);
768 0 : } else if (bw_modifier_type < SDP_BW_MODIFIER_AS ||
769 : bw_modifier_type >= SDP_MAX_BW_MODIFIER_VAL) {
770 0 : return ("Invalid bw modifier type");
771 : } else {
772 0 : return (sdp_bw_modifier_val[bw_modifier_type].name);
773 : }
774 : }
775 :
776 0 : const char *sdp_get_group_attr_name (sdp_group_attr_e group_attr_type)
777 : {
778 0 : if (group_attr_type == SDP_GROUP_ATTR_UNSUPPORTED) {
779 0 : return (SDP_UNSUPPORTED);
780 0 : } else if (group_attr_type >= SDP_MAX_GROUP_ATTR_VAL) {
781 0 : return ("Invalid a=group: attribute type");
782 : } else {
783 0 : return (sdp_group_attr_val[group_attr_type].name);
784 : }
785 : }
786 :
787 0 : const char *sdp_get_src_filter_mode_name (sdp_src_filter_mode_e type)
788 : {
789 0 : if (type >= SDP_MAX_FILTER_MODE) {
790 0 : return ("Invalid source filter mode");
791 : } else {
792 0 : return (sdp_src_filter_mode_val[type].name);
793 : }
794 : }
795 :
796 0 : const char *sdp_get_rtcp_unicast_mode_name (sdp_rtcp_unicast_mode_e type)
797 : {
798 0 : if (type >= SDP_RTCP_MAX_UNICAST_MODE) {
799 0 : return ("Invalid rtcp unicast mode");
800 : } else {
801 0 : return (sdp_rtcp_unicast_mode_val[type].name);
802 : }
803 : }
804 :
805 : /* Function: sdp_init_description
806 : * Description: Allocates a new SDP structure that can be used for either
807 : * parsing or building an SDP description. This routine
808 : * saves the config pointer passed in the SDP structure so
809 : * SDP will know how to parse/build based on the options defined.
810 : * An SDP structure must be allocated before parsing or building
811 : * since the handle must be passed to these routines.
812 : * Parameters: config_p The config handle returned by sdp_init_config
813 : * Returns: A handle for a new SDP structure as a void ptr.
814 : */
815 0 : sdp_t *sdp_init_description (sdp_conf_options_t *conf_p)
816 : {
817 : int i;
818 : sdp_t *sdp_p;
819 :
820 0 : if (!conf_p) {
821 0 : return (NULL);
822 : }
823 :
824 0 : sdp_p = (sdp_t *)SDP_MALLOC(sizeof(sdp_t));
825 0 : if (sdp_p == NULL) {
826 0 : return (NULL);
827 : }
828 :
829 0 : sdp_p->conf_p = conf_p;
830 0 : sdp_p->version = SDP_CURRENT_VERSION;
831 0 : sdp_p->owner_name[0] = '\0';
832 0 : sdp_p->owner_sessid[0] = '\0';
833 0 : sdp_p->owner_version[0] = '\0';
834 0 : sdp_p->owner_network_type = SDP_NT_INVALID;
835 0 : sdp_p->owner_addr_type = SDP_AT_INVALID;
836 0 : sdp_p->owner_addr[0] = '\0';
837 0 : sdp_p->sessname[0] = '\0';
838 0 : sdp_p->sessinfo_found = FALSE;
839 0 : sdp_p->uri_found = FALSE;
840 :
841 0 : sdp_p->default_conn.nettype = SDP_NT_INVALID;
842 0 : sdp_p->default_conn.addrtype = SDP_AT_INVALID;
843 0 : sdp_p->default_conn.conn_addr[0] = '\0';
844 0 : sdp_p->default_conn.is_multicast = FALSE;
845 0 : sdp_p->default_conn.ttl = 0;
846 0 : sdp_p->default_conn.num_of_addresses = 0;
847 :
848 0 : sdp_p->bw.bw_data_count = 0;
849 0 : sdp_p->bw.bw_data_list = NULL;
850 :
851 0 : sdp_p->timespec_p = NULL;
852 0 : sdp_p->sess_attrs_p = NULL;
853 0 : sdp_p->mca_p = NULL;
854 0 : sdp_p->mca_count = 0;
855 :
856 : /* Set default debug flags from application config. */
857 0 : for (i=0; i < SDP_MAX_DEBUG_TYPES; i++) {
858 0 : sdp_p->debug_flag[i] = conf_p->debug_flag[i];
859 : }
860 :
861 0 : return (sdp_p);
862 : }
863 :
864 :
865 : /* Function: void sdp_debug(sdp_t *sdp_p, sdp_debug_e debug_type,
866 : * tinybool my_bool);
867 : * Description: Define the type of debug for this particular SDP structure.
868 : * By default, each SDP description has the settings that are
869 : * set for the application.
870 : * Valid debug types are ERRORS, WARNINGS, and TRACE. Each
871 : * debug type can be turned on/off individually. The
872 : * debug level can be redefined at any time.
873 : * Parameters: sdp_ptr The SDP handle returned by sdp_init_description.
874 : * debug_type Specifies the debug type being enabled/disabled.
875 : * my_bool Defines whether the debug should be enabled or not.
876 : * Returns: Nothing.
877 : */
878 0 : void sdp_debug (sdp_t *sdp_p, sdp_debug_e debug_type, tinybool debug_flag)
879 : {
880 0 : if (!sdp_p) {
881 0 : return;
882 : }
883 :
884 0 : if (debug_type < SDP_MAX_DEBUG_TYPES) {
885 0 : sdp_p->debug_flag[debug_type] = debug_flag;
886 : }
887 : }
888 :
889 :
890 : /* Function: void sdp_set_string_debug(sdp_t *sdp_p, char *debug_str)
891 : * Description: Define a string to be associated with all debug output
892 : * for this SDP. The string will be copied into the SDP
893 : * structure and so the library will not be dependent on
894 : * the application's memory for this string.
895 : * Parameters: sdp_p The SDP handle returned by sdp_init_description.
896 : * debug_str Pointer to a string that should be printed out
897 : * with every debug msg.
898 : * Returns: Nothing.
899 : */
900 0 : void sdp_set_string_debug (sdp_t *sdp_p, const char *debug_str)
901 : {
902 0 : if (!sdp_p) {
903 0 : return;
904 : }
905 :
906 0 : sstrncpy(sdp_p->debug_str, debug_str, sizeof(sdp_p->debug_str));
907 : }
908 :
909 :
910 : /* Function: sdp_validate_sdp
911 : * Description: Validate an SDP structure.
912 : * Parameters: sdp_p The SDP handle of the struct to validate.
913 : * Returns: A result value indicating if the validation was successful.
914 : * If not, what type of error was encountered.
915 : */
916 0 : sdp_result_e sdp_validate_sdp (sdp_t *sdp_p)
917 : {
918 : int i;
919 : uint16_t num_media_levels;
920 :
921 : /* Need to validate c= info is specified at session level or
922 : * at all m= levels.
923 : */
924 0 : if (sdp_connection_valid((void *)sdp_p, SDP_SESSION_LEVEL) == FALSE) {
925 0 : num_media_levels = sdp_get_num_media_lines((void *)sdp_p);
926 0 : for (i=1; i <= num_media_levels; i++) {
927 0 : if (sdp_connection_valid((void *)sdp_p, (unsigned short)i) == FALSE) {
928 0 : sdp_parse_error(sdp_p,
929 : "%s c= connection line not specified for "
930 : "every media level, validation failed.",
931 0 : sdp_p->debug_str);
932 0 : return (SDP_FAILURE);
933 : }
934 : }
935 : }
936 :
937 : /* Validate required lines were specified */
938 0 : if ((sdp_owner_valid((void *)sdp_p) == FALSE) &&
939 0 : (sdp_p->conf_p->owner_reqd == TRUE)) {
940 0 : sdp_parse_error(sdp_p,
941 : "%s o= owner line not specified, validation failed.",
942 0 : sdp_p->debug_str);
943 0 : return (SDP_FAILURE);
944 : }
945 :
946 0 : if ((sdp_session_name_valid((void *)sdp_p) == FALSE) &&
947 0 : (sdp_p->conf_p->session_name_reqd == TRUE)) {
948 0 : sdp_parse_error(sdp_p,
949 : "%s s= session name line not specified, validation failed.",
950 0 : sdp_p->debug_str);
951 0 : return (SDP_FAILURE);
952 : }
953 :
954 0 : if ((sdp_timespec_valid((void *)sdp_p) == FALSE) &&
955 0 : (sdp_p->conf_p->timespec_reqd == TRUE)) {
956 0 : sdp_parse_error(sdp_p,
957 : "%s t= timespec line not specified, validation failed.",
958 0 : sdp_p->debug_str);
959 0 : return (SDP_FAILURE);
960 : }
961 :
962 0 : return (SDP_SUCCESS);
963 : }
964 :
965 : /* Function: sdp_parse
966 : * Description: Parse an SDP description in the specified buffer.
967 : * Parameters: sdp_p The SDP handle returned by sdp_init_description
968 : * bufp Pointer to the buffer containing the SDP
969 : * description to parse.
970 : * len The length of the buffer.
971 : * Returns: A result value indicating if the parse was successful and
972 : * if not, what type of error was encountered. The
973 : * information from the parse is stored in the sdp_p structure.
974 : */
975 0 : sdp_result_e sdp_parse (sdp_t *sdp_p, const char *buf, size_t len)
976 : {
977 : uint8_t i;
978 0 : uint16_t cur_level = SDP_SESSION_LEVEL;
979 : const char *ptr;
980 0 : const char *next_ptr = NULL;
981 : char *line_end;
982 0 : sdp_token_e last_token = SDP_TOKEN_V;
983 0 : sdp_result_e result = SDP_SUCCESS;
984 0 : tinybool parse_done = FALSE;
985 0 : tinybool end_found = FALSE;
986 0 : tinybool first_line = TRUE;
987 0 : tinybool unrec_token = FALSE;
988 0 : const char **bufp = &buf;
989 :
990 0 : if (!sdp_p) {
991 0 : return (SDP_INVALID_SDP_PTR);
992 : }
993 :
994 0 : if ((bufp == NULL) || (*bufp == NULL)) {
995 0 : return (SDP_NULL_BUF_PTR);
996 : }
997 :
998 0 : if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
999 0 : SDP_PRINT("%s Trace SDP Parse:", sdp_p->debug_str);
1000 : }
1001 :
1002 0 : next_ptr = *bufp;
1003 0 : sdp_p->conf_p->num_parses++;
1004 :
1005 : /* Initialize the last valid capability instance to zero. Used
1006 : * to help in parsing X-cpar attrs. */
1007 0 : sdp_p->cap_valid = FALSE;
1008 0 : sdp_p->last_cap_inst = 0;
1009 :
1010 0 : sdp_p->parse_line = 0;
1011 :
1012 : /* We want to try to find the end of the SDP description, even if
1013 : * we find a parsing error.
1014 : */
1015 0 : while (!end_found) {
1016 : /* If the last char of this line goes beyond the end of the buffer,
1017 : * we don't parse it.
1018 : */
1019 0 : ptr = next_ptr;
1020 0 : sdp_p->parse_line++;
1021 0 : line_end = sdp_findchar(ptr, "\n");
1022 0 : if ((line_end >= (*bufp + len)) ||
1023 0 : (*line_end == '\0')) {
1024 : /* As this does not update the result value the SDP up to this point
1025 : * is still accept as valid. So encountering this is not treated as
1026 : * an error.
1027 : */
1028 0 : sdp_parse_error(sdp_p,
1029 : "%s End of line beyond end of buffer.",
1030 0 : sdp_p->debug_str);
1031 0 : CSFLogError(logTag, "SDP: Invalid SDP, no \\n (len %u): %*s",
1032 : (unsigned)len, (int)len, *bufp);
1033 0 : end_found = TRUE;
1034 0 : break;
1035 : }
1036 :
1037 : /* Print the line if we're tracing. */
1038 0 : if ((parse_done == FALSE) &&
1039 0 : (sdp_p->debug_flag[SDP_DEBUG_TRACE])) {
1040 0 : SDP_PRINT("%s ", sdp_p->debug_str);
1041 :
1042 0 : SDP_PRINT("%*s", (int)(line_end - ptr), ptr);
1043 :
1044 : }
1045 :
1046 : /* Find out which token this line has, if any. */
1047 0 : for (i=0; i < SDP_MAX_TOKENS; i++) {
1048 0 : if (strncmp(ptr, sdp_token[i].name, SDP_TOKEN_LEN) == 0) {
1049 0 : break;
1050 : }
1051 : }
1052 0 : if (i == SDP_MAX_TOKENS) {
1053 : /* See if the second char on the next line is an '=' char.
1054 : * If so, we note this as an unrecognized token line. */
1055 0 : if (ptr[1] == '=') {
1056 0 : unrec_token = TRUE;
1057 : }
1058 0 : if (first_line == TRUE) {
1059 0 : sdp_parse_error(sdp_p,
1060 : "%s Attempt to parse text not recognized as "
1061 0 : "SDP text, parse fails.", sdp_p->debug_str);
1062 : /* If we haven't already printed out the line we
1063 : * were trying to parse, do it now.
1064 : */
1065 0 : if (!sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
1066 0 : SDP_PRINT("%s ", sdp_p->debug_str);
1067 0 : SDP_PRINT("%*s", (int)(line_end - ptr), ptr);
1068 : }
1069 0 : sdp_p->conf_p->num_not_sdp_desc++;
1070 0 : return (SDP_NOT_SDP_DESCRIPTION);
1071 : } else {
1072 0 : end_found = TRUE;
1073 0 : break;
1074 : }
1075 : }
1076 :
1077 : /* This is the beginning of a new SDP description. */
1078 0 : if ((first_line != TRUE) && (i == SDP_TOKEN_V)) {
1079 0 : end_found = TRUE;
1080 0 : break;
1081 : }
1082 :
1083 : /* Advance the next ptr to one char beyond the end of the line. */
1084 0 : next_ptr = line_end + 1;
1085 0 : if (next_ptr >= (*bufp + len)) {
1086 0 : end_found = TRUE;
1087 : }
1088 :
1089 : /* If we've finished parsing and are just looking for the end of
1090 : * the SDP description, we don't need to do anything else here.
1091 : */
1092 0 : if (parse_done == TRUE) {
1093 0 : continue;
1094 : }
1095 :
1096 : /* Only certain tokens are valid at the media level. */
1097 0 : if (cur_level != SDP_SESSION_LEVEL) {
1098 0 : if ((i != SDP_TOKEN_I) && (i != SDP_TOKEN_C) &&
1099 0 : (i != SDP_TOKEN_B) && (i != SDP_TOKEN_K) &&
1100 0 : (i != SDP_TOKEN_A) && (i != SDP_TOKEN_M)) {
1101 0 : sdp_p->conf_p->num_invalid_token_order++;
1102 0 : sdp_parse_error(sdp_p,
1103 : "%s Warning: Invalid token %s found at media level",
1104 0 : sdp_p->debug_str, sdp_token[i].name);
1105 0 : continue;
1106 : }
1107 : }
1108 :
1109 : /* Verify the token ordering. */
1110 0 : if (first_line == TRUE) {
1111 0 : if (i != SDP_TOKEN_V) {
1112 0 : if (sdp_p->conf_p->version_reqd == TRUE) {
1113 0 : sdp_parse_error(sdp_p,
1114 : "%s First line not v=, parse fails",
1115 0 : sdp_p->debug_str);
1116 0 : sdp_p->conf_p->num_invalid_token_order++;
1117 0 : result = SDP_INVALID_TOKEN_ORDERING;
1118 0 : parse_done = TRUE;
1119 : } else {
1120 0 : last_token = (sdp_token_e)i;
1121 : }
1122 : } else {
1123 0 : last_token = (sdp_token_e)i;
1124 : }
1125 0 : first_line = FALSE;
1126 : } else {
1127 0 : if (i < last_token) {
1128 0 : sdp_p->conf_p->num_invalid_token_order++;
1129 0 : sdp_parse_error(sdp_p,
1130 : "%s Warning: Invalid token ordering detected, "
1131 0 : "token %s found after token %s", sdp_p->debug_str,
1132 : sdp_token[i].name, sdp_token[last_token].name);
1133 : }
1134 : }
1135 :
1136 : /* Finally parse the line. */
1137 0 : ptr += SDP_TOKEN_LEN;
1138 0 : result = sdp_token[i].parse_func(sdp_p, cur_level, (const char *)ptr);
1139 0 : last_token = (sdp_token_e)i;
1140 0 : if (last_token == SDP_TOKEN_M) {
1141 0 : if (cur_level == SDP_SESSION_LEVEL) {
1142 0 : cur_level = 1;
1143 : } else {
1144 0 : cur_level++;
1145 : }
1146 : /* The token ordering can start again at i= */
1147 0 : last_token = (sdp_token_e)(SDP_TOKEN_I - 1);
1148 : }
1149 0 : if (result != SDP_SUCCESS) {
1150 0 : parse_done = TRUE;
1151 : }
1152 :
1153 : /* Skip the new line char at the end of this line and see if
1154 : * this is the end of the buffer.
1155 : */
1156 0 : if ((line_end + 1) == (*bufp + len)) {
1157 0 : end_found = TRUE;
1158 : }
1159 : }
1160 :
1161 : /* If we found no valid lines, return an error. */
1162 0 : if (first_line == TRUE) {
1163 0 : sdp_p->conf_p->num_not_sdp_desc++;
1164 0 : return (SDP_NOT_SDP_DESCRIPTION);
1165 : }
1166 :
1167 : /* If no errors were found yet, validate the overall sdp. */
1168 0 : if (result == SDP_SUCCESS) {
1169 0 : result = sdp_validate_sdp(sdp_p);
1170 : }
1171 : /* Return the pointer where we left off. */
1172 0 : *bufp = next_ptr;
1173 : /* If the SDP is valid, but the next line following was an
1174 : * unrecognized <token>= line, indicate this on the return. */
1175 0 : if ((result == SDP_SUCCESS) && (unrec_token == TRUE)) {
1176 0 : return (SDP_UNRECOGNIZED_TOKEN);
1177 : } else {
1178 0 : return (result);
1179 : }
1180 : }
1181 :
1182 :
1183 : /* Function: sdp_build
1184 : * Description: Build an SDP description in the specified buffer based
1185 : * on the information in the given SDP structure.
1186 : * Parameters: sdp_p The SDP handle returned by sdp_init_description
1187 : * fs A flex_string where the SDP description should be built.
1188 : * Returns: A result value indicating if the build was successful and
1189 : * if not, what type of error was encountered - e.g.,
1190 : * description was too long for the given buffer.
1191 : */
1192 0 : sdp_result_e sdp_build (sdp_t *sdp_p, flex_string *fs)
1193 : {
1194 : int i, j;
1195 0 : sdp_result_e result = SDP_SUCCESS;
1196 :
1197 0 : if (!sdp_p) {
1198 0 : return (SDP_INVALID_SDP_PTR);
1199 : }
1200 :
1201 0 : if (!fs) {
1202 0 : return (SDP_NULL_BUF_PTR);
1203 : }
1204 :
1205 0 : if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
1206 0 : SDP_PRINT("%s Trace SDP Build:", sdp_p->debug_str);
1207 : }
1208 :
1209 0 : sdp_p->conf_p->num_builds++;
1210 :
1211 0 : for (i=0; ((i < SDP_TOKEN_M) &&
1212 0 : (result == SDP_SUCCESS)); i++) {
1213 0 : result = sdp_token[i].build_func(sdp_p, SDP_SESSION_LEVEL, fs);
1214 : /* ok not to check buffer space (yet) as the if() checks it */
1215 : }
1216 : /* If the session level was ok, build the media lines. */
1217 0 : if (result == SDP_SUCCESS) {
1218 0 : for (i=1; ((i <= sdp_p->mca_count) &&
1219 0 : (result == SDP_SUCCESS)); i++) {
1220 0 : result = sdp_token[SDP_TOKEN_M].build_func(sdp_p, (uint16_t)i, fs);
1221 :
1222 : /* ok not to check buffer space (yet) as the for() checks it */
1223 0 : for (j=SDP_TOKEN_I;
1224 0 : ((j < SDP_TOKEN_M) && (result == SDP_SUCCESS));
1225 0 : j++) {
1226 0 : if ((j == SDP_TOKEN_U) || (j == SDP_TOKEN_E) ||
1227 0 : (j == SDP_TOKEN_P) || (j == SDP_TOKEN_T) ||
1228 0 : (j == SDP_TOKEN_R) || (j == SDP_TOKEN_Z)) {
1229 : /* These tokens not valid at media level. */
1230 0 : continue;
1231 : }
1232 0 : result = sdp_token[j].build_func(sdp_p, (uint16_t)i, fs);
1233 : /* ok not to check buffer space (yet) as the for() checks it */
1234 : }
1235 : }
1236 : }
1237 :
1238 0 : return (result);
1239 : }
1240 :
1241 : /* Function: sdp_free_description
1242 : * Description: Free an SDP description and all memory associated with it.
1243 : * Parameters: sdp_p The SDP handle returned by sdp_init_description
1244 : * Returns: A result value indicating if the free was successful and
1245 : * if not, what type of error was encountered - e.g., sdp_p
1246 : * was invalid and didn't point to an SDP structure.
1247 : */
1248 0 : sdp_result_e sdp_free_description (sdp_t *sdp_p)
1249 : {
1250 : sdp_timespec_t *time_p, *next_time_p;
1251 : sdp_attr_t *attr_p, *next_attr_p;
1252 : sdp_mca_t *mca_p, *next_mca_p;
1253 : sdp_bw_t *bw_p;
1254 : sdp_bw_data_t *bw_data_p;
1255 :
1256 0 : if (!sdp_p) {
1257 0 : return (SDP_INVALID_SDP_PTR);
1258 : }
1259 :
1260 : /* Free the config structure */
1261 0 : sdp_free_config(sdp_p->conf_p);
1262 :
1263 : /* Free any timespec structures - should be only one since
1264 : * this is all we currently support.
1265 : */
1266 0 : time_p = sdp_p->timespec_p;
1267 0 : while (time_p != NULL) {
1268 0 : next_time_p = time_p->next_p;
1269 0 : SDP_FREE(time_p);
1270 0 : time_p = next_time_p;
1271 : }
1272 :
1273 0 : bw_p = &(sdp_p->bw);
1274 0 : bw_data_p = bw_p->bw_data_list;
1275 0 : while (bw_data_p != NULL) {
1276 0 : bw_p->bw_data_list = bw_data_p->next_p;
1277 0 : SDP_FREE(bw_data_p);
1278 0 : bw_data_p = bw_p->bw_data_list;
1279 : }
1280 :
1281 : /* Free any session attr structures */
1282 0 : attr_p = sdp_p->sess_attrs_p;
1283 0 : while (attr_p != NULL) {
1284 0 : next_attr_p = attr_p->next_p;
1285 0 : sdp_free_attr(attr_p);
1286 0 : attr_p = next_attr_p;
1287 : }
1288 :
1289 : /* Free any mca structures */
1290 0 : mca_p = sdp_p->mca_p;
1291 0 : while (mca_p != NULL) {
1292 0 : next_mca_p = mca_p->next_p;
1293 :
1294 : /* Free any media attr structures */
1295 0 : attr_p = mca_p->media_attrs_p;
1296 0 : while (attr_p != NULL) {
1297 0 : next_attr_p = attr_p->next_p;
1298 0 : sdp_free_attr(attr_p);
1299 0 : attr_p = next_attr_p;
1300 : }
1301 :
1302 : /* Free the media profiles struct if allocated. */
1303 0 : if (mca_p->media_profiles_p != NULL) {
1304 0 : SDP_FREE(mca_p->media_profiles_p);
1305 : }
1306 :
1307 0 : bw_p = &(mca_p->bw);
1308 0 : bw_data_p = bw_p->bw_data_list;
1309 0 : while (bw_data_p != NULL) {
1310 0 : bw_p->bw_data_list = bw_data_p->next_p;
1311 0 : SDP_FREE(bw_data_p);
1312 0 : bw_data_p = bw_p->bw_data_list;
1313 : }
1314 :
1315 0 : SDP_FREE(mca_p);
1316 0 : mca_p = next_mca_p;
1317 : }
1318 :
1319 0 : SDP_FREE(sdp_p);
1320 :
1321 0 : return (SDP_SUCCESS);
1322 : }
1323 :
1324 : /*
1325 : * sdp_parse_error
1326 : * Send SDP parsing errors to log and up to peerconnection
1327 : */
1328 0 : void sdp_parse_error(sdp_t* sdp, const char *format, ...) {
1329 : flex_string fs;
1330 : va_list ap;
1331 :
1332 0 : flex_string_init(&fs);
1333 :
1334 0 : va_start(ap, format);
1335 0 : flex_string_vsprintf(&fs, format, ap);
1336 0 : va_end(ap);
1337 :
1338 0 : CSFLogError("SDP Parse", "SDP Parse Error %s, line %u", fs.buffer,
1339 : sdp->parse_line);
1340 :
1341 0 : if (sdp->conf_p->error_handler) {
1342 0 : sdp->conf_p->error_handler(sdp->conf_p->error_handler_context,
1343 : sdp->parse_line,
1344 0 : fs.buffer);
1345 : }
1346 :
1347 0 : flex_string_free(&fs);
1348 0 : }
|