Bug 844071 - Patch 1 - handle building and parsing of setup and connection attributes r=abr

This commit is contained in:
Ethan Hugg 2013-08-27 07:40:22 -07:00
parent f5ee31f9e2
commit 56a7c8de8a
8 changed files with 470 additions and 1 deletions

View File

@ -528,6 +528,9 @@ gsmsdp_init_media (fsmdef_media_t *media)
media->candidate_ct = 0;
media->rtcp_mux = FALSE;
/* ACTPASS is the value we put in every offer */
media->setup = SDP_SETUP_ACTPASS;
media->local_datachannel_port = 0;
media->remote_datachannel_port = 0;
media->datachannel_streams = WEBRTC_DATACHANNEL_STREAMS_DEFAULT;
@ -1821,6 +1824,71 @@ gsmsdp_set_rtcp_mux_attribute (sdp_attr_e sdp_attr, uint16_t level, void *sdp_p,
}
}
/*
* gsmsdp_set_setup_attribute
*
* Description:
*
* Adds a setup attribute to the specified SDP.
*
* Parameters:
*
* level - The media level of the SDP where the media attribute exists.
* sdp_p - Pointer to the SDP to set the ice candidate attribute against.
* setup_type - Value for the a=setup line
*/
static void
gsmsdp_set_setup_attribute(uint16_t level,
void *sdp_p, sdp_setup_type_e setup_type) {
uint16_t a_instance = 0;
sdp_result_e result;
result = sdp_add_new_attr(sdp_p, level, 0, SDP_ATTR_SETUP, &a_instance);
if (result != SDP_SUCCESS) {
GSM_ERR_MSG("Failed to add attribute");
return;
}
result = sdp_attr_set_setup_attribute(sdp_p, level, 0,
a_instance, setup_type);
if (result != SDP_SUCCESS) {
GSM_ERR_MSG("Failed to set attribute");
}
}
/*
* gsmsdp_set_connection_attribute
*
* Description:
*
* Adds a connection attribute to the specified SDP.
*
* Parameters:
*
* level - The media level of the SDP where the media attribute exists.
* sdp_p - Pointer to the SDP to set the ice candidate attribute against.
* connection_type - Value for the a=connection line
*/
static void
gsmsdp_set_connection_attribute(uint16_t level,
void *sdp_p, sdp_connection_type_e connection_type) {
uint16_t a_instance = 0;
sdp_result_e result;
result = sdp_add_new_attr(sdp_p, level, 0, SDP_ATTR_CONNECTION,
&a_instance);
if (result != SDP_SUCCESS) {
GSM_ERR_MSG("Failed to add attribute");
return;
}
result = sdp_attr_set_connection_attribute(sdp_p, level, 0,
a_instance, connection_type);
if (result != SDP_SUCCESS) {
GSM_ERR_MSG("Failed to set attribute");
}
}
/*
* gsmsdp_set_dtls_fingerprint_attribute
*
@ -4641,6 +4709,7 @@ gsmsdp_negotiate_media_lines (fsm_fcb_t *fcb_p, cc_sdp_t *sdp_p, boolean initial
sdp_result_e sdp_res;
boolean created_media_stream = FALSE;
int lsm_rc;
sdp_setup_type_e remote_setup_type;
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
@ -4939,6 +5008,40 @@ gsmsdp_negotiate_media_lines (fsm_fcb_t *fcb_p, cc_sdp_t *sdp_p, boolean initial
if (sdpmode) {
int j;
/* Find the remote a=setup value */
sdp_res = sdp_attr_get_setup_attribute(
sdp_p->dest_sdp, i, 0, 1, &remote_setup_type);
/* setup attribute
We are setting our local SDP to be ACTIVE if the value
in the remote SDP is missing, PASSIVE or ACTPASS.
If the remote value is ACTIVE, then we will respond
with PASSIVE.
If the remote value is HOLDCONN we will respond with
HOLDCONN and set the direction to INACTIVE
The DTLS role will then be set when the TransportFlow
is created */
media->setup = SDP_SETUP_ACTIVE;
if (sdp_res == SDP_SUCCESS) {
if (remote_setup_type == SDP_SETUP_ACTIVE) {
media->setup = SDP_SETUP_PASSIVE;
} else if (remote_setup_type == SDP_SETUP_HOLDCONN) {
media->setup = SDP_SETUP_HOLDCONN;
media->direction = SDP_DIRECTION_INACTIVE;
}
}
gsmsdp_set_setup_attribute(media->level, dcb_p->sdp->src_sdp,
media->setup);
/* TODO(ehugg) we are not yet supporting existing connections
See bug 857115. We currently always respond with
connection:new */
gsmsdp_set_connection_attribute(media->level,
dcb_p->sdp->src_sdp, SDP_CONNECTION_NEW);
/* Set ICE */
for (j=0; j<media->candidate_ct; j++) {
gsmsdp_set_ice_attribute (SDP_ATTR_ICE_CANDIDATE, media->level,
@ -5456,6 +5559,13 @@ gsmsdp_add_media_line (fsmdef_dcb_t *dcb_p, const cc_media_cap_t *media_cap,
SDP_RTCP_FB_CCM_TO_BITMAP(SDP_RTCP_FB_CCM_FIR));
}
/* setup and connection attributes */
gsmsdp_set_setup_attribute(level, dcb_p->sdp->src_sdp, media->setup);
/* This is a new media line so we should send connection:new */
gsmsdp_set_connection_attribute(level, dcb_p->sdp->src_sdp,
SDP_CONNECTION_NEW);
/*
* wait until here to set ICE candidates as SDP is now initialized
*/

View File

@ -207,6 +207,11 @@ typedef struct fsmdef_media_t_ {
*/
boolean rtcp_mux;
/*
* The value of the a=setup line
*/
sdp_setup_type_e setup;
/*
* port number used in m= data channel line
*/

View File

@ -519,6 +519,14 @@ typedef enum {
SDP_RTCP_FB_CCM_UNKNOWN
} sdp_rtcp_fb_ccm_type_e;
typedef enum {
SDP_CONNECTION_NOT_FOUND = -1,
SDP_CONNECTION_NEW = 0,
SDP_CONNECTION_EXISTING,
SDP_MAX_CONNECTION,
SDP_CONNECTION_UNKNOWN
} sdp_connection_type_e;
#define SDP_RTCP_FB_NACK_TO_BITMAP(type) (1 << (type))
#define SDP_RTCP_FB_ACK_TO_BITMAP(type) (1 << (SDP_MAX_RTCP_FB_NACK + (type)))
#define SDP_RTCP_FB_CCM_TO_BITMAP(type) (1 << (SDP_MAX_RTCP_FB_NACK + \
@ -1017,6 +1025,8 @@ typedef struct sdp_attr {
char unknown[SDP_MAX_STRING_LEN+1];
sdp_source_filter_t source_filter;
sdp_fmtp_fb_t rtcp_fb;
sdp_setup_type_e setup;
sdp_connection_type_e connection;
} attr;
struct sdp_attr *next_p;
} sdp_attr_t;
@ -2069,6 +2079,23 @@ sdp_result_e
sdp_attr_set_rtcp_mux_attribute(void *sdp_ptr, u16 level,
u8 cap_num, sdp_attr_e sdp_attr, u16 inst_num, const tinybool rtcp_mux);
sdp_result_e
sdp_attr_get_setup_attribute (void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num, sdp_setup_type_e *setup_type);
sdp_result_e
sdp_attr_set_setup_attribute(void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num, sdp_setup_type_e setup_type);
sdp_result_e
sdp_attr_get_connection_attribute (void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num, sdp_connection_type_e *connection_type);
sdp_result_e
sdp_attr_set_connection_attribute(void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num, sdp_connection_type_e connection_type);
sdp_result_e
sdp_attr_get_dtls_fingerprint_attribute (void *sdp_ptr, u16 level,
u8 cap_num, sdp_attr_e sdp_attr, u16 inst_num,

View File

@ -4986,3 +4986,127 @@ sdp_result_e sdp_parse_attr_rtcp_fb (sdp_t *sdp_p,
return SDP_SUCCESS;
}
sdp_result_e sdp_build_attr_setup(sdp_t *sdp_p,
sdp_attr_t *attr_p,
flex_string *fs)
{
switch (attr_p->attr.setup) {
case SDP_SETUP_ACTIVE:
case SDP_SETUP_PASSIVE:
case SDP_SETUP_ACTPASS:
case SDP_SETUP_HOLDCONN:
flex_string_sprintf(fs, "a=%s:%s\r\n",
sdp_attr[attr_p->type].name,
sdp_setup_type_val[attr_p->attr.setup].name);
break;
default:
CSFLogError(logTag, "%s Error: Invalid setup enum (%d)",
sdp_p->debug_str, attr_p->attr.setup);
return SDP_FAILURE;
}
return SDP_SUCCESS;
}
sdp_result_e sdp_parse_attr_setup(sdp_t *sdp_p,
sdp_attr_t *attr_p,
const char *ptr)
{
int i = find_token_enum("setup attribute", sdp_p, &ptr,
sdp_setup_type_val,
SDP_MAX_SETUP, SDP_SETUP_UNKNOWN);
if (i < 0) {
sdp_parse_error(sdp_p->peerconnection,
"%s Warning: could not parse setup attribute",
sdp_p->debug_str);
sdp_p->conf_p->num_invalid_param++;
return SDP_INVALID_PARAMETER;
}
attr_p->attr.setup = (sdp_setup_type_e) i;
switch (attr_p->attr.setup) {
case SDP_SETUP_ACTIVE:
case SDP_SETUP_PASSIVE:
case SDP_SETUP_ACTPASS:
case SDP_SETUP_HOLDCONN:
/* All these values are OK */
break;
case SDP_SETUP_UNKNOWN:
sdp_parse_error(sdp_p->peerconnection,
"%s Warning: Unknown setup attribute",
sdp_p->debug_str);
return SDP_INVALID_PARAMETER;
break;
default:
/* This is an internal error, not a parsing error */
CSFLogError(logTag, "%s Error: Invalid setup enum (%d)",
sdp_p->debug_str, attr_p->attr.setup);
return SDP_FAILURE;
break;
}
return SDP_SUCCESS;
}
sdp_result_e sdp_build_attr_connection(sdp_t *sdp_p,
sdp_attr_t *attr_p,
flex_string *fs)
{
switch (attr_p->attr.connection) {
case SDP_CONNECTION_NEW:
case SDP_CONNECTION_EXISTING:
flex_string_sprintf(fs, "a=%s:%s\r\n",
sdp_attr[attr_p->type].name,
sdp_connection_type_val[attr_p->attr.connection].name);
break;
default:
CSFLogError(logTag, "%s Error: Invalid connection enum (%d)",
sdp_p->debug_str, attr_p->attr.connection);
return SDP_FAILURE;
}
return SDP_SUCCESS;
}
sdp_result_e sdp_parse_attr_connection(sdp_t *sdp_p,
sdp_attr_t *attr_p,
const char *ptr)
{
int i = find_token_enum("connection attribute", sdp_p, &ptr,
sdp_connection_type_val,
SDP_MAX_CONNECTION, SDP_CONNECTION_UNKNOWN);
if (i < 0) {
sdp_parse_error(sdp_p->peerconnection,
"%s Warning: could not parse connection attribute",
sdp_p->debug_str);
sdp_p->conf_p->num_invalid_param++;
return SDP_INVALID_PARAMETER;
}
attr_p->attr.connection = (sdp_connection_type_e) i;
switch (attr_p->attr.connection) {
case SDP_CONNECTION_NEW:
case SDP_CONNECTION_EXISTING:
/* All these values are OK */
break;
case SDP_CONNECTION_UNKNOWN:
sdp_parse_error(sdp_p->peerconnection,
"%s Warning: Unknown connection attribute",
sdp_p->debug_str);
return SDP_INVALID_PARAMETER;
break;
default:
/* This is an internal error, not a parsing error */
CSFLogError(logTag, "%s Error: Invalid connection enum (%d)",
sdp_p->debug_str, attr_p->attr.connection);
return SDP_FAILURE;
break;
}
return SDP_SUCCESS;
}

View File

@ -4084,6 +4084,163 @@ sdp_result_e sdp_attr_set_rtcp_mux_attribute(void *sdp_ptr, u16 level,
return (SDP_SUCCESS);
}
/* Function: sdp_attr_get_setup_attribute
* Description: Returns the value of a setup attribute at a given level
*
* Parameters: sdp_ptr 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.
* setup_type Returns sdp_setup_type_e enum
* Returns:
* SDP_SUCCESS Attribute param was set successfully.
* SDP_INVALID_SDP_PTR SDP pointer invalid
* SDP_INVALID_PARAMETER Specified attribute is not defined.
*/
sdp_result_e sdp_attr_get_setup_attribute (void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num, sdp_setup_type_e *setup_type)
{
sdp_t *sdp_p = (sdp_t *)sdp_ptr;
sdp_attr_t *attr_p;
if (!sdp_verify_sdp_ptr(sdp_p)) {
return SDP_INVALID_SDP_PTR;
}
attr_p = sdp_find_attr(sdp_p, level, cap_num, SDP_ATTR_SETUP, inst_num);
if (!attr_p) {
if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
CSFLogError(logTag,
"%s setup attribute, level %u instance %u not found.",
sdp_p->debug_str, level, inst_num);
}
sdp_p->conf_p->num_invalid_param++;
return SDP_INVALID_PARAMETER;
}
*setup_type = attr_p->attr.setup;
return SDP_SUCCESS;
}
/* Function: sdp_attr_set_setup_attribute
* Description: Sets the value of a setup attribute parameter
*
* Parameters: sdp_ptr The SDP handle returned by sdp_init_description.
* level The level to set 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.
* setup_type setup attribute value to set
* Returns: SDP_SUCCESS Attribute param was set successfully.
* SDP_INVALID_SDP_PTR SDP ptr invalid
* SDP_INVALID_PARAMETER Specified attribute is not defined.
*/
sdp_result_e
sdp_attr_set_setup_attribute(void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num, sdp_setup_type_e setup_type)
{
sdp_t *sdp_p = (sdp_t *)sdp_ptr;
sdp_attr_t *attr_p;
if (!sdp_verify_sdp_ptr(sdp_p)) {
return SDP_INVALID_SDP_PTR;
}
attr_p = sdp_find_attr(sdp_p, level, cap_num, SDP_ATTR_SETUP, inst_num);
if (!attr_p) {
if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
CSFLogError(logTag, "%s setup attribute, level %u instance %u "
"not found.", sdp_p->debug_str, level, inst_num);
}
sdp_p->conf_p->num_invalid_param++;
return SDP_INVALID_PARAMETER;
}
attr_p->attr.setup = setup_type;
return SDP_SUCCESS;
}
/* Function: sdp_attr_get_connection_attribute
* Description: Returns the value of a connection attribute at a given level
*
* Parameters: sdp_ptr 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.
* connection_type Returns sdp_connection_type_e enum
* Returns:
* SDP_SUCCESS Attribute param was set successfully.
* SDP_INVALID_SDP_PTR SDP pointer invalid
* SDP_INVALID_PARAMETER Specified attribute is not defined.
*/
sdp_result_e sdp_attr_get_connection_attribute (void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num, sdp_connection_type_e *connection_type)
{
sdp_t *sdp_p = (sdp_t *)sdp_ptr;
sdp_attr_t *attr_p;
if (!sdp_verify_sdp_ptr(sdp_p)) {
return SDP_INVALID_SDP_PTR;
}
attr_p = sdp_find_attr(sdp_p, level, cap_num, SDP_ATTR_CONNECTION,
inst_num);
if (!attr_p) {
if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
CSFLogError(logTag,
"%s setup attribute, level %u instance %u not found.",
sdp_p->debug_str, level, inst_num);
}
sdp_p->conf_p->num_invalid_param++;
return SDP_INVALID_PARAMETER;
}
*connection_type = attr_p->attr.connection;
return SDP_SUCCESS;
}
/* Function: sdp_attr_set_connection_attribute
* Description: Sets the value of a connection attribute parameter
*
* Parameters: sdp_ptr The SDP handle returned by sdp_init_description.
* level The level to set 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.
* connection_type connection attribute value to set
* Returns: SDP_SUCCESS Attribute param was set successfully.
* SDP_INVALID_SDP_PTR SDP ptr invalid
* SDP_INVALID_PARAMETER Specified attribute is not defined.
*/
sdp_result_e
sdp_attr_set_connection_attribute(void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num, sdp_connection_type_e connection_type)
{
sdp_t *sdp_p = (sdp_t *)sdp_ptr;
sdp_attr_t *attr_p;
if (!sdp_verify_sdp_ptr(sdp_p)) {
return SDP_INVALID_SDP_PTR;
}
attr_p = sdp_find_attr(sdp_p, level, cap_num, SDP_ATTR_CONNECTION,
inst_num);
if (!attr_p) {
if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
CSFLogError(logTag, "%s connection attribute, level %u instance %u "
"not found.", sdp_p->debug_str, level, inst_num);
}
sdp_p->conf_p->num_invalid_param++;
return SDP_INVALID_PARAMETER;
}
attr_p->attr.connection = connection_type;
return SDP_SUCCESS;
}
/* Function: sdp_attr_get_dtls_fingerprint_attribute
* Description: Returns the value of dtls fingerprint attribute at a given level
*

View File

@ -169,7 +169,11 @@ const sdp_attrarray_t sdp_attr[SDP_MAX_ATTR_TYPES] =
{"maxptime", sizeof("maxptime"),
sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32},
{"rtcp-fb", sizeof("rtcp-fb"),
sdp_parse_attr_rtcp_fb, sdp_build_attr_rtcp_fb}
sdp_parse_attr_rtcp_fb, sdp_build_attr_rtcp_fb},
{"setup", sizeof("setup"),
sdp_parse_attr_setup, sdp_build_attr_setup},
{"connection", sizeof("connection"),
sdp_parse_attr_connection, sdp_build_attr_connection},
};
/* Note: These *must* be in the same order as the enum types. */
@ -483,6 +487,21 @@ const sdp_namearray_t sdp_rtcp_fb_ccm_type_val[SDP_MAX_RTCP_FB_CCM] =
SDP_NAME("vbcm")
};
/* Maintain the same order as defined in typedef sdp_setup_type_e */
const sdp_namearray_t sdp_setup_type_val[SDP_MAX_SETUP] =
{
SDP_NAME("active"),
SDP_NAME("passive"),
SDP_NAME("actpass"),
SDP_NAME("holdconn")
};
/* Maintain the same order as defined in typedef sdp_connection_type_e */
const sdp_namearray_t sdp_connection_type_val[SDP_MAX_CONNECTION] =
{
SDP_NAME("new"),
SDP_NAME("existing")
};
/* Maintain same order as defined in typedef sdp_srtp_crypto_suite_t */
const sdp_srtp_crypto_suite_list sdp_srtp_crypto_suite_array[SDP_SRTP_MAX_NUM_CRYPTO_SUITES] =

View File

@ -37,6 +37,8 @@ extern const sdp_namearray_t sdp_rtcp_fb_type_val[];
extern const sdp_namearray_t sdp_rtcp_fb_nack_type_val[];
extern const sdp_namearray_t sdp_rtcp_fb_ack_type_val[];
extern const sdp_namearray_t sdp_rtcp_fb_ccm_type_val[];
extern const sdp_namearray_t sdp_setup_type_val[];
extern const sdp_namearray_t sdp_connection_type_val[];
extern const sdp_srtp_crypto_suite_list sdp_srtp_crypto_suite_array[];
@ -149,6 +151,18 @@ extern sdp_result_e sdp_parse_attr_rtcp_fb(sdp_t *sdp_p,
extern sdp_result_e sdp_build_attr_rtcp_fb(sdp_t *sdp_p,
sdp_attr_t *attr_p,
flex_string *fs);
extern sdp_result_e sdp_parse_attr_setup(sdp_t *sdp_p,
sdp_attr_t *attr_p,
const char *ptr);
extern sdp_result_e sdp_build_attr_setup(sdp_t *sdp_p,
sdp_attr_t *attr_p,
flex_string *fs);
extern sdp_result_e sdp_parse_attr_connection(sdp_t *sdp_p,
sdp_attr_t *attr_p,
const char *ptr);
extern sdp_result_e sdp_build_attr_connection(sdp_t *sdp_p,
sdp_attr_t *attr_p,
flex_string *fs);
extern sdp_result_e sdp_parse_attr_mptime(
sdp_t *sdp_p, sdp_attr_t *attr_p, const char *ptr);
extern sdp_result_e sdp_build_attr_mptime(

View File

@ -242,10 +242,23 @@ typedef enum {
SDP_ATTR_DTLS_FINGERPRINT,
SDP_ATTR_MAXPTIME,
SDP_ATTR_RTCP_FB, /* RFC 4585 */
SDP_ATTR_SETUP,
SDP_ATTR_CONNECTION,
SDP_MAX_ATTR_TYPES,
SDP_ATTR_INVALID
} sdp_attr_e;
/* This is here so that it can be used in the VcmSIPCCBinding interface */
typedef enum {
SDP_SETUP_NOT_FOUND = -1,
SDP_SETUP_ACTIVE = 0,
SDP_SETUP_PASSIVE,
SDP_SETUP_ACTPASS,
SDP_SETUP_HOLDCONN,
SDP_MAX_SETUP,
SDP_SETUP_UNKNOWN
} sdp_setup_type_e;
/**
* Gets the value of the fmtp attribute- parameter-sets parameter for H.264 codec
*