4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Contains implementation of various interfaces exported by library
41 #include "sdp_parse.h"
42 #include "commp_util.h"
44 #define FIELD_EQUALS_CRLF_LEN 4 /* first two characters and CRLF */
46 #define SDP_ATTR_TO_STR(m_attr) { \
47 while ((m_attr) != NULL) { \
48 if ((m_attr)->a_value != NULL) { \
49 wrote = snprintf(buf, len, "a=%s%c%s%s", \
50 (m_attr)->a_name, COMMP_COLON, (m_attr)-> \
51 a_value, COMMP_CRLF); \
53 wrote = snprintf(buf, len, "a=%s%s", (m_attr)-> \
54 a_name, COMMP_CRLF); \
58 (m_attr) = (m_attr)->a_next; \
62 #define SDP_KEY_TO_STR(m_key) { \
63 if ((m_key) != NULL) { \
64 if ((m_key)->k_enckey != NULL) { \
65 wrote = snprintf(buf, len, "k=%s%c%s%s", \
66 (m_key)->k_method, COMMP_COLON, (m_key)-> \
67 k_enckey, COMMP_CRLF); \
69 wrote = snprintf(buf, len, "k=%s%s", (m_key)-> \
70 k_method, COMMP_CRLF); \
77 #define SDP_BANDWIDTH_TO_STR(m_bw) { \
78 while ((m_bw) != NULL) { \
79 wrote = snprintf(buf, len, "b=%s%c%llu%s", (m_bw)-> \
80 b_type, COMMP_COLON, (m_bw)->b_value, COMMP_CRLF); \
83 (m_bw) = (m_bw)->b_next; \
87 #define SDP_INFORMATION_TO_STR(m_info) { \
88 if ((m_info) != NULL) { \
89 wrote = snprintf(buf, len, "i=%s%s", (m_info), COMMP_CRLF); \
95 #define SDP_CONNECTION_TO_STR(m_conn) { \
96 while ((m_conn) != NULL) { \
97 if (strcasecmp((m_conn)->c_addrtype, \
98 COMMP_ADDRTYPE_IP4) == 0) { \
99 if ((m_conn)->c_addrcount > 1) { \
100 wrote = snprintf(buf, len, "c=%s %s %s/%d/%d" \
101 "%s", (m_conn)->c_nettype, (m_conn)-> \
102 c_addrtype, (m_conn)->c_address, (m_conn)->\
103 c_ttl, (m_conn)->c_addrcount, COMMP_CRLF); \
104 } else if ((m_conn)->c_addrcount == 1) { \
105 wrote = snprintf(buf, len, "c=%s %s %s/%d%s", \
106 (m_conn)->c_nettype, (m_conn)->c_addrtype, \
107 (m_conn)->c_address, (m_conn)->c_ttl, \
110 wrote = snprintf(buf, len, "c=%s %s %s%s", \
111 (m_conn)->c_nettype, (m_conn)->c_addrtype, \
112 (m_conn)->c_address, COMMP_CRLF); \
114 } else if (strcasecmp((m_conn)->c_addrtype, \
115 COMMP_ADDRTYPE_IP6) == 0) { \
116 if ((m_conn)->c_addrcount <= 1) { \
117 wrote = snprintf(buf, len, "c=%s %s %s%s", \
118 (m_conn)->c_nettype, (m_conn)->c_addrtype, \
119 (m_conn)->c_address, COMMP_CRLF); \
121 wrote = snprintf(buf, len, "c=%s %s %s/%d%s", \
122 (m_conn)->c_nettype, (m_conn)->c_addrtype, \
123 (m_conn)->c_address, (m_conn)->c_addrcount,\
127 wrote = snprintf(buf, len, "c=%s %s %s%s", (m_conn)-> \
128 c_nettype, (m_conn)->c_addrtype, (m_conn)-> \
129 c_address, COMMP_CRLF); \
133 (m_conn) = (m_conn)->c_next; \
137 #define SDP_ADD_KEY(d_key, s_key) { \
138 if ((s_key) != NULL) { \
139 if (sdp_add_key(&(d_key), (s_key)->k_method, \
140 (s_key)->k_enckey) != 0) { \
141 sdp_free_session(new_sess); \
147 #define SDP_ADD_ATTRIBUTE(d_attr, s_attr) { \
148 while ((s_attr) != NULL) { \
149 if (sdp_add_attribute(&(d_attr), (s_attr)->a_name, \
150 (s_attr)->a_value) != 0) { \
151 sdp_free_session(new_sess); \
154 (s_attr) = (s_attr)->a_next; \
158 #define SDP_ADD_BANDWIDTH(d_bw, s_bw) { \
159 while ((s_bw) != NULL) { \
160 if (sdp_add_bandwidth(&(d_bw), (s_bw)->b_type, \
161 (s_bw)->b_value) != 0) { \
162 sdp_free_session(new_sess); \
165 (s_bw) = (s_bw)->b_next; \
169 #define SDP_ADD_CONNECTION(d_conn, s_conn) { \
170 while ((s_conn) != NULL) { \
171 if (sdp_add_connection(&(d_conn), (s_conn)->c_nettype, \
172 (s_conn)->c_addrtype, (s_conn)->c_address, \
173 (s_conn)->c_ttl, (s_conn)->c_addrcount) != 0) { \
174 sdp_free_session(new_sess); \
177 (s_conn) = (s_conn)->c_next; \
181 #define SDP_LEN_CONNECTION(m_conn) { \
182 while ((m_conn) != NULL) { \
183 len += FIELD_EQUALS_CRLF_LEN; \
184 len += strlen((m_conn)->c_nettype); \
185 len += strlen((m_conn)->c_addrtype) + 1; \
186 len += strlen((m_conn)->c_address) + 1; \
187 len += snprintf(buf, 1, "%u", (m_conn)->c_ttl) + 1; \
188 len += snprintf(buf, 1, "%d", (m_conn)->c_addrcount) + 1; \
189 (m_conn) = (m_conn)->c_next; \
193 #define SDP_LEN_BANDWIDTH(m_bw) { \
194 while ((m_bw) != NULL) { \
195 len += FIELD_EQUALS_CRLF_LEN; \
196 len += strlen((m_bw)->b_type); \
197 len += snprintf(buf, 1, "%llu", (m_bw)->b_value) + 1; \
198 (m_bw) = (m_bw)->b_next; \
202 #define SDP_LEN_KEY(m_key) { \
203 if ((m_key) != NULL) { \
204 len += FIELD_EQUALS_CRLF_LEN; \
205 len += strlen((m_key)->k_method); \
206 if ((m_key)->k_enckey != NULL) \
207 len += strlen((m_key)->k_enckey) + 1; \
211 #define SDP_LEN_ATTRIBUTE(m_attr) { \
212 while ((m_attr) != NULL) { \
213 len += FIELD_EQUALS_CRLF_LEN; \
214 len += strlen((m_attr)->a_name); \
215 if ((m_attr)->a_value != NULL) \
216 len += strlen((m_attr)->a_value) + 1; \
217 (m_attr) = (m_attr)->a_next; \
222 * Given a media list and media name ("audio", "video", et al), it searches
223 * the list for that media. Returns NULL if media not present.
226 sdp_find_media(sdp_media_t
*media
, const char *name
)
228 if (media
== NULL
|| name
== NULL
|| (strlen(name
) == 0)) {
231 while (media
!= NULL
) {
232 if (media
->m_name
!= NULL
) {
233 if (strcasecmp(name
, media
->m_name
) == 0)
236 media
= media
->m_next
;
242 * Given a attribute list and name of the attribute ("rtpmap", "fmtp", et al),
243 * this API searches the list for that attribute. Returns NULL if not found.
246 sdp_find_attribute(sdp_attr_t
*attr
, const char *name
)
248 if (attr
== NULL
|| name
== NULL
|| (strlen(name
) == 0)) {
251 while (attr
!= NULL
) {
252 if (attr
->a_name
!= NULL
) {
253 if (strcasecmp(attr
->a_name
, name
) == 0)
262 * Given a media list and a format number, this API will return the rtpmap
263 * attribute matching the format number.
266 sdp_find_media_rtpmap(sdp_media_t
*media
, const char *format
)
268 sdp_attr_t
*attr
= NULL
;
271 if (media
== NULL
|| format
== NULL
|| (strlen(format
) == 0)) {
274 attr
= media
->m_attr
;
275 while (attr
!= NULL
) {
276 if (attr
->a_name
!= NULL
&& (strcasecmp(attr
->a_name
,
278 if (attr
->a_value
!= NULL
) {
280 while (isspace(*tmp
))
282 if (strncasecmp(tmp
, format
,
283 strlen(format
)) == 0) {
294 * Adds origin field to the session.
295 * o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>
298 sdp_add_origin(sdp_session_t
*session
, const char *name
, uint64_t id
,
299 uint64_t ver
, const char *nettype
, const char *addrtype
,
302 sdp_origin_t
*origin
;
305 if (session
== NULL
|| name
== NULL
|| nettype
== NULL
||
306 addrtype
== NULL
|| address
== NULL
) {
309 if (session
->s_origin
!= NULL
)
311 origin
= calloc(1, sizeof (sdp_origin_t
));
315 origin
->o_version
= ver
;
316 if ((ret
= commp_add_str(&origin
->o_username
, name
, strlen(name
))) != 0)
318 if ((ret
= commp_add_str(&origin
->o_nettype
, nettype
,
319 strlen(nettype
))) != 0) {
322 if ((ret
= commp_add_str(&origin
->o_addrtype
, addrtype
,
323 strlen(addrtype
))) != 0) {
326 if ((ret
= commp_add_str(&origin
->o_address
, address
,
327 strlen(address
))) != 0) {
330 session
->s_origin
= origin
;
333 sdp_free_origin(origin
);
338 * Adds session name field to the session.
342 sdp_add_name(sdp_session_t
*session
, const char *name
)
344 if (session
== NULL
|| name
== NULL
)
346 if (session
->s_name
!= NULL
)
348 return (commp_add_str(&session
->s_name
, name
, strlen(name
)));
352 * Adds session information field to the session or media section of SDP.
353 * i=<session description>
356 sdp_add_information(char **information
, const char *value
)
358 if (information
== NULL
|| value
== NULL
)
360 if (*information
!= NULL
)
362 return (commp_add_str(information
, value
, strlen(value
)));
366 * Adds uri field to the session.
370 sdp_add_uri(sdp_session_t
*session
, const char *uri
)
372 if (session
== NULL
|| uri
== NULL
)
374 if (session
->s_uri
!= NULL
)
376 return (commp_add_str(&session
->s_uri
, uri
, strlen(uri
)));
380 * Adds email address field to the session.
384 sdp_add_email(sdp_session_t
*session
, const char *email
)
386 if (session
== NULL
|| email
== NULL
|| (strlen(email
) == 0))
388 return (add_value_to_list(&session
->s_email
, email
, strlen(email
),
393 * Adds phone number field to the session.
397 sdp_add_phone(sdp_session_t
*session
, const char *phone
)
399 if (session
== NULL
|| phone
== NULL
|| (strlen(phone
) == 0))
401 return (add_value_to_list(&session
->s_phone
, phone
, strlen(phone
),
406 * Adds connection field to the session or media section of SDP
407 * c=<nettype> <addrtype> <connection-address>[/ttl]/<number of addresses>
410 sdp_add_connection(sdp_conn_t
**conn
, const char *nettype
, const char *addrtype
,
411 const char *address
, uint8_t ttl
, int addrcount
)
414 sdp_conn_t
*new_conn
;
417 if (conn
== NULL
|| nettype
== NULL
|| addrtype
== NULL
||
421 new_conn
= calloc(1, sizeof (sdp_conn_t
));
422 if (new_conn
== NULL
)
424 new_conn
->c_ttl
= ttl
;
425 new_conn
->c_addrcount
= addrcount
;
426 if ((ret
= commp_add_str(&new_conn
->c_nettype
, nettype
,
427 strlen(nettype
))) != 0) {
430 if ((ret
= commp_add_str(&new_conn
->c_addrtype
, addrtype
,
431 strlen(addrtype
))) != 0) {
434 if ((ret
= commp_add_str(&new_conn
->c_address
, address
,
435 strlen(address
))) != 0) {
442 while (tmp
->c_next
!= NULL
)
444 tmp
->c_next
= new_conn
;
448 sdp_free_connection(new_conn
);
453 * Adds bandwidth field to the session or media section of SDP.
454 * b=<bwtype>:<bandwidth>
457 sdp_add_bandwidth(sdp_bandwidth_t
**bw
, const char *type
, uint64_t value
)
459 sdp_bandwidth_t
*new_bw
;
460 sdp_bandwidth_t
*tmp
;
463 if (bw
== NULL
|| type
== NULL
)
465 new_bw
= calloc(1, sizeof (sdp_bandwidth_t
));
468 new_bw
->b_value
= value
;
469 if ((ret
= commp_add_str(&new_bw
->b_type
, type
, strlen(type
))) != 0) {
477 while (tmp
->b_next
!= NULL
)
479 tmp
->b_next
= new_bw
;
485 * Adds time field to the session
486 * t=<start-time> <stop-time>
489 sdp_add_time(sdp_session_t
*session
, uint64_t starttime
, uint64_t stoptime
,
492 sdp_time_t
*new_time
;
497 if (session
== NULL
) {
500 new_time
= calloc(1, sizeof (sdp_time_t
));
501 if (new_time
== NULL
) {
504 new_time
->t_start
= starttime
;
505 new_time
->t_stop
= stoptime
;
506 tmp
= session
->s_time
;
508 session
->s_time
= new_time
;
510 while (tmp
->t_next
!= NULL
)
512 tmp
->t_next
= new_time
;
520 * Adds repeat field to the time structure of session
521 * r=<repeat interval> <active duration> <offsets from start-time>
524 sdp_add_repeat(sdp_time_t
*time
, uint64_t interval
, uint64_t duration
,
528 sdp_repeat_t
*new_repeat
;
531 if (time
== NULL
|| offset
== NULL
)
533 new_repeat
= calloc(1, sizeof (sdp_repeat_t
));
534 if (new_repeat
== NULL
)
536 new_repeat
->r_interval
= interval
;
537 new_repeat
->r_duration
= duration
;
538 if ((ret
= sdp_str_to_list(&new_repeat
->r_offset
, offset
,
539 strlen(offset
), B_FALSE
)) != 0) {
542 tmp
= time
->t_repeat
;
544 time
->t_repeat
= new_repeat
;
546 while (tmp
->r_next
!= NULL
)
548 tmp
->r_next
= new_repeat
;
552 sdp_free_repeat(new_repeat
);
557 * Adds time zone field to the session
558 * z=<adjustment time> <offset> <adjustment time> <offset> ....
561 sdp_add_zone(sdp_session_t
*session
, uint64_t time
, const char *offset
)
563 sdp_zone_t
*new_zone
;
567 if (session
== NULL
|| offset
== NULL
)
569 new_zone
= calloc(1, sizeof (sdp_zone_t
));
570 if (new_zone
== NULL
)
572 new_zone
->z_time
= time
;
573 if ((ret
= commp_add_str(&new_zone
->z_offset
, offset
,
574 strlen(offset
))) != 0) {
578 tmp
= session
->s_zone
;
580 session
->s_zone
= new_zone
;
582 while (tmp
->z_next
!= NULL
) {
585 tmp
->z_next
= new_zone
;
591 * Adds key field to session or media section of SDP.
593 * k=<method>:<encryption key>
596 sdp_add_key(sdp_key_t
**key
, const char *method
, const char *enckey
)
600 if (key
== NULL
|| method
== NULL
)
604 *key
= calloc(1, sizeof (sdp_key_t
));
607 if ((ret
= commp_add_str(&((*key
)->k_method
), method
,
608 strlen(method
))) != 0) {
611 if (enckey
!= NULL
) {
612 if ((ret
= commp_add_str(&((*key
)->k_enckey
), enckey
,
613 strlen(enckey
))) != 0) {
625 * Adds attribute field to session or media section of SDP.
627 * a=<attribute>:<value>
630 sdp_add_attribute(sdp_attr_t
**attr
, const char *name
, const char *value
)
633 sdp_attr_t
*new_attr
;
636 if (attr
== NULL
|| name
== NULL
)
638 new_attr
= calloc(1, sizeof (sdp_attr_t
));
639 if (new_attr
== NULL
)
641 if ((ret
= commp_add_str(&new_attr
->a_name
, name
, strlen(name
))) != 0)
644 if ((ret
= commp_add_str(&new_attr
->a_value
, value
,
645 strlen(value
))) != 0) {
653 while (tmp
->a_next
!= NULL
)
655 tmp
->a_next
= new_attr
;
659 sdp_free_attribute(new_attr
);
664 * Adds media field to the session.
665 * m=<media> <port>[/portcount] <proto> <fmt> ...
668 sdp_add_media(sdp_session_t
*session
, const char *name
, uint_t port
,
669 int portcount
, const char *protocol
, const char *fmt
, sdp_media_t
**media
)
672 sdp_media_t
*new_media
;
677 if (session
== NULL
|| name
== NULL
|| protocol
== NULL
||
678 portcount
<= 0 || fmt
== NULL
) {
681 new_media
= calloc(1, sizeof (sdp_media_t
));
682 if (new_media
== NULL
) {
685 new_media
->m_session
= session
;
686 new_media
->m_port
= port
;
687 new_media
->m_portcount
= portcount
;
688 if ((ret
= commp_add_str(&new_media
->m_name
, name
, strlen(name
))) != 0)
690 if ((ret
= commp_add_str(&new_media
->m_proto
, protocol
,
691 strlen(protocol
))) != 0) {
694 if ((ret
= sdp_str_to_list(&new_media
->m_format
, fmt
,
695 strlen(fmt
), B_TRUE
)) != 0) {
698 tmp
= session
->s_media
;
700 session
->s_media
= new_media
;
702 while (tmp
->m_next
!= NULL
)
704 tmp
->m_next
= new_media
;
710 sdp_free_media(new_media
);
715 * This internal API is required by sdp_session_to_str(). It determines the
716 * length of buffer that is required to hold the session. Since the RFC does
717 * not limit the size of various sub-fields in the field. We need to scan
718 * through the structure to determine the length.
721 sdp_get_length(const sdp_session_t
*session
)
730 sdp_repeat_t
*repeat
;
734 len
+= FIELD_EQUALS_CRLF_LEN
;
735 len
+= snprintf(buf
, 1, "%d", session
->s_version
);
736 if (session
->s_origin
!= NULL
) {
737 len
+= FIELD_EQUALS_CRLF_LEN
;
738 len
+= strlen(session
->s_origin
->o_username
);
739 len
+= snprintf(buf
, 1, "%llu", session
->s_origin
->o_id
) + 1;
740 len
+= snprintf(buf
, 1, "%llu", session
->s_origin
->o_version
)
742 len
+= strlen(session
->s_origin
->o_nettype
) + 1;
743 len
+= strlen(session
->s_origin
->o_addrtype
) + 1;
744 len
+= strlen(session
->s_origin
->o_address
) + 1;
746 if (session
->s_name
!= NULL
)
747 len
+= strlen(session
->s_name
) + FIELD_EQUALS_CRLF_LEN
;
748 if (session
->s_info
!= NULL
)
749 len
+= strlen(session
->s_info
) + FIELD_EQUALS_CRLF_LEN
;
750 if (session
->s_uri
!= NULL
)
751 len
+= strlen(session
->s_uri
) + FIELD_EQUALS_CRLF_LEN
;
752 list
= session
->s_email
;
753 while (list
!= NULL
) {
754 len
+= strlen((char *)list
->value
) + FIELD_EQUALS_CRLF_LEN
;
757 list
= session
->s_phone
;
758 while (list
!= NULL
) {
759 len
+= strlen((char *)list
->value
) + FIELD_EQUALS_CRLF_LEN
;
762 conn
= session
->s_conn
;
763 SDP_LEN_CONNECTION(conn
);
765 SDP_LEN_BANDWIDTH(bw
);
766 time
= session
->s_time
;
767 while (time
!= NULL
) {
768 len
+= FIELD_EQUALS_CRLF_LEN
;
769 len
+= snprintf(buf
, 1, "%llu", time
->t_start
);
770 len
+= snprintf(buf
, 1, "%llu", time
->t_stop
) + 1;
771 repeat
= time
->t_repeat
;
772 while (repeat
!= NULL
) {
773 len
+= FIELD_EQUALS_CRLF_LEN
;
774 len
+= snprintf(buf
, 1, "%llu", repeat
->r_interval
);
775 len
+= snprintf(buf
, 1, "%llu", repeat
->r_duration
) + 1;
776 list
= repeat
->r_offset
;
777 while (list
!= NULL
) {
778 len
+= snprintf(buf
, 1, "%llu",
779 *(uint64_t *)list
->value
) + 1;
782 repeat
= repeat
->r_next
;
786 if (session
->s_zone
!= NULL
)
787 len
+= FIELD_EQUALS_CRLF_LEN
;
788 zone
= session
->s_zone
;
789 while (zone
!= NULL
) {
790 len
+= snprintf(buf
, 1, "%llu", zone
->z_time
) + 1;
791 len
+= strlen(zone
->z_offset
) + 1;
794 SDP_LEN_KEY(session
->s_key
);
795 attr
= session
->s_attr
;
796 SDP_LEN_ATTRIBUTE(attr
);
797 media
= session
->s_media
;
798 while (media
!= NULL
) {
799 len
+= FIELD_EQUALS_CRLF_LEN
;
800 len
+= strlen(media
->m_name
);
801 len
+= snprintf(buf
, 1, "%u", media
->m_port
) + 1;
802 len
+= snprintf(buf
, 1, "%d", media
->m_portcount
) + 1;
803 len
+= strlen(media
->m_proto
) + 1;
804 list
= media
->m_format
;
805 while (list
!= NULL
) {
806 len
+= strlen((char *)list
->value
) + 1;
809 if (media
->m_info
!= NULL
)
810 len
+= strlen(media
->m_info
) + FIELD_EQUALS_CRLF_LEN
;
811 conn
= media
->m_conn
;
812 SDP_LEN_CONNECTION(conn
);
814 SDP_LEN_BANDWIDTH(bw
);
815 SDP_LEN_KEY(media
->m_key
);
816 attr
= media
->m_attr
;
817 SDP_LEN_ATTRIBUTE(attr
);
818 media
= media
->m_next
;
824 * Given a session structure it clones (deep copy) and returns the cloned copy
827 sdp_clone_session(const sdp_session_t
*session
)
829 sdp_session_t
*new_sess
;
830 sdp_origin_t
*origin
;
833 sdp_time_t
*new_time
;
834 sdp_repeat_t
*repeat
;
836 sdp_media_t
*new_media
;
846 new_sess
= calloc(1, sizeof (sdp_session_t
));
847 if (new_sess
== NULL
)
849 new_sess
->sdp_session_version
= session
->sdp_session_version
;
850 new_sess
->s_version
= session
->s_version
;
851 origin
= session
->s_origin
;
852 if (origin
!= NULL
&& (sdp_add_origin(new_sess
, origin
->o_username
,
853 origin
->o_id
, origin
->o_version
, origin
->o_nettype
, origin
->
854 o_addrtype
, origin
->o_address
) != 0)) {
857 if (session
->s_name
!= NULL
&& sdp_add_name(new_sess
, session
->
861 if (session
->s_info
!= NULL
&& sdp_add_information(&new_sess
->
862 s_info
, session
->s_info
) != 0) {
865 if (session
->s_uri
!= NULL
&& sdp_add_uri(new_sess
, session
->
869 list
= session
->s_email
;
870 while (list
!= NULL
) {
871 if (sdp_add_email(new_sess
, (char *)list
->value
) != 0)
875 list
= session
->s_phone
;
876 while (list
!= NULL
) {
877 if (sdp_add_phone(new_sess
, (char *)list
->value
) != 0)
881 conn
= session
->s_conn
;
882 SDP_ADD_CONNECTION(new_sess
->s_conn
, conn
);
884 SDP_ADD_BANDWIDTH(new_sess
->s_bw
, bw
);
885 time
= session
->s_time
;
886 while (time
!= NULL
) {
887 if (sdp_add_time(new_sess
, time
->t_start
, time
->t_stop
,
891 repeat
= time
->t_repeat
;
892 while (repeat
!= NULL
) {
893 if (sdp_list_to_str(repeat
->r_offset
, &offset
,
897 if (sdp_add_repeat(new_time
, repeat
->r_interval
,
898 repeat
->r_duration
, offset
) != 0) {
903 repeat
= repeat
->r_next
;
907 zone
= session
->s_zone
;
908 while (zone
!= NULL
) {
909 if (sdp_add_zone(new_sess
, zone
->z_time
, zone
->z_offset
) != 0)
913 SDP_ADD_KEY(new_sess
->s_key
, session
->s_key
);
914 attr
= session
->s_attr
;
915 SDP_ADD_ATTRIBUTE(new_sess
->s_attr
, attr
);
916 media
= session
->s_media
;
917 while (media
!= NULL
) {
918 if (sdp_list_to_str(media
->m_format
, &format
, B_TRUE
) != 0)
920 if (sdp_add_media(new_sess
, media
->m_name
,
921 media
->m_port
, media
->m_portcount
, media
->m_proto
,
922 format
, &new_media
) != 0) {
927 if (media
->m_info
!= NULL
) {
928 if (sdp_add_information(&new_media
->m_info
,
929 media
->m_info
) != 0) {
933 conn
= media
->m_conn
;
934 SDP_ADD_CONNECTION(new_media
->m_conn
, conn
);
936 SDP_ADD_BANDWIDTH(new_media
->m_bw
, bw
);
937 SDP_ADD_KEY(new_media
->m_key
, media
->m_key
);
938 attr
= media
->m_attr
;
939 SDP_ADD_ATTRIBUTE(new_media
->m_attr
, attr
);
940 new_media
->m_session
= new_sess
;
941 media
= media
->m_next
;
945 sdp_free_session(new_sess
);
950 * should i check if individual members are NULL, if not snprintf
954 * Given a session structure, this API converts it into character
955 * buffer, which will be used as a payload later on.
958 sdp_session_to_str(const sdp_session_t
*session
, int *error
)
965 sdp_origin_t
*origin
;
971 sdp_repeat_t
*repeat
;
977 if (session
== NULL
) {
982 s_len
= sdp_get_length(session
);
983 ret
= malloc(s_len
+ 1);
991 wrote
= snprintf(buf
, len
, "v=%d%s", session
->s_version
, COMMP_CRLF
);
994 origin
= session
->s_origin
;
995 if (origin
!= NULL
) {
996 wrote
= snprintf(buf
, len
, "o=%s %llu %llu %s %s %s%s",
997 origin
->o_username
, origin
->o_id
, origin
->o_version
,
998 origin
->o_nettype
, origin
->o_addrtype
, origin
->o_address
,
1003 if (session
->s_name
!= NULL
) {
1004 wrote
= snprintf(buf
, len
, "s=%s%s", session
->s_name
,
1009 SDP_INFORMATION_TO_STR(session
->s_info
);
1010 if (session
->s_uri
!= NULL
) {
1011 wrote
= snprintf(buf
, len
, "u=%s%s", session
->s_uri
,
1016 list
= session
->s_email
;
1017 while (list
!= NULL
) {
1018 wrote
= snprintf(buf
, len
, "e=%s%s", (char *)list
->value
,
1024 list
= session
->s_phone
;
1025 while (list
!= NULL
) {
1026 wrote
= snprintf(buf
, len
, "p=%s%s", (char *)list
->value
,
1032 conn
= session
->s_conn
;
1033 SDP_CONNECTION_TO_STR(conn
);
1035 SDP_BANDWIDTH_TO_STR(bw
);
1036 time
= session
->s_time
;
1037 while (time
!= NULL
) {
1038 wrote
= snprintf(buf
, len
, "t=%llu %llu%s", time
->t_start
,
1039 time
->t_stop
, COMMP_CRLF
);
1042 repeat
= time
->t_repeat
;
1043 while (repeat
!= NULL
) {
1044 wrote
= snprintf(buf
, len
, "r=%llu %llu", repeat
->
1045 r_interval
, repeat
->r_duration
);
1048 list
= repeat
->r_offset
;
1049 while (list
!= NULL
) {
1050 wrote
= snprintf(buf
, len
, " %llu",
1051 *(uint64_t *)list
->value
);
1056 wrote
= snprintf(buf
, len
, "%s", COMMP_CRLF
);
1059 repeat
= repeat
->r_next
;
1061 time
= time
->t_next
;
1063 zone
= session
->s_zone
;
1065 wrote
= snprintf(buf
, len
, "z=%llu %s", zone
->z_time
,
1069 zone
= zone
->z_next
;
1070 while (zone
!= NULL
) {
1071 wrote
= snprintf(buf
, len
, " %llu %s", zone
->z_time
,
1075 zone
= zone
->z_next
;
1077 wrote
= snprintf(buf
, len
, "%s", COMMP_CRLF
);
1081 SDP_KEY_TO_STR(session
->s_key
);
1082 attr
= session
->s_attr
;
1083 SDP_ATTR_TO_STR(attr
);
1084 media
= session
->s_media
;
1085 while (media
!= NULL
) {
1086 if (media
->m_portcount
== 1) {
1087 wrote
= snprintf(buf
, len
, "m=%s %d %s", media
->m_name
,
1088 media
->m_port
, media
->m_proto
);
1090 wrote
= snprintf(buf
, len
, "m=%s %d/%d %s", media
->
1091 m_name
, media
->m_port
, media
->m_portcount
, media
->
1096 list
= media
->m_format
;
1097 while (list
!= NULL
) {
1098 wrote
= snprintf(buf
, len
, " %s", (char *)list
->value
);
1103 wrote
= snprintf(buf
, len
, "%s", COMMP_CRLF
);
1106 SDP_INFORMATION_TO_STR(media
->m_info
);
1107 conn
= media
->m_conn
;
1108 SDP_CONNECTION_TO_STR(conn
);
1110 SDP_BANDWIDTH_TO_STR(bw
);
1111 SDP_KEY_TO_STR(media
->m_key
);
1112 attr
= media
->m_attr
;
1113 SDP_ATTR_TO_STR(attr
);
1114 media
= media
->m_next
;
1122 * Given a session structure and the field ('v', 'o', 's', et al), this API
1123 * deletes the corresponding structure element. It frees the memory and sets the
1127 sdp_delete_all_field(sdp_session_t
*session
, const char field
)
1129 if (session
== NULL
)
1132 case SDP_ORIGIN_FIELD
:
1133 sdp_free_origin(session
->s_origin
);
1134 session
->s_origin
= NULL
;
1136 case SDP_NAME_FIELD
:
1137 free(session
->s_name
);
1138 session
->s_name
= NULL
;
1140 case SDP_INFO_FIELD
:
1141 free(session
->s_info
);
1142 session
->s_info
= NULL
;
1145 free(session
->s_uri
);
1146 session
->s_uri
= NULL
;
1148 case SDP_EMAIL_FIELD
:
1149 sdp_free_list(session
->s_email
);
1150 session
->s_email
= NULL
;
1152 case SDP_PHONE_FIELD
:
1153 sdp_free_list(session
->s_phone
);
1154 session
->s_phone
= NULL
;
1156 case SDP_CONNECTION_FIELD
:
1157 sdp_free_connection(session
->s_conn
);
1158 session
->s_conn
= NULL
;
1160 case SDP_BANDWIDTH_FIELD
:
1161 sdp_free_bandwidth(session
->s_bw
);
1162 session
->s_bw
= NULL
;
1164 case SDP_TIME_FIELD
:
1165 sdp_free_time(session
->s_time
);
1166 session
->s_time
= NULL
;
1168 case SDP_ZONE_FIELD
:
1169 sdp_free_zone(session
->s_zone
);
1170 session
->s_zone
= NULL
;
1173 sdp_free_key(session
->s_key
);
1174 session
->s_key
= NULL
;
1176 case SDP_ATTRIBUTE_FIELD
:
1177 sdp_free_attribute(session
->s_attr
);
1178 session
->s_attr
= NULL
;
1180 case SDP_MEDIA_FIELD
:
1181 sdp_free_media(session
->s_media
);
1182 session
->s_media
= NULL
;
1191 * Given a media structure and the field ('i', 'b', 'c', et al), this API
1192 * deletes the corresponding structure element. It frees the memory and sets
1193 * the pointer to NULL.
1196 sdp_delete_all_media_field(sdp_media_t
*media
, const char field
)
1201 case SDP_INFO_FIELD
:
1202 free(media
->m_info
);
1203 media
->m_info
= NULL
;
1205 case SDP_CONNECTION_FIELD
:
1206 sdp_free_connection(media
->m_conn
);
1207 media
->m_conn
= NULL
;
1209 case SDP_BANDWIDTH_FIELD
:
1210 sdp_free_bandwidth(media
->m_bw
);
1214 sdp_free_key(media
->m_key
);
1215 media
->m_key
= NULL
;
1217 case SDP_ATTRIBUTE_FIELD
:
1218 sdp_free_attribute(media
->m_attr
);
1219 media
->m_attr
= NULL
;
1228 * Given a media list and the media, this API deletes that media from the
1229 * list. It frees the memory corresponding to that media.
1232 sdp_delete_media(sdp_media_t
**l_media
, sdp_media_t
*media
)
1237 if (l_media
== NULL
|| *l_media
== NULL
|| media
== NULL
)
1241 while (cur
!= NULL
&& cur
!= media
) {
1247 if (cur
== *l_media
)
1248 *l_media
= cur
->m_next
;
1250 prev
->m_next
= cur
->m_next
;
1252 sdp_free_media(cur
);
1257 * Given an attribute list and an attribute, this API deletes that attribue
1258 * from the list. It frees the memory corresponding to that attribute.
1261 sdp_delete_attribute(sdp_attr_t
**l_attr
, sdp_attr_t
*attr
)
1266 if (l_attr
== NULL
|| *l_attr
== NULL
|| attr
== NULL
)
1270 while (cur
!= NULL
&& cur
!= attr
) {
1277 *l_attr
= cur
->a_next
;
1279 prev
->a_next
= cur
->a_next
;
1281 sdp_free_attribute(cur
);
1286 * Allocates a new sdp session structure and assigns a version number to it.
1287 * Currently one version is defined and it is 1. This will be useful in future
1288 * in the unlikely need to change the structure.
1293 sdp_session_t
*session
= NULL
;
1295 session
= calloc(1, sizeof (sdp_session_t
));
1296 if (session
!= NULL
)
1297 session
->sdp_session_version
= SDP_SESSION_VERSION_1
;