Commit 1af4a7c0 authored by Simon Morlat's avatar Simon Morlat
Browse files

improve SDP<->SalMediaDescription conversion and offer answer algorithm

parent 028f4c55
......@@ -947,6 +947,12 @@ unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size){
return belle_sip_random_bytes(ret,size);
}
unsigned int sal_get_random(void){
unsigned int ret=0;
belle_sip_random_bytes((unsigned char*)&ret,4);
return ret;
}
belle_sip_source_t * sal_create_timer(Sal *sal, belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms, const char* timer_name) {
belle_sip_main_loop_t *ml = belle_sip_stack_get_main_loop(sal->stack);
return belle_sip_main_loop_create_timeout(ml, func, data, timeout_value_ms, timer_name);
......
......@@ -87,7 +87,7 @@ static belle_sdp_media_description_t *stream_description_to_sdp ( const SalMedia
rtp_port=stream->rtp_port;
rtcp_port=stream->rtcp_port;
media_desc = belle_sdp_media_description_create ( sal_stream_type_to_string ( stream->type )
media_desc = belle_sdp_media_description_create ( sal_stream_description_get_type_as_string(stream)
,stream->rtp_port
,1
,sal_media_proto_to_string ( stream->proto )
......@@ -351,7 +351,7 @@ static void sdp_parse_ice_media_parameters(belle_sdp_media_description_t *media_
while (3 == sscanf(ptr, "%u %s %u%n", &componentID, candidate.addr, &candidate.port, &offset)) {
if ((componentID > 0) && (componentID <= SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES)) {
SalIceRemoteCandidate *remote_candidate = &stream->ice_remote_candidates[componentID - 1];
strncpy(remote_candidate->addr, candidate.addr, sizeof(remote_candidate->addr));
strncpy(remote_candidate->addr, candidate.addr, sizeof(remote_candidate->addr)-1);
remote_candidate->port = candidate.port;
}
ptr += offset;
......@@ -360,9 +360,9 @@ static void sdp_parse_ice_media_parameters(belle_sdp_media_description_t *media_
} else break;
}
} else if ((keywordcmp("ice-ufrag", att_name) == 0) && (value != NULL)) {
strncpy(stream->ice_ufrag, value, sizeof(stream->ice_ufrag));
strncpy(stream->ice_ufrag, value, sizeof(stream->ice_ufrag)-1);
} else if ((keywordcmp("ice-pwd", att_name) == 0) && (value != NULL)) {
strncpy(stream->ice_pwd, value, sizeof(stream->ice_pwd));
strncpy(stream->ice_pwd, value, sizeof(stream->ice_pwd) -1);
} else if (keywordcmp("ice-mismatch", att_name) == 0) {
stream->ice_mismatch = TRUE;
}
......@@ -383,16 +383,18 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
memset ( stream,0,sizeof ( *stream ) );
proto = belle_sdp_media_get_protocol ( media );
stream->proto=SalProtoUnknown;
stream->proto=SalProtoOther;
if ( proto ) {
if ( strcasecmp ( proto,"RTP/AVP" ) ==0 )
stream->proto=SalProtoRtpAvp;
else if ( strcasecmp ( proto,"RTP/SAVP" ) ==0 ) {
stream->proto=SalProtoRtpSavp;
}else{
strncpy(stream->proto_other,proto,sizeof(stream->proto_other)-1);
}
}
if ( ( cnx=belle_sdp_media_description_get_connection ( media_desc ) ) && belle_sdp_connection_get_address ( cnx ) ) {
strncpy ( stream->rtp_addr,belle_sdp_connection_get_address ( cnx ),sizeof ( stream->rtp_addr ) );
strncpy ( stream->rtp_addr,belle_sdp_connection_get_address ( cnx ), sizeof ( stream->rtp_addr ) -1 );
}
stream->rtp_port=belle_sdp_media_get_media_port ( media );
......@@ -439,7 +441,7 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
if (nb == 1) {
/* SDP rtcp attribute only contains the port */
} else if (nb == 2) {
strncpy(stream->rtcp_addr, tmp, sizeof(stream->rtcp_addr));
strncpy(stream->rtcp_addr, tmp, sizeof(stream->rtcp_addr)-1);
} else {
ms_warning("sdp has a strange a=rtcp line (%s) nb=%i", value, nb);
}
......@@ -470,10 +472,10 @@ int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, S
desc->dir = SalStreamSendRecv;
if ( ( cnx=belle_sdp_session_description_get_connection ( session_desc ) ) && belle_sdp_connection_get_address ( cnx ) ) {
strncpy ( desc->addr,belle_sdp_connection_get_address ( cnx ),sizeof ( desc->addr ) );
strncpy ( desc->addr,belle_sdp_connection_get_address ( cnx ),sizeof ( desc->addr ) -1 );
}
if ( (sname=belle_sdp_session_description_get_session_name(session_desc)) && belle_sdp_session_name_get_value(sname) ){
strncpy(desc->name,belle_sdp_session_name_get_value(sname),sizeof(desc->name));
strncpy(desc->name,belle_sdp_session_name_get_value(sname),sizeof(desc->name) - 1);
}
if ( belle_sdp_session_description_get_bandwidth ( session_desc,"AS" ) >0 ) {
......@@ -493,10 +495,10 @@ int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, S
/* Get ICE remote ufrag and remote pwd, and ice_lite flag */
value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-ufrag");
if (value) strncpy(desc->ice_ufrag, value, sizeof(desc->ice_ufrag));
if (value) strncpy(desc->ice_ufrag, value, sizeof(desc->ice_ufrag) - 1);
value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-pwd");
if (value) strncpy(desc->ice_pwd, value, sizeof(desc->ice_pwd));
if (value) strncpy(desc->ice_pwd, value, sizeof(desc->ice_pwd)-1);
value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-lite");
if (value) desc->ice_lite = TRUE;
......
......@@ -293,6 +293,7 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
md->n_active_streams=1;
strncpy(md->streams[0].rtp_addr,local_ip,sizeof(md->streams[0].rtp_addr));
strncpy(md->streams[0].rtcp_addr,local_ip,sizeof(md->streams[0].rtcp_addr));
strncpy(md->streams[0].name,"Audio",sizeof(md->streams[0].name)-1);
md->streams[0].rtp_port=call->audio_port;
md->streams[0].rtcp_port=call->audio_port+1;
md->streams[0].proto=(call->params.media_encryption == LinphoneMediaEncryptionSRTP) ?
......@@ -309,6 +310,7 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
if (call->params.has_video){
md->n_active_streams++;
strncpy(md->streams[0].name,"Video",sizeof(md->streams[0].name)-1);
md->streams[1].rtp_port=call->video_port;
md->streams[1].rtcp_port=call->video_port+1;
md->streams[1].proto=md->streams[0].proto;
......
......@@ -262,6 +262,7 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
result->ice_completed = local_cap->ice_completed;
memcpy(result->ice_candidates, local_cap->ice_candidates, sizeof(result->ice_candidates));
memcpy(result->ice_remote_candidates, local_cap->ice_remote_candidates, sizeof(result->ice_remote_candidates));
strcpy(result->name,local_cap->name);
}
/**
......@@ -291,6 +292,35 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
return 0;
}
static bool_t local_stream_not_already_used(const SalMediaDescription *result, const SalStreamDescription *stream){
int i;
for(i=0;i<result->n_total_streams;++i){
const SalStreamDescription *ss=&result->streams[i];
if (strcmp(ss->name,stream->name)==0){
ms_message("video stream already used in answer");
return FALSE;
}
}
return TRUE;
}
/*in answering mode, we consider that if we are able to make SAVP, then we can do AVP as well*/
static bool_t proto_compatible(SalMediaProto local, SalMediaProto remote){
if (local==remote) return TRUE;
if (remote==SalProtoRtpAvp && local==SalProtoRtpSavp) return TRUE;
return FALSE;
}
static const SalStreamDescription *find_local_matching_stream(const SalMediaDescription *result, const SalMediaDescription *local_capabilities, const SalStreamDescription *remote_stream){
int i;
for(i=0;i<local_capabilities->n_active_streams;++i){
const SalStreamDescription *ss=&local_capabilities->streams[i];
if (ss->type==remote_stream->type && proto_compatible(ss->proto,remote_stream->proto)
&& local_stream_not_already_used(result,ss)) return ss;
}
return NULL;
}
/**
* Returns a media description to run the streams with, based on the local capabilities and
* and the received offer.
......@@ -305,17 +335,14 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
result->n_active_streams=0;
for(i=0;i<remote_offer->n_total_streams;++i){
rs=&remote_offer->streams[i];
if (rs->proto!=SalProtoUnknown){
ls=sal_media_description_find_stream((SalMediaDescription*)local_capabilities,rs->proto,rs->type);
/* if matching failed, and remote proposes Avp only, ask for local Savp streams */
if (!ls && rs->proto == SalProtoRtpAvp) {
ls=sal_media_description_find_stream((SalMediaDescription*)local_capabilities,SalProtoRtpSavp,rs->type);
}
if (rs->proto!=SalProtoOther){
ls=find_local_matching_stream(result,local_capabilities,rs);
}else ms_warning("Unknown protocol for mline %i, declining",i);
if (ls){
initiate_incoming(ls,rs,&result->streams[i],one_matching_codec);
if (result->streams[i].rtp_port!=0) result->n_active_streams++;
}else {
ms_message("Declining mline %i, no corresponding stream in local capabilities description.",i);
/* create an inactive stream for the answer, as there where no matching stream in local capabilities */
result->streams[i].dir=SalStreamInactive;
result->streams[i].rtp_port=0;
......@@ -324,6 +351,9 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
if (rs->type==SalOther){
strncpy(result->streams[i].typeother,rs->typeother,sizeof(rs->typeother)-1);
}
if (rs->proto==SalProtoOther){
strncpy(result->streams[i].proto_other,rs->proto_other,sizeof(rs->proto_other)-1);
}
}
}
result->n_total_streams=i;
......
......@@ -42,10 +42,12 @@ void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc){
}
static void linphone_proxy_config_init(LinphoneCore* lc,LinphoneProxyConfig *obj){
const char *dial_prefix;
memset(obj,0,sizeof(LinphoneProxyConfig));
obj->magic=linphone_proxy_config_magic;
obj->expires=LP_CONFIG_DEFAULT_INT((lc?lc->config:NULL),"reg_expires",3600);
obj->dial_prefix=ms_strdup(LP_CONFIG_DEFAULT_STRING((lc?lc->config:NULL),"dial_prefix",'\0'));
dial_prefix=LP_CONFIG_DEFAULT_STRING((lc?lc->config:NULL),"dial_prefix",NULL);
if (dial_prefix) obj->dial_prefix=ms_strdup(dial_prefix);
obj->dial_escape_plus=LP_CONFIG_DEFAULT_INT((lc?lc->config:NULL),"dial_escape_plus",0);
obj->privacy=LP_CONFIG_DEFAULT_INT((lc?lc->config:NULL),"privacy",LinphonePrivacyDefault);
}
......
......@@ -498,6 +498,11 @@ const char* sal_stream_type_to_string(SalStreamType type) {
}
}
const char *sal_stream_description_get_type_as_string(const SalStreamDescription *desc){
if (desc->type==SalOther) return desc->typeother;
else return sal_stream_type_to_string(desc->type);
}
const char* sal_media_proto_to_string(SalMediaProto type) {
switch (type) {
case SalProtoRtpAvp:return "RTP/AVP";
......@@ -506,6 +511,11 @@ const char* sal_media_proto_to_string(SalMediaProto type) {
}
}
const char *sal_stream_description_get_proto_as_string(const SalStreamDescription *desc){
if (desc->proto==SalProtoOther) return desc->proto_other;
else return sal_media_proto_to_string(desc->proto);
}
const char* sal_stream_dir_to_string(SalStreamDir type) {
switch (type) {
......
......@@ -121,9 +121,9 @@ typedef enum {
const char* sal_stream_type_to_string(SalStreamType type);
typedef enum{
SalProtoUnknown,
SalProtoRtpAvp,
SalProtoRtpSavp
SalProtoRtpSavp,
SalProtoOther
}SalMediaProto;
const char* sal_media_proto_to_string(SalMediaProto type);
......@@ -177,9 +177,11 @@ typedef struct SalSrtpCryptoAlgo {
#define SAL_CRYPTO_ALGO_MAX 4
typedef struct SalStreamDescription{
char name[16]; /*unique name of stream, in order to ease offer/answer model algorithm*/
SalMediaProto proto;
SalStreamType type;
char typeother[32];
char proto_other[32];
char rtp_addr[64];
char rtcp_addr[64];
int rtp_port;
......@@ -197,9 +199,13 @@ typedef struct SalStreamDescription{
char ice_pwd[SAL_MEDIA_DESCRIPTION_MAX_ICE_PWD_LEN];
bool_t ice_mismatch;
bool_t ice_completed;
bool_t pad[2];
} SalStreamDescription;
#define SAL_MEDIA_DESCRIPTION_MAX_STREAMS 4
const char *sal_stream_description_get_type_as_string(const SalStreamDescription *desc);
const char *sal_stream_description_get_proto_as_string(const SalStreamDescription *desc);
#define SAL_MEDIA_DESCRIPTION_MAX_STREAMS 8
typedef struct SalMediaDescription{
int refcount;
......@@ -217,6 +223,7 @@ typedef struct SalMediaDescription{
char ice_pwd[SAL_MEDIA_DESCRIPTION_MAX_ICE_PWD_LEN];
bool_t ice_lite;
bool_t ice_completed;
bool_t pad[2];
} SalMediaDescription;
typedef struct SalMessage{
......@@ -691,6 +698,7 @@ LINPHONE_PUBLIC void sal_enable_dns_srv(Sal *sal, bool_t enable);
LINPHONE_PUBLIC bool_t sal_dns_srv_enabled(const Sal *sal);
LINPHONE_PUBLIC void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file);
LINPHONE_PUBLIC const char *sal_get_dns_user_hosts_file(const Sal *sal);
unsigned int sal_get_random(void);
unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size);
belle_sip_source_t * sal_create_timer(Sal *sal, belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms, const char* timer_name);
void sal_cancel_timer(Sal *sal, belle_sip_source_t *timer);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment