📄 sdp.c
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@CFILE sdp.c Simple SDP interface. * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * @author Kai Vehmanen <kai.vehmanen@nokia.com> * * @date Created: Fri Feb 18 10:25:08 2000 ppessi */#include "config.h"#include <stddef.h>#include <stdlib.h>#include <string.h>#include <stdarg.h>#include <stdio.h>#include <assert.h>#include <sofia-sip/su_alloc.h>#include <sofia-sip/su_types.h>#include "sofia-sip/sdp.h"struct align { void *_a; char _b; };#define ALIGN(v, n) ((n - (intptr_t)(v)) & (n - 1))#define STRUCT_ALIGN_ (sizeof(struct align) - offsetof(struct align, _b))#define STRUCT_ALIGN(v) ALIGN(v, sizeof(void *))#define ASSERT_STRUCT_ALIGN(p) \ (STRUCT_ALIGN(p) ? (void)assert(!"STRUCT_ALIGNED(" #p ")") : (void)0)const unsigned sdp_struct_align_ = sizeof(void *) - STRUCT_ALIGN_;#define STR_XTRA(rv, s) ((s) ? rv += strlen((s)) + 1 : 0)#define PTR_XTRA(rv, p, f) \ ((p) ? (rv += STRUCT_ALIGN(rv) + f(p)) : 0)#define LST_XTRA(rv, l, f) \ ((l) ? (rv += STRUCT_ALIGN(rv) + list_xtra_all((xtra_f*)f, l)) : 0)#define STRUCT_DUP(p, dst, src) \ ASSERT_STRUCT_ALIGN(p); assert(*(int*)(src) >= (int)sizeof(*src)); \ ((*(int*)(src) >= (int)sizeof(*src) \ ? (dst = memcpy((p), (src), sizeof(*src))) \ : (dst = memcpy((p), (src), *(int*)(src))), \ memset((p)+*(int*)(src), 0, sizeof(*src) - *(int*)(src))), \ ((p) += sizeof(*src)))#define STRUCT_DUP2(p, dst, src) \ ASSERT_STRUCT_ALIGN(p); assert(*(int*)(src) >= (int)sizeof(*src)); \ (dst = memcpy((p), (src), *(int*)(src)), ((p) += *(int*)(src)))#define STR_DUP(p, dst, src, m) \ ((src->m) ? ((dst->m) = strcpy((p), (src->m)), (p) += strlen((p)) + 1) \ : ((dst->m) = 0))#define PTR_DUP(p, dst, src, m, dup) \ ((dst->m) = (src->m)?((p += STRUCT_ALIGN(p)), ((dup)(&(p), (src->m)))): 0)#define LST_DUP(p, dst, src, m, dup) \ ((dst->m) = (src->m)?((p += STRUCT_ALIGN(p)),\ list_dup_all((dup_f*)(dup), &(p), src->m)) : 0)#define MED_XTRA_EX(rv, l, c) \ ((l) ? (rv += STRUCT_ALIGN(rv) + media_xtra_ex(l, c)) : 0)#define MED_DUP_EX(p, dst, src, m, dst_c, src_c) \ ((dst->m) = (src->m)?((p += STRUCT_ALIGN(p)),\ media_dup_all(&(p), src->m, dst, dst_c, src_c)) : 0)#define MED_XTRA_ALL(rv, m) \ ((m) ? (rv += STRUCT_ALIGN(rv) + media_xtra_all(m)) : 0)#define MED_DUP_ALL(p, dst, src, m) \ ((dst->m) = (src->m)?((p += STRUCT_ALIGN(p)),\ media_dup_all(&(p), src->m, dst)) : 0)typedef size_t xtra_f(void const *);typedef void *dup_f(char **bb, void const *src);static size_t list_xtra_all(xtra_f *xtra, void const *v);static void *list_dup_all(dup_f *dup, char **bb, void const *vsrc);static size_t session_xtra(sdp_session_t const *o); static sdp_session_t *session_dup(char **pp, sdp_session_t const *o);static size_t origin_xtra(sdp_origin_t const *o); static sdp_origin_t *origin_dup(char **pp, sdp_origin_t const *o);static size_t connection_xtra(sdp_connection_t const *o); static sdp_connection_t *connection_dup(char **pp, sdp_connection_t const *o);static size_t bandwidth_xtra(sdp_bandwidth_t const *o); static sdp_bandwidth_t *bandwidth_dup(char **pp, sdp_bandwidth_t const *o);static size_t time_xtra(sdp_time_t const *o); static sdp_time_t *time_dup(char **pp, sdp_time_t const *o);static size_t repeat_xtra(sdp_repeat_t const *o); static sdp_repeat_t *repeat_dup(char **pp, sdp_repeat_t const *o);static size_t zone_xtra(sdp_zone_t const *o); static sdp_zone_t *zone_dup(char **pp, sdp_zone_t const *o);static size_t key_xtra(sdp_key_t const *o); static sdp_key_t *key_dup(char **pp, sdp_key_t const *o);static size_t attribute_xtra(sdp_attribute_t const *o); static sdp_attribute_t *attribute_dup(char **pp, sdp_attribute_t const *o);static size_t list_xtra(sdp_list_t const *o); static sdp_list_t *list_dup(char **pp, sdp_list_t const *o);static size_t rtpmap_xtra(sdp_rtpmap_t const *o); static sdp_rtpmap_t *rtpmap_dup(char **pp, sdp_rtpmap_t const *o);static size_t media_xtra(sdp_media_t const *o);static sdp_media_t *media_dup(char **pp, sdp_media_t const *o, sdp_session_t *sdp);#ifdef nomorestatic size_t media_xtra_ex(sdp_media_t const *o, sdp_connection_t const *c);static sdp_media_t *media_dup_ex(char **pp, sdp_media_t const *o, sdp_session_t *sdp, sdp_connection_t *dst_c, sdp_connection_t const *src_c);#endifstatic size_t media_xtra_all(sdp_media_t const *o);static sdp_media_t *media_dup_all(char **pp, sdp_media_t const *o, sdp_session_t *sdp);/** Define a function body duplicating an SDP structure. */#define SDP_DUP(type, name) \ sdp_##type##_t *rv; size_t size; char *p, *end; \ if (!name) return NULL; \ size = type##_xtra(name); \ p = su_alloc(h, size); end = p + size; \ rv = type##_dup(&p, name); \ assert(p == end); \ return rv;/** Define a function body duplicating a list of SDP structures. */#define SDP_LIST_DUP(type, name) \ sdp_##type##_t *rv; size_t size; char *p, *end; \ if (!name) return NULL; \ size = list_xtra_all((xtra_f*)type##_xtra, name); \ rv = su_alloc(h, size); p = (char *)rv; end = p + size; \ list_dup_all((dup_f*)type##_dup, &p, name); \ assert(p == end); \ return rv;/**Duplicate an SDP origin description. * * The function sdp_origin_dup() duplicates (deeply copies) an SDP origin * description燖a o allocating memory using memory @a home. * * @param h Memory home * @param o SDP origin description to be duplicated * * @return * If successful, a pointer to newly allocated sdp_origin_t structure is * returned, otherwise NULL is returned. */sdp_origin_t *sdp_origin_dup(su_home_t *h, sdp_origin_t const *o){ SDP_DUP(origin, o);}/**Duplicate an SDP connection description. * * The function sdp_connection_dup() duplicates (deeply copies) an SDP * connection description燖a c allocating memory using memory @a home. * * @param h Memory home * @param c SDP connection description to be duplicated * * @return * If successful, a pointer to newly allocated sdp_connection_t structure is * returned, otherwise NULL is returned. */sdp_connection_t *sdp_connection_dup(su_home_t *h, sdp_connection_t const *c){ SDP_LIST_DUP(connection, c);}/**Duplicate an SDP bandwidth description. * * The function sdp_bandwidth_dup() duplicates (deeply copies) an SDP * bandwidth description燖a b allocating memory using memory @a home. * * @param h Memory home * @param b SDP bandwidth description to be duplicated * * @return * If successful, a pointer to newly allocated sdp_bandwidth_t structure is * returned, otherwise NULL is returned. */sdp_bandwidth_t *sdp_bandwidth_dup(su_home_t *h, sdp_bandwidth_t const *b){ SDP_LIST_DUP(bandwidth, b);}/**Duplicate an SDP time description. * * The function sdp_time_dup() duplicates (deeply copies) an SDP time * description燖a t allocating memory using memory @a home. * * @param h Memory home * @param t SDP time description to be duplicated * * @return * If successful, a pointer to newly allocated sdp_time_t structure is * returned, otherwise NULL is returned. */sdp_time_t *sdp_time_dup(su_home_t *h, sdp_time_t const *t){ SDP_LIST_DUP(time, t);}/**Duplicate an SDP repeat description. * * The function sdp_repeat_dup() duplicates (deeply copies) an SDP repeat * description燖a r allocating memory using memory @a home. * * @param h Memory home * @param r SDP repeat description to be duplicated * * @return * If successful, a pointer to newly allocated sdp_repeat_t structure is * returned, otherwise NULL is returned. */sdp_repeat_t *sdp_repeat_dup(su_home_t *h, sdp_repeat_t const *r){ SDP_DUP(repeat, r);}/**Duplicate an SDP zone description. * * The function sdp_zone_dup() duplicates (deeply copies) an SDP zone * description燖a z allocating memory using memory @a home. * * @param h Memory home * @param z SDP zone description to be duplicated * * @return * If successful, a pointer to newly allocated sdp_zone_t structure is * returned, otherwise NULL is returned. */sdp_zone_t *sdp_zone_dup(su_home_t *h, sdp_zone_t const *z){ SDP_DUP(zone, z);}/**Duplicate an SDP key description. * * The function sdp_key_dup() duplicates (deeply copies) an SDP key * description燖a k allocating memory using memory @a home. * * @param h Memory home * @param k SDP key description to be duplicated * * @return * If successful, a pointer to newly allocated sdp_key_t structure is * returned, otherwise NULL is returned. */sdp_key_t *sdp_key_dup(su_home_t *h, sdp_key_t const *k){ SDP_DUP(key, k);}/**Duplicate an SDP attribute list. * * The function sdp_attribute_dup() duplicates (deeply copies) an SDP * attribute list @a a allocating memory using memory @a home. * * @param h Memory home * @param a SDP attribute description to be duplicated * * @return * If successful, a pointer to newly allocated sdp_attribute_t structure is * returned, otherwise NULL is returned. */sdp_attribute_t *sdp_attribute_dup(su_home_t *h, sdp_attribute_t const *a){ SDP_LIST_DUP(attribute, a);}/**Duplicate an SDP list of text. * * The function sdp_list_dup() duplicates (deeply copies) an SDP text * list @a l allocating memory using memory @a home. * * @param h Memory home * @param l SDP list description to be duplicated * * @return * If successful, a pointer to newly allocated sdp_list_t structure is * returned, otherwise NULL is returned. */sdp_list_t *sdp_list_dup(su_home_t *h, sdp_list_t const *l){ SDP_LIST_DUP(list, l);}/**Duplicate an SDP rtpmap list. * * The function sdp_rtpmap_dup() duplicates (deeply copies) an SDP rtpmap * list @a rm allocating memory using memory @a home. * * @param h Memory home * @param rm SDP rtpmap description to be duplicated * * @return * If successful, a pointer to newly allocated sdp_rtpmap_t structure is * returned, otherwise NULL is returned. */sdp_rtpmap_t *sdp_rtpmap_dup(su_home_t *h, sdp_rtpmap_t const *rm){ SDP_LIST_DUP(rtpmap, rm);}/**Duplicate an SDP media description. * * The function sdp_media_dup() duplicates (deeply copies) an SDP media * description燖a m allocating memory using memory @a home. * * @param h Memory home * @param m SDP media description to be duplicated * @param sdp SDP session description to which the newly allocated * media description is linked * * @return * If successful, a pointer to newly allocated sdp_media_t structure is * returned, otherwise NULL is returned. */sdp_media_t *sdp_media_dup(su_home_t *h, sdp_media_t const *m, sdp_session_t *sdp){ sdp_media_t *rv; size_t size; char *p, *end; size = media_xtra(m); p = su_alloc(h, size); end = p + size; rv = media_dup(&p, m, sdp); assert(p == end); return rv;}/**Duplicate an SDP media description. * * The function sdp_media_dup_all() duplicates (deeply copies) a list of SDP * media descriptions燖a m allocating memory using memory @a home. * * @param h Memory home * @param m list of SDP media descriptions to be duplicated * @param sdp SDP session description to which the newly allocated * media descriptions are linked * * @return * If successful, a pointer to a newly allocated list of sdp_media_t * structures is returned, otherwise NULL is returned. */sdp_media_t *sdp_media_dup_all(su_home_t *h, sdp_media_t const *m, sdp_session_t *sdp){ sdp_media_t *rv; size_t size; char *p, *end; size = media_xtra_all(m); p = su_alloc(h, size); end = p + size; rv = media_dup_all(&p, m, sdp); assert(p == end); return rv;}#ifdef nomore /* really deprecated *//**Duplicate media description with common address. * * This function is provided in order to avoid duplicate @c c= lines. If * the @c c= line in media description equals to @a src_c, it is not * duplicated but replaced with @a dst_c instead. * * @param home Memory home * @param src SDP media description to be duplicated * @param sdp SDP session description to which the newly allocated * media description is linked * @param dst_c Connection description used instead of duplicate of @a src_c. * @param src_c Connection description not to be duplicated * @return * If successful, a pointer to newly allocated sdp_media_t structure is * returned, otherwise NULL is returned. * * @deprecated * This function is deprecated. Use sdp_media_dup() instead. */sdp_media_t *sdp_media_dup_ex(su_home_t *home, sdp_media_t const *src, sdp_session_t *sdp, sdp_connection_t *dst_c, sdp_connection_t const *src_c){ sdp_media_t *rv; size_t size; char *p, *end; size = media_xtra_all(src, src_c); p = su_alloc(home, size); end = p + size; rv = media_dup_all(&p, src, sdp, dst_c, src_c); assert(p == end); return rv;}#endif/* ---------------------------------------------------------------------- */static size_t origin_xtra(sdp_origin_t const *o){ size_t rv = sizeof(*o); STR_XTRA(rv, o->o_username); PTR_XTRA(rv, o->o_address, connection_xtra); return rv;}staticsdp_origin_t *origin_dup(char **pp, sdp_origin_t const *src){ char *p; sdp_origin_t *o; p = *pp; STRUCT_DUP(p, o, src); STR_DUP(p, o, src, o_username); PTR_DUP(p, o, src, o_address, connection_dup); assert((size_t)(p - *pp) == origin_xtra(src)); *pp = p; return o;}static size_t connection_xtra(sdp_connection_t const *c){ size_t rv = sizeof(*c); STR_XTRA(rv, c->c_address); return rv;}staticsdp_connection_t *connection_dup(char **pp, sdp_connection_t const *src){ char *p; sdp_connection_t *c; p = *pp; STRUCT_DUP(p, c, src);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -