simplify dtls session/media description attributes mgt

This commit is contained in:
Jehan Monnier 2015-02-16 17:50:28 +01:00
parent 009fe8afc9
commit ccb890ad94
5 changed files with 64 additions and 106 deletions

View file

@ -389,23 +389,6 @@ belle_sdp_session_description_t * media_description_to_sdp ( const SalMediaDescr
if (desc->ice_pwd[0] != '\0') belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("ice-pwd",desc->ice_pwd));
if (desc->ice_ufrag[0] != '\0') belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("ice-ufrag",desc->ice_ufrag));
/* insert DTLS session attribute if needed */
if ((desc->dtls_role != SalDtlsRoleInvalid) && (strlen(desc->dtls_fingerprint)>0)) {
switch(desc->dtls_role) {
case SalDtlsRoleIsClient:
belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("setup","active"));
break;
case SalDtlsRoleIsServer:
belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("setup","passive"));
break;
case SalDtlsRoleUnset:
default:
belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("setup","actpass"));
break;
}
belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("fingerprint",desc->dtls_fingerprint));
}
if (desc->rtcp_xr.enabled == TRUE) {
belle_sdp_session_description_add_attribute(session_desc, create_rtcp_xr_attribute(&desc->rtcp_xr));
}
@ -777,20 +760,10 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
} else if (strncmp(value, "passive", 7) == 0) {
stream->dtls_role = SalDtlsRoleIsServer;
}
if (stream->dtls_role != SalDtlsRoleInvalid || md->dtls_role != SalDtlsRoleInvalid) {
if (stream->dtls_role != SalDtlsRoleInvalid) {
attribute=belle_sdp_media_description_get_attribute(media_desc,"fingerprint");
if (attribute && (value=belle_sdp_attribute_get_value(attribute))!=NULL){
strncpy(stream->dtls_fingerprint, value, sizeof(stream->dtls_fingerprint)-1);
} else {
/* no valid stream attributes, get them from session */
if (stream->dtls_role == SalDtlsRoleInvalid) stream->dtls_role = md->dtls_role;
strncpy(stream->dtls_fingerprint, md->dtls_fingerprint, strlen(md->dtls_fingerprint)+1);
}
strncpy(stream->dtls_fingerprint, belle_sdp_attribute_get_value(attribute),sizeof(stream->dtls_fingerprint));
}
} else { /* no setup attribute found in the stream, get the one from the session */
stream->dtls_role = md->dtls_role;
strncpy(stream->dtls_fingerprint, md->dtls_fingerprint, strlen(md->dtls_fingerprint)+1);
}
}
@ -849,26 +822,30 @@ int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, S
desc->dir=SalStreamInactive;
}
/* Read dtls specific session attributes if any (setup and fingerprint - rfc5763) */
/* Presence of a valid dtls offer(setup and fingerprint attribute) is set in media Description by a dtls_fingerprint string longer than 0
* and a dtls_role != SalDtlsRoleInvalid */
desc->dtls_role = SalDtlsRoleInvalid;
desc->dtls_fingerprint[0] = '\0';
/*DTLS attributes can be defined at session level.*/
value=belle_sdp_session_description_get_attribute_value(session_desc,"setup");
if (value){
SalDtlsRole session_role;
if (strncmp(value, "actpass", 7) == 0) {
desc->dtls_role = SalDtlsRoleUnset;
session_role = SalDtlsRoleUnset;
} else if (strncmp(value, "active", 6) == 0) {
desc->dtls_role = SalDtlsRoleIsClient;
session_role = SalDtlsRoleIsClient;
} else if (strncmp(value, "passive", 7) == 0) {
desc->dtls_role = SalDtlsRoleIsServer;
session_role = SalDtlsRoleIsServer;
}
value=belle_sdp_session_description_get_attribute_value(session_desc,"fingerprint");
if (value){
int i;
/*copy dtls attributes to every streams, might be overwritten stream by stream*/
for (i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;i++) {
strncpy(desc->streams[i].dtls_fingerprint, value, sizeof(desc->streams[i].dtls_fingerprint));
desc->streams[i].dtls_role=session_role;
}
}
}
value=belle_sdp_session_description_get_attribute_value(session_desc,"fingerprint");
if (value){
strncpy(desc->dtls_fingerprint, value, sizeof(desc->dtls_fingerprint)-1);
}
/* Get ICE remote ufrag and remote pwd, and ice_lite flag */
value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-ufrag");

View file

