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 259 kB image not shown  

Quelle  sdp_attr_access.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_attr_access";

/* Attribute access routines are all defined by the following parameters.
 *
 * sdp_p     The SDP handle returned by sdp_init_description.
 * level       The level the attribute is defined.  Can be either
 *             SDP_SESSION_LEVEL or 0-n specifying a media line level.
 * inst_num    The instance number of the attribute.  Multiple instances
 *             of a particular attribute may exist at each level and so
 *             the inst_num determines the particular attribute at that
 *             level that should be accessed.  Note that this is the
 *             instance number of the specified type of attribute, not the
 *             overall attribute number at the level.  Also note that the
 *             instance number is 1-based.  For example:
 *             v=0
 *             o=mhandley 2890844526 2890842807 IN IP4 126.16.64.4
 *             s=SDP Seminar
 *             c=IN IP4 10.1.0.2
 *             t=0 0
 *             m=audio 1234 RTP/AVP 0 101 102
 *             a=foo 1
 *             a=foo 2
 *             a=bar 1   # This is instance 1 of attribute bar.
 *             a=foo 3   # This is instance 3 of attribute foo.
 * cap_num     Almost all of the attributes may be defined as X-cpar
 *             parameters (with the exception of X-sqn, X-cap, and X-cpar).
 *             If the cap_num is set to zero, then the attribute is not
 *             an X-cpar parameter attribute.  If the cap_num is any other
 *             value, it specifies the capability number that the X-cpar
 *             attribute is specified for.
 */


/* Attribute handling:
 *
 * There are two basic types of attributes handled by the SDP library,
 * those defined by a= token lines, and those embedded with a=X-cpar lines.
 * The handling for each of these is described here.
 *
 * Simple (non X-cpar attributes):
 *
 * Attributes not embedded in a=X-cpar lines are referenced by level and
 * instance number.  For these attributes the capability number is always
 * set to zero.
 *
 * An application will typically process these attributes in one of two ways.
 * With the first method, the application can determine the total number
 * of attributes defined at a given level and process them one at a time.
 * For each attribute, the application will query the library to find out
 * what type of attribute it is and which instance within that type. The
 * application can then process this particular attribute referencing it
 * by level and instance number.
 *
 * A second method of processing attributes is for applications to determine
 * each type of attribute they are interested in, query the SDP library to
 * find out how many of that type of attribute exist at a given level, and
 * process each one at a time.
 *
 * X-cpar attribute processing:
 *
 * X-cpar attributes can contain embedded attributes.  They are associated
 * with X-cap attribute lines.  An example of X-cap and X-cpar attributes
 * found in an SDP is as follows:
 *
 * v=0
 * o=- 25678 753849 IN IP4 128.96.41.1
 * s=-
 * t=0 0
 * c=IN IP4 10.1.0.2
 * m=audio 3456 RTP/AVP 18 96
 * a=rtpmap:96 telephone-event/8000
 * a=fmtp:96 0-15,32-35
 * a=X-sqn: 0
 * a=X-cap: 1 audio RTP/AVP 0 18 96 97
 * a=X-cpar: a=fmtp:96 0-16,32-35
 * a=X-cpar: a=rtpmap:97 X-NSE/8000
 * a=X-cpar: a=fmtp:97 195-197
 * a=X-cap: 5 image udptl t38
 * a=X-cap: 6 application udp X-tmr
 * a=X-cap: 7 audio RTP/AVP 100 101
 * a=X-cpar: a=rtpmap:100 g.711/8000
 * a=X-cpar: a=rtpmap:101 g.729/8000
 *
 * X-cap attributes can be defined at the SESSION_LEVEL or any media level.
 * An X-cap attr is defined by the level and instance number just like
 * other attributes.  In the example above, X-cap attrs are defined at
 * media level 1 and there are four instances at that level.
 *
 * The X-cpar attributes can also be referenced by level and instance number.
 * However, the embedded attribute within an X-cpar attribute must be
 * referenced by level, instance number, and capability number.  This is
 * because the X-cpar attribute is associated with a particular X-cap/
 * capability.
 * For all attributes that are not embedded within an X-cpar attribute, the
 * cap_num should be referenced as zero.  But for X-cpar attributes, the
 * cap_num is specified to be one of the capability numbers of the previous
 * X-cap line.  The number of capabilities specified in an X-cap line is
 * equal to the number of payloads.  Thus, in this example, the first X-cap
 * attr instance specifies capabilities 1-4, the second specifies capability
 * 5, the third capability 6, and the fourth capabilities 7-8.
 *
 * X-cpar attributes can be processed with methods similar to the two
 * previously mentioned.  For each X-cap attribute, the application can
 * use one of two methods to process the X-cpar attributes.  First, it
 * can query the total number of X-cpar attributes associated with a
 * given X-cap attribute.  The X-cap attribute is here defined by a level
 * and a capability number.  In the example above, the total number of
 * attributes defined is as follows:
 *  level 1, cap_num 1 - total attrs: 3
 *  level 1, cap_num 5 - total attrs: 0
 *  level 1, cap_num 6 - total attrs: 0
 *  level 1, cap_num 7 - total attrs: 2
 *
 * Note that if the application queried the number of attributes for
 * cap_num 2, 3, or 4, it would also return 3 attrs, and for cap_num
 * 8 the library would return 2.
 *
 * Once the application determines the total number of attributes for
 * that capability, it can again query the embedded attribute type and
 * instance.  For example, sdp_get_attr_type would return the following:
 *  level 1, cap_num 1, attr 1 -> attr type fmtp, instance 1
 *  level 1, cap_num 1, attr 2 -> attr type rtpmap, instance 1
 *  level 1, cap_num 1, attr 3 -> attr type fmtp, instance 2
 *  level 1, cap_num 7, attr 1 -> attr type rtpmap, instance 1
 *  level 1, cap_num 7, attr 2 -> attr type rtpmap, instance 2
 *
 * The individual embedded attributes can then be accessed by level,
 * cap_num, and instance number.
 *
 * With the second method for handling X-cpar attributes, the application
 * determines the types of attributes it is interested in.  It can then
 * query the SDP library to determine the number of attributes of that
 * type found for that level and cap_num, and then process each one at
 * a time.  e.g., calling sdp_attr_num_instances would give:
 *  level 1, cap_num 1, attr_type fmtp -> two instances
 *  level 1, cap_num 1, attr_type rtpmap -> one instance
 *  level 1, cap_num 7, attr_type fmtp -> zero instances
 *  level 1, cap_num 7, attr_type rtpmap -> two instances
 */



/* Function:    sdp_add_new_attr
 * Description: Add a new attribute of the specified type at the given
 *              level and capability level or base attribute if cap_num
 *              is zero.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              attr_type   The type of attribute to add.
 *              inst_num    Pointer to a uint16_t in which to return the instance
 *                          number of the newly added attribute.
 * Returns:     SDP_SUCCESS            Attribute was added successfully.
 *              SDP_NO_RESOURCE        No memory avail for new attribute.
 *              SDP_INVALID_PARAMETER  Specified media line is not defined.
 */

sdp_result_e sdp_add_new_attr (sdp_t *sdp_p, uint16_t level, uint8_t cap_num,
                               sdp_attr_e attr_type, uint16_t *inst_num)
{
    uint16_t          i;
    sdp_mca_t   *mca_p;
    sdp_mca_t   *cap_p;
    sdp_attr_t  *attr_p;
    sdp_attr_t  *new_attr_p;
    sdp_attr_t  *prev_attr_p=NULL;
    sdp_fmtp_t  *fmtp_p;
    sdp_comediadir_t  *comediadir_p;

    *inst_num = 0;

    if ((cap_num != 0) &&
        ((attr_type == SDP_ATTR_X_CAP) || (attr_type == SDP_ATTR_X_CPAR) ||
         (attr_type == SDP_ATTR_X_SQN) || (attr_type == SDP_ATTR_CDSC) ||
         (attr_type == SDP_ATTR_CPAR) || (attr_type == SDP_ATTR_SQN))) {
        if (sdp_p->debug_flag[SDP_DEBUG_WARNINGS]) {
            SDPLogDebug(logTag, "%s Warning: Invalid attribute type for X-cpar/cdsc "
                     "parameter.", sdp_p->debug_str);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (SDP_INVALID_PARAMETER);
    }

    /* Some attributes are valid only under media level */
    if (level == SDP_SESSION_LEVEL) {
        switch (attr_type) {
            case SDP_ATTR_RTCP:
            case SDP_ATTR_LABEL:
                return (SDP_INVALID_MEDIA_LEVEL);

            default:
                break;
        }
    }

    new_attr_p = (sdp_attr_t *)SDP_MALLOC(sizeof(sdp_attr_t));
    if (new_attr_p == NULL) {
        sdp_p->conf_p->num_no_resource++;
        return (SDP_NO_RESOURCE);
    }

    new_attr_p->type = attr_type;
    new_attr_p->next_p = NULL;

    /* Initialize the new attribute structure */
    if ((new_attr_p->type == SDP_ATTR_X_CAP) ||
        (new_attr_p->type == SDP_ATTR_CDSC)) {
        new_attr_p->attr.cap_p = (sdp_mca_t *)SDP_MALLOC(sizeof(sdp_mca_t));
        if (new_attr_p->attr.cap_p == NULL) {
            sdp_free_attr(new_attr_p);
            sdp_p->conf_p->num_no_resource++;
            return (SDP_NO_RESOURCE);
        }
    } else if (new_attr_p->type == SDP_ATTR_FMTP) {
        fmtp_p = &(new_attr_p->attr.fmtp);
        fmtp_p->fmtp_format = SDP_FMTP_UNKNOWN_TYPE;
        // set to invalid value
        fmtp_p->packetization_mode = SDP_INVALID_PACKETIZATION_MODE_VALUE;
        fmtp_p->level_asymmetry_allowed = SDP_INVALID_LEVEL_ASYMMETRY_ALLOWED_VALUE;
        fmtp_p->annexb_required = FALSE;
        fmtp_p->annexa_required = FALSE;
        fmtp_p->maxval = 0;
        fmtp_p->bitrate = 0;
        fmtp_p->cif = 0;
        fmtp_p->qcif = 0;
        fmtp_p->profile = SDP_INVALID_VALUE;
        fmtp_p->level = SDP_INVALID_VALUE;
        fmtp_p->parameter_add = SDP_FMTP_UNUSED;
        fmtp_p->usedtx = SDP_FMTP_UNUSED;
        fmtp_p->stereo = SDP_FMTP_UNUSED;
        fmtp_p->useinbandfec = SDP_FMTP_UNUSED;
        fmtp_p->cbr = SDP_FMTP_UNUSED;
        for (i=0; i < SDP_NE_NUM_BMAP_WORDS; i++) {
            fmtp_p->bmap[i] = 0;
        }
    } else if ((new_attr_p->type == SDP_ATTR_RTPMAP) ||
               (new_attr_p->type == SDP_ATTR_SPRTMAP)) {
        new_attr_p->attr.transport_map.num_chan = 1;
    } else if (new_attr_p->type == SDP_ATTR_DIRECTION) {
        comediadir_p = &(new_attr_p->attr.comediadir);
        comediadir_p->role = SDP_MEDIADIR_ROLE_PASSIVE;
        comediadir_p->conn_info_present = FALSE;
    } else if (new_attr_p->type == SDP_ATTR_MPTIME) {
        sdp_mptime_t *mptime = &(new_attr_p->attr.mptime);
        mptime->num_intervals = 0;
    }

    if (cap_num == 0) {
        /* Add a new attribute. */
        if (level == SDP_SESSION_LEVEL) {
            if (sdp_p->sess_attrs_p == NULL) {
                sdp_p->sess_attrs_p = new_attr_p;
            } else {
                for (attr_p = sdp_p->sess_attrs_p;
                     attr_p != NULL;
                     prev_attr_p = attr_p, attr_p = attr_p->next_p) {
                    /* Count the num instances of this type. */
                    if (attr_p->type == attr_type) {
                        (*inst_num)++;
                    }
                }
                prev_attr_p->next_p = new_attr_p;
            }
        } else {
            mca_p = sdp_find_media_level(sdp_p, level);
            if (mca_p == NULL) {
                sdp_free_attr(new_attr_p);
                sdp_p->conf_p->num_invalid_param++;
                return (SDP_INVALID_PARAMETER);
            }
            if (mca_p->media_attrs_p == NULL) {
                mca_p->media_attrs_p = new_attr_p;
            } else {
                for (attr_p = mca_p->media_attrs_p;
                     attr_p != NULL;
                     prev_attr_p = attr_p, attr_p = attr_p->next_p) {
                    /* Count the num instances of this type. */
                    if (attr_p->type == attr_type) {
                        (*inst_num)++;
                    }
                }
                prev_attr_p->next_p = new_attr_p;
            }
        }
    } else {
        /* Add a new capability attribute - find the capability attr. */
        attr_p = sdp_find_capability(sdp_p, level, cap_num);
        if (attr_p == NULL) {
            sdp_free_attr(new_attr_p);
            sdp_p->conf_p->num_invalid_param++;
            return (SDP_INVALID_PARAMETER);
        }
        cap_p = attr_p->attr.cap_p;
        if (cap_p->media_attrs_p == NULL) {
            cap_p->media_attrs_p = new_attr_p;
        } else {
            for (attr_p = cap_p->media_attrs_p;
                 attr_p != NULL;
                 prev_attr_p = attr_p, attr_p = attr_p->next_p) {
                /* Count the num instances of this type. */
                if (attr_p->type == attr_type) {
                    (*inst_num)++;
                }
            }
            prev_attr_p->next_p = new_attr_p;
        }
    }

    /* Increment the instance num for the attr just added. */
    (*inst_num)++;
    return (SDP_SUCCESS);
}

/* Function:    sdp_attr_num_instances
 * Description: Get the number of attributes of the specified type at
 *              the given level and capability level.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              attr_type   The type of attribute to add.
 *              num_attr_inst Pointer to a uint16_t in which to return the
 *                          number of attributes.
 * Returns:     SDP_SUCCESS            Attribute was added successfully.
 *              SDP_INVALID_PARAMETER  Specified media line is not defined.
 */

sdp_result_e sdp_attr_num_instances (sdp_t *sdp_p, uint16_t level, uint8_t cap_num,
                                     sdp_attr_e attr_type, uint16_t *num_attr_inst)
{
    sdp_attr_t  *attr_p;
    sdp_result_e rc;
    static char  fname[] = "attr_num_instances";

    *num_attr_inst = 0;

    rc = sdp_find_attr_list(sdp_p, level, cap_num, &attr_p, fname);
    if (rc == SDP_SUCCESS) {
        /* Found the attr list. Count the number of attrs of the given
         * type at this level. */

        for (; attr_p != NULL; attr_p = attr_p->next_p) {
            if (attr_p->type == attr_type) {
                (*num_attr_inst)++;
            }
        }

    }

    return (rc);
}

/* Forward declaration for use in sdp_free_attr */
static boolean sdp_attr_is_long_string(sdp_attr_e attr_type);


/* Internal routine to free the memory associated with an attribute.
 * Certain attributes allocate additional memory.  Free this and then
 * free the attribute itself.
 * Note that this routine may be called at any point (i.e., may be
 * called due to a failure case) and so the additional memory
 * associated with an attribute may or may not have been already
 * allocated. This routine should check this carefully.
 */

void sdp_free_attr (sdp_attr_t *attr_p)
{
    sdp_mca_t   *cap_p;
    sdp_attr_t  *cpar_p;
    sdp_attr_t  *next_cpar_p;
    int          i;

    /* If this is an X-cap/cdsc attr, free the cap_p structure and
     * all X-cpar/cpar attributes. */

    if ((attr_p->type == SDP_ATTR_X_CAP) ||
        (attr_p->type == SDP_ATTR_CDSC)) {
        cap_p = attr_p->attr.cap_p;
        if (cap_p != NULL) {
            for (cpar_p = cap_p->media_attrs_p; cpar_p != NULL;) {
                next_cpar_p = cpar_p->next_p;
                sdp_free_attr(cpar_p);
                cpar_p = next_cpar_p;
            }
            SDP_FREE(cap_p);
        }
    } else if ((attr_p->type == SDP_ATTR_SDESCRIPTIONS) ||
              (attr_p->type == SDP_ATTR_SRTP_CONTEXT)) {
        SDP_FREE(attr_p->attr.srtp_context.session_parameters);
    } else if (sdp_attr_is_long_string(attr_p->type)) {
        SDP_FREE(attr_p->attr.stringp);
    }

    if (attr_p->type == SDP_ATTR_GROUP) {
        for (i = 0; i < attr_p->attr.stream_data.num_group_id; i++) {
            SDP_FREE(attr_p->attr.stream_data.group_ids[i]);
        }
    } else if (attr_p->type == SDP_ATTR_MSID_SEMANTIC) {
        for (i = 0; i < SDP_MAX_MEDIA_STREAMS; ++i) {
            SDP_FREE(attr_p->attr.msid_semantic.msids[i]);
        }
    }

    /* Now free the actual attribute memory. */
    SDP_FREE(attr_p);

}


/* Function:    sdp_find_attr_list
 * Description: Find the attribute list for the specified level and cap_num.
 *              Note: This is not an API for the application but an internal
 *              routine used by the SDP library.
 * Parameters:  sdp_p       Pointer to the SDP to search.
 *              level       The level to check for the attribute list.
 *              cap_num     The capability number associated with the
 *                          attribute list.  If none, should be zero.
 *              attr_p      Pointer to the attr list pointer. Will be
 *                          filled in on return if successful.
 *              fname       String function name calling this routine.
 *                          Use for printing debug.
 * Returns:     SDP_SUCCESS
 *              SDP_INVALID_MEDIA_LEVEL
 *              SDP_INVALID_CAPABILITY
 *              SDP_FAILURE
 */

sdp_result_e sdp_find_attr_list (sdp_t *sdp_p, uint16_t level, uint8_t cap_num,
                                 sdp_attr_t **attr_p, char *fname)
{
    sdp_mca_t   *mca_p;
    sdp_mca_t   *cap_p;
    sdp_attr_t  *cap_attr_p;

    /* Initialize the attr pointer. */
    *attr_p = NULL;

    if (cap_num == 0) {
        /* Find attribute list at the specified level. */
        if (level == SDP_SESSION_LEVEL) {
            *attr_p = sdp_p->sess_attrs_p;
        } else {
            mca_p = sdp_find_media_level(sdp_p, level);
            if (mca_p == NULL) {
                sdp_p->conf_p->num_invalid_param++;
                return (SDP_INVALID_PARAMETER);
            }
            *attr_p = mca_p->media_attrs_p;
        }
    } else {
        /* Find the attr list for the capability specified. */
        cap_attr_p = sdp_find_capability(sdp_p, level, cap_num);
        if (cap_attr_p == NULL) {
            if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
                SDPLogError(logTag, "%s %s, invalid capability %u at "
                          "level %u specified.", sdp_p->debug_str, fname,
                          (unsigned)cap_num, (unsigned)level);
            }
            sdp_p->conf_p->num_invalid_param++;
            return (SDP_INVALID_CAPABILITY);
        }
        cap_p = cap_attr_p->attr.cap_p;
        *attr_p = cap_p->media_attrs_p;
    }

    return (SDP_SUCCESS);
}

/* Find fmtp inst_num with correct payload value or -1 for failure */
int sdp_find_fmtp_inst (sdp_t *sdp_p, uint16_t level, uint16_t payload_num)
{
    uint16_t          attr_count=0;
    sdp_mca_t   *mca_p;
    sdp_attr_t  *attr_p;

    /* Attr is at a media level */
    mca_p = sdp_find_media_level(sdp_p, level);
    if (mca_p == NULL) {
      return (-1);
    }
    for (attr_p = mca_p->media_attrs_p; attr_p != NULL;
         attr_p = attr_p->next_p) {
      if (attr_p->type == SDP_ATTR_FMTP) {
        attr_count++;
        if (attr_p->attr.fmtp.payload_num == payload_num) {
          return (attr_count);
        }
      }
    }

    return (-1);

}

/* Function:    sdp_find_attr
 * Description: Find the specified attribute in an SDP structure.
 *              Note: This is not an API for the application but an internal
 *              routine used by the SDP library.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              attr_type   The type of attribute to find.
 *              inst_num    The instance num of the attribute to find.
 *                          Range should be (1 - max num insts of this
 *                          particular type of attribute at this level).
 * Returns:     Pointer to the attribute or NULL if not found.
 */

sdp_attr_t *sdp_find_attr (sdp_t *sdp_p, uint16_t level, uint8_t cap_num,
                           sdp_attr_e attr_type, uint16_t inst_num)
{
    uint16_t          attr_count=0;
    sdp_mca_t   *mca_p;
    sdp_mca_t   *cap_p;
    sdp_attr_t  *attr_p;

    if (inst_num < 1) {
        return (NULL);
    }

    if (cap_num == 0) {
        if (level == SDP_SESSION_LEVEL) {
            for (attr_p = sdp_p->sess_attrs_p; attr_p != NULL;
                 attr_p = attr_p->next_p) {
                if (attr_p->type == attr_type) {
                    attr_count++;
                    if (attr_count == inst_num) {
                        return (attr_p);
                    }
                }
            }
        } else {  /* Attr is at a media level */
            mca_p = sdp_find_media_level(sdp_p, level);
            if (mca_p == NULL) {
                return (NULL);
            }
            for (attr_p = mca_p->media_attrs_p; attr_p != NULL;
                 attr_p = attr_p->next_p) {
                if (attr_p->type == attr_type) {
                    attr_count++;
                    if (attr_count == inst_num) {
                        return (attr_p);
                    }
                }
            }
        }  /* Attr is at a media level */
    } else {
        /* Attr is a capability X-cpar/cpar attribute. */
        attr_p = sdp_find_capability(sdp_p, level, cap_num);
        if (attr_p == NULL) {
            return (NULL);
        }
        cap_p = attr_p->attr.cap_p;
        /* Now find the specific attribute. */
        for (attr_p = cap_p->media_attrs_p; attr_p != NULL;
             attr_p = attr_p->next_p) {
            if (attr_p->type == attr_type) {
                attr_count++;
                if (attr_count == inst_num) {
                    return (attr_p);
                }
            }
        }
    }

    return (NULL);
}

/* Function:    sdp_find_capability
 * Description: Find the specified capability attribute in an SDP structure.
 *              Note: This is not an API for the application but an internal
 *              routine used by the SDP library.
 * Parameters:  sdp_p       The SDP handle.
 *              level       The level to check for the capability.
 *              cap_num     The capability number to locate.
 * Returns:     Pointer to the capability attribute or NULL if not found.
 */

sdp_attr_t *sdp_find_capability (sdp_t *sdp_p, uint16_t level, uint8_t cap_num)
{
    uint8_t           cur_cap_num=0;
    sdp_mca_t   *mca_p;
    sdp_mca_t   *cap_p;
    sdp_attr_t  *attr_p;

    if (level == SDP_SESSION_LEVEL) {
        for (attr_p = sdp_p->sess_attrs_p; attr_p != NULL;
             attr_p = attr_p->next_p) {
            if ((attr_p->type == SDP_ATTR_X_CAP) ||
                (attr_p->type == SDP_ATTR_CDSC)) {
                cap_p = attr_p->attr.cap_p;
                cur_cap_num += cap_p->num_payloads;
                if (cap_num <= cur_cap_num) {
                    /* This is the right capability */
                    return (attr_p);
                }
            }
        }
    } else {  /* Capability is at a media level */
        mca_p = sdp_find_media_level(sdp_p, level);
        if (mca_p == NULL) {
            return (NULL);
        }
        for (attr_p = mca_p->media_attrs_p; attr_p != NULL;
             attr_p = attr_p->next_p) {
            if ((attr_p->type == SDP_ATTR_X_CAP) ||
                (attr_p->type == SDP_ATTR_CDSC)) {
                cap_p = attr_p->attr.cap_p;
                cur_cap_num += cap_p->num_payloads;
                if (cap_num <= cur_cap_num) {
                    /* This is the right capability */
                    return (attr_p);
                }
            }
        }
    }

    /* We didn't find the specified capability. */
    if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
        SDPLogError(logTag, "%s Unable to find specified capability (level %u, "
                  "cap_num %u).", sdp_p->debug_str, (unsigned)level, (unsigned)cap_num);
    }
    sdp_p->conf_p->num_invalid_param++;
    return (NULL);
}

/* Function:    sdp_attr_valid(sdp_t *sdp_p)
 * Description: Returns true or false depending on whether the specified
 *              instance of the given attribute has been defined at the
 *              given level.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              attr_type   The attribute type to validate.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              inst_num    The attribute instance number to check.
 * Returns:     TRUE or FALSE.
 */

tinybool sdp_attr_valid (sdp_t *sdp_p, sdp_attr_e attr_type, uint16_t level,
                         uint8_t cap_num, uint16_t inst_num)
{
    if (sdp_find_attr(sdp_p, level, cap_num, attr_type, inst_num) == NULL) {
        return (FALSE);
    } else {
        return (TRUE);
    }
}

/* Function:    sdp_attr_line_number(sdp_t *sdp_p)
 * Description: Returns the line number this attribute appears on.
 *              Only works if the SDP was parsed rather than created
 *              locally.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              attr_type   The attribute type to validate.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              inst_num    The attribute instance number to check.
 * Returns:     line number, or 0 if an error
 */

uint32_t sdp_attr_line_number (sdp_t *sdp_p, sdp_attr_e attr_type, uint16_t level,
                          uint8_t cap_num, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    attr_p = sdp_find_attr(sdp_p, level, cap_num, attr_type, inst_num);
    if (attr_p == NULL) {
        return 0;
    } else {
        return attr_p->line_number;
    }
}

static boolean sdp_attr_is_simple_string(sdp_attr_e attr_type) {
    if ((attr_type != SDP_ATTR_BEARER) &&
        (attr_type != SDP_ATTR_CALLED) &&
        (attr_type != SDP_ATTR_CONN_TYPE) &&
        (attr_type != SDP_ATTR_DIALED) &&
        (attr_type != SDP_ATTR_DIALING) &&
        (attr_type != SDP_ATTR_FRAMING) &&
        (attr_type != SDP_ATTR_MID) &&
        (attr_type != SDP_ATTR_X_SIDIN) &&
        (attr_type != SDP_ATTR_X_SIDOUT)&&
        (attr_type != SDP_ATTR_X_CONFID) &&
        (attr_type != SDP_ATTR_LABEL) &&
        (attr_type != SDP_ATTR_ICE_OPTIONS) &&
        (attr_type != SDP_ATTR_IMAGEATTR) &&
        (attr_type != SDP_ATTR_SIMULCAST) &&
        (attr_type != SDP_ATTR_RID)) {
      return FALSE;
    }
    return TRUE;
}

/* Function:    sdp_attr_get_simple_string
 * Description: Returns a pointer to a string attribute parameter.  This
 *              routine can only be called for attributes that have just
 *              one string parameter.  The value is returned as a const
 *              ptr and so cannot be modified by the application.  If the
 *              given attribute is not defined, NULL will be returned.
 *              Attributes with a simple string parameter currently include:
 *              bearer, called, connection_type, dialed, dialing, direction
 *              and framing.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              attr_type   The simple string attribute type.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              inst_num    The attribute instance number to check.
 * Returns:     Pointer to the parameter value.
 */

const char *sdp_attr_get_simple_string (sdp_t *sdp_p, sdp_attr_e attr_type,
                                        uint16_t level, uint8_t cap_num, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    if (!sdp_attr_is_simple_string(attr_type)) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s Attribute type is not a simple string (%s)",
                      sdp_p->debug_str, sdp_get_attr_name(attr_type));
        }
        sdp_p->conf_p->num_invalid_param++;
        return (NULL);
    }

    attr_p = sdp_find_attr(sdp_p, level, cap_num, attr_type, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s Attribute %s, level %u instance %u not found.",
                      sdp_p->debug_str, sdp_get_attr_name(attr_type),
                      (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (NULL);
    } else {
        return (attr_p->attr.string_val);
    }
}

static boolean sdp_attr_is_long_string(sdp_attr_e attr_type) {
  return (attr_type == SDP_ATTR_IDENTITY || attr_type == SDP_ATTR_DTLS_MESSAGE);
}

/* Identical in usage to sdp_attr_get_simple_string() */
const char *sdp_attr_get_long_string (sdp_t *sdp_p, sdp_attr_e attr_type,
                                      uint16_t level, uint8_t cap_num, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    if (!sdp_attr_is_long_string(attr_type)) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s Attribute type is not a long string (%s)",
                      sdp_p->debug_str, sdp_get_attr_name(attr_type));
        }
        sdp_p->conf_p->num_invalid_param++;
        return (NULL);
    }

    attr_p = sdp_find_attr(sdp_p, level, cap_num, attr_type, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s Attribute %s, level %u instance %u not found.",
                      sdp_p->debug_str, sdp_get_attr_name(attr_type),
                      (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (NULL);
    } else {
        return (attr_p->attr.stringp);
    }
}

static boolean sdp_attr_is_simple_u32(sdp_attr_e attr_type) {
    if ((attr_type != SDP_ATTR_EECID) &&
        (attr_type != SDP_ATTR_PTIME) &&
        (attr_type != SDP_ATTR_MAXPTIME) &&
        (attr_type != SDP_ATTR_SCTPPORT) &&
        (attr_type != SDP_ATTR_MAXMESSAGESIZE) &&
        (attr_type != SDP_ATTR_T38_VERSION) &&
        (attr_type != SDP_ATTR_T38_MAXBITRATE) &&
        (attr_type != SDP_ATTR_T38_MAXBUFFER) &&
        (attr_type != SDP_ATTR_T38_MAXDGRAM) &&
        (attr_type != SDP_ATTR_X_SQN) &&
        (attr_type != SDP_ATTR_TC1_PAYLOAD_BYTES) &&
        (attr_type != SDP_ATTR_TC1_WINDOW_SIZE) &&
        (attr_type != SDP_ATTR_TC2_PAYLOAD_BYTES) &&
        (attr_type != SDP_ATTR_TC2_WINDOW_SIZE) &&
        (attr_type != SDP_ATTR_FRAMERATE)) {
        return FALSE;
    }

    return TRUE;
}

/* Function:    sdp_attr_get_simple_u32
 * Description: Returns an unsigned 32-bit attribute parameter.  This
 *              routine can only be called for attributes that have just
 *              one uint32_t parameter.  If the given attribute is not defined,
 *              zero will be returned.  There is no way for the application
 *              to determine if zero is the actual value or the attribute
 *              wasn't defined, so the application must use the
 *              sdp_attr_valid function to determine this.
 *              Attributes with a simple uint32_t parameter currently include:
 *              eecid, ptime, T38FaxVersion, T38maxBitRate, T38FaxMaxBuffer,
 *              T38FaxMaxDatagram, X-sqn, TC1PayloadBytes, TC1WindowSize,
 *              TC2PayloadBytes, TC2WindowSize, rtcp.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              attr_type   The simple uint32_t attribute type.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              inst_num    The attribute instance number to check.
 * Returns:     uint32_t parameter value.
 */

uint32_t sdp_attr_get_simple_u32 (sdp_t *sdp_p, sdp_attr_e attr_type, uint16_t level,
                             uint8_t cap_num, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    if (!sdp_attr_is_simple_u32(attr_type)) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s Attribute type is not a simple uint32_t (%s)",
                      sdp_p->debug_str, sdp_get_attr_name(attr_type));
        }
        sdp_p->conf_p->num_invalid_param++;
        return (0);
    }

    attr_p = sdp_find_attr(sdp_p, level, cap_num, attr_type, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s Attribute %s, level %u instance %u not found.",
                      sdp_p->debug_str, sdp_get_attr_name(attr_type),
                      (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (0);
    } else {
        return (attr_p->attr.u32_val);
    }
}

/* Function:    sdp_attr_get_simple_boolean
 * Description: Returns a boolean attribute parameter.  This
 *              routine can only be called for attributes that have just
 *              one boolean parameter.  If the given attribute is not defined,
 *              FALSE will be returned.  There is no way for the application
 *              to determine if FALSE is the actual value or the attribute
 *              wasn't defined, so the application must use the
 *              sdp_attr_valid function to determine this.
 *              Attributes with a simple boolean parameter currently include:
 *              T38FaxFillBitRemoval, T38FaxTranscodingMMR,
 *              T38FaxTranscodingJBIG, and TMRGwXid.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              attr_type   The simple boolean attribute type.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              inst_num    The attribute instance number to check.
 * Returns:     Boolean value.
 */

tinybool sdp_attr_get_simple_boolean (sdp_t *sdp_p, sdp_attr_e attr_type,
                                      uint16_t level, uint8_t cap_num, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    if ((attr_type != SDP_ATTR_T38_FILLBITREMOVAL) &&
        (attr_type != SDP_ATTR_T38_TRANSCODINGMMR) &&
        (attr_type != SDP_ATTR_T38_TRANSCODINGJBIG) &&
        (attr_type != SDP_ATTR_TMRGWXID)) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s Attribute type is not a simple boolean (%s)",
                      sdp_p->debug_str, sdp_get_attr_name(attr_type));
        }
        sdp_p->conf_p->num_invalid_param++;
        return (FALSE);
    }

    attr_p = sdp_find_attr(sdp_p, level, cap_num, attr_type, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s Attribute %s, level %u instance %u not found.",
                      sdp_p->debug_str, sdp_get_attr_name(attr_type),
                      (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (FALSE);
    } else {
        return (attr_p->attr.boolean_val);
    }
}

/*
 * sdp_attr_get_maxprate
 *
 * This function is used by the application layer to get the packet-rate
 * within the maxprate attribute.
 *
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              inst_num    The attribute instance number to set.
 *
 * Returns a pointer to a constant char array that stores the packet-rate,
 * OR null if the attribute does not exist.
 */

const char*
sdp_attr_get_maxprate (sdp_t *sdp_p, uint16_t level, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    attr_p = sdp_find_attr(sdp_p, level, 0, SDP_ATTR_MAXPRATE, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s Attribute %s, level %u instance %u not found.",
                      sdp_p->debug_str, sdp_get_attr_name(SDP_ATTR_MAXPRATE),
                      (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (NULL);
    } else {
        return (attr_p->attr.string_val);
    }
}

/* Function:    sdp_attr_get_t38ratemgmt
 * Description: Returns the value of the t38ratemgmt attribute
 *              parameter specified for the given attribute.  If the given
 *              attribute is not defined, SDP_T38_UNKNOWN_RATE is returned.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              inst_num    The attribute instance number to check.
 * Returns:     Ratemgmt value.
 */

sdp_t38_ratemgmt_e sdp_attr_get_t38ratemgmt (sdp_t *sdp_p, uint16_t level,
                                             uint8_t cap_num, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    attr_p = sdp_find_attr(sdp_p, level, cap_num,
                           SDP_ATTR_T38_RATEMGMT, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s t38ratemgmt attribute, level %u instance %u "
                      "not found.", sdp_p->debug_str, (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (SDP_T38_UNKNOWN_RATE);
    } else {
        return (attr_p->attr.t38ratemgmt);
    }
}

/* Function:    sdp_attr_get_t38udpec
 * Description: Returns the value of the t38udpec attribute
 *              parameter specified for the given attribute.  If the given
 *              attribute is not defined, SDP_T38_UDPEC_UNKNOWN is returned.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              inst_num    The attribute instance number to check.
 * Returns:     UDP EC value.
 */

sdp_t38_udpec_e sdp_attr_get_t38udpec (sdp_t *sdp_p, uint16_t level,
                                       uint8_t cap_num, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    attr_p = sdp_find_attr(sdp_p, level, cap_num,
                           SDP_ATTR_T38_UDPEC, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s t38udpec attribute, level %u instance %u "
                      "not found.", sdp_p->debug_str, (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (SDP_T38_UDPEC_UNKNOWN);
    } else {
        return (attr_p->attr.t38udpec);
    }
}

/* Function:    sdp_get_media_direction
 * Description: Determines the direction defined for a given level.  The
 *              direction will be inactive, sendonly, recvonly, or sendrecv
 *              as determined by the last of these attributes specified at
 *              the given level.  If none of these attributes are specified,
 *              the direction will be sendrecv by default.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 * Returns:     An SDP direction enum value.
 */

sdp_direction_e sdp_get_media_direction (sdp_t *sdp_p, uint16_t level,
                                         uint8_t cap_num)
{
    sdp_mca_t   *mca_p;
    sdp_attr_t  *attr_p;
    sdp_direction_e direction = SDP_DIRECTION_SENDRECV;

    if (cap_num == 0) {
        /* Find the pointer to the attr list for this level. */
        if (level == SDP_SESSION_LEVEL) {
            attr_p = sdp_p->sess_attrs_p;
        } else {  /* Attr is at a media level */
            mca_p = sdp_find_media_level(sdp_p, level);
            if (mca_p == NULL) {
                return (direction);
            }
            attr_p = mca_p->media_attrs_p;
        }

        /* Scan for direction oriented attributes.  Last one wins. */
        for (; attr_p != NULL; attr_p = attr_p->next_p) {
            if (attr_p->type == SDP_ATTR_INACTIVE) {
                direction = SDP_DIRECTION_INACTIVE;
            } else if (attr_p->type == SDP_ATTR_SENDONLY) {
                direction = SDP_DIRECTION_SENDONLY;
            } else if (attr_p->type == SDP_ATTR_RECVONLY) {
                direction = SDP_DIRECTION_RECVONLY;
            } else if (attr_p->type == SDP_ATTR_SENDRECV) {
                direction = SDP_DIRECTION_SENDRECV;
            }
        }
    } else {
        if (sdp_p->debug_flag[SDP_DEBUG_WARNINGS]) {
            SDPLogDebug(logTag, "%s Warning: Invalid cap_num for media direction.",
                     sdp_p->debug_str);
        }
    }

    return (direction);
}

/* Since there are four different attribute names which all have the same
 * qos parameters, all of these attributes are accessed through this same
 * set of APIs.  To distinguish between specific attributes, the application
 * must also pass the attribute type.  The attribute must be one of:
 * SDP_ATTR_QOS, SDP_ATTR_SECURE, SDP_ATTR_X_PC_QOS, and SDP_ATTR_X_QOS.
 */

tinybool sdp_validate_qos_attr (sdp_attr_e qos_attr)
{
    if ((qos_attr == SDP_ATTR_QOS) ||
        (qos_attr == SDP_ATTR_SECURE) ||
        (qos_attr == SDP_ATTR_X_PC_QOS) ||
        (qos_attr == SDP_ATTR_X_QOS) ||
        (qos_attr == SDP_ATTR_CURR) ||
        (qos_attr == SDP_ATTR_DES) ||
        (qos_attr == SDP_ATTR_CONF)){
        return (TRUE);
    } else {
        return (FALSE);
    }
}

/* Function:    sdp_attr_get_qos_strength
 * Description: Returns the value of the qos attribute strength
 *              parameter specified for the given attribute.  If the given
 *              attribute is not defined, SDP_QOS_STRENGTH_UNKNOWN is
 *              returned.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              qos_attr    The specific type of qos attribute.  May be
 *                          qos, secure, X-pc-qos, or X-qos.
 *              inst_num    The attribute instance number to check.
 * Returns:     Qos strength value.
 */

sdp_qos_strength_e sdp_attr_get_qos_strength (sdp_t *sdp_p, uint16_t level,
                                uint8_t cap_num, sdp_attr_e qos_attr, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    if (sdp_validate_qos_attr(qos_attr) == FALSE) {
        if (sdp_p->debug_flag[SDP_DEBUG_WARNINGS]) {
            SDPLogDebug(logTag, "%s Warning: Invalid QOS attribute specified for"
                     "get qos strength.", sdp_p->debug_str);
        }
        return (SDP_QOS_STRENGTH_UNKNOWN);
    }
    attr_p = sdp_find_attr(sdp_p, level, cap_num, qos_attr, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s %s attribute, level %u instance %u "
                      "not found.", sdp_p->debug_str,
                      sdp_get_attr_name(qos_attr), (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (SDP_QOS_STRENGTH_UNKNOWN);
    } else {
        switch (qos_attr) {
            case SDP_ATTR_QOS:
                return (attr_p->attr.qos.strength);
            case SDP_ATTR_DES:
                return (attr_p->attr.des.strength);
            default:
                return SDP_QOS_STRENGTH_UNKNOWN;

        }
    }
}

/* Function:    sdp_attr_get_qos_direction
 * Description: Returns the value of the qos attribute direction
 *              parameter specified for the given attribute.  If the given
 *              attribute is not defined, SDP_QOS_DIR_UNKNOWN is
 *              returned.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              qos_attr    The specific type of qos attribute.  May be
 *                          qos, secure, X-pc-qos, or X-qos.
 *              inst_num    The attribute instance number to check.
 * Returns:     Qos direction value.
 */

sdp_qos_dir_e sdp_attr_get_qos_direction (sdp_t *sdp_p, uint16_t level,
                                uint8_t cap_num, sdp_attr_e qos_attr, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    if (sdp_validate_qos_attr(qos_attr) == FALSE) {
        if (sdp_p->debug_flag[SDP_DEBUG_WARNINGS]) {
            SDPLogDebug(logTag, "%s Warning: Invalid QOS attribute specified "
                     "for get qos direction.", sdp_p->debug_str);
        }
        return (SDP_QOS_DIR_UNKNOWN);
    }
    attr_p = sdp_find_attr(sdp_p, level, cap_num, qos_attr, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s %s attribute, level %u instance %u "
                      "not found.", sdp_p->debug_str,
                      sdp_get_attr_name(qos_attr), (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (SDP_QOS_DIR_UNKNOWN);
    } else {
         switch (qos_attr) {
            case SDP_ATTR_QOS:
                 return (attr_p->attr.qos.direction);
            case SDP_ATTR_CURR:
                 return (attr_p->attr.curr.direction);
            case SDP_ATTR_DES:
                 return (attr_p->attr.des.direction);
            case SDP_ATTR_CONF:
                 return (attr_p->attr.conf.direction);
            default:
                return SDP_QOS_DIR_UNKNOWN;

        }
    }
}

/* Function:    sdp_attr_get_qos_status_type
 * Description: Returns the value of the qos attribute status_type
 *              parameter specified for the given attribute.  If the given
 *              attribute is not defined, SDP_QOS_STATUS_TYPE_UNKNOWN is
 *              returned.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              qos_attr    The specific type of qos attribute.  May be
 *                          qos, secure, X-pc-qos, or X-qos.
 *              inst_num    The attribute instance number to check.
 * Returns:     Qos direction value.
 */

sdp_qos_status_types_e sdp_attr_get_qos_status_type (sdp_t *sdp_p, uint16_t level,
                                uint8_t cap_num, sdp_attr_e qos_attr, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    if (sdp_validate_qos_attr(qos_attr) == FALSE) {
        if (sdp_p->debug_flag[SDP_DEBUG_WARNINGS]) {
            SDPLogDebug(logTag, "%s Warning: Invalid QOS attribute specified "
                     "for get qos status_type.", sdp_p->debug_str);
        }
        return (SDP_QOS_STATUS_TYPE_UNKNOWN);
    }
    attr_p = sdp_find_attr(sdp_p, level, cap_num, qos_attr, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s %s attribute, level %u instance %u "
                      "not found.", sdp_p->debug_str,
                      sdp_get_attr_name(qos_attr), (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (SDP_QOS_STATUS_TYPE_UNKNOWN);
    } else {
        switch (qos_attr) {
            case SDP_ATTR_CURR:
                return (attr_p->attr.curr.status_type);
            case SDP_ATTR_DES:
                return (attr_p->attr.des.status_type);
            case SDP_ATTR_CONF:
                return (attr_p->attr.conf.status_type);
            default:
                return SDP_QOS_STATUS_TYPE_UNKNOWN;

        }
    }
}

/* Function:    sdp_attr_get_qos_confirm
 * Description: Returns the value of the qos attribute confirm
 *              parameter specified for the given attribute.  Returns TRUE if
 *              the confirm parameter is specified.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              qos_attr    The specific type of qos attribute.  May be
 *                          qos, secure, X-pc-qos, or X-qos.
 *              inst_num    The attribute instance number to check.
 * Returns:     Boolean value.
 */

tinybool sdp_attr_get_qos_confirm (sdp_t *sdp_p, uint16_t level,
                                uint8_t cap_num, sdp_attr_e qos_attr, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    if (sdp_validate_qos_attr(qos_attr) == FALSE) {
        if (sdp_p->debug_flag[SDP_DEBUG_WARNINGS]) {
            SDPLogDebug(logTag, "%s Warning: Invalid QOS attribute specified "
                     "for get qos confirm.", sdp_p->debug_str);
        }
        return (FALSE);
    }
    attr_p = sdp_find_attr(sdp_p, level, cap_num, qos_attr, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s %s attribute, level %u instance %u "
                      "not found.", sdp_p->debug_str,
                      sdp_get_attr_name(qos_attr), (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (FALSE);
    } else {
        return (attr_p->attr.qos.confirm);
    }
}

/* Function:    sdp_attr_get_curr_type
 * Description: Returns the value of the curr attribute status_type
 *              parameter specified for the given attribute.  If the given
 *              attribute is not defined, SDP_CURR_UNKNOWN_TYPE is
 *              returned.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              qos_attr    The specific type of qos attribute.  May be
 *                          qos, secure, X-pc-qos, or X-qos.
 *              inst_num    The attribute instance number to check.
 * Returns:     Curr type value.
 */

sdp_curr_type_e sdp_attr_get_curr_type (sdp_t *sdp_p, uint16_t level,
                                uint8_t cap_num, sdp_attr_e qos_attr, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    attr_p = sdp_find_attr(sdp_p, level, cap_num, qos_attr, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s %s attribute, level %u instance %u "
                      "not found.", sdp_p->debug_str,
                      sdp_get_attr_name(qos_attr), (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (SDP_CURR_UNKNOWN_TYPE);
    } else {
        return (attr_p->attr.curr.type);
    }
}

/* Function:    sdp_attr_get_des_type
 * Description: Returns the value of the des attribute status_type
 *              parameter specified for the given attribute.  If the given
 *              attribute is not defined, SDP_DES_UNKNOWN_TYPE is
 *              returned.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              qos_attr    The specific type of qos attribute.  May be
 *                          qos, secure, X-pc-qos, or X-qos.
 *              inst_num    The attribute instance number to check.
 * Returns:     DES type value.
 */

sdp_des_type_e sdp_attr_get_des_type (sdp_t *sdp_p, uint16_t level,
                                uint8_t cap_num, sdp_attr_e qos_attr, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    attr_p = sdp_find_attr(sdp_p, level, cap_num, qos_attr, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s %s attribute, level %u instance %u "
                      "not found.", sdp_p->debug_str,
                      sdp_get_attr_name(qos_attr), (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (SDP_DES_UNKNOWN_TYPE);
    } else {
        return (attr_p->attr.des.type);
    }
}

/* Function:    sdp_attr_get_conf_type
 * Description: Returns the value of the des attribute status_type
 *              parameter specified for the given attribute.  If the given
 *              attribute is not defined, SDP_CONF_UNKNOWN_TYPE is
 *              returned.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              qos_attr    The specific type of qos attribute.  May be
 *                          qos, secure, X-pc-qos, or X-qos.
 *              inst_num    The attribute instance number to check.
 * Returns:     CONF type value.
 */

sdp_conf_type_e sdp_attr_get_conf_type (sdp_t *sdp_p, uint16_t level,
                                uint8_t cap_num, sdp_attr_e qos_attr, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    attr_p = sdp_find_attr(sdp_p, level, cap_num, qos_attr, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s %s attribute, level %u instance %u "
                      "not found.", sdp_p->debug_str,
                      sdp_get_attr_name(qos_attr), (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (SDP_CONF_UNKNOWN_TYPE);
    } else {
        return (attr_p->attr.conf.type);
    }
}

/* Function:    sdp_attr_get_subnet_nettype
 * Description: Returns the value of the subnet attribute network type
 *              parameter specified for the given attribute.  If the given
 *              attribute is not defined, SDP_NT_INVALID is returned.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              inst_num    The attribute instance number to check.
 * Returns:     Nettype value.
 */

sdp_nettype_e sdp_attr_get_subnet_nettype (sdp_t *sdp_p, uint16_t level,
                                           uint8_t cap_num, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    attr_p = sdp_find_attr(sdp_p, level, cap_num,
                           SDP_ATTR_SUBNET, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s Subnet attribute, level %u instance %u "
                      "not found.", sdp_p->debug_str, (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (SDP_NT_INVALID);
    } else {
        return (attr_p->attr.subnet.nettype);
    }
}

/* Function:    sdp_attr_get_subnet_addrtype
 * Description: Returns the value of the subnet attribute address type
 *              parameter specified for the given attribute.  If the given
 *              attribute is not defined, SDP_AT_INVALID is returned.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              inst_num    The attribute instance number to check.
 * Returns:     Addrtype value.
 */

sdp_addrtype_e sdp_attr_get_subnet_addrtype (sdp_t *sdp_p, uint16_t level,
                                             uint8_t cap_num, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    attr_p = sdp_find_attr(sdp_p, level, cap_num,
                           SDP_ATTR_SUBNET, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s Subnet attribute, level %u instance %u "
                      "not found.", sdp_p->debug_str, (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (SDP_AT_INVALID);
    } else {
        return (attr_p->attr.subnet.addrtype);
    }
}

/* Function:    sdp_attr_get_subnet_addr
 * Description: Returns the value of the subnet attribute address
 *              parameter specified for the given attribute.  If the given
 *              attribute is not defined, NULL is returned.  Value is
 *              returned as a const ptr and so cannot be modified by the
 *              application.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              inst_num    The attribute instance number to check.
 * Returns:     Pointer to address or NULL.
 */

const char *sdp_attr_get_subnet_addr (sdp_t *sdp_p, uint16_t level,
                                      uint8_t cap_num, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    attr_p = sdp_find_attr(sdp_p, level, cap_num,
                           SDP_ATTR_SUBNET, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s Subnet attribute, level %u instance %u "
                      "not found.", sdp_p->debug_str, (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (NULL);
    } else {
        return (attr_p->attr.subnet.addr);
    }
}

/* Function:    sdp_attr_get_subnet_prefix
 * Description: Returns the value of the subnet attribute prefix
 *              parameter specified for the given attribute.  If the given
 *              attribute is not defined, SDP_INVALID_PARAM is returned.
 *              Note that this is value is defined to be (-2) and is
 *              different from the return code SDP_INVALID_PARAMETER.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              inst_num    The attribute instance number to check.
 * Returns:     Prefix value or SDP_INVALID_PARAM.
 */

int32_t sdp_attr_get_subnet_prefix (sdp_t *sdp_p, uint16_t level,
                                  uint8_t cap_num, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    attr_p = sdp_find_attr(sdp_p, level, cap_num,
                           SDP_ATTR_SUBNET, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s Subnet attribute, level %u instance %u "
                      "not found.", sdp_p->debug_str, (unsigned)level, (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (SDP_INVALID_VALUE);
    } else {
        return (attr_p->attr.subnet.prefix);
    }
}

/* Function:    sdp_attr_rtpmap_payload_valid
 * Description: Returns true or false depending on whether an rtpmap
 *              attribute was specified with the given payload value
 *              at the given level.  If it was, the instance number of
 *              that attribute is returned.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              inst_num    The attribute instance number of the attribute
 *                          found is returned via this param.
 * Returns:     TRUE or FALSE.
 */

tinybool sdp_attr_rtpmap_payload_valid (sdp_t *sdp_p, uint16_t level, uint8_t cap_num,
                                        uint16_t *inst_num, uint16_t payload_type)
{
    uint16_t          i;
    sdp_attr_t  *attr_p;
    uint16_t          num_instances;

    *inst_num = 0;

    if (sdp_attr_num_instances(sdp_p, level, cap_num,
                          SDP_ATTR_RTPMAP, &num_instances) != SDP_SUCCESS) {
        return (FALSE);
    }

    for (i=1; i <= num_instances; i++) {
        attr_p = sdp_find_attr(sdp_p, level, cap_num, SDP_ATTR_RTPMAP, i);
        if ((attr_p != NULL) &&
            (attr_p->attr.transport_map.payload_num == payload_type)) {
            *inst_num = i;
            return (TRUE);
        }
    }

    return (FALSE);
}

/* Function:    sdp_attr_get_rtpmap_payload_type
 * Description: Returns the value of the rtpmap attribute payload type
 *              parameter specified for the given attribute.  If the given
 *              attribute is not defined, zero is returned.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              inst_num    The attribute instance number to check.
 * Returns:     Payload type value.
 */

uint16_t sdp_attr_get_rtpmap_payload_type (sdp_t *sdp_p, uint16_t level,
                                      uint8_t cap_num, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    attr_p = sdp_find_attr(sdp_p, level, cap_num, SDP_ATTR_RTPMAP, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s rtpmap attribute, level %u instance %u "
                                "not found.",
                                sdp_p->debug_str,
                                (unsigned)level,
                                (unsigned)inst_num);
        }
        sdp_p->conf_p->num_invalid_param++;
        return (0);
    } else {
        return (attr_p->attr.transport_map.payload_num);
    }
}

/* Function:    sdp_attr_get_rtpmap_encname
 * Description: Returns a pointer to the value of the encoding name
 *              parameter specified for the given attribute.  Value is
 *              returned as a const ptr and so cannot be modified by the
 *              application.  If the given attribute is not defined, NULL
 *              will be returned.
 * Parameters:  sdp_p     The SDP handle returned by sdp_init_description.
 *              level       The level to check for the attribute.
 *              cap_num     The capability number associated with the
 *                          attribute if any.  If none, should be zero.
 *              inst_num    The attribute instance number to check.
 * Returns:     Codec value or SDP_CODEC_INVALID.
 */

const char *sdp_attr_get_rtpmap_encname (sdp_t *sdp_p, uint16_t level,
                                         uint8_t cap_num, uint16_t inst_num)
{
    sdp_attr_t  *attr_p;

    attr_p = sdp_find_attr(sdp_p, level, cap_num, SDP_ATTR_RTPMAP, inst_num);
    if (attr_p == NULL) {
        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
            SDPLogError(logTag, "%s rtpmap attribute, level %u instance %u "
                                "not found.",
--> --------------------

--> maximum size reached

--> --------------------

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

¤ Dauer der Verarbeitung: 0.46 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.