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.
28 * Contains implementation of various interfaces exported by library
39 #include "sdp_parse.h"
40 #include "commp_util.h"
42 #define FIELD_EQUALS_CRLF_LEN 4 /* first two characters and CRLF */
44 #define SDP_ATTR_TO_STR(m_attr) { \
45 while ((m_attr) != NULL) { \
46 if ((m_attr)->a_value != NULL) { \
47 wrote = snprintf(buf, len, "a=%s%c%s%s", \
48 (m_attr)->a_name, COMMP_COLON, (m_attr)-> \
49 a_value, COMMP_CRLF); \
51 wrote = snprintf(buf, len, "a=%s%s", (m_attr)-> \
52 a_name, COMMP_CRLF); \
56 (m_attr) = (m_attr)->a_next; \
60 #define SDP_KEY_TO_STR(m_key) { \
61 if ((m_key) != NULL) { \
62 if ((m_key)->k_enckey != NULL) { \
63 wrote = snprintf(buf, len, "k=%s%c%s%s", \
64 (m_key)->k_method, COMMP_COLON, (m_key)-> \
65 k_enckey, COMMP_CRLF); \
67 wrote = snprintf(buf, len, "k=%s%s", (m_key)-> \
68 k_method, COMMP_CRLF); \
75 #define SDP_BANDWIDTH_TO_STR(m_bw) { \
76 while ((m_bw) != NULL) { \
77 wrote = snprintf(buf, len, "b=%s%c%llu%s", (m_bw)-> \
78 b_type, COMMP_COLON, (m_bw)->b_value, COMMP_CRLF); \
81 (m_bw) = (m_bw)->b_next; \
85 #define SDP_INFORMATION_TO_STR(m_info) { \
86 if ((m_info) != NULL) { \
87 wrote = snprintf(buf, len, "i=%s%s", (m_info), COMMP_CRLF); \
93 #define SDP_CONNECTION_TO_STR(m_conn) { \
94 while ((m_conn) != NULL) { \
95 if (strcasecmp((m_conn)->c_addrtype, \
96 COMMP_ADDRTYPE_IP4) == 0) { \
97 if ((m_conn)->c_addrcount > 1) { \
98 wrote = snprintf(buf, len, "c=%s %s %s/%d/%d" \
99 "%s", (m_conn)->c_nettype, (m_conn)-> \
100 c_addrtype, (m_conn)->c_address, (m_conn)->\
101 c_ttl, (m_conn)->c_addrcount, COMMP_CRLF); \
102 } else if ((m_conn)->c_addrcount == 1) { \
103 wrote = snprintf(buf, len, "c=%s %s %s/%d%s", \
104 (m_conn)->c_nettype, (m_conn)->c_addrtype, \
105 (m_conn)->c_address, (m_conn)->c_ttl, \
108 wrote = snprintf(buf, len, "c=%s %s %s%s", \
109 (m_conn)->c_nettype, (m_conn)->c_addrtype, \
110 (m_conn)->c_address, COMMP_CRLF); \
112 } else if (strcasecmp((m_conn)->c_addrtype, \
113 COMMP_ADDRTYPE_IP6) == 0) { \
114 if ((m_conn)->c_addrcount <= 1) { \
115 wrote = snprintf(buf, len, "c=%s %s %s%s", \
116 (m_conn)->c_nettype, (m_conn)->c_addrtype, \
117 (m_conn)->c_address, COMMP_CRLF); \
119 wrote = snprintf(buf, len, "c=%s %s %s/%d%s", \
120 (m_conn)->c_nettype, (m_conn)->c_addrtype, \
121 (m_conn)->c_address, (m_conn)->c_addrcount,\
125 wrote = snprintf(buf, len, "c=%s %s %s%s", (m_conn)-> \
126 c_nettype, (m_conn)->c_addrtype, (m_conn)-> \
127 c_address, COMMP_CRLF); \
131 (m_conn) = (m_conn)->c_next; \
135 #define SDP_ADD_KEY(d_key, s_key) { \
136 if ((s_key) != NULL) { \
137 if (sdp_add_key(&(d_key), (s_key)->k_method, \
138 (s_key)->k_enckey) != 0) { \
139 sdp_free_session(new_sess); \
145 #define SDP_ADD_ATTRIBUTE(d_attr, s_attr) { \
146 while ((s_attr) != NULL) { \
147 if (sdp_add_attribute(&(d_attr), (s_attr)->a_name, \
148 (s_attr)->a_value) != 0) { \
149 sdp_free_session(new_sess); \
152 (s_attr) = (s_attr)->a_next; \
156 #define SDP_ADD_BANDWIDTH(d_bw, s_bw) { \
157 while ((s_bw) != NULL) { \
158 if (sdp_add_bandwidth(&(d_bw), (s_bw)->b_type, \
159 (s_bw)->b_value) != 0) { \
160 sdp_free_session(new_sess); \
163 (s_bw) = (s_bw)->b_next; \
167 #define SDP_ADD_CONNECTION(d_conn, s_conn) { \
168 while ((s_conn) != NULL) { \
169 if (sdp_add_connection(&(d_conn), (s_conn)->c_nettype, \
170 (s_conn)->c_addrtype, (s_conn)->c_address, \
171 (s_conn)->c_ttl, (s_conn)->c_addrcount) != 0) { \
172 sdp_free_session(new_sess); \
175 (s_conn) = (s_conn)->c_next; \
179 #define SDP_LEN_CONNECTION(m_conn) { \
180 while ((m_conn) != NULL) { \
181 len += FIELD_EQUALS_CRLF_LEN; \
182 len += strlen((m_conn)->c_nettype); \
183 len += strlen((m_conn)->c_addrtype) + 1; \
184 len += strlen((m_conn)->c_address) + 1; \
185 len += snprintf(buf, 1, "%u", (m_conn)->c_ttl) + 1; \
186 len += snprintf(buf, 1, "%d", (m_conn)->c_addrcount) + 1; \
187 (m_conn) = (m_conn)->c_next; \
191 #define SDP_LEN_BANDWIDTH(m_bw) { \
192 while ((m_bw) != NULL) { \
193 len += FIELD_EQUALS_CRLF_LEN; \
194 len += strlen((m_bw)->b_type); \
195 len += snprintf(buf, 1, "%llu", (m_bw)->b_value) + 1; \
196 (m_bw) = (m_bw)->b_next; \
200 #define SDP_LEN_KEY(m_key) { \
201 if ((m_key) != NULL) { \
202 len += FIELD_EQUALS_CRLF_LEN; \
203 len += strlen((m_key)->k_method); \
204 if ((m_key)->k_enckey != NULL) \
205 len += strlen((m_key)->k_enckey) + 1; \
209 #define SDP_LEN_ATTRIBUTE(m_attr) { \
210 while ((m_attr) != NULL) { \
211 len += FIELD_EQUALS_CRLF_LEN; \
212 len += strlen((m_attr)->a_name); \
213 if ((m_attr)->a_value != NULL) \
214 len += strlen((m_attr)->a_value) + 1; \
215 (m_attr) = (m_attr)->a_next; \
220 * Given a media list and media name ("audio", "video", et al), it searches
221 * the list for that media. Returns NULL if media not present.
224 sdp_find_media(sdp_media_t
*media
, const char *name
)
226 if (media
== NULL
|| name
== NULL
|| (strlen(name
) == 0)) {
229 while (media
!= NULL
) {
230 if (media
->m_name
!= NULL
) {
231 if (strcasecmp(name
, media
->m_name
) == 0)
234 media
= media
->m_next
;
240 * Given a attribute list and name of the attribute ("rtpmap", "fmtp", et al),
241 * this API searches the list for that attribute. Returns NULL if not found.
244 sdp_find_attribute(sdp_attr_t
*attr
, const char *name
)
246 if (attr
== NULL
|| name
== NULL
|| (strlen(name
) == 0)) {
249 while (attr
!= NULL
) {
250 if (attr
->a_name
!= NULL
) {
251 if (strcasecmp(attr
->a_name
, name
) == 0)
260 * Given a media list and a format number, this API will return the rtpmap
261 * attribute matching the format number.
264 sdp_find_media_rtpmap(sdp_media_t
*media
, const char *format
)
266 sdp_attr_t
*attr
= NULL
;
269 if (media
== NULL
|| format
== NULL
|| (strlen(format
) == 0)) {
272 attr
= media
->m_attr
;
273 while (attr
!= NULL
) {
274 if (attr
->a_name
!= NULL
&& (strcasecmp(attr
->a_name
,
276 if (attr
->a_value
!= NULL
) {
278 while (isspace(*tmp
))
280 if (strncasecmp(tmp
, format
,
281 strlen(format
)) == 0) {
292 * Adds origin field to the session.
293 * o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>
296 sdp_add_origin(sdp_session_t
*session
, const char *name
, uint64_t id
,
297 uint64_t ver
, const char *nettype
, const char *addrtype
,
300 sdp_origin_t
*origin
;
303 if (session
== NULL
|| name
== NULL
|| nettype
== NULL
||
304 addrtype
== NULL
|| address
== NULL
) {
307 if (session
->s_origin
!= NULL
)
309 origin
= calloc(1, sizeof (sdp_origin_t
));
313 origin
->o_version
= ver
;
314 if ((ret
= commp_add_str(&origin
->o_username
, name
, strlen(name
))) != 0)
316 if ((ret
= commp_add_str(&origin
->o_nettype
, nettype
,
317 strlen(nettype
))) != 0) {
320 if ((ret
= commp_add_str(&origin
->o_addrtype
, addrtype
,
321 strlen(addrtype
))) != 0) {
324 if ((ret
= commp_add_str(&origin
->o_address
, address
,
325 strlen(address
))) != 0) {
328 session
->s_origin
= origin
;
331 sdp_free_origin(origin
);
336 * Adds session name field to the session.
340 sdp_add_name(sdp_session_t
*session
, const char *name
)
342 if (session
== NULL
|| name
== NULL
)
344 if (session
->s_name
!= NULL
)
346 return (commp_add_str(&session
->s_name
, name
, strlen(name
)));
350 * Adds session information field to the session or media section of SDP.
351 * i=<session description>
354 sdp_add_information(char **information
, const char *value
)
356 if (information
== NULL
|| value
== NULL
)
358 if (*information
!= NULL
)
360 return (commp_add_str(information
, value
, strlen(value
)));
364 * Adds uri field to the session.
368 sdp_add_uri(sdp_session_t
*session
, const char *uri
)
370 if (session
== NULL
|| uri
== NULL
)
372 if (session
->s_uri
!= NULL
)
374 return (commp_add_str(&session
->s_uri
, uri
, strlen(uri
)));
378 * Adds email address field to the session.
382 sdp_add_email(sdp_session_t
*session
, const char *email
)
384 if (session
== NULL
|| email
== NULL
|| (strlen(email
) == 0))
386 return (add_value_to_list(&session
->s_email
, email
, strlen(email
),
391 * Adds phone number field to the session.
395 sdp_add_phone(sdp_session_t
*session
, const char *phone
)
397 if (session
== NULL
|| phone
== NULL
|| (strlen(phone
) == 0))
399 return (add_value_to_list(&session
->s_phone
, phone
, strlen(phone
),
404 * Adds connection field to the session or media section of SDP
405 * c=<nettype> <addrtype> <connection-address>[/ttl]/<number of addresses>
408 sdp_add_connection(sdp_conn_t
**conn
, const char *nettype
, const char *addrtype
,
409 const char *address
, uint8_t ttl
, int addrcount
)
412 sdp_conn_t
*new_conn
;
415 if (conn
== NULL
|| nettype
== NULL
|| addrtype
== NULL
||
419 new_conn
= calloc(1, sizeof (sdp_conn_t
));
420 if (new_conn
== NULL
)
422 new_conn
->c_ttl
= ttl
;
423 new_conn
->c_addrcount
= addrcount
;
424 if ((ret
= commp_add_str(&new_conn
->c_nettype
, nettype
,
425 strlen(nettype
))) != 0) {
428 if ((ret
= commp_add_str(&new_conn
->c_addrtype
, addrtype
,
429 strlen(addrtype
))) != 0) {
432 if ((ret
= commp_add_str(&new_conn
->c_address
, address
,
433 strlen(address
))) != 0) {
440 while (tmp
->c_next
!= NULL
)
442 tmp
->c_next
= new_conn
;
446 sdp_free_connection(new_conn
);
451 * Adds bandwidth field to the session or media section of SDP.
452 * b=<bwtype>:<bandwidth>
455 sdp_add_bandwidth(sdp_bandwidth_t
**bw
, const char *type
, uint64_t value
)
457 sdp_bandwidth_t
*new_bw
;
458 sdp_bandwidth_t
*tmp
;
461 if (bw
== NULL
|| type
== NULL
)
463 new_bw
= calloc(1, sizeof (sdp_bandwidth_t
));
466 new_bw
->b_value
= value
;
467 if ((ret
= commp_add_str(&new_bw
->b_type
, type
, strlen(type
))) != 0) {
475 while (tmp
->b_next
!= NULL
)
477 tmp
->b_next
= new_bw
;
483 * Adds time field to the session
484 * t=<start-time> <stop-time>
487 sdp_add_time(sdp_session_t
*session
, uint64_t starttime
, uint64_t stoptime
,
490 sdp_time_t
*new_time
;
495 if (session
== NULL
) {
498 new_time
= calloc(1, sizeof (sdp_time_t
));
499 if (new_time
== NULL
) {
502 new_time
->t_start
= starttime
;
503 new_time
->t_stop
= stoptime
;
504 tmp
= session
->s_time
;
506 session
->s_time
= new_time
;
508 while (tmp
->t_next
!= NULL
)
510 tmp
->t_next
= new_time
;
518 * Adds repeat field to the time structure of session
519 * r=<repeat interval> <active duration> <offsets from start-time>
522 sdp_add_repeat(sdp_time_t
*time
, uint64_t interval
, uint64_t duration
,
526 sdp_repeat_t
*new_repeat
;
529 if (time
== NULL
|| offset
== NULL
)
531 new_repeat
= calloc(1, sizeof (sdp_repeat_t
));
532 if (new_repeat
== NULL
)
534 new_repeat
->r_interval
= interval
;
535 new_repeat
->r_duration
= duration
;
536 if ((ret
= sdp_str_to_list(&new_repeat
->r_offset
, offset
,
537 strlen(offset
), B_FALSE
)) != 0) {
540 tmp
= time
->t_repeat
;
542 time
->t_repeat
= new_repeat
;
544 while (tmp
->r_next
!= NULL
)
546 tmp
->r_next
= new_repeat
;
550 sdp_free_repeat(new_repeat
);
555 * Adds time zone field to the session
556 * z=<adjustment time> <offset> <adjustment time> <offset> ....
559 sdp_add_zone(sdp_session_t
*session
, uint64_t time
, const char *offset
)
561 sdp_zone_t
*new_zone
;
565 if (session
== NULL
|| offset
== NULL
)
567 new_zone
= calloc(1, sizeof (sdp_zone_t
));
568 if (new_zone
== NULL
)
570 new_zone
->z_time
= time
;
571 if ((ret
= commp_add_str(&new_zone
->z_offset
, offset
,
572 strlen(offset
))) != 0) {
576 tmp
= session
->s_zone
;
578 session
->s_zone
= new_zone
;
580 while (tmp
->z_next
!= NULL
) {
583 tmp
->z_next
= new_zone
;
589 * Adds key field to session or media section of SDP.
591 * k=<method>:<encryption key>
594 sdp_add_key(sdp_key_t
**key
, const char *method
, const char *enckey
)
598 if (key
== NULL
|| method
== NULL
)
602 *key
= calloc(1, sizeof (sdp_key_t
));
605 if ((ret
= commp_add_str(&((*key
)->k_method
), method
,
606 strlen(method
))) != 0) {
609 if (enckey
!= NULL
) {
610 if ((ret
= commp_add_str(&((*key
)->k_enckey
), enckey
,
611 strlen(enckey
))) != 0) {
623 * Adds attribute field to session or media section of SDP.
625 * a=<attribute>:<value>
628 sdp_add_attribute(sdp_attr_t
**attr
, const char *name
, const char *value
)
631 sdp_attr_t
*new_attr
;
634 if (attr
== NULL
|| name
== NULL
)
636 new_attr
= calloc(1, sizeof (sdp_attr_t
));
637 if (new_attr
== NULL
)
639 if ((ret
= commp_add_str(&new_attr
->a_name
, name
, strlen(name
))) != 0)
642 if ((ret
= commp_add_str(&new_attr
->a_value
, value
,
643 strlen(value
))) != 0) {
651 while (tmp
->a_next
!= NULL
)
653 tmp
->a_next
= new_attr
;
657 sdp_free_attribute(new_attr
);
662 * Adds media field to the session.
663 * m=<media> <port>[/portcount] <proto> <fmt> ...
666 sdp_add_media(sdp_session_t
*session
, const char *name
, uint_t port
,
667 int portcount
, const char *protocol
, const char *fmt
, sdp_media_t
**media
)
670 sdp_media_t
*new_media
;
675 if (session
== NULL
|| name
== NULL
|| protocol
== NULL
||
676 portcount
<= 0 || fmt
== NULL
) {
679 new_media
= calloc(1, sizeof (sdp_media_t
));
680 if (new_media
== NULL
) {
683 new_media
->m_session
= session
;
684 new_media
->m_port
= port
;
685 new_media
->m_portcount
= portcount
;
686 if ((ret
= commp_add_str(&new_media
->m_name
, name
, strlen(name
))) != 0)
688 if ((ret
= commp_add_str(&new_media
->m_proto
, protocol
,
689 strlen(protocol
))) != 0) {
692 if ((ret
= sdp_str_to_list(&new_media
->m_format
, fmt
,
693 strlen(fmt
), B_TRUE
)) != 0) {
696 tmp
= session
->s_media
;
698 session
->s_media
= new_media
;
700 while (tmp
->m_next
!= NULL
)
702 tmp
->m_next
= new_media
;
708 sdp_free_media(new_media
);
713 * This internal API is required by sdp_session_to_str(). It determines the
714 * length of buffer that is required to hold the session. Since the RFC does
715 * not limit the size of various sub-fields in the field. We need to scan
716 * through the structure to determine the length.
719 sdp_get_length(const sdp_session_t
*session
)
728 sdp_repeat_t
*repeat
;
732 len
+= FIELD_EQUALS_CRLF_LEN
;
733 len
+= snprintf(buf
, 1, "%d", session
->s_version
);
734 if (session
->s_origin
!= NULL
) {
735 len
+= FIELD_EQUALS_CRLF_LEN
;
736 len
+= strlen(session
->s_origin
->o_username
);
737 len
+= snprintf(buf
, 1, "%llu", session
->s_origin
->o_id
) + 1;
738 len
+= snprintf(buf
, 1, "%llu", session
->s_origin
->o_version
)
740 len
+= strlen(session
->s_origin
->o_nettype
) + 1;
741 len
+= strlen(session
->s_origin
->o_addrtype
) + 1;
742 len
+= strlen(session
->s_origin
->o_address
) + 1;
744 if (session
->s_name
!= NULL
)
745 len
+= strlen(session
->s_name
) + FIELD_EQUALS_CRLF_LEN
;
746 if (session
->s_info
!= NULL
)
747 len
+= strlen(session
->s_info
) + FIELD_EQUALS_CRLF_LEN
;
748 if (session
->s_uri
!= NULL
)
749 len
+= strlen(session
->s_uri
) + FIELD_EQUALS_CRLF_LEN
;
750 list
= session
->s_email
;
751 while (list
!= NULL
) {
752 len
+= strlen((char *)list
->value
) + FIELD_EQUALS_CRLF_LEN
;
755 list
= session
->s_phone
;
756 while (list
!= NULL
) {
757 len
+= strlen((char *)list
->value
) + FIELD_EQUALS_CRLF_LEN
;
760 conn
= session
->s_conn
;
761 SDP_LEN_CONNECTION(conn
);
763 SDP_LEN_BANDWIDTH(bw
);
764 time
= session
->s_time
;
765 while (time
!= NULL
) {
766 len
+= FIELD_EQUALS_CRLF_LEN
;
767 len
+= snprintf(buf
, 1, "%llu", time
->t_start
);
768 len
+= snprintf(buf
, 1, "%llu", time
->t_stop
) + 1;
769 repeat
= time
->t_repeat
;
770 while (repeat
!= NULL
) {
771 len
+= FIELD_EQUALS_CRLF_LEN
;
772 len
+= snprintf(buf
, 1, "%llu", repeat
->r_interval
);
773 len
+= snprintf(buf
, 1, "%llu", repeat
->r_duration
) + 1;
774 list
= repeat
->r_offset
;
775 while (list
!= NULL
) {
776 len
+= snprintf(buf
, 1, "%llu",
777 *(uint64_t *)list
->value
) + 1;
780 repeat
= repeat
->r_next
;
784 if (session
->s_zone
!= NULL
)
785 len
+= FIELD_EQUALS_CRLF_LEN
;
786 zone
= session
->s_zone
;
787 while (zone
!= NULL
) {
788 len
+= snprintf(buf
, 1, "%llu", zone
->z_time
) + 1;
789 len
+= strlen(zone
->z_offset
) + 1;
792 SDP_LEN_KEY(session
->s_key
);
793 attr
= session
->s_attr
;
794 SDP_LEN_ATTRIBUTE(attr
);
795 media
= session
->s_media
;
796 while (media
!= NULL
) {
797 len
+= FIELD_EQUALS_CRLF_LEN
;
798 len
+= strlen(media
->m_name
);
799 len
+= snprintf(buf
, 1, "%u", media
->m_port
) + 1;
800 len
+= snprintf(buf
, 1, "%d", media
->m_portcount
) + 1;
801 len
+= strlen(media
->m_proto
) + 1;
802 list
= media
->m_format
;
803 while (list
!= NULL
) {
804 len
+= strlen((char *)list
->value
) + 1;
807 if (media
->m_info
!= NULL
)
808 len
+= strlen(media
->m_info
) + FIELD_EQUALS_CRLF_LEN
;
809 conn
= media
->m_conn
;
810 SDP_LEN_CONNECTION(conn
);
812 SDP_LEN_BANDWIDTH(bw
);
813 SDP_LEN_KEY(media
->m_key
);
814 attr
= media
->m_attr
;
815 SDP_LEN_ATTRIBUTE(attr
);
816 media
= media
->m_next
;
822 * Given a session structure it clones (deep copy) and returns the cloned copy
825 sdp_clone_session(const sdp_session_t
*session
)
827 sdp_session_t
*new_sess
;
828 sdp_origin_t
*origin
;
831 sdp_time_t
*new_time
;
832 sdp_repeat_t
*repeat
;
834 sdp_media_t
*new_media
;
844 new_sess
= calloc(1, sizeof (sdp_session_t
));
845 if (new_sess
== NULL
)
847 new_sess
->sdp_session_version
= session
->sdp_session_version
;
848 new_sess
->s_version
= session
->s_version
;
849 origin
= session
->s_origin
;
850 if (origin
!= NULL
&& (sdp_add_origin(new_sess
, origin
->o_username
,
851 origin
->o_id
, origin
->o_version
, origin
->o_nettype
, origin
->
852 o_addrtype
, origin
->o_address
) != 0)) {
855 if (session
->s_name
!= NULL
&& sdp_add_name(new_sess
, session
->
859 if (session
->s_info
!= NULL
&& sdp_add_information(&new_sess
->
860 s_info
, session
->s_info
) != 0) {
863 if (session
->s_uri
!= NULL
&& sdp_add_uri(new_sess
, session
->
867 list
= session
->s_email
;
868 while (list
!= NULL
) {
869 if (sdp_add_email(new_sess
, (char *)list
->value
) != 0)
873 list
= session
->s_phone
;
874 while (list
!= NULL
) {
875 if (sdp_add_phone(new_sess
, (char *)list
->value
) != 0)
879 conn
= session
->s_conn
;
880 SDP_ADD_CONNECTION(new_sess
->s_conn
, conn
);
882 SDP_ADD_BANDWIDTH(new_sess
->s_bw
, bw
);
883 time
= session
->s_time
;
884 while (time
!= NULL
) {
885 if (sdp_add_time(new_sess
, time
->t_start
, time
->t_stop
,
889 repeat
= time
->t_repeat
;
890 while (repeat
!= NULL
) {
891 if (sdp_list_to_str(repeat
->r_offset
, &offset
,
895 if (sdp_add_repeat(new_time
, repeat
->r_interval
,
896 repeat
->r_duration
, offset
) != 0) {
901 repeat
= repeat
->r_next
;
905 zone
= session
->s_zone
;
906 while (zone
!= NULL
) {
907 if (sdp_add_zone(new_sess
, zone
->z_time
, zone
->z_offset
) != 0)
911 SDP_ADD_KEY(new_sess
->s_key
, session
->s_key
);
912 attr
= session
->s_attr
;
913 SDP_ADD_ATTRIBUTE(new_sess
->s_attr
, attr
);
914 media
= session
->s_media
;
915 while (media
!= NULL
) {
916 if (sdp_list_to_str(media
->m_format
, &format
, B_TRUE
) != 0)
918 if (sdp_add_media(new_sess
, media
->m_name
,
919 media
->m_port
, media
->m_portcount
, media
->m_proto
,
920 format
, &new_media
) != 0) {
925 if (media
->m_info
!= NULL
) {
926 if (sdp_add_information(&new_media
->m_info
,
927 media
->m_info
) != 0) {
931 conn
= media
->m_conn
;
932 SDP_ADD_CONNECTION(new_media
->m_conn
, conn
);
934 SDP_ADD_BANDWIDTH(new_media
->m_bw
, bw
);
935 SDP_ADD_KEY(new_media
->m_key
, media
->m_key
);
936 attr
= media
->m_attr
;
937 SDP_ADD_ATTRIBUTE(new_media
->m_attr
, attr
);
938 new_media
->m_session
= new_sess
;
939 media
= media
->m_next
;
943 sdp_free_session(new_sess
);
948 * should i check if individual members are NULL, if not snprintf
952 * Given a session structure, this API converts it into character
953 * buffer, which will be used as a payload later on.
956 sdp_session_to_str(const sdp_session_t
*session
, int *error
)
963 sdp_origin_t
*origin
;
969 sdp_repeat_t
*repeat
;
975 if (session
== NULL
) {
980 s_len
= sdp_get_length(session
);
981 ret
= malloc(s_len
+ 1);
989 wrote
= snprintf(buf
, len
, "v=%d%s", session
->s_version
, COMMP_CRLF
);
992 origin
= session
->s_origin
;
993 if (origin
!= NULL
) {
994 wrote
= snprintf(buf
, len
, "o=%s %llu %llu %s %s %s%s",
995 origin
->o_username
, origin
->o_id
, origin
->o_version
,
996 origin
->o_nettype
, origin
->o_addrtype
, origin
->o_address
,
1001 if (session
->s_name
!= NULL
) {
1002 wrote
= snprintf(buf
, len
, "s=%s%s", session
->s_name
,
1007 SDP_INFORMATION_TO_STR(session
->s_info
);
1008 if (session
->s_uri
!= NULL
) {
1009 wrote
= snprintf(buf
, len
, "u=%s%s", session
->s_uri
,
1014 list
= session
->s_email
;
1015 while (list
!= NULL
) {
1016 wrote
= snprintf(buf
, len
, "e=%s%s", (char *)list
->value
,
1022 list
= session
->s_phone
;
1023 while (list
!= NULL
) {
1024 wrote
= snprintf(buf
, len
, "p=%s%s", (char *)list
->value
,
1030 conn
= session
->s_conn
;
1031 SDP_CONNECTION_TO_STR(conn
);
1033 SDP_BANDWIDTH_TO_STR(bw
);
1034 time
= session
->s_time
;
1035 while (time
!= NULL
) {
1036 wrote
= snprintf(buf
, len
, "t=%llu %llu%s", time
->t_start
,
1037 time
->t_stop
, COMMP_CRLF
);
1040 repeat
= time
->t_repeat
;
1041 while (repeat
!= NULL
) {
1042 wrote
= snprintf(buf
, len
, "r=%llu %llu", repeat
->
1043 r_interval
, repeat
->r_duration
);
1046 list
= repeat
->r_offset
;
1047 while (list
!= NULL
) {
1048 wrote
= snprintf(buf
, len
, " %llu",
1049 *(uint64_t *)list
->value
);
1054 wrote
= snprintf(buf
, len
, "%s", COMMP_CRLF
);
1057 repeat
= repeat
->r_next
;
1059 time
= time
->t_next
;
1061 zone
= session
->s_zone
;
1063 wrote
= snprintf(buf
, len
, "z=%llu %s", zone
->z_time
,
1067 zone
= zone
->z_next
;
1068 while (zone
!= NULL
) {
1069 wrote
= snprintf(buf
, len
, " %llu %s", zone
->z_time
,
1073 zone
= zone
->z_next
;
1075 wrote
= snprintf(buf
, len
, "%s", COMMP_CRLF
);
1079 SDP_KEY_TO_STR(session
->s_key
);
1080 attr
= session
->s_attr
;
1081 SDP_ATTR_TO_STR(attr
);
1082 media
= session
->s_media
;
1083 while (media
!= NULL
) {
1084 if (media
->m_portcount
== 1) {
1085 wrote
= snprintf(buf
, len
, "m=%s %d %s", media
->m_name
,
1086 media
->m_port
, media
->m_proto
);
1088 wrote
= snprintf(buf
, len
, "m=%s %d/%d %s", media
->
1089 m_name
, media
->m_port
, media
->m_portcount
, media
->
1094 list
= media
->m_format
;
1095 while (list
!= NULL
) {
1096 wrote
= snprintf(buf
, len
, " %s", (char *)list
->value
);
1101 wrote
= snprintf(buf
, len
, "%s", COMMP_CRLF
);
1104 SDP_INFORMATION_TO_STR(media
->m_info
);
1105 conn
= media
->m_conn
;
1106 SDP_CONNECTION_TO_STR(conn
);
1108 SDP_BANDWIDTH_TO_STR(bw
);
1109 SDP_KEY_TO_STR(media
->m_key
);
1110 attr
= media
->m_attr
;
1111 SDP_ATTR_TO_STR(attr
);
1112 media
= media
->m_next
;
1120 * Given a session structure and the field ('v', 'o', 's', et al), this API
1121 * deletes the corresponding structure element. It frees the memory and sets the
1125 sdp_delete_all_field(sdp_session_t
*session
, const char field
)
1127 if (session
== NULL
)
1130 case SDP_ORIGIN_FIELD
:
1131 sdp_free_origin(session
->s_origin
);
1132 session
->s_origin
= NULL
;
1134 case SDP_NAME_FIELD
:
1135 free(session
->s_name
);
1136 session
->s_name
= NULL
;
1138 case SDP_INFO_FIELD
:
1139 free(session
->s_info
);
1140 session
->s_info
= NULL
;
1143 free(session
->s_uri
);
1144 session
->s_uri
= NULL
;
1146 case SDP_EMAIL_FIELD
:
1147 sdp_free_list(session
->s_email
);
1148 session
->s_email
= NULL
;
1150 case SDP_PHONE_FIELD
:
1151 sdp_free_list(session
->s_phone
);
1152 session
->s_phone
= NULL
;
1154 case SDP_CONNECTION_FIELD
:
1155 sdp_free_connection(session
->s_conn
);
1156 session
->s_conn
= NULL
;
1158 case SDP_BANDWIDTH_FIELD
:
1159 sdp_free_bandwidth(session
->s_bw
);
1160 session
->s_bw
= NULL
;
1162 case SDP_TIME_FIELD
:
1163 sdp_free_time(session
->s_time
);
1164 session
->s_time
= NULL
;
1166 case SDP_ZONE_FIELD
:
1167 sdp_free_zone(session
->s_zone
);
1168 session
->s_zone
= NULL
;
1171 sdp_free_key(session
->s_key
);
1172 session
->s_key
= NULL
;
1174 case SDP_ATTRIBUTE_FIELD
:
1175 sdp_free_attribute(session
->s_attr
);
1176 session
->s_attr
= NULL
;
1178 case SDP_MEDIA_FIELD
:
1179 sdp_free_media(session
->s_media
);
1180 session
->s_media
= NULL
;
1189 * Given a media structure and the field ('i', 'b', 'c', et al), this API
1190 * deletes the corresponding structure element. It frees the memory and sets
1191 * the pointer to NULL.
1194 sdp_delete_all_media_field(sdp_media_t
*media
, const char field
)
1199 case SDP_INFO_FIELD
:
1200 free(media
->m_info
);
1201 media
->m_info
= NULL
;
1203 case SDP_CONNECTION_FIELD
:
1204 sdp_free_connection(media
->m_conn
);
1205 media
->m_conn
= NULL
;
1207 case SDP_BANDWIDTH_FIELD
:
1208 sdp_free_bandwidth(media
->m_bw
);
1212 sdp_free_key(media
->m_key
);
1213 media
->m_key
= NULL
;
1215 case SDP_ATTRIBUTE_FIELD
:
1216 sdp_free_attribute(media
->m_attr
);
1217 media
->m_attr
= NULL
;
1226 * Given a media list and the media, this API deletes that media from the
1227 * list. It frees the memory corresponding to that media.
1230 sdp_delete_media(sdp_media_t
**l_media
, sdp_media_t
*media
)
1235 if (l_media
== NULL
|| *l_media
== NULL
|| media
== NULL
)
1239 while (cur
!= NULL
&& cur
!= media
) {
1245 if (cur
== *l_media
)
1246 *l_media
= cur
->m_next
;
1248 prev
->m_next
= cur
->m_next
;
1250 sdp_free_media(cur
);
1255 * Given an attribute list and an attribute, this API deletes that attribue
1256 * from the list. It frees the memory corresponding to that attribute.
1259 sdp_delete_attribute(sdp_attr_t
**l_attr
, sdp_attr_t
*attr
)
1264 if (l_attr
== NULL
|| *l_attr
== NULL
|| attr
== NULL
)
1268 while (cur
!= NULL
&& cur
!= attr
) {
1275 *l_attr
= cur
->a_next
;
1277 prev
->a_next
= cur
->a_next
;
1279 sdp_free_attribute(cur
);
1284 * Allocates a new sdp session structure and assigns a version number to it.
1285 * Currently one version is defined and it is 1. This will be useful in future
1286 * in the unlikely need to change the structure.
1291 sdp_session_t
*session
= NULL
;
1293 session
= calloc(1, sizeof (sdp_session_t
));
1294 if (session
!= NULL
)
1295 session
->sdp_session_version
= SDP_SESSION_VERSION_1
;