a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * CDDL HEADER START
a93a1f58a8763fa69172980b98e3d24720c1136egm *
a93a1f58a8763fa69172980b98e3d24720c1136egm * The contents of this file are subject to the terms of the
a93a1f58a8763fa69172980b98e3d24720c1136egm * Common Development and Distribution License (the "License").
a93a1f58a8763fa69172980b98e3d24720c1136egm * You may not use this file except in compliance with the License.
a93a1f58a8763fa69172980b98e3d24720c1136egm *
a93a1f58a8763fa69172980b98e3d24720c1136egm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a93a1f58a8763fa69172980b98e3d24720c1136egm * or http://www.opensolaris.org/os/licensing.
a93a1f58a8763fa69172980b98e3d24720c1136egm * See the License for the specific language governing permissions
a93a1f58a8763fa69172980b98e3d24720c1136egm * and limitations under the License.
a93a1f58a8763fa69172980b98e3d24720c1136egm *
a93a1f58a8763fa69172980b98e3d24720c1136egm * When distributing Covered Code, include this CDDL HEADER in each
a93a1f58a8763fa69172980b98e3d24720c1136egm * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a93a1f58a8763fa69172980b98e3d24720c1136egm * If applicable, add the following below this CDDL HEADER, with the
a93a1f58a8763fa69172980b98e3d24720c1136egm * fields enclosed by brackets "[]" replaced with your own identifying
a93a1f58a8763fa69172980b98e3d24720c1136egm * information: Portions Copyright [yyyy] [name of copyright owner]
a93a1f58a8763fa69172980b98e3d24720c1136egm *
a93a1f58a8763fa69172980b98e3d24720c1136egm * CDDL HEADER END
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
a93a1f58a8763fa69172980b98e3d24720c1136egm * Use is subject to license terms.
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#pragma ident "%Z%%M% %I% %E% SMI"
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Contains implementation of various interfaces exported by library
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#include <stdio.h>
a93a1f58a8763fa69172980b98e3d24720c1136egm#include <assert.h>
a93a1f58a8763fa69172980b98e3d24720c1136egm#include <errno.h>
a93a1f58a8763fa69172980b98e3d24720c1136egm#include <stdlib.h>
a93a1f58a8763fa69172980b98e3d24720c1136egm#include <string.h>
a93a1f58a8763fa69172980b98e3d24720c1136egm#include <ctype.h>
a93a1f58a8763fa69172980b98e3d24720c1136egm#include <sdp.h>
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#include "sdp_parse.h"
a93a1f58a8763fa69172980b98e3d24720c1136egm#include "commp_util.h"
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#define FIELD_EQUALS_CRLF_LEN 4 /* first two characters and CRLF */
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#define SDP_ATTR_TO_STR(m_attr) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm while ((m_attr) != NULL) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((m_attr)->a_value != NULL) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "a=%s%c%s%s", \
a93a1f58a8763fa69172980b98e3d24720c1136egm (m_attr)->a_name, COMMP_COLON, (m_attr)-> \
a93a1f58a8763fa69172980b98e3d24720c1136egm a_value, COMMP_CRLF); \
a93a1f58a8763fa69172980b98e3d24720c1136egm } else { \
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "a=%s%s", (m_attr)-> \
a93a1f58a8763fa69172980b98e3d24720c1136egm a_name, COMMP_CRLF); \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote; \
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote; \
a93a1f58a8763fa69172980b98e3d24720c1136egm (m_attr) = (m_attr)->a_next; \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#define SDP_KEY_TO_STR(m_key) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((m_key) != NULL) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((m_key)->k_enckey != NULL) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "k=%s%c%s%s", \
a93a1f58a8763fa69172980b98e3d24720c1136egm (m_key)->k_method, COMMP_COLON, (m_key)-> \
a93a1f58a8763fa69172980b98e3d24720c1136egm k_enckey, COMMP_CRLF); \
a93a1f58a8763fa69172980b98e3d24720c1136egm } else { \
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "k=%s%s", (m_key)-> \
a93a1f58a8763fa69172980b98e3d24720c1136egm k_method, COMMP_CRLF); \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote; \
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote; \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#define SDP_BANDWIDTH_TO_STR(m_bw) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm while ((m_bw) != NULL) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "b=%s%c%llu%s", (m_bw)-> \
a93a1f58a8763fa69172980b98e3d24720c1136egm b_type, COMMP_COLON, (m_bw)->b_value, COMMP_CRLF); \
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote; \
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote; \
a93a1f58a8763fa69172980b98e3d24720c1136egm (m_bw) = (m_bw)->b_next; \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#define SDP_INFORMATION_TO_STR(m_info) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((m_info) != NULL) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "i=%s%s", (m_info), COMMP_CRLF); \
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote; \
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote; \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#define SDP_CONNECTION_TO_STR(m_conn) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm while ((m_conn) != NULL) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm if (strcasecmp((m_conn)->c_addrtype, \
a93a1f58a8763fa69172980b98e3d24720c1136egm COMMP_ADDRTYPE_IP4) == 0) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((m_conn)->c_addrcount > 1) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "c=%s %s %s/%d/%d" \
a93a1f58a8763fa69172980b98e3d24720c1136egm "%s", (m_conn)->c_nettype, (m_conn)-> \
a93a1f58a8763fa69172980b98e3d24720c1136egm c_addrtype, (m_conn)->c_address, (m_conn)->\
a93a1f58a8763fa69172980b98e3d24720c1136egm c_ttl, (m_conn)->c_addrcount, COMMP_CRLF); \
a93a1f58a8763fa69172980b98e3d24720c1136egm } else if ((m_conn)->c_addrcount == 1) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "c=%s %s %s/%d%s", \
a93a1f58a8763fa69172980b98e3d24720c1136egm (m_conn)->c_nettype, (m_conn)->c_addrtype, \
a93a1f58a8763fa69172980b98e3d24720c1136egm (m_conn)->c_address, (m_conn)->c_ttl, \
a93a1f58a8763fa69172980b98e3d24720c1136egm COMMP_CRLF); \
a93a1f58a8763fa69172980b98e3d24720c1136egm } else { \
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "c=%s %s %s%s", \
a93a1f58a8763fa69172980b98e3d24720c1136egm (m_conn)->c_nettype, (m_conn)->c_addrtype, \
a93a1f58a8763fa69172980b98e3d24720c1136egm (m_conn)->c_address, COMMP_CRLF); \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm } else if (strcasecmp((m_conn)->c_addrtype, \
a93a1f58a8763fa69172980b98e3d24720c1136egm COMMP_ADDRTYPE_IP6) == 0) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((m_conn)->c_addrcount <= 1) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "c=%s %s %s%s", \
a93a1f58a8763fa69172980b98e3d24720c1136egm (m_conn)->c_nettype, (m_conn)->c_addrtype, \
a93a1f58a8763fa69172980b98e3d24720c1136egm (m_conn)->c_address, COMMP_CRLF); \
a93a1f58a8763fa69172980b98e3d24720c1136egm } else { \
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "c=%s %s %s/%d%s", \
a93a1f58a8763fa69172980b98e3d24720c1136egm (m_conn)->c_nettype, (m_conn)->c_addrtype, \
a93a1f58a8763fa69172980b98e3d24720c1136egm (m_conn)->c_address, (m_conn)->c_addrcount,\
a93a1f58a8763fa69172980b98e3d24720c1136egm COMMP_CRLF); \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm } else { \
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "c=%s %s %s%s", (m_conn)-> \
a93a1f58a8763fa69172980b98e3d24720c1136egm c_nettype, (m_conn)->c_addrtype, (m_conn)-> \
a93a1f58a8763fa69172980b98e3d24720c1136egm c_address, COMMP_CRLF); \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote; \
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote; \
a93a1f58a8763fa69172980b98e3d24720c1136egm (m_conn) = (m_conn)->c_next; \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#define SDP_ADD_KEY(d_key, s_key) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((s_key) != NULL) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm if (sdp_add_key(&(d_key), (s_key)->k_method, \
a93a1f58a8763fa69172980b98e3d24720c1136egm (s_key)->k_enckey) != 0) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_session(new_sess); \
a93a1f58a8763fa69172980b98e3d24720c1136egm return (NULL); \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#define SDP_ADD_ATTRIBUTE(d_attr, s_attr) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm while ((s_attr) != NULL) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm if (sdp_add_attribute(&(d_attr), (s_attr)->a_name, \
a93a1f58a8763fa69172980b98e3d24720c1136egm (s_attr)->a_value) != 0) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_session(new_sess); \
a93a1f58a8763fa69172980b98e3d24720c1136egm return (NULL); \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm (s_attr) = (s_attr)->a_next; \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#define SDP_ADD_BANDWIDTH(d_bw, s_bw) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm while ((s_bw) != NULL) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm if (sdp_add_bandwidth(&(d_bw), (s_bw)->b_type, \
a93a1f58a8763fa69172980b98e3d24720c1136egm (s_bw)->b_value) != 0) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_session(new_sess); \
a93a1f58a8763fa69172980b98e3d24720c1136egm return (NULL); \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm (s_bw) = (s_bw)->b_next; \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#define SDP_ADD_CONNECTION(d_conn, s_conn) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm while ((s_conn) != NULL) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm if (sdp_add_connection(&(d_conn), (s_conn)->c_nettype, \
a93a1f58a8763fa69172980b98e3d24720c1136egm (s_conn)->c_addrtype, (s_conn)->c_address, \
a93a1f58a8763fa69172980b98e3d24720c1136egm (s_conn)->c_ttl, (s_conn)->c_addrcount) != 0) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_session(new_sess); \
a93a1f58a8763fa69172980b98e3d24720c1136egm return (NULL); \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm (s_conn) = (s_conn)->c_next; \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#define SDP_LEN_CONNECTION(m_conn) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm while ((m_conn) != NULL) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm len += FIELD_EQUALS_CRLF_LEN; \
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen((m_conn)->c_nettype); \
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen((m_conn)->c_addrtype) + 1; \
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen((m_conn)->c_address) + 1; \
a93a1f58a8763fa69172980b98e3d24720c1136egm len += snprintf(buf, 1, "%u", (m_conn)->c_ttl) + 1; \
a93a1f58a8763fa69172980b98e3d24720c1136egm len += snprintf(buf, 1, "%d", (m_conn)->c_addrcount) + 1; \
a93a1f58a8763fa69172980b98e3d24720c1136egm (m_conn) = (m_conn)->c_next; \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#define SDP_LEN_BANDWIDTH(m_bw) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm while ((m_bw) != NULL) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm len += FIELD_EQUALS_CRLF_LEN; \
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen((m_bw)->b_type); \
a93a1f58a8763fa69172980b98e3d24720c1136egm len += snprintf(buf, 1, "%llu", (m_bw)->b_value) + 1; \
a93a1f58a8763fa69172980b98e3d24720c1136egm (m_bw) = (m_bw)->b_next; \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#define SDP_LEN_KEY(m_key) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((m_key) != NULL) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm len += FIELD_EQUALS_CRLF_LEN; \
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen((m_key)->k_method); \
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((m_key)->k_enckey != NULL) \
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen((m_key)->k_enckey) + 1; \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm#define SDP_LEN_ATTRIBUTE(m_attr) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm while ((m_attr) != NULL) { \
a93a1f58a8763fa69172980b98e3d24720c1136egm len += FIELD_EQUALS_CRLF_LEN; \
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen((m_attr)->a_name); \
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((m_attr)->a_value != NULL) \
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen((m_attr)->a_value) + 1; \
a93a1f58a8763fa69172980b98e3d24720c1136egm (m_attr) = (m_attr)->a_next; \
a93a1f58a8763fa69172980b98e3d24720c1136egm } \
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Given a media list and media name ("audio", "video", et al), it searches
a93a1f58a8763fa69172980b98e3d24720c1136egm * the list for that media. Returns NULL if media not present.
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_media_t *
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_find_media(sdp_media_t *media, const char *name)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm if (media == NULL || name == NULL || (strlen(name) == 0)) {
a93a1f58a8763fa69172980b98e3d24720c1136egm return (NULL);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm while (media != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if (media->m_name != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if (strcasecmp(name, media->m_name) == 0)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (media);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm media = media->m_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm return (media);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Given a attribute list and name of the attribute ("rtpmap", "fmtp", et al),
a93a1f58a8763fa69172980b98e3d24720c1136egm * this API searches the list for that attribute. Returns NULL if not found.
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_attr_t *
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_find_attribute(sdp_attr_t *attr, const char *name)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm if (attr == NULL || name == NULL || (strlen(name) == 0)) {
a93a1f58a8763fa69172980b98e3d24720c1136egm return (NULL);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm while (attr != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if (attr->a_name != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if (strcasecmp(attr->a_name, name) == 0)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (attr);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm attr = attr->a_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm return (attr);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Given a media list and a format number, this API will return the rtpmap
a93a1f58a8763fa69172980b98e3d24720c1136egm * attribute matching the format number.
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_attr_t *
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_find_media_rtpmap(sdp_media_t *media, const char *format)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_attr_t *attr = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm char *tmp = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm if (media == NULL || format == NULL || (strlen(format) == 0)) {
a93a1f58a8763fa69172980b98e3d24720c1136egm return (NULL);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm attr = media->m_attr;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (attr != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if (attr->a_name != NULL && (strcasecmp(attr->a_name,
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_RTPMAP) == 0)) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if (attr->a_value != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp = attr->a_value;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (isspace(*tmp))
a93a1f58a8763fa69172980b98e3d24720c1136egm ++tmp;
a93a1f58a8763fa69172980b98e3d24720c1136egm if (strncasecmp(tmp, format,
a93a1f58a8763fa69172980b98e3d24720c1136egm strlen(format)) == 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm return (attr);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm attr = attr->a_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm return (attr);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Adds origin field to the session.
a93a1f58a8763fa69172980b98e3d24720c1136egm * o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_add_origin(sdp_session_t *session, const char *name, uint64_t id,
a93a1f58a8763fa69172980b98e3d24720c1136egm uint64_t ver, const char *nettype, const char *addrtype,
a93a1f58a8763fa69172980b98e3d24720c1136egm const char *address)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_origin_t *origin;
a93a1f58a8763fa69172980b98e3d24720c1136egm int ret = 0;
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session == NULL || name == NULL || nettype == NULL ||
a93a1f58a8763fa69172980b98e3d24720c1136egm addrtype == NULL || address == NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session->s_origin != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EPROTO);
a93a1f58a8763fa69172980b98e3d24720c1136egm origin = calloc(1, sizeof (sdp_origin_t));
a93a1f58a8763fa69172980b98e3d24720c1136egm if (origin == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ENOMEM);
a93a1f58a8763fa69172980b98e3d24720c1136egm origin->o_id = id;
a93a1f58a8763fa69172980b98e3d24720c1136egm origin->o_version = ver;
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = commp_add_str(&origin->o_username, name, strlen(name))) != 0)
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = commp_add_str(&origin->o_nettype, nettype,
a93a1f58a8763fa69172980b98e3d24720c1136egm strlen(nettype))) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = commp_add_str(&origin->o_addrtype, addrtype,
a93a1f58a8763fa69172980b98e3d24720c1136egm strlen(addrtype))) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = commp_add_str(&origin->o_address, address,
a93a1f58a8763fa69172980b98e3d24720c1136egm strlen(address))) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_origin = origin;
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ret);
a93a1f58a8763fa69172980b98e3d24720c1136egmerr_ret:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_origin(origin);
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ret);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Adds session name field to the session.
a93a1f58a8763fa69172980b98e3d24720c1136egm * s=<session name>
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_add_name(sdp_session_t *session, const char *name)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session == NULL || name == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session->s_name != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EPROTO);
a93a1f58a8763fa69172980b98e3d24720c1136egm return (commp_add_str(&session->s_name, name, strlen(name)));
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Adds session information field to the session or media section of SDP.
a93a1f58a8763fa69172980b98e3d24720c1136egm * i=<session description>
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_add_information(char **information, const char *value)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm if (information == NULL || value == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm if (*information != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EPROTO);
a93a1f58a8763fa69172980b98e3d24720c1136egm return (commp_add_str(information, value, strlen(value)));
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Adds uri field to the session.
a93a1f58a8763fa69172980b98e3d24720c1136egm * u=<uri>
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_add_uri(sdp_session_t *session, const char *uri)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session == NULL || uri == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session->s_uri != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EPROTO);
a93a1f58a8763fa69172980b98e3d24720c1136egm return (commp_add_str(&session->s_uri, uri, strlen(uri)));
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Adds email address field to the session.
a93a1f58a8763fa69172980b98e3d24720c1136egm * e=<email-address>
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_add_email(sdp_session_t *session, const char *email)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session == NULL || email == NULL || (strlen(email) == 0))
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm return (add_value_to_list(&session->s_email, email, strlen(email),
a93a1f58a8763fa69172980b98e3d24720c1136egm B_TRUE));
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Adds phone number field to the session.
a93a1f58a8763fa69172980b98e3d24720c1136egm * p=<phone-number>
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_add_phone(sdp_session_t *session, const char *phone)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session == NULL || phone == NULL || (strlen(phone) == 0))
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm return (add_value_to_list(&session->s_phone, phone, strlen(phone),
a93a1f58a8763fa69172980b98e3d24720c1136egm B_TRUE));
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Adds connection field to the session or media section of SDP
a93a1f58a8763fa69172980b98e3d24720c1136egm * c=<nettype> <addrtype> <connection-address>[/ttl]/<number of addresses>
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_add_connection(sdp_conn_t **conn, const char *nettype, const char *addrtype,
a93a1f58a8763fa69172980b98e3d24720c1136egm const char *address, uint8_t ttl, int addrcount)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_conn_t *tmp;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_conn_t *new_conn;
a93a1f58a8763fa69172980b98e3d24720c1136egm int ret = 0;
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm if (conn == NULL || nettype == NULL || addrtype == NULL ||
a93a1f58a8763fa69172980b98e3d24720c1136egm address == NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm new_conn = calloc(1, sizeof (sdp_conn_t));
a93a1f58a8763fa69172980b98e3d24720c1136egm if (new_conn == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ENOMEM);
a93a1f58a8763fa69172980b98e3d24720c1136egm new_conn->c_ttl = ttl;
a93a1f58a8763fa69172980b98e3d24720c1136egm new_conn->c_addrcount = addrcount;
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = commp_add_str(&new_conn->c_nettype, nettype,
a93a1f58a8763fa69172980b98e3d24720c1136egm strlen(nettype))) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = commp_add_str(&new_conn->c_addrtype, addrtype,
a93a1f58a8763fa69172980b98e3d24720c1136egm strlen(addrtype))) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = commp_add_str(&new_conn->c_address, address,
a93a1f58a8763fa69172980b98e3d24720c1136egm strlen(address))) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if (*conn == NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm *conn = new_conn;
a93a1f58a8763fa69172980b98e3d24720c1136egm } else {
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp = *conn;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (tmp->c_next != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp = tmp->c_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp->c_next = new_conn;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ret);
a93a1f58a8763fa69172980b98e3d24720c1136egmerr_ret:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_connection(new_conn);
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ret);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Adds bandwidth field to the session or media section of SDP.
a93a1f58a8763fa69172980b98e3d24720c1136egm * b=<bwtype>:<bandwidth>
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_add_bandwidth(sdp_bandwidth_t **bw, const char *type, uint64_t value)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_bandwidth_t *new_bw;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_bandwidth_t *tmp;
a93a1f58a8763fa69172980b98e3d24720c1136egm int ret = 0;
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm if (bw == NULL || type == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm new_bw = calloc(1, sizeof (sdp_bandwidth_t));
a93a1f58a8763fa69172980b98e3d24720c1136egm if (new_bw == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ENOMEM);
a93a1f58a8763fa69172980b98e3d24720c1136egm new_bw->b_value = value;
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = commp_add_str(&new_bw->b_type, type, strlen(type))) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm free(new_bw);
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ret);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if (*bw == NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm *bw = new_bw;
a93a1f58a8763fa69172980b98e3d24720c1136egm } else {
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp = *bw;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (tmp->b_next != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp = tmp->b_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp->b_next = new_bw;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ret);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Adds time field to the session
a93a1f58a8763fa69172980b98e3d24720c1136egm * t=<start-time> <stop-time>
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_add_time(sdp_session_t *session, uint64_t starttime, uint64_t stoptime,
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_time_t **time)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_time_t *new_time;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_time_t *tmp;
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm if (time != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm *time = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session == NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm new_time = calloc(1, sizeof (sdp_time_t));
a93a1f58a8763fa69172980b98e3d24720c1136egm if (new_time == NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ENOMEM);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm new_time->t_start = starttime;
a93a1f58a8763fa69172980b98e3d24720c1136egm new_time->t_stop = stoptime;
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp = session->s_time;
a93a1f58a8763fa69172980b98e3d24720c1136egm if (tmp == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_time = new_time;
a93a1f58a8763fa69172980b98e3d24720c1136egm else {
a93a1f58a8763fa69172980b98e3d24720c1136egm while (tmp->t_next != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp = tmp->t_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp->t_next = new_time;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if (time != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm *time = new_time;
a93a1f58a8763fa69172980b98e3d24720c1136egm return (0);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Adds repeat field to the time structure of session
a93a1f58a8763fa69172980b98e3d24720c1136egm * r=<repeat interval> <active duration> <offsets from start-time>
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_add_repeat(sdp_time_t *time, uint64_t interval, uint64_t duration,
a93a1f58a8763fa69172980b98e3d24720c1136egm const char *offset)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_repeat_t *tmp;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_repeat_t *new_repeat;
a93a1f58a8763fa69172980b98e3d24720c1136egm int ret = 0;
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm if (time == NULL || offset == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm new_repeat = calloc(1, sizeof (sdp_repeat_t));
a93a1f58a8763fa69172980b98e3d24720c1136egm if (new_repeat == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ENOMEM);
a93a1f58a8763fa69172980b98e3d24720c1136egm new_repeat->r_interval = interval;
a93a1f58a8763fa69172980b98e3d24720c1136egm new_repeat->r_duration = duration;
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = sdp_str_to_list(&new_repeat->r_offset, offset,
a93a1f58a8763fa69172980b98e3d24720c1136egm strlen(offset), B_FALSE)) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp = time->t_repeat;
a93a1f58a8763fa69172980b98e3d24720c1136egm if (tmp == NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm time->t_repeat = new_repeat;
a93a1f58a8763fa69172980b98e3d24720c1136egm } else {
a93a1f58a8763fa69172980b98e3d24720c1136egm while (tmp->r_next != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp = tmp->r_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp->r_next = new_repeat;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ret);
a93a1f58a8763fa69172980b98e3d24720c1136egmerr_ret:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_repeat(new_repeat);
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ret);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Adds time zone field to the session
a93a1f58a8763fa69172980b98e3d24720c1136egm * z=<adjustment time> <offset> <adjustment time> <offset> ....
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_add_zone(sdp_session_t *session, uint64_t time, const char *offset)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_zone_t *new_zone;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_zone_t *tmp;
a93a1f58a8763fa69172980b98e3d24720c1136egm int ret = 0;
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session == NULL || offset == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm new_zone = calloc(1, sizeof (sdp_zone_t));
a93a1f58a8763fa69172980b98e3d24720c1136egm if (new_zone == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ENOMEM);
a93a1f58a8763fa69172980b98e3d24720c1136egm new_zone->z_time = time;
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = commp_add_str(&new_zone->z_offset, offset,
a93a1f58a8763fa69172980b98e3d24720c1136egm strlen(offset))) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm free(new_zone);
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ret);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp = session->s_zone;
a93a1f58a8763fa69172980b98e3d24720c1136egm if (tmp == NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_zone = new_zone;
a93a1f58a8763fa69172980b98e3d24720c1136egm } else {
a93a1f58a8763fa69172980b98e3d24720c1136egm while (tmp->z_next != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp = tmp->z_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp->z_next = new_zone;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ret);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Adds key field to session or media section of SDP.
a93a1f58a8763fa69172980b98e3d24720c1136egm * k=<method>
a93a1f58a8763fa69172980b98e3d24720c1136egm * k=<method>:<encryption key>
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_add_key(sdp_key_t **key, const char *method, const char *enckey)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm int ret = 0;
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm if (key == NULL || method == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm if (*key != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EPROTO);
a93a1f58a8763fa69172980b98e3d24720c1136egm *key = calloc(1, sizeof (sdp_key_t));
a93a1f58a8763fa69172980b98e3d24720c1136egm if (*key == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ENOMEM);
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = commp_add_str(&((*key)->k_method), method,
a93a1f58a8763fa69172980b98e3d24720c1136egm strlen(method))) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if (enckey != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = commp_add_str(&((*key)->k_enckey), enckey,
a93a1f58a8763fa69172980b98e3d24720c1136egm strlen(enckey))) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ret);
a93a1f58a8763fa69172980b98e3d24720c1136egmerr_ret:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_key(*key);
a93a1f58a8763fa69172980b98e3d24720c1136egm *key = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ret);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Adds attribute field to session or media section of SDP.
a93a1f58a8763fa69172980b98e3d24720c1136egm * a=<attribute>
a93a1f58a8763fa69172980b98e3d24720c1136egm * a=<attribute>:<value>
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_add_attribute(sdp_attr_t **attr, const char *name, const char *value)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_attr_t *tmp;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_attr_t *new_attr;
a93a1f58a8763fa69172980b98e3d24720c1136egm int ret = 0;
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm if (attr == NULL || name == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm new_attr = calloc(1, sizeof (sdp_attr_t));
a93a1f58a8763fa69172980b98e3d24720c1136egm if (new_attr == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ENOMEM);
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = commp_add_str(&new_attr->a_name, name, strlen(name))) != 0)
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm if (value != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = commp_add_str(&new_attr->a_value, value,
a93a1f58a8763fa69172980b98e3d24720c1136egm strlen(value))) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp = *attr;
a93a1f58a8763fa69172980b98e3d24720c1136egm if (tmp == NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm *attr = new_attr;
a93a1f58a8763fa69172980b98e3d24720c1136egm } else {
a93a1f58a8763fa69172980b98e3d24720c1136egm while (tmp->a_next != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp = tmp->a_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp->a_next = new_attr;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ret);
a93a1f58a8763fa69172980b98e3d24720c1136egmerr_ret:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_attribute(new_attr);
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ret);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Adds media field to the session.
a93a1f58a8763fa69172980b98e3d24720c1136egm * m=<media> <port>[/portcount] <proto> <fmt> ...
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_add_media(sdp_session_t *session, const char *name, uint_t port,
a93a1f58a8763fa69172980b98e3d24720c1136egm int portcount, const char *protocol, const char *fmt, sdp_media_t **media)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_media_t *tmp;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_media_t *new_media;
a93a1f58a8763fa69172980b98e3d24720c1136egm int ret = 0;
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm if (media != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm *media = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session == NULL || name == NULL || protocol == NULL ||
a93a1f58a8763fa69172980b98e3d24720c1136egm portcount <= 0 || fmt == NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm new_media = calloc(1, sizeof (sdp_media_t));
a93a1f58a8763fa69172980b98e3d24720c1136egm if (new_media == NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ENOMEM);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm new_media->m_session = session;
a93a1f58a8763fa69172980b98e3d24720c1136egm new_media->m_port = port;
a93a1f58a8763fa69172980b98e3d24720c1136egm new_media->m_portcount = portcount;
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = commp_add_str(&new_media->m_name, name, strlen(name))) != 0)
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = commp_add_str(&new_media->m_proto, protocol,
a93a1f58a8763fa69172980b98e3d24720c1136egm strlen(protocol))) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if ((ret = sdp_str_to_list(&new_media->m_format, fmt,
a93a1f58a8763fa69172980b98e3d24720c1136egm strlen(fmt), B_TRUE)) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp = session->s_media;
a93a1f58a8763fa69172980b98e3d24720c1136egm if (tmp == NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_media = new_media;
a93a1f58a8763fa69172980b98e3d24720c1136egm } else {
a93a1f58a8763fa69172980b98e3d24720c1136egm while (tmp->m_next != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp = tmp->m_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm tmp->m_next = new_media;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if (media != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm *media = new_media;
a93a1f58a8763fa69172980b98e3d24720c1136egm return (0);
a93a1f58a8763fa69172980b98e3d24720c1136egmerr_ret:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_media(new_media);
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ret);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * This internal API is required by sdp_session_to_str(). It determines the
a93a1f58a8763fa69172980b98e3d24720c1136egm * length of buffer that is required to hold the session. Since the RFC does
a93a1f58a8763fa69172980b98e3d24720c1136egm * not limit the size of various sub-fields in the field. We need to scan
a93a1f58a8763fa69172980b98e3d24720c1136egm * through the structure to determine the length.
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_get_length(const sdp_session_t *session)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm int len = 0;
a93a1f58a8763fa69172980b98e3d24720c1136egm char buf[1];
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_list_t *list;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_conn_t *conn;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_bandwidth_t *bw;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_zone_t *zone;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_time_t *time;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_repeat_t *repeat;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_attr_t *attr;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_media_t *media;
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm len += FIELD_EQUALS_CRLF_LEN;
a93a1f58a8763fa69172980b98e3d24720c1136egm len += snprintf(buf, 1, "%d", session->s_version);
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session->s_origin != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm len += FIELD_EQUALS_CRLF_LEN;
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen(session->s_origin->o_username);
a93a1f58a8763fa69172980b98e3d24720c1136egm len += snprintf(buf, 1, "%llu", session->s_origin->o_id) + 1;
a93a1f58a8763fa69172980b98e3d24720c1136egm len += snprintf(buf, 1, "%llu", session->s_origin->o_version)
a93a1f58a8763fa69172980b98e3d24720c1136egm + 1;
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen(session->s_origin->o_nettype) + 1;
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen(session->s_origin->o_addrtype) + 1;
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen(session->s_origin->o_address) + 1;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session->s_name != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen(session->s_name) + FIELD_EQUALS_CRLF_LEN;
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session->s_info != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen(session->s_info) + FIELD_EQUALS_CRLF_LEN;
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session->s_uri != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen(session->s_uri) + FIELD_EQUALS_CRLF_LEN;
a93a1f58a8763fa69172980b98e3d24720c1136egm list = session->s_email;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (list != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen((char *)list->value) + FIELD_EQUALS_CRLF_LEN;
a93a1f58a8763fa69172980b98e3d24720c1136egm list = list->next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm list = session->s_phone;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (list != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen((char *)list->value) + FIELD_EQUALS_CRLF_LEN;
a93a1f58a8763fa69172980b98e3d24720c1136egm list = list->next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm conn = session->s_conn;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_LEN_CONNECTION(conn);
a93a1f58a8763fa69172980b98e3d24720c1136egm bw = session->s_bw;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_LEN_BANDWIDTH(bw);
a93a1f58a8763fa69172980b98e3d24720c1136egm time = session->s_time;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (time != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm len += FIELD_EQUALS_CRLF_LEN;
a93a1f58a8763fa69172980b98e3d24720c1136egm len += snprintf(buf, 1, "%llu", time->t_start);
a93a1f58a8763fa69172980b98e3d24720c1136egm len += snprintf(buf, 1, "%llu", time->t_stop) + 1;
a93a1f58a8763fa69172980b98e3d24720c1136egm repeat = time->t_repeat;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (repeat != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm len += FIELD_EQUALS_CRLF_LEN;
a93a1f58a8763fa69172980b98e3d24720c1136egm len += snprintf(buf, 1, "%llu", repeat->r_interval);
a93a1f58a8763fa69172980b98e3d24720c1136egm len += snprintf(buf, 1, "%llu", repeat->r_duration) + 1;
a93a1f58a8763fa69172980b98e3d24720c1136egm list = repeat->r_offset;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (list != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm len += snprintf(buf, 1, "%llu",
a93a1f58a8763fa69172980b98e3d24720c1136egm *(uint64_t *)list->value) + 1;
a93a1f58a8763fa69172980b98e3d24720c1136egm list = list->next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm repeat = repeat->r_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm time = time->t_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session->s_zone != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm len += FIELD_EQUALS_CRLF_LEN;
a93a1f58a8763fa69172980b98e3d24720c1136egm zone = session->s_zone;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (zone != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm len += snprintf(buf, 1, "%llu", zone->z_time) + 1;
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen(zone->z_offset) + 1;
a93a1f58a8763fa69172980b98e3d24720c1136egm zone = zone->z_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_LEN_KEY(session->s_key);
a93a1f58a8763fa69172980b98e3d24720c1136egm attr = session->s_attr;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_LEN_ATTRIBUTE(attr);
a93a1f58a8763fa69172980b98e3d24720c1136egm media = session->s_media;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (media != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm len += FIELD_EQUALS_CRLF_LEN;
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen(media->m_name);
a93a1f58a8763fa69172980b98e3d24720c1136egm len += snprintf(buf, 1, "%u", media->m_port) + 1;
a93a1f58a8763fa69172980b98e3d24720c1136egm len += snprintf(buf, 1, "%d", media->m_portcount) + 1;
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen(media->m_proto) + 1;
a93a1f58a8763fa69172980b98e3d24720c1136egm list = media->m_format;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (list != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen((char *)list->value) + 1;
a93a1f58a8763fa69172980b98e3d24720c1136egm list = list->next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if (media->m_info != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm len += strlen(media->m_info) + FIELD_EQUALS_CRLF_LEN;
a93a1f58a8763fa69172980b98e3d24720c1136egm conn = media->m_conn;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_LEN_CONNECTION(conn);
a93a1f58a8763fa69172980b98e3d24720c1136egm bw = media->m_bw;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_LEN_BANDWIDTH(bw);
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_LEN_KEY(media->m_key);
a93a1f58a8763fa69172980b98e3d24720c1136egm attr = media->m_attr;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_LEN_ATTRIBUTE(attr);
a93a1f58a8763fa69172980b98e3d24720c1136egm media = media->m_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm return (len);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Given a session structure it clones (deep copy) and returns the cloned copy
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_session_t *
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_clone_session(const sdp_session_t *session)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_session_t *new_sess;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_origin_t *origin;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_list_t *list;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_time_t *time;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_time_t *new_time;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_repeat_t *repeat;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_media_t *media;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_media_t *new_media;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_conn_t *conn;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_bandwidth_t *bw;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_attr_t *attr;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_zone_t *zone;
a93a1f58a8763fa69172980b98e3d24720c1136egm char *offset = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm char *format = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (NULL);
a93a1f58a8763fa69172980b98e3d24720c1136egm new_sess = calloc(1, sizeof (sdp_session_t));
a93a1f58a8763fa69172980b98e3d24720c1136egm if (new_sess == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (NULL);
a93a1f58a8763fa69172980b98e3d24720c1136egm new_sess->sdp_session_version = session->sdp_session_version;
a93a1f58a8763fa69172980b98e3d24720c1136egm new_sess->s_version = session->s_version;
a93a1f58a8763fa69172980b98e3d24720c1136egm origin = session->s_origin;
a93a1f58a8763fa69172980b98e3d24720c1136egm if (origin != NULL && (sdp_add_origin(new_sess, origin->o_username,
a93a1f58a8763fa69172980b98e3d24720c1136egm origin->o_id, origin->o_version, origin->o_nettype, origin->
a93a1f58a8763fa69172980b98e3d24720c1136egm o_addrtype, origin->o_address) != 0)) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session->s_name != NULL && sdp_add_name(new_sess, session->
a93a1f58a8763fa69172980b98e3d24720c1136egm s_name) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session->s_info != NULL && sdp_add_information(&new_sess->
a93a1f58a8763fa69172980b98e3d24720c1136egm s_info, session->s_info) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session->s_uri != NULL && sdp_add_uri(new_sess, session->
a93a1f58a8763fa69172980b98e3d24720c1136egm s_uri) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm list = session->s_email;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (list != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if (sdp_add_email(new_sess, (char *)list->value) != 0)
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm list = list->next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm list = session->s_phone;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (list != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if (sdp_add_phone(new_sess, (char *)list->value) != 0)
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm list = list->next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm conn = session->s_conn;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_ADD_CONNECTION(new_sess->s_conn, conn);
a93a1f58a8763fa69172980b98e3d24720c1136egm bw = session->s_bw;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_ADD_BANDWIDTH(new_sess->s_bw, bw);
a93a1f58a8763fa69172980b98e3d24720c1136egm time = session->s_time;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (time != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if (sdp_add_time(new_sess, time->t_start, time->t_stop,
a93a1f58a8763fa69172980b98e3d24720c1136egm &new_time) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm repeat = time->t_repeat;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (repeat != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if (sdp_list_to_str(repeat->r_offset, &offset,
a93a1f58a8763fa69172980b98e3d24720c1136egm B_FALSE) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if (sdp_add_repeat(new_time, repeat->r_interval,
a93a1f58a8763fa69172980b98e3d24720c1136egm repeat->r_duration, offset) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm free(offset);
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm free(offset);
a93a1f58a8763fa69172980b98e3d24720c1136egm repeat = repeat->r_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm time = time->t_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm zone = session->s_zone;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (zone != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if (sdp_add_zone(new_sess, zone->z_time, zone->z_offset) != 0)
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm zone = zone->z_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_ADD_KEY(new_sess->s_key, session->s_key);
a93a1f58a8763fa69172980b98e3d24720c1136egm attr = session->s_attr;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_ADD_ATTRIBUTE(new_sess->s_attr, attr);
a93a1f58a8763fa69172980b98e3d24720c1136egm media = session->s_media;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (media != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if (sdp_list_to_str(media->m_format, &format, B_TRUE) != 0)
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm if (sdp_add_media(new_sess, media->m_name,
a93a1f58a8763fa69172980b98e3d24720c1136egm media->m_port, media->m_portcount, media->m_proto,
a93a1f58a8763fa69172980b98e3d24720c1136egm format, &new_media) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm free(format);
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm free(format);
a93a1f58a8763fa69172980b98e3d24720c1136egm if (media->m_info != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if (sdp_add_information(&new_media->m_info,
a93a1f58a8763fa69172980b98e3d24720c1136egm media->m_info) != 0) {
a93a1f58a8763fa69172980b98e3d24720c1136egm goto err_ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm conn = media->m_conn;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_ADD_CONNECTION(new_media->m_conn, conn);
a93a1f58a8763fa69172980b98e3d24720c1136egm bw = media->m_bw;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_ADD_BANDWIDTH(new_media->m_bw, bw);
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_ADD_KEY(new_media->m_key, media->m_key);
a93a1f58a8763fa69172980b98e3d24720c1136egm attr = media->m_attr;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_ADD_ATTRIBUTE(new_media->m_attr, attr);
a93a1f58a8763fa69172980b98e3d24720c1136egm new_media->m_session = new_sess;
a93a1f58a8763fa69172980b98e3d24720c1136egm media = media->m_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm return (new_sess);
a93a1f58a8763fa69172980b98e3d24720c1136egmerr_ret:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_session(new_sess);
a93a1f58a8763fa69172980b98e3d24720c1136egm return (NULL);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * should i check if individual members are NULL, if not snprintf
a93a1f58a8763fa69172980b98e3d24720c1136egm * will core dump.
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Given a session structure, this API converts it into character
a93a1f58a8763fa69172980b98e3d24720c1136egm * buffer, which will be used as a payload later on.
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmchar *
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_session_to_str(const sdp_session_t *session, int *error)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm char *ret = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm char *buf = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm int len = 0;
a93a1f58a8763fa69172980b98e3d24720c1136egm int s_len = 0;
a93a1f58a8763fa69172980b98e3d24720c1136egm int wrote = 0;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_origin_t *origin;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_list_t *list;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_conn_t *conn;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_attr_t *attr;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_bandwidth_t *bw;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_time_t *time;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_repeat_t *repeat;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_zone_t *zone;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_media_t *media;
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm if (error != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm *error = 0;
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session == NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if (error != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm *error = EINVAL;
a93a1f58a8763fa69172980b98e3d24720c1136egm return (NULL);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm s_len = sdp_get_length(session);
a93a1f58a8763fa69172980b98e3d24720c1136egm ret = malloc(s_len + 1);
a93a1f58a8763fa69172980b98e3d24720c1136egm if (ret == NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if (error != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm *error = ENOMEM;
a93a1f58a8763fa69172980b98e3d24720c1136egm return (NULL);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = ret;
a93a1f58a8763fa69172980b98e3d24720c1136egm len = s_len + 1;
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "v=%d%s", session->s_version, COMMP_CRLF);
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm origin = session->s_origin;
a93a1f58a8763fa69172980b98e3d24720c1136egm if (origin != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "o=%s %llu %llu %s %s %s%s",
a93a1f58a8763fa69172980b98e3d24720c1136egm origin->o_username, origin->o_id, origin->o_version,
a93a1f58a8763fa69172980b98e3d24720c1136egm origin->o_nettype, origin->o_addrtype, origin->o_address,
a93a1f58a8763fa69172980b98e3d24720c1136egm COMMP_CRLF);
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session->s_name != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "s=%s%s", session->s_name,
a93a1f58a8763fa69172980b98e3d24720c1136egm COMMP_CRLF);
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_INFORMATION_TO_STR(session->s_info);
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session->s_uri != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "u=%s%s", session->s_uri,
a93a1f58a8763fa69172980b98e3d24720c1136egm COMMP_CRLF);
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm list = session->s_email;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (list != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "e=%s%s", (char *)list->value,
a93a1f58a8763fa69172980b98e3d24720c1136egm COMMP_CRLF);
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm list = list->next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm list = session->s_phone;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (list != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "p=%s%s", (char *)list->value,
a93a1f58a8763fa69172980b98e3d24720c1136egm COMMP_CRLF);
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm list = list->next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm conn = session->s_conn;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_CONNECTION_TO_STR(conn);
a93a1f58a8763fa69172980b98e3d24720c1136egm bw = session->s_bw;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_BANDWIDTH_TO_STR(bw);
a93a1f58a8763fa69172980b98e3d24720c1136egm time = session->s_time;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (time != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "t=%llu %llu%s", time->t_start,
a93a1f58a8763fa69172980b98e3d24720c1136egm time->t_stop, COMMP_CRLF);
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm repeat = time->t_repeat;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (repeat != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "r=%llu %llu", repeat->
a93a1f58a8763fa69172980b98e3d24720c1136egm r_interval, repeat->r_duration);
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm list = repeat->r_offset;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (list != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, " %llu",
a93a1f58a8763fa69172980b98e3d24720c1136egm *(uint64_t *)list->value);
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm list = list->next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "%s", COMMP_CRLF);
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm repeat = repeat->r_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm time = time->t_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm zone = session->s_zone;
a93a1f58a8763fa69172980b98e3d24720c1136egm if (zone != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "z=%llu %s", zone->z_time,
a93a1f58a8763fa69172980b98e3d24720c1136egm zone->z_offset);
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm zone = zone->z_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (zone != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, " %llu %s", zone->z_time,
a93a1f58a8763fa69172980b98e3d24720c1136egm zone->z_offset);
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm zone = zone->z_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "%s", COMMP_CRLF);
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_KEY_TO_STR(session->s_key);
a93a1f58a8763fa69172980b98e3d24720c1136egm attr = session->s_attr;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_ATTR_TO_STR(attr);
a93a1f58a8763fa69172980b98e3d24720c1136egm media = session->s_media;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (media != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm if (media->m_portcount == 1) {
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "m=%s %d %s", media->m_name,
a93a1f58a8763fa69172980b98e3d24720c1136egm media->m_port, media->m_proto);
a93a1f58a8763fa69172980b98e3d24720c1136egm } else {
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "m=%s %d/%d %s", media->
a93a1f58a8763fa69172980b98e3d24720c1136egm m_name, media->m_port, media->m_portcount, media->
a93a1f58a8763fa69172980b98e3d24720c1136egm m_proto);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm list = media->m_format;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (list != NULL) {
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, " %s", (char *)list->value);
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm list = list->next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm wrote = snprintf(buf, len, "%s", COMMP_CRLF);
a93a1f58a8763fa69172980b98e3d24720c1136egm len = len - wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm buf = buf + wrote;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_INFORMATION_TO_STR(media->m_info);
a93a1f58a8763fa69172980b98e3d24720c1136egm conn = media->m_conn;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_CONNECTION_TO_STR(conn);
a93a1f58a8763fa69172980b98e3d24720c1136egm bw = media->m_bw;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_BANDWIDTH_TO_STR(bw);
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_KEY_TO_STR(media->m_key);
a93a1f58a8763fa69172980b98e3d24720c1136egm attr = media->m_attr;
a93a1f58a8763fa69172980b98e3d24720c1136egm SDP_ATTR_TO_STR(attr);
a93a1f58a8763fa69172980b98e3d24720c1136egm media = media->m_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm assert(len >= 1);
a93a1f58a8763fa69172980b98e3d24720c1136egm *buf = '\0';
a93a1f58a8763fa69172980b98e3d24720c1136egm return (ret);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Given a session structure and the field ('v', 'o', 's', et al), this API
a93a1f58a8763fa69172980b98e3d24720c1136egm * deletes the corresponding structure element. It frees the memory and sets the
a93a1f58a8763fa69172980b98e3d24720c1136egm * pointer to NULL
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_delete_all_field(sdp_session_t *session, const char field)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm switch (field) {
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_ORIGIN_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_origin(session->s_origin);
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_origin = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_NAME_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm free(session->s_name);
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_name = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_INFO_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm free(session->s_info);
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_info = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_URI_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm free(session->s_uri);
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_uri = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_EMAIL_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_list(session->s_email);
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_email = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_PHONE_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_list(session->s_phone);
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_phone = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_CONNECTION_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_connection(session->s_conn);
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_conn = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_BANDWIDTH_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_bandwidth(session->s_bw);
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_bw = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_TIME_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_time(session->s_time);
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_time = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_ZONE_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_zone(session->s_zone);
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_zone = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_KEY_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_key(session->s_key);
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_key = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_ATTRIBUTE_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_attribute(session->s_attr);
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_attr = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_MEDIA_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_media(session->s_media);
a93a1f58a8763fa69172980b98e3d24720c1136egm session->s_media = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm default:
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm return (0);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Given a media structure and the field ('i', 'b', 'c', et al), this API
a93a1f58a8763fa69172980b98e3d24720c1136egm * deletes the corresponding structure element. It frees the memory and sets
a93a1f58a8763fa69172980b98e3d24720c1136egm * the pointer to NULL.
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_delete_all_media_field(sdp_media_t *media, const char field)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm if (media == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm switch (field) {
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_INFO_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm free(media->m_info);
a93a1f58a8763fa69172980b98e3d24720c1136egm media->m_info = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_CONNECTION_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_connection(media->m_conn);
a93a1f58a8763fa69172980b98e3d24720c1136egm media->m_conn = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_BANDWIDTH_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_bandwidth(media->m_bw);
a93a1f58a8763fa69172980b98e3d24720c1136egm media->m_bw = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_KEY_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_key(media->m_key);
a93a1f58a8763fa69172980b98e3d24720c1136egm media->m_key = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm case SDP_ATTRIBUTE_FIELD:
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_attribute(media->m_attr);
a93a1f58a8763fa69172980b98e3d24720c1136egm media->m_attr = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm break;
a93a1f58a8763fa69172980b98e3d24720c1136egm default:
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm return (0);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Given a media list and the media, this API deletes that media from the
a93a1f58a8763fa69172980b98e3d24720c1136egm * list. It frees the memory corresponding to that media.
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_delete_media(sdp_media_t **l_media, sdp_media_t *media)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_media_t *cur;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_media_t *prev;
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm if (l_media == NULL || *l_media == NULL || media == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm cur = *l_media;
a93a1f58a8763fa69172980b98e3d24720c1136egm prev = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (cur != NULL && cur != media) {
a93a1f58a8763fa69172980b98e3d24720c1136egm prev = cur;
a93a1f58a8763fa69172980b98e3d24720c1136egm cur = cur->m_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if (cur == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm if (cur == *l_media)
a93a1f58a8763fa69172980b98e3d24720c1136egm *l_media = cur->m_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm else
a93a1f58a8763fa69172980b98e3d24720c1136egm prev->m_next = cur->m_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm cur->m_next = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_media(cur);
a93a1f58a8763fa69172980b98e3d24720c1136egm return (0);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Given an attribute list and an attribute, this API deletes that attribue
a93a1f58a8763fa69172980b98e3d24720c1136egm * from the list. It frees the memory corresponding to that attribute.
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmint
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_delete_attribute(sdp_attr_t **l_attr, sdp_attr_t *attr)
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_attr_t *cur;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_attr_t *prev;
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm if (l_attr == NULL || *l_attr == NULL || attr == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm cur = *l_attr;
a93a1f58a8763fa69172980b98e3d24720c1136egm prev = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm while (cur != NULL && cur != attr) {
a93a1f58a8763fa69172980b98e3d24720c1136egm prev = cur;
a93a1f58a8763fa69172980b98e3d24720c1136egm cur = cur->a_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm }
a93a1f58a8763fa69172980b98e3d24720c1136egm if (cur == NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm return (EINVAL);
a93a1f58a8763fa69172980b98e3d24720c1136egm if (cur == *l_attr)
a93a1f58a8763fa69172980b98e3d24720c1136egm *l_attr = cur->a_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm else
a93a1f58a8763fa69172980b98e3d24720c1136egm prev->a_next = cur->a_next;
a93a1f58a8763fa69172980b98e3d24720c1136egm cur->a_next = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_free_attribute(cur);
a93a1f58a8763fa69172980b98e3d24720c1136egm return (0);
a93a1f58a8763fa69172980b98e3d24720c1136egm}
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm/*
a93a1f58a8763fa69172980b98e3d24720c1136egm * Allocates a new sdp session structure and assigns a version number to it.
a93a1f58a8763fa69172980b98e3d24720c1136egm * Currently one version is defined and it is 1. This will be useful in future
a93a1f58a8763fa69172980b98e3d24720c1136egm * in the unlikely need to change the structure.
a93a1f58a8763fa69172980b98e3d24720c1136egm */
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_session_t *
a93a1f58a8763fa69172980b98e3d24720c1136egmsdp_new_session()
a93a1f58a8763fa69172980b98e3d24720c1136egm{
a93a1f58a8763fa69172980b98e3d24720c1136egm sdp_session_t *session = NULL;
a93a1f58a8763fa69172980b98e3d24720c1136egm
a93a1f58a8763fa69172980b98e3d24720c1136egm session = calloc(1, sizeof (sdp_session_t));
a93a1f58a8763fa69172980b98e3d24720c1136egm if (session != NULL)
a93a1f58a8763fa69172980b98e3d24720c1136egm session->sdp_session_version = SDP_SESSION_VERSION_1;
a93a1f58a8763fa69172980b98e3d24720c1136egm return (session);
a93a1f58a8763fa69172980b98e3d24720c1136egm}