1*a93a1f58Sgm209912 /* 2*a93a1f58Sgm209912 * CDDL HEADER START 3*a93a1f58Sgm209912 * 4*a93a1f58Sgm209912 * The contents of this file are subject to the terms of the 5*a93a1f58Sgm209912 * Common Development and Distribution License (the "License"). 6*a93a1f58Sgm209912 * You may not use this file except in compliance with the License. 7*a93a1f58Sgm209912 * 8*a93a1f58Sgm209912 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*a93a1f58Sgm209912 * or http://www.opensolaris.org/os/licensing. 10*a93a1f58Sgm209912 * See the License for the specific language governing permissions 11*a93a1f58Sgm209912 * and limitations under the License. 12*a93a1f58Sgm209912 * 13*a93a1f58Sgm209912 * When distributing Covered Code, include this CDDL HEADER in each 14*a93a1f58Sgm209912 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*a93a1f58Sgm209912 * If applicable, add the following below this CDDL HEADER, with the 16*a93a1f58Sgm209912 * fields enclosed by brackets "[]" replaced with your own identifying 17*a93a1f58Sgm209912 * information: Portions Copyright [yyyy] [name of copyright owner] 18*a93a1f58Sgm209912 * 19*a93a1f58Sgm209912 * CDDL HEADER END 20*a93a1f58Sgm209912 */ 21*a93a1f58Sgm209912 22*a93a1f58Sgm209912 /* 23*a93a1f58Sgm209912 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24*a93a1f58Sgm209912 * Use is subject to license terms. 25*a93a1f58Sgm209912 */ 26*a93a1f58Sgm209912 27*a93a1f58Sgm209912 #pragma ident "%Z%%M% %I% %E% SMI" 28*a93a1f58Sgm209912 29*a93a1f58Sgm209912 /* 30*a93a1f58Sgm209912 * Contains implementation of various interfaces exported by library 31*a93a1f58Sgm209912 */ 32*a93a1f58Sgm209912 33*a93a1f58Sgm209912 #include <stdio.h> 34*a93a1f58Sgm209912 #include <assert.h> 35*a93a1f58Sgm209912 #include <errno.h> 36*a93a1f58Sgm209912 #include <stdlib.h> 37*a93a1f58Sgm209912 #include <string.h> 38*a93a1f58Sgm209912 #include <ctype.h> 39*a93a1f58Sgm209912 #include <sdp.h> 40*a93a1f58Sgm209912 41*a93a1f58Sgm209912 #include "sdp_parse.h" 42*a93a1f58Sgm209912 #include "commp_util.h" 43*a93a1f58Sgm209912 44*a93a1f58Sgm209912 #define FIELD_EQUALS_CRLF_LEN 4 /* first two characters and CRLF */ 45*a93a1f58Sgm209912 46*a93a1f58Sgm209912 #define SDP_ATTR_TO_STR(m_attr) { \ 47*a93a1f58Sgm209912 while ((m_attr) != NULL) { \ 48*a93a1f58Sgm209912 if ((m_attr)->a_value != NULL) { \ 49*a93a1f58Sgm209912 wrote = snprintf(buf, len, "a=%s%c%s%s", \ 50*a93a1f58Sgm209912 (m_attr)->a_name, COMMP_COLON, (m_attr)-> \ 51*a93a1f58Sgm209912 a_value, COMMP_CRLF); \ 52*a93a1f58Sgm209912 } else { \ 53*a93a1f58Sgm209912 wrote = snprintf(buf, len, "a=%s%s", (m_attr)-> \ 54*a93a1f58Sgm209912 a_name, COMMP_CRLF); \ 55*a93a1f58Sgm209912 } \ 56*a93a1f58Sgm209912 len = len - wrote; \ 57*a93a1f58Sgm209912 buf = buf + wrote; \ 58*a93a1f58Sgm209912 (m_attr) = (m_attr)->a_next; \ 59*a93a1f58Sgm209912 } \ 60*a93a1f58Sgm209912 } 61*a93a1f58Sgm209912 62*a93a1f58Sgm209912 #define SDP_KEY_TO_STR(m_key) { \ 63*a93a1f58Sgm209912 if ((m_key) != NULL) { \ 64*a93a1f58Sgm209912 if ((m_key)->k_enckey != NULL) { \ 65*a93a1f58Sgm209912 wrote = snprintf(buf, len, "k=%s%c%s%s", \ 66*a93a1f58Sgm209912 (m_key)->k_method, COMMP_COLON, (m_key)-> \ 67*a93a1f58Sgm209912 k_enckey, COMMP_CRLF); \ 68*a93a1f58Sgm209912 } else { \ 69*a93a1f58Sgm209912 wrote = snprintf(buf, len, "k=%s%s", (m_key)-> \ 70*a93a1f58Sgm209912 k_method, COMMP_CRLF); \ 71*a93a1f58Sgm209912 } \ 72*a93a1f58Sgm209912 len = len - wrote; \ 73*a93a1f58Sgm209912 buf = buf + wrote; \ 74*a93a1f58Sgm209912 } \ 75*a93a1f58Sgm209912 } 76*a93a1f58Sgm209912 77*a93a1f58Sgm209912 #define SDP_BANDWIDTH_TO_STR(m_bw) { \ 78*a93a1f58Sgm209912 while ((m_bw) != NULL) { \ 79*a93a1f58Sgm209912 wrote = snprintf(buf, len, "b=%s%c%llu%s", (m_bw)-> \ 80*a93a1f58Sgm209912 b_type, COMMP_COLON, (m_bw)->b_value, COMMP_CRLF); \ 81*a93a1f58Sgm209912 len = len - wrote; \ 82*a93a1f58Sgm209912 buf = buf + wrote; \ 83*a93a1f58Sgm209912 (m_bw) = (m_bw)->b_next; \ 84*a93a1f58Sgm209912 } \ 85*a93a1f58Sgm209912 } 86*a93a1f58Sgm209912 87*a93a1f58Sgm209912 #define SDP_INFORMATION_TO_STR(m_info) { \ 88*a93a1f58Sgm209912 if ((m_info) != NULL) { \ 89*a93a1f58Sgm209912 wrote = snprintf(buf, len, "i=%s%s", (m_info), COMMP_CRLF); \ 90*a93a1f58Sgm209912 len = len - wrote; \ 91*a93a1f58Sgm209912 buf = buf + wrote; \ 92*a93a1f58Sgm209912 } \ 93*a93a1f58Sgm209912 } 94*a93a1f58Sgm209912 95*a93a1f58Sgm209912 #define SDP_CONNECTION_TO_STR(m_conn) { \ 96*a93a1f58Sgm209912 while ((m_conn) != NULL) { \ 97*a93a1f58Sgm209912 if (strcasecmp((m_conn)->c_addrtype, \ 98*a93a1f58Sgm209912 COMMP_ADDRTYPE_IP4) == 0) { \ 99*a93a1f58Sgm209912 if ((m_conn)->c_addrcount > 1) { \ 100*a93a1f58Sgm209912 wrote = snprintf(buf, len, "c=%s %s %s/%d/%d" \ 101*a93a1f58Sgm209912 "%s", (m_conn)->c_nettype, (m_conn)-> \ 102*a93a1f58Sgm209912 c_addrtype, (m_conn)->c_address, (m_conn)->\ 103*a93a1f58Sgm209912 c_ttl, (m_conn)->c_addrcount, COMMP_CRLF); \ 104*a93a1f58Sgm209912 } else if ((m_conn)->c_addrcount == 1) { \ 105*a93a1f58Sgm209912 wrote = snprintf(buf, len, "c=%s %s %s/%d%s", \ 106*a93a1f58Sgm209912 (m_conn)->c_nettype, (m_conn)->c_addrtype, \ 107*a93a1f58Sgm209912 (m_conn)->c_address, (m_conn)->c_ttl, \ 108*a93a1f58Sgm209912 COMMP_CRLF); \ 109*a93a1f58Sgm209912 } else { \ 110*a93a1f58Sgm209912 wrote = snprintf(buf, len, "c=%s %s %s%s", \ 111*a93a1f58Sgm209912 (m_conn)->c_nettype, (m_conn)->c_addrtype, \ 112*a93a1f58Sgm209912 (m_conn)->c_address, COMMP_CRLF); \ 113*a93a1f58Sgm209912 } \ 114*a93a1f58Sgm209912 } else if (strcasecmp((m_conn)->c_addrtype, \ 115*a93a1f58Sgm209912 COMMP_ADDRTYPE_IP6) == 0) { \ 116*a93a1f58Sgm209912 if ((m_conn)->c_addrcount <= 1) { \ 117*a93a1f58Sgm209912 wrote = snprintf(buf, len, "c=%s %s %s%s", \ 118*a93a1f58Sgm209912 (m_conn)->c_nettype, (m_conn)->c_addrtype, \ 119*a93a1f58Sgm209912 (m_conn)->c_address, COMMP_CRLF); \ 120*a93a1f58Sgm209912 } else { \ 121*a93a1f58Sgm209912 wrote = snprintf(buf, len, "c=%s %s %s/%d%s", \ 122*a93a1f58Sgm209912 (m_conn)->c_nettype, (m_conn)->c_addrtype, \ 123*a93a1f58Sgm209912 (m_conn)->c_address, (m_conn)->c_addrcount,\ 124*a93a1f58Sgm209912 COMMP_CRLF); \ 125*a93a1f58Sgm209912 } \ 126*a93a1f58Sgm209912 } else { \ 127*a93a1f58Sgm209912 wrote = snprintf(buf, len, "c=%s %s %s%s", (m_conn)-> \ 128*a93a1f58Sgm209912 c_nettype, (m_conn)->c_addrtype, (m_conn)-> \ 129*a93a1f58Sgm209912 c_address, COMMP_CRLF); \ 130*a93a1f58Sgm209912 } \ 131*a93a1f58Sgm209912 len = len - wrote; \ 132*a93a1f58Sgm209912 buf = buf + wrote; \ 133*a93a1f58Sgm209912 (m_conn) = (m_conn)->c_next; \ 134*a93a1f58Sgm209912 } \ 135*a93a1f58Sgm209912 } 136*a93a1f58Sgm209912 137*a93a1f58Sgm209912 #define SDP_ADD_KEY(d_key, s_key) { \ 138*a93a1f58Sgm209912 if ((s_key) != NULL) { \ 139*a93a1f58Sgm209912 if (sdp_add_key(&(d_key), (s_key)->k_method, \ 140*a93a1f58Sgm209912 (s_key)->k_enckey) != 0) { \ 141*a93a1f58Sgm209912 sdp_free_session(new_sess); \ 142*a93a1f58Sgm209912 return (NULL); \ 143*a93a1f58Sgm209912 } \ 144*a93a1f58Sgm209912 } \ 145*a93a1f58Sgm209912 } 146*a93a1f58Sgm209912 147*a93a1f58Sgm209912 #define SDP_ADD_ATTRIBUTE(d_attr, s_attr) { \ 148*a93a1f58Sgm209912 while ((s_attr) != NULL) { \ 149*a93a1f58Sgm209912 if (sdp_add_attribute(&(d_attr), (s_attr)->a_name, \ 150*a93a1f58Sgm209912 (s_attr)->a_value) != 0) { \ 151*a93a1f58Sgm209912 sdp_free_session(new_sess); \ 152*a93a1f58Sgm209912 return (NULL); \ 153*a93a1f58Sgm209912 } \ 154*a93a1f58Sgm209912 (s_attr) = (s_attr)->a_next; \ 155*a93a1f58Sgm209912 } \ 156*a93a1f58Sgm209912 } 157*a93a1f58Sgm209912 158*a93a1f58Sgm209912 #define SDP_ADD_BANDWIDTH(d_bw, s_bw) { \ 159*a93a1f58Sgm209912 while ((s_bw) != NULL) { \ 160*a93a1f58Sgm209912 if (sdp_add_bandwidth(&(d_bw), (s_bw)->b_type, \ 161*a93a1f58Sgm209912 (s_bw)->b_value) != 0) { \ 162*a93a1f58Sgm209912 sdp_free_session(new_sess); \ 163*a93a1f58Sgm209912 return (NULL); \ 164*a93a1f58Sgm209912 } \ 165*a93a1f58Sgm209912 (s_bw) = (s_bw)->b_next; \ 166*a93a1f58Sgm209912 } \ 167*a93a1f58Sgm209912 } 168*a93a1f58Sgm209912 169*a93a1f58Sgm209912 #define SDP_ADD_CONNECTION(d_conn, s_conn) { \ 170*a93a1f58Sgm209912 while ((s_conn) != NULL) { \ 171*a93a1f58Sgm209912 if (sdp_add_connection(&(d_conn), (s_conn)->c_nettype, \ 172*a93a1f58Sgm209912 (s_conn)->c_addrtype, (s_conn)->c_address, \ 173*a93a1f58Sgm209912 (s_conn)->c_ttl, (s_conn)->c_addrcount) != 0) { \ 174*a93a1f58Sgm209912 sdp_free_session(new_sess); \ 175*a93a1f58Sgm209912 return (NULL); \ 176*a93a1f58Sgm209912 } \ 177*a93a1f58Sgm209912 (s_conn) = (s_conn)->c_next; \ 178*a93a1f58Sgm209912 } \ 179*a93a1f58Sgm209912 } 180*a93a1f58Sgm209912 181*a93a1f58Sgm209912 #define SDP_LEN_CONNECTION(m_conn) { \ 182*a93a1f58Sgm209912 while ((m_conn) != NULL) { \ 183*a93a1f58Sgm209912 len += FIELD_EQUALS_CRLF_LEN; \ 184*a93a1f58Sgm209912 len += strlen((m_conn)->c_nettype); \ 185*a93a1f58Sgm209912 len += strlen((m_conn)->c_addrtype) + 1; \ 186*a93a1f58Sgm209912 len += strlen((m_conn)->c_address) + 1; \ 187*a93a1f58Sgm209912 len += snprintf(buf, 1, "%u", (m_conn)->c_ttl) + 1; \ 188*a93a1f58Sgm209912 len += snprintf(buf, 1, "%d", (m_conn)->c_addrcount) + 1; \ 189*a93a1f58Sgm209912 (m_conn) = (m_conn)->c_next; \ 190*a93a1f58Sgm209912 } \ 191*a93a1f58Sgm209912 } 192*a93a1f58Sgm209912 193*a93a1f58Sgm209912 #define SDP_LEN_BANDWIDTH(m_bw) { \ 194*a93a1f58Sgm209912 while ((m_bw) != NULL) { \ 195*a93a1f58Sgm209912 len += FIELD_EQUALS_CRLF_LEN; \ 196*a93a1f58Sgm209912 len += strlen((m_bw)->b_type); \ 197*a93a1f58Sgm209912 len += snprintf(buf, 1, "%llu", (m_bw)->b_value) + 1; \ 198*a93a1f58Sgm209912 (m_bw) = (m_bw)->b_next; \ 199*a93a1f58Sgm209912 } \ 200*a93a1f58Sgm209912 } 201*a93a1f58Sgm209912 202*a93a1f58Sgm209912 #define SDP_LEN_KEY(m_key) { \ 203*a93a1f58Sgm209912 if ((m_key) != NULL) { \ 204*a93a1f58Sgm209912 len += FIELD_EQUALS_CRLF_LEN; \ 205*a93a1f58Sgm209912 len += strlen((m_key)->k_method); \ 206*a93a1f58Sgm209912 if ((m_key)->k_enckey != NULL) \ 207*a93a1f58Sgm209912 len += strlen((m_key)->k_enckey) + 1; \ 208*a93a1f58Sgm209912 } \ 209*a93a1f58Sgm209912 } 210*a93a1f58Sgm209912 211*a93a1f58Sgm209912 #define SDP_LEN_ATTRIBUTE(m_attr) { \ 212*a93a1f58Sgm209912 while ((m_attr) != NULL) { \ 213*a93a1f58Sgm209912 len += FIELD_EQUALS_CRLF_LEN; \ 214*a93a1f58Sgm209912 len += strlen((m_attr)->a_name); \ 215*a93a1f58Sgm209912 if ((m_attr)->a_value != NULL) \ 216*a93a1f58Sgm209912 len += strlen((m_attr)->a_value) + 1; \ 217*a93a1f58Sgm209912 (m_attr) = (m_attr)->a_next; \ 218*a93a1f58Sgm209912 } \ 219*a93a1f58Sgm209912 } 220*a93a1f58Sgm209912 221*a93a1f58Sgm209912 /* 222*a93a1f58Sgm209912 * Given a media list and media name ("audio", "video", et al), it searches 223*a93a1f58Sgm209912 * the list for that media. Returns NULL if media not present. 224*a93a1f58Sgm209912 */ 225*a93a1f58Sgm209912 sdp_media_t * 226*a93a1f58Sgm209912 sdp_find_media(sdp_media_t *media, const char *name) 227*a93a1f58Sgm209912 { 228*a93a1f58Sgm209912 if (media == NULL || name == NULL || (strlen(name) == 0)) { 229*a93a1f58Sgm209912 return (NULL); 230*a93a1f58Sgm209912 } 231*a93a1f58Sgm209912 while (media != NULL) { 232*a93a1f58Sgm209912 if (media->m_name != NULL) { 233*a93a1f58Sgm209912 if (strcasecmp(name, media->m_name) == 0) 234*a93a1f58Sgm209912 return (media); 235*a93a1f58Sgm209912 } 236*a93a1f58Sgm209912 media = media->m_next; 237*a93a1f58Sgm209912 } 238*a93a1f58Sgm209912 return (media); 239*a93a1f58Sgm209912 } 240*a93a1f58Sgm209912 241*a93a1f58Sgm209912 /* 242*a93a1f58Sgm209912 * Given a attribute list and name of the attribute ("rtpmap", "fmtp", et al), 243*a93a1f58Sgm209912 * this API searches the list for that attribute. Returns NULL if not found. 244*a93a1f58Sgm209912 */ 245*a93a1f58Sgm209912 sdp_attr_t * 246*a93a1f58Sgm209912 sdp_find_attribute(sdp_attr_t *attr, const char *name) 247*a93a1f58Sgm209912 { 248*a93a1f58Sgm209912 if (attr == NULL || name == NULL || (strlen(name) == 0)) { 249*a93a1f58Sgm209912 return (NULL); 250*a93a1f58Sgm209912 } 251*a93a1f58Sgm209912 while (attr != NULL) { 252*a93a1f58Sgm209912 if (attr->a_name != NULL) { 253*a93a1f58Sgm209912 if (strcasecmp(attr->a_name, name) == 0) 254*a93a1f58Sgm209912 return (attr); 255*a93a1f58Sgm209912 } 256*a93a1f58Sgm209912 attr = attr->a_next; 257*a93a1f58Sgm209912 } 258*a93a1f58Sgm209912 return (attr); 259*a93a1f58Sgm209912 } 260*a93a1f58Sgm209912 261*a93a1f58Sgm209912 /* 262*a93a1f58Sgm209912 * Given a media list and a format number, this API will return the rtpmap 263*a93a1f58Sgm209912 * attribute matching the format number. 264*a93a1f58Sgm209912 */ 265*a93a1f58Sgm209912 sdp_attr_t * 266*a93a1f58Sgm209912 sdp_find_media_rtpmap(sdp_media_t *media, const char *format) 267*a93a1f58Sgm209912 { 268*a93a1f58Sgm209912 sdp_attr_t *attr = NULL; 269*a93a1f58Sgm209912 char *tmp = NULL; 270*a93a1f58Sgm209912 271*a93a1f58Sgm209912 if (media == NULL || format == NULL || (strlen(format) == 0)) { 272*a93a1f58Sgm209912 return (NULL); 273*a93a1f58Sgm209912 } 274*a93a1f58Sgm209912 attr = media->m_attr; 275*a93a1f58Sgm209912 while (attr != NULL) { 276*a93a1f58Sgm209912 if (attr->a_name != NULL && (strcasecmp(attr->a_name, 277*a93a1f58Sgm209912 SDP_RTPMAP) == 0)) { 278*a93a1f58Sgm209912 if (attr->a_value != NULL) { 279*a93a1f58Sgm209912 tmp = attr->a_value; 280*a93a1f58Sgm209912 while (isspace(*tmp)) 281*a93a1f58Sgm209912 ++tmp; 282*a93a1f58Sgm209912 if (strncasecmp(tmp, format, 283*a93a1f58Sgm209912 strlen(format)) == 0) { 284*a93a1f58Sgm209912 return (attr); 285*a93a1f58Sgm209912 } 286*a93a1f58Sgm209912 } 287*a93a1f58Sgm209912 } 288*a93a1f58Sgm209912 attr = attr->a_next; 289*a93a1f58Sgm209912 } 290*a93a1f58Sgm209912 return (attr); 291*a93a1f58Sgm209912 } 292*a93a1f58Sgm209912 293*a93a1f58Sgm209912 /* 294*a93a1f58Sgm209912 * Adds origin field to the session. 295*a93a1f58Sgm209912 * o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address> 296*a93a1f58Sgm209912 */ 297*a93a1f58Sgm209912 int 298*a93a1f58Sgm209912 sdp_add_origin(sdp_session_t *session, const char *name, uint64_t id, 299*a93a1f58Sgm209912 uint64_t ver, const char *nettype, const char *addrtype, 300*a93a1f58Sgm209912 const char *address) 301*a93a1f58Sgm209912 { 302*a93a1f58Sgm209912 sdp_origin_t *origin; 303*a93a1f58Sgm209912 int ret = 0; 304*a93a1f58Sgm209912 305*a93a1f58Sgm209912 if (session == NULL || name == NULL || nettype == NULL || 306*a93a1f58Sgm209912 addrtype == NULL || address == NULL) { 307*a93a1f58Sgm209912 return (EINVAL); 308*a93a1f58Sgm209912 } 309*a93a1f58Sgm209912 if (session->s_origin != NULL) 310*a93a1f58Sgm209912 return (EPROTO); 311*a93a1f58Sgm209912 origin = calloc(1, sizeof (sdp_origin_t)); 312*a93a1f58Sgm209912 if (origin == NULL) 313*a93a1f58Sgm209912 return (ENOMEM); 314*a93a1f58Sgm209912 origin->o_id = id; 315*a93a1f58Sgm209912 origin->o_version = ver; 316*a93a1f58Sgm209912 if ((ret = commp_add_str(&origin->o_username, name, strlen(name))) != 0) 317*a93a1f58Sgm209912 goto err_ret; 318*a93a1f58Sgm209912 if ((ret = commp_add_str(&origin->o_nettype, nettype, 319*a93a1f58Sgm209912 strlen(nettype))) != 0) { 320*a93a1f58Sgm209912 goto err_ret; 321*a93a1f58Sgm209912 } 322*a93a1f58Sgm209912 if ((ret = commp_add_str(&origin->o_addrtype, addrtype, 323*a93a1f58Sgm209912 strlen(addrtype))) != 0) { 324*a93a1f58Sgm209912 goto err_ret; 325*a93a1f58Sgm209912 } 326*a93a1f58Sgm209912 if ((ret = commp_add_str(&origin->o_address, address, 327*a93a1f58Sgm209912 strlen(address))) != 0) { 328*a93a1f58Sgm209912 goto err_ret; 329*a93a1f58Sgm209912 } 330*a93a1f58Sgm209912 session->s_origin = origin; 331*a93a1f58Sgm209912 return (ret); 332*a93a1f58Sgm209912 err_ret: 333*a93a1f58Sgm209912 sdp_free_origin(origin); 334*a93a1f58Sgm209912 return (ret); 335*a93a1f58Sgm209912 } 336*a93a1f58Sgm209912 337*a93a1f58Sgm209912 /* 338*a93a1f58Sgm209912 * Adds session name field to the session. 339*a93a1f58Sgm209912 * s=<session name> 340*a93a1f58Sgm209912 */ 341*a93a1f58Sgm209912 int 342*a93a1f58Sgm209912 sdp_add_name(sdp_session_t *session, const char *name) 343*a93a1f58Sgm209912 { 344*a93a1f58Sgm209912 if (session == NULL || name == NULL) 345*a93a1f58Sgm209912 return (EINVAL); 346*a93a1f58Sgm209912 if (session->s_name != NULL) 347*a93a1f58Sgm209912 return (EPROTO); 348*a93a1f58Sgm209912 return (commp_add_str(&session->s_name, name, strlen(name))); 349*a93a1f58Sgm209912 } 350*a93a1f58Sgm209912 351*a93a1f58Sgm209912 /* 352*a93a1f58Sgm209912 * Adds session information field to the session or media section of SDP. 353*a93a1f58Sgm209912 * i=<session description> 354*a93a1f58Sgm209912 */ 355*a93a1f58Sgm209912 int 356*a93a1f58Sgm209912 sdp_add_information(char **information, const char *value) 357*a93a1f58Sgm209912 { 358*a93a1f58Sgm209912 if (information == NULL || value == NULL) 359*a93a1f58Sgm209912 return (EINVAL); 360*a93a1f58Sgm209912 if (*information != NULL) 361*a93a1f58Sgm209912 return (EPROTO); 362*a93a1f58Sgm209912 return (commp_add_str(information, value, strlen(value))); 363*a93a1f58Sgm209912 } 364*a93a1f58Sgm209912 365*a93a1f58Sgm209912 /* 366*a93a1f58Sgm209912 * Adds uri field to the session. 367*a93a1f58Sgm209912 * u=<uri> 368*a93a1f58Sgm209912 */ 369*a93a1f58Sgm209912 int 370*a93a1f58Sgm209912 sdp_add_uri(sdp_session_t *session, const char *uri) 371*a93a1f58Sgm209912 { 372*a93a1f58Sgm209912 if (session == NULL || uri == NULL) 373*a93a1f58Sgm209912 return (EINVAL); 374*a93a1f58Sgm209912 if (session->s_uri != NULL) 375*a93a1f58Sgm209912 return (EPROTO); 376*a93a1f58Sgm209912 return (commp_add_str(&session->s_uri, uri, strlen(uri))); 377*a93a1f58Sgm209912 } 378*a93a1f58Sgm209912 379*a93a1f58Sgm209912 /* 380*a93a1f58Sgm209912 * Adds email address field to the session. 381*a93a1f58Sgm209912 * e=<email-address> 382*a93a1f58Sgm209912 */ 383*a93a1f58Sgm209912 int 384*a93a1f58Sgm209912 sdp_add_email(sdp_session_t *session, const char *email) 385*a93a1f58Sgm209912 { 386*a93a1f58Sgm209912 if (session == NULL || email == NULL || (strlen(email) == 0)) 387*a93a1f58Sgm209912 return (EINVAL); 388*a93a1f58Sgm209912 return (add_value_to_list(&session->s_email, email, strlen(email), 389*a93a1f58Sgm209912 B_TRUE)); 390*a93a1f58Sgm209912 } 391*a93a1f58Sgm209912 392*a93a1f58Sgm209912 /* 393*a93a1f58Sgm209912 * Adds phone number field to the session. 394*a93a1f58Sgm209912 * p=<phone-number> 395*a93a1f58Sgm209912 */ 396*a93a1f58Sgm209912 int 397*a93a1f58Sgm209912 sdp_add_phone(sdp_session_t *session, const char *phone) 398*a93a1f58Sgm209912 { 399*a93a1f58Sgm209912 if (session == NULL || phone == NULL || (strlen(phone) == 0)) 400*a93a1f58Sgm209912 return (EINVAL); 401*a93a1f58Sgm209912 return (add_value_to_list(&session->s_phone, phone, strlen(phone), 402*a93a1f58Sgm209912 B_TRUE)); 403*a93a1f58Sgm209912 } 404*a93a1f58Sgm209912 405*a93a1f58Sgm209912 /* 406*a93a1f58Sgm209912 * Adds connection field to the session or media section of SDP 407*a93a1f58Sgm209912 * c=<nettype> <addrtype> <connection-address>[/ttl]/<number of addresses> 408*a93a1f58Sgm209912 */ 409*a93a1f58Sgm209912 int 410*a93a1f58Sgm209912 sdp_add_connection(sdp_conn_t **conn, const char *nettype, const char *addrtype, 411*a93a1f58Sgm209912 const char *address, uint8_t ttl, int addrcount) 412*a93a1f58Sgm209912 { 413*a93a1f58Sgm209912 sdp_conn_t *tmp; 414*a93a1f58Sgm209912 sdp_conn_t *new_conn; 415*a93a1f58Sgm209912 int ret = 0; 416*a93a1f58Sgm209912 417*a93a1f58Sgm209912 if (conn == NULL || nettype == NULL || addrtype == NULL || 418*a93a1f58Sgm209912 address == NULL) { 419*a93a1f58Sgm209912 return (EINVAL); 420*a93a1f58Sgm209912 } 421*a93a1f58Sgm209912 new_conn = calloc(1, sizeof (sdp_conn_t)); 422*a93a1f58Sgm209912 if (new_conn == NULL) 423*a93a1f58Sgm209912 return (ENOMEM); 424*a93a1f58Sgm209912 new_conn->c_ttl = ttl; 425*a93a1f58Sgm209912 new_conn->c_addrcount = addrcount; 426*a93a1f58Sgm209912 if ((ret = commp_add_str(&new_conn->c_nettype, nettype, 427*a93a1f58Sgm209912 strlen(nettype))) != 0) { 428*a93a1f58Sgm209912 goto err_ret; 429*a93a1f58Sgm209912 } 430*a93a1f58Sgm209912 if ((ret = commp_add_str(&new_conn->c_addrtype, addrtype, 431*a93a1f58Sgm209912 strlen(addrtype))) != 0) { 432*a93a1f58Sgm209912 goto err_ret; 433*a93a1f58Sgm209912 } 434*a93a1f58Sgm209912 if ((ret = commp_add_str(&new_conn->c_address, address, 435*a93a1f58Sgm209912 strlen(address))) != 0) { 436*a93a1f58Sgm209912 goto err_ret; 437*a93a1f58Sgm209912 } 438*a93a1f58Sgm209912 if (*conn == NULL) { 439*a93a1f58Sgm209912 *conn = new_conn; 440*a93a1f58Sgm209912 } else { 441*a93a1f58Sgm209912 tmp = *conn; 442*a93a1f58Sgm209912 while (tmp->c_next != NULL) 443*a93a1f58Sgm209912 tmp = tmp->c_next; 444*a93a1f58Sgm209912 tmp->c_next = new_conn; 445*a93a1f58Sgm209912 } 446*a93a1f58Sgm209912 return (ret); 447*a93a1f58Sgm209912 err_ret: 448*a93a1f58Sgm209912 sdp_free_connection(new_conn); 449*a93a1f58Sgm209912 return (ret); 450*a93a1f58Sgm209912 } 451*a93a1f58Sgm209912 452*a93a1f58Sgm209912 /* 453*a93a1f58Sgm209912 * Adds bandwidth field to the session or media section of SDP. 454*a93a1f58Sgm209912 * b=<bwtype>:<bandwidth> 455*a93a1f58Sgm209912 */ 456*a93a1f58Sgm209912 int 457*a93a1f58Sgm209912 sdp_add_bandwidth(sdp_bandwidth_t **bw, const char *type, uint64_t value) 458*a93a1f58Sgm209912 { 459*a93a1f58Sgm209912 sdp_bandwidth_t *new_bw; 460*a93a1f58Sgm209912 sdp_bandwidth_t *tmp; 461*a93a1f58Sgm209912 int ret = 0; 462*a93a1f58Sgm209912 463*a93a1f58Sgm209912 if (bw == NULL || type == NULL) 464*a93a1f58Sgm209912 return (EINVAL); 465*a93a1f58Sgm209912 new_bw = calloc(1, sizeof (sdp_bandwidth_t)); 466*a93a1f58Sgm209912 if (new_bw == NULL) 467*a93a1f58Sgm209912 return (ENOMEM); 468*a93a1f58Sgm209912 new_bw->b_value = value; 469*a93a1f58Sgm209912 if ((ret = commp_add_str(&new_bw->b_type, type, strlen(type))) != 0) { 470*a93a1f58Sgm209912 free(new_bw); 471*a93a1f58Sgm209912 return (ret); 472*a93a1f58Sgm209912 } 473*a93a1f58Sgm209912 if (*bw == NULL) { 474*a93a1f58Sgm209912 *bw = new_bw; 475*a93a1f58Sgm209912 } else { 476*a93a1f58Sgm209912 tmp = *bw; 477*a93a1f58Sgm209912 while (tmp->b_next != NULL) 478*a93a1f58Sgm209912 tmp = tmp->b_next; 479*a93a1f58Sgm209912 tmp->b_next = new_bw; 480*a93a1f58Sgm209912 } 481*a93a1f58Sgm209912 return (ret); 482*a93a1f58Sgm209912 } 483*a93a1f58Sgm209912 484*a93a1f58Sgm209912 /* 485*a93a1f58Sgm209912 * Adds time field to the session 486*a93a1f58Sgm209912 * t=<start-time> <stop-time> 487*a93a1f58Sgm209912 */ 488*a93a1f58Sgm209912 int 489*a93a1f58Sgm209912 sdp_add_time(sdp_session_t *session, uint64_t starttime, uint64_t stoptime, 490*a93a1f58Sgm209912 sdp_time_t **time) 491*a93a1f58Sgm209912 { 492*a93a1f58Sgm209912 sdp_time_t *new_time; 493*a93a1f58Sgm209912 sdp_time_t *tmp; 494*a93a1f58Sgm209912 495*a93a1f58Sgm209912 if (time != NULL) 496*a93a1f58Sgm209912 *time = NULL; 497*a93a1f58Sgm209912 if (session == NULL) { 498*a93a1f58Sgm209912 return (EINVAL); 499*a93a1f58Sgm209912 } 500*a93a1f58Sgm209912 new_time = calloc(1, sizeof (sdp_time_t)); 501*a93a1f58Sgm209912 if (new_time == NULL) { 502*a93a1f58Sgm209912 return (ENOMEM); 503*a93a1f58Sgm209912 } 504*a93a1f58Sgm209912 new_time->t_start = starttime; 505*a93a1f58Sgm209912 new_time->t_stop = stoptime; 506*a93a1f58Sgm209912 tmp = session->s_time; 507*a93a1f58Sgm209912 if (tmp == NULL) 508*a93a1f58Sgm209912 session->s_time = new_time; 509*a93a1f58Sgm209912 else { 510*a93a1f58Sgm209912 while (tmp->t_next != NULL) 511*a93a1f58Sgm209912 tmp = tmp->t_next; 512*a93a1f58Sgm209912 tmp->t_next = new_time; 513*a93a1f58Sgm209912 } 514*a93a1f58Sgm209912 if (time != NULL) 515*a93a1f58Sgm209912 *time = new_time; 516*a93a1f58Sgm209912 return (0); 517*a93a1f58Sgm209912 } 518*a93a1f58Sgm209912 519*a93a1f58Sgm209912 /* 520*a93a1f58Sgm209912 * Adds repeat field to the time structure of session 521*a93a1f58Sgm209912 * r=<repeat interval> <active duration> <offsets from start-time> 522*a93a1f58Sgm209912 */ 523*a93a1f58Sgm209912 int 524*a93a1f58Sgm209912 sdp_add_repeat(sdp_time_t *time, uint64_t interval, uint64_t duration, 525*a93a1f58Sgm209912 const char *offset) 526*a93a1f58Sgm209912 { 527*a93a1f58Sgm209912 sdp_repeat_t *tmp; 528*a93a1f58Sgm209912 sdp_repeat_t *new_repeat; 529*a93a1f58Sgm209912 int ret = 0; 530*a93a1f58Sgm209912 531*a93a1f58Sgm209912 if (time == NULL || offset == NULL) 532*a93a1f58Sgm209912 return (EINVAL); 533*a93a1f58Sgm209912 new_repeat = calloc(1, sizeof (sdp_repeat_t)); 534*a93a1f58Sgm209912 if (new_repeat == NULL) 535*a93a1f58Sgm209912 return (ENOMEM); 536*a93a1f58Sgm209912 new_repeat->r_interval = interval; 537*a93a1f58Sgm209912 new_repeat->r_duration = duration; 538*a93a1f58Sgm209912 if ((ret = sdp_str_to_list(&new_repeat->r_offset, offset, 539*a93a1f58Sgm209912 strlen(offset), B_FALSE)) != 0) { 540*a93a1f58Sgm209912 goto err_ret; 541*a93a1f58Sgm209912 } 542*a93a1f58Sgm209912 tmp = time->t_repeat; 543*a93a1f58Sgm209912 if (tmp == NULL) { 544*a93a1f58Sgm209912 time->t_repeat = new_repeat; 545*a93a1f58Sgm209912 } else { 546*a93a1f58Sgm209912 while (tmp->r_next != NULL) 547*a93a1f58Sgm209912 tmp = tmp->r_next; 548*a93a1f58Sgm209912 tmp->r_next = new_repeat; 549*a93a1f58Sgm209912 } 550*a93a1f58Sgm209912 return (ret); 551*a93a1f58Sgm209912 err_ret: 552*a93a1f58Sgm209912 sdp_free_repeat(new_repeat); 553*a93a1f58Sgm209912 return (ret); 554*a93a1f58Sgm209912 } 555*a93a1f58Sgm209912 556*a93a1f58Sgm209912 /* 557*a93a1f58Sgm209912 * Adds time zone field to the session 558*a93a1f58Sgm209912 * z=<adjustment time> <offset> <adjustment time> <offset> .... 559*a93a1f58Sgm209912 */ 560*a93a1f58Sgm209912 int 561*a93a1f58Sgm209912 sdp_add_zone(sdp_session_t *session, uint64_t time, const char *offset) 562*a93a1f58Sgm209912 { 563*a93a1f58Sgm209912 sdp_zone_t *new_zone; 564*a93a1f58Sgm209912 sdp_zone_t *tmp; 565*a93a1f58Sgm209912 int ret = 0; 566*a93a1f58Sgm209912 567*a93a1f58Sgm209912 if (session == NULL || offset == NULL) 568*a93a1f58Sgm209912 return (EINVAL); 569*a93a1f58Sgm209912 new_zone = calloc(1, sizeof (sdp_zone_t)); 570*a93a1f58Sgm209912 if (new_zone == NULL) 571*a93a1f58Sgm209912 return (ENOMEM); 572*a93a1f58Sgm209912 new_zone->z_time = time; 573*a93a1f58Sgm209912 if ((ret = commp_add_str(&new_zone->z_offset, offset, 574*a93a1f58Sgm209912 strlen(offset))) != 0) { 575*a93a1f58Sgm209912 free(new_zone); 576*a93a1f58Sgm209912 return (ret); 577*a93a1f58Sgm209912 } 578*a93a1f58Sgm209912 tmp = session->s_zone; 579*a93a1f58Sgm209912 if (tmp == NULL) { 580*a93a1f58Sgm209912 session->s_zone = new_zone; 581*a93a1f58Sgm209912 } else { 582*a93a1f58Sgm209912 while (tmp->z_next != NULL) { 583*a93a1f58Sgm209912 tmp = tmp->z_next; 584*a93a1f58Sgm209912 } 585*a93a1f58Sgm209912 tmp->z_next = new_zone; 586*a93a1f58Sgm209912 } 587*a93a1f58Sgm209912 return (ret); 588*a93a1f58Sgm209912 } 589*a93a1f58Sgm209912 590*a93a1f58Sgm209912 /* 591*a93a1f58Sgm209912 * Adds key field to session or media section of SDP. 592*a93a1f58Sgm209912 * k=<method> 593*a93a1f58Sgm209912 * k=<method>:<encryption key> 594*a93a1f58Sgm209912 */ 595*a93a1f58Sgm209912 int 596*a93a1f58Sgm209912 sdp_add_key(sdp_key_t **key, const char *method, const char *enckey) 597*a93a1f58Sgm209912 { 598*a93a1f58Sgm209912 int ret = 0; 599*a93a1f58Sgm209912 600*a93a1f58Sgm209912 if (key == NULL || method == NULL) 601*a93a1f58Sgm209912 return (EINVAL); 602*a93a1f58Sgm209912 if (*key != NULL) 603*a93a1f58Sgm209912 return (EPROTO); 604*a93a1f58Sgm209912 *key = calloc(1, sizeof (sdp_key_t)); 605*a93a1f58Sgm209912 if (*key == NULL) 606*a93a1f58Sgm209912 return (ENOMEM); 607*a93a1f58Sgm209912 if ((ret = commp_add_str(&((*key)->k_method), method, 608*a93a1f58Sgm209912 strlen(method))) != 0) { 609*a93a1f58Sgm209912 goto err_ret; 610*a93a1f58Sgm209912 } 611*a93a1f58Sgm209912 if (enckey != NULL) { 612*a93a1f58Sgm209912 if ((ret = commp_add_str(&((*key)->k_enckey), enckey, 613*a93a1f58Sgm209912 strlen(enckey))) != 0) { 614*a93a1f58Sgm209912 goto err_ret; 615*a93a1f58Sgm209912 } 616*a93a1f58Sgm209912 } 617*a93a1f58Sgm209912 return (ret); 618*a93a1f58Sgm209912 err_ret: 619*a93a1f58Sgm209912 sdp_free_key(*key); 620*a93a1f58Sgm209912 *key = NULL; 621*a93a1f58Sgm209912 return (ret); 622*a93a1f58Sgm209912 } 623*a93a1f58Sgm209912 624*a93a1f58Sgm209912 /* 625*a93a1f58Sgm209912 * Adds attribute field to session or media section of SDP. 626*a93a1f58Sgm209912 * a=<attribute> 627*a93a1f58Sgm209912 * a=<attribute>:<value> 628*a93a1f58Sgm209912 */ 629*a93a1f58Sgm209912 int 630*a93a1f58Sgm209912 sdp_add_attribute(sdp_attr_t **attr, const char *name, const char *value) 631*a93a1f58Sgm209912 { 632*a93a1f58Sgm209912 sdp_attr_t *tmp; 633*a93a1f58Sgm209912 sdp_attr_t *new_attr; 634*a93a1f58Sgm209912 int ret = 0; 635*a93a1f58Sgm209912 636*a93a1f58Sgm209912 if (attr == NULL || name == NULL) 637*a93a1f58Sgm209912 return (EINVAL); 638*a93a1f58Sgm209912 new_attr = calloc(1, sizeof (sdp_attr_t)); 639*a93a1f58Sgm209912 if (new_attr == NULL) 640*a93a1f58Sgm209912 return (ENOMEM); 641*a93a1f58Sgm209912 if ((ret = commp_add_str(&new_attr->a_name, name, strlen(name))) != 0) 642*a93a1f58Sgm209912 goto err_ret; 643*a93a1f58Sgm209912 if (value != NULL) { 644*a93a1f58Sgm209912 if ((ret = commp_add_str(&new_attr->a_value, value, 645*a93a1f58Sgm209912 strlen(value))) != 0) { 646*a93a1f58Sgm209912 goto err_ret; 647*a93a1f58Sgm209912 } 648*a93a1f58Sgm209912 } 649*a93a1f58Sgm209912 tmp = *attr; 650*a93a1f58Sgm209912 if (tmp == NULL) { 651*a93a1f58Sgm209912 *attr = new_attr; 652*a93a1f58Sgm209912 } else { 653*a93a1f58Sgm209912 while (tmp->a_next != NULL) 654*a93a1f58Sgm209912 tmp = tmp->a_next; 655*a93a1f58Sgm209912 tmp->a_next = new_attr; 656*a93a1f58Sgm209912 } 657*a93a1f58Sgm209912 return (ret); 658*a93a1f58Sgm209912 err_ret: 659*a93a1f58Sgm209912 sdp_free_attribute(new_attr); 660*a93a1f58Sgm209912 return (ret); 661*a93a1f58Sgm209912 } 662*a93a1f58Sgm209912 663*a93a1f58Sgm209912 /* 664*a93a1f58Sgm209912 * Adds media field to the session. 665*a93a1f58Sgm209912 * m=<media> <port>[/portcount] <proto> <fmt> ... 666*a93a1f58Sgm209912 */ 667*a93a1f58Sgm209912 int 668*a93a1f58Sgm209912 sdp_add_media(sdp_session_t *session, const char *name, uint_t port, 669*a93a1f58Sgm209912 int portcount, const char *protocol, const char *fmt, sdp_media_t **media) 670*a93a1f58Sgm209912 { 671*a93a1f58Sgm209912 sdp_media_t *tmp; 672*a93a1f58Sgm209912 sdp_media_t *new_media; 673*a93a1f58Sgm209912 int ret = 0; 674*a93a1f58Sgm209912 675*a93a1f58Sgm209912 if (media != NULL) 676*a93a1f58Sgm209912 *media = NULL; 677*a93a1f58Sgm209912 if (session == NULL || name == NULL || protocol == NULL || 678*a93a1f58Sgm209912 portcount <= 0 || fmt == NULL) { 679*a93a1f58Sgm209912 return (EINVAL); 680*a93a1f58Sgm209912 } 681*a93a1f58Sgm209912 new_media = calloc(1, sizeof (sdp_media_t)); 682*a93a1f58Sgm209912 if (new_media == NULL) { 683*a93a1f58Sgm209912 return (ENOMEM); 684*a93a1f58Sgm209912 } 685*a93a1f58Sgm209912 new_media->m_session = session; 686*a93a1f58Sgm209912 new_media->m_port = port; 687*a93a1f58Sgm209912 new_media->m_portcount = portcount; 688*a93a1f58Sgm209912 if ((ret = commp_add_str(&new_media->m_name, name, strlen(name))) != 0) 689*a93a1f58Sgm209912 goto err_ret; 690*a93a1f58Sgm209912 if ((ret = commp_add_str(&new_media->m_proto, protocol, 691*a93a1f58Sgm209912 strlen(protocol))) != 0) { 692*a93a1f58Sgm209912 goto err_ret; 693*a93a1f58Sgm209912 } 694*a93a1f58Sgm209912 if ((ret = sdp_str_to_list(&new_media->m_format, fmt, 695*a93a1f58Sgm209912 strlen(fmt), B_TRUE)) != 0) { 696*a93a1f58Sgm209912 goto err_ret; 697*a93a1f58Sgm209912 } 698*a93a1f58Sgm209912 tmp = session->s_media; 699*a93a1f58Sgm209912 if (tmp == NULL) { 700*a93a1f58Sgm209912 session->s_media = new_media; 701*a93a1f58Sgm209912 } else { 702*a93a1f58Sgm209912 while (tmp->m_next != NULL) 703*a93a1f58Sgm209912 tmp = tmp->m_next; 704*a93a1f58Sgm209912 tmp->m_next = new_media; 705*a93a1f58Sgm209912 } 706*a93a1f58Sgm209912 if (media != NULL) 707*a93a1f58Sgm209912 *media = new_media; 708*a93a1f58Sgm209912 return (0); 709*a93a1f58Sgm209912 err_ret: 710*a93a1f58Sgm209912 sdp_free_media(new_media); 711*a93a1f58Sgm209912 return (ret); 712*a93a1f58Sgm209912 } 713*a93a1f58Sgm209912 714*a93a1f58Sgm209912 /* 715*a93a1f58Sgm209912 * This internal API is required by sdp_session_to_str(). It determines the 716*a93a1f58Sgm209912 * length of buffer that is required to hold the session. Since the RFC does 717*a93a1f58Sgm209912 * not limit the size of various sub-fields in the field. We need to scan 718*a93a1f58Sgm209912 * through the structure to determine the length. 719*a93a1f58Sgm209912 */ 720*a93a1f58Sgm209912 int 721*a93a1f58Sgm209912 sdp_get_length(const sdp_session_t *session) 722*a93a1f58Sgm209912 { 723*a93a1f58Sgm209912 int len = 0; 724*a93a1f58Sgm209912 char buf[1]; 725*a93a1f58Sgm209912 sdp_list_t *list; 726*a93a1f58Sgm209912 sdp_conn_t *conn; 727*a93a1f58Sgm209912 sdp_bandwidth_t *bw; 728*a93a1f58Sgm209912 sdp_zone_t *zone; 729*a93a1f58Sgm209912 sdp_time_t *time; 730*a93a1f58Sgm209912 sdp_repeat_t *repeat; 731*a93a1f58Sgm209912 sdp_attr_t *attr; 732*a93a1f58Sgm209912 sdp_media_t *media; 733*a93a1f58Sgm209912 734*a93a1f58Sgm209912 len += FIELD_EQUALS_CRLF_LEN; 735*a93a1f58Sgm209912 len += snprintf(buf, 1, "%d", session->s_version); 736*a93a1f58Sgm209912 if (session->s_origin != NULL) { 737*a93a1f58Sgm209912 len += FIELD_EQUALS_CRLF_LEN; 738*a93a1f58Sgm209912 len += strlen(session->s_origin->o_username); 739*a93a1f58Sgm209912 len += snprintf(buf, 1, "%llu", session->s_origin->o_id) + 1; 740*a93a1f58Sgm209912 len += snprintf(buf, 1, "%llu", session->s_origin->o_version) 741*a93a1f58Sgm209912 + 1; 742*a93a1f58Sgm209912 len += strlen(session->s_origin->o_nettype) + 1; 743*a93a1f58Sgm209912 len += strlen(session->s_origin->o_addrtype) + 1; 744*a93a1f58Sgm209912 len += strlen(session->s_origin->o_address) + 1; 745*a93a1f58Sgm209912 } 746*a93a1f58Sgm209912 if (session->s_name != NULL) 747*a93a1f58Sgm209912 len += strlen(session->s_name) + FIELD_EQUALS_CRLF_LEN; 748*a93a1f58Sgm209912 if (session->s_info != NULL) 749*a93a1f58Sgm209912 len += strlen(session->s_info) + FIELD_EQUALS_CRLF_LEN; 750*a93a1f58Sgm209912 if (session->s_uri != NULL) 751*a93a1f58Sgm209912 len += strlen(session->s_uri) + FIELD_EQUALS_CRLF_LEN; 752*a93a1f58Sgm209912 list = session->s_email; 753*a93a1f58Sgm209912 while (list != NULL) { 754*a93a1f58Sgm209912 len += strlen((char *)list->value) + FIELD_EQUALS_CRLF_LEN; 755*a93a1f58Sgm209912 list = list->next; 756*a93a1f58Sgm209912 } 757*a93a1f58Sgm209912 list = session->s_phone; 758*a93a1f58Sgm209912 while (list != NULL) { 759*a93a1f58Sgm209912 len += strlen((char *)list->value) + FIELD_EQUALS_CRLF_LEN; 760*a93a1f58Sgm209912 list = list->next; 761*a93a1f58Sgm209912 } 762*a93a1f58Sgm209912 conn = session->s_conn; 763*a93a1f58Sgm209912 SDP_LEN_CONNECTION(conn); 764*a93a1f58Sgm209912 bw = session->s_bw; 765*a93a1f58Sgm209912 SDP_LEN_BANDWIDTH(bw); 766*a93a1f58Sgm209912 time = session->s_time; 767*a93a1f58Sgm209912 while (time != NULL) { 768*a93a1f58Sgm209912 len += FIELD_EQUALS_CRLF_LEN; 769*a93a1f58Sgm209912 len += snprintf(buf, 1, "%llu", time->t_start); 770*a93a1f58Sgm209912 len += snprintf(buf, 1, "%llu", time->t_stop) + 1; 771*a93a1f58Sgm209912 repeat = time->t_repeat; 772*a93a1f58Sgm209912 while (repeat != NULL) { 773*a93a1f58Sgm209912 len += FIELD_EQUALS_CRLF_LEN; 774*a93a1f58Sgm209912 len += snprintf(buf, 1, "%llu", repeat->r_interval); 775*a93a1f58Sgm209912 len += snprintf(buf, 1, "%llu", repeat->r_duration) + 1; 776*a93a1f58Sgm209912 list = repeat->r_offset; 777*a93a1f58Sgm209912 while (list != NULL) { 778*a93a1f58Sgm209912 len += snprintf(buf, 1, "%llu", 779*a93a1f58Sgm209912 *(uint64_t *)list->value) + 1; 780*a93a1f58Sgm209912 list = list->next; 781*a93a1f58Sgm209912 } 782*a93a1f58Sgm209912 repeat = repeat->r_next; 783*a93a1f58Sgm209912 } 784*a93a1f58Sgm209912 time = time->t_next; 785*a93a1f58Sgm209912 } 786*a93a1f58Sgm209912 if (session->s_zone != NULL) 787*a93a1f58Sgm209912 len += FIELD_EQUALS_CRLF_LEN; 788*a93a1f58Sgm209912 zone = session->s_zone; 789*a93a1f58Sgm209912 while (zone != NULL) { 790*a93a1f58Sgm209912 len += snprintf(buf, 1, "%llu", zone->z_time) + 1; 791*a93a1f58Sgm209912 len += strlen(zone->z_offset) + 1; 792*a93a1f58Sgm209912 zone = zone->z_next; 793*a93a1f58Sgm209912 } 794*a93a1f58Sgm209912 SDP_LEN_KEY(session->s_key); 795*a93a1f58Sgm209912 attr = session->s_attr; 796*a93a1f58Sgm209912 SDP_LEN_ATTRIBUTE(attr); 797*a93a1f58Sgm209912 media = session->s_media; 798*a93a1f58Sgm209912 while (media != NULL) { 799*a93a1f58Sgm209912 len += FIELD_EQUALS_CRLF_LEN; 800*a93a1f58Sgm209912 len += strlen(media->m_name); 801*a93a1f58Sgm209912 len += snprintf(buf, 1, "%u", media->m_port) + 1; 802*a93a1f58Sgm209912 len += snprintf(buf, 1, "%d", media->m_portcount) + 1; 803*a93a1f58Sgm209912 len += strlen(media->m_proto) + 1; 804*a93a1f58Sgm209912 list = media->m_format; 805*a93a1f58Sgm209912 while (list != NULL) { 806*a93a1f58Sgm209912 len += strlen((char *)list->value) + 1; 807*a93a1f58Sgm209912 list = list->next; 808*a93a1f58Sgm209912 } 809*a93a1f58Sgm209912 if (media->m_info != NULL) 810*a93a1f58Sgm209912 len += strlen(media->m_info) + FIELD_EQUALS_CRLF_LEN; 811*a93a1f58Sgm209912 conn = media->m_conn; 812*a93a1f58Sgm209912 SDP_LEN_CONNECTION(conn); 813*a93a1f58Sgm209912 bw = media->m_bw; 814*a93a1f58Sgm209912 SDP_LEN_BANDWIDTH(bw); 815*a93a1f58Sgm209912 SDP_LEN_KEY(media->m_key); 816*a93a1f58Sgm209912 attr = media->m_attr; 817*a93a1f58Sgm209912 SDP_LEN_ATTRIBUTE(attr); 818*a93a1f58Sgm209912 media = media->m_next; 819*a93a1f58Sgm209912 } 820*a93a1f58Sgm209912 return (len); 821*a93a1f58Sgm209912 } 822*a93a1f58Sgm209912 823*a93a1f58Sgm209912 /* 824*a93a1f58Sgm209912 * Given a session structure it clones (deep copy) and returns the cloned copy 825*a93a1f58Sgm209912 */ 826*a93a1f58Sgm209912 sdp_session_t * 827*a93a1f58Sgm209912 sdp_clone_session(const sdp_session_t *session) 828*a93a1f58Sgm209912 { 829*a93a1f58Sgm209912 sdp_session_t *new_sess; 830*a93a1f58Sgm209912 sdp_origin_t *origin; 831*a93a1f58Sgm209912 sdp_list_t *list; 832*a93a1f58Sgm209912 sdp_time_t *time; 833*a93a1f58Sgm209912 sdp_time_t *new_time; 834*a93a1f58Sgm209912 sdp_repeat_t *repeat; 835*a93a1f58Sgm209912 sdp_media_t *media; 836*a93a1f58Sgm209912 sdp_media_t *new_media; 837*a93a1f58Sgm209912 sdp_conn_t *conn; 838*a93a1f58Sgm209912 sdp_bandwidth_t *bw; 839*a93a1f58Sgm209912 sdp_attr_t *attr; 840*a93a1f58Sgm209912 sdp_zone_t *zone; 841*a93a1f58Sgm209912 char *offset = NULL; 842*a93a1f58Sgm209912 char *format = NULL; 843*a93a1f58Sgm209912 844*a93a1f58Sgm209912 if (session == NULL) 845*a93a1f58Sgm209912 return (NULL); 846*a93a1f58Sgm209912 new_sess = calloc(1, sizeof (sdp_session_t)); 847*a93a1f58Sgm209912 if (new_sess == NULL) 848*a93a1f58Sgm209912 return (NULL); 849*a93a1f58Sgm209912 new_sess->sdp_session_version = session->sdp_session_version; 850*a93a1f58Sgm209912 new_sess->s_version = session->s_version; 851*a93a1f58Sgm209912 origin = session->s_origin; 852*a93a1f58Sgm209912 if (origin != NULL && (sdp_add_origin(new_sess, origin->o_username, 853*a93a1f58Sgm209912 origin->o_id, origin->o_version, origin->o_nettype, origin-> 854*a93a1f58Sgm209912 o_addrtype, origin->o_address) != 0)) { 855*a93a1f58Sgm209912 goto err_ret; 856*a93a1f58Sgm209912 } 857*a93a1f58Sgm209912 if (session->s_name != NULL && sdp_add_name(new_sess, session-> 858*a93a1f58Sgm209912 s_name) != 0) { 859*a93a1f58Sgm209912 goto err_ret; 860*a93a1f58Sgm209912 } 861*a93a1f58Sgm209912 if (session->s_info != NULL && sdp_add_information(&new_sess-> 862*a93a1f58Sgm209912 s_info, session->s_info) != 0) { 863*a93a1f58Sgm209912 goto err_ret; 864*a93a1f58Sgm209912 } 865*a93a1f58Sgm209912 if (session->s_uri != NULL && sdp_add_uri(new_sess, session-> 866*a93a1f58Sgm209912 s_uri) != 0) { 867*a93a1f58Sgm209912 goto err_ret; 868*a93a1f58Sgm209912 } 869*a93a1f58Sgm209912 list = session->s_email; 870*a93a1f58Sgm209912 while (list != NULL) { 871*a93a1f58Sgm209912 if (sdp_add_email(new_sess, (char *)list->value) != 0) 872*a93a1f58Sgm209912 goto err_ret; 873*a93a1f58Sgm209912 list = list->next; 874*a93a1f58Sgm209912 } 875*a93a1f58Sgm209912 list = session->s_phone; 876*a93a1f58Sgm209912 while (list != NULL) { 877*a93a1f58Sgm209912 if (sdp_add_phone(new_sess, (char *)list->value) != 0) 878*a93a1f58Sgm209912 goto err_ret; 879*a93a1f58Sgm209912 list = list->next; 880*a93a1f58Sgm209912 } 881*a93a1f58Sgm209912 conn = session->s_conn; 882*a93a1f58Sgm209912 SDP_ADD_CONNECTION(new_sess->s_conn, conn); 883*a93a1f58Sgm209912 bw = session->s_bw; 884*a93a1f58Sgm209912 SDP_ADD_BANDWIDTH(new_sess->s_bw, bw); 885*a93a1f58Sgm209912 time = session->s_time; 886*a93a1f58Sgm209912 while (time != NULL) { 887*a93a1f58Sgm209912 if (sdp_add_time(new_sess, time->t_start, time->t_stop, 888*a93a1f58Sgm209912 &new_time) != 0) { 889*a93a1f58Sgm209912 goto err_ret; 890*a93a1f58Sgm209912 } 891*a93a1f58Sgm209912 repeat = time->t_repeat; 892*a93a1f58Sgm209912 while (repeat != NULL) { 893*a93a1f58Sgm209912 if (sdp_list_to_str(repeat->r_offset, &offset, 894*a93a1f58Sgm209912 B_FALSE) != 0) { 895*a93a1f58Sgm209912 goto err_ret; 896*a93a1f58Sgm209912 } 897*a93a1f58Sgm209912 if (sdp_add_repeat(new_time, repeat->r_interval, 898*a93a1f58Sgm209912 repeat->r_duration, offset) != 0) { 899*a93a1f58Sgm209912 free(offset); 900*a93a1f58Sgm209912 goto err_ret; 901*a93a1f58Sgm209912 } 902*a93a1f58Sgm209912 free(offset); 903*a93a1f58Sgm209912 repeat = repeat->r_next; 904*a93a1f58Sgm209912 } 905*a93a1f58Sgm209912 time = time->t_next; 906*a93a1f58Sgm209912 } 907*a93a1f58Sgm209912 zone = session->s_zone; 908*a93a1f58Sgm209912 while (zone != NULL) { 909*a93a1f58Sgm209912 if (sdp_add_zone(new_sess, zone->z_time, zone->z_offset) != 0) 910*a93a1f58Sgm209912 goto err_ret; 911*a93a1f58Sgm209912 zone = zone->z_next; 912*a93a1f58Sgm209912 } 913*a93a1f58Sgm209912 SDP_ADD_KEY(new_sess->s_key, session->s_key); 914*a93a1f58Sgm209912 attr = session->s_attr; 915*a93a1f58Sgm209912 SDP_ADD_ATTRIBUTE(new_sess->s_attr, attr); 916*a93a1f58Sgm209912 media = session->s_media; 917*a93a1f58Sgm209912 while (media != NULL) { 918*a93a1f58Sgm209912 if (sdp_list_to_str(media->m_format, &format, B_TRUE) != 0) 919*a93a1f58Sgm209912 goto err_ret; 920*a93a1f58Sgm209912 if (sdp_add_media(new_sess, media->m_name, 921*a93a1f58Sgm209912 media->m_port, media->m_portcount, media->m_proto, 922*a93a1f58Sgm209912 format, &new_media) != 0) { 923*a93a1f58Sgm209912 free(format); 924*a93a1f58Sgm209912 goto err_ret; 925*a93a1f58Sgm209912 } 926*a93a1f58Sgm209912 free(format); 927*a93a1f58Sgm209912 if (media->m_info != NULL) { 928*a93a1f58Sgm209912 if (sdp_add_information(&new_media->m_info, 929*a93a1f58Sgm209912 media->m_info) != 0) { 930*a93a1f58Sgm209912 goto err_ret; 931*a93a1f58Sgm209912 } 932*a93a1f58Sgm209912 } 933*a93a1f58Sgm209912 conn = media->m_conn; 934*a93a1f58Sgm209912 SDP_ADD_CONNECTION(new_media->m_conn, conn); 935*a93a1f58Sgm209912 bw = media->m_bw; 936*a93a1f58Sgm209912 SDP_ADD_BANDWIDTH(new_media->m_bw, bw); 937*a93a1f58Sgm209912 SDP_ADD_KEY(new_media->m_key, media->m_key); 938*a93a1f58Sgm209912 attr = media->m_attr; 939*a93a1f58Sgm209912 SDP_ADD_ATTRIBUTE(new_media->m_attr, attr); 940*a93a1f58Sgm209912 new_media->m_session = new_sess; 941*a93a1f58Sgm209912 media = media->m_next; 942*a93a1f58Sgm209912 } 943*a93a1f58Sgm209912 return (new_sess); 944*a93a1f58Sgm209912 err_ret: 945*a93a1f58Sgm209912 sdp_free_session(new_sess); 946*a93a1f58Sgm209912 return (NULL); 947*a93a1f58Sgm209912 } 948*a93a1f58Sgm209912 949*a93a1f58Sgm209912 /* 950*a93a1f58Sgm209912 * should i check if individual members are NULL, if not snprintf 951*a93a1f58Sgm209912 * will core dump. 952*a93a1f58Sgm209912 */ 953*a93a1f58Sgm209912 /* 954*a93a1f58Sgm209912 * Given a session structure, this API converts it into character 955*a93a1f58Sgm209912 * buffer, which will be used as a payload later on. 956*a93a1f58Sgm209912 */ 957*a93a1f58Sgm209912 char * 958*a93a1f58Sgm209912 sdp_session_to_str(const sdp_session_t *session, int *error) 959*a93a1f58Sgm209912 { 960*a93a1f58Sgm209912 char *ret = NULL; 961*a93a1f58Sgm209912 char *buf = NULL; 962*a93a1f58Sgm209912 int len = 0; 963*a93a1f58Sgm209912 int s_len = 0; 964*a93a1f58Sgm209912 int wrote = 0; 965*a93a1f58Sgm209912 sdp_origin_t *origin; 966*a93a1f58Sgm209912 sdp_list_t *list; 967*a93a1f58Sgm209912 sdp_conn_t *conn; 968*a93a1f58Sgm209912 sdp_attr_t *attr; 969*a93a1f58Sgm209912 sdp_bandwidth_t *bw; 970*a93a1f58Sgm209912 sdp_time_t *time; 971*a93a1f58Sgm209912 sdp_repeat_t *repeat; 972*a93a1f58Sgm209912 sdp_zone_t *zone; 973*a93a1f58Sgm209912 sdp_media_t *media; 974*a93a1f58Sgm209912 975*a93a1f58Sgm209912 if (error != NULL) 976*a93a1f58Sgm209912 *error = 0; 977*a93a1f58Sgm209912 if (session == NULL) { 978*a93a1f58Sgm209912 if (error != NULL) 979*a93a1f58Sgm209912 *error = EINVAL; 980*a93a1f58Sgm209912 return (NULL); 981*a93a1f58Sgm209912 } 982*a93a1f58Sgm209912 s_len = sdp_get_length(session); 983*a93a1f58Sgm209912 ret = malloc(s_len + 1); 984*a93a1f58Sgm209912 if (ret == NULL) { 985*a93a1f58Sgm209912 if (error != NULL) 986*a93a1f58Sgm209912 *error = ENOMEM; 987*a93a1f58Sgm209912 return (NULL); 988*a93a1f58Sgm209912 } 989*a93a1f58Sgm209912 buf = ret; 990*a93a1f58Sgm209912 len = s_len + 1; 991*a93a1f58Sgm209912 wrote = snprintf(buf, len, "v=%d%s", session->s_version, COMMP_CRLF); 992*a93a1f58Sgm209912 len = len - wrote; 993*a93a1f58Sgm209912 buf = buf + wrote; 994*a93a1f58Sgm209912 origin = session->s_origin; 995*a93a1f58Sgm209912 if (origin != NULL) { 996*a93a1f58Sgm209912 wrote = snprintf(buf, len, "o=%s %llu %llu %s %s %s%s", 997*a93a1f58Sgm209912 origin->o_username, origin->o_id, origin->o_version, 998*a93a1f58Sgm209912 origin->o_nettype, origin->o_addrtype, origin->o_address, 999*a93a1f58Sgm209912 COMMP_CRLF); 1000*a93a1f58Sgm209912 len = len - wrote; 1001*a93a1f58Sgm209912 buf = buf + wrote; 1002*a93a1f58Sgm209912 } 1003*a93a1f58Sgm209912 if (session->s_name != NULL) { 1004*a93a1f58Sgm209912 wrote = snprintf(buf, len, "s=%s%s", session->s_name, 1005*a93a1f58Sgm209912 COMMP_CRLF); 1006*a93a1f58Sgm209912 len = len - wrote; 1007*a93a1f58Sgm209912 buf = buf + wrote; 1008*a93a1f58Sgm209912 } 1009*a93a1f58Sgm209912 SDP_INFORMATION_TO_STR(session->s_info); 1010*a93a1f58Sgm209912 if (session->s_uri != NULL) { 1011*a93a1f58Sgm209912 wrote = snprintf(buf, len, "u=%s%s", session->s_uri, 1012*a93a1f58Sgm209912 COMMP_CRLF); 1013*a93a1f58Sgm209912 len = len - wrote; 1014*a93a1f58Sgm209912 buf = buf + wrote; 1015*a93a1f58Sgm209912 } 1016*a93a1f58Sgm209912 list = session->s_email; 1017*a93a1f58Sgm209912 while (list != NULL) { 1018*a93a1f58Sgm209912 wrote = snprintf(buf, len, "e=%s%s", (char *)list->value, 1019*a93a1f58Sgm209912 COMMP_CRLF); 1020*a93a1f58Sgm209912 len = len - wrote; 1021*a93a1f58Sgm209912 buf = buf + wrote; 1022*a93a1f58Sgm209912 list = list->next; 1023*a93a1f58Sgm209912 } 1024*a93a1f58Sgm209912 list = session->s_phone; 1025*a93a1f58Sgm209912 while (list != NULL) { 1026*a93a1f58Sgm209912 wrote = snprintf(buf, len, "p=%s%s", (char *)list->value, 1027*a93a1f58Sgm209912 COMMP_CRLF); 1028*a93a1f58Sgm209912 len = len - wrote; 1029*a93a1f58Sgm209912 buf = buf + wrote; 1030*a93a1f58Sgm209912 list = list->next; 1031*a93a1f58Sgm209912 } 1032*a93a1f58Sgm209912 conn = session->s_conn; 1033*a93a1f58Sgm209912 SDP_CONNECTION_TO_STR(conn); 1034*a93a1f58Sgm209912 bw = session->s_bw; 1035*a93a1f58Sgm209912 SDP_BANDWIDTH_TO_STR(bw); 1036*a93a1f58Sgm209912 time = session->s_time; 1037*a93a1f58Sgm209912 while (time != NULL) { 1038*a93a1f58Sgm209912 wrote = snprintf(buf, len, "t=%llu %llu%s", time->t_start, 1039*a93a1f58Sgm209912 time->t_stop, COMMP_CRLF); 1040*a93a1f58Sgm209912 len = len - wrote; 1041*a93a1f58Sgm209912 buf = buf + wrote; 1042*a93a1f58Sgm209912 repeat = time->t_repeat; 1043*a93a1f58Sgm209912 while (repeat != NULL) { 1044*a93a1f58Sgm209912 wrote = snprintf(buf, len, "r=%llu %llu", repeat-> 1045*a93a1f58Sgm209912 r_interval, repeat->r_duration); 1046*a93a1f58Sgm209912 len = len - wrote; 1047*a93a1f58Sgm209912 buf = buf + wrote; 1048*a93a1f58Sgm209912 list = repeat->r_offset; 1049*a93a1f58Sgm209912 while (list != NULL) { 1050*a93a1f58Sgm209912 wrote = snprintf(buf, len, " %llu", 1051*a93a1f58Sgm209912 *(uint64_t *)list->value); 1052*a93a1f58Sgm209912 len = len - wrote; 1053*a93a1f58Sgm209912 buf = buf + wrote; 1054*a93a1f58Sgm209912 list = list->next; 1055*a93a1f58Sgm209912 } 1056*a93a1f58Sgm209912 wrote = snprintf(buf, len, "%s", COMMP_CRLF); 1057*a93a1f58Sgm209912 len = len - wrote; 1058*a93a1f58Sgm209912 buf = buf + wrote; 1059*a93a1f58Sgm209912 repeat = repeat->r_next; 1060*a93a1f58Sgm209912 } 1061*a93a1f58Sgm209912 time = time->t_next; 1062*a93a1f58Sgm209912 } 1063*a93a1f58Sgm209912 zone = session->s_zone; 1064*a93a1f58Sgm209912 if (zone != NULL) { 1065*a93a1f58Sgm209912 wrote = snprintf(buf, len, "z=%llu %s", zone->z_time, 1066*a93a1f58Sgm209912 zone->z_offset); 1067*a93a1f58Sgm209912 len = len - wrote; 1068*a93a1f58Sgm209912 buf = buf + wrote; 1069*a93a1f58Sgm209912 zone = zone->z_next; 1070*a93a1f58Sgm209912 while (zone != NULL) { 1071*a93a1f58Sgm209912 wrote = snprintf(buf, len, " %llu %s", zone->z_time, 1072*a93a1f58Sgm209912 zone->z_offset); 1073*a93a1f58Sgm209912 len = len - wrote; 1074*a93a1f58Sgm209912 buf = buf + wrote; 1075*a93a1f58Sgm209912 zone = zone->z_next; 1076*a93a1f58Sgm209912 } 1077*a93a1f58Sgm209912 wrote = snprintf(buf, len, "%s", COMMP_CRLF); 1078*a93a1f58Sgm209912 len = len - wrote; 1079*a93a1f58Sgm209912 buf = buf + wrote; 1080*a93a1f58Sgm209912 } 1081*a93a1f58Sgm209912 SDP_KEY_TO_STR(session->s_key); 1082*a93a1f58Sgm209912 attr = session->s_attr; 1083*a93a1f58Sgm209912 SDP_ATTR_TO_STR(attr); 1084*a93a1f58Sgm209912 media = session->s_media; 1085*a93a1f58Sgm209912 while (media != NULL) { 1086*a93a1f58Sgm209912 if (media->m_portcount == 1) { 1087*a93a1f58Sgm209912 wrote = snprintf(buf, len, "m=%s %d %s", media->m_name, 1088*a93a1f58Sgm209912 media->m_port, media->m_proto); 1089*a93a1f58Sgm209912 } else { 1090*a93a1f58Sgm209912 wrote = snprintf(buf, len, "m=%s %d/%d %s", media-> 1091*a93a1f58Sgm209912 m_name, media->m_port, media->m_portcount, media-> 1092*a93a1f58Sgm209912 m_proto); 1093*a93a1f58Sgm209912 } 1094*a93a1f58Sgm209912 len = len - wrote; 1095*a93a1f58Sgm209912 buf = buf + wrote; 1096*a93a1f58Sgm209912 list = media->m_format; 1097*a93a1f58Sgm209912 while (list != NULL) { 1098*a93a1f58Sgm209912 wrote = snprintf(buf, len, " %s", (char *)list->value); 1099*a93a1f58Sgm209912 len = len - wrote; 1100*a93a1f58Sgm209912 buf = buf + wrote; 1101*a93a1f58Sgm209912 list = list->next; 1102*a93a1f58Sgm209912 } 1103*a93a1f58Sgm209912 wrote = snprintf(buf, len, "%s", COMMP_CRLF); 1104*a93a1f58Sgm209912 len = len - wrote; 1105*a93a1f58Sgm209912 buf = buf + wrote; 1106*a93a1f58Sgm209912 SDP_INFORMATION_TO_STR(media->m_info); 1107*a93a1f58Sgm209912 conn = media->m_conn; 1108*a93a1f58Sgm209912 SDP_CONNECTION_TO_STR(conn); 1109*a93a1f58Sgm209912 bw = media->m_bw; 1110*a93a1f58Sgm209912 SDP_BANDWIDTH_TO_STR(bw); 1111*a93a1f58Sgm209912 SDP_KEY_TO_STR(media->m_key); 1112*a93a1f58Sgm209912 attr = media->m_attr; 1113*a93a1f58Sgm209912 SDP_ATTR_TO_STR(attr); 1114*a93a1f58Sgm209912 media = media->m_next; 1115*a93a1f58Sgm209912 } 1116*a93a1f58Sgm209912 assert(len >= 1); 1117*a93a1f58Sgm209912 *buf = '\0'; 1118*a93a1f58Sgm209912 return (ret); 1119*a93a1f58Sgm209912 } 1120*a93a1f58Sgm209912 1121*a93a1f58Sgm209912 /* 1122*a93a1f58Sgm209912 * Given a session structure and the field ('v', 'o', 's', et al), this API 1123*a93a1f58Sgm209912 * deletes the corresponding structure element. It frees the memory and sets the 1124*a93a1f58Sgm209912 * pointer to NULL 1125*a93a1f58Sgm209912 */ 1126*a93a1f58Sgm209912 int 1127*a93a1f58Sgm209912 sdp_delete_all_field(sdp_session_t *session, const char field) 1128*a93a1f58Sgm209912 { 1129*a93a1f58Sgm209912 if (session == NULL) 1130*a93a1f58Sgm209912 return (EINVAL); 1131*a93a1f58Sgm209912 switch (field) { 1132*a93a1f58Sgm209912 case SDP_ORIGIN_FIELD: 1133*a93a1f58Sgm209912 sdp_free_origin(session->s_origin); 1134*a93a1f58Sgm209912 session->s_origin = NULL; 1135*a93a1f58Sgm209912 break; 1136*a93a1f58Sgm209912 case SDP_NAME_FIELD: 1137*a93a1f58Sgm209912 free(session->s_name); 1138*a93a1f58Sgm209912 session->s_name = NULL; 1139*a93a1f58Sgm209912 break; 1140*a93a1f58Sgm209912 case SDP_INFO_FIELD: 1141*a93a1f58Sgm209912 free(session->s_info); 1142*a93a1f58Sgm209912 session->s_info = NULL; 1143*a93a1f58Sgm209912 break; 1144*a93a1f58Sgm209912 case SDP_URI_FIELD: 1145*a93a1f58Sgm209912 free(session->s_uri); 1146*a93a1f58Sgm209912 session->s_uri = NULL; 1147*a93a1f58Sgm209912 break; 1148*a93a1f58Sgm209912 case SDP_EMAIL_FIELD: 1149*a93a1f58Sgm209912 sdp_free_list(session->s_email); 1150*a93a1f58Sgm209912 session->s_email = NULL; 1151*a93a1f58Sgm209912 break; 1152*a93a1f58Sgm209912 case SDP_PHONE_FIELD: 1153*a93a1f58Sgm209912 sdp_free_list(session->s_phone); 1154*a93a1f58Sgm209912 session->s_phone = NULL; 1155*a93a1f58Sgm209912 break; 1156*a93a1f58Sgm209912 case SDP_CONNECTION_FIELD: 1157*a93a1f58Sgm209912 sdp_free_connection(session->s_conn); 1158*a93a1f58Sgm209912 session->s_conn = NULL; 1159*a93a1f58Sgm209912 break; 1160*a93a1f58Sgm209912 case SDP_BANDWIDTH_FIELD: 1161*a93a1f58Sgm209912 sdp_free_bandwidth(session->s_bw); 1162*a93a1f58Sgm209912 session->s_bw = NULL; 1163*a93a1f58Sgm209912 break; 1164*a93a1f58Sgm209912 case SDP_TIME_FIELD: 1165*a93a1f58Sgm209912 sdp_free_time(session->s_time); 1166*a93a1f58Sgm209912 session->s_time = NULL; 1167*a93a1f58Sgm209912 break; 1168*a93a1f58Sgm209912 case SDP_ZONE_FIELD: 1169*a93a1f58Sgm209912 sdp_free_zone(session->s_zone); 1170*a93a1f58Sgm209912 session->s_zone = NULL; 1171*a93a1f58Sgm209912 break; 1172*a93a1f58Sgm209912 case SDP_KEY_FIELD: 1173*a93a1f58Sgm209912 sdp_free_key(session->s_key); 1174*a93a1f58Sgm209912 session->s_key = NULL; 1175*a93a1f58Sgm209912 break; 1176*a93a1f58Sgm209912 case SDP_ATTRIBUTE_FIELD: 1177*a93a1f58Sgm209912 sdp_free_attribute(session->s_attr); 1178*a93a1f58Sgm209912 session->s_attr = NULL; 1179*a93a1f58Sgm209912 break; 1180*a93a1f58Sgm209912 case SDP_MEDIA_FIELD: 1181*a93a1f58Sgm209912 sdp_free_media(session->s_media); 1182*a93a1f58Sgm209912 session->s_media = NULL; 1183*a93a1f58Sgm209912 break; 1184*a93a1f58Sgm209912 default: 1185*a93a1f58Sgm209912 return (EINVAL); 1186*a93a1f58Sgm209912 } 1187*a93a1f58Sgm209912 return (0); 1188*a93a1f58Sgm209912 } 1189*a93a1f58Sgm209912 1190*a93a1f58Sgm209912 /* 1191*a93a1f58Sgm209912 * Given a media structure and the field ('i', 'b', 'c', et al), this API 1192*a93a1f58Sgm209912 * deletes the corresponding structure element. It frees the memory and sets 1193*a93a1f58Sgm209912 * the pointer to NULL. 1194*a93a1f58Sgm209912 */ 1195*a93a1f58Sgm209912 int 1196*a93a1f58Sgm209912 sdp_delete_all_media_field(sdp_media_t *media, const char field) 1197*a93a1f58Sgm209912 { 1198*a93a1f58Sgm209912 if (media == NULL) 1199*a93a1f58Sgm209912 return (EINVAL); 1200*a93a1f58Sgm209912 switch (field) { 1201*a93a1f58Sgm209912 case SDP_INFO_FIELD: 1202*a93a1f58Sgm209912 free(media->m_info); 1203*a93a1f58Sgm209912 media->m_info = NULL; 1204*a93a1f58Sgm209912 break; 1205*a93a1f58Sgm209912 case SDP_CONNECTION_FIELD: 1206*a93a1f58Sgm209912 sdp_free_connection(media->m_conn); 1207*a93a1f58Sgm209912 media->m_conn = NULL; 1208*a93a1f58Sgm209912 break; 1209*a93a1f58Sgm209912 case SDP_BANDWIDTH_FIELD: 1210*a93a1f58Sgm209912 sdp_free_bandwidth(media->m_bw); 1211*a93a1f58Sgm209912 media->m_bw = NULL; 1212*a93a1f58Sgm209912 break; 1213*a93a1f58Sgm209912 case SDP_KEY_FIELD: 1214*a93a1f58Sgm209912 sdp_free_key(media->m_key); 1215*a93a1f58Sgm209912 media->m_key = NULL; 1216*a93a1f58Sgm209912 break; 1217*a93a1f58Sgm209912 case SDP_ATTRIBUTE_FIELD: 1218*a93a1f58Sgm209912 sdp_free_attribute(media->m_attr); 1219*a93a1f58Sgm209912 media->m_attr = NULL; 1220*a93a1f58Sgm209912 break; 1221*a93a1f58Sgm209912 default: 1222*a93a1f58Sgm209912 return (EINVAL); 1223*a93a1f58Sgm209912 } 1224*a93a1f58Sgm209912 return (0); 1225*a93a1f58Sgm209912 } 1226*a93a1f58Sgm209912 1227*a93a1f58Sgm209912 /* 1228*a93a1f58Sgm209912 * Given a media list and the media, this API deletes that media from the 1229*a93a1f58Sgm209912 * list. It frees the memory corresponding to that media. 1230*a93a1f58Sgm209912 */ 1231*a93a1f58Sgm209912 int 1232*a93a1f58Sgm209912 sdp_delete_media(sdp_media_t **l_media, sdp_media_t *media) 1233*a93a1f58Sgm209912 { 1234*a93a1f58Sgm209912 sdp_media_t *cur; 1235*a93a1f58Sgm209912 sdp_media_t *prev; 1236*a93a1f58Sgm209912 1237*a93a1f58Sgm209912 if (l_media == NULL || *l_media == NULL || media == NULL) 1238*a93a1f58Sgm209912 return (EINVAL); 1239*a93a1f58Sgm209912 cur = *l_media; 1240*a93a1f58Sgm209912 prev = NULL; 1241*a93a1f58Sgm209912 while (cur != NULL && cur != media) { 1242*a93a1f58Sgm209912 prev = cur; 1243*a93a1f58Sgm209912 cur = cur->m_next; 1244*a93a1f58Sgm209912 } 1245*a93a1f58Sgm209912 if (cur == NULL) 1246*a93a1f58Sgm209912 return (EINVAL); 1247*a93a1f58Sgm209912 if (cur == *l_media) 1248*a93a1f58Sgm209912 *l_media = cur->m_next; 1249*a93a1f58Sgm209912 else 1250*a93a1f58Sgm209912 prev->m_next = cur->m_next; 1251*a93a1f58Sgm209912 cur->m_next = NULL; 1252*a93a1f58Sgm209912 sdp_free_media(cur); 1253*a93a1f58Sgm209912 return (0); 1254*a93a1f58Sgm209912 } 1255*a93a1f58Sgm209912 1256*a93a1f58Sgm209912 /* 1257*a93a1f58Sgm209912 * Given an attribute list and an attribute, this API deletes that attribue 1258*a93a1f58Sgm209912 * from the list. It frees the memory corresponding to that attribute. 1259*a93a1f58Sgm209912 */ 1260*a93a1f58Sgm209912 int 1261*a93a1f58Sgm209912 sdp_delete_attribute(sdp_attr_t **l_attr, sdp_attr_t *attr) 1262*a93a1f58Sgm209912 { 1263*a93a1f58Sgm209912 sdp_attr_t *cur; 1264*a93a1f58Sgm209912 sdp_attr_t *prev; 1265*a93a1f58Sgm209912 1266*a93a1f58Sgm209912 if (l_attr == NULL || *l_attr == NULL || attr == NULL) 1267*a93a1f58Sgm209912 return (EINVAL); 1268*a93a1f58Sgm209912 cur = *l_attr; 1269*a93a1f58Sgm209912 prev = NULL; 1270*a93a1f58Sgm209912 while (cur != NULL && cur != attr) { 1271*a93a1f58Sgm209912 prev = cur; 1272*a93a1f58Sgm209912 cur = cur->a_next; 1273*a93a1f58Sgm209912 } 1274*a93a1f58Sgm209912 if (cur == NULL) 1275*a93a1f58Sgm209912 return (EINVAL); 1276*a93a1f58Sgm209912 if (cur == *l_attr) 1277*a93a1f58Sgm209912 *l_attr = cur->a_next; 1278*a93a1f58Sgm209912 else 1279*a93a1f58Sgm209912 prev->a_next = cur->a_next; 1280*a93a1f58Sgm209912 cur->a_next = NULL; 1281*a93a1f58Sgm209912 sdp_free_attribute(cur); 1282*a93a1f58Sgm209912 return (0); 1283*a93a1f58Sgm209912 } 1284*a93a1f58Sgm209912 1285*a93a1f58Sgm209912 /* 1286*a93a1f58Sgm209912 * Allocates a new sdp session structure and assigns a version number to it. 1287*a93a1f58Sgm209912 * Currently one version is defined and it is 1. This will be useful in future 1288*a93a1f58Sgm209912 * in the unlikely need to change the structure. 1289*a93a1f58Sgm209912 */ 1290*a93a1f58Sgm209912 sdp_session_t * 1291*a93a1f58Sgm209912 sdp_new_session() 1292*a93a1f58Sgm209912 { 1293*a93a1f58Sgm209912 sdp_session_t *session = NULL; 1294*a93a1f58Sgm209912 1295*a93a1f58Sgm209912 session = calloc(1, sizeof (sdp_session_t)); 1296*a93a1f58Sgm209912 if (session != NULL) 1297*a93a1f58Sgm209912 session->sdp_session_version = SDP_SESSION_VERSION_1; 1298*a93a1f58Sgm209912 return (session); 1299*a93a1f58Sgm209912 } 1300