Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/sipcc/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 47 kB image not shown  

Quelle  sdp_main.c   Sprache: C

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "sdp_os_defs.h"
#include "sipcc_sdp.h"
#include "sdp_private.h"

#include "sdp_log.h"

static const char* logTag = "sdp_main";

/* Note: These *must* be in the same order as the enum types. */
const sdp_tokenarray_t sdp_token[SDP_MAX_TOKENS] =
{
    {"v=", sdp_parse_version,      sdp_build_version },
    {"o=", sdp_parse_owner,        sdp_build_owner },
    {"s=", sdp_parse_sessname,     sdp_build_sessname },
    {"i=", sdp_parse_sessinfo,     sdp_build_sessinfo },
    {"u=", sdp_parse_uri,          sdp_build_uri },
    {"e=", sdp_parse_email,        sdp_build_email },
    {"p=", sdp_parse_phonenum,     sdp_build_phonenum },
    {"c=", sdp_parse_connection,   sdp_build_connection },
    {"b=", sdp_parse_bandwidth,    sdp_build_bandwidth },
    {"t=", sdp_parse_timespec,     sdp_build_timespec },
    {"r=", sdp_parse_repeat_time,  sdp_build_repeat_time },
    {"z=", sdp_parse_timezone_adj, sdp_build_timezone_adj },
    {"k=", sdp_parse_encryption,   sdp_build_encryption },
    {"a=", sdp_parse_attribute,    sdp_build_attribute },
    {"m=", sdp_parse_media,        sdp_build_media }
};


/* Note: These *must* be in the same order as the enum types. */
const sdp_attrarray_t sdp_attr[SDP_MAX_ATTR_TYPES] =
{
    {"bearer"sizeof("bearer"),
     sdp_parse_attr_simple_string, sdp_build_attr_simple_string },
    {"called"sizeof("called"),
     sdp_parse_attr_simple_string, sdp_build_attr_simple_string },
    {"connection_type"sizeof("connection_type"),
     sdp_parse_attr_simple_string, sdp_build_attr_simple_string },
    {"dialed"sizeof("dialed"),
     sdp_parse_attr_simple_string, sdp_build_attr_simple_string },
    {"dialing"sizeof("dialing"),
     sdp_parse_attr_simple_string, sdp_build_attr_simple_string },
    {"direction"sizeof("direction"),
     sdp_parse_attr_comediadir, sdp_build_attr_comediadir },
    {"eecid"sizeof("eecid"),
     sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
    {"fmtp"sizeof("fmtp"),
     sdp_parse_attr_fmtp, sdp_build_attr_fmtp },
    {"sctpmap"sizeof("sctpmap"),
     sdp_parse_attr_sctpmap, sdp_build_attr_sctpmap },
    {"framing"sizeof("framing"),
     sdp_parse_attr_simple_string, sdp_build_attr_simple_string },
    {"inactive"sizeof("inactive"),
     sdp_parse_attr_direction, sdp_build_attr_direction },
    {"ptime"sizeof("ptime"),
     sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
    {"qos"sizeof("qos"),
     sdp_parse_attr_qos, sdp_build_attr_qos },
    {"curr"sizeof("curr"),
     sdp_parse_attr_curr, sdp_build_attr_curr },
    {"des"sizeof("des"),
     sdp_parse_attr_des, sdp_build_attr_des},
    {"conf"sizeof("conf"),
     sdp_parse_attr_conf, sdp_build_attr_conf},
    {"recvonly"sizeof("recvonly"),
     sdp_parse_attr_direction, sdp_build_attr_direction },
    {"rtpmap"sizeof("rtpmap"),
     sdp_parse_attr_transport_map, sdp_build_attr_transport_map },
    {"secure"sizeof("secure"),
     sdp_parse_attr_qos, sdp_build_attr_qos },
    {"sendonly"sizeof("sendonly"),
     sdp_parse_attr_direction, sdp_build_attr_direction },
    {"sendrecv"sizeof("sendrecv"),
     sdp_parse_attr_direction, sdp_build_attr_direction },
    {"subnet"sizeof("subnet"),
     sdp_parse_attr_subnet, sdp_build_attr_subnet },
    {"T38FaxVersion"sizeof("T38FaxVersion"),
     sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
    {"T38MaxBitRate"sizeof("T38MaxBitRate"),
     sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
    {"T38FaxFillBitRemoval"sizeof("T38FaxFillBitRemoval"),
     sdp_parse_attr_simple_bool, sdp_build_attr_simple_bool },
    {"T38FaxTranscodingMMR"sizeof("T38FaxTranscodingMMR"),
     sdp_parse_attr_simple_bool, sdp_build_attr_simple_bool },
    {"T38FaxTranscodingJBIG"sizeof("T38FaxTranscodingJBIG"),
     sdp_parse_attr_simple_bool, sdp_build_attr_simple_bool },
    {"T38FaxRateManagement"sizeof("T38FaxRateManagement"),
     sdp_parse_attr_t38_ratemgmt, sdp_build_attr_t38_ratemgmt },
    {"T38FaxMaxBuffer"sizeof("T38FaxMaxBuffer"),
     sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
    {"T38FaxMaxDatagram"sizeof("T38FaxMaxDatagram"),
     sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
    {"T38FaxUdpEC"sizeof("T38FaxUdpEC"),
     sdp_parse_attr_t38_udpec, sdp_build_attr_t38_udpec },
    {"X-cap"sizeof("X-cap"),
     sdp_parse_attr_cap, sdp_build_attr_cap },
    {"X-cpar"sizeof("X-cpar"),
     sdp_parse_attr_cpar, sdp_build_attr_cpar },
    {"X-pc-codec"sizeof("X-pc-codec"),
     sdp_parse_attr_pc_codec, sdp_build_attr_pc_codec },
    {"X-pc-qos"sizeof("X-pc-qos"),
     sdp_parse_attr_qos, sdp_build_attr_qos },
    {"X-qos"sizeof("X-qos"),
     sdp_parse_attr_qos, sdp_build_attr_qos },
    {"X-sqn"sizeof("X-sqn"),
     sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
    {"TMRGwXid"sizeof("TMRGwXid"),
     sdp_parse_attr_simple_bool, sdp_build_attr_simple_bool },
    {"TC1PayloadBytes"sizeof("TC1PayloadBytes"),
     sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
    {"TC1WindowSize"sizeof("TC1WindowSize"),
     sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
    {"TC2PayloadBytes"sizeof("TC2PayloadBytes"),
     sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
    {"TC2WindowSize"sizeof("TC2WindowSize"),
     sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
    {"rtcp"sizeof("rtcp"),
     sdp_parse_attr_rtcp, sdp_build_attr_rtcp },
    {"rtr"sizeof("rtr"),
     sdp_parse_attr_rtr, sdp_build_attr_rtr},
    {"silenceSupp"sizeof("silenceSupp"),
     sdp_parse_attr_silencesupp, sdp_build_attr_silencesupp },
    {"X-crypto"sizeof("X-crypto"),
     sdp_parse_attr_srtpcontext, sdp_build_attr_srtpcontext },
    {"mptime"sizeof("mptime"),
      sdp_parse_attr_mptime, sdp_build_attr_mptime },
    {"X-sidin"sizeof("X-sidin"),
      sdp_parse_attr_x_sidin, sdp_build_attr_x_sidin },
    {"X-sidout"sizeof("X-sidout"),
      sdp_parse_attr_x_sidout, sdp_build_attr_x_sidout },
    {"X-confid"sizeof("X-confid"),
      sdp_parse_attr_x_confid, sdp_build_attr_x_confid },
    {"group"sizeof("group"),
      sdp_parse_attr_group, sdp_build_attr_group },
    {"mid"sizeof("mid"),
      sdp_parse_attr_simple_string, sdp_build_attr_simple_string },
    {"source-filter"sizeof("source-filter"),
      sdp_parse_attr_source_filter, sdp_build_source_filter},
    {"rtcp-unicast"sizeof("rtcp-unicast"),
      sdp_parse_attr_rtcp_unicast, sdp_build_attr_rtcp_unicast},
    {"maxprate"sizeof("maxprate"),
      sdp_parse_attr_maxprate, sdp_build_attr_simple_string},
    {"sqn"sizeof("sqn"),
     sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
    {"cdsc"sizeof("cdsc"),
     sdp_parse_attr_cap, sdp_build_attr_cap },
    {"cpar"sizeof("cpar"),
     sdp_parse_attr_cpar, sdp_build_attr_cpar },
    {"sprtmap"sizeof("sprtmap"),
     sdp_parse_attr_transport_map, sdp_build_attr_transport_map },
    {"crypto"sizeof("crypto"),
     sdp_parse_attr_sdescriptions, sdp_build_attr_sdescriptions },
    {"label"sizeof("label"),
      sdp_parse_attr_simple_string, sdp_build_attr_simple_string },
    {"framerate"sizeof("framerate"),
      sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32 },
    {"candidate"sizeof("candidate"),
      sdp_parse_attr_ice_attr, sdp_build_attr_ice_attr },
    {"ice-ufrag"sizeof("ice-ufrag"),
      sdp_parse_attr_ice_attr, sdp_build_attr_ice_attr },
    {"ice-pwd"sizeof("ice-pwd"),
      sdp_parse_attr_ice_attr, sdp_build_attr_ice_attr},
    {"ice-lite"sizeof("ice-lite"),
      sdp_parse_attr_simple_flag, sdp_build_attr_simple_flag},
    {"rtcp-mux"sizeof("rtcp-mux"),
      sdp_parse_attr_simple_flag, sdp_build_attr_simple_flag},
    {"fingerprint"sizeof("fingerprint"),
      sdp_parse_attr_complete_line, sdp_build_attr_simple_string},
    {"maxptime"sizeof("maxptime"),
      sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32},
    {"rtcp-fb"sizeof("rtcp-fb"),
      sdp_parse_attr_rtcp_fb, sdp_build_attr_rtcp_fb},
    {"setup"sizeof("setup"),
      sdp_parse_attr_setup, sdp_build_attr_setup},
    {"connection"sizeof("connection"),
      sdp_parse_attr_connection, sdp_build_attr_connection},
    {"extmap"sizeof("extmap"),
      sdp_parse_attr_extmap, sdp_build_attr_extmap},
    {"identity"sizeof("identity"),
      sdp_parse_attr_long_line, sdp_build_attr_long_line},
    {"msid"sizeof("msid"),
      sdp_parse_attr_msid, sdp_build_attr_msid},
    {"msid-semantic"sizeof("msid-semantic"),
      sdp_parse_attr_msid_semantic, sdp_build_attr_msid_semantic},
    {"bundle-only"sizeof("bundle-only"),
      sdp_parse_attr_simple_flag, sdp_build_attr_simple_flag},
    {"end-of-candidates"sizeof("end-of-candidates"),
      sdp_parse_attr_simple_flag, sdp_build_attr_simple_flag},
    {"ice-options"sizeof("ice-options"),
      sdp_parse_attr_complete_line, sdp_build_attr_simple_string},
    {"ssrc"sizeof("ssrc"),
      sdp_parse_attr_ssrc, sdp_build_attr_ssrc},
    {"imageattr"sizeof("imageattr"),
      sdp_parse_attr_complete_line, sdp_build_attr_simple_string},
    {"simulcast"sizeof("simulcast"),
      sdp_parse_attr_complete_line, sdp_build_attr_simple_string},
    {"rid"sizeof("rid"),
      sdp_parse_attr_complete_line, sdp_build_attr_simple_string},
    {"dtls-message"sizeof("dtls-message"),
      sdp_parse_attr_long_line, sdp_build_attr_long_line},
    {"sctp-port"sizeof("sctp-port"),
      sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32},
    {"max-message-size"sizeof("max-message-size"),
      sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32},
    {"ssrc-group"sizeof("ssrc-group"), sdp_parse_attr_ssrc_group,
      sdp_build_attr_ssrc_group},
    {"rtcp-rsize"sizeof("rtcp-rsize"),
      sdp_parse_attr_simple_flag, sdp_build_attr_simple_flag},
};

/* Note: These *must* be in the same order as the enum types. */
const sdp_namearray_t sdp_media[SDP_MAX_MEDIA_TYPES] =
{
    {"audio",        sizeof("audio")},
    {"video",        sizeof("video")},
    {"application",  sizeof("application")},
    {"data",         sizeof("data")},
    {"control",      sizeof("control")},
    {"nas/radius",   sizeof("nas/radius")},
    {"nas/tacacs",   sizeof("nas/tacacs")},
    {"nas/diameter"sizeof("nas/diameter")},
    {"nas/l2tp",     sizeof("nas/l2tp")},
    {"nas/login",    sizeof("nas/login")},
    {"nas/none",     sizeof("nas/none")},
    {"image",        sizeof("image")},
    {"text",         sizeof("text")}
};


/* Note: These *must* be in the same order as the enum types. */
const sdp_namearray_t sdp_nettype[SDP_MAX_NETWORK_TYPES] =
{
    {"IN",           sizeof("IN")},
    {"ATM",          sizeof("ATM")},
    {"FR",           sizeof("FR")},
    {"LOCAL",        sizeof("LOCAL")}
};


/* Note: These *must* be in the same order as the enum types. */
const sdp_namearray_t sdp_addrtype[SDP_MAX_ADDR_TYPES] =
{
    {"IP4",          sizeof("IP4")},
    {"IP6",          sizeof("IP6")},
    {"NSAP",         sizeof("NSAP")},
    {"EPN",          sizeof("EPN")},
    {"E164",         sizeof("E164")},
    {"GWID",         sizeof("GWID")}
};


/* Note: These *must* be in the same order as the enum type. */
const sdp_namearray_t sdp_transport[SDP_MAX_TRANSPORT_TYPES] =
{
    {"RTP/AVP",      sizeof("RTP/AVP")},
    {"udp",          sizeof("udp")},
    {"udptl",        sizeof("udptl")},
    {"ces10",        sizeof("ces10")},
    {"LOCAL",        sizeof("LOCAL")},
    {"AAL2/ITU",     sizeof("AAL2/ITU")},
    {"AAL2/ATMF",    sizeof("AAL2/ATMF")},
    {"AAL2/custom",  sizeof("AAL2/custom")},
    {"AAL1/AVP",     sizeof("AAL1/AVP")},
    {"udpsprt",      sizeof("udpsprt")},
    {"RTP/SAVP",     sizeof("RTP/SAVP")},
    {"tcp",          sizeof("tcp")},
    {"RTP/SAVPF",    sizeof("RTP/SAVPF")},
    {"DTLS/SCTP",    sizeof("DTLS/SCTP")},
    {"RTP/AVPF",     sizeof("RTP/AVPF")},
    {"UDP/TLS/RTP/SAVP"sizeof("UDP/TLS/RTP/SAVP")},
    {"UDP/TLS/RTP/SAVPF"sizeof("UDP/TLS/RTP/SAVPF")},
    {"TCP/DTLS/RTP/SAVP"sizeof("TCP/DTLS/RTP/SAVP")},
    {"TCP/DTLS/RTP/SAVPF"sizeof("TCP/DTLS/RTP/SAVPF")},
    {"UDP/DTLS/SCTP",    sizeof("UDP/DTLS/SCTP")},
    {"TCP/DTLS/SCTP",    sizeof("TCP/DTLS/SCTP")},
};

/* Note: These *must* be in the same order as the enum type. */
const sdp_namearray_t sdp_encrypt[SDP_MAX_ENCRYPT_TYPES] =
{
    {"clear",        sizeof("clear")},
    {"base64",       sizeof("base64")},
    {"uri",          sizeof("uri")},
    {"prompt",       sizeof("prompt")}
};

/* Note: These *must* be in the same order as the enum type. */
const sdp_namearray_t sdp_payload[SDP_MAX_STRING_PAYLOAD_TYPES] =
{
    {"t38",          sizeof("t38")},
    {"X-tmr",        sizeof("X-tmr")},
    {"T120",         sizeof("T120")}
};

/* Note: These *must* be in the same order as the enum type. */
const sdp_namearray_t sdp_t38_rate[SDP_T38_MAX_RATES] =
{
    {"localTCF",        sizeof("localTCF")},
    {"transferredTCF",  sizeof("transferredTCF")},
    {"unknown",         sizeof("unknown")}
};

/* Note: These *must* be in the same order as the enum type. */
const sdp_namearray_t sdp_t38_udpec[SDP_T38_MAX_UDPEC] =
{
    {"t38UDPRedundancy",  sizeof("t38UDPRedundancy")},
    {"t38UDPFEC",         sizeof("t38UDPFEC")},
    {"unknown",           sizeof("unknown")}
};

/* Note: These *must* be in the same order as the enum type. */
const sdp_namearray_t sdp_qos_strength[SDP_MAX_QOS_STRENGTH] =
{
    {"optional",          sizeof("optional")},
    {"mandatory",         sizeof("mandatory")},
    {"success",           sizeof("success")},
    {"failure",           sizeof("failure")},
    {"none",              sizeof("none")}
};

/* Note: These *must* be in the same order as the enum type. */
const sdp_namearray_t sdp_qos_status_type[SDP_MAX_QOS_STATUS_TYPES] =
{
    {"local",          sizeof("local")},
    {"remote",         sizeof("remote")},
    {"e2e",            sizeof("e2e")}
};

/* Note: These *must* be in the same order as the enum type. */
const sdp_namearray_t sdp_curr_type[SDP_MAX_CURR_TYPES] =
{
    {"qos",            sizeof("qos")},
    {"unknown",         sizeof("unknown")}
};

/* Note: These *must* be in the same order as the enum type. */
const sdp_namearray_t sdp_des_type[SDP_MAX_DES_TYPES] =
{
    {"qos",            sizeof("qos")},
    {"unknown",         sizeof("unknown")}
};

/* Note: These *must* be in the same order as the enum type. */
const sdp_namearray_t sdp_conf_type[SDP_MAX_CONF_TYPES] =
{
    {"qos",            sizeof("qos")},
    {"unknown",         sizeof("unknown")}
};
/* Note: These *must* be in the same order as the enum type. */
const sdp_namearray_t sdp_qos_direction[SDP_MAX_QOS_DIR] =
{
    {"send",              sizeof("send")},
    {"recv",              sizeof("recv")},
    {"sendrecv",          sizeof("sendrecv")},
    {"none",              sizeof("none")}
};

/* Note: These *must* be in the same order as the enum type. */
const sdp_namearray_t sdp_silencesupp_pref[SDP_MAX_SILENCESUPP_PREF] = {
    {"standard",          sizeof("standard")},
    {"custom",            sizeof("custom")},
    {"-",                 sizeof("-")}
};

/* Note: These *must* be in the same order as the enum type. */
const sdp_namearray_t sdp_silencesupp_siduse[SDP_MAX_SILENCESUPP_SIDUSE] = {
    {"No SID",            sizeof("No SID")},
    {"Fixed Noise",       sizeof("Fixed Noise")},
    {"Sampled Noise",     sizeof("Sampled Noise")},
    {"-",                 sizeof("-")}
};

/* Note: These *must* be in the same order as the enum type. */
const sdp_namearray_t sdp_mediadir_role[SDP_MAX_MEDIADIR_ROLES] =
{
    {"passive",       sizeof("passive")},
    {"active",        sizeof("active")},
    {"both",          sizeof("both")},
    {"reuse",         sizeof("reuse")},
    {"unknown",       sizeof("unknown")}
};

/* Note: These *must* be in the same order as the enum type. */
const sdp_namearray_t sdp_fmtp_codec_param[SDP_MAX_FMTP_PARAM] =
{
    {"annexa",              sizeof("annexa")}, /* 0 */
    {"annexb",              sizeof("annexb")}, /* 1 */
    {"bitrate",             sizeof("bitrate")}, /* 2 */
    {"QCIF",                sizeof("QCIF")}, /* 3 */
    {"CIF",                 sizeof("CIF")},  /* 4 */
    {"MAXBR",               sizeof("MAXBR")}, /* 5 */
    {"SQCIF",               sizeof("SQCIF")}, /* 6 */
    {"CIF4",                sizeof("CIF4")}, /* 7 */
    {"CIF16",               sizeof("CIF16")}, /* 8 */
    {"CUSTOM",              sizeof("CUSTOM")}, /* 9 */
    {"PAR",                 sizeof("PAR")}, /* 10 */
    {"CPCF",                sizeof("CPCF")}, /* 11 */
    {"BPP",                 sizeof("BPP")}, /* 12 */
    {"HRD",                 sizeof("HRD")}, /* 13 */
    {"PROFILE",             sizeof("PROFILE")}, /* 14 */
    {"LEVEL",               sizeof("LEVEL")}, /* 15 */
    {"INTERLACE",           sizeof("INTERLACE")}, /* 16 */

    /* H.264 related */
    {"profile-level-id",      sizeof("profile-level-id")}, /* 17 */
    {"sprop-parameter-sets",  sizeof("sprop-parameter-sets")}, /* 18 */
    {"packetization-mode",    sizeof("packetization-mode")}, /* 19 */
    {"sprop-interleaving-depth",    sizeof("sprop-interleaving-depth")}, /* 20 */
    {"sprop-deint-buf-req",   sizeof("sprop-deint-buf-req")}, /* 21 */
    {"sprop-max-don-diff",    sizeof("sprop-max-don-diff")}, /* 22 */
    {"sprop-init-buf-time",   sizeof("sprop-init-buf-time")}, /* 23 */

    {"max-mbps",              sizeof("max-mbps")}, /* 24 */
    {"max-fs",                sizeof("max-fs")}, /* 25 */
    {"max-cpb",               sizeof("max-cpb")}, /* 26 */
    {"max-dpb",               sizeof("max-dpb")}, /* 27 */
    {"max-br",                sizeof("max-br")}, /* 28 */
    {"redundant-pic-cap",     sizeof("redundant-pic-cap")}, /* 29 */
    {"deint-buf-cap",         sizeof("deint-buf-cap")}, /* 30 */
    {"max-rcmd-nalu-size",    sizeof("max-rcmd_nali-size")}, /* 31 */
    {"parameter-add",         sizeof("parameter-add")}, /* 32 */

    /* Annexes - require special handling */
     {"D"sizeof("D")}, /* 33 */
     {"F"sizeof("F")}, /* 34 */
     {"I"sizeof("I")}, /* 35 */
     {"J"sizeof("J")}, /* 36 */
     {"T"sizeof("T")}, /* 37 */
     {"K"sizeof("K")}, /* 38 */
     {"N"sizeof("N")}, /* 39 */
     {"P"sizeof("P")}, /* 40 */

     {"mode",                sizeof("mode")},  /* 41 */
    {"level-asymmetry-allowed",         sizeof("level-asymmetry-allowed")}, /* 42 */
    {"maxaveragebitrate",               sizeof("maxaveragebitrate")}, /* 43 */
    {"usedtx",                          sizeof("usedtx")}, /* 44 */
    {"stereo",                          sizeof("stereo")}, /* 45 */
    {"useinbandfec",                    sizeof("useinbandfec")}, /* 46 */
    {"maxcodedaudiobandwidth",          sizeof("maxcodedaudiobandwidth")}, /* 47 */
    {"cbr",                             sizeof("cbr")}, /* 48 */
    {"max-fr",                          sizeof("max-fr")}, /* 49 */
    {"maxplaybackrate",                 sizeof("maxplaybackrate")}, /* 50 */
    {"apt",                             sizeof("apt")}, /* 51 */
    {"rtx-time",                         sizeof("rtx-time")}, /* 52 */
    {"level-idx",                        sizeof("level-idx")}, /* 53 */
    {"tier",                             sizeof("tier")}, /* 54 */
} ;

/* Note: These *must* be in the same order as the enum type. */
const sdp_namearray_t sdp_fmtp_codec_param_val[SDP_MAX_FMTP_PARAM_VAL] =
{
    {"yes",                 sizeof("yes")},
    {"no",                  sizeof("no")}
};

const sdp_namearray_t sdp_bw_modifier_val[SDP_MAX_BW_MODIFIER_VAL] =
{
    {"AS",                  sizeof("AS")},
    {"CT",                  sizeof("CT")},
    {"TIAS",                sizeof("TIAS")}
};

const sdp_namearray_t sdp_group_attr_val[SDP_MAX_GROUP_ATTR_VAL] =
{
    {"FID",                 sizeof("FID")},
    {"LS",                  sizeof("LS")},
    {"ANAT",                sizeof("ANAT")},
    {"BUNDLE",              sizeof("BUNDLE")}
};

const sdp_namearray_t sdp_ssrc_group_attr_val[SDP_MAX_SSRC_GROUP_ATTR_VAL] = {
    {"DUP"sizeof("DUP")},
    {"FEC"sizeof("FEC")},
    {"FEC-FR"sizeof("FEC-FR")},
    {"FID"sizeof("FID")},
    {"SIM"sizeof("SIM")}
};

const sdp_namearray_t sdp_srtp_context_crypto_suite[SDP_SRTP_MAX_NUM_CRYPTO_SUITES] =
{
  {"UNKNOWN_CRYPTO_SUITE",    sizeof("UNKNOWN_CRYPTO_SUITE")},
  {"AES_CM_128_HMAC_SHA1_32"sizeof("AES_CM_128_HMAC_SHA1_32")},
  {"AES_CM_128_HMAC_SHA1_80"sizeof("AES_CM_128_HMAC_SHA1_80")},
  {"F8_128_HMAC_SHA1_80"sizeof("F8_128_HMAC_SHA1_80")}
};

/* Maintain the same order as defined in typedef sdp_src_filter_mode_e */
const sdp_namearray_t sdp_src_filter_mode_val[SDP_MAX_FILTER_MODE] =
{
    {"incl"sizeof("incl")},
    {"excl"sizeof("excl")}
};

/* Maintain the same order as defined in typdef sdp_rtcp_unicast_mode_e */
const sdp_namearray_t sdp_rtcp_unicast_mode_val[SDP_RTCP_MAX_UNICAST_MODE] =
{
    {"reflection"sizeof("reflection")},
    {"rsi",        sizeof("rsi")}
};

#define SDP_NAME(x) {x, sizeof(x)}
/* Maintain the same order as defined in typdef sdp_rtcp_fb_type_e */
const sdp_namearray_t sdp_rtcp_fb_type_val[SDP_MAX_RTCP_FB] =
{
    SDP_NAME("ack"),
    SDP_NAME("ccm"),
    SDP_NAME("nack"),
    SDP_NAME("trr-int"),
    SDP_NAME("goog-remb"),
    SDP_NAME("transport-cc")
};

/* Maintain the same order as defined in typdef sdp_rtcp_fb_nack_type_e */
const sdp_namearray_t sdp_rtcp_fb_nack_type_val[SDP_MAX_RTCP_FB_NACK] =
{
    SDP_NAME(""),
    SDP_NAME("sli"),
    SDP_NAME("pli"),
    SDP_NAME("rpsi"),
    SDP_NAME("app"),
    SDP_NAME("rai"),
    SDP_NAME("tllei"),
    SDP_NAME("pslei"),
    SDP_NAME("ecn")
};

/* Maintain the same order as defined in typdef sdp_rtcp_fb_ack_type_e */
const sdp_namearray_t sdp_rtcp_fb_ack_type_val[SDP_MAX_RTCP_FB_ACK] =
{
    SDP_NAME("rpsi"),
    SDP_NAME("app")
};

/* Maintain the same order as defined in typdef sdp_rtcp_fb_ccm_type_e */
const sdp_namearray_t sdp_rtcp_fb_ccm_type_val[SDP_MAX_RTCP_FB_CCM] =
{
    SDP_NAME("fir"),
    SDP_NAME("tmmbr"),
    SDP_NAME("tstr"),
    SDP_NAME("vbcm")
};

/* Maintain the same order as defined in typedef sdp_setup_type_e */
const sdp_namearray_t sdp_setup_type_val[SDP_MAX_SETUP] =
{
    SDP_NAME("active"),
    SDP_NAME("passive"),
    SDP_NAME("actpass"),
    SDP_NAME("holdconn")
};

/* Maintain the same order as defined in typedef sdp_connection_type_e */
const sdp_namearray_t sdp_connection_type_val[SDP_MAX_CONNECTION] =
{
    SDP_NAME("new"),
    SDP_NAME("existing")
};

/*  Maintain same order as defined in typedef sdp_srtp_crypto_suite_t */
const sdp_srtp_crypto_suite_list sdp_srtp_crypto_suite_array[SDP_SRTP_MAX_NUM_CRYPTO_SUITES] =
{
  {SDP_SRTP_UNKNOWN_CRYPTO_SUITE, UNKNOWN_CRYPTO_SUITE, 0, 0},
  {SDP_SRTP_AES_CM_128_HMAC_SHA1_32, AES_CM_128_HMAC_SHA1_32,
      SDP_SRTP_AES_CM_128_HMAC_SHA1_32_KEY_BYTES,
      SDP_SRTP_AES_CM_128_HMAC_SHA1_32_SALT_BYTES},
  {SDP_SRTP_AES_CM_128_HMAC_SHA1_80, AES_CM_128_HMAC_SHA1_80,
      SDP_SRTP_AES_CM_128_HMAC_SHA1_80_KEY_BYTES,
      SDP_SRTP_AES_CM_128_HMAC_SHA1_80_SALT_BYTES},
  {SDP_SRTP_F8_128_HMAC_SHA1_80, F8_128_HMAC_SHA1_80,
      SDP_SRTP_F8_128_HMAC_SHA1_80_KEY_BYTES,
      SDP_SRTP_F8_128_HMAC_SHA1_80_SALT_BYTES}
};

const char* sdp_result_name[SDP_MAX_RC] =
    {"SDP_SUCCESS",
     "SDP_FAILURE",
     "SDP_INVALID_SDP_PTR",
     "SDP_NOT_SDP_DESCRIPTION",
     "SDP_INVALID_TOKEN_ORDERING",
     "SDP_INVALID_PARAMETER",
     "SDP_INVALID_MEDIA_LEVEL",
     "SDP_INVALID_CAPABILITY",
     "SDP_NO_RESOURCE",
     "SDP_UNRECOGNIZED_TOKEN",
     "SDP_NULL_BUF_PTR",
     "SDP_POTENTIAL_SDP_OVERFLOW",
     "SDP_EMPTY_TOKEN"};

const char *sdp_get_result_name ( sdp_result_e rc )
{
    if (rc >= SDP_MAX_RC) {
        return ("Invalid SDP result code");
    } else {
        return (sdp_result_name[rc]);
    }
}

const char *sdp_get_attr_name ( sdp_attr_e attr_type )
{
    if (attr_type >= SDP_MAX_ATTR_TYPES) {
        return ("Invalid attribute type");
    } else {
        return (sdp_attr[attr_type].name);
    }
}

const char *sdp_get_media_name ( sdp_media_e media_type )
{
    if (media_type == SDP_MEDIA_UNSUPPORTED) {
        return (SDP_UNSUPPORTED);
    } else if (media_type >= SDP_MAX_MEDIA_TYPES) {
        return ("Invalid media type");
    } else {
        return (sdp_media[media_type].name);
    }
}

const char *sdp_get_network_name ( sdp_nettype_e network_type )
{
    if (network_type == SDP_NT_UNSUPPORTED) {
        return (SDP_UNSUPPORTED);
    } else if (network_type >= SDP_MAX_NETWORK_TYPES) {
        return ("Invalid network type");
    } else {
        return (sdp_nettype[network_type].name);
    }
}

const char *sdp_get_address_name ( sdp_addrtype_e addr_type )
{
    if (addr_type == SDP_AT_UNSUPPORTED) {
        return (SDP_UNSUPPORTED);
    } else if (addr_type >= SDP_MAX_ADDR_TYPES) {
        if (addr_type == SDP_AT_FQDN) {
            return ("*");
        } else {
            return ("Invalid address type");
        }
    } else {
        return (sdp_addrtype[addr_type].name);
    }
}

const char *sdp_get_transport_name ( sdp_transport_e transport_type )
{
    if (transport_type == SDP_TRANSPORT_UNSUPPORTED) {
        return (SDP_UNSUPPORTED);
    } else if (transport_type >= SDP_MAX_TRANSPORT_TYPES) {
        return ("Invalid transport type");
    } else {
        return (sdp_transport[transport_type].name);
    }
}

const char *sdp_get_encrypt_name ( sdp_encrypt_type_e encrypt_type )
{
    if (encrypt_type == SDP_ENCRYPT_UNSUPPORTED) {
        return (SDP_UNSUPPORTED);
    } else if (encrypt_type >= SDP_MAX_ENCRYPT_TYPES) {
        return ("Invalid encryption type");
    } else {
        return (sdp_encrypt[encrypt_type].name);
    }
}

const char *sdp_get_payload_name ( sdp_payload_e payload )
{
    if (payload == SDP_PAYLOAD_UNSUPPORTED) {
        return (SDP_UNSUPPORTED);
    } else if (payload >= SDP_MAX_STRING_PAYLOAD_TYPES) {
        return ("Invalid payload type");
    } else {
        return (sdp_payload[payload].name);
    }
}

const char *sdp_get_t38_ratemgmt_name ( sdp_t38_ratemgmt_e rate )
{
    if (rate >= SDP_T38_MAX_RATES) {
        return ("Invalid rate");
    } else {
        return (sdp_t38_rate[rate].name);
    }
}

const char *sdp_get_t38_udpec_name ( sdp_t38_udpec_e udpec )
{
    if (udpec >= SDP_T38_MAX_UDPEC) {
        return ("Invalid udpec");
    } else {
        return (sdp_t38_udpec[udpec].name);
    }
}

const char *sdp_get_qos_strength_name ( sdp_qos_strength_e strength )
{
    if (strength >= SDP_MAX_QOS_STRENGTH) {
        return ("Invalid qos strength");
    } else {
        return (sdp_qos_strength[strength].name);
    }
}

const char *sdp_get_qos_direction_name ( sdp_qos_dir_e direction )
{
    if (direction >= SDP_MAX_QOS_DIR) {
        return ("Invalid qos direction");
    } else {
        return (sdp_qos_direction[direction].name);
    }
}

const char *sdp_get_qos_status_type_name ( sdp_qos_status_types_e status_type )
{
    if (status_type >= SDP_MAX_QOS_STATUS_TYPES) {
        return ("Invalid qos status type");
    } else {
        return (sdp_qos_status_type[status_type].name);
    }
}

const char *sdp_get_curr_type_name (sdp_curr_type_e curr_type )
{
    if (curr_type >= SDP_MAX_CURR_TYPES) {
        return ("Invalid curr type");
    } else {
        return (sdp_curr_type[curr_type].name);
    }
}

const char *sdp_get_des_type_name (sdp_des_type_e des_type )
{
    if (des_type >= SDP_MAX_DES_TYPES) {
        return ("Invalid des type");
    } else {
        return (sdp_des_type[des_type].name);
    }
}

const char *sdp_get_conf_type_name (sdp_conf_type_e conf_type )
{
    if (conf_type >= SDP_MAX_CONF_TYPES) {
        return ("Invalid conf type");
    } else {
        return (sdp_conf_type[conf_type].name);
    }
}

const char *sdp_get_silencesupp_pref_name (sdp_silencesupp_pref_e pref)
{
    if (pref >= SDP_MAX_SILENCESUPP_PREF) {
        return ("Invalid silencesupp pref");
    } else {
        return (sdp_silencesupp_pref[pref].name);
    }
}

const char *sdp_get_silencesupp_siduse_name (sdp_silencesupp_siduse_e siduse)
{
    if (siduse >= SDP_MAX_SILENCESUPP_SIDUSE) {
        return ("Invalid silencesupp siduse");
    } else {
        return (sdp_silencesupp_siduse[siduse].name);
    }
}

const char *sdp_get_mediadir_role_name (sdp_mediadir_role_e role)
{
    if (role >= SDP_MEDIADIR_ROLE_UNKNOWN) {
        return ("Invalid media direction role");
    } else {
        return (sdp_mediadir_role[role].name);
    }
}


const char *sdp_get_bw_modifier_name (sdp_bw_modifier_e bw_modifier_type)
{
    if (bw_modifier_type == SDP_BW_MODIFIER_UNSUPPORTED) {
        return (SDP_UNSUPPORTED);
    } else if (bw_modifier_type < SDP_BW_MODIFIER_AS ||
            bw_modifier_type >= SDP_MAX_BW_MODIFIER_VAL) {
        return ("Invalid bw modifier type");
    } else {
        return (sdp_bw_modifier_val[bw_modifier_type].name);
    }
}

const char *sdp_get_group_attr_name (sdp_group_attr_e group_attr_type)
{
    if (group_attr_type == SDP_GROUP_ATTR_UNSUPPORTED) {
        return (SDP_UNSUPPORTED);
    } else if (group_attr_type >= SDP_MAX_GROUP_ATTR_VAL) {
        return ("Invalid a=group: attribute type");
    } else {
        return (sdp_group_attr_val[group_attr_type].name);
    }
}

const char *sdp_get_ssrc_group_attr_name(
    sdp_ssrc_group_attr_e ssrc_group_attr_type) {
    if (ssrc_group_attr_type == SDP_SSRC_GROUP_ATTR_UNSUPPORTED) {
        return (SDP_UNSUPPORTED);
    } else if (ssrc_group_attr_type >= SDP_MAX_SSRC_GROUP_ATTR_VAL) {
        return ("Invalid a=ssrc-group: attribute type");
    } else {
        return (sdp_ssrc_group_attr_val[ssrc_group_attr_type].name);
    }
}

const char *sdp_get_src_filter_mode_name (sdp_src_filter_mode_e type)
{
    if (type >= SDP_MAX_FILTER_MODE) {
        return ("Invalid source filter mode");
    } else {
        return (sdp_src_filter_mode_val[type].name);
    }
}

const char *sdp_get_rtcp_unicast_mode_name (sdp_rtcp_unicast_mode_e type)
{
    if (type >= SDP_RTCP_MAX_UNICAST_MODE) {
        return ("Invalid rtcp unicast mode");
    } else {
        return (sdp_rtcp_unicast_mode_val[type].name);
    }
}

/* Function:    sdp_init_description
 * Description: Allocates a new SDP structure that can be used for either
 *              parsing or building an SDP description.  This routine
 *              saves the config pointer passed in the SDP structure so
 *              SDP will know how to parse/build based on the options defined.
 *              An SDP structure must be allocated before parsing or building
 *              since the handle must be passed to these routines.
 * Parameters:  config_p     The config handle returned by sdp_init_config
 * Returns:     A handle for a new SDP structure as a void ptr.
*/

sdp_t *sdp_init_description (sdp_conf_options_t *conf_p)
{
    int i;
    sdp_t *sdp_p;

    if (!conf_p) {
        return (NULL);
    }

    sdp_p = (sdp_t *)SDP_MALLOC(sizeof(sdp_t));
    if (sdp_p == NULL) {
        return (NULL);
    }

    sdp_p->conf_p             = conf_p;
    sdp_p->version            = SDP_CURRENT_VERSION;
    sdp_p->owner_name[0]      = '\0';
    sdp_p->owner_sessid[0]    = '\0';
    sdp_p->owner_version[0]   = '\0';
    sdp_p->owner_network_type = SDP_NT_INVALID;
    sdp_p->owner_addr_type    = SDP_AT_INVALID;
    sdp_p->owner_addr[0]      = '\0';
    sdp_p->sessname[0]        = '\0';
    sdp_p->sessinfo_found     = FALSE;
    sdp_p->uri_found          = FALSE;

    sdp_p->default_conn.nettype      = SDP_NT_INVALID;
    sdp_p->default_conn.addrtype     = SDP_AT_INVALID;
    sdp_p->default_conn.conn_addr[0] = '\0';
    sdp_p->default_conn.is_multicast = FALSE;
    sdp_p->default_conn.ttl          = 0;
    sdp_p->default_conn.num_of_addresses = 0;

    sdp_p->bw.bw_data_count   = 0;
    sdp_p->bw.bw_data_list    = NULL;

    sdp_p->timespec_p         = NULL;
    sdp_p->sess_attrs_p       = NULL;
    sdp_p->mca_p              = NULL;
    sdp_p->mca_count          = 0;

    /* Set default debug flags from application config. */
    for (i=0; i < SDP_MAX_DEBUG_TYPES; i++) {
        sdp_p->debug_flag[i] = conf_p->debug_flag[i];
    }

    return (sdp_p);
}


/* Function:    void sdp_debug(sdp_t *sdp_p, sdp_debug_e debug_type,
 *                             tinybool my_bool);
 * Description: Define the type of debug for this particular SDP structure.
 *              By default, each SDP description has the settings that are
 *              set for the application.
 *              Valid debug types are ERRORS, WARNINGS, and TRACE.  Each
 *              debug type can be turned on/off individually.  The
 *              debug level can be redefined at any time.
 * Parameters: sdp_ptr    The SDP handle returned by sdp_init_description.
 *              debug_type Specifies the debug type being enabled/disabled.
 *              my_bool    Defines whether the debug should be enabled or not.
 * Returns: Nothing.
 */

void sdp_debug (sdp_t *sdp_p, sdp_debug_e debug_type, tinybool debug_flag)
{
    if (!sdp_p) {
        return;
    }

    if (debug_type < SDP_MAX_DEBUG_TYPES)  {
        sdp_p->debug_flag[debug_type] = debug_flag;
    }
}


/* Function:    void sdp_set_string_debug(sdp_t *sdp_p, char *debug_str)
 * Description: Define a string to be associated with all debug output
 *              for this SDP. The string will be copied into the SDP
 *              structure and so the library will not be dependent on
 *              the application's memory for this string.
 * Parameters:  sdp_p      The SDP handle returned by sdp_init_description.
 *              debug_str  Pointer to a string that should be printed out
 *                         with every debug msg.
 * Returns:     Nothing.
 */

void sdp_set_string_debug (sdp_t *sdp_p, const char *debug_str)
{
    if (!sdp_p) {
        return;
    }

    sstrncpy(sdp_p->debug_str, debug_str, sizeof(sdp_p->debug_str));
}


/* Function:    sdp_validate_sdp
 * Description: Validate an SDP structure.
 * Parameters:  sdp_p    The SDP handle of the struct to validate.
 * Returns:     A result value indicating if the validation was successful.
 *              If not, what type of error was encountered.
 */

sdp_result_e sdp_validate_sdp (sdp_t *sdp_p)
{
    int i;
    uint16_t num_media_levels;

    /* Need to validate c= info is specified at session level or
     * at all m= levels.
     */

    if (sdp_connection_valid((void *)sdp_p, SDP_SESSION_LEVEL) == FALSE) {
        num_media_levels = sdp_get_num_media_lines((void *)sdp_p);
        for (i=1; i <= num_media_levels; i++) {
            if (sdp_connection_valid((void *)sdp_p, (unsigned short)i) == FALSE) {
                sdp_parse_error(sdp_p,
                    "%s c= connection line not specified for "
                    "every media level, validation failed.",
                    sdp_p->debug_str);
                return (SDP_FAILURE);
            }
        }
    }

    /* Validate required lines were specified */
    if ((sdp_owner_valid((void *)sdp_p) == FALSE) &&
        (sdp_p->conf_p->owner_reqd == TRUE)) {
        sdp_parse_error(sdp_p,
            "%s o= owner line not specified, validation failed.",
            sdp_p->debug_str);
        return (SDP_FAILURE);
    }

    if ((sdp_session_name_valid((void *)sdp_p) == FALSE) &&
        (sdp_p->conf_p->session_name_reqd == TRUE)) {
        sdp_parse_error(sdp_p,
            "%s s= session name line not specified, validation failed.",
            sdp_p->debug_str);
        return (SDP_FAILURE);
    }

    if ((sdp_timespec_valid((void *)sdp_p) == FALSE) &&
        (sdp_p->conf_p->timespec_reqd == TRUE)) {
        sdp_parse_error(sdp_p,
            "%s t= timespec line not specified, validation failed.",
            sdp_p->debug_str);
        return (SDP_FAILURE);
    }

    return (SDP_SUCCESS);
}

/* Function:    sdp_parse
 * Description: Parse an SDP description in the specified buffer.
 * Parameters:  sdp_p    The SDP handle returned by sdp_init_description
 *              bufp     Pointer to the buffer containing the SDP
 *                       description to parse.
 *              len      The length of the buffer.
 * Returns:     A result value indicating if the parse was successful and
 *              if not, what type of error was encountered.  The
 *              information from the parse is stored in the sdp_p structure.
 */

sdp_result_e sdp_parse (sdp_t *sdp_p, const char *buf, size_t len)
{
    uint8_t           i;
    uint16_t          cur_level = SDP_SESSION_LEVEL;
    const char  *ptr;
    const char  *next_ptr = NULL;
    char        *line_end;
    sdp_token_e  last_token = SDP_TOKEN_V;
    sdp_result_e result = SDP_SUCCESS;
    tinybool     parse_done = FALSE;
    tinybool     end_found = FALSE;
    tinybool     first_line = TRUE;
    tinybool     unrec_token = FALSE;
    const char   **bufp = &buf;

    if (!sdp_p) {
        return (SDP_INVALID_SDP_PTR);
    }

    if ((bufp == NULL) || (*bufp == NULL)) {
        return (SDP_NULL_BUF_PTR);
    }

    if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
        SDP_PRINT("%s Trace SDP Parse:", sdp_p->debug_str);
    }

    next_ptr = *bufp;
    sdp_p->conf_p->num_parses++;

    /* Initialize the last valid capability instance to zero.  Used
     * to help in parsing X-cpar attrs. */

    sdp_p->cap_valid = FALSE;
    sdp_p->last_cap_inst = 0;

    sdp_p->parse_line = 0;

    /* We want to try to find the end of the SDP description, even if
     * we find a parsing error.
     */

    while (!end_found) {
        /* If the last char of this line goes beyond the end of the buffer,
         * we don't parse it.
         */

        ptr = next_ptr;
        sdp_p->parse_line++;
        line_end = sdp_findchar(ptr, "\n");
        if ((line_end >= (*bufp + len)) ||
           (*line_end == '\0')) {
            /* As this does not update the result value the SDP up to this point
             * is still accept as valid. So encountering this is not treated as
             * an error.
             */

            sdp_parse_error(sdp_p,
                "%s End of line beyond end of buffer.",
                sdp_p->debug_str);
            SDPLogError(logTag, "SDP: Invalid SDP, no \\n (len %u): %*s",
                        (unsigned)len, (int)len, *bufp);
            end_found = TRUE;
            break;
        }

        /* Print the line if we're tracing. */
        if ((parse_done == FALSE) &&
          (sdp_p->debug_flag[SDP_DEBUG_TRACE])) {
            SDP_PRINT("%s ", sdp_p->debug_str);

            SDP_PRINT("%*s", (int)(line_end - ptr), ptr);

        }

        /* Find out which token this line has, if any. */
        for (i=0; i < SDP_MAX_TOKENS; i++) {
            if (strncmp(ptr, sdp_token[i].name, SDP_TOKEN_LEN) == 0) {
                break;
            }
        }
        if (i == SDP_MAX_TOKENS) {
            /* See if the second char on the next line is an '=' char.
             * If so, we note this as an unrecognized token line. */

            if (ptr[1] == '=') {
                unrec_token = TRUE;
            }
            if (first_line == TRUE) {
                sdp_parse_error(sdp_p,
                    "%s Attempt to parse text not recognized as "
                    "SDP text, parse fails.", sdp_p->debug_str);
                    /* If we haven't already printed out the line we
                     * were trying to parse, do it now.
                     */

                if (!sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
                    SDP_PRINT("%s ", sdp_p->debug_str);
                    SDP_PRINT("%*s", (int)(line_end - ptr), ptr);
                }
                sdp_p->conf_p->num_not_sdp_desc++;
                return (SDP_NOT_SDP_DESCRIPTION);
            } else {
                end_found = TRUE;
                break;
            }
        }

        /* This is the beginning of a new SDP description. */
        if ((first_line != TRUE) && (i == SDP_TOKEN_V)) {
            end_found = TRUE;
            break;
        }

        /* Advance the next ptr to one char beyond the end of the line. */
        next_ptr = line_end + 1;
        if (next_ptr >= (*bufp + len)) {
            end_found = TRUE;
        }

        /* If we've finished parsing and are just looking for the end of
         * the SDP description, we don't need to do anything else here.
         */

        if (parse_done == TRUE) {
            continue;
        }

        /* Only certain tokens are valid at the media level. */
        if (cur_level != SDP_SESSION_LEVEL) {
            if ((i != SDP_TOKEN_I) && (i != SDP_TOKEN_C) &&
                (i != SDP_TOKEN_B) && (i != SDP_TOKEN_K) &&
                (i != SDP_TOKEN_A) && (i != SDP_TOKEN_M)) {
                sdp_p->conf_p->num_invalid_token_order++;
                sdp_parse_error(sdp_p,
                    "%s Warning: Invalid token %s found at media level",
                    sdp_p->debug_str, sdp_token[i].name);
                continue;
            }
        }

        /* Verify the token ordering. */
        if (first_line == TRUE) {
            if (i != SDP_TOKEN_V) {
                if (sdp_p->conf_p->version_reqd == TRUE) {
                    sdp_parse_error(sdp_p,
                        "%s First line not v=, parse fails",
                        sdp_p->debug_str);
                    sdp_p->conf_p->num_invalid_token_order++;
                    result = SDP_INVALID_TOKEN_ORDERING;
                    parse_done = TRUE;
                } else {
                    last_token = (sdp_token_e)i;
                }
            } else {
                last_token = (sdp_token_e)i;
            }
            first_line = FALSE;
        } else {
            if (i < last_token) {
                sdp_p->conf_p->num_invalid_token_order++;
                sdp_parse_error(sdp_p,
                    "%s Warning: Invalid token ordering detected, "
                    "token %s found after token %s", sdp_p->debug_str,
                    sdp_token[i].name, sdp_token[last_token].name);
            }
        }

        /* Finally parse the line. */
        ptr += SDP_TOKEN_LEN;
        result = sdp_token[i].parse_func(sdp_p, cur_level, (const char *)ptr);
        last_token = (sdp_token_e)i;
        if (last_token == SDP_TOKEN_M) {
            if (cur_level == SDP_SESSION_LEVEL) {
                cur_level = 1;
            } else {
                cur_level++;
            }
            /* The token ordering can start again at i= */
            last_token = (sdp_token_e)(SDP_TOKEN_I - 1);
        }
        if (result != SDP_SUCCESS) {
            parse_done = TRUE;
        }

        /* Skip the new line char at the end of this line and see if
         * this is the end of the buffer.
         */

        if ((line_end + 1) == (*bufp + len)) {
            end_found = TRUE;
        }
    }

    /* If we found no valid lines, return an error. */
    if (first_line == TRUE) {
        sdp_p->conf_p->num_not_sdp_desc++;
        return (SDP_NOT_SDP_DESCRIPTION);
    }

    /* If no errors were found yet, validate the overall sdp. */
    if (result == SDP_SUCCESS) {
        result = sdp_validate_sdp(sdp_p);
    }
    /* Return the pointer where we left off. */
    *bufp = next_ptr;
    /* If the SDP is valid, but the next line following was an
     * unrecognized <token>= line, indicate this on the return. */

    if ((result == SDP_SUCCESS) && (unrec_token == TRUE)) {
        return (SDP_UNRECOGNIZED_TOKEN);
    } else {
        return (result);
    }
}


/* Function:    sdp_build
 * Description: Build an SDP description in the specified buffer based
 *              on the information in the given SDP structure.
 * Parameters:  sdp_p    The SDP handle returned by sdp_init_description
 *              fs A flex_string where the SDP description should be built.
 * Returns:     A result value indicating if the build was successful and
 *              if not, what type of error was encountered - e.g.,
 *              description was too long for the given buffer.
 */

sdp_result_e sdp_build (sdp_t *sdp_p, flex_string *fs)
{
    int i, j;
    sdp_result_e        result = SDP_SUCCESS;

    if (!sdp_p) {
        return (SDP_INVALID_SDP_PTR);
    }

    if (!fs) {
        return (SDP_NULL_BUF_PTR);
    }

    if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
        SDP_PRINT("%s Trace SDP Build:", sdp_p->debug_str);
    }

    sdp_p->conf_p->num_builds++;

    for (i=0; ((i < SDP_TOKEN_M) &&
               (result == SDP_SUCCESS)); i++) {
        result = sdp_token[i].build_func(sdp_p, SDP_SESSION_LEVEL, fs);
        /* ok not to check buffer space (yet) as the if() checks it */
    }
    /* If the session level was ok, build the media lines. */
    if (result == SDP_SUCCESS) {
        for (i=1; ((i <= sdp_p->mca_count) &&
                   (result == SDP_SUCCESS)); i++) {
            result = sdp_token[SDP_TOKEN_M].build_func(sdp_p, (uint16_t)i, fs);

            /* ok not to check buffer space (yet) as the for() checks it */
            for (j=SDP_TOKEN_I;
                 ((j < SDP_TOKEN_M) && (result == SDP_SUCCESS));
                 j++) {
                if ((j == SDP_TOKEN_U) || (j == SDP_TOKEN_E) ||
                    (j == SDP_TOKEN_P) || (j == SDP_TOKEN_T) ||
                    (j == SDP_TOKEN_R) || (j == SDP_TOKEN_Z)) {
                    /* These tokens not valid at media level. */
                    continue;
                }
                result = sdp_token[j].build_func(sdp_p, (uint16_t)i, fs);
                /* ok not to check buffer space (yet) as the for() checks it */
            }
        }
    }

    return (result);
}

/* Function:    sdp_free_description
 * Description: Free an SDP description and all memory associated with it.
 * Parameters:  sdp_p  The SDP handle returned by sdp_init_description
 * Returns:     A result value indicating if the free was successful and
 *              if not, what type of error was encountered - e.g., sdp_p
 *              was invalid and didn't point to an SDP structure.
*/

sdp_result_e sdp_free_description (sdp_t *sdp_p)
{
    sdp_timespec_t  *time_p, *next_time_p;
    sdp_attr_t      *attr_p, *next_attr_p;
    sdp_mca_t       *mca_p, *next_mca_p;
    sdp_bw_t        *bw_p;
    sdp_bw_data_t   *bw_data_p;

    if (!sdp_p) {
        return (SDP_INVALID_SDP_PTR);
    }

    /* Free the config structure */
    sdp_free_config(sdp_p->conf_p);

    /* Free any timespec structures - should be only one since
     * this is all we currently support.
     */

    time_p = sdp_p->timespec_p;
    while (time_p != NULL) {
        next_time_p = time_p->next_p;
        SDP_FREE(time_p);
        time_p = next_time_p;
    }

    bw_p = &(sdp_p->bw);
    bw_data_p = bw_p->bw_data_list;
    while (bw_data_p != NULL) {
        bw_p->bw_data_list = bw_data_p->next_p;
        SDP_FREE(bw_data_p);
        bw_data_p = bw_p->bw_data_list;
    }

    /* Free any session attr structures */
    attr_p = sdp_p->sess_attrs_p;
    while (attr_p != NULL) {
        next_attr_p = attr_p->next_p;
        sdp_free_attr(attr_p);
        attr_p = next_attr_p;
    }

    /* Free any mca structures */
    mca_p = sdp_p->mca_p;
    while (mca_p != NULL) {
        next_mca_p = mca_p->next_p;

        /* Free any media attr structures */
        attr_p = mca_p->media_attrs_p;
        while (attr_p != NULL) {
            next_attr_p = attr_p->next_p;
            sdp_free_attr(attr_p);
            attr_p = next_attr_p;
        }

        /* Free the media profiles struct if allocated. */
        if (mca_p->media_profiles_p != NULL) {
            SDP_FREE(mca_p->media_profiles_p);
        }

        bw_p = &(mca_p->bw);
        bw_data_p = bw_p->bw_data_list;
        while (bw_data_p != NULL) {
            bw_p->bw_data_list = bw_data_p->next_p;
            SDP_FREE(bw_data_p);
            bw_data_p = bw_p->bw_data_list;
        }

        SDP_FREE(mca_p);
        mca_p = next_mca_p;
    }

    SDP_FREE(sdp_p);

    return (SDP_SUCCESS);
}

/*
 * sdp_parse_error
 * Send SDP parsing errors to log and up to peerconnection
 */

void sdp_parse_error(sdp_t* sdp, const char *format, ...) {
    flex_string fs;
    va_list ap;

    flex_string_init(&fs);

    va_start(ap, format);
    flex_string_vsprintf(&fs, format, ap);
    va_end(ap);

    SDPLogError("SDP Parse""SDP Parse Error %s, line %u", fs.buffer,
                sdp->parse_line);

    if (sdp->conf_p->error_handler) {
        sdp->conf_p->error_handler(sdp->conf_p->error_handler_context,
                                   sdp->parse_line,
                                   fs.buffer);
    }

    flex_string_free(&fs);
}

Messung V0.5
C=96 H=92 G=93

¤ Dauer der Verarbeitung: 0.19 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.