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/. */
5 #include "sdp_os_defs.h"
7 #include "sdp_private.h"
11 static const char* logTag
= "sdp_main";
13 /* Note: These *must* be in the same order as the enum types. */
14 const sdp_tokenarray_t sdp_token
[SDP_MAX_TOKENS
] =
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
}
34 /* Note: These *must* be in the same order as the enum types. */
35 const sdp_attrarray_t sdp_attr
[SDP_MAX_ATTR_TYPES
] =
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 {"ssrc-group", sizeof("ssrc-group"), sdp_parse_attr_ssrc_group
,
210 sdp_build_attr_ssrc_group
},
211 {"rtcp-rsize", sizeof("rtcp-rsize"),
212 sdp_parse_attr_simple_flag
, sdp_build_attr_simple_flag
},
215 /* Note: These *must* be in the same order as the enum types. */
216 const sdp_namearray_t sdp_media
[SDP_MAX_MEDIA_TYPES
] =
218 {"audio", sizeof("audio")},
219 {"video", sizeof("video")},
220 {"application", sizeof("application")},
221 {"data", sizeof("data")},
222 {"control", sizeof("control")},
223 {"nas/radius", sizeof("nas/radius")},
224 {"nas/tacacs", sizeof("nas/tacacs")},
225 {"nas/diameter", sizeof("nas/diameter")},
226 {"nas/l2tp", sizeof("nas/l2tp")},
227 {"nas/login", sizeof("nas/login")},
228 {"nas/none", sizeof("nas/none")},
229 {"image", sizeof("image")},
230 {"text", sizeof("text")}
234 /* Note: These *must* be in the same order as the enum types. */
235 const sdp_namearray_t sdp_nettype
[SDP_MAX_NETWORK_TYPES
] =
237 {"IN", sizeof("IN")},
238 {"ATM", sizeof("ATM")},
239 {"FR", sizeof("FR")},
240 {"LOCAL", sizeof("LOCAL")}
244 /* Note: These *must* be in the same order as the enum types. */
245 const sdp_namearray_t sdp_addrtype
[SDP_MAX_ADDR_TYPES
] =
247 {"IP4", sizeof("IP4")},
248 {"IP6", sizeof("IP6")},
249 {"NSAP", sizeof("NSAP")},
250 {"EPN", sizeof("EPN")},
251 {"E164", sizeof("E164")},
252 {"GWID", sizeof("GWID")}
256 /* Note: These *must* be in the same order as the enum type. */
257 const sdp_namearray_t sdp_transport
[SDP_MAX_TRANSPORT_TYPES
] =
259 {"RTP/AVP", sizeof("RTP/AVP")},
260 {"udp", sizeof("udp")},
261 {"udptl", sizeof("udptl")},
262 {"ces10", sizeof("ces10")},
263 {"LOCAL", sizeof("LOCAL")},
264 {"AAL2/ITU", sizeof("AAL2/ITU")},
265 {"AAL2/ATMF", sizeof("AAL2/ATMF")},
266 {"AAL2/custom", sizeof("AAL2/custom")},
267 {"AAL1/AVP", sizeof("AAL1/AVP")},
268 {"udpsprt", sizeof("udpsprt")},
269 {"RTP/SAVP", sizeof("RTP/SAVP")},
270 {"tcp", sizeof("tcp")},
271 {"RTP/SAVPF", sizeof("RTP/SAVPF")},
272 {"DTLS/SCTP", sizeof("DTLS/SCTP")},
273 {"RTP/AVPF", sizeof("RTP/AVPF")},
274 {"UDP/TLS/RTP/SAVP", sizeof("UDP/TLS/RTP/SAVP")},
275 {"UDP/TLS/RTP/SAVPF", sizeof("UDP/TLS/RTP/SAVPF")},
276 {"TCP/DTLS/RTP/SAVP", sizeof("TCP/DTLS/RTP/SAVP")},
277 {"TCP/DTLS/RTP/SAVPF", sizeof("TCP/DTLS/RTP/SAVPF")},
278 {"UDP/DTLS/SCTP", sizeof("UDP/DTLS/SCTP")},
279 {"TCP/DTLS/SCTP", sizeof("TCP/DTLS/SCTP")},
282 /* Note: These *must* be in the same order as the enum type. */
283 const sdp_namearray_t sdp_encrypt
[SDP_MAX_ENCRYPT_TYPES
] =
285 {"clear", sizeof("clear")},
286 {"base64", sizeof("base64")},
287 {"uri", sizeof("uri")},
288 {"prompt", sizeof("prompt")}
291 /* Note: These *must* be in the same order as the enum type. */
292 const sdp_namearray_t sdp_payload
[SDP_MAX_STRING_PAYLOAD_TYPES
] =
294 {"t38", sizeof("t38")},
295 {"X-tmr", sizeof("X-tmr")},
296 {"T120", sizeof("T120")}
299 /* Note: These *must* be in the same order as the enum type. */
300 const sdp_namearray_t sdp_t38_rate
[SDP_T38_MAX_RATES
] =
302 {"localTCF", sizeof("localTCF")},
303 {"transferredTCF", sizeof("transferredTCF")},
304 {"unknown", sizeof("unknown")}
307 /* Note: These *must* be in the same order as the enum type. */
308 const sdp_namearray_t sdp_t38_udpec
[SDP_T38_MAX_UDPEC
] =
310 {"t38UDPRedundancy", sizeof("t38UDPRedundancy")},
311 {"t38UDPFEC", sizeof("t38UDPFEC")},
312 {"unknown", sizeof("unknown")}
315 /* Note: These *must* be in the same order as the enum type. */
316 const sdp_namearray_t sdp_qos_strength
[SDP_MAX_QOS_STRENGTH
] =
318 {"optional", sizeof("optional")},
319 {"mandatory", sizeof("mandatory")},
320 {"success", sizeof("success")},
321 {"failure", sizeof("failure")},
322 {"none", sizeof("none")}
325 /* Note: These *must* be in the same order as the enum type. */
326 const sdp_namearray_t sdp_qos_status_type
[SDP_MAX_QOS_STATUS_TYPES
] =
328 {"local", sizeof("local")},
329 {"remote", sizeof("remote")},
330 {"e2e", sizeof("e2e")}
333 /* Note: These *must* be in the same order as the enum type. */
334 const sdp_namearray_t sdp_curr_type
[SDP_MAX_CURR_TYPES
] =
336 {"qos", sizeof("qos")},
337 {"unknown", sizeof("unknown")}
340 /* Note: These *must* be in the same order as the enum type. */
341 const sdp_namearray_t sdp_des_type
[SDP_MAX_DES_TYPES
] =
343 {"qos", sizeof("qos")},
344 {"unknown", sizeof("unknown")}
347 /* Note: These *must* be in the same order as the enum type. */
348 const sdp_namearray_t sdp_conf_type
[SDP_MAX_CONF_TYPES
] =
350 {"qos", sizeof("qos")},
351 {"unknown", sizeof("unknown")}
353 /* Note: These *must* be in the same order as the enum type. */
354 const sdp_namearray_t sdp_qos_direction
[SDP_MAX_QOS_DIR
] =
356 {"send", sizeof("send")},
357 {"recv", sizeof("recv")},
358 {"sendrecv", sizeof("sendrecv")},
359 {"none", sizeof("none")}
362 /* Note: These *must* be in the same order as the enum type. */
363 const sdp_namearray_t sdp_silencesupp_pref
[SDP_MAX_SILENCESUPP_PREF
] = {
364 {"standard", sizeof("standard")},
365 {"custom", sizeof("custom")},
369 /* Note: These *must* be in the same order as the enum type. */
370 const sdp_namearray_t sdp_silencesupp_siduse
[SDP_MAX_SILENCESUPP_SIDUSE
] = {
371 {"No SID", sizeof("No SID")},
372 {"Fixed Noise", sizeof("Fixed Noise")},
373 {"Sampled Noise", sizeof("Sampled Noise")},
377 /* Note: These *must* be in the same order as the enum type. */
378 const sdp_namearray_t sdp_mediadir_role
[SDP_MAX_MEDIADIR_ROLES
] =
380 {"passive", sizeof("passive")},
381 {"active", sizeof("active")},
382 {"both", sizeof("both")},
383 {"reuse", sizeof("reuse")},
384 {"unknown", sizeof("unknown")}
387 /* Note: These *must* be in the same order as the enum type. */
388 const sdp_namearray_t sdp_fmtp_codec_param
[SDP_MAX_FMTP_PARAM
] =
390 {"annexa", sizeof("annexa")}, /* 0 */
391 {"annexb", sizeof("annexb")}, /* 1 */
392 {"bitrate", sizeof("bitrate")}, /* 2 */
393 {"QCIF", sizeof("QCIF")}, /* 3 */
394 {"CIF", sizeof("CIF")}, /* 4 */
395 {"MAXBR", sizeof("MAXBR")}, /* 5 */
396 {"SQCIF", sizeof("SQCIF")}, /* 6 */
397 {"CIF4", sizeof("CIF4")}, /* 7 */
398 {"CIF16", sizeof("CIF16")}, /* 8 */
399 {"CUSTOM", sizeof("CUSTOM")}, /* 9 */
400 {"PAR", sizeof("PAR")}, /* 10 */
401 {"CPCF", sizeof("CPCF")}, /* 11 */
402 {"BPP", sizeof("BPP")}, /* 12 */
403 {"HRD", sizeof("HRD")}, /* 13 */
404 {"PROFILE", sizeof("PROFILE")}, /* 14 */
405 {"LEVEL", sizeof("LEVEL")}, /* 15 */
406 {"INTERLACE", sizeof("INTERLACE")}, /* 16 */
409 {"profile-level-id", sizeof("profile-level-id")}, /* 17 */
410 {"sprop-parameter-sets", sizeof("sprop-parameter-sets")}, /* 18 */
411 {"packetization-mode", sizeof("packetization-mode")}, /* 19 */
412 {"sprop-interleaving-depth", sizeof("sprop-interleaving-depth")}, /* 20 */
413 {"sprop-deint-buf-req", sizeof("sprop-deint-buf-req")}, /* 21 */
414 {"sprop-max-don-diff", sizeof("sprop-max-don-diff")}, /* 22 */
415 {"sprop-init-buf-time", sizeof("sprop-init-buf-time")}, /* 23 */
417 {"max-mbps", sizeof("max-mbps")}, /* 24 */
418 {"max-fs", sizeof("max-fs")}, /* 25 */
419 {"max-cpb", sizeof("max-cpb")}, /* 26 */
420 {"max-dpb", sizeof("max-dpb")}, /* 27 */
421 {"max-br", sizeof("max-br")}, /* 28 */
422 {"redundant-pic-cap", sizeof("redundant-pic-cap")}, /* 29 */
423 {"deint-buf-cap", sizeof("deint-buf-cap")}, /* 30 */
424 {"max-rcmd-nalu-size", sizeof("max-rcmd_nali-size")}, /* 31 */
425 {"parameter-add", sizeof("parameter-add")}, /* 32 */
427 /* Annexes - require special handling */
428 {"D", sizeof("D")}, /* 33 */
429 {"F", sizeof("F")}, /* 34 */
430 {"I", sizeof("I")}, /* 35 */
431 {"J", sizeof("J")}, /* 36 */
432 {"T", sizeof("T")}, /* 37 */
433 {"K", sizeof("K")}, /* 38 */
434 {"N", sizeof("N")}, /* 39 */
435 {"P", sizeof("P")}, /* 40 */
437 {"mode", sizeof("mode")}, /* 41 */
438 {"level-asymmetry-allowed", sizeof("level-asymmetry-allowed")}, /* 42 */
439 {"maxaveragebitrate", sizeof("maxaveragebitrate")}, /* 43 */
440 {"usedtx", sizeof("usedtx")}, /* 44 */
441 {"stereo", sizeof("stereo")}, /* 45 */
442 {"useinbandfec", sizeof("useinbandfec")}, /* 46 */
443 {"maxcodedaudiobandwidth", sizeof("maxcodedaudiobandwidth")}, /* 47 */
444 {"cbr", sizeof("cbr")}, /* 48 */
445 {"max-fr", sizeof("max-fr")}, /* 49 */
446 {"maxplaybackrate", sizeof("maxplaybackrate")}, /* 50 */
447 {"apt", sizeof("apt")}, /* 51 */
448 {"rtx-time", sizeof("rtx-time")} /* 52 */
451 /* Note: These *must* be in the same order as the enum type. */
452 const sdp_namearray_t sdp_fmtp_codec_param_val
[SDP_MAX_FMTP_PARAM_VAL
] =
454 {"yes", sizeof("yes")},
458 const sdp_namearray_t sdp_bw_modifier_val
[SDP_MAX_BW_MODIFIER_VAL
] =
460 {"AS", sizeof("AS")},
461 {"CT", sizeof("CT")},
462 {"TIAS", sizeof("TIAS")}
465 const sdp_namearray_t sdp_group_attr_val
[SDP_MAX_GROUP_ATTR_VAL
] =
467 {"FID", sizeof("FID")},
468 {"LS", sizeof("LS")},
469 {"ANAT", sizeof("ANAT")},
470 {"BUNDLE", sizeof("BUNDLE")}
473 const sdp_namearray_t sdp_ssrc_group_attr_val
[SDP_MAX_SSRC_GROUP_ATTR_VAL
] = {
474 {"DUP", sizeof("DUP")},
475 {"FEC", sizeof("FEC")},
476 {"FEC-FR", sizeof("FEC-FR")},
477 {"FID", sizeof("FID")},
478 {"SIM", sizeof("SIM")}
481 const sdp_namearray_t sdp_srtp_context_crypto_suite
[SDP_SRTP_MAX_NUM_CRYPTO_SUITES
] =
483 {"UNKNOWN_CRYPTO_SUITE", sizeof("UNKNOWN_CRYPTO_SUITE")},
484 {"AES_CM_128_HMAC_SHA1_32", sizeof("AES_CM_128_HMAC_SHA1_32")},
485 {"AES_CM_128_HMAC_SHA1_80", sizeof("AES_CM_128_HMAC_SHA1_80")},
486 {"F8_128_HMAC_SHA1_80", sizeof("F8_128_HMAC_SHA1_80")}
489 /* Maintain the same order as defined in typedef sdp_src_filter_mode_e */
490 const sdp_namearray_t sdp_src_filter_mode_val
[SDP_MAX_FILTER_MODE
] =
492 {"incl", sizeof("incl")},
493 {"excl", sizeof("excl")}
496 /* Maintain the same order as defined in typdef sdp_rtcp_unicast_mode_e */
497 const sdp_namearray_t sdp_rtcp_unicast_mode_val
[SDP_RTCP_MAX_UNICAST_MODE
] =
499 {"reflection", sizeof("reflection")},
500 {"rsi", sizeof("rsi")}
503 #define SDP_NAME(x) {x, sizeof(x)}
504 /* Maintain the same order as defined in typdef sdp_rtcp_fb_type_e */
505 const sdp_namearray_t sdp_rtcp_fb_type_val
[SDP_MAX_RTCP_FB
] =
511 SDP_NAME("goog-remb"),
512 SDP_NAME("transport-cc")
515 /* Maintain the same order as defined in typdef sdp_rtcp_fb_nack_type_e */
516 const sdp_namearray_t sdp_rtcp_fb_nack_type_val
[SDP_MAX_RTCP_FB_NACK
] =
529 /* Maintain the same order as defined in typdef sdp_rtcp_fb_ack_type_e */
530 const sdp_namearray_t sdp_rtcp_fb_ack_type_val
[SDP_MAX_RTCP_FB_ACK
] =
536 /* Maintain the same order as defined in typdef sdp_rtcp_fb_ccm_type_e */
537 const sdp_namearray_t sdp_rtcp_fb_ccm_type_val
[SDP_MAX_RTCP_FB_CCM
] =
545 /* Maintain the same order as defined in typedef sdp_setup_type_e */
546 const sdp_namearray_t sdp_setup_type_val
[SDP_MAX_SETUP
] =
554 /* Maintain the same order as defined in typedef sdp_connection_type_e */
555 const sdp_namearray_t sdp_connection_type_val
[SDP_MAX_CONNECTION
] =
561 /* Maintain same order as defined in typedef sdp_srtp_crypto_suite_t */
562 const sdp_srtp_crypto_suite_list sdp_srtp_crypto_suite_array
[SDP_SRTP_MAX_NUM_CRYPTO_SUITES
] =
564 {SDP_SRTP_UNKNOWN_CRYPTO_SUITE
, UNKNOWN_CRYPTO_SUITE
, 0, 0},
565 {SDP_SRTP_AES_CM_128_HMAC_SHA1_32
, AES_CM_128_HMAC_SHA1_32
,
566 SDP_SRTP_AES_CM_128_HMAC_SHA1_32_KEY_BYTES
,
567 SDP_SRTP_AES_CM_128_HMAC_SHA1_32_SALT_BYTES
},
568 {SDP_SRTP_AES_CM_128_HMAC_SHA1_80
, AES_CM_128_HMAC_SHA1_80
,
569 SDP_SRTP_AES_CM_128_HMAC_SHA1_80_KEY_BYTES
,
570 SDP_SRTP_AES_CM_128_HMAC_SHA1_80_SALT_BYTES
},
571 {SDP_SRTP_F8_128_HMAC_SHA1_80
, F8_128_HMAC_SHA1_80
,
572 SDP_SRTP_F8_128_HMAC_SHA1_80_KEY_BYTES
,
573 SDP_SRTP_F8_128_HMAC_SHA1_80_SALT_BYTES
}
576 const char* sdp_result_name
[SDP_MAX_RC
] =
579 "SDP_INVALID_SDP_PTR",
580 "SDP_NOT_SDP_DESCRIPTION",
581 "SDP_INVALID_TOKEN_ORDERING",
582 "SDP_INVALID_PARAMETER",
583 "SDP_INVALID_MEDIA_LEVEL",
584 "SDP_INVALID_CAPABILITY",
586 "SDP_UNRECOGNIZED_TOKEN",
588 "SDP_POTENTIAL_SDP_OVERFLOW",
591 const char *sdp_get_result_name ( sdp_result_e rc
)
593 if (rc
>= SDP_MAX_RC
) {
594 return ("Invalid SDP result code");
596 return (sdp_result_name
[rc
]);
600 const char *sdp_get_attr_name ( sdp_attr_e attr_type
)
602 if (attr_type
>= SDP_MAX_ATTR_TYPES
) {
603 return ("Invalid attribute type");
605 return (sdp_attr
[attr_type
].name
);
609 const char *sdp_get_media_name ( sdp_media_e media_type
)
611 if (media_type
== SDP_MEDIA_UNSUPPORTED
) {
612 return (SDP_UNSUPPORTED
);
613 } else if (media_type
>= SDP_MAX_MEDIA_TYPES
) {
614 return ("Invalid media type");
616 return (sdp_media
[media_type
].name
);
620 const char *sdp_get_network_name ( sdp_nettype_e network_type
)
622 if (network_type
== SDP_NT_UNSUPPORTED
) {
623 return (SDP_UNSUPPORTED
);
624 } else if (network_type
>= SDP_MAX_NETWORK_TYPES
) {
625 return ("Invalid network type");
627 return (sdp_nettype
[network_type
].name
);
631 const char *sdp_get_address_name ( sdp_addrtype_e addr_type
)
633 if (addr_type
== SDP_AT_UNSUPPORTED
) {
634 return (SDP_UNSUPPORTED
);
635 } else if (addr_type
>= SDP_MAX_ADDR_TYPES
) {
636 if (addr_type
== SDP_AT_FQDN
) {
639 return ("Invalid address type");
642 return (sdp_addrtype
[addr_type
].name
);
646 const char *sdp_get_transport_name ( sdp_transport_e transport_type
)
648 if (transport_type
== SDP_TRANSPORT_UNSUPPORTED
) {
649 return (SDP_UNSUPPORTED
);
650 } else if (transport_type
>= SDP_MAX_TRANSPORT_TYPES
) {
651 return ("Invalid transport type");
653 return (sdp_transport
[transport_type
].name
);
657 const char *sdp_get_encrypt_name ( sdp_encrypt_type_e encrypt_type
)
659 if (encrypt_type
== SDP_ENCRYPT_UNSUPPORTED
) {
660 return (SDP_UNSUPPORTED
);
661 } else if (encrypt_type
>= SDP_MAX_ENCRYPT_TYPES
) {
662 return ("Invalid encryption type");
664 return (sdp_encrypt
[encrypt_type
].name
);
668 const char *sdp_get_payload_name ( sdp_payload_e payload
)
670 if (payload
== SDP_PAYLOAD_UNSUPPORTED
) {
671 return (SDP_UNSUPPORTED
);
672 } else if (payload
>= SDP_MAX_STRING_PAYLOAD_TYPES
) {
673 return ("Invalid payload type");
675 return (sdp_payload
[payload
].name
);
679 const char *sdp_get_t38_ratemgmt_name ( sdp_t38_ratemgmt_e rate
)
681 if (rate
>= SDP_T38_MAX_RATES
) {
682 return ("Invalid rate");
684 return (sdp_t38_rate
[rate
].name
);
688 const char *sdp_get_t38_udpec_name ( sdp_t38_udpec_e udpec
)
690 if (udpec
>= SDP_T38_MAX_UDPEC
) {
691 return ("Invalid udpec");
693 return (sdp_t38_udpec
[udpec
].name
);
697 const char *sdp_get_qos_strength_name ( sdp_qos_strength_e strength
)
699 if (strength
>= SDP_MAX_QOS_STRENGTH
) {
700 return ("Invalid qos strength");
702 return (sdp_qos_strength
[strength
].name
);
706 const char *sdp_get_qos_direction_name ( sdp_qos_dir_e direction
)
708 if (direction
>= SDP_MAX_QOS_DIR
) {
709 return ("Invalid qos direction");
711 return (sdp_qos_direction
[direction
].name
);
715 const char *sdp_get_qos_status_type_name ( sdp_qos_status_types_e status_type
)
717 if (status_type
>= SDP_MAX_QOS_STATUS_TYPES
) {
718 return ("Invalid qos status type");
720 return (sdp_qos_status_type
[status_type
].name
);
724 const char *sdp_get_curr_type_name (sdp_curr_type_e curr_type
)
726 if (curr_type
>= SDP_MAX_CURR_TYPES
) {
727 return ("Invalid curr type");
729 return (sdp_curr_type
[curr_type
].name
);
733 const char *sdp_get_des_type_name (sdp_des_type_e des_type
)
735 if (des_type
>= SDP_MAX_DES_TYPES
) {
736 return ("Invalid des type");
738 return (sdp_des_type
[des_type
].name
);
742 const char *sdp_get_conf_type_name (sdp_conf_type_e conf_type
)
744 if (conf_type
>= SDP_MAX_CONF_TYPES
) {
745 return ("Invalid conf type");
747 return (sdp_conf_type
[conf_type
].name
);
751 const char *sdp_get_silencesupp_pref_name (sdp_silencesupp_pref_e pref
)
753 if (pref
>= SDP_MAX_SILENCESUPP_PREF
) {
754 return ("Invalid silencesupp pref");
756 return (sdp_silencesupp_pref
[pref
].name
);
760 const char *sdp_get_silencesupp_siduse_name (sdp_silencesupp_siduse_e siduse
)
762 if (siduse
>= SDP_MAX_SILENCESUPP_SIDUSE
) {
763 return ("Invalid silencesupp siduse");
765 return (sdp_silencesupp_siduse
[siduse
].name
);
769 const char *sdp_get_mediadir_role_name (sdp_mediadir_role_e role
)
771 if (role
>= SDP_MEDIADIR_ROLE_UNKNOWN
) {
772 return ("Invalid media direction role");
774 return (sdp_mediadir_role
[role
].name
);
779 const char *sdp_get_bw_modifier_name (sdp_bw_modifier_e bw_modifier_type
)
781 if (bw_modifier_type
== SDP_BW_MODIFIER_UNSUPPORTED
) {
782 return (SDP_UNSUPPORTED
);
783 } else if (bw_modifier_type
< SDP_BW_MODIFIER_AS
||
784 bw_modifier_type
>= SDP_MAX_BW_MODIFIER_VAL
) {
785 return ("Invalid bw modifier type");
787 return (sdp_bw_modifier_val
[bw_modifier_type
].name
);
791 const char *sdp_get_group_attr_name (sdp_group_attr_e group_attr_type
)
793 if (group_attr_type
== SDP_GROUP_ATTR_UNSUPPORTED
) {
794 return (SDP_UNSUPPORTED
);
795 } else if (group_attr_type
>= SDP_MAX_GROUP_ATTR_VAL
) {
796 return ("Invalid a=group: attribute type");
798 return (sdp_group_attr_val
[group_attr_type
].name
);
802 const char *sdp_get_ssrc_group_attr_name(
803 sdp_ssrc_group_attr_e ssrc_group_attr_type
) {
804 if (ssrc_group_attr_type
== SDP_SSRC_GROUP_ATTR_UNSUPPORTED
) {
805 return (SDP_UNSUPPORTED
);
806 } else if (ssrc_group_attr_type
>= SDP_MAX_SSRC_GROUP_ATTR_VAL
) {
807 return ("Invalid a=ssrc-group: attribute type");
809 return (sdp_ssrc_group_attr_val
[ssrc_group_attr_type
].name
);
813 const char *sdp_get_src_filter_mode_name (sdp_src_filter_mode_e type
)
815 if (type
>= SDP_MAX_FILTER_MODE
) {
816 return ("Invalid source filter mode");
818 return (sdp_src_filter_mode_val
[type
].name
);
822 const char *sdp_get_rtcp_unicast_mode_name (sdp_rtcp_unicast_mode_e type
)
824 if (type
>= SDP_RTCP_MAX_UNICAST_MODE
) {
825 return ("Invalid rtcp unicast mode");
827 return (sdp_rtcp_unicast_mode_val
[type
].name
);
831 /* Function: sdp_init_description
832 * Description: Allocates a new SDP structure that can be used for either
833 * parsing or building an SDP description. This routine
834 * saves the config pointer passed in the SDP structure so
835 * SDP will know how to parse/build based on the options defined.
836 * An SDP structure must be allocated before parsing or building
837 * since the handle must be passed to these routines.
838 * Parameters: config_p The config handle returned by sdp_init_config
839 * Returns: A handle for a new SDP structure as a void ptr.
841 sdp_t
*sdp_init_description (sdp_conf_options_t
*conf_p
)
850 sdp_p
= (sdp_t
*)SDP_MALLOC(sizeof(sdp_t
));
855 sdp_p
->conf_p
= conf_p
;
856 sdp_p
->version
= SDP_CURRENT_VERSION
;
857 sdp_p
->owner_name
[0] = '\0';
858 sdp_p
->owner_sessid
[0] = '\0';
859 sdp_p
->owner_version
[0] = '\0';
860 sdp_p
->owner_network_type
= SDP_NT_INVALID
;
861 sdp_p
->owner_addr_type
= SDP_AT_INVALID
;
862 sdp_p
->owner_addr
[0] = '\0';
863 sdp_p
->sessname
[0] = '\0';
864 sdp_p
->sessinfo_found
= FALSE
;
865 sdp_p
->uri_found
= FALSE
;
867 sdp_p
->default_conn
.nettype
= SDP_NT_INVALID
;
868 sdp_p
->default_conn
.addrtype
= SDP_AT_INVALID
;
869 sdp_p
->default_conn
.conn_addr
[0] = '\0';
870 sdp_p
->default_conn
.is_multicast
= FALSE
;
871 sdp_p
->default_conn
.ttl
= 0;
872 sdp_p
->default_conn
.num_of_addresses
= 0;
874 sdp_p
->bw
.bw_data_count
= 0;
875 sdp_p
->bw
.bw_data_list
= NULL
;
877 sdp_p
->timespec_p
= NULL
;
878 sdp_p
->sess_attrs_p
= NULL
;
880 sdp_p
->mca_count
= 0;
882 /* Set default debug flags from application config. */
883 for (i
=0; i
< SDP_MAX_DEBUG_TYPES
; i
++) {
884 sdp_p
->debug_flag
[i
] = conf_p
->debug_flag
[i
];
891 /* Function: void sdp_debug(sdp_t *sdp_p, sdp_debug_e debug_type,
893 * Description: Define the type of debug for this particular SDP structure.
894 * By default, each SDP description has the settings that are
895 * set for the application.
896 * Valid debug types are ERRORS, WARNINGS, and TRACE. Each
897 * debug type can be turned on/off individually. The
898 * debug level can be redefined at any time.
899 * Parameters: sdp_ptr The SDP handle returned by sdp_init_description.
900 * debug_type Specifies the debug type being enabled/disabled.
901 * my_bool Defines whether the debug should be enabled or not.
904 void sdp_debug (sdp_t
*sdp_p
, sdp_debug_e debug_type
, tinybool debug_flag
)
910 if (debug_type
< SDP_MAX_DEBUG_TYPES
) {
911 sdp_p
->debug_flag
[debug_type
] = debug_flag
;
916 /* Function: void sdp_set_string_debug(sdp_t *sdp_p, char *debug_str)
917 * Description: Define a string to be associated with all debug output
918 * for this SDP. The string will be copied into the SDP
919 * structure and so the library will not be dependent on
920 * the application's memory for this string.
921 * Parameters: sdp_p The SDP handle returned by sdp_init_description.
922 * debug_str Pointer to a string that should be printed out
923 * with every debug msg.
926 void sdp_set_string_debug (sdp_t
*sdp_p
, const char *debug_str
)
932 sstrncpy(sdp_p
->debug_str
, debug_str
, sizeof(sdp_p
->debug_str
));
936 /* Function: sdp_validate_sdp
937 * Description: Validate an SDP structure.
938 * Parameters: sdp_p The SDP handle of the struct to validate.
939 * Returns: A result value indicating if the validation was successful.
940 * If not, what type of error was encountered.
942 sdp_result_e
sdp_validate_sdp (sdp_t
*sdp_p
)
945 uint16_t num_media_levels
;
947 /* Need to validate c= info is specified at session level or
950 if (sdp_connection_valid((void *)sdp_p
, SDP_SESSION_LEVEL
) == FALSE
) {
951 num_media_levels
= sdp_get_num_media_lines((void *)sdp_p
);
952 for (i
=1; i
<= num_media_levels
; i
++) {
953 if (sdp_connection_valid((void *)sdp_p
, (unsigned short)i
) == FALSE
) {
954 sdp_parse_error(sdp_p
,
955 "%s c= connection line not specified for "
956 "every media level, validation failed.",
958 return (SDP_FAILURE
);
963 /* Validate required lines were specified */
964 if ((sdp_owner_valid((void *)sdp_p
) == FALSE
) &&
965 (sdp_p
->conf_p
->owner_reqd
== TRUE
)) {
966 sdp_parse_error(sdp_p
,
967 "%s o= owner line not specified, validation failed.",
969 return (SDP_FAILURE
);
972 if ((sdp_session_name_valid((void *)sdp_p
) == FALSE
) &&
973 (sdp_p
->conf_p
->session_name_reqd
== TRUE
)) {
974 sdp_parse_error(sdp_p
,
975 "%s s= session name line not specified, validation failed.",
977 return (SDP_FAILURE
);
980 if ((sdp_timespec_valid((void *)sdp_p
) == FALSE
) &&
981 (sdp_p
->conf_p
->timespec_reqd
== TRUE
)) {
982 sdp_parse_error(sdp_p
,
983 "%s t= timespec line not specified, validation failed.",
985 return (SDP_FAILURE
);
988 return (SDP_SUCCESS
);
991 /* Function: sdp_parse
992 * Description: Parse an SDP description in the specified buffer.
993 * Parameters: sdp_p The SDP handle returned by sdp_init_description
994 * bufp Pointer to the buffer containing the SDP
995 * description to parse.
996 * len The length of the buffer.
997 * Returns: A result value indicating if the parse was successful and
998 * if not, what type of error was encountered. The
999 * information from the parse is stored in the sdp_p structure.
1001 sdp_result_e
sdp_parse (sdp_t
*sdp_p
, const char *buf
, size_t len
)
1004 uint16_t cur_level
= SDP_SESSION_LEVEL
;
1006 const char *next_ptr
= NULL
;
1008 sdp_token_e last_token
= SDP_TOKEN_V
;
1009 sdp_result_e result
= SDP_SUCCESS
;
1010 tinybool parse_done
= FALSE
;
1011 tinybool end_found
= FALSE
;
1012 tinybool first_line
= TRUE
;
1013 tinybool unrec_token
= FALSE
;
1014 const char **bufp
= &buf
;
1017 return (SDP_INVALID_SDP_PTR
);
1020 if ((bufp
== NULL
) || (*bufp
== NULL
)) {
1021 return (SDP_NULL_BUF_PTR
);
1024 if (sdp_p
->debug_flag
[SDP_DEBUG_TRACE
]) {
1025 SDP_PRINT("%s Trace SDP Parse:", sdp_p
->debug_str
);
1029 sdp_p
->conf_p
->num_parses
++;
1031 /* Initialize the last valid capability instance to zero. Used
1032 * to help in parsing X-cpar attrs. */
1033 sdp_p
->cap_valid
= FALSE
;
1034 sdp_p
->last_cap_inst
= 0;
1036 sdp_p
->parse_line
= 0;
1038 /* We want to try to find the end of the SDP description, even if
1039 * we find a parsing error.
1041 while (!end_found
) {
1042 /* If the last char of this line goes beyond the end of the buffer,
1043 * we don't parse it.
1046 sdp_p
->parse_line
++;
1047 line_end
= sdp_findchar(ptr
, "\n");
1048 if ((line_end
>= (*bufp
+ len
)) ||
1049 (*line_end
== '\0')) {
1050 /* As this does not update the result value the SDP up to this point
1051 * is still accept as valid. So encountering this is not treated as
1054 sdp_parse_error(sdp_p
,
1055 "%s End of line beyond end of buffer.",
1057 SDPLogError(logTag
, "SDP: Invalid SDP, no \\n (len %u): %*s",
1058 (unsigned)len
, (int)len
, *bufp
);
1063 /* Print the line if we're tracing. */
1064 if ((parse_done
== FALSE
) &&
1065 (sdp_p
->debug_flag
[SDP_DEBUG_TRACE
])) {
1066 SDP_PRINT("%s ", sdp_p
->debug_str
);
1068 SDP_PRINT("%*s", (int)(line_end
- ptr
), ptr
);
1072 /* Find out which token this line has, if any. */
1073 for (i
=0; i
< SDP_MAX_TOKENS
; i
++) {
1074 if (strncmp(ptr
, sdp_token
[i
].name
, SDP_TOKEN_LEN
) == 0) {
1078 if (i
== SDP_MAX_TOKENS
) {
1079 /* See if the second char on the next line is an '=' char.
1080 * If so, we note this as an unrecognized token line. */
1081 if (ptr
[1] == '=') {
1084 if (first_line
== TRUE
) {
1085 sdp_parse_error(sdp_p
,
1086 "%s Attempt to parse text not recognized as "
1087 "SDP text, parse fails.", sdp_p
->debug_str
);
1088 /* If we haven't already printed out the line we
1089 * were trying to parse, do it now.
1091 if (!sdp_p
->debug_flag
[SDP_DEBUG_TRACE
]) {
1092 SDP_PRINT("%s ", sdp_p
->debug_str
);
1093 SDP_PRINT("%*s", (int)(line_end
- ptr
), ptr
);
1095 sdp_p
->conf_p
->num_not_sdp_desc
++;
1096 return (SDP_NOT_SDP_DESCRIPTION
);
1103 /* This is the beginning of a new SDP description. */
1104 if ((first_line
!= TRUE
) && (i
== SDP_TOKEN_V
)) {
1109 /* Advance the next ptr to one char beyond the end of the line. */
1110 next_ptr
= line_end
+ 1;
1111 if (next_ptr
>= (*bufp
+ len
)) {
1115 /* If we've finished parsing and are just looking for the end of
1116 * the SDP description, we don't need to do anything else here.
1118 if (parse_done
== TRUE
) {
1122 /* Only certain tokens are valid at the media level. */
1123 if (cur_level
!= SDP_SESSION_LEVEL
) {
1124 if ((i
!= SDP_TOKEN_I
) && (i
!= SDP_TOKEN_C
) &&
1125 (i
!= SDP_TOKEN_B
) && (i
!= SDP_TOKEN_K
) &&
1126 (i
!= SDP_TOKEN_A
) && (i
!= SDP_TOKEN_M
)) {
1127 sdp_p
->conf_p
->num_invalid_token_order
++;
1128 sdp_parse_error(sdp_p
,
1129 "%s Warning: Invalid token %s found at media level",
1130 sdp_p
->debug_str
, sdp_token
[i
].name
);
1135 /* Verify the token ordering. */
1136 if (first_line
== TRUE
) {
1137 if (i
!= SDP_TOKEN_V
) {
1138 if (sdp_p
->conf_p
->version_reqd
== TRUE
) {
1139 sdp_parse_error(sdp_p
,
1140 "%s First line not v=, parse fails",
1142 sdp_p
->conf_p
->num_invalid_token_order
++;
1143 result
= SDP_INVALID_TOKEN_ORDERING
;
1146 last_token
= (sdp_token_e
)i
;
1149 last_token
= (sdp_token_e
)i
;
1153 if (i
< last_token
) {
1154 sdp_p
->conf_p
->num_invalid_token_order
++;
1155 sdp_parse_error(sdp_p
,
1156 "%s Warning: Invalid token ordering detected, "
1157 "token %s found after token %s", sdp_p
->debug_str
,
1158 sdp_token
[i
].name
, sdp_token
[last_token
].name
);
1162 /* Finally parse the line. */
1163 ptr
+= SDP_TOKEN_LEN
;
1164 result
= sdp_token
[i
].parse_func(sdp_p
, cur_level
, (const char *)ptr
);
1165 last_token
= (sdp_token_e
)i
;
1166 if (last_token
== SDP_TOKEN_M
) {
1167 if (cur_level
== SDP_SESSION_LEVEL
) {
1172 /* The token ordering can start again at i= */
1173 last_token
= (sdp_token_e
)(SDP_TOKEN_I
- 1);
1175 if (result
!= SDP_SUCCESS
) {
1179 /* Skip the new line char at the end of this line and see if
1180 * this is the end of the buffer.
1182 if ((line_end
+ 1) == (*bufp
+ len
)) {
1187 /* If we found no valid lines, return an error. */
1188 if (first_line
== TRUE
) {
1189 sdp_p
->conf_p
->num_not_sdp_desc
++;
1190 return (SDP_NOT_SDP_DESCRIPTION
);
1193 /* If no errors were found yet, validate the overall sdp. */
1194 if (result
== SDP_SUCCESS
) {
1195 result
= sdp_validate_sdp(sdp_p
);
1197 /* Return the pointer where we left off. */
1199 /* If the SDP is valid, but the next line following was an
1200 * unrecognized <token>= line, indicate this on the return. */
1201 if ((result
== SDP_SUCCESS
) && (unrec_token
== TRUE
)) {
1202 return (SDP_UNRECOGNIZED_TOKEN
);
1209 /* Function: sdp_build
1210 * Description: Build an SDP description in the specified buffer based
1211 * on the information in the given SDP structure.
1212 * Parameters: sdp_p The SDP handle returned by sdp_init_description
1213 * fs A flex_string where the SDP description should be built.
1214 * Returns: A result value indicating if the build was successful and
1215 * if not, what type of error was encountered - e.g.,
1216 * description was too long for the given buffer.
1218 sdp_result_e
sdp_build (sdp_t
*sdp_p
, flex_string
*fs
)
1221 sdp_result_e result
= SDP_SUCCESS
;
1224 return (SDP_INVALID_SDP_PTR
);
1228 return (SDP_NULL_BUF_PTR
);
1231 if (sdp_p
->debug_flag
[SDP_DEBUG_TRACE
]) {
1232 SDP_PRINT("%s Trace SDP Build:", sdp_p
->debug_str
);
1235 sdp_p
->conf_p
->num_builds
++;
1237 for (i
=0; ((i
< SDP_TOKEN_M
) &&
1238 (result
== SDP_SUCCESS
)); i
++) {
1239 result
= sdp_token
[i
].build_func(sdp_p
, SDP_SESSION_LEVEL
, fs
);
1240 /* ok not to check buffer space (yet) as the if() checks it */
1242 /* If the session level was ok, build the media lines. */
1243 if (result
== SDP_SUCCESS
) {
1244 for (i
=1; ((i
<= sdp_p
->mca_count
) &&
1245 (result
== SDP_SUCCESS
)); i
++) {
1246 result
= sdp_token
[SDP_TOKEN_M
].build_func(sdp_p
, (uint16_t)i
, fs
);
1248 /* ok not to check buffer space (yet) as the for() checks it */
1250 ((j
< SDP_TOKEN_M
) && (result
== SDP_SUCCESS
));
1252 if ((j
== SDP_TOKEN_U
) || (j
== SDP_TOKEN_E
) ||
1253 (j
== SDP_TOKEN_P
) || (j
== SDP_TOKEN_T
) ||
1254 (j
== SDP_TOKEN_R
) || (j
== SDP_TOKEN_Z
)) {
1255 /* These tokens not valid at media level. */
1258 result
= sdp_token
[j
].build_func(sdp_p
, (uint16_t)i
, fs
);
1259 /* ok not to check buffer space (yet) as the for() checks it */
1267 /* Function: sdp_free_description
1268 * Description: Free an SDP description and all memory associated with it.
1269 * Parameters: sdp_p The SDP handle returned by sdp_init_description
1270 * Returns: A result value indicating if the free was successful and
1271 * if not, what type of error was encountered - e.g., sdp_p
1272 * was invalid and didn't point to an SDP structure.
1274 sdp_result_e
sdp_free_description (sdp_t
*sdp_p
)
1276 sdp_timespec_t
*time_p
, *next_time_p
;
1277 sdp_attr_t
*attr_p
, *next_attr_p
;
1278 sdp_mca_t
*mca_p
, *next_mca_p
;
1280 sdp_bw_data_t
*bw_data_p
;
1283 return (SDP_INVALID_SDP_PTR
);
1286 /* Free the config structure */
1287 sdp_free_config(sdp_p
->conf_p
);
1289 /* Free any timespec structures - should be only one since
1290 * this is all we currently support.
1292 time_p
= sdp_p
->timespec_p
;
1293 while (time_p
!= NULL
) {
1294 next_time_p
= time_p
->next_p
;
1296 time_p
= next_time_p
;
1299 bw_p
= &(sdp_p
->bw
);
1300 bw_data_p
= bw_p
->bw_data_list
;
1301 while (bw_data_p
!= NULL
) {
1302 bw_p
->bw_data_list
= bw_data_p
->next_p
;
1303 SDP_FREE(bw_data_p
);
1304 bw_data_p
= bw_p
->bw_data_list
;
1307 /* Free any session attr structures */
1308 attr_p
= sdp_p
->sess_attrs_p
;
1309 while (attr_p
!= NULL
) {
1310 next_attr_p
= attr_p
->next_p
;
1311 sdp_free_attr(attr_p
);
1312 attr_p
= next_attr_p
;
1315 /* Free any mca structures */
1316 mca_p
= sdp_p
->mca_p
;
1317 while (mca_p
!= NULL
) {
1318 next_mca_p
= mca_p
->next_p
;
1320 /* Free any media attr structures */
1321 attr_p
= mca_p
->media_attrs_p
;
1322 while (attr_p
!= NULL
) {
1323 next_attr_p
= attr_p
->next_p
;
1324 sdp_free_attr(attr_p
);
1325 attr_p
= next_attr_p
;
1328 /* Free the media profiles struct if allocated. */
1329 if (mca_p
->media_profiles_p
!= NULL
) {
1330 SDP_FREE(mca_p
->media_profiles_p
);
1333 bw_p
= &(mca_p
->bw
);
1334 bw_data_p
= bw_p
->bw_data_list
;
1335 while (bw_data_p
!= NULL
) {
1336 bw_p
->bw_data_list
= bw_data_p
->next_p
;
1337 SDP_FREE(bw_data_p
);
1338 bw_data_p
= bw_p
->bw_data_list
;
1347 return (SDP_SUCCESS
);
1352 * Send SDP parsing errors to log and up to peerconnection
1354 void sdp_parse_error(sdp_t
* sdp
, const char *format
, ...) {
1358 flex_string_init(&fs
);
1360 va_start(ap
, format
);
1361 flex_string_vsprintf(&fs
, format
, ap
);
1364 SDPLogError("SDP Parse", "SDP Parse Error %s, line %u", fs
.buffer
,
1367 if (sdp
->conf_p
->error_handler
) {
1368 sdp
->conf_p
->error_handler(sdp
->conf_p
->error_handler_context
,
1373 flex_string_free(&fs
);