@ -438,7 +438,22 @@ static int setup_encryption_key(SalSrtpCryptoAlgo *crypto, MSCryptoSuite suite,
}
return 0;
}
static void setup_dtls_keys(LinphoneCall *call, SalMediaDescription *md){
int i;
for(i=0; i<md->nb_streams; i++) {
if (!sal_stream_description_active(&md->streams[i])) continue;
/* if media encryption is set to DTLS check presence of fingerprint in the call which shall have been set at stream init but it may have failed when retrieving certificate resulting in no fingerprint present and then DTLS not usable */
if (sal_stream_description_has_dtls(&md->streams[i]) == TRUE) {
strncpy(md->streams[i].dtls_fingerprint, call->dtls_certificate_fingerprint, sizeof(md->streams[i].dtls_fingerprint)); /* get the self fingerprint from call(it's computed at stream init) */
md->streams[i].dtls_role = SalDtlsRoleUnset; /* if we are offering, SDP will have actpass setup attribute when role is unset, if we are responding the result mediadescription will be set to SalDtlsRoleIsClient */
} else {
md->streams[i].dtls_fingerprint[0] = '\0';
md->streams[i].dtls_role = SalDtlsRoleInvalid;
}
}
}
static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){
LinphoneCore *lc=call->core;
int i,j;
@ -675,16 +690,8 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
l = make_codec_list(lc, &codec_hints, lc->codecs_conf.video_codecs);
md->streams[i].payloads = l;
}
setup_encryption_keys(call,md);
/* if media encryption is set to DTLS check presence of fingerprint in the call which shall have been set at stream init but it may have failed when retrieving certificate resulting in no fingerprint present and then DTLS not usable */
if ((call->params->media_encryption==LinphoneMediaEncryptionDTLS) && (call->dtls_certificate_fingerprint!= NULL)) {
memcpy(md->dtls_fingerprint, call->dtls_certificate_fingerprint, strlen((const char *)(call->dtls_certificate_fingerprint))); /* get the self fingerprint from call(it's computed at stream init) */
md->dtls_role = SalDtlsRoleUnset; /* if we are offering, SDP will have actpass setup attribute when role is unset, if we are responding the result mediadescription will be set to SalDtlsRoleIsClient */
} else {
md->dtls_fingerprint[0] = '\0';
md->dtls_role = SalDtlsRoleInvalid;
}
setup_dtls_keys(call,md);
setup_rtcp_fb(call, md);
setup_rtcp_xr(call, md);
@ -2434,10 +2441,6 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b
/* DTLS engine was already initialised during stream init. Before starting it we must be sure that the role(client or server) is set.
* Role may have already been set to server if we initiate the call and already received a packet from peer, in that case do nothing */
SalDtlsRole salRole = stream->dtls_role;
if (salRole==SalDtlsRoleInvalid) { /* it's invalid in streams[0] but check also at session level */
salRole = call->resultdesc->dtls_role;
}
if (salRole!=SalDtlsRoleInvalid) { /* if DTLS is available at both end points */
/* give the peer certificate fingerprint to dtls context */
SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op);
@ -2582,10 +2585,6 @@ static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inpu
if (sal_stream_description_has_dtls(vstream) == TRUE) {
/*DTLS*/
SalDtlsRole salRole = vstream->dtls_role;
if (salRole==SalDtlsRoleInvalid) { /* it's invalid in streams[0] but check also at session level */
salRole = call->resultdesc->dtls_role;
}
if (salRole!=SalDtlsRoleInvalid) { /* if DTLS is available at both end points */
/* give the peer certificate fingerprint to dtls context */
SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op);

View file

@ -394,6 +394,21 @@ static void initiate_outgoing(const SalStreamDescription *local_offer,
result->rtp_ssrc=local_offer->rtp_ssrc;
strncpy(result->rtcp_cname,local_offer->rtcp_cname,sizeof(result->rtcp_cname));
// Handle dtls session attribute: if both local and remote have a dtls fingerprint and a dtls setup, get the remote fingerprint into the result
if ((local_offer->dtls_role!=SalDtlsRoleInvalid) && (remote_answer->dtls_role!=SalDtlsRoleInvalid)
&&(strlen(local_offer->dtls_fingerprint)>0) && (strlen(remote_answer->dtls_fingerprint)>0)) {
strncpy(result->dtls_fingerprint, remote_answer->dtls_fingerprint,sizeof(result->dtls_fingerprint));
if (remote_answer->dtls_role==SalDtlsRoleIsClient) {
result->dtls_role = SalDtlsRoleIsServer;
} else {
result->dtls_role = SalDtlsRoleIsClient;
}
} else {
result->dtls_fingerprint[0] = '\0';
result->dtls_role = SalDtlsRoleInvalid;
}
}
@ -449,6 +464,20 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
result->rtp_ssrc=local_cap->rtp_ssrc;
strncpy(result->rtcp_cname,local_cap->rtcp_cname,sizeof(result->rtcp_cname));
// Handle dtls stream attribute: if both local and remote have a dtls fingerprint and a dtls setup, add the local fingerprint to the answer
// Note: local description usually stores dtls config at session level which means it apply to all streams, check this too
if (((local_cap->dtls_role!=SalDtlsRoleInvalid)) && (remote_offer->dtls_role!=SalDtlsRoleInvalid)
&& (strlen(local_cap->dtls_fingerprint)>0) && (strlen(remote_offer->dtls_fingerprint)>0)) {
strncpy(result->dtls_fingerprint, local_cap->dtls_fingerprint,sizeof(result->dtls_fingerprint));
if (remote_offer->dtls_role==SalDtlsRoleUnset) {
result->dtls_role = SalDtlsRoleIsClient;
}
} else {
result->dtls_fingerprint[0] = '\0';
result->dtls_role = SalDtlsRoleInvalid;
}
}
@ -484,21 +513,6 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
result->rtcp_xr.enabled = FALSE;
}
// Handle dtls session attribute: if both local and remote have a dtls fingerprint and a dtls setup, get the remote fingerprint into the result
if ((local_offer->dtls_role!=SalDtlsRoleInvalid) && (remote_answer->dtls_role!=SalDtlsRoleInvalid)
&&(strlen(local_offer->dtls_fingerprint)>0) && (strlen(remote_answer->dtls_fingerprint)>0)) {
strcpy(result->dtls_fingerprint, remote_answer->dtls_fingerprint);
if (remote_answer->dtls_role==SalDtlsRoleIsClient) {
result->dtls_role = SalDtlsRoleIsServer;
} else {
result->dtls_role = SalDtlsRoleIsClient;
}
} else {
result->dtls_fingerprint[0] = '\0';
result->dtls_role = SalDtlsRoleInvalid;
}
return 0;
}
@ -553,24 +567,6 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
}else ms_warning("Unknown protocol for mline %i, declining",i);
if (ls){
initiate_incoming(ls,rs,&result->streams[i],one_matching_codec);
// Handle dtls stream attribute: if both local and remote have a dtls fingerprint and a dtls setup, add the local fingerprint to the answer
// Note: local description usually stores dtls config at session level which means it apply to all streams, check this too
if (((ls->dtls_role!=SalDtlsRoleInvalid) || (local_capabilities->dtls_role!=SalDtlsRoleInvalid)) && (rs->dtls_role!=SalDtlsRoleInvalid)
&& ((strlen(ls->dtls_fingerprint)>0) || (strlen(local_capabilities->dtls_fingerprint)>0)) && (strlen(rs->dtls_fingerprint)>0)) {
if (strlen(ls->dtls_fingerprint)>0) { /* get the fingerprint in stream description */
strcpy(result->streams[i].dtls_fingerprint, ls->dtls_fingerprint);
} else { /* get the fingerprint in session description */
strcpy(result->streams[i].dtls_fingerprint, local_capabilities->dtls_fingerprint);
}
if (rs->dtls_role==SalDtlsRoleUnset) {
result->streams[i].dtls_role = SalDtlsRoleIsClient;
}
} else {
result->streams[i].dtls_fingerprint[0] = '\0';
result->streams[i].dtls_role = SalDtlsRoleInvalid;
}
// Handle media RTCP XR attribute
memset(&result->streams[i].rtcp_xr, 0, sizeof(result->streams[i].rtcp_xr));
if (rs->rtcp_xr.enabled == TRUE) {
@ -611,18 +607,6 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
strcpy(result->name,local_capabilities->name);
// Handle dtls session attribute: if both local and remote have a dtls fingerprint and a dtls setup, add the local fingerprint to the answer
if ((local_capabilities->dtls_role!=SalDtlsRoleInvalid) && (remote_offer->dtls_role!=SalDtlsRoleInvalid)
&&(strlen(local_capabilities->dtls_fingerprint)>0) && (strlen(remote_offer->dtls_fingerprint)>0)) {
strcpy(result->dtls_fingerprint, local_capabilities->dtls_fingerprint);
if (remote_offer->dtls_role==SalDtlsRoleUnset) {
result->dtls_role = SalDtlsRoleIsClient;
}
} else {
result->dtls_fingerprint[0] = '\0';
result->dtls_role = SalDtlsRoleInvalid;
}
// Handle session RTCP XR attribute
memset(&result->rtcp_xr, 0, sizeof(result->rtcp_xr));
if (remote_offer->rtcp_xr.enabled == TRUE) {

View file

@ -260,8 +260,6 @@ typedef struct SalMediaDescription{
bool_t ice_lite;
bool_t ice_completed;
bool_t pad[2];
char dtls_fingerprint[256];
SalDtlsRole dtls_role;
} SalMediaDescription;
typedef struct SalMessage{

@ -1 +1 @@
Subproject commit 07a8b569317d23e9442882be267d6640498a7b5e
Subproject commit 8d120b3c118625b827834d1e53b93185d335c3df