/* 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
--> --------------------