mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-02-07 14:18:25 +00:00
improve SDP<->SalMediaDescription conversion and offer answer algorithm
This commit is contained in:
parent
028f4c550b
commit
1af4a7c091
7 changed files with 81 additions and 21 deletions
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue