From dce46d13a14d4c9d88ba256bf083a6f11bd4c0d3 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Tue, 18 Mar 2014 18:15:42 +0100 Subject: [PATCH 01/55] remove lpc2xml xml2lpc from linphone.pc --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 69b109cb3..c38507fa4 100644 --- a/configure.ac +++ b/configure.ac @@ -767,7 +767,7 @@ AM_CONDITIONAL(ENABLE_MANUAL, test x$have_sgmltools$build_manual = xyesyes ) dnl for external use of linphone libs LINPHONE_CFLAGS="-I${includedir} -I${includedir}/linphone" -LINPHONE_LIBS="-L${libdir} -llinphone -llpc2xml -lxml2lpc" +LINPHONE_LIBS="-L${libdir} -llinphone" AC_SUBST(LINPHONE_CFLAGS) AC_SUBST(LINPHONE_LIBS) From 4c3baa0528a21d08e5e180d952dcd7c5702c2fcf Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 14 Mar 2014 15:14:31 +0100 Subject: [PATCH 02/55] Define RTCP XR structure in oRTP instead of sal. --- coreapi/bellesip_sal/sal_sdp.c | 74 +++++++++++++++++----------------- coreapi/linphonecall.c | 10 ++--- include/sal/sal.h | 28 ++----------- 3 files changed, 45 insertions(+), 67 deletions(-) diff --git a/coreapi/bellesip_sal/sal_sdp.c b/coreapi/bellesip_sal/sal_sdp.c index 080a43dcc..b6981b567 100644 --- a/coreapi/bellesip_sal/sal_sdp.c +++ b/coreapi/bellesip_sal/sal_sdp.c @@ -68,22 +68,22 @@ static void add_ice_remote_candidates(belle_sdp_media_description_t *md, const S if (buffer[0] != '\0') belle_sdp_media_description_add_attribute(md,belle_sdp_attribute_create("remote-candidates",buffer)); } -static belle_sdp_attribute_t * create_rtcp_xr_attribute(const SalRtcpXrDescription *desc) { +static belle_sdp_attribute_t * create_rtcp_xr_attribute(const OrtpRtcpXrConfiguration *config) { belle_sdp_rtcp_xr_attribute_t *attribute = belle_sdp_rtcp_xr_attribute_new(); - if (desc->rcvr_rtt_mode != SalRtcpXrRcvrRttNone) { - if (desc->rcvr_rtt_mode == SalRtcpXrRcvrRttAll) belle_sdp_rtcp_xr_attribute_set_rcvr_rtt_mode(attribute, "all"); - else if (desc->rcvr_rtt_mode == SalRtcpXrRcvrRttSender) belle_sdp_rtcp_xr_attribute_set_rcvr_rtt_mode(attribute, "sender"); - belle_sdp_rtcp_xr_attribute_set_rcvr_rtt_max_size(attribute, desc->rcvr_rtt_max_size); + if (config->rcvr_rtt_mode != OrtpRtcpXrRcvrRttNone) { + if (config->rcvr_rtt_mode == OrtpRtcpXrRcvrRttAll) belle_sdp_rtcp_xr_attribute_set_rcvr_rtt_mode(attribute, "all"); + else if (config->rcvr_rtt_mode == OrtpRtcpXrRcvrRttSender) belle_sdp_rtcp_xr_attribute_set_rcvr_rtt_mode(attribute, "sender"); + belle_sdp_rtcp_xr_attribute_set_rcvr_rtt_max_size(attribute, config->rcvr_rtt_max_size); } - belle_sdp_rtcp_xr_attribute_set_stat_summary(attribute, (desc->stat_summary_enabled == TRUE)); - if (desc->stat_summary_enabled == TRUE) { - if (desc->stat_summary_flags & SalRtcpXrStatSummaryLoss) belle_sdp_rtcp_xr_attribute_add_stat_summary_flag(attribute, "loss"); - if (desc->stat_summary_flags & SalRtcpXrStatSummaryDup) belle_sdp_rtcp_xr_attribute_add_stat_summary_flag(attribute, "dup"); - if (desc->stat_summary_flags & SalRtcpXrStatSummaryJitt) belle_sdp_rtcp_xr_attribute_add_stat_summary_flag(attribute, "jitt"); - if (desc->stat_summary_flags & SalRtcpXrStatSummaryTTL) belle_sdp_rtcp_xr_attribute_add_stat_summary_flag(attribute, "TTL"); - if (desc->stat_summary_flags & SalRtcpXrStatSummaryHL) belle_sdp_rtcp_xr_attribute_add_stat_summary_flag(attribute, "HL"); + belle_sdp_rtcp_xr_attribute_set_stat_summary(attribute, (config->stat_summary_enabled == TRUE)); + if (config->stat_summary_enabled == TRUE) { + if (config->stat_summary_flags & OrtpRtcpXrStatSummaryLoss) belle_sdp_rtcp_xr_attribute_add_stat_summary_flag(attribute, "loss"); + if (config->stat_summary_flags & OrtpRtcpXrStatSummaryDup) belle_sdp_rtcp_xr_attribute_add_stat_summary_flag(attribute, "dup"); + if (config->stat_summary_flags & OrtpRtcpXrStatSummaryJitt) belle_sdp_rtcp_xr_attribute_add_stat_summary_flag(attribute, "jitt"); + if (config->stat_summary_flags & OrtpRtcpXrStatSummaryTTL) belle_sdp_rtcp_xr_attribute_add_stat_summary_flag(attribute, "TTL"); + if (config->stat_summary_flags & OrtpRtcpXrStatSummaryHL) belle_sdp_rtcp_xr_attribute_add_stat_summary_flag(attribute, "HL"); } - belle_sdp_rtcp_xr_attribute_set_voip_metrics(attribute, (desc->voip_metrics_enabled == TRUE)); + belle_sdp_rtcp_xr_attribute_set_voip_metrics(attribute, (config->voip_metrics_enabled == TRUE)); return BELLE_SDP_ATTRIBUTE(attribute); } @@ -400,55 +400,55 @@ static void sdp_parse_media_ice_parameters(belle_sdp_media_description_t *media_ } } -static void sal_init_rtcp_xr_description(SalRtcpXrDescription *desc) { - desc->enabled = FALSE; - desc->rcvr_rtt_mode = SalRtcpXrRcvrRttNone; - desc->rcvr_rtt_max_size = -1; - desc->stat_summary_flags = 0; - desc->voip_metrics_enabled = FALSE; +static void sal_init_rtcp_xr_description(OrtpRtcpXrConfiguration *config) { + config->enabled = FALSE; + config->rcvr_rtt_mode = OrtpRtcpXrRcvrRttNone; + config->rcvr_rtt_max_size = -1; + config->stat_summary_flags = 0; + config->voip_metrics_enabled = FALSE; } -static void sdp_parse_rtcp_xr_parameters(const belle_sdp_attribute_t *attribute, SalRtcpXrDescription *desc) { - sal_init_rtcp_xr_description(desc); +static void sdp_parse_rtcp_xr_parameters(const belle_sdp_attribute_t *attribute, OrtpRtcpXrConfiguration *config) { + sal_init_rtcp_xr_description(config); if (attribute != NULL) { const belle_sdp_rtcp_xr_attribute_t *xr_attr = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute); const char *rcvr_rtt_mode = belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_mode(xr_attr); if (rcvr_rtt_mode != NULL) { if (strcasecmp(rcvr_rtt_mode, "all") == 0) { - desc->rcvr_rtt_mode = SalRtcpXrRcvrRttAll; + config->rcvr_rtt_mode = OrtpRtcpXrRcvrRttAll; } else if (strcasecmp(rcvr_rtt_mode, "sender") == 0) { - desc->rcvr_rtt_mode = SalRtcpXrRcvrRttSender; + config->rcvr_rtt_mode = OrtpRtcpXrRcvrRttSender; } - desc->rcvr_rtt_max_size = belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_max_size(xr_attr); + config->rcvr_rtt_max_size = belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_max_size(xr_attr); } - desc->stat_summary_enabled = (belle_sdp_rtcp_xr_attribute_has_stat_summary(xr_attr) != 0); - if (desc->stat_summary_enabled) { + config->stat_summary_enabled = (belle_sdp_rtcp_xr_attribute_has_stat_summary(xr_attr) != 0); + if (config->stat_summary_enabled) { belle_sip_list_t *stat_summary_flag_it; for (stat_summary_flag_it = belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(xr_attr); stat_summary_flag_it != NULL; stat_summary_flag_it = stat_summary_flag_it->next ) { const char *flag = (const char *)stat_summary_flag_it->data; if (flag != NULL) { - if (strcasecmp(flag, "loss") == 0) desc->stat_summary_flags |= SalRtcpXrStatSummaryLoss; - else if (strcasecmp(flag, "dup") == 0) desc->stat_summary_flags |= SalRtcpXrStatSummaryDup; - else if (strcasecmp(flag, "jitt") == 0) desc->stat_summary_flags |= SalRtcpXrStatSummaryJitt; - else if (strcasecmp(flag, "TTL") == 0) desc->stat_summary_flags |= SalRtcpXrStatSummaryTTL; - else if (strcasecmp(flag, "HL") == 0) desc->stat_summary_flags |= SalRtcpXrStatSummaryHL; + if (strcasecmp(flag, "loss") == 0) config->stat_summary_flags |= OrtpRtcpXrStatSummaryLoss; + else if (strcasecmp(flag, "dup") == 0) config->stat_summary_flags |= OrtpRtcpXrStatSummaryDup; + else if (strcasecmp(flag, "jitt") == 0) config->stat_summary_flags |= OrtpRtcpXrStatSummaryJitt; + else if (strcasecmp(flag, "TTL") == 0) config->stat_summary_flags |= OrtpRtcpXrStatSummaryTTL; + else if (strcasecmp(flag, "HL") == 0) config->stat_summary_flags |= OrtpRtcpXrStatSummaryHL; } } } - desc->voip_metrics_enabled = (belle_sdp_rtcp_xr_attribute_has_voip_metrics(xr_attr) != 0); - desc->enabled = TRUE; + config->voip_metrics_enabled = (belle_sdp_rtcp_xr_attribute_has_voip_metrics(xr_attr) != 0); + config->enabled = TRUE; } } -static void sdp_parse_session_rtcp_xr_parameters(belle_sdp_session_description_t *session_desc, SalRtcpXrDescription *desc) { +static void sdp_parse_session_rtcp_xr_parameters(belle_sdp_session_description_t *session_desc, OrtpRtcpXrConfiguration *config) { const belle_sdp_attribute_t *attribute = belle_sdp_session_description_get_attribute(session_desc, "rtcp-xr"); - sdp_parse_rtcp_xr_parameters(attribute, desc); + sdp_parse_rtcp_xr_parameters(attribute, config); } -static void sdp_parse_media_rtcp_xr_parameters(belle_sdp_media_description_t *media_desc, SalRtcpXrDescription *desc) { +static void sdp_parse_media_rtcp_xr_parameters(belle_sdp_media_description_t *media_desc, OrtpRtcpXrConfiguration *config) { const belle_sdp_attribute_t *attribute = belle_sdp_media_description_get_attribute(media_desc, "rtcp-xr"); - sdp_parse_rtcp_xr_parameters(attribute, desc); + sdp_parse_rtcp_xr_parameters(attribute, config); } static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md, belle_sdp_media_description_t *media_desc) { diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index eee0e6305..1c88b8531 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -264,15 +264,15 @@ static void setup_rtcp_xr(LinphoneCall *call, SalMediaDescription *md) { md->rtcp_xr.enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_enabled", 0); if (md->rtcp_xr.enabled == TRUE) { const char *rcvr_rtt_mode = lp_config_get_string(lc->config, "rtp", "rtcp_xr_rcvr_rtt_mode", "none"); - if (strcasecmp(rcvr_rtt_mode, "all") == 0) md->rtcp_xr.rcvr_rtt_mode = SalRtcpXrRcvrRttAll; - else if (strcasecmp(rcvr_rtt_mode, "sender") == 0) md->rtcp_xr.rcvr_rtt_mode = SalRtcpXrRcvrRttSender; - else md->rtcp_xr.rcvr_rtt_mode = SalRtcpXrRcvrRttNone; - if (md->rtcp_xr.rcvr_rtt_mode != SalRtcpXrRcvrRttNone) { + if (strcasecmp(rcvr_rtt_mode, "all") == 0) md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttAll; + else if (strcasecmp(rcvr_rtt_mode, "sender") == 0) md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttSender; + else md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttNone; + if (md->rtcp_xr.rcvr_rtt_mode != OrtpRtcpXrRcvrRttNone) { md->rtcp_xr.rcvr_rtt_max_size = lp_config_get_int(lc->config, "rtp", "rtcp_xr_rcvr_rtt_max_size", 0); } md->rtcp_xr.stat_summary_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_stat_summary_enabled", 0); if (md->rtcp_xr.stat_summary_enabled == TRUE) { - md->rtcp_xr.stat_summary_flags = SalRtcpXrStatSummaryLoss | SalRtcpXrStatSummaryDup | SalRtcpXrStatSummaryJitt | SalRtcpXrStatSummaryTTL; + md->rtcp_xr.stat_summary_flags = OrtpRtcpXrStatSummaryLoss | OrtpRtcpXrStatSummaryDup | OrtpRtcpXrStatSummaryJitt | OrtpRtcpXrStatSummaryTTL; } md->rtcp_xr.voip_metrics_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_enabled", 0); } diff --git a/include/sal/sal.h b/include/sal/sal.h index bb4a37d30..650b5085a 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -31,6 +31,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif #include "mediastreamer2/mscommon.h" +#include "ortp/rtpsession.h" #include "ortp/ortp_srtp.h" #include "belle-sip/belle-sip.h" @@ -135,20 +136,6 @@ typedef enum{ }SalStreamDir; const char* sal_stream_dir_to_string(SalStreamDir type); -typedef enum { - SalRtcpXrRcvrRttNone, - SalRtcpXrRcvrRttAll, - SalRtcpXrRcvrRttSender -} SalRtcpXrRcvrRttMode; - -typedef enum { - SalRtcpXrStatSummaryLoss = (1 << 0), - SalRtcpXrStatSummaryDup = (1 << 1), - SalRtcpXrStatSummaryJitt = (1 << 2), - SalRtcpXrStatSummaryTTL = (1 << 3), - SalRtcpXrStatSummaryHL = (1 << 4) -} SalRtcpXrStatSummaryFlag; - #define SAL_ENDPOINT_CANDIDATE_MAX 2 @@ -190,15 +177,6 @@ typedef struct SalSrtpCryptoAlgo { #define SAL_CRYPTO_ALGO_MAX 4 -typedef struct SalRtcpXrDescription { - bool_t enabled; - bool_t stat_summary_enabled; - bool_t voip_metrics_enabled; - SalRtcpXrRcvrRttMode rcvr_rtt_mode; - int rcvr_rtt_max_size; - SalRtcpXrStatSummaryFlag stat_summary_flags; -} SalRtcpXrDescription; - typedef struct SalStreamDescription{ char name[16]; /*unique name of stream, in order to ease offer/answer model algorithm*/ SalMediaProto proto; @@ -216,7 +194,7 @@ typedef struct SalStreamDescription{ SalSrtpCryptoAlgo crypto[SAL_CRYPTO_ALGO_MAX]; unsigned int crypto_local_tag; int max_rate; - SalRtcpXrDescription rtcp_xr; + OrtpRtcpXrConfiguration rtcp_xr; SalIceCandidate ice_candidates[SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES]; SalIceRemoteCandidate ice_remote_candidates[SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES]; char ice_ufrag[SAL_MEDIA_DESCRIPTION_MAX_ICE_UFRAG_LEN]; @@ -243,7 +221,7 @@ typedef struct SalMediaDescription{ unsigned int session_id; SalStreamDir dir; SalStreamDescription streams[SAL_MEDIA_DESCRIPTION_MAX_STREAMS]; - SalRtcpXrDescription rtcp_xr; + OrtpRtcpXrConfiguration rtcp_xr; char ice_ufrag[SAL_MEDIA_DESCRIPTION_MAX_ICE_UFRAG_LEN]; char ice_pwd[SAL_MEDIA_DESCRIPTION_MAX_ICE_PWD_LEN]; bool_t ice_lite; From 9a4fd369481a1f8d46a078a86047e4c44d586691 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 14 Mar 2014 17:07:12 +0100 Subject: [PATCH 03/55] Configure the RTCP XR parameters of the rtp session. --- coreapi/bellesip_sal/sal_sdp.c | 10 ++++++---- coreapi/linphonecall.c | 5 ++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/coreapi/bellesip_sal/sal_sdp.c b/coreapi/bellesip_sal/sal_sdp.c index b6981b567..383c0cdd3 100644 --- a/coreapi/bellesip_sal/sal_sdp.c +++ b/coreapi/bellesip_sal/sal_sdp.c @@ -409,11 +409,12 @@ static void sal_init_rtcp_xr_description(OrtpRtcpXrConfiguration *config) { } static void sdp_parse_rtcp_xr_parameters(const belle_sdp_attribute_t *attribute, OrtpRtcpXrConfiguration *config) { - sal_init_rtcp_xr_description(config); - if (attribute != NULL) { - const belle_sdp_rtcp_xr_attribute_t *xr_attr = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute); - const char *rcvr_rtt_mode = belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_mode(xr_attr); + const belle_sdp_rtcp_xr_attribute_t *xr_attr; + const char *rcvr_rtt_mode; + sal_init_rtcp_xr_description(config); + xr_attr = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute); + rcvr_rtt_mode = belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_mode(xr_attr); if (rcvr_rtt_mode != NULL) { if (strcasecmp(rcvr_rtt_mode, "all") == 0) { config->rcvr_rtt_mode = OrtpRtcpXrRcvrRttAll; @@ -540,6 +541,7 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md, sdp_parse_media_ice_parameters(media_desc, stream); /* Get RTCP-XR attributes if any */ + stream->rtcp_xr = md->rtcp_xr; // Use session parameters if no stream parameters are defined sdp_parse_media_rtcp_xr_parameters(media_desc, &stream->rtcp_xr); md->n_total_streams++; diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 1c88b8531..87dcf5e66 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -1508,6 +1508,7 @@ void linphone_call_init_video_stream(LinphoneCall *call){ ice_check_list_set_rtp_session(call->videostream->ms.ice_check_list, call->videostream->ms.session); ms_message ("creating new ice video check list [%p] for session [%p]",call->videostream->ms.ice_check_list,call->videostream->ms.session); } + call->videostream_app_evq = ortp_ev_queue_new(); rtp_session_register_event_queue(call->videostream->ms.session,call->videostream_app_evq); #ifdef TEST_EXT_RENDERER @@ -1811,6 +1812,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna call->audiostream_encrypted=FALSE; } }else call->audiostream_encrypted=FALSE; + rtp_session_configure_rtcp_xr(call->audiostream->ms.session, &stream->rtcp_xr); audio_stream_start_full( call->audiostream, call->audio_profile, @@ -1932,7 +1934,8 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna }else{ call->videostream_encrypted=FALSE; } - + rtp_session_configure_rtcp_xr(call->videostream->ms.session, &vstream->rtcp_xr); + call->log->video_enabled = TRUE; video_stream_set_direction (call->videostream, dir); ms_message("%s lc rotation:%d\n", __FUNCTION__, lc->device_rotation); From 894fd28432a4bd8bc86ae289e11ad004349fe864 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Mon, 17 Mar 2014 11:15:39 +0100 Subject: [PATCH 04/55] Fix RTCP XR parameters negociation. --- coreapi/offeranswer.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c index 67a9a5a60..b9f8d4c82 100644 --- a/coreapi/offeranswer.c +++ b/coreapi/offeranswer.c @@ -273,16 +273,17 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer, const SalMediaDescription *remote_answer, SalMediaDescription *result){ int i,j; - const SalStreamDescription *ls,*rs; + for(i=0,j=0;in_total_streams;++i){ ms_message("Processing for stream %i",i); ls=&local_offer->streams[i]; rs=sal_media_description_find_stream((SalMediaDescription*)remote_answer,ls->proto,ls->type); if (rs) { initiate_outgoing(ls,rs,&result->streams[j]); + memcpy(&result->streams[i].rtcp_xr, &ls->rtcp_xr, sizeof(result->streams[i].rtcp_xr)); if ((ls->rtcp_xr.enabled == TRUE) && (rs->rtcp_xr.enabled == FALSE)) { - memset(&result->streams[j].rtcp_xr, 0, sizeof(result->streams[j].rtcp_xr)); + result->streams[i].rtcp_xr.enabled = FALSE; } ++j; } @@ -292,8 +293,9 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer, result->n_total_streams=local_offer->n_total_streams; result->bandwidth=remote_answer->bandwidth; strcpy(result->addr,remote_answer->addr); + memcpy(&result->rtcp_xr, &local_offer->rtcp_xr, sizeof(result->rtcp_xr)); if ((local_offer->rtcp_xr.enabled == TRUE) && (remote_answer->rtcp_xr.enabled == FALSE)) { - memset(&result->rtcp_xr, 0, sizeof(result->rtcp_xr)); + result->rtcp_xr.enabled = FALSE; } return 0; @@ -352,10 +354,11 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities // Handle media RTCP XR attribute memset(&result->streams[i].rtcp_xr, 0, sizeof(result->streams[i].rtcp_xr)); if (rs->rtcp_xr.enabled == TRUE) { - if (ls->rtcp_xr.enabled == TRUE) { - memcpy(&result->streams[i].rtcp_xr, &ls->rtcp_xr, sizeof(result->streams[i].rtcp_xr)); - } else if (local_capabilities->rtcp_xr.enabled == TRUE) { - memcpy(&result->streams[i].rtcp_xr, &local_capabilities->rtcp_xr, sizeof(result->streams[i].rtcp_xr)); + const OrtpRtcpXrConfiguration *rtcp_xr_conf = NULL; + if (ls->rtcp_xr.enabled == TRUE) rtcp_xr_conf = &ls->rtcp_xr; + else if (local_capabilities->rtcp_xr.enabled == TRUE) rtcp_xr_conf = &local_capabilities->rtcp_xr; + if ((rtcp_xr_conf != NULL) && (ls->dir == SalStreamSendRecv)) { + memcpy(&result->streams[i].rtcp_xr, rtcp_xr_conf, sizeof(result->streams[i].rtcp_xr)); } else { result->streams[i].rtcp_xr.enabled = TRUE; } @@ -389,7 +392,7 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities // Handle session RTCP XR attribute memset(&result->rtcp_xr, 0, sizeof(result->rtcp_xr)); if (remote_offer->rtcp_xr.enabled == TRUE) { - if (local_capabilities->rtcp_xr.enabled == TRUE) { + if ((local_capabilities->rtcp_xr.enabled == TRUE) && (local_capabilities->dir == SalStreamSendRecv)) { memcpy(&result->rtcp_xr, &local_capabilities->rtcp_xr, sizeof(result->rtcp_xr)); } else { result->rtcp_xr.enabled = TRUE; From 681b445470767b431ba204e6360ffb73049655eb Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Mon, 17 Mar 2014 13:25:13 +0100 Subject: [PATCH 05/55] Prevent duplication of RTCP XR attribute in the medias when identical to the session one. --- coreapi/bellesip_sal/sal_sdp.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/coreapi/bellesip_sal/sal_sdp.c b/coreapi/bellesip_sal/sal_sdp.c index 383c0cdd3..3faa7a063 100644 --- a/coreapi/bellesip_sal/sal_sdp.c +++ b/coreapi/bellesip_sal/sal_sdp.c @@ -87,7 +87,7 @@ static belle_sdp_attribute_t * create_rtcp_xr_attribute(const OrtpRtcpXrConfigur return BELLE_SDP_ATTRIBUTE(attribute); } -static belle_sdp_media_description_t *stream_description_to_sdp ( const SalMediaDescription *md, const SalStreamDescription *stream ) { +static void stream_description_to_sdp ( belle_sdp_session_description_t *session_desc, const SalMediaDescription *md, const SalStreamDescription *stream ) { belle_sdp_mime_parameter_t* mime_param; belle_sdp_media_description_t* media_desc; int j; @@ -215,10 +215,27 @@ static belle_sdp_media_description_t *stream_description_to_sdp ( const SalMedia } if (stream->rtcp_xr.enabled == TRUE) { - belle_sdp_media_description_add_attribute(media_desc, create_rtcp_xr_attribute(&stream->rtcp_xr)); + char sastr[1024] = {0}; + char mastr[1024] = {0}; + size_t saoff = 0; + size_t maoff = 0; + const belle_sdp_attribute_t *session_attribute = belle_sdp_session_description_get_attribute(session_desc, "rtcp-xr"); + belle_sdp_attribute_t *media_attribute; + if (session_attribute != NULL) { + belle_sip_object_marshal((belle_sip_object_t*)session_attribute, sastr, sizeof(sastr), &saoff); + } + media_attribute = create_rtcp_xr_attribute(&stream->rtcp_xr); + if (media_attribute != NULL) { + belle_sip_object_marshal((belle_sip_object_t*)media_attribute, mastr, sizeof(mastr), &maoff); + } + if (strcmp(sastr, mastr) != 0) { + belle_sdp_media_description_add_attribute(media_desc, media_attribute); + } else { + belle_sip_object_unref((belle_sip_object_t*)media_attribute); + } } - return media_desc; + belle_sdp_session_description_add_media_description(session_desc, media_desc); } belle_sdp_session_description_t * media_description_to_sdp ( const SalMediaDescription *desc ) { @@ -272,7 +289,7 @@ belle_sdp_session_description_t * media_description_to_sdp ( const SalMediaDescr } for ( i=0; in_total_streams; i++ ) { - belle_sdp_session_description_add_media_description ( session_desc,stream_description_to_sdp(desc,&desc->streams[i])); + stream_description_to_sdp(session_desc, desc, &desc->streams[i]); } return session_desc; } From 4f68673168c5cd84ed7eb3a414c4b60f7af338ca Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Mon, 17 Mar 2014 14:56:25 +0100 Subject: [PATCH 06/55] Define RTCP XR packets sending intervals. --- coreapi/linphonecall.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 87dcf5e66..fe64ef860 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -1718,6 +1718,19 @@ static int find_crypto_index_from_tag(const SalSrtpCryptoAlgo crypto[],unsigned return -1; } +static void configure_rtp_session_for_rtcp_xr(LinphoneCore *lc, RtpSession *session, const OrtpRtcpXrConfiguration *config) { + rtp_session_configure_rtcp_xr(session, config); + if (config->rcvr_rtt_mode != OrtpRtcpXrRcvrRttNone) { + rtp_session_set_rtcp_xr_rcvr_rtt_interval(session, lp_config_get_int(lc->config, "rtp", "rtcp_xr_rcvr_rtt_interval_duration", 5000)); + } + if (config->stat_summary_enabled == TRUE) { + rtp_session_set_rtcp_xr_stat_summary_interval(session, lp_config_get_int(lc->config, "rtp", "rtcp_xr_stat_summary_interval_duration", 5000)); + } + if (config->voip_metrics_enabled == TRUE) { + rtp_session_set_rtcp_xr_voip_metrics_interval(session, lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_interval_duration", 5000)); + } +} + static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cname, bool_t muted, bool_t send_ringbacktone, bool_t use_arc){ LinphoneCore *lc=call->core; int used_pt=-1; @@ -1812,7 +1825,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna call->audiostream_encrypted=FALSE; } }else call->audiostream_encrypted=FALSE; - rtp_session_configure_rtcp_xr(call->audiostream->ms.session, &stream->rtcp_xr); + configure_rtp_session_for_rtcp_xr(lc, call->audiostream->ms.session, &stream->rtcp_xr); audio_stream_start_full( call->audiostream, call->audio_profile, @@ -1934,7 +1947,7 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna }else{ call->videostream_encrypted=FALSE; } - rtp_session_configure_rtcp_xr(call->videostream->ms.session, &vstream->rtcp_xr); + configure_rtp_session_for_rtcp_xr(lc, call->videostream->ms.session, &vstream->rtcp_xr); call->log->video_enabled = TRUE; video_stream_set_direction (call->videostream, dir); From ff9f8c71c219061be175f6aab20bf823b02c3ff3 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Mon, 17 Mar 2014 17:44:57 +0100 Subject: [PATCH 07/55] Pass good RTCP XR configuration to the RTP session. --- coreapi/linphonecall.c | 44 +++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index fe64ef860..c3864f90e 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -1718,15 +1718,45 @@ static int find_crypto_index_from_tag(const SalSrtpCryptoAlgo crypto[],unsigned return -1; } -static void configure_rtp_session_for_rtcp_xr(LinphoneCore *lc, RtpSession *session, const OrtpRtcpXrConfiguration *config) { - rtp_session_configure_rtcp_xr(session, config); - if (config->rcvr_rtt_mode != OrtpRtcpXrRcvrRttNone) { +static void configure_rtp_session_for_rtcp_xr(LinphoneCore *lc, LinphoneCall *call, SalStreamType type) { + RtpSession *session; + const OrtpRtcpXrConfiguration *localconfig; + const OrtpRtcpXrConfiguration *remoteconfig; + OrtpRtcpXrConfiguration currentconfig; + const SalStreamDescription *localstream; + const SalStreamDescription *remotestream; + + localstream = sal_media_description_find_stream(call->localdesc, SalProtoRtpSavp, type); + if (!localstream) localstream = sal_media_description_find_stream(call->localdesc, SalProtoRtpAvp, type); + if (!localstream) return; + localconfig = &localstream->rtcp_xr; + remotestream = sal_media_description_find_stream(sal_call_get_remote_media_description(call->op), SalProtoRtpSavp, type); + if (!remotestream) remotestream = sal_media_description_find_stream(sal_call_get_remote_media_description(call->op), SalProtoRtpAvp, type); + if (!remotestream) return; + remoteconfig = &remotestream->rtcp_xr; + + if (localstream->dir == SalStreamInactive) return; + else if (localstream->dir == SalStreamRecvOnly) { + /* Use local config for unilateral parameters and remote config for collaborative parameters. */ + memcpy(¤tconfig, localconfig, sizeof(currentconfig)); + currentconfig.rcvr_rtt_mode = remoteconfig->rcvr_rtt_mode; + currentconfig.rcvr_rtt_max_size = remoteconfig->rcvr_rtt_max_size; + } else { + memcpy(¤tconfig, remoteconfig, sizeof(currentconfig)); + } + if (type == SalAudio) { + session = call->audiostream->ms.session; + } else { + session = call->videostream->ms.session; + } + rtp_session_configure_rtcp_xr(session, ¤tconfig); + if (currentconfig.rcvr_rtt_mode != OrtpRtcpXrRcvrRttNone) { rtp_session_set_rtcp_xr_rcvr_rtt_interval(session, lp_config_get_int(lc->config, "rtp", "rtcp_xr_rcvr_rtt_interval_duration", 5000)); } - if (config->stat_summary_enabled == TRUE) { + if (currentconfig.stat_summary_enabled == TRUE) { rtp_session_set_rtcp_xr_stat_summary_interval(session, lp_config_get_int(lc->config, "rtp", "rtcp_xr_stat_summary_interval_duration", 5000)); } - if (config->voip_metrics_enabled == TRUE) { + if (currentconfig.voip_metrics_enabled == TRUE) { rtp_session_set_rtcp_xr_voip_metrics_interval(session, lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_interval_duration", 5000)); } } @@ -1825,7 +1855,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna call->audiostream_encrypted=FALSE; } }else call->audiostream_encrypted=FALSE; - configure_rtp_session_for_rtcp_xr(lc, call->audiostream->ms.session, &stream->rtcp_xr); + configure_rtp_session_for_rtcp_xr(lc, call, SalAudio); audio_stream_start_full( call->audiostream, call->audio_profile, @@ -1947,7 +1977,7 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna }else{ call->videostream_encrypted=FALSE; } - configure_rtp_session_for_rtcp_xr(lc, call->videostream->ms.session, &vstream->rtcp_xr); + configure_rtp_session_for_rtcp_xr(lc, call, SalVideo); call->log->video_enabled = TRUE; video_stream_set_direction (call->videostream, dir); From 22e88c8da1ceb8deffdee888ea54d3ae889d3ebf Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 18 Mar 2014 11:51:19 +0100 Subject: [PATCH 08/55] Copy RTCP XR configuration in each streams when creating the local media description. --- coreapi/linphonecall.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index c3864f90e..8568910f7 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -260,6 +260,7 @@ static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){ static void setup_rtcp_xr(LinphoneCall *call, SalMediaDescription *md) { LinphoneCore *lc = call->core; + int i; md->rtcp_xr.enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_enabled", 0); if (md->rtcp_xr.enabled == TRUE) { @@ -276,6 +277,9 @@ static void setup_rtcp_xr(LinphoneCall *call, SalMediaDescription *md) { } md->rtcp_xr.voip_metrics_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_enabled", 0); } + for (i = 0; i < md->n_active_streams; i++) { + memcpy(&md->streams[i].rtcp_xr, &md->rtcp_xr, sizeof(md->streams[i].rtcp_xr)); + } } void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call){ From 0e2446c0b68d1143011921246b1505e17956fdc5 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 18 Mar 2014 16:15:32 +0100 Subject: [PATCH 09/55] Indicate what RTCP packet has been updated in the LinphoneCallStats structure. --- coreapi/linphonecall.c | 4 ++++ coreapi/linphonecore.h | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 8568910f7..d5c0bdf3c 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -2691,6 +2691,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp); call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp = evd->packet; evd->packet = NULL; + call->stats[LINPHONE_CALL_STATS_VIDEO].updated = LinphoneCallStatsReceivedRTCPUpdate; update_local_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO],(MediaStream*)call->videostream); if (lc->vtable.call_stats_updated) lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]); @@ -2700,6 +2701,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp); call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp = evd->packet; evd->packet = NULL; + call->stats[LINPHONE_CALL_STATS_VIDEO].updated = LinphoneCallStatsSentRTCPUpdate; update_local_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO],(MediaStream*)call->videostream); if (lc->vtable.call_stats_updated) lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]); @@ -2734,6 +2736,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp); call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp = evd->packet; evd->packet = NULL; + call->stats[LINPHONE_CALL_STATS_AUDIO].updated = LinphoneCallStatsReceivedRTCPUpdate; update_local_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO],(MediaStream*)call->audiostream); if (lc->vtable.call_stats_updated) lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]); @@ -2743,6 +2746,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp); call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp = evd->packet; evd->packet = NULL; + call->stats[LINPHONE_CALL_STATS_AUDIO].updated = LinphoneCallStatsSentRTCPUpdate; update_local_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO],(MediaStream*)call->audiostream); if (lc->vtable.call_stats_updated) lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]); diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 9d3ecb455..5a303bb19 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -564,6 +564,19 @@ enum _LinphoneUpnpState{ typedef enum _LinphoneUpnpState LinphoneUpnpState; +/** + * Enum describing what has been updated in a LinphoneCallStats object. +**/ +typedef enum _LinphoneCallStatsRTCPUpdate LinphoneCallStatsRTCPUpdate; + +/** + * Enum describing what has been updated in a LinphoneCallStats object. +**/ +enum _LinphoneCallStatsRTCPUpdate { + LinphoneCallStatsReceivedRTCPUpdate, /**< received_rtcp field of LinphoneCallStats object has been updated */ + LinphoneCallStatsSentRTCPUpdate /**< sent_rtcp field of LinphoneCallStats object has been updated */ +}; + /** * The LinphoneCallStats objects carries various statistic informations regarding quality of audio or video streams. * @@ -594,6 +607,7 @@ struct _LinphoneCallStats { float upload_bandwidth; /** Date: Wed, 19 Mar 2014 16:07:40 +0100 Subject: [PATCH 10/55] Update oRTP submodule for RTCP XR. --- oRTP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oRTP b/oRTP index b2e5f313e..c0418933b 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit b2e5f313e6f245588751835ccd01bcd5dc2e8b1e +Subproject commit c0418933b7ce4765993b7304809e43df6ed392dd From 06c9f941132e783656ca6fcd54b8b02db7cbcda6 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Wed, 19 Mar 2014 22:00:16 +0100 Subject: [PATCH 11/55] update ms2 --- mediastreamer2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediastreamer2 b/mediastreamer2 index 9956d3d6e..e858677a1 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 9956d3d6e37a09991b948b1cad8d1382e046b0d1 +Subproject commit e858677a1835ac46823b76d887aba6a7b5b50e44 From 67faeff9a8c2031c0ff27e6b13227fc05653b85f Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 20 Mar 2014 10:36:56 +0100 Subject: [PATCH 12/55] fix proxy config selection: use default proxy config if no matching proxy config is found for a given destination. --- coreapi/linphonecore.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index c4fffd030..38093e7c8 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2526,7 +2526,6 @@ LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const L for (elem=linphone_core_get_proxy_config_list(lc);elem!=NULL;elem=elem->next){ LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data; const char *domain=linphone_proxy_config_get_domain(cfg); -/* ms_warning("Checking %s / %s %s", domain, linphone_address_get_domain(uri), linphone_proxy_config_get_route(cfg)); */ if (domain!=NULL && strcmp(domain,linphone_address_get_domain(uri))==0){ if (linphone_proxy_config_register_enabled(cfg)) { found_cfg=cfg; @@ -2540,7 +2539,7 @@ end: if (!found_cfg && found_noreg_cfg) found_cfg = found_noreg_cfg; if (found_cfg && found_cfg!=default_cfg){ ms_debug("Overriding default proxy setting for this call/message/subscribe operation."); - } + }else if (!found_cfg) found_cfg=default_cfg; /*when no matching proxy config is found, use the default proxy config*/ return found_cfg; } From 904db718b3bc09c7e53dbb183351e9c3a1d0518a Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Thu, 20 Mar 2014 14:16:04 +0100 Subject: [PATCH 13/55] make sure multiple incoming calls with privacy enabled can be handled --- .cproject | 14 ------- coreapi/callbacks.c | 3 +- coreapi/linphonecore.h | 12 +++--- tester/call_tester.c | 94 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 21 deletions(-) diff --git a/.cproject b/.cproject index f20bc862b..45790510b 100644 --- a/.cproject +++ b/.cproject @@ -39,20 +39,6 @@ - - - - - - - - - - - - - - diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index f39700f01..469baf8af 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -206,7 +206,8 @@ static void call_received(SalOp *h){ const char *from,*to; char *alt_contact; LinphoneAddress *from_addr, *to_addr; - bool_t prevent_colliding_calls=lp_config_get_int(lc->config,"sip","prevent_colliding_calls",TRUE); + /*this mode is deprcated because probably useless*/ + bool_t prevent_colliding_calls=lp_config_get_int(lc->config,"sip","prevent_colliding_calls",FALSE); /* first check if we can answer successfully to this invite */ if (linphone_presence_model_get_basic_status(lc->presence_model) == LinphonePresenceBasicStatusClosed) { diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 5a303bb19..2af2d54de 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -563,12 +563,6 @@ enum _LinphoneUpnpState{ **/ typedef enum _LinphoneUpnpState LinphoneUpnpState; - -/** - * Enum describing what has been updated in a LinphoneCallStats object. -**/ -typedef enum _LinphoneCallStatsRTCPUpdate LinphoneCallStatsRTCPUpdate; - /** * Enum describing what has been updated in a LinphoneCallStats object. **/ @@ -577,6 +571,12 @@ enum _LinphoneCallStatsRTCPUpdate { LinphoneCallStatsSentRTCPUpdate /**< sent_rtcp field of LinphoneCallStats object has been updated */ }; +/** + * Enum describing what has been updated in a LinphoneCallStats object. +**/ + +typedef enum _LinphoneCallStatsRTCPUpdate LinphoneCallStatsRTCPUpdate; + /** * The LinphoneCallStats objects carries various statistic informations regarding quality of audio or video streams. * diff --git a/tester/call_tester.c b/tester/call_tester.c index cfb4a7333..3e7f23dda 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -887,7 +887,99 @@ static void call_with_privacy(void) { } +static void call_waiting_indication_with_param(bool_t enable_caller_privacy) { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + LinphoneCoreManager* laure = linphone_core_manager_new( "laure_rc"); + stats initial_marie_stat; + stats initial_pauline_stat; + stats initial_laure_stat; + char hellopath[256]; + MSList *iterator; + LinphoneCall* marie_call_pauline; + LinphoneCall* pauline_called_by_marie; + LinphoneCall* pauline_called_by_laure=NULL; + LinphoneCallParams *laure_params=linphone_core_create_default_call_parameters(laure->lc); + LinphoneCallParams *marie_params=linphone_core_create_default_call_parameters(marie->lc); + if (enable_caller_privacy) + linphone_call_params_set_privacy(marie_params,LinphonePrivacyId); + + MSList* lcs=ms_list_append(NULL,marie->lc); + lcs=ms_list_append(lcs,pauline->lc); + lcs=ms_list_append(lcs,laure->lc); + + CU_ASSERT_TRUE(call_with_caller_params(marie,pauline,marie_params)); + marie_call_pauline=linphone_core_get_current_call(marie->lc); + pauline_called_by_marie=linphone_core_get_current_call(pauline->lc); + + initial_marie_stat=marie->stat; + initial_pauline_stat=pauline->stat; + initial_laure_stat=laure->stat; + + + /*use playfile for callee to avoid locking on capture card*/ + linphone_core_use_files (laure->lc,TRUE); + snprintf(hellopath,sizeof(hellopath), "%s/sounds/hello8000.wav", liblinphone_tester_file_prefix); + linphone_core_set_play_file(laure->lc,hellopath); + if (enable_caller_privacy) + linphone_call_params_set_privacy(laure_params,LinphonePrivacyId); + + CU_ASSERT_PTR_NOT_NULL(linphone_core_invite_address_with_params(laure->lc,pauline->identity,laure_params)); + + CU_ASSERT_TRUE(wait_for(laure->lc + ,pauline->lc + ,&pauline->stat.number_of_LinphoneCallIncomingReceived + ,2)); + + CU_ASSERT_EQUAL(laure->stat.number_of_LinphoneCallOutgoingProgress,1); + + + CU_ASSERT_TRUE(wait_for(laure->lc + ,pauline->lc + ,&laure->stat.number_of_LinphoneCallOutgoingRinging + ,1)); + + for (iterator=(MSList *)linphone_core_get_calls(pauline->lc);iterator!=NULL;iterator=iterator->next) { + LinphoneCall *call=(LinphoneCall *)iterator->data; + if (call != pauline_called_by_marie) { + /*fine, this is the call waiting*/ + linphone_core_accept_call(pauline->lc,pauline_called_by_laure=call); + } + } + + CU_ASSERT_TRUE(wait_for(laure->lc + ,pauline->lc + ,&laure->stat.number_of_LinphoneCallConnected + ,1)); + + CU_ASSERT_TRUE(wait_for(pauline->lc + ,marie->lc + ,&marie->stat.number_of_LinphoneCallPausedByRemote + ,1)); + + if (pauline_called_by_laure && enable_caller_privacy ) + CU_ASSERT_EQUAL(linphone_call_params_get_privacy(linphone_call_get_current_params(pauline_called_by_laure)),LinphonePrivacyId); + + linphone_core_terminate_all_calls(pauline->lc); + + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallEnd,1,2000)); + + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); + ms_list_free(lcs); +} +static void call_waiting_indication(void) { + call_waiting_indication_with_param(FALSE); +} + +static void call_waiting_indication_with_privacy(void) { + call_waiting_indication_with_param(TRUE); +} static void simple_conference(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); @@ -1721,6 +1813,8 @@ test_t call_tests[] = { { "Call rejected because of wrong credential", call_rejected_because_wrong_credentials}, { "Call rejected without 403 because of wrong credential", call_rejected_without_403_because_wrong_credentials}, { "Call rejected without 403 because of wrong credential and no auth req cb", call_rejected_without_403_because_wrong_credentials_no_auth_req_cb}, + { "Call waiting indication", call_waiting_indication }, + { "Call waiting indication with privacy", call_waiting_indication_with_privacy }, { "Simple conference", simple_conference }, { "Simple call transfer", simple_call_transfer }, { "Unattended call transfer", unattended_call_transfer }, From 4d6894901eccaa611eec33f83ca8ea62dc878455 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 20 Mar 2014 16:25:15 +0100 Subject: [PATCH 14/55] remove unused variable and update ms2 --- coreapi/misc.c | 2 +- mediastreamer2 | 2 +- tester/call_tester.c | 9 --------- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/coreapi/misc.c b/coreapi/misc.c index b2dd6774e..e87544502 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -1308,7 +1308,7 @@ int linphone_core_migrate_to_multi_transport(LinphoneCore *lc){ newtp.udp_port=port; newtp.tcp_port=port; newtp.tls_port=LC_SIP_TRANSPORT_RANDOM; - lp_config_set_string(lc->config, "sip","sip_random_port",NULL); //remove + lp_config_set_string(lc->config, "sip","sip_random_port",NULL); /*remove*/ linphone_core_set_sip_transports(lc,&newtp); } lp_config_set_int(lc->config,"sip","multi_transport_migration_done",1); diff --git a/mediastreamer2 b/mediastreamer2 index e858677a1..aceebbf52 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit e858677a1835ac46823b76d887aba6a7b5b50e44 +Subproject commit aceebbf52fd94430c1aa17941f3d184be97a5b34 diff --git a/tester/call_tester.c b/tester/call_tester.c index 3e7f23dda..515c7980e 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -891,12 +891,8 @@ static void call_waiting_indication_with_param(bool_t enable_caller_privacy) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); LinphoneCoreManager* laure = linphone_core_manager_new( "laure_rc"); - stats initial_marie_stat; - stats initial_pauline_stat; - stats initial_laure_stat; char hellopath[256]; MSList *iterator; - LinphoneCall* marie_call_pauline; LinphoneCall* pauline_called_by_marie; LinphoneCall* pauline_called_by_laure=NULL; LinphoneCallParams *laure_params=linphone_core_create_default_call_parameters(laure->lc); @@ -910,13 +906,8 @@ static void call_waiting_indication_with_param(bool_t enable_caller_privacy) { lcs=ms_list_append(lcs,laure->lc); CU_ASSERT_TRUE(call_with_caller_params(marie,pauline,marie_params)); - marie_call_pauline=linphone_core_get_current_call(marie->lc); pauline_called_by_marie=linphone_core_get_current_call(pauline->lc); - initial_marie_stat=marie->stat; - initial_pauline_stat=pauline->stat; - initial_laure_stat=laure->stat; - /*use playfile for callee to avoid locking on capture card*/ linphone_core_use_files (laure->lc,TRUE); From 90733896412b6f0dbc7808cbfda0edb5b1f5833b Mon Sep 17 00:00:00 2001 From: Margaux Clerc Date: Fri, 21 Mar 2014 14:44:05 +0100 Subject: [PATCH 15/55] Add audio assistant Fix wizard bug --- gtk/Makefile.am | 4 +- gtk/audio_assistant.c | 461 +++++++++++++++++++++++++++++++++++++++++ gtk/audio_assistant.ui | 21 ++ gtk/incall_view.c | 7 - gtk/linphone.h | 29 ++- gtk/main.c | 20 +- gtk/main.ui | 129 +++++++----- gtk/propertybox.c | 8 +- gtk/setupwizard.c | 3 +- gtk/singleinstance.c | 31 ++- 10 files changed, 629 insertions(+), 84 deletions(-) create mode 100644 gtk/audio_assistant.c create mode 100644 gtk/audio_assistant.ui diff --git a/gtk/Makefile.am b/gtk/Makefile.am index c612ff07d..0daee4a7d 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -14,7 +14,8 @@ UI_FILES= about.ui \ call_statistics.ui \ ldap.ui \ config-uri.ui \ - provisioning-fetch.ui + provisioning-fetch.ui \ + audio_assistant.ui PIXMAPS= \ stock_people.png @@ -52,6 +53,7 @@ linphone_SOURCES= \ singleinstance.c \ conference.c \ config-fetching.c \ + audio_assistant.c \ linphone.h if BUILD_WIZARD linphone_SOURCES+= \ diff --git a/gtk/audio_assistant.c b/gtk/audio_assistant.c new file mode 100644 index 000000000..a9ecdd1bb --- /dev/null +++ b/gtk/audio_assistant.c @@ -0,0 +1,461 @@ +/* +linphone, gtk-glade interface. +Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include + +#include "linphone.h" +#include "linphonecore_utils.h" +#include "mediastreamer2/mediastream.h" +#include "mediastreamer2/msvolume.h" + +static GtkWidget *audio_assistant=NULL; + +GtkWidget *get_widget_from_assistant(const char *name){ + return (GtkWidget *)g_object_get_data(G_OBJECT(audio_assistant),name); +} +void set_widget_to_assistant(const char *name,GtkWidget *w){ + g_object_set_data(G_OBJECT(audio_assistant),name,w); +} + +void update_record_button(gboolean is_visible){ + GtkWidget *rec_button = get_widget_from_assistant("rec_button"); + gtk_widget_set_sensitive(rec_button,is_visible); +} + +void activate_record_button(gboolean is_active){ + GtkWidget *rec_button = get_widget_from_assistant("rec_button"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rec_button),is_active); +} + +void update_play_button(gboolean is_visible){ + GtkWidget *play_button = get_widget_from_assistant("play_button"); + gtk_widget_set_sensitive(play_button,is_visible); +} + +void activate_play_button(gboolean is_active){ + GtkWidget *play_button = get_widget_from_assistant("play_button"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(play_button),is_active); +} + + + +gchar *get_record_file(){ + char filename[256]={0}; + char date[64]={0}; + time_t curtime=time(NULL); + struct tm loctime; + + #ifdef WIN32 + loctime=*localtime(&curtime); + #else + localtime_r(&curtime,&loctime); + #endif + snprintf(date,sizeof(date)-1,"%i%02i%02i-%02i%02i%2i",loctime.tm_year+1900,loctime.tm_mon+1,loctime.tm_mday, loctime.tm_hour, loctime.tm_min, loctime.tm_sec); + + snprintf(filename,sizeof(filename)-1,"record-%s.wav",date); + return g_build_path(G_DIR_SEPARATOR_S,g_get_tmp_dir(),filename,NULL);; +} + +float audio_stream_get_record_volume(AudioStream *st){ + if (st && st->volsend){ + float vol=0; + ms_filter_call_method(st->volsend,MS_VOLUME_GET,&vol); + return vol; + } + return LINPHONE_VOLUME_DB_LOWEST; +} + +float audio_stream_get_max_volume(AudioStream *st){ + if (st && st->volsend){ + float vol=0; + ms_filter_call_method(st->volsend,MS_VOLUME_GET_MAX,&vol); + return vol; + } + return LINPHONE_VOLUME_DB_LOWEST; +} + +static gboolean update_audio_label(volume_ctx_t *ctx){ + float volume_db=ctx->get_volume(ctx->data); + gchar *result; + if (volume_db < -30) result = "No Voice"; + if (volume_db > -30 && volume_db < -15) result = "Low"; + if (volume_db > -15 && volume_db < 0) result = "Good"; + if (volume_db > 0) result = "Too loud"; + //g_message("volume_db=%f, frac=%f",volume_db,frac); + gtk_label_set_text(GTK_LABEL(ctx->widget),result); + return TRUE; +} + +static void on_audio_label_destroy(guint task_id){ + g_source_remove(task_id); +} + +void linphone_gtk_init_audio_label(GtkWidget *w, get_volume_t get_volume, void *data){ + guint task_id=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"task_id_t")); + if (task_id==0){ + volume_ctx_t *ctx=g_new(volume_ctx_t,1); + ctx->widget=w; + ctx->get_volume=get_volume; + ctx->data=data; + ctx->last_value=0; + g_object_set_data_full(G_OBJECT(w),"ctx_t",ctx,g_free); + task_id=g_timeout_add(200,(GSourceFunc)update_audio_label,ctx); + g_object_set_data_full(G_OBJECT(w),"task_id_t",GINT_TO_POINTER(task_id),(GDestroyNotify)on_audio_label_destroy); + } +} + +void linphone_gtk_uninit_audio_label(GtkWidget *w){ + guint task_id=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"task_id_t")); + if (task_id!=0){ + g_object_set_data(G_OBJECT(w),"ctx_t",NULL); + g_object_set_data(G_OBJECT(w),"task_id_t",NULL); + } +} + +void playback_device_changed(GtkWidget *w){ + gchar *sel=gtk_combo_box_get_active_text(GTK_COMBO_BOX(w)); + linphone_core_set_playback_device(linphone_gtk_get_core(),sel); + g_free(sel); +} + +void capture_device_changed(GtkWidget *capture_device){ + gchar *sel; + GtkWidget *mic_audiolevel; + AudioStream *audio_stream; + + mic_audiolevel = get_widget_from_assistant("mic_audiolevel"); + audio_stream = (AudioStream *) g_object_get_data(G_OBJECT(capture_device),"audio_stream"); + sel = gtk_combo_box_get_active_text(GTK_COMBO_BOX(capture_device)); + linphone_core_set_capture_device(linphone_gtk_get_core(),sel); + linphone_gtk_uninit_audio_meter(mic_audiolevel); + audio_stream_stop(audio_stream); + linphone_gtk_init_audio_meter(mic_audiolevel,(get_volume_t)audio_stream_get_record_volume,audio_stream); + + g_free(sel); +} + +static void dialog_click(GtkWidget *dialog, guint response_id, GtkWidget *page){ + switch(response_id){ + case GTK_RESPONSE_YES: + gtk_assistant_set_page_complete(GTK_ASSISTANT(audio_assistant),page,TRUE); + break; + default: + break; + } + gtk_widget_destroy(dialog); +} + +static void calibration_finished(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay, void *data){ + ms_message("echo calibration finished %s.",status==LinphoneEcCalibratorDone ? "successfully" : "with faillure"); + if (status==LinphoneEcCalibratorDone) ms_message("Measured delay is %i",delay); + + GtkWidget * dialog; + GtkWidget *speaker_page = get_widget_from_assistant("speaker_page"); + + dialog = gtk_message_dialog_new ( + GTK_WINDOW(audio_assistant), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_YES_NO, + "%s","Did you hear three beeps ?"); + + g_signal_connect(G_OBJECT (dialog), "response", + G_CALLBACK (dialog_click),speaker_page); + gtk_widget_show(dialog); +} + +void linphone_gtk_start_sound(GtkWidget *w){ + LinphoneCore *lc = linphone_gtk_get_core(); + linphone_core_start_echo_calibration(lc,calibration_finished,NULL,NULL,NULL); +} + +static gboolean linphone_gtk_stop_record(gpointer data){ + AudioStream *stream = (AudioStream *)g_object_get_data(G_OBJECT(audio_assistant),"record_stream"); + if(stream != NULL){ + audio_stream_stop(stream); + g_object_set_data(G_OBJECT(audio_assistant),"record_stream",NULL); + } + update_record_button(FALSE); + update_play_button(TRUE); + return FALSE; +} + + +void linphone_gtk_start_record_sound(GtkWidget *w, gpointer data){ + LinphoneCore *lc = linphone_gtk_get_core(); + AudioStream *stream = NULL; + MSSndCardManager *manager = ms_snd_card_manager_get(); + gboolean active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); + + if(active){ + gchar *path = get_record_file(); + stream=audio_stream_new(8888, 8889, FALSE); + if(stream != NULL){ + audio_stream_start_full(stream,&av_profile,"127.0.0.1",8888,"127.0.0.1",8889,0,0,NULL, + path,NULL,ms_snd_card_manager_get_card(manager,linphone_core_get_capture_device(lc)),FALSE); + g_object_set_data(G_OBJECT(audio_assistant),"record_stream",stream); + } + gint timeout_id = gtk_timeout_add(6000,(GtkFunction)linphone_gtk_stop_record,NULL); + g_object_set_data(G_OBJECT(audio_assistant),"timeout_id",GINT_TO_POINTER(timeout_id)); + g_object_set_data(G_OBJECT(audio_assistant),"path",path); + } else { + stream = (AudioStream *)g_object_get_data(G_OBJECT(audio_assistant),"record_stream"); + gint timeout_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(audio_assistant),"timeout_id")); + gtk_timeout_remove(timeout_id); + if(stream != NULL){ + audio_stream_stop(stream); + g_object_set_data(G_OBJECT(audio_assistant),"record_stream",NULL); + } + update_record_button(FALSE); + update_play_button(TRUE); + } +} + +static void endoffile_cb(void *ud, MSFilter *f, unsigned int ev,void * arg){ + switch (ev) { + case MS_PLAYER_EOF: { + ms_message("EndOfFile received"); + activate_play_button(FALSE); + break; + } + break; + } +} + +void linphone_gtk_start_play_record_sound(GtkWidget *w,gpointer data){ + LinphoneCore *lc = linphone_gtk_get_core(); + gboolean active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); + AudioStream *stream = NULL; + MSSndCardManager *manager = ms_snd_card_manager_get(); + + if(active){ + gchar *path = g_object_get_data(G_OBJECT(audio_assistant),"path"); + stream=audio_stream_new(8888, 8889, FALSE); + if(path != NULL){ + audio_stream_start_full(stream,&av_profile,"127.0.0.1",8888,"127.0.0.1",8889,0,0,path, + NULL,ms_snd_card_manager_get_card(manager,linphone_core_get_playback_device(lc)),NULL,FALSE); + ms_filter_add_notify_callback(stream->soundread,endoffile_cb,stream,FALSE); + g_object_set_data(G_OBJECT(audio_assistant),"play_stream",stream); + } + } else { + stream = (AudioStream *)g_object_get_data(G_OBJECT(audio_assistant),"play_stream"); + if(stream != NULL){ + audio_stream_stop(stream); + g_object_set_data(G_OBJECT(audio_assistant),"play_stream",NULL); + } + } +} + +static GtkWidget *create_intro(){ + GtkWidget *vbox=gtk_vbox_new(FALSE,2); + GtkWidget *label=gtk_label_new(_("Welcome !\nThis assistant will help you to configure audio settings for Linphone")); + gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 2); + gtk_widget_show_all(vbox); + return vbox; +} + +static GtkWidget *create_mic_page(){ + GtkWidget *vbox=gtk_table_new(3,2,FALSE); + LinphoneCore *lc=linphone_gtk_get_core(); + + GtkWidget *labelMicChoice=gtk_label_new(_("Capture device")); + GtkWidget *labelMicLevel=gtk_label_new(_("Recorded volume")); + GtkWidget *mic_audiolevel=gtk_progress_bar_new(); + GtkWidget *capture_device=gtk_combo_box_new(); + GtkWidget *box = gtk_vbox_new(FALSE,0); + GtkWidget *label_audiolevel=gtk_label_new(_("No voice")); + + gtk_box_pack_start(GTK_BOX(box),mic_audiolevel,TRUE,TRUE,1); + gtk_box_pack_start(GTK_BOX(box),label_audiolevel,FALSE,FALSE,1); + + gtk_table_attach_defaults(GTK_TABLE(vbox), labelMicChoice, 0, 1, 0, 1); + gtk_table_attach_defaults(GTK_TABLE(vbox), capture_device, 1, 2, 0, 1); + gtk_table_attach_defaults(GTK_TABLE(vbox), labelMicLevel, 0, 1, 1, 2); + gtk_table_attach_defaults(GTK_TABLE(vbox), box, 1, 2, 1, 2); + + gtk_table_set_row_spacings(GTK_TABLE(vbox),10); + + set_widget_to_assistant("mic_audiolevel",mic_audiolevel); + set_widget_to_assistant("label_audiolevel",label_audiolevel); + + const char **sound_devices=linphone_core_get_sound_devices(lc); + linphone_gtk_fill_combo_box(capture_device, sound_devices, + linphone_core_get_capture_device(lc), CAP_CAPTURE); + gtk_widget_show_all(vbox); + + g_signal_connect(G_OBJECT(capture_device),"changed",(GCallback)capture_device_changed,capture_device); + + return vbox; +} + +static GtkWidget *create_speaker_page(){ + GtkWidget *vbox=gtk_table_new(2,2,FALSE); + LinphoneCore *lc=linphone_gtk_get_core(); + + GtkWidget *labelSpeakerChoice=gtk_label_new(_("Playback device")); + GtkWidget *labelSpeakerLevel=gtk_label_new(_("Play three beeps")); + GtkWidget *spk_button=gtk_button_new_from_stock(GTK_STOCK_MEDIA_PLAY); + GtkWidget *playback_device=gtk_combo_box_new(); + + gtk_table_attach_defaults(GTK_TABLE(vbox), labelSpeakerChoice, 0, 1, 0, 1); + gtk_table_attach_defaults(GTK_TABLE(vbox), playback_device, 1, 2, 0, 1); + gtk_table_attach_defaults(GTK_TABLE(vbox), labelSpeakerLevel, 0, 1, 1, 2); + gtk_table_attach(GTK_TABLE(vbox), spk_button, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0,0); + + gtk_table_set_row_spacings(GTK_TABLE(vbox),10); + + const char **sound_devices=linphone_core_get_sound_devices(lc); + linphone_gtk_fill_combo_box(playback_device, sound_devices, + linphone_core_get_playback_device(lc),CAP_PLAYBACK); + gtk_widget_show_all(vbox); + + set_widget_to_assistant("speaker_page",vbox); + g_signal_connect(G_OBJECT(playback_device),"changed",(GCallback)playback_device_changed,playback_device); + g_signal_connect(G_OBJECT(spk_button),"clicked",(GCallback)linphone_gtk_start_sound,vbox); + + return vbox; +} + +static GtkWidget *create_play_record_page(){ + GtkWidget *vbox=gtk_table_new(2,2,FALSE); + GtkWidget *labelRecord=gtk_label_new(_("Press the record button and say some words")); + GtkWidget *labelPlay=gtk_label_new(_("Listen to your record voice")); + GtkWidget *rec_button=gtk_toggle_button_new_with_label("Record"); + GtkWidget *play_button=gtk_toggle_button_new_with_label("Play"); + GtkWidget *image; + + image=gtk_image_new_from_stock(GTK_STOCK_MEDIA_RECORD,GTK_ICON_SIZE_MENU); + gtk_button_set_image(GTK_BUTTON(rec_button),image); + + image=gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY,GTK_ICON_SIZE_MENU); + gtk_button_set_image(GTK_BUTTON(play_button),image); + gtk_widget_set_sensitive(play_button,FALSE); + + gtk_table_attach_defaults(GTK_TABLE(vbox), labelRecord, 0, 1, 0, 1); + gtk_table_attach(GTK_TABLE(vbox), rec_button, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0,0); + gtk_table_attach_defaults(GTK_TABLE(vbox), labelPlay, 0, 1, 1, 2); + gtk_table_attach(GTK_TABLE(vbox), play_button, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0,0); + + gtk_widget_show_all(vbox); + + set_widget_to_assistant("rec_button",rec_button); + set_widget_to_assistant("play_button",play_button); + g_signal_connect(G_OBJECT(rec_button),"toggled",(GCallback)linphone_gtk_start_record_sound,vbox); + g_signal_connect(G_OBJECT(play_button),"toggled",(GCallback)linphone_gtk_start_play_record_sound,vbox); + + return vbox; +} + +static GtkWidget *create_end_page(){ + GtkWidget *vbox=gtk_vbox_new(FALSE,2); + GtkWidget *label=gtk_label_new(_("Let's start Linphone now")); + gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 2); + gtk_widget_show_all(vbox); + return vbox; +} + +static void prepare(GtkAssistant *w, GtkWidget *p, void * data){ + AudioStream *audio_stream = NULL; + LinphoneCore *lc=linphone_gtk_get_core(); + int page = gtk_assistant_get_current_page(w); + GtkWidget *mic_audiolevel = get_widget_from_assistant("mic_audiolevel"); + GtkWidget *label_audiolevel = get_widget_from_assistant("label_audiolevel"); + + //Speaker page + if(page == 1){ + MSSndCardManager *manager = ms_snd_card_manager_get(); + audio_stream = audio_stream_start_with_sndcards(&av_profile,9897,"127.0.0.1",9898,0,0,ms_snd_card_manager_get_card(manager,linphone_core_get_playback_device(lc)),ms_snd_card_manager_get_card(manager,linphone_core_get_capture_device(lc)),FALSE); + if(mic_audiolevel != NULL && audio_stream != NULL){ + g_object_set_data(G_OBJECT(audio_assistant),"stream",audio_stream); + linphone_gtk_init_audio_meter(mic_audiolevel,(get_volume_t)audio_stream_get_record_volume,audio_stream); + linphone_gtk_init_audio_label(label_audiolevel,(get_volume_t)audio_stream_get_max_volume,audio_stream); + } + + + } else if(page == 2 || page == 0){ + if(mic_audiolevel != NULL && label_audiolevel != NULL){ + audio_stream = (AudioStream *)g_object_get_data(G_OBJECT(audio_assistant),"stream"); + if(audio_stream != NULL){ + linphone_gtk_uninit_audio_meter(mic_audiolevel); + linphone_gtk_uninit_audio_label(label_audiolevel); + audio_stream_stop(audio_stream); + g_object_set_data(G_OBJECT(audio_assistant),"stream",NULL); + } + } + } +} + +void linphone_gtk_close_audio_assistant(GtkWidget *w){ + gchar *path = g_object_get_data(G_OBJECT(audio_assistant),"path"); + g_unlink(path); + gtk_widget_destroy(w); + audio_assistant = NULL; + linphone_gtk_show_main_window(); +} + +void linphone_gtk_audio_assistant_apply(GtkWidget *w){ + linphone_gtk_close_audio_assistant(w); +} + +void linphone_gtk_show_audio_assistant(void){ + GtkWidget *w; + if(audio_assistant!=NULL) + return; + w=audio_assistant=linphone_gtk_create_window("audio_assistant"); + + gtk_window_set_resizable (GTK_WINDOW(w), FALSE); + gtk_window_set_title(GTK_WINDOW(w),_("Audio Assistant")); + + GtkWidget *welcome=create_intro(); + GtkWidget *mic_page=create_mic_page(); + GtkWidget *speaker_page=create_speaker_page(); + GtkWidget *play_record_page=create_play_record_page(); + GtkWidget *end_page=create_end_page(); + + gtk_assistant_append_page(GTK_ASSISTANT(w),welcome); + gtk_assistant_set_page_type(GTK_ASSISTANT(w),welcome,GTK_ASSISTANT_PAGE_INTRO); + gtk_assistant_set_page_title(GTK_ASSISTANT(w),welcome,_("Audio assistant")); + gtk_assistant_set_page_complete(GTK_ASSISTANT(w),welcome,TRUE); + + gtk_assistant_append_page(GTK_ASSISTANT(w),mic_page); + gtk_assistant_set_page_type(GTK_ASSISTANT(w),mic_page,GTK_ASSISTANT_PAGE_CONTENT); + gtk_assistant_set_page_title(GTK_ASSISTANT(w),mic_page,_("Mic Gain calibration")); + gtk_assistant_set_page_complete(GTK_ASSISTANT(w),mic_page,TRUE); + + gtk_assistant_append_page(GTK_ASSISTANT(w),speaker_page); + gtk_assistant_set_page_type(GTK_ASSISTANT(w),speaker_page,GTK_ASSISTANT_PAGE_CONTENT); + gtk_assistant_set_page_complete(GTK_ASSISTANT(w),speaker_page,FALSE); + gtk_assistant_set_page_title(GTK_ASSISTANT(w),speaker_page,_("Speaker volume calibration")); + + gtk_assistant_append_page(GTK_ASSISTANT(w),play_record_page); + gtk_assistant_set_page_type(GTK_ASSISTANT(w),play_record_page,GTK_ASSISTANT_PAGE_CONTENT); + gtk_assistant_set_page_complete(GTK_ASSISTANT(w),play_record_page,TRUE); + gtk_assistant_set_page_title(GTK_ASSISTANT(w),play_record_page,_("Record and Play")); + + gtk_assistant_append_page(GTK_ASSISTANT(w),end_page); + gtk_assistant_set_page_type(GTK_ASSISTANT(w),end_page,GTK_ASSISTANT_PAGE_SUMMARY); + gtk_assistant_set_page_complete(GTK_ASSISTANT(w),end_page,TRUE); + gtk_assistant_set_page_title(GTK_ASSISTANT(w),end_page,_("Terminating")); + + g_signal_connect(G_OBJECT(w),"close",(GCallback)linphone_gtk_close_audio_assistant,w); + g_signal_connect(G_OBJECT(w),"cancel",(GCallback)linphone_gtk_close_audio_assistant,w); + g_signal_connect(G_OBJECT(w),"prepare",(GCallback)prepare,NULL); + + gtk_widget_show(w); +} diff --git a/gtk/audio_assistant.ui b/gtk/audio_assistant.ui new file mode 100644 index 000000000..4fa0588c5 --- /dev/null +++ b/gtk/audio_assistant.ui @@ -0,0 +1,21 @@ + + + + + + False + 12 + + + + + + + + + + + + + + diff --git a/gtk/incall_view.c b/gtk/incall_view.c index 8f96cfb27..bdf54ec24 100644 --- a/gtk/incall_view.c +++ b/gtk/incall_view.c @@ -567,13 +567,6 @@ static gboolean linphone_gtk_in_call_view_refresh(LinphoneCall *call){ return TRUE; } -typedef struct _volume_ctx{ - GtkWidget *widget; - get_volume_t get_volume; - void *data; - float last_value; -}volume_ctx_t; - #define UNSIGNIFICANT_VOLUME (-26) #define SMOOTH 0.15 diff --git a/gtk/linphone.h b/gtk/linphone.h index e1df87ab3..910981a53 100644 --- a/gtk/linphone.h +++ b/gtk/linphone.h @@ -53,6 +53,27 @@ enum { COMPLETION_LDAP }; +typedef float (*get_volume_t)(void *data); + +typedef struct _volume_ctx{ + GtkWidget *widget; + get_volume_t get_volume; + void *data; + float last_value; +}volume_ctx_t; + +typedef enum { + CAP_IGNORE, + CAP_PLAYBACK, + CAP_CAPTURE +}DeviceCap; + +enum { + START_LINPHONE, + START_AUDIO_ASSISTANT, + START_LINPHONE_WITH_CALL +}; + GdkPixbuf * create_pixbuf(const gchar *filename); GdkPixbufAnimation *create_pixbuf_animation(const gchar *filename); void add_pixmap_directory(const gchar *directory); @@ -96,7 +117,6 @@ LinphoneLDAPContactProvider* linphone_gtk_get_ldap(void); void linphone_gtk_set_ldap(LinphoneLDAPContactProvider* ldap); int linphone_gtk_is_ldap_supported(void); - void linphone_gtk_open_browser(const char *url); void linphone_gtk_check_for_new_version(void); const char *linphone_gtk_get_lang(const char *config_file); @@ -150,8 +170,8 @@ void linphone_gtk_unset_from_conference(LinphoneCall *call); void linphone_gtk_terminate_conference_participant(LinphoneCall *call); void linphone_gtk_in_call_view_show_encryption(LinphoneCall *call); void linphone_gtk_update_video_button(LinphoneCall *call); -typedef float (*get_volume_t)(void *data); void linphone_gtk_init_audio_meter(GtkWidget *w, get_volume_t get_volume, void *data); +void linphone_gtk_uninit_audio_meter(GtkWidget *w); void linphone_gtk_show_login_frame(LinphoneProxyConfig *cfg, gboolean disable_auto_login); void linphone_gtk_exit_login_frame(void); @@ -159,14 +179,17 @@ void linphone_gtk_set_ui_config(const char *key, const char *value); void linphone_gtk_log_uninit(); -bool_t linphone_gtk_init_instance(const char *app_name, const char *addr_to_call); +bool_t linphone_gtk_init_instance(const char *app_name, int option, const char *addr_to_call); void linphone_gtk_uninit_instance(void); void linphone_gtk_monitor_usb(void); void linphone_gtk_unmonitor_usb(void); +void linphone_gtk_fill_combo_box(GtkWidget *combo, const char **devices, const char *selected, DeviceCap cap); gchar *linphone_gtk_get_record_path(const LinphoneAddress *address, gboolean is_conference); void linphone_gtk_schedule_restart(void); +void linphone_gtk_show_audio_assistant(void); + void linphone_gtk_set_configuration_uri(void); GtkWidget * linphone_gtk_show_config_fetching(void); void linphone_gtk_close_config_fetching(GtkWidget *w, LinphoneConfiguringState state); diff --git a/gtk/main.c b/gtk/main.c index f40acb8b6..347abafce 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -86,8 +86,10 @@ static gboolean verbose=0; static gboolean quit_done=FALSE; static gboolean auto_answer = 0; static gchar * addr_to_call = NULL; +static int start_option = START_LINPHONE; static gboolean no_video=FALSE; static gboolean iconified=FALSE; +static gboolean run_audio_assistant=FALSE; static gchar *workingdir=NULL; static char *progpath=NULL; gchar *linphone_logfile=NULL; @@ -153,6 +155,13 @@ static GOptionEntry linphone_options[]={ .arg_data = (gpointer) &custom_config_file, .description = N_("Configuration file") }, + { + .long_name = "run-audio-assistant", + .short_name = '\0', + .arg = G_OPTION_ARG_NONE, + .arg_data = (gpointer) &run_audio_assistant, + .description = N_("Run the audio assistant") + }, {0} }; @@ -2136,6 +2145,11 @@ static void linphone_gtk_init_ui(void){ } #endif + if(run_audio_assistant){ + linphone_gtk_show_audio_assistant(); + start_option=START_AUDIO_ASSISTANT; + iconified = TRUE; + } #ifndef HAVE_GTK_OSX linphone_gtk_init_status_icon(); #endif @@ -2168,7 +2182,6 @@ int main(int argc, char *argv[]){ config_file=linphone_gtk_get_config_file(NULL); - #ifdef WIN32 /*workaround for windows: sometimes LANG is defined to an integer value, not understood by gtk */ if ((lang=getenv("LANG"))!=NULL){ @@ -2226,6 +2239,9 @@ int main(int argc, char *argv[]){ } config_file=linphone_gtk_get_config_file(custom_config_file); + if(run_audio_assistant) start_option=START_AUDIO_ASSISTANT; + if(addr_to_call != NULL) start_option=START_LINPHONE_WITH_CALL; + settings=gtk_settings_get_default(); g_type_class_unref (g_type_class_ref (GTK_TYPE_IMAGE_MENU_ITEM)); g_type_class_unref (g_type_class_ref (GTK_TYPE_BUTTON)); @@ -2275,7 +2291,7 @@ int main(int argc, char *argv[]){ #endif core_start: - if (linphone_gtk_init_instance(app_name, addr_to_call) == FALSE){ + if (linphone_gtk_init_instance(app_name, start_option, addr_to_call) == FALSE){ g_warning("Another running instance of linphone has been detected. It has been woken-up."); g_warning("This instance is going to exit now."); gdk_threads_leave(); diff --git a/gtk/main.ui b/gtk/main.ui index 8be5b3555..44750d572 100644 --- a/gtk/main.ui +++ b/gtk/main.ui @@ -786,6 +786,12 @@ False gtk-add + + True + False + 0.49000000953674316 + gtk-properties + True False @@ -821,6 +827,59 @@ False gtk-add + + + + + + + + All users + + + Online users + + + + + + + + + + + ADSL + + + Fiber Channel + + + + + + + + + + + Default + + + + + + + + + + + ADSL + + + Fiber Channel + + + False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK @@ -991,6 +1050,17 @@ + + + Audio assistant + True + False + False + image21 + False + + + @@ -1733,9 +1803,6 @@ 5 - - - False @@ -1762,6 +1829,9 @@ 3 + + + @@ -1881,59 +1951,6 @@ - - - - - - - - All users - - - Online users - - - - - - - - - - - ADSL - - - Fiber Channel - - - - - - - - - - - Default - - - - - - - - - - - ADSL - - - Fiber Channel - - - True False diff --git a/gtk/propertybox.c b/gtk/propertybox.c index b2b54715f..494f1a5fb 100644 --- a/gtk/propertybox.c +++ b/gtk/propertybox.c @@ -21,13 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "linphone_tunnel.h" #include "lpconfig.h" -typedef enum { - CAP_IGNORE, - CAP_PLAYBACK, - CAP_CAPTURE -}DeviceCap; - -static void linphone_gtk_fill_combo_box(GtkWidget *combo, const char **devices, const char *selected, DeviceCap cap){ +void linphone_gtk_fill_combo_box(GtkWidget *combo, const char **devices, const char *selected, DeviceCap cap){ const char **p=devices; int i=0,active=-1; GtkTreeModel *model; diff --git a/gtk/setupwizard.c b/gtk/setupwizard.c index b418b7104..27f7363b7 100644 --- a/gtk/setupwizard.c +++ b/gtk/setupwizard.c @@ -81,7 +81,7 @@ static void linphone_account_informations_changed(GtkEntry *entry, GtkWidget *w) GtkEntry* username = GTK_ENTRY(g_object_get_data(G_OBJECT(w),"username")); gtk_assistant_set_page_complete(GTK_ASSISTANT(assistant),w, - gtk_entry_get_text_length(username) >= LOGIN_MIN_SIZE); + gtk_entry_get_text_length(username) > 0); } static GtkWidget *create_linphone_account_informations_page() { @@ -453,6 +453,7 @@ static void linphone_gtk_assistant_prepare(GtkWidget *assistant, GtkWidget *page static gint destroy_assistant(GtkWidget* w){ gtk_widget_destroy(w); + the_assistant = NULL; return FALSE; } diff --git a/gtk/singleinstance.c b/gtk/singleinstance.c index 5bb70c002..e78f6ac6a 100644 --- a/gtk/singleinstance.c +++ b/gtk/singleinstance.c @@ -33,11 +33,26 @@ gchar *make_name(const char *appname){ return g_strdup(appname); } -static gboolean execute_wakeup(char *uri){ - linphone_gtk_show_main_window(); - if (strlen(uri)>0) - linphone_gtk_refer_received(linphone_gtk_get_core(),uri); - g_free(uri); +static gboolean execute_wakeup(char *buf){ + char uri[255]={0}; + int option; + + if (strlen(buf)>1) sscanf(buf,"%i%s",&option,uri); + else sscanf(buf,"%i",&option); + + switch(option){ + case START_LINPHONE: + linphone_gtk_show_main_window(); + break; + case START_AUDIO_ASSISTANT: + linphone_gtk_show_audio_assistant(); + break; + case START_LINPHONE_WITH_CALL: + linphone_gtk_refer_received(linphone_gtk_get_core(),uri); + break; + }; + + g_free(buf); return FALSE; } @@ -71,14 +86,16 @@ static void linphone_gtk_init_pipe(const char *name){ ms_thread_create(&pipe_thread,NULL,server_pipe_thread,NULL); } -bool_t linphone_gtk_init_instance(const char *app_name, const char *addr_to_call){ +bool_t linphone_gtk_init_instance(const char *app_name, int option, const char *addr_to_call){ pipe_name=make_name(app_name); ortp_pipe_t p=ortp_client_pipe_connect(pipe_name); if (p!=(ortp_pipe_t)-1){ uint8_t buf[256]={0}; g_message("There is already a running instance."); if (addr_to_call!=NULL){ - strncpy((char*)buf,addr_to_call,sizeof(buf)-1); + sprintf((char *)buf,"%i%s",option,addr_to_call); + } else { + sprintf((char *)buf,"%i",option); } if (ortp_pipe_write(p,buf,sizeof(buf))==-1){ g_error("Fail to send wakeup command to running instance: %s",strerror(errno)); From 269f8d1c4ee1b587a262e407891224471ae2ad20 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 21 Mar 2014 18:13:54 +0100 Subject: [PATCH 16/55] add new API to obtain full details about failures (calls, registration, events). Fix bug when receiving a 487 after cancelling call, resulting in a call waiting tone to be played. --- coreapi/bellesip_sal/sal_impl.c | 25 +-- coreapi/bellesip_sal/sal_impl.h | 9 +- coreapi/bellesip_sal/sal_op_call.c | 38 ++-- coreapi/bellesip_sal/sal_op_events.c | 23 +- coreapi/bellesip_sal/sal_op_impl.c | 168 ++++++++------- coreapi/bellesip_sal/sal_op_message.c | 43 ++-- coreapi/bellesip_sal/sal_op_presence.c | 26 ++- coreapi/bellesip_sal/sal_op_publish.c | 24 ++- coreapi/bellesip_sal/sal_op_registration.c | 7 +- coreapi/callbacks.c | 231 ++++++++++----------- coreapi/chat.c | 13 +- coreapi/event.c | 6 +- coreapi/event.h | 5 + coreapi/linphonecall.c | 23 +- coreapi/linphonecore.c | 10 +- coreapi/linphonecore.h | 25 ++- coreapi/misc.c | 56 ++++- coreapi/private.h | 14 +- coreapi/proxy.c | 6 +- include/sal/sal.h | 36 ++-- tester/call_tester.c | 4 +- 21 files changed, 451 insertions(+), 341 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 47242cdd5..be3c9ba17 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -162,8 +162,8 @@ void sal_process_authentication(SalOp *op) { static void process_dialog_terminated(void *sal, const belle_sip_dialog_terminated_event_t *event){ belle_sip_dialog_t* dialog = belle_sip_dialog_terminated_event_get_dialog(event); SalOp* op = belle_sip_dialog_get_application_data(dialog); - if (op && op->callbacks.process_dialog_terminated) { - op->callbacks.process_dialog_terminated(op,event); + if (op && op->callbacks && op->callbacks->process_dialog_terminated) { + op->callbacks->process_dialog_terminated(op,event); } else { ms_error("sal process_dialog_terminated no op found for this dialog [%p], ignoring",dialog); } @@ -177,8 +177,8 @@ static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *e op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); /*also reset auth count on IO error*/ op->auth_requests=0; - if (op->callbacks.process_io_error) { - op->callbacks.process_io_error(op,event); + if (op->callbacks && op->callbacks->process_io_error) { + op->callbacks->process_io_error(op,event); } } else { /*ms_error("sal process_io_error not implemented yet for non transaction");*/ @@ -290,8 +290,8 @@ static void process_request_event(void *ud, const belle_sip_request_event_t *eve sal_op_set_privacy_from_message(op,(belle_sip_message_t*)req); sal_op_assign_recv_headers(op,(belle_sip_message_t*)req); - if (op->callbacks.process_request_event) { - op->callbacks.process_request_event(op,event); + if (op->callbacks && op->callbacks->process_request_event) { + op->callbacks->process_request_event(op,event); } else { ms_error("sal process_request_event not implemented yet"); } @@ -329,7 +329,7 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even sal_op_assign_recv_headers(op,(belle_sip_message_t*)response); - if (op->callbacks.process_response_event) { + if (op->callbacks && op->callbacks->process_response_event) { /*handle authorization*/ switch (response_code) { case 200: @@ -365,7 +365,7 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even /*not an auth request*/ op->auth_requests=0; } - op->callbacks.process_response_event(op,event); + op->callbacks->process_response_event(op,event); } else { ms_error("Unhandled event response [%p]",event); } @@ -375,8 +375,8 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { belle_sip_client_transaction_t* client_transaction = belle_sip_timeout_event_get_client_transaction(event); SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); - if (op && op->callbacks.process_timeout) { - op->callbacks.process_timeout(op,event); + if (op && op->callbacks && op->callbacks->process_timeout) { + op->callbacks->process_timeout(op,event); } else { ms_error("Unhandled event timeout [%p]",event); } @@ -393,8 +393,8 @@ static void process_transaction_terminated(void *user_ctx, const belle_sip_trans trans=BELLE_SIP_TRANSACTION(server_transaction); op = (SalOp*)belle_sip_transaction_get_application_data(trans); - if (op && op->callbacks.process_transaction_terminated) { - op->callbacks.process_transaction_terminated(op,event); + if (op && op->callbacks && op->callbacks->process_transaction_terminated) { + op->callbacks->process_transaction_terminated(op,event); } else { ms_message("Unhandled transaction terminated [%p]",trans); } @@ -443,6 +443,7 @@ Sal * sal_init(){ sal->refresher_retry_after=60000; /*default value in ms*/ return sal; } + void sal_set_user_pointer(Sal *sal, void *user_data){ sal->up=user_data; } diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index 1a38ce7dc..c203c9cb1 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -76,7 +76,8 @@ const char* sal_op_type_to_string(SalOpType type); struct SalOp{ SalOpBase base; - belle_sip_listener_callbacks_t callbacks; + const belle_sip_listener_callbacks_t *callbacks; + SalErrorInfo error_info; belle_sip_client_transaction_t *pending_auth_transaction; belle_sip_server_transaction_t* pending_server_trans; belle_sip_server_transaction_t* pending_update_server_trans; @@ -132,8 +133,10 @@ bool_t sal_op_is_secure(const SalOp* op); void sal_process_authentication(SalOp *op); belle_sip_header_contact_t* sal_op_create_contact(SalOp *op) ; -bool_t sal_compute_sal_errors(belle_sip_response_t* response,SalError* sal_err,SalReason* sal_reason,char* reason, size_t reason_size); -void sal_compute_sal_errors_from_code(int code ,SalError* sal_err,SalReason* sal_reason) ; +bool_t _sal_compute_sal_errors(belle_sip_response_t* response, SalReason* sal_reason, char* reason, size_t reason_size); +SalReason _sal_reason_from_sip_code(int code); + +void sal_op_set_error_info_from_response(SalOp *op, belle_sip_response_t *response); /*presence*/ void sal_op_presence_fill_cbs(SalOp*op); /*messaging*/ diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 01422e224..a77acafd0 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -38,19 +38,8 @@ static void call_set_released_and_unref(SalOp* op) { static void call_set_error(SalOp* op,belle_sip_response_t* response){ - SalError error=SalErrorUnknown; - SalReason sr=SalReasonUnknown; - belle_sip_header_t* reason_header = belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Reason"); - char* reason=(char*)belle_sip_response_get_reason_phrase(response); - int code = belle_sip_response_get_status_code(response); - if (reason_header){ - reason = ms_strdup_printf("%s %s",reason,belle_sip_header_get_unparsed_value(reason_header)); - } - sal_compute_sal_errors_from_code(code,&error,&sr); - op->base.root->callbacks.call_failure(op,error,sr,reason,code); - if (reason_header != NULL){ - ms_free(reason); - } + sal_op_set_error_info_from_response(op,response); + op->base.root->callbacks.call_failure(op); } static void sdp_process(SalOp *h){ @@ -127,7 +116,8 @@ static void call_process_io_error(void *user_ctx, const belle_sip_io_error_event if (!op->dialog) { /*call terminated very early*/ - op->base.root->callbacks.call_failure(op,SalErrorNoResponse,SalReasonUnknown,"Service Unavailable",503); + sal_error_info_set(&op->error_info,SalReasonIOError,503,"IO error",NULL); + op->base.root->callbacks.call_failure(op); call_set_released(op); } else { /*dialog will terminated shortly, nothing to do*/ @@ -290,7 +280,8 @@ static void call_process_timeout(void *user_ctx, const belle_sip_timeout_event_t if (!op->dialog) { /*call terminated very early*/ - op->base.root->callbacks.call_failure(op,SalErrorNoResponse,SalReasonUnknown,"Request Timeout",408); + sal_error_info_set(&op->error_info,SalReasonRequestTimeout,408,"Request timeout",NULL); + op->base.root->callbacks.call_failure(op); call_set_released(op); } else { /*dialog will terminated shortly, nothing to do*/ @@ -631,13 +622,18 @@ int sal_call(SalOp *op, const char *from, const char *to){ return sal_op_send_request(op,invite); } +static belle_sip_listener_callbacks_t call_op_callbacks={0}; + void sal_op_call_fill_cbs(SalOp*op) { - op->callbacks.process_io_error=call_process_io_error; - op->callbacks.process_response_event=call_process_response; - op->callbacks.process_timeout=call_process_timeout; - op->callbacks.process_transaction_terminated=call_process_transaction_terminated; - op->callbacks.process_request_event=process_request_event; - op->callbacks.process_dialog_terminated=process_dialog_terminated; + if (call_op_callbacks.process_response_event==NULL){ + call_op_callbacks.process_io_error=call_process_io_error; + call_op_callbacks.process_response_event=call_process_response; + call_op_callbacks.process_timeout=call_process_timeout; + call_op_callbacks.process_transaction_terminated=call_process_transaction_terminated; + call_op_callbacks.process_request_event=process_request_event; + call_op_callbacks.process_dialog_terminated=process_dialog_terminated; + } + op->callbacks=&call_op_callbacks; op->type=SalOpCall; } diff --git a/coreapi/bellesip_sal/sal_op_events.c b/coreapi/bellesip_sal/sal_op_events.c index 1972c97f6..4409c73a3 100644 --- a/coreapi/bellesip_sal/sal_op_events.c +++ b/coreapi/bellesip_sal/sal_op_events.c @@ -37,8 +37,6 @@ static void subscribe_refresher_listener (belle_sip_refresher_t* refresher ,unsigned int status_code ,const char* reason_phrase) { SalOp* op = (SalOp*)user_pointer; - SalError error=SalErrorUnknown; - SalReason sr=SalReasonUnknown; belle_sip_transaction_t *tr=BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher)); /*belle_sip_response_t* response=belle_sip_transaction_get_response(tr);*/ SalSubscribeStatus sss=SalSubscribeTerminated; @@ -50,8 +48,8 @@ static void subscribe_refresher_listener (belle_sip_refresher_t* refresher set_or_update_dialog(op,belle_sip_transaction_get_dialog(tr)); } if (status_code>=200){ - sal_compute_sal_errors_from_code(status_code,&error,&sr); - op->base.root->callbacks.subscribe_response(op,sss,error,sr); + sal_error_info_set(&op->error_info,SalReasonUnknown,status_code,reason_phrase,NULL); + op->base.root->callbacks.subscribe_response(op,sss); }else if (status_code==0){ op->base.root->callbacks.on_expire(op); } @@ -172,13 +170,18 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque } } +static belle_sip_listener_callbacks_t op_subscribe_callbacks={ 0 }; + void sal_op_subscribe_fill_cbs(SalOp*op) { - op->callbacks.process_io_error=subscribe_process_io_error; - op->callbacks.process_response_event=subscribe_response_event; - op->callbacks.process_timeout=subscribe_process_timeout; - op->callbacks.process_transaction_terminated=subscribe_process_transaction_terminated; - op->callbacks.process_request_event=subscribe_process_request_event; - op->callbacks.process_dialog_terminated=subscribe_process_dialog_terminated; + if (op_subscribe_callbacks.process_io_error==NULL){ + op_subscribe_callbacks.process_io_error=subscribe_process_io_error; + op_subscribe_callbacks.process_response_event=subscribe_response_event; + op_subscribe_callbacks.process_timeout=subscribe_process_timeout; + op_subscribe_callbacks.process_transaction_terminated=subscribe_process_transaction_terminated; + op_subscribe_callbacks.process_request_event=subscribe_process_request_event; + op_subscribe_callbacks.process_dialog_terminated=subscribe_process_dialog_terminated; + } + op->callbacks=&op_subscribe_callbacks; op->type=SalOpSubscribe; } diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index b3124300c..3e5ebe2a5 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -62,6 +62,7 @@ void sal_op_release_impl(SalOp *op){ if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); if (op->pending_update_server_trans) belle_sip_object_unref(op->pending_update_server_trans); if (op->event) belle_sip_object_unref(op->event); + sal_error_info_reset(&op->error_info); __sal_op_free(op); return ; } @@ -334,6 +335,12 @@ int sal_op_send_request(SalOp* op, belle_sip_request_t* request) { SalReason sal_reason_to_sip_code(SalReason r){ int ret=500; switch(r){ + case SalReasonNone: + ret=200; + break; + case SalReasonIOError: + ret=503; + break; case SalReasonUnknown: ret=400; break; @@ -401,110 +408,123 @@ SalReason sal_reason_to_sip_code(SalReason r){ return ret; } -void sal_compute_sal_errors_from_code(int code ,SalError* sal_err,SalReason* sal_reason) { - *sal_err=SalErrorFailure; +SalReason _sal_reason_from_sip_code(int code) { + if (code>=100 && code<300) return SalReasonNone; + switch(code) { + case 0: + return SalReasonIOError; case 301: - *sal_reason=SalReasonMovedPermanently; - break; + return SalReasonMovedPermanently; case 302: - *sal_reason=SalReasonRedirect; - break; + return SalReasonRedirect; case 401: case 407: - *sal_reason=SalReasonUnauthorized; - break; + return SalReasonUnauthorized; case 403: - *sal_reason=SalReasonForbidden; - break; + return SalReasonForbidden; case 404: - *sal_reason=SalReasonNotFound; - break; + return SalReasonNotFound; case 408: - *sal_reason=SalReasonRequestTimeout; - break; + return SalReasonRequestTimeout; case 410: - *sal_reason=SalReasonGone; - break; + return SalReasonGone; case 415: - *sal_reason=SalReasonUnsupportedContent; - break; + return SalReasonUnsupportedContent; case 422: ms_error ("422 not implemented yet");; break; case 480: - *sal_reason=SalReasonTemporarilyUnavailable; - break; + return SalReasonTemporarilyUnavailable; case 481: - *sal_reason=SalReasonNoMatch; - break; + return SalReasonNoMatch; case 484: - *sal_reason=SalReasonAddressIncomplete; - break; + return SalReasonAddressIncomplete; case 486: - *sal_reason=SalReasonBusy; - break; + return SalReasonBusy; case 487: - break; + return SalReasonNone; case 488: - *sal_reason=SalReasonNotAcceptable; - break; + return SalReasonNotAcceptable; case 491: - *sal_reason=SalReasonRequestPending; - break; + return SalReasonRequestPending; case 501: - *sal_reason=SalReasonNotImplemented; - break; + return SalReasonNotImplemented; case 502: - *sal_reason=SalReasonBadGateway; - break; + return SalReasonBadGateway; case 504: - *sal_reason=SalReasonServerTimeout; - break; + return SalReasonServerTimeout; case 600: - *sal_reason=SalReasonDoNotDisturb; - break; + return SalReasonDoNotDisturb; case 603: - *sal_reason=SalReasonDeclined; - break; + return SalReasonDeclined; case 503: - *sal_reason=SalReasonServiceUnavailable; - break; + return SalReasonServiceUnavailable; default: - if (code>=300){ - *sal_err=SalErrorFailure; - *sal_reason=SalReasonUnknown; - }else if (code>=100){ - *sal_err=SalErrorNone; - *sal_reason=SalReasonUnknown; - }else if (code==0){ - *sal_err=SalErrorNoResponse; - } - /* no break */ + return SalReasonUnknown; + } + return SalReasonUnknown; +} + +const SalErrorInfo *sal_error_info_none(void){ + static SalErrorInfo none={ + SalReasonNone, + "Ok", + 200, + NULL, + NULL + }; + return &none; +} + +void sal_error_info_reset(SalErrorInfo *ei){ + if (ei->status_string){ + ms_free(ei->status_string); + ei->status_string=NULL; + } + if (ei->warnings){ + ms_free(ei->warnings); + ei->warnings=NULL; + + } + if (ei->full_string){ + ms_free(ei->full_string); + ei->full_string=NULL; + } + ei->protocol_code=0; + ei->reason=SalReasonNone; +} + +void sal_error_info_set(SalErrorInfo *ei, SalReason reason, int code, const char *status_string, const char *warning){ + sal_error_info_reset(ei); + if (reason==SalReasonUnknown) ei->reason=_sal_reason_from_sip_code(code); + else ei->reason=reason; + ei->protocol_code=code; + ei->status_string=status_string ? ms_strdup(status_string) : NULL; + ei->warnings=warning ? ms_strdup(warning) : NULL; + if (ei->status_string){ + if (ei->warnings) + ei->full_string=ms_strdup_printf("%s %s",ei->status_string,ei->warnings); + else ei->full_string=ms_strdup(ei->status_string); } } -/*return TRUE if error code*/ -bool_t sal_compute_sal_errors(belle_sip_response_t* response,SalError* sal_err,SalReason* sal_reason,char* reason, size_t reason_size) { - int code = belle_sip_response_get_status_code(response); - belle_sip_header_t* reason_header = belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Reason"); - *sal_err=SalErrorUnknown; - *sal_reason = SalReasonUnknown; - if (reason_header){ - snprintf(reason - ,reason_size - ,"%s %s" - ,belle_sip_response_get_reason_phrase(response) - ,belle_sip_header_get_unparsed_value(reason_header)); - } else { - strncpy(reason,belle_sip_response_get_reason_phrase(response),reason_size); - } - if (code>=400) { - sal_compute_sal_errors_from_code(code,sal_err,sal_reason); - return TRUE; - } else { - return FALSE; - } +void sal_op_set_error_info_from_response(SalOp *op, belle_sip_response_t *response){ + int code = belle_sip_response_get_status_code(response); + const char *reason_phrase=belle_sip_response_get_reason_phrase(response); + /*Remark: the reason header is to be used mainly in SIP requests, thus the use and prototype of this function should be changed.*/ + belle_sip_header_t* reason_header = belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Reason"); + belle_sip_header_t *warning=belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Warning"); + SalErrorInfo *ei=&op->error_info; + const char *warnings; + + warnings=warning ? belle_sip_header_get_unparsed_value(warning) : NULL; + if (warnings==NULL) warnings=reason_header ? belle_sip_header_get_unparsed_value(reason_header) : NULL; + sal_error_info_set(ei,SalReasonUnknown,code,reason_phrase,warnings); +} + +const SalErrorInfo *sal_op_get_error_info(const SalOp *op){ + return &op->error_info; } void set_or_update_dialog(SalOp* op, belle_sip_dialog_t* dialog) { diff --git a/coreapi/bellesip_sal/sal_op_message.c b/coreapi/bellesip_sal/sal_op_message.c index bf7f7b82a..05f1199b8 100644 --- a/coreapi/bellesip_sal/sal_op_message.c +++ b/coreapi/bellesip_sal/sal_op_message.c @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. static void process_error( SalOp* op) { if (op->dir == SalOpDirOutgoing) { - op->base.root->callbacks.text_delivery_update(op, SalTextDeliveryFailed, SalReasonUnknown); + op->base.root->callbacks.text_delivery_update(op, SalTextDeliveryFailed); } else { ms_warning("unexpected io error for incoming message on op [%p]",op); } @@ -30,33 +30,20 @@ static void process_error( SalOp* op) { static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ SalOp* op = (SalOp*)user_ctx; -// belle_sip_object_t* source = belle_sip_io_error_event_get_source(event); -// if (BELLE_SIP_IS_INSTANCE_OF(source,belle_sip_transaction_t)) { -// /*reset op to make sure transaction terminated does not need op*/ -// belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(source),NULL); -// } + sal_error_info_set(&op->error_info,SalReasonIOError,503,"IO Error",NULL); process_error(op); } static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { SalOp* op=(SalOp*)user_ctx; -// belle_sip_client_transaction_t *client_transaction=belle_sip_timeout_event_get_client_transaction(event); -// belle_sip_server_transaction_t *server_transaction=belle_sip_timeout_event_get_server_transaction(event); -// /*reset op to make sure transaction terminated does not need op*/ -// if (client_transaction) { -// belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),NULL); -// } else { -// belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(server_transaction),NULL); -// } + sal_error_info_set(&op->error_info,SalReasonRequestTimeout,408,"Request timeout",NULL); process_error(op); } static void process_response_event(void *op_base, const belle_sip_response_event_t *event){ SalOp* op = (SalOp*)op_base; - /*belle_sip_client_transaction_t *client_transaction=belle_sip_response_event_get_client_transaction(event);*/ int code = belle_sip_response_get_status_code(belle_sip_response_event_get_response(event)); SalTextDeliveryStatus status; - SalReason reason=SalReasonUnknown; - SalError err=SalErrorNone; + sal_op_set_error_info_from_response(op,belle_sip_response_event_get_response(event)); if (code>=100 && code <200) status=SalTextDeliveryInProgress; @@ -64,13 +51,10 @@ static void process_response_event(void *op_base, const belle_sip_response_event status=SalTextDeliveryDone; else status=SalTextDeliveryFailed; - if (status != SalTextDeliveryInProgress) { - /*reset op to make sure transaction terminated does not need op - belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),NULL);*/ - } - sal_compute_sal_errors_from_code(code,&err,&reason); - op->base.root->callbacks.text_delivery_update(op,status, reason); + + op->base.root->callbacks.text_delivery_update(op,status); } + static bool_t is_plain_text(belle_sip_header_content_type_t* content_type) { return strcmp("text",belle_sip_header_content_type_get_type(content_type))==0 && strcmp("plain",belle_sip_header_content_type_get_subtype(content_type))==0; @@ -191,10 +175,15 @@ int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg) return sal_message_send(op,from,to,"text/plain",msg); } +static belle_sip_listener_callbacks_t op_message_callbacks={0}; + void sal_op_message_fill_cbs(SalOp*op) { - op->callbacks.process_io_error=process_io_error; - op->callbacks.process_response_event=process_response_event; - op->callbacks.process_timeout=process_timeout; - op->callbacks.process_request_event=process_request_event; + if (op_message_callbacks.process_io_error==NULL){ + op_message_callbacks.process_io_error=process_io_error; + op_message_callbacks.process_response_event=process_response_event; + op_message_callbacks.process_timeout=process_timeout; + op_message_callbacks.process_request_event=process_request_event; + } + op->callbacks=&op_message_callbacks; op->type=SalOpMessage; } diff --git a/coreapi/bellesip_sal/sal_op_presence.c b/coreapi/bellesip_sal/sal_op_presence.c index 9f7d6f871..ca526fd5d 100644 --- a/coreapi/bellesip_sal/sal_op_presence.c +++ b/coreapi/bellesip_sal/sal_op_presence.c @@ -94,13 +94,12 @@ static void presence_response_event(void *op_base, const belle_sip_response_even belle_sip_response_t* response=belle_sip_response_event_get_response(event); belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); int code = belle_sip_response_get_status_code(response); - char reason[256]={0}; - SalError error=SalErrorUnknown; - SalReason sr=SalReasonUnknown; belle_sip_header_expires_t* expires; + + sal_op_set_error_info_from_response(op,response); - if (sal_compute_sal_errors(response,&error,&sr,reason, sizeof(reason))) { - ms_error("subscription to [%s] rejected reason [%s]",sal_op_get_to(op),reason[0]!=0?reason:sal_reason_to_string(sr)); + if (code>=300) { + ms_message("subscription to [%s] rejected",sal_op_get_to(op)); op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/ return; } @@ -267,13 +266,18 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques } } +static belle_sip_listener_callbacks_t op_presence_callbacks={0}; + void sal_op_presence_fill_cbs(SalOp*op) { - op->callbacks.process_io_error=presence_process_io_error; - op->callbacks.process_response_event=presence_response_event; - op->callbacks.process_timeout=presence_process_timeout; - op->callbacks.process_transaction_terminated=presence_process_transaction_terminated; - op->callbacks.process_request_event=presence_process_request_event; - op->callbacks.process_dialog_terminated=presence_process_dialog_terminated; + if (op_presence_callbacks.process_request_event==NULL){ + op_presence_callbacks.process_io_error=presence_process_io_error; + op_presence_callbacks.process_response_event=presence_response_event; + op_presence_callbacks.process_timeout=presence_process_timeout; + op_presence_callbacks.process_transaction_terminated=presence_process_transaction_terminated; + op_presence_callbacks.process_request_event=presence_process_request_event; + op_presence_callbacks.process_dialog_terminated=presence_process_dialog_terminated; + } + op->callbacks=&op_presence_callbacks; op->type=SalOpPresence; } diff --git a/coreapi/bellesip_sal/sal_op_publish.c b/coreapi/bellesip_sal/sal_op_publish.c index a55042919..81a7ce724 100644 --- a/coreapi/bellesip_sal/sal_op_publish.c +++ b/coreapi/bellesip_sal/sal_op_publish.c @@ -35,24 +35,26 @@ static void publish_refresher_listener (belle_sip_refresher_t* refresher }else if (status_code==0){ op->base.root->callbacks.on_expire(op); }else if (status_code>=200){ - SalError err; - SalReason reason; - sal_compute_sal_errors_from_code(status_code,&err,&reason); - op->base.root->callbacks.on_publish_response(op,err,reason); + sal_error_info_set(&op->error_info,SalReasonUnknown,status_code,reason_phrase,NULL); + op->base.root->callbacks.on_publish_response(op); } } static void publish_response_event(void *userctx, const belle_sip_response_event_t *event){ SalOp *op=(SalOp*)userctx; - int code=belle_sip_response_get_status_code(belle_sip_response_event_get_response(event)); - SalError err; - SalReason reason; - sal_compute_sal_errors_from_code(code,&err,&reason); - op->base.root->callbacks.on_publish_response(op,err,reason); + sal_op_set_error_info_from_response(op,belle_sip_response_event_get_response(event)); + if (op->error_info.protocol_code>=200){ + op->base.root->callbacks.on_publish_response(op); + } } -void sal_op_publish_fill_cbs(SalOp*op) { - op->callbacks.process_response_event=publish_response_event; +static belle_sip_listener_callbacks_t op_publish_callbacks={0}; + +void sal_op_publish_fill_cbs(SalOp *op) { + if (op_publish_callbacks.process_response_event==NULL){ + op_publish_callbacks.process_response_event=publish_response_event; + } + op->callbacks=&op_publish_callbacks; op->type=SalOpPublish; } diff --git a/coreapi/bellesip_sal/sal_op_registration.c b/coreapi/bellesip_sal/sal_op_registration.c index 2f12d4533..17a3861b4 100644 --- a/coreapi/bellesip_sal/sal_op_registration.c +++ b/coreapi/bellesip_sal/sal_op_registration.c @@ -24,8 +24,6 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher ,unsigned int status_code ,const char* reason_phrase) { SalOp* op = (SalOp*)user_pointer; - SalError sal_err; - SalReason sal_reason; belle_sip_response_t* response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher))); ms_message("Register refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase,sal_op_get_proxy(op)); @@ -57,9 +55,8 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher chooses not to re-register, the UA SHOULD discard any stored service route for that address-of-record. */ sal_op_set_service_route(op,NULL); - - sal_compute_sal_errors_from_code(status_code,&sal_err,&sal_reason); - op->base.root->callbacks.register_failure(op,sal_err,sal_reason,reason_phrase); + sal_error_info_set(&op->error_info,SalReasonUnknown,status_code,reason_phrase,NULL); + op->base.root->callbacks.register_failure(op); if (op->auth_info) { /*add pending auth*/ sal_add_pending_auth(op->base.root,op); diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 469baf8af..80818be37 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -32,7 +32,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #endif -static void register_failure(SalOp *op, SalError error, SalReason reason, const char *details); +static void register_failure(SalOp *op); static int media_parameters_changed(LinphoneCall *call, SalMediaDescription *oldmd, SalMediaDescription *newmd) { if (call->params.in_conference != call->current_params.in_conference) return SAL_MEDIA_DESCRIPTION_CHANGED; @@ -550,7 +550,7 @@ static void call_terminated(SalOp *op, const char *from){ break; case LinphoneCallIncomingReceived: case LinphoneCallIncomingEarlyMedia: - call->reason=LinphoneReasonNotAnswered; + sal_error_info_set(&call->non_op_error,SalReasonRequestTimeout,0,"Incoming call cancelled",NULL); break; default: break; @@ -593,14 +593,15 @@ static int resume_call_after_failed_transfer(LinphoneCall *call){ return BELLE_SIP_STOP; } -static void call_failure(SalOp *op, SalError error, SalReason sr, const char *details, int code){ +static void call_failure(SalOp *op){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); + const SalErrorInfo *ei=sal_op_get_error_info(op); char *msg486=_("User is busy."); char *msg480=_("User is temporarily unavailable."); /*char *retrymsg=_("%s. Retry after %i minute(s).");*/ char *msg600=_("User does not want to be disturbed."); char *msg603=_("Call declined."); - const char *msg=details; + const char *msg=ei->full_string; LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); LinphoneCall *referer=call->referer; @@ -610,102 +611,95 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de } if (lc->vtable.show) lc->vtable.show(lc); - - if (error==SalErrorNoResponse){ - msg=_("No response."); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg); - }else if (error==SalErrorProtocol){ - msg=details ? details : _("Protocol error."); - if (lc->vtable.display_status) - lc->vtable.display_status(lc, msg); - }else if (error==SalErrorFailure){ - switch(sr){ - case SalReasonDeclined: - msg=msg603; - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg603); - break; - case SalReasonBusy: - msg=msg486; - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg486); - break; - case SalReasonRedirect: - { - ms_error("case SalReasonRedirect"); + switch(ei->reason){ + case SalReasonNone: + break; + case SalReasonRequestTimeout: + msg=_("Request timeout."); + if (lc->vtable.display_status) + lc->vtable.display_status(lc,msg); + break; + case SalReasonDeclined: + msg=msg603; + if (lc->vtable.display_status) + lc->vtable.display_status(lc,msg603); + break; + case SalReasonBusy: + msg=msg486; + if (lc->vtable.display_status) + lc->vtable.display_status(lc,msg486); + break; + case SalReasonRedirect: + { + linphone_call_stop_media_streams(call); + if ( call->state==LinphoneCallOutgoingInit + || call->state==LinphoneCallOutgoingProgress + || call->state==LinphoneCallOutgoingRinging /*push case*/ + || call->state==LinphoneCallOutgoingEarlyMedia){ + LinphoneAddress* redirection_to = (LinphoneAddress*)sal_op_get_remote_contact_address(call->op); + if( redirection_to ){ + char* url = linphone_address_as_string(redirection_to); + ms_warning("Redirecting call [%p] to %s",call, url); + ms_free(url); + linphone_call_create_op(call); + linphone_core_start_invite(lc, call, redirection_to); + return; + } + } + msg=_("Redirected"); + if (lc->vtable.display_status) + lc->vtable.display_status(lc,msg); + } + break; + case SalReasonTemporarilyUnavailable: + msg=msg480; + if (lc->vtable.display_status) + lc->vtable.display_status(lc,msg480); + break; + case SalReasonNotFound: + if (lc->vtable.display_status) + lc->vtable.display_status(lc,msg); + break; + case SalReasonDoNotDisturb: + msg=msg600; + if (lc->vtable.display_status) + lc->vtable.display_status(lc,msg600); + break; + case SalReasonUnsupportedContent: /*params.media_encryption == LinphoneMediaEncryptionSRTP && + !linphone_core_is_media_encryption_mandatory(lc)) { + int i; + ms_message("Outgoing call [%p] failed with SRTP (SAVP) enabled",call); linphone_call_stop_media_streams(call); - if ( call->state==LinphoneCallOutgoingInit + if (call->state==LinphoneCallOutgoingInit || call->state==LinphoneCallOutgoingProgress || call->state==LinphoneCallOutgoingRinging /*push case*/ || call->state==LinphoneCallOutgoingEarlyMedia){ - LinphoneAddress* redirection_to = (LinphoneAddress*)sal_op_get_remote_contact_address(call->op); - if( redirection_to ){ - char* url = linphone_address_as_string(redirection_to); - ms_error("Redirecting call [%p] to %s",call, url); - ms_free(url); - linphone_call_create_op(call); - linphone_core_start_invite(lc, call, redirection_to); - return; + ms_message("Retrying call [%p] with AVP",call); + /* clear SRTP local params */ + call->params.media_encryption = LinphoneMediaEncryptionNone; + for(i=0; ilocaldesc->n_active_streams; i++) { + call->localdesc->streams[i].proto = SalProtoRtpAvp; + memset(call->localdesc->streams[i].crypto, 0, sizeof(call->localdesc->streams[i].crypto)); } + linphone_core_restart_invite(lc, call); + return; } - msg=_("Redirected"); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg); } - break; - case SalReasonTemporarilyUnavailable: - msg=msg480; - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg480); - break; - case SalReasonNotFound: - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg); - break; - case SalReasonDoNotDisturb: - msg=msg600; - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg600); - break; - case SalReasonUnsupportedContent: /*params.media_encryption == LinphoneMediaEncryptionSRTP && - !linphone_core_is_media_encryption_mandatory(lc)) { - int i; - ms_message("Outgoing call [%p] failed with SRTP (SAVP) enabled",call); - linphone_call_stop_media_streams(call); - if ( call->state==LinphoneCallOutgoingInit - || call->state==LinphoneCallOutgoingProgress - || call->state==LinphoneCallOutgoingRinging /*push case*/ - || call->state==LinphoneCallOutgoingEarlyMedia){ - ms_message("Retrying call [%p] with AVP",call); - /* clear SRTP local params */ - call->params.media_encryption = LinphoneMediaEncryptionNone; - for(i=0; ilocaldesc->n_active_streams; i++) { - call->localdesc->streams[i].proto = SalProtoRtpAvp; - memset(call->localdesc->streams[i].crypto, 0, sizeof(call->localdesc->streams[i].crypto)); - } - linphone_core_restart_invite(lc, call); - return; - } - - } - msg=_("Incompatible media parameters."); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg); - break; - case SalReasonRequestPending: - /*restore previous state, the application will decide to resubmit the action if relevant*/ - call->reason=linphone_reason_from_sal(sr); - linphone_call_set_state(call,call->prevstate,msg); - return; - break; - default: - if (lc->vtable.display_status) - lc->vtable.display_status(lc,_("Call failed.")); - } + msg=_("Incompatible media parameters."); + if (lc->vtable.display_status) + lc->vtable.display_status(lc,msg); + break; + case SalReasonRequestPending: + /*restore previous state, the application will decide to resubmit the action if relevant*/ + linphone_call_set_state(call,call->prevstate,msg); + return; + break; + default: + if (lc->vtable.display_status) + lc->vtable.display_status(lc,_("Call failed.")); } /*some call error are not fatal*/ @@ -714,8 +708,7 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de case LinphoneCallPausing: case LinphoneCallResuming: ms_message("Call error on state [%s], restoring previous state",linphone_call_state_to_string(call->prevstate)); - call->reason=linphone_reason_from_sal(sr); - linphone_call_set_state(call, call->prevstate,details); + linphone_call_set_state(call, call->prevstate,ei->full_string); return; default: break; /*nothing to do*/ @@ -728,13 +721,14 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de linphone_call_delete_upnp_session(call); #endif //BUILD_UPNP - call->reason=linphone_reason_from_sal(sr); - if (sr==SalReasonDeclined){ - linphone_call_set_state(call,LinphoneCallEnd,"Call declined."); - }else{ - linphone_call_set_state(call,LinphoneCallError,details); + if (call->state!=LinphoneCallEnd && call->state!=LinphoneCallError){ + if (ei->reason==SalReasonDeclined){ + linphone_call_set_state(call,LinphoneCallEnd,"Call declined."); + }else{ + linphone_call_set_state(call,LinphoneCallError,ei->full_string); + } + if (ei->reason!=SalReasonNone) linphone_core_play_call_error_tone(lc,linphone_reason_from_sal(ei->reason)); } - linphone_core_play_call_error_tone(lc,call->reason); if (referer){ /*notify referer of the failure*/ @@ -773,7 +767,6 @@ static void register_success(SalOp *op, bool_t registered){ ms_message("Registration success for removed proxy config, ignored"); return; } - linphone_proxy_config_set_error(cfg,LinphoneReasonNone); linphone_proxy_config_set_state(cfg, registered ? LinphoneRegistrationOk : LinphoneRegistrationCleared , registered ? "Registration successful" : "Unregistration done"); if (lc->vtable.display_status){ @@ -785,9 +778,11 @@ static void register_success(SalOp *op, bool_t registered){ } -static void register_failure(SalOp *op, SalError error, SalReason reason, const char *details){ +static void register_failure(SalOp *op){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op); + const SalErrorInfo *ei=sal_op_get_error_info(op); + const char *details=ei->full_string; if (cfg==NULL){ ms_warning("Registration failed for unknown proxy config."); @@ -801,15 +796,12 @@ static void register_failure(SalOp *op, SalError error, SalReason reason, const details=_("no response timeout"); if (lc->vtable.display_status) { - char *msg=ortp_strdup_printf(_("Registration on %s failed: %s"),sal_op_get_proxy(op),details ); + char *msg=ortp_strdup_printf(_("Registration on %s failed: %s"),sal_op_get_proxy(op), details); lc->vtable.display_status(lc,msg); ms_free(msg); } - linphone_proxy_config_set_error(cfg,linphone_reason_from_sal(reason)); - - if (error== SalErrorFailure - && reason == SalReasonServiceUnavailable + if ((ei->reason == SalReasonServiceUnavailable || ei->reason == SalReasonIOError) && linphone_proxy_config_get_state(cfg) == LinphoneRegistrationOk) { linphone_proxy_config_set_state(cfg,LinphoneRegistrationProgress,_("Service unavailable, retrying")); } else { @@ -1031,22 +1023,15 @@ static LinphoneChatMessageState chatStatusSal2Linphone(SalTextDeliveryStatus sta return LinphoneChatMessageStateIdle; } -static int op_equals(LinphoneCall *a, SalOp *b) { - return a->op !=b; /*return 0 if equals*/ -} - -static void text_delivery_update(SalOp *op, SalTextDeliveryStatus status, SalReason reason){ +static void text_delivery_update(SalOp *op, SalTextDeliveryStatus status){ LinphoneChatMessage *chat_msg=(LinphoneChatMessage* )sal_op_get_user_pointer(op); - const MSList* calls; if (chat_msg == NULL) { // Do not handle delivery status for isComposing messages. return; } - calls = linphone_core_get_calls(chat_msg->chat_room->lc); chat_msg->state=chatStatusSal2Linphone(status); - chat_msg->reason=linphone_reason_from_sal(reason); linphone_chat_message_store_state(chat_msg); if (chat_msg && chat_msg->cb) { ms_message("Notifying text delivery with status %i",chat_msg->state); @@ -1056,11 +1041,6 @@ static void text_delivery_update(SalOp *op, SalTextDeliveryStatus status, SalRea } if (status != SalTextDeliveryInProgress) { /*don't release op if progress*/ linphone_chat_message_destroy(chat_msg); - - if (!ms_list_find_custom((MSList*)calls, (MSCompareFunc) op_equals, op)) { - /*op was only create for messaging purpose, destroying*/ - sal_op_release(op); - } } } @@ -1069,7 +1049,7 @@ static void info_received(SalOp *op, const SalBody *body){ linphone_core_notify_info_message(lc,op,body); } -static void subscribe_response(SalOp *op, SalSubscribeStatus status, SalError error, SalReason reason){ +static void subscribe_response(SalOp *op, SalSubscribeStatus status){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); if (lev==NULL) return; @@ -1079,7 +1059,6 @@ static void subscribe_response(SalOp *op, SalSubscribeStatus status, SalError er }else if (status==SalSubscribePending){ linphone_event_set_state(lev,LinphoneSubscriptionPending); }else{ - linphone_event_set_reason(lev, linphone_reason_from_sal(reason)); linphone_event_set_state(lev,LinphoneSubscriptionError); } } @@ -1121,18 +1100,18 @@ static void subscribe_closed(SalOp *op){ linphone_event_set_state(lev,LinphoneSubscriptionTerminated); } -static void on_publish_response(SalOp* op, SalError err, SalReason reason){ +static void on_publish_response(SalOp* op){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); + const SalErrorInfo *ei=sal_op_get_error_info(op); if (lev==NULL) return; - if (err==SalErrorNone){ + if (ei->reason==SalReasonNone){ if (!lev->terminating) linphone_event_set_publish_state(lev,LinphonePublishOk); else linphone_event_set_publish_state(lev,LinphonePublishCleared); }else{ - linphone_event_set_reason(lev,linphone_reason_from_sal(reason)); linphone_event_set_publish_state(lev,LinphonePublishError); } } diff --git a/coreapi/chat.c b/coreapi/chat.c index bb944e1cc..264d6d768 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -160,7 +160,7 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM identity=linphone_proxy_config_get_identity(proxy); }else identity=linphone_core_get_primary_contact(cr->lc); /*sending out of calls*/ - op = sal_op_new(cr->lc->sal); + msg->op = op = sal_op_new(cr->lc->sal); linphone_configure_op(cr->lc,op,cr->peer_url,msg->custom_headers,lp_config_get_int(cr->lc->config,"sip","chat_msg_with_contact",0)); sal_op_set_user_pointer(op, msg); /*if out of call, directly store msg*/ } @@ -779,6 +779,7 @@ LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* msg) * Destroys a LinphoneChatMessage. **/ void linphone_chat_message_destroy(LinphoneChatMessage* msg) { + if (msg->op) sal_op_release(msg->op); if (msg->message) ms_free(msg->message); if (msg->external_body_url) ms_free(msg->external_body_url); if (msg->from) linphone_address_destroy(msg->from); @@ -787,9 +788,17 @@ void linphone_chat_message_destroy(LinphoneChatMessage* msg) { ms_free(msg); } +/** + * Get full details about delivery error of a chat message. + * @param msg a LinphoneChatMessage + * @return a LinphoneErrorInfo describing the details. +**/ +const LinphoneErrorInfo *linphone_chat_message_get_error_info(const LinphoneChatMessage *msg){ + return linphone_error_info_from_sal_op(msg->op); +} LinphoneReason linphone_chat_message_get_reason(LinphoneChatMessage* msg) { - return msg->reason; + return linphone_error_info_get_reason(linphone_chat_message_get_error_info(msg)); } /** diff --git a/coreapi/event.c b/coreapi/event.c index 6a7930943..e4d66db3e 100644 --- a/coreapi/event.c +++ b/coreapi/event.c @@ -114,12 +114,12 @@ LinphonePublishState linphone_event_get_publish_state(const LinphoneEvent *lev){ return lev->publish_state; } -void linphone_event_set_reason(LinphoneEvent *lev, LinphoneReason reason){ - lev->reason=reason; +const LinphoneErrorInfo *linphone_event_get_error_info(const LinphoneEvent *lev){ + return linphone_error_info_from_sal_op(lev->op); } LinphoneReason linphone_event_get_reason(const LinphoneEvent *lev){ - return lev->reason; + return linphone_error_info_get_reason(linphone_event_get_error_info(lev)); } LinphoneEvent *linphone_core_create_subscribe(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires){ diff --git a/coreapi/event.h b/coreapi/event.h index e01ab9414..5985d1c96 100644 --- a/coreapi/event.h +++ b/coreapi/event.h @@ -207,6 +207,11 @@ LINPHONE_PUBLIC int linphone_event_update_publish(LinphoneEvent *lev, const Linp **/ LINPHONE_PUBLIC LinphoneReason linphone_event_get_reason(const LinphoneEvent *lev); +/** + * Get full details about an error occured. +**/ +const LinphoneErrorInfo *linphone_event_get_error_info(const LinphoneEvent *lev); + /** * Get subscription state. If the event object was not created by a subscription mechanism, #LinphoneSubscriptionNone is returned. **/ diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index d5c0bdf3c..4ff3537fb 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -793,11 +793,11 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const call->state=cstate; } if (cstate==LinphoneCallEnd || cstate==LinphoneCallError){ - switch(call->reason){ - case LinphoneReasonDeclined: + switch(call->non_op_error.reason){ + case SalReasonDeclined: call->log->status=LinphoneCallDeclined; break; - case LinphoneReasonNotAnswered: + case SalReasonRequestTimeout: call->log->status=LinphoneCallMissed; break; default: @@ -814,6 +814,11 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const lc->vtable.call_state_changed(lc,call,cstate,message); if (cstate==LinphoneCallReleased){ if (call->op!=NULL) { + /*transfer the last error so that it can be obtained even in Released state*/ + if (call->non_op_error.reason==SalReasonNone){ + const SalErrorInfo *ei=sal_op_get_error_info(call->op); + sal_error_info_set(&call->non_op_error,ei->reason,ei->protocol_code,ei->status_string,ei->warnings); + } /* so that we cannot have anymore upcalls for SAL concerning this call*/ sal_op_release(call->op); @@ -877,6 +882,7 @@ static void linphone_call_destroy(LinphoneCall *obj) } linphone_call_params_uninit(&obj->params); linphone_call_params_uninit(&obj->current_params); + sal_error_info_reset(&obj->non_op_error); ms_free(obj); } @@ -998,7 +1004,16 @@ LinphoneCallState linphone_call_get_state(const LinphoneCall *call){ * Returns the reason for a call termination (either error or normal termination) **/ LinphoneReason linphone_call_get_reason(const LinphoneCall *call){ - return call->reason; + return linphone_error_info_get_reason(linphone_call_get_error_info(call)); +} + +/** + * Returns full details about call errors or termination reasons. +**/ +const LinphoneErrorInfo *linphone_call_get_error_info(const LinphoneCall *call){ + if (call->non_op_error.reason!=SalReasonNone){ + return (const LinphoneErrorInfo*)&call->non_op_error; + }else return linphone_error_info_from_sal_op(call->op); } /** diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 38093e7c8..9cd36d0fd 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2281,7 +2281,7 @@ void linphone_core_iterate(LinphoneCore *lc){ ms_message("incoming call timeout (%i)",lc->sip_conf.inc_timeout); decline_reason=lc->current_call ? LinphoneReasonBusy : LinphoneReasonDeclined; call->log->status=LinphoneCallMissed; - call->reason=LinphoneReasonNotAnswered; + sal_error_info_set(&call->non_op_error,SalReasonRequestTimeout,408,"Not answered",NULL); linphone_core_decline_call(lc,call,decline_reason); } } @@ -3470,8 +3470,8 @@ int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *e static void terminate_call(LinphoneCore *lc, LinphoneCall *call){ if (call->state==LinphoneCallIncomingReceived){ - if (call->reason!=LinphoneReasonNotAnswered) - call->reason=LinphoneReasonDeclined; + if (call->non_op_error.reason!=SalReasonRequestTimeout) + call->non_op_error.reason=SalReasonDeclined; } /*stop ringing*/ linphone_core_stop_ringing(lc); @@ -3490,7 +3490,7 @@ static void terminate_call(LinphoneCore *lc, LinphoneCall *call){ int linphone_core_redirect_call(LinphoneCore *lc, LinphoneCall *call, const char *redirect_uri){ if (call->state==LinphoneCallIncomingReceived){ sal_call_decline(call->op,SalReasonRedirect,redirect_uri); - call->reason=LinphoneReasonDeclined; + sal_error_info_set(&call->non_op_error,SalReasonRedirect,603,"Call redirected",NULL); terminate_call(lc,call); }else{ ms_error("Bad state for call redirection."); @@ -6152,6 +6152,8 @@ const char *linphone_reason_to_string(LinphoneReason err){ return "Bad gateway"; case LinphoneReasonServerTimeout: return "Server timeout"; + case LinphoneReasonUnknown: + return "Unknown error"; } return "unknown error"; } diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 2af2d54de..f2d4b2514 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -159,6 +159,7 @@ typedef struct _LinphoneCall LinphoneCall; * Enum describing various failure reasons or contextual information for some events. * @see linphone_call_get_reason() * @see linphone_proxy_config_get_error() + * @see linphone_error_info_get_reason() * @ingroup misc **/ enum _LinphoneReason{ @@ -181,7 +182,8 @@ enum _LinphoneReason{ LinphoneReasonAddressIncomplete, /**
reason); +} + +/** + * Get textual phrase from the error info. + * This is the text that is provided by the peer in the protocol (SIP). + * @param ei the error info. + * @return the error phrase + * @ingroup misc +**/ +const char *linphone_error_info_get_phrase(const LinphoneErrorInfo *ei){ + const SalErrorInfo *sei=(const SalErrorInfo*)ei; + return sei->status_string; +} + +/** + * Provides additional information regarding the failure. + * With SIP protocol, the "Reason" and "Warning" headers are returned. + * @param ei the error info. + * @return more details about the failure. + * @ingroup misc +**/ +const char *linphone_error_info_get_details(const LinphoneErrorInfo *ei){ + const SalErrorInfo *sei=(const SalErrorInfo*)ei; + return sei->warnings; +} + +/** + * Get the status code from the low level protocol (ex a SIP status code). + * @param ei the error info. + * @return the status code. + * @ingroup misc +**/ +int linphone_error_info_get_protocol_code(const LinphoneErrorInfo *ei){ + const SalErrorInfo *sei=(const SalErrorInfo*)ei; + return sei->protocol_code; +} + /** * Set the name of the mediastreamer2 filter to be used for rendering video. * This is for advanced users of the library, mainly to workaround hardware/driver bugs. diff --git a/coreapi/private.h b/coreapi/private.h index 9e8d0af0f..18de67587 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -146,7 +146,7 @@ struct _LinphoneChatMessage { LinphoneChatMessageState state; bool_t is_read; unsigned int storage_id; - LinphoneReason reason; + SalOp *op; }; typedef struct StunCandidate{ @@ -159,6 +159,7 @@ struct _LinphoneCall { int magic; /*used to distinguish from proxy config*/ struct _LinphoneCore *core; + SalErrorInfo non_op_error; int af; /*the address family to prefer for RTP path, guessed from signaling path*/ LinphoneCallDir dir; SalMediaDescription *biggestdesc; /*media description with all already proposed streams, used to remember the mapping of streams*/ @@ -174,7 +175,6 @@ struct _LinphoneCall LinphoneCallState state; LinphoneCallState prevstate; LinphoneCallState transfer_state; /*idle if no transfer*/ - LinphoneReason reason; LinphoneProxyConfig *dest_proxy; int refcnt; void * user_pointer; @@ -204,7 +204,7 @@ struct _LinphoneCall unsigned int remote_session_ver; LinphoneCall *referer; /*when this call is the result of a transfer, referer is set to the original call that caused the transfer*/ LinphoneCall *transfer_target;/*if this call received a transfer request, then transfer_target points to the new call created to the refer target */ - int localdesc_changed; + int localdesc_changed;/*not a boolean, contains a mask representing changes*/ bool_t refer_pending; bool_t expect_media_in_ack; @@ -373,7 +373,6 @@ int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call) void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call); bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription *md); extern SalCallbacks linphone_sal_callbacks; -void linphone_proxy_config_set_error(LinphoneProxyConfig *cfg, LinphoneReason error); bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc); LinphoneCall * is_a_linphone_call(void *user_pointer); @@ -413,7 +412,6 @@ struct _LinphoneProxyConfig bool_t pad[3]; void* user_data; time_t deletion_date; - LinphoneReason error; LinphonePrivacyMask privacy; }; @@ -693,7 +691,6 @@ struct _LinphoneEvent{ SalCustomHeader *send_custom_headers; LinphoneSubscriptionState subscription_state; LinphonePublishState publish_state; - LinphoneReason reason; void *userdata; int refcnt; char *name; @@ -806,7 +803,6 @@ LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir, LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name); void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state); void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state); -void linphone_event_set_reason(LinphoneEvent *lev, LinphoneReason reason); LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatus ss); const LinphoneContent *linphone_content_from_sal_body(LinphoneContent *obj, const SalBody *ref); void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc); @@ -847,6 +843,10 @@ char * linphone_get_xml_text_content(xmlparsing_context_t *xml_ctx, const char * void linphone_free_xml_text_content(const char *text); xmlXPathObjectPtr linphone_get_xml_xpath_object_for_node_list(xmlparsing_context_t *xml_ctx, const char *xpath_expression); +static inline const LinphoneErrorInfo *linphone_error_info_from_sal_op(const SalOp *op){ + if (op==NULL) return (LinphoneErrorInfo*)sal_error_info_none(); + return (const LinphoneErrorInfo*)sal_op_get_error_info(op); +} /** Belle Sip-based objects need unique ids */ diff --git a/coreapi/proxy.c b/coreapi/proxy.c index 5e0b8ff18..74c8a7730 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -1368,11 +1368,11 @@ LinphoneRegistrationState linphone_proxy_config_get_state(const LinphoneProxyCon } LinphoneReason linphone_proxy_config_get_error(const LinphoneProxyConfig *cfg) { - return cfg->error; + return linphone_error_info_get_reason(linphone_proxy_config_get_error_info(cfg)); } -void linphone_proxy_config_set_error(LinphoneProxyConfig *cfg,LinphoneReason error) { - cfg->error = error; +const LinphoneErrorInfo *linphone_proxy_config_get_error_info(const LinphoneProxyConfig *cfg){ + return linphone_error_info_from_sal_op(cfg->op); } const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphoneProxyConfig* cfg) { diff --git a/include/sal/sal.h b/include/sal/sal.h index 650b5085a..f508484ec 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -254,6 +254,7 @@ SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md, SalMediaProto proto, SalStreamType type); void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_dir); + /*this structure must be at the first byte of the SalOp structure defined by implementors*/ typedef struct SalOpBase{ Sal *root; @@ -279,15 +280,8 @@ typedef struct SalOpBase{ } SalOpBase; -typedef enum SalError{ - SalErrorNone, - SalErrorNoResponse, - SalErrorProtocol, - SalErrorFailure, /* see SalReason for more details */ - SalErrorUnknown -} SalError; - typedef enum SalReason{ + SalReasonNone, /*no error, please leave first so that it takes 0 value*/ SalReasonDeclined, SalReasonBusy, SalReasonRedirect, @@ -308,11 +302,20 @@ typedef enum SalReason{ SalReasonAddressIncomplete, SalReasonNotImplemented, SalReasonBadGateway, - SalReasonServerTimeout + SalReasonServerTimeout, + SalReasonIOError }SalReason; const char* sal_reason_to_string(const SalReason reason); +typedef struct SalErrorInfo{ + SalReason reason; + char *status_string; + int protocol_code; + char *warnings; + char *full_string; /*concatenation of status_string + warnings*/ +}SalErrorInfo; + typedef enum SalPresenceStatus{ SalPresenceOffline, SalPresenceOnline, @@ -400,21 +403,21 @@ typedef void (*SalOnCallAccepted)(SalOp *op); typedef void (*SalOnCallAck)(SalOp *op); typedef void (*SalOnCallUpdating)(SalOp *op);/*< Called when a reINVITE/UPDATE is received*/ typedef void (*SalOnCallTerminated)(SalOp *op, const char *from); -typedef void (*SalOnCallFailure)(SalOp *op, SalError error, SalReason reason, const char *details, int code); +typedef void (*SalOnCallFailure)(SalOp *op); typedef void (*SalOnCallReleased)(SalOp *salop); typedef void (*SalOnAuthRequestedLegacy)(SalOp *op, const char *realm, const char *username); typedef bool_t (*SalOnAuthRequested)(Sal *sal,SalAuthInfo* info); typedef void (*SalOnAuthFailure)(SalOp *op, SalAuthInfo* info); typedef void (*SalOnRegisterSuccess)(SalOp *op, bool_t registered); -typedef void (*SalOnRegisterFailure)(SalOp *op, SalError error, SalReason reason, const char *details); +typedef void (*SalOnRegisterFailure)(SalOp *op); typedef void (*SalOnVfuRequest)(SalOp *op); typedef void (*SalOnDtmfReceived)(SalOp *op, char dtmf); typedef void (*SalOnRefer)(Sal *sal, SalOp *op, const char *referto); typedef void (*SalOnTextReceived)(SalOp *op, const SalMessage *msg); -typedef void (*SalOnTextDeliveryUpdate)(SalOp *op, SalTextDeliveryStatus, SalReason); +typedef void (*SalOnTextDeliveryUpdate)(SalOp *op, SalTextDeliveryStatus); typedef void (*SalOnIsComposingReceived)(SalOp *op, const SalIsComposing *is_composing); typedef void (*SalOnNotifyRefer)(SalOp *op, SalReferStatus state); -typedef void (*SalOnSubscribeResponse)(SalOp *op, SalSubscribeStatus status, SalError error, SalReason reason); +typedef void (*SalOnSubscribeResponse)(SalOp *op, SalSubscribeStatus status); typedef void (*SalOnNotify)(SalOp *op, SalSubscribeStatus status, const char *event, const SalBody *body); typedef void (*SalOnSubscribeReceived)(SalOp *salop, const char *event, const SalBody *body); typedef void (*SalOnSubscribeClosed)(SalOp *salop); @@ -425,7 +428,7 @@ typedef void (*SalOnSubscribePresenceReceived)(SalOp *salop, const char *from); typedef void (*SalOnSubscribePresenceClosed)(SalOp *salop, const char *from); typedef void (*SalOnPingReply)(SalOp *salop); typedef void (*SalOnInfoReceived)(SalOp *salop, const SalBody *body); -typedef void (*SalOnPublishResponse)(SalOp *salop, SalError error, SalReason reason); +typedef void (*SalOnPublishResponse)(SalOp *salop); typedef void (*SalOnExpire)(SalOp *salop); /*allows sal implementation to access auth info if available, return TRUE if found*/ @@ -577,6 +580,11 @@ bool_t sal_op_is_ipv6(SalOp *op); /*returns TRUE if there is no pending request that may block a future one */ bool_t sal_op_is_idle(SalOp *op); +const SalErrorInfo *sal_error_info_none(void); +const SalErrorInfo *sal_op_get_error_info(const SalOp *op); +void sal_error_info_reset(SalErrorInfo *ei); +void sal_error_info_set(SalErrorInfo *ei, SalReason reason, int code, const char *status_string, const char *warning); + /*Call API*/ int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc); int sal_call(SalOp *h, const char *from, const char *to); diff --git a/tester/call_tester.c b/tester/call_tester.c index 515c7980e..ed44faa9e 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -914,7 +914,7 @@ static void call_waiting_indication_with_param(bool_t enable_caller_privacy) { snprintf(hellopath,sizeof(hellopath), "%s/sounds/hello8000.wav", liblinphone_tester_file_prefix); linphone_core_set_play_file(laure->lc,hellopath); if (enable_caller_privacy) - linphone_call_params_set_privacy(laure_params,LinphonePrivacyId); + linphone_call_params_set_privacy(laure_params,LinphonePrivacyId); CU_ASSERT_PTR_NOT_NULL(linphone_core_invite_address_with_params(laure->lc,pauline->identity,laure_params)); @@ -1185,7 +1185,7 @@ static void early_media_call_with_ringing(void){ marie_call = linphone_core_invite_address(marie->lc, pauline->identity); - CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingReceived,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingReceived,1,3000)); CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingRinging,1,1000)); From c08b540f7b09afc92759207ad39e4ac96e7b3c62 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 21 Mar 2014 19:06:33 +0100 Subject: [PATCH 17/55] fix crash in ms2, enhance audio assistant, fix crash when changing the record device --- gtk/audio_assistant.c | 54 +++++++++++++++++++++++-------------------- gtk/incall_view.c | 4 ++-- mediastreamer2 | 2 +- 3 files changed, 32 insertions(+), 28 deletions(-) diff --git a/gtk/audio_assistant.c b/gtk/audio_assistant.c index a9ecdd1bb..1e5bbddeb 100644 --- a/gtk/audio_assistant.c +++ b/gtk/audio_assistant.c @@ -25,37 +25,39 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "mediastreamer2/msvolume.h" static GtkWidget *audio_assistant=NULL; +static void prepare(GtkAssistant *w); GtkWidget *get_widget_from_assistant(const char *name){ return (GtkWidget *)g_object_get_data(G_OBJECT(audio_assistant),name); } -void set_widget_to_assistant(const char *name,GtkWidget *w){ + +static void set_widget_to_assistant(const char *name,GtkWidget *w){ g_object_set_data(G_OBJECT(audio_assistant),name,w); } -void update_record_button(gboolean is_visible){ +static void update_record_button(gboolean is_visible){ GtkWidget *rec_button = get_widget_from_assistant("rec_button"); gtk_widget_set_sensitive(rec_button,is_visible); } -void activate_record_button(gboolean is_active){ +#if 0 +static void activate_record_button(gboolean is_active){ GtkWidget *rec_button = get_widget_from_assistant("rec_button"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rec_button),is_active); } +#endif -void update_play_button(gboolean is_visible){ +static void update_play_button(gboolean is_visible){ GtkWidget *play_button = get_widget_from_assistant("play_button"); gtk_widget_set_sensitive(play_button,is_visible); } -void activate_play_button(gboolean is_active){ +static void activate_play_button(gboolean is_active){ GtkWidget *play_button = get_widget_from_assistant("play_button"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(play_button),is_active); } - - -gchar *get_record_file(){ +static gchar *get_record_file(){ char filename[256]={0}; char date[64]={0}; time_t curtime=time(NULL); @@ -72,7 +74,7 @@ gchar *get_record_file(){ return g_build_path(G_DIR_SEPARATOR_S,g_get_tmp_dir(),filename,NULL);; } -float audio_stream_get_record_volume(AudioStream *st){ +static float audio_stream_get_record_volume(AudioStream *st){ if (st && st->volsend){ float vol=0; ms_filter_call_method(st->volsend,MS_VOLUME_GET,&vol); @@ -81,7 +83,7 @@ float audio_stream_get_record_volume(AudioStream *st){ return LINPHONE_VOLUME_DB_LOWEST; } -float audio_stream_get_max_volume(AudioStream *st){ +static float audio_stream_get_max_volume(AudioStream *st){ if (st && st->volsend){ float vol=0; ms_filter_call_method(st->volsend,MS_VOLUME_GET_MAX,&vol); @@ -93,11 +95,11 @@ float audio_stream_get_max_volume(AudioStream *st){ static gboolean update_audio_label(volume_ctx_t *ctx){ float volume_db=ctx->get_volume(ctx->data); gchar *result; - if (volume_db < -30) result = "No Voice"; - if (volume_db > -30 && volume_db < -15) result = "Low"; - if (volume_db > -15 && volume_db < 0) result = "Good"; - if (volume_db > 0) result = "Too loud"; - //g_message("volume_db=%f, frac=%f",volume_db,frac); + if (volume_db < -20) result = _("No voice detected"); + else if (volume_db <= -10) result = _("Too low"); + else if (volume_db < -6) result = _("Good"); + else result = _("Too loud"); + g_message("volume_max_db=%f, text=%s",volume_db,result); gtk_label_set_text(GTK_LABEL(ctx->widget),result); return TRUE; } @@ -128,26 +130,30 @@ void linphone_gtk_uninit_audio_label(GtkWidget *w){ } } -void playback_device_changed(GtkWidget *w){ +static void playback_device_changed(GtkWidget *w){ gchar *sel=gtk_combo_box_get_active_text(GTK_COMBO_BOX(w)); linphone_core_set_playback_device(linphone_gtk_get_core(),sel); g_free(sel); } -void capture_device_changed(GtkWidget *capture_device){ +static void capture_device_changed(GtkWidget *capture_device){ gchar *sel; GtkWidget *mic_audiolevel; + GtkWidget *label_audiolevel; + GtkWidget *assistant=gtk_widget_get_toplevel(capture_device); AudioStream *audio_stream; mic_audiolevel = get_widget_from_assistant("mic_audiolevel"); - audio_stream = (AudioStream *) g_object_get_data(G_OBJECT(capture_device),"audio_stream"); + label_audiolevel = get_widget_from_assistant("label_audiolevel"); + audio_stream = (AudioStream *) g_object_get_data(G_OBJECT(assistant),"stream"); sel = gtk_combo_box_get_active_text(GTK_COMBO_BOX(capture_device)); linphone_core_set_capture_device(linphone_gtk_get_core(),sel); linphone_gtk_uninit_audio_meter(mic_audiolevel); + linphone_gtk_uninit_audio_label(label_audiolevel); audio_stream_stop(audio_stream); - linphone_gtk_init_audio_meter(mic_audiolevel,(get_volume_t)audio_stream_get_record_volume,audio_stream); - g_free(sel); + /*now restart the audio stream*/ + prepare(GTK_ASSISTANT(assistant)); } static void dialog_click(GtkWidget *dialog, guint response_id, GtkWidget *page){ @@ -370,7 +376,7 @@ static GtkWidget *create_end_page(){ return vbox; } -static void prepare(GtkAssistant *w, GtkWidget *p, void * data){ +static void prepare(GtkAssistant *w){ AudioStream *audio_stream = NULL; LinphoneCore *lc=linphone_gtk_get_core(); int page = gtk_assistant_get_current_page(w); @@ -380,14 +386,12 @@ static void prepare(GtkAssistant *w, GtkWidget *p, void * data){ //Speaker page if(page == 1){ MSSndCardManager *manager = ms_snd_card_manager_get(); - audio_stream = audio_stream_start_with_sndcards(&av_profile,9897,"127.0.0.1",9898,0,0,ms_snd_card_manager_get_card(manager,linphone_core_get_playback_device(lc)),ms_snd_card_manager_get_card(manager,linphone_core_get_capture_device(lc)),FALSE); - if(mic_audiolevel != NULL && audio_stream != NULL){ + audio_stream = audio_stream_start_with_sndcards(&av_profile,9898,"127.0.0.1",19898,0,0,ms_snd_card_manager_get_card(manager,linphone_core_get_playback_device(lc)),ms_snd_card_manager_get_card(manager,linphone_core_get_capture_device(lc)),FALSE); + if (mic_audiolevel != NULL && audio_stream != NULL){ g_object_set_data(G_OBJECT(audio_assistant),"stream",audio_stream); linphone_gtk_init_audio_meter(mic_audiolevel,(get_volume_t)audio_stream_get_record_volume,audio_stream); linphone_gtk_init_audio_label(label_audiolevel,(get_volume_t)audio_stream_get_max_volume,audio_stream); } - - } else if(page == 2 || page == 0){ if(mic_audiolevel != NULL && label_audiolevel != NULL){ audio_stream = (AudioStream *)g_object_get_data(G_OBJECT(audio_assistant),"stream"); diff --git a/gtk/incall_view.c b/gtk/incall_view.c index bdf54ec24..8ab6309f6 100644 --- a/gtk/incall_view.c +++ b/gtk/incall_view.c @@ -567,12 +567,12 @@ static gboolean linphone_gtk_in_call_view_refresh(LinphoneCall *call){ return TRUE; } -#define UNSIGNIFICANT_VOLUME (-26) +#define UNSIGNIFICANT_VOLUME (-23) #define SMOOTH 0.15 static gboolean update_audio_meter(volume_ctx_t *ctx){ float volume_db=ctx->get_volume(ctx->data); - float frac=(volume_db-UNSIGNIFICANT_VOLUME)/(float)(-UNSIGNIFICANT_VOLUME+3.0); + float frac=(volume_db-UNSIGNIFICANT_VOLUME)/(float)(-UNSIGNIFICANT_VOLUME-3.0); if (frac<0) frac=0; if (frac>1.0) frac=1.0; if (fraclast_value){ diff --git a/mediastreamer2 b/mediastreamer2 index aceebbf52..8663a08ed 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit aceebbf52fd94430c1aa17941f3d184be97a5b34 +Subproject commit 8663a08ed7bed3ceccaadd72e4ae3b9d5c568f31 From 9de8fe1b7659aecc3ceeb456484e7ec4c3af3ca0 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Sun, 23 Mar 2014 11:38:18 +0100 Subject: [PATCH 18/55] fix make dist --- po/POTFILES.in | 1 + 1 file changed, 1 insertion(+) diff --git a/po/POTFILES.in b/po/POTFILES.in index 988253adb..5d2aabf39 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -13,6 +13,7 @@ gtk/setupwizard.c gtk/incall_view.c gtk/loginframe.c gtk/config-fetching.c +gtk/audio_assistant.c [type: gettext/glade]gtk/main.ui [type: gettext/glade]gtk/about.ui [type: gettext/glade]gtk/contact.ui From 100e8e903e5bc930e3fffd6f071622710debe537 Mon Sep 17 00:00:00 2001 From: Margaux Clerc Date: Mon, 24 Mar 2014 15:11:32 +0100 Subject: [PATCH 19/55] Add audio assistant start icon --- .gitignore | 1 + configure.ac | 1 + gtk/audio_assistant.c | 8 ++++++-- gtk/linphone.h | 1 + gtk/main.c | 4 ++++ share/Makefile.am | 7 ++++--- share/audio-assistant.desktop.in | 9 +++++++++ 7 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 share/audio-assistant.desktop.in diff --git a/.gitignore b/.gitignore index 0512fc3df..2adb3b20b 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,7 @@ Specfile .anjuta_sym_db.db gtk-glade/version_date.h share/linphone.desktop +share/audio-assistant.desktop Debug/ build/macos/Info-linphone.plist coreapi/help/Doxyfile diff --git a/configure.ac b/configure.ac index c38507fa4..786cb6287 100644 --- a/configure.ac +++ b/configure.ac @@ -900,6 +900,7 @@ AC_CONFIG_FILES([ share/xml/Makefile share/linphone.pc share/linphone.desktop + share/audio-assistant.desktop scripts/Makefile tools/Makefile linphone.spec diff --git a/gtk/audio_assistant.c b/gtk/audio_assistant.c index 1e5bbddeb..431fa9995 100644 --- a/gtk/audio_assistant.c +++ b/gtk/audio_assistant.c @@ -407,10 +407,14 @@ static void prepare(GtkAssistant *w){ void linphone_gtk_close_audio_assistant(GtkWidget *w){ gchar *path = g_object_get_data(G_OBJECT(audio_assistant),"path"); - g_unlink(path); + if(path != NULL){ + g_unlink(path); + } gtk_widget_destroy(w); + if(linphone_gtk_get_audio_assistant_option()){ + gtk_main_quit(); + } audio_assistant = NULL; - linphone_gtk_show_main_window(); } void linphone_gtk_audio_assistant_apply(GtkWidget *w){ diff --git a/gtk/linphone.h b/gtk/linphone.h index 910981a53..2a256cab5 100644 --- a/gtk/linphone.h +++ b/gtk/linphone.h @@ -189,6 +189,7 @@ gchar *linphone_gtk_get_record_path(const LinphoneAddress *address, gboolean is_ void linphone_gtk_schedule_restart(void); void linphone_gtk_show_audio_assistant(void); +gboolean linphone_gtk_get_audio_assistant_option(void); void linphone_gtk_set_configuration_uri(void); GtkWidget * linphone_gtk_show_config_fetching(void); diff --git a/gtk/main.c b/gtk/main.c index 347abafce..2fd3fd897 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -271,6 +271,10 @@ void linphone_gtk_schedule_restart(void){ restart=TRUE; } +gboolean linphone_gtk_get_audio_assistant_option(void){ + return run_audio_assistant; +} + static void linphone_gtk_init_liblinphone(const char *config_file, const char *factory_config_file, const char *db_file) { LinphoneCoreVTable vtable={0}; diff --git a/share/Makefile.am b/share/Makefile.am index 63f15dfe4..f0df44261 100644 --- a/share/Makefile.am +++ b/share/Makefile.am @@ -23,7 +23,7 @@ ring_DATA=$(LINPHONE_RINGS) #to be compliant with freedesktop.org: linphone_fddir= $(datadir)/applications -linphone_fd_DATA= linphone.desktop +linphone_fd_DATA= linphone.desktop audio-assistant.desktop pkgconfigdir=$(libdir)/pkgconfig @@ -43,9 +43,10 @@ rootca.pem: cp -f $(srcdir)/archived-rootca.pem $(builddir)/rootca.pem ; \ fi -EXTRA_DIST = $(LINPHONE_SOUNDS) \ +EXTRA_DIST = $(LINPHONE_SOUNDS) \ $(LINPHONE_RINGS) \ - linphone.desktop.in \ + linphone.desktop.in \ + audio-assistant.desktop.in \ linphone.pc.in \ Makefile.inc \ archived-rootca.pem diff --git a/share/audio-assistant.desktop.in b/share/audio-assistant.desktop.in new file mode 100644 index 000000000..5e164ca2b --- /dev/null +++ b/share/audio-assistant.desktop.in @@ -0,0 +1,9 @@ +[Desktop Entry] +Name=Audio assistant +Comment=Linphone audio assistant +Comment[fr]=Assistant audio de Linphone. +Type=Application +Exec=linphone --run-audio-assistant +Icon=/usr/local/share/pixmaps/linphone/linphone.png +Terminal=false +Categories=Network;Telephony; \ No newline at end of file From a53029578d223077d2fdd70a5a83277dafc0b074 Mon Sep 17 00:00:00 2001 From: Margaux Clerc Date: Mon, 24 Mar 2014 15:51:02 +0100 Subject: [PATCH 20/55] Fix compilation with video disabled --- gtk/propertybox.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gtk/propertybox.c b/gtk/propertybox.c index 494f1a5fb..86356a97b 100644 --- a/gtk/propertybox.c +++ b/gtk/propertybox.c @@ -1280,6 +1280,7 @@ void linphone_gtk_fill_webcams(GtkWidget *pb){ } void linphone_gtk_fill_video_renderers(GtkWidget *pb){ +#ifdef VIDEO_ENABLED /* video_stream_get_default_video_renderer requires video enabled */ LinphoneCore *lc=linphone_gtk_get_core(); GtkWidget *combo=linphone_gtk_get_widget(pb,"renderers"); MSList *l=ms_filter_lookup_by_interface(MSFilterVideoDisplayInterface); @@ -1290,7 +1291,7 @@ void linphone_gtk_fill_video_renderers(GtkWidget *pb){ GtkListStore *store; GtkCellRenderer *renderer=gtk_cell_renderer_text_new(); GtkTreeModel *model=GTK_TREE_MODEL(store=gtk_list_store_new(2,G_TYPE_STRING,G_TYPE_STRING)); - + if (current_renderer==NULL) current_renderer=video_stream_get_default_video_renderer(); gtk_combo_box_set_model(GTK_COMBO_BOX(combo),model); @@ -1308,6 +1309,7 @@ void linphone_gtk_fill_video_renderers(GtkWidget *pb){ } ms_list_free(l); if (active!=-1) gtk_combo_box_set_active(GTK_COMBO_BOX(combo),active); +#endif } typedef struct { From 25e3c367483bfeeacb26fdc22d29588809be8d28 Mon Sep 17 00:00:00 2001 From: Margaux Clerc Date: Mon, 24 Mar 2014 16:30:01 +0100 Subject: [PATCH 21/55] Fix audio-assistant.ui gtk version --- gtk/audio_assistant.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtk/audio_assistant.ui b/gtk/audio_assistant.ui index 4fa0588c5..b8390f5d8 100644 --- a/gtk/audio_assistant.ui +++ b/gtk/audio_assistant.ui @@ -1,6 +1,6 @@ - + False From 9d31ca0e5d967b0cb1194955d9d3626312bcf150 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Mon, 24 Mar 2014 16:33:12 +0100 Subject: [PATCH 22/55] add java wrapper to LinphoneErrorInfo --- coreapi/linphonecore_jni.cc | 72 +++++++++++++++++++ java/common/org/linphone/core/ErrorInfo.java | 24 +++++++ .../org/linphone/core/LinphoneCall.java | 8 +++ .../linphone/core/LinphoneChatMessage.java | 14 ++-- .../org/linphone/core/LinphoneEvent.java | 6 ++ .../linphone/core/LinphoneProxyConfig.java | 6 ++ java/common/org/linphone/core/Reason.java | 4 ++ .../impl/org/linphone/core/ErrorInfoImpl.java | 41 +++++++++++ .../org/linphone/core/LinphoneCallImpl.java | 10 +++ .../core/LinphoneChatMessageImpl.java | 5 ++ .../org/linphone/core/LinphoneEventImpl.java | 5 ++ .../core/LinphoneProxyConfigImpl.java | 5 ++ 12 files changed, 196 insertions(+), 4 deletions(-) create mode 100644 java/common/org/linphone/core/ErrorInfo.java create mode 100644 java/impl/org/linphone/core/ErrorInfoImpl.java diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 51346f696..b64a684f8 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -1622,6 +1622,10 @@ extern "C" jint Java_org_linphone_core_LinphoneProxyConfigImpl_getError(JNIEnv* return linphone_proxy_config_get_error((LinphoneProxyConfig *) ptr); } +extern "C" jlong Java_org_linphone_core_LinphoneProxyConfigImpl_getErrorInfo(JNIEnv* env,jobject thiz,jlong ptr) { + return (jlong)linphone_proxy_config_get_error_info((LinphoneProxyConfig *) ptr); +} + //Auth Info extern "C" jlong Java_org_linphone_core_LinphoneAuthInfoImpl_newLinphoneAuthInfo(JNIEnv* env @@ -2074,6 +2078,18 @@ extern "C" jlong Java_org_linphone_core_LinphoneCallImpl_getRemoteAddress( JNIEn return (jlong)linphone_call_get_remote_address((LinphoneCall*)ptr); } +extern "C" jlong Java_org_linphone_core_LinphoneCallImpl_getErrorInfo( JNIEnv* env + ,jobject thiz + ,jlong ptr) { + return (jlong)linphone_call_get_error_info((LinphoneCall*)ptr); +} + +extern "C" jint Java_org_linphone_core_LinphoneCallImpl_getReason( JNIEnv* env + ,jobject thiz + ,jlong ptr) { + return (jint)linphone_call_get_reason((LinphoneCall*)ptr); +} + extern "C" jstring Java_org_linphone_core_LinphoneCallImpl_getRemoteUserAgent(JNIEnv *env, jobject thiz, jlong ptr) { LinphoneCall *call = (LinphoneCall *)ptr; const char *value=linphone_call_get_remote_user_agent(call); @@ -2400,6 +2416,12 @@ extern "C" jint Java_org_linphone_core_LinphoneChatMessageImpl_getReason(JNIEnv* return linphone_chat_message_get_reason((LinphoneChatMessage*)ptr); } +extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getErrorInfo(JNIEnv* env + ,jobject thiz + ,jlong ptr) { + return (jlong)linphone_chat_message_get_error_info((LinphoneChatMessage*)ptr); +} + extern "C" jstring Java_org_linphone_core_LinphoneChatMessageImpl_getCustomHeader(JNIEnv* env ,jobject thiz ,jlong ptr, jstring jheader_name) { @@ -3684,6 +3706,11 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_getReason(JNIEnv return linphone_event_get_reason(ev); } +JNIEXPORT jlong JNICALL Java_org_linphone_core_LinphoneEventImpl_getErrorInfo(JNIEnv *env, jobject jobj, jlong evptr){ + LinphoneEvent *ev=(LinphoneEvent*)evptr; + return (jlong)linphone_event_get_error_info(ev); +} + /* * Class: org_linphone_core_LinphoneEventImpl * Method: getSubscriptionDir @@ -4616,4 +4643,49 @@ JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneCoreImpl_isSdp200AckEn return (jboolean)linphone_core_sdp_200_ack_enabled((const LinphoneCore*)lc); } +/* Header for class org_linphone_core_ErrorInfoImpl */ +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_linphone_core_ErrorInfoImpl + * Method: getReason + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_linphone_core_ErrorInfoImpl_getReason(JNIEnv *env, jobject jobj, jlong ei){ + return linphone_error_info_get_reason((const LinphoneErrorInfo*)ei); +} + +/* + * Class: org_linphone_core_ErrorInfoImpl + * Method: getProtocolCode + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_linphone_core_ErrorInfoImpl_getProtocolCode(JNIEnv *env, jobject jobj, jlong ei){ + return linphone_error_info_get_protocol_code((const LinphoneErrorInfo*)ei); +} + +/* + * Class: org_linphone_core_ErrorInfoImpl + * Method: getPhrase + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_linphone_core_ErrorInfoImpl_getPhrase(JNIEnv *env, jobject jobj, jlong ei){ + const char *tmp=linphone_error_info_get_phrase((const LinphoneErrorInfo*)ei); + return tmp ? env->NewStringUTF(tmp) : NULL; +} + +/* + * Class: org_linphone_core_ErrorInfoImpl + * Method: getDetails + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_linphone_core_ErrorInfoImpl_getDetails(JNIEnv *env, jobject jobj, jlong ei){ + const char *tmp=linphone_error_info_get_details((const LinphoneErrorInfo*)ei); + return tmp ? env->NewStringUTF(tmp) : NULL; +} + +#ifdef __cplusplus +} +#endif diff --git a/java/common/org/linphone/core/ErrorInfo.java b/java/common/org/linphone/core/ErrorInfo.java new file mode 100644 index 000000000..348f7fd61 --- /dev/null +++ b/java/common/org/linphone/core/ErrorInfo.java @@ -0,0 +1,24 @@ +package org.linphone.core; + +public interface ErrorInfo { + /** + * Return the Reason enum corresponding to the error type. + * @return the reason. + */ + Reason getReason(); + /** + * Get the protocol code corresponding to the error (typically a SIP status code). + * @return the code. + */ + int getProtocolCode(); + /** + * Get the reason-phrase provided by the protocol (typically a SIP reason-phrase). + * @return the reason phrase. + */ + String getPhrase(); + /** + * Get details about the error, if provided by the protocol. For SIP it consists of the content of a Warning or Reason header. + * @return details about the error. + */ + String getDetails(); +} diff --git a/java/common/org/linphone/core/LinphoneCall.java b/java/common/org/linphone/core/LinphoneCall.java index 62be0d638..90fe60ded 100644 --- a/java/common/org/linphone/core/LinphoneCall.java +++ b/java/common/org/linphone/core/LinphoneCall.java @@ -315,4 +315,12 @@ public interface LinphoneCall { **/ LinphoneCall getTransferTargetCall(); + Reason getReason(); + + /** + * Returns last error reported for the call. + * @return an ErrorInfo. + */ + ErrorInfo getErrorInfo(); + } diff --git a/java/common/org/linphone/core/LinphoneChatMessage.java b/java/common/org/linphone/core/LinphoneChatMessage.java index 7d5d8b472..356294102 100644 --- a/java/common/org/linphone/core/LinphoneChatMessage.java +++ b/java/common/org/linphone/core/LinphoneChatMessage.java @@ -142,8 +142,14 @@ public interface LinphoneChatMessage { */ int getStorageId(); - /** - * @return the reason if response received - */ - Reason getReason(); + /** + * @return the reason if response received + */ + Reason getReason(); + + /** + * Returns full error in case of failure when sending message. + * @return an ErrorInfo. + */ + ErrorInfo getErrorInfo(); } diff --git a/java/common/org/linphone/core/LinphoneEvent.java b/java/common/org/linphone/core/LinphoneEvent.java index cdc34d404..dcdfcfc48 100644 --- a/java/common/org/linphone/core/LinphoneEvent.java +++ b/java/common/org/linphone/core/LinphoneEvent.java @@ -58,6 +58,12 @@ public interface LinphoneEvent { */ Reason getReason(); + /** + * In case of error notified, returns the full error details. + * @return an ErrorInfo. + */ + ErrorInfo getErrorInfo(); + /** * Assign an application context to the LinphoneEvent, for later use. * @param obj diff --git a/java/common/org/linphone/core/LinphoneProxyConfig.java b/java/common/org/linphone/core/LinphoneProxyConfig.java index e613fd194..0ff1900a3 100644 --- a/java/common/org/linphone/core/LinphoneProxyConfig.java +++ b/java/common/org/linphone/core/LinphoneProxyConfig.java @@ -211,4 +211,10 @@ public interface LinphoneProxyConfig { * @return reason code. */ public Reason getError(); + + /** + * Get full error information about last error occured on the proxy config. + * @return an ErrorInfo. + */ + public ErrorInfo getErrorInfo(); } diff --git a/java/common/org/linphone/core/Reason.java b/java/common/org/linphone/core/Reason.java index d08a53e46..0d7625a36 100644 --- a/java/common/org/linphone/core/Reason.java +++ b/java/common/org/linphone/core/Reason.java @@ -84,6 +84,10 @@ public class Reason { * Server timeout */ static public Reason ServerTimeout = new Reason(19,"ServerTimeout"); + /** + * Unknown + */ + static public Reason Unknown = new Reason(20,"Unknown"); protected final int mValue; private final String mStringValue; diff --git a/java/impl/org/linphone/core/ErrorInfoImpl.java b/java/impl/org/linphone/core/ErrorInfoImpl.java new file mode 100644 index 000000000..e9b6bd5f3 --- /dev/null +++ b/java/impl/org/linphone/core/ErrorInfoImpl.java @@ -0,0 +1,41 @@ +package org.linphone.core; + +public class ErrorInfoImpl implements ErrorInfo { + private Reason mReason; + private int mCode; + private String mPhrase; + private String mDetails; + + private native int getReason(long nativePtr); + private native int getProtocolCode(long nativePtr); + private native String getPhrase(long nativePtr); + private native String getDetails(long nativePtr); + + public ErrorInfoImpl(long nativePtr){ + mReason=Reason.fromInt(getReason(nativePtr)); + mCode=getProtocolCode(nativePtr); + mPhrase=getPhrase(nativePtr); + mDetails=getDetails(nativePtr); + } + + @Override + public Reason getReason() { + return mReason; + } + + @Override + public int getProtocolCode() { + return mCode; + } + + @Override + public String getPhrase() { + return mPhrase; + } + + @Override + public String getDetails() { + return mDetails; + } + +} diff --git a/java/impl/org/linphone/core/LinphoneCallImpl.java b/java/impl/org/linphone/core/LinphoneCallImpl.java index af79eb725..66a9bf1d9 100644 --- a/java/impl/org/linphone/core/LinphoneCallImpl.java +++ b/java/impl/org/linphone/core/LinphoneCallImpl.java @@ -226,4 +226,14 @@ class LinphoneCallImpl implements LinphoneCall { public LinphoneCall getTransferTargetCall() { return (LinphoneCall)getTransferTargetCall(nativePtr); } + @Override + public Reason getReason() { + // TODO Auto-generated method stub + return null; + } + private native long getErrorInfo(long nativePtr); + @Override + public ErrorInfo getErrorInfo() { + return new ErrorInfoImpl(getErrorInfo(nativePtr)); + } } diff --git a/java/impl/org/linphone/core/LinphoneChatMessageImpl.java b/java/impl/org/linphone/core/LinphoneChatMessageImpl.java index 2708a82af..a891cad8b 100644 --- a/java/impl/org/linphone/core/LinphoneChatMessageImpl.java +++ b/java/impl/org/linphone/core/LinphoneChatMessageImpl.java @@ -100,4 +100,9 @@ public class LinphoneChatMessageImpl implements LinphoneChatMessage { public Reason getReason() { return Reason.fromInt(getReason(nativePtr)); } + private native long getErrorInfo(long nativePtr); + @Override + public ErrorInfo getErrorInfo() { + return new ErrorInfoImpl(getErrorInfo(nativePtr)); + } } diff --git a/java/impl/org/linphone/core/LinphoneEventImpl.java b/java/impl/org/linphone/core/LinphoneEventImpl.java index 42d14ef20..2b4c1a71b 100644 --- a/java/impl/org/linphone/core/LinphoneEventImpl.java +++ b/java/impl/org/linphone/core/LinphoneEventImpl.java @@ -118,5 +118,10 @@ public class LinphoneEventImpl implements LinphoneEvent { else sendPublish(mNativePtr, null, null, null, null); } + private native long getErrorInfo(long nativePtr); + @Override + public ErrorInfo getErrorInfo() { + return new ErrorInfoImpl(getErrorInfo(mNativePtr)); + } } diff --git a/java/impl/org/linphone/core/LinphoneProxyConfigImpl.java b/java/impl/org/linphone/core/LinphoneProxyConfigImpl.java index 2fe08ad91..96b153733 100644 --- a/java/impl/org/linphone/core/LinphoneProxyConfigImpl.java +++ b/java/impl/org/linphone/core/LinphoneProxyConfigImpl.java @@ -207,4 +207,9 @@ class LinphoneProxyConfigImpl implements LinphoneProxyConfig { public String getContactUriParameters() { return getContactUriParameters(nativePtr); } + private native long getErrorInfo(long nativePtr); + @Override + public ErrorInfo getErrorInfo() { + return new ErrorInfoImpl(getErrorInfo(nativePtr)); + } } From cf25820aec64a6ecb676eae872cf106f42fb0085 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Mon, 24 Mar 2014 16:53:13 +0100 Subject: [PATCH 23/55] add new checks for ErrorInfo mechanism --- tester/eventapi_tester.c | 12 +++++++++++- tester/register_tester.c | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/tester/eventapi_tester.c b/tester/eventapi_tester.c index 49f0cdc83..5f10a5183 100644 --- a/tester/eventapi_tester.c +++ b/tester/eventapi_tester.c @@ -111,6 +111,8 @@ static void subscribe_test_declined(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); LinphoneContent content={0}; + LinphoneEvent *lev; + const LinphoneErrorInfo *ei; MSList* lcs=ms_list_append(NULL,marie->lc); lcs=ms_list_append(lcs,pauline->lc); @@ -122,13 +124,21 @@ static void subscribe_test_declined(void) { pauline->decline_subscribe=TRUE; - linphone_core_subscribe(marie->lc,pauline->identity,"dodo",600,&content); + lev=linphone_core_subscribe(marie->lc,pauline->identity,"dodo",600,&content); + linphone_event_ref(lev); CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingInit,1,1000)); CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,1000)); CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionError,1,21000));/*yes flexisip may wait 20 secs in case of forking*/ + ei=linphone_event_get_error_info(lev); + CU_ASSERT_PTR_NOT_NULL(ei); + if (ei){ + CU_ASSERT_EQUAL(linphone_error_info_get_protocol_code(ei),603); + CU_ASSERT_PTR_NOT_NULL(linphone_error_info_get_phrase(ei)); + } CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionTerminated,1,1000)); + linphone_event_unref(lev); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } diff --git a/tester/register_tester.c b/tester/register_tester.c index 547c2cec4..28850e141 100644 --- a/tester/register_tester.c +++ b/tester/register_tester.c @@ -356,6 +356,22 @@ static void authenticated_register_with_wrong_credentials_with_params(const char /*wait for retry*/ CU_ASSERT_TRUE(wait_for(mgr->lc,mgr->lc,&counters->number_of_auth_info_requested,4)); CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,1); + + /*check the detailed error info */ + if (!user_agent || strcmp(user_agent,"tester-no-403")!=0){ + LinphoneProxyConfig *cfg=NULL; + linphone_core_get_default_proxy(mgr->lc,&cfg); + CU_ASSERT_PTR_NOT_NULL(cfg); + if (cfg){ + const LinphoneErrorInfo *ei=linphone_proxy_config_get_error_info(cfg); + const char *phrase=linphone_error_info_get_phrase(ei); + CU_ASSERT_PTR_NOT_NULL(phrase); + if (phrase) CU_ASSERT_TRUE(strcmp(phrase,"Forbidden")==0); + CU_ASSERT_EQUAL(linphone_error_info_get_protocol_code(ei),403); + CU_ASSERT_PTR_NULL(linphone_error_info_get_details(ei)); + } + + } linphone_core_manager_destroy(mgr); } static void authenticated_register_with_wrong_credentials() { From 546dcfb160e81142911837203c9c9726804287a7 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Tue, 25 Mar 2014 10:58:18 +0100 Subject: [PATCH 24/55] enable real early media sending for incoming calls. --- coreapi/callbacks.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 80818be37..f7a1fa363 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -143,8 +143,7 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia if (call->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){ send_ringbacktone=TRUE; } - if (call->state==LinphoneCallIncomingEarlyMedia || - (call->state==LinphoneCallOutgoingEarlyMedia && !call->params.real_early_media)){ + if ((call->state==LinphoneCallIncomingEarlyMedia || call->state==LinphoneCallOutgoingEarlyMedia) && !call->params.real_early_media){ all_muted=TRUE; } linphone_call_start_media_streams(call,all_muted,send_ringbacktone); From 51bd9c2c9c09ad409556f7d7e37602aa00c64cb3 Mon Sep 17 00:00:00 2001 From: Margaux Clerc Date: Tue, 25 Mar 2014 11:07:22 +0100 Subject: [PATCH 25/55] Add audio-assistant in rpm --- linphone.spec.in | 1 + 1 file changed, 1 insertion(+) diff --git a/linphone.spec.in b/linphone.spec.in index 728ad5151..eb8c65b51 100644 --- a/linphone.spec.in +++ b/linphone.spec.in @@ -85,6 +85,7 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/*.so.* %{_mandir}/* %{_datadir}/applications/%{name}.desktop +%{_datadir}/applications/audio-assistant.desktop %{_datadir}/pixmaps/linphone %{_datadir}/linphone %{_datadir}/pixmaps/linphone.png From c25273e9ca522bb096364ffddf50a68f43f70cfc Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Tue, 25 Mar 2014 12:48:17 +0100 Subject: [PATCH 26/55] add C function to disable chat --- coreapi/bellesip_sal/sal_op_message.c | 21 ++++++++++++++++++--- coreapi/callbacks.c | 5 ++++- coreapi/chat.c | 25 +++++++++++++++++++++++++ coreapi/linphonecore.h | 3 +++ coreapi/private.h | 1 + include/sal/sal.h | 1 + tester/message_tester.c | 20 ++++++++++++++++++++ 7 files changed, 72 insertions(+), 4 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_message.c b/coreapi/bellesip_sal/sal_op_message.c index 05f1199b8..c346347d0 100644 --- a/coreapi/bellesip_sal/sal_op_message.c +++ b/coreapi/bellesip_sal/sal_op_message.c @@ -92,6 +92,11 @@ void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *eve || (external_body=is_external_body(content_type)))) { SalMessage salmsg; char message_id[256]={0}; + + if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); + op->pending_server_trans=server_transaction; + belle_sip_object_ref(op->pending_server_trans); + address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address)); @@ -120,6 +125,8 @@ void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *eve saliscomposing.from=from; saliscomposing.text=belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); op->base.root->callbacks.is_composing_received(op,&saliscomposing); + resp = belle_sip_response_create_from_request(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); belle_sip_object_unref(address); belle_sip_free(from); } else { @@ -130,14 +137,11 @@ void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *eve belle_sip_server_transaction_send_response(server_transaction,resp); return; } - resp = belle_sip_response_create_from_request(req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); } static void process_request_event(void *op_base, const belle_sip_request_event_t *event) { SalOp* op = (SalOp*)op_base; sal_process_incoming_message(op,event); - sal_op_release(op); } int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg){ @@ -171,6 +175,17 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co } +int sal_message_reply(SalOp *op, SalReason reason){ + if (op->pending_server_trans){ + int code=sal_reason_to_sip_code(reason); + belle_sip_response_t *resp = belle_sip_response_create_from_request( + belle_sip_transaction_get_request((belle_sip_transaction_t*)op->pending_server_trans),code); + belle_sip_server_transaction_send_response(op->pending_server_trans,resp); + return 0; + }else ms_error("sal_message_reply(): no server transaction"); + return -1; +} + int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg) { return sal_message_send(op,from,to,"text/plain",msg); } diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index f7a1fa363..0daf09cd2 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -878,9 +878,12 @@ static bool_t is_duplicate_msg(LinphoneCore *lc, const char *msg_id){ static void text_received(SalOp *op, const SalMessage *msg){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - if (is_duplicate_msg(lc,msg->message_id)==FALSE){ + LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); + if (lc->chat_deny_code==LinphoneReasonNone && is_duplicate_msg(lc,msg->message_id)==FALSE){ linphone_core_message_received(lc,op,msg); } + sal_message_reply(op,lc->chat_deny_code); + if (!call) sal_op_release(op); } static void is_composing_received(SalOp *op, const SalIsComposing *is_composing) { diff --git a/coreapi/chat.c b/coreapi/chat.c index 264d6d768..ef01b8b11 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -37,6 +37,31 @@ * @{ */ +/** + * Inconditionnaly disable incoming chat messages. + * @param lc the core + * @param deny_reason the deny reason (#LinphoneReasonNone has no effect). +**/ +void linphone_core_disable_chat(LinphoneCore *lc, LinphoneReason deny_reason){ + lc->chat_deny_code=deny_reason; +} + +/** + * Enable reception of incoming chat messages. + * By default it is enabled but it can be disabled with linphone_core_disable_chat(). + * @param lc the core +**/ +void linphone_core_enable_chat(LinphoneCore *lc){ + lc->chat_deny_code=LinphoneReasonNone; +} + +/** + * Returns whether chat is enabled. +**/ +bool_t linphone_core_chat_enabled(const LinphoneCore *lc){ + return lc->chat_deny_code!=LinphoneReasonNone; +} + /** * Returns an array of chat rooms * @param lc #LinphoneCore object diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index f2d4b2514..927b46a43 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -1038,6 +1038,9 @@ LINPHONE_PUBLIC void linphone_core_set_chat_database_path(LinphoneCore *lc, cons LINPHONE_PUBLIC LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to); LINPHONE_PUBLIC LinphoneChatRoom * linphone_core_get_or_create_chat_room(LinphoneCore *lc, const char *to); LINPHONE_PUBLIC LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr); +LINPHONE_PUBLIC void linphone_core_disable_chat(LinphoneCore *lc, LinphoneReason deny_reason); +LINPHONE_PUBLIC void linphone_core_enable_chat(LinphoneCore *lc); +LINPHONE_PUBLIC bool_t linphone_core_chat_enabled(const LinphoneCore *lc); LINPHONE_PUBLIC void linphone_chat_room_destroy(LinphoneChatRoom *cr); LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr,const char* message); LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_message_2(LinphoneChatRoom *cr, const char* message, const char* external_body_url, LinphoneChatMessageState state, time_t time, bool_t is_read, bool_t is_incoming); diff --git a/coreapi/private.h b/coreapi/private.h index 18de67587..a9bd1f0bf 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -681,6 +681,7 @@ struct _LinphoneCore #endif //BUILD_UPNP belle_http_provider_t *http_provider; MSList *tones; + LinphoneReason chat_deny_code; }; diff --git a/include/sal/sal.h b/include/sal/sal.h index f508484ec..9990d099e 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -618,6 +618,7 @@ int sal_unregister(SalOp *h); /*Messaging */ int sal_text_send(SalOp *op, const char *from, const char *to, const char *text); int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg); +int sal_message_reply(SalOp *op, SalReason reason); /*presence Subscribe/notify*/ int sal_subscribe_presence(SalOp *op, const char *from, const char *to, int expires); diff --git a/tester/message_tester.c b/tester/message_tester.c index 5cf1b54a8..259727715 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -263,6 +263,25 @@ static void text_message_with_send_error(void) { linphone_core_manager_destroy(pauline); } +static void text_message_denied(void) { + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + char* to = linphone_address_as_string(pauline->identity); + LinphoneChatRoom* chat_room = linphone_core_create_chat_room(marie->lc,to); + LinphoneChatMessage* message = linphone_chat_room_create_message(chat_room,"Bli bli bli \n blu"); + + /*pauline doesn't want to be disturbed*/ + linphone_core_disable_chat(pauline->lc,LinphoneReasonDoNotDisturb); + + linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,marie->lc); + + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageNotDelivered,1)); + CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageReceived,0); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + static const char *info_content="blabla"; void info_message_received(LinphoneCore *lc, LinphoneCall* call, const LinphoneInfoMessage *msg){ @@ -360,6 +379,7 @@ test_t message_tests[] = { { "Text message with ack", text_message_with_ack }, { "Text message with send error", text_message_with_send_error }, { "Text message with external body", text_message_with_external_body }, + { "Text message denied", text_message_denied }, { "Info message", info_message }, { "Info message with body", info_message_with_body }, { "IsComposing notification", is_composing_notification } From 2276fd70fe35e3d7132f83228b691d4fd8a92768 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Tue, 25 Mar 2014 13:11:15 +0100 Subject: [PATCH 27/55] wrap chat enablement methods to java --- coreapi/linphonecore_jni.cc | 28 +++++++ .../org/linphone/core/LinphoneCore.java | 20 +++++ .../org/linphone/core/LinphoneCoreImpl.java | 79 +++++++++++-------- 3 files changed, 95 insertions(+), 32 deletions(-) diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index b64a684f8..fc793f2c5 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -1455,6 +1455,34 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_createProxyConfig(JNIEn return (jlong) proxy; } +/* + * Class: org_linphone_core_LinphoneCoreImpl + * Method: disableChat + * Signature: (JI)V + */ +extern "C" JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_disableChat(JNIEnv *env, jobject jobj, jlong ptr, jint reason){ + linphone_core_disable_chat((LinphoneCore*)ptr,(LinphoneReason)reason); +} + +/* + * Class: org_linphone_core_LinphoneCoreImpl + * Method: enableChat + * Signature: (J)V + */ +extern "C" JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_enableChat(JNIEnv *env, jobject jobj, jlong ptr){ + linphone_core_enable_chat((LinphoneCore*)ptr); +} + +/* + * Class: org_linphone_core_LinphoneCoreImpl + * Method: chatEnabled + * Signature: (J)Z + */ +extern "C" JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneCoreImpl_chatEnabled(JNIEnv *env, jobject jobj, jlong ptr){ + return (jboolean) linphone_core_chat_enabled((LinphoneCore*)ptr); +} + + //ProxyConfig extern "C" jlong Java_org_linphone_core_LinphoneProxyConfigImpl_newLinphoneProxyConfig(JNIEnv* env,jobject thiz) { diff --git a/java/common/org/linphone/core/LinphoneCore.java b/java/common/org/linphone/core/LinphoneCore.java index 5a211736c..72164a3fe 100644 --- a/java/common/org/linphone/core/LinphoneCore.java +++ b/java/common/org/linphone/core/LinphoneCore.java @@ -1564,5 +1564,25 @@ public interface LinphoneCore { */ public boolean isSdp200AckEnabled(); + /** + * Inconditionnaly disable incoming chat messages. + * @param lc the core + * @param deny_reason the deny reason (using ReasonNone has no effect). + **/ + public void disableChat(Reason denycode); + + /** + * Enable reception of incoming chat messages. + * By default it is enabled but it can be disabled with linphone_core_disable_chat(). + * @param lc the core + **/ + public void enableChat(); + + + /** + * Returns whether chat is enabled. + * @return true if chat is enabled, false otherwise. + **/ + public boolean chatEnabled(); } diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java index 5eeb0ac37..16ca38e36 100644 --- a/java/impl/org/linphone/core/LinphoneCoreImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java @@ -966,79 +966,79 @@ class LinphoneCoreImpl implements LinphoneCore { } private native boolean upnpAvailable(long ptr); - public boolean upnpAvailable() { + public synchronized boolean upnpAvailable() { return upnpAvailable(nativePtr); } private native int getUpnpState(long ptr); - public UpnpState getUpnpState() { + public synchronized UpnpState getUpnpState() { return UpnpState.fromInt(getUpnpState(nativePtr)); } private native String getUpnpExternalIpaddress(long ptr); - public String getUpnpExternalIpaddress() { + public synchronized String getUpnpExternalIpaddress() { return getUpnpExternalIpaddress(nativePtr); } private native int startConferenceRecording(long nativePtr, String path); @Override - public void startConferenceRecording(String path) { + public synchronized void startConferenceRecording(String path) { startConferenceRecording(nativePtr,path); } private native int stopConferenceRecording(long nativePtr); @Override - public void stopConferenceRecording() { + public synchronized void stopConferenceRecording() { stopConferenceRecording(nativePtr); } @Override - public PayloadType findPayloadType(String mime) { + public synchronized PayloadType findPayloadType(String mime) { return findPayloadType(mime, FIND_PAYLOAD_IGNORE_RATE); } private native void setSipDscp(long nativePtr, int dscp); @Override - public void setSipDscp(int dscp) { + public synchronized void setSipDscp(int dscp) { setSipDscp(nativePtr,dscp); } private native int getSipDscp(long nativePtr); @Override - public int getSipDscp() { + public synchronized int getSipDscp() { return getSipDscp(nativePtr); } private native void setAudioDscp(long nativePtr, int dscp); @Override - public void setAudioDscp(int dscp) { + public synchronized void setAudioDscp(int dscp) { setAudioDscp(nativePtr, dscp); } private native int getAudioDscp(long nativePtr); @Override - public int getAudioDscp() { + public synchronized int getAudioDscp() { return getAudioDscp(nativePtr); } private native void setVideoDscp(long nativePtr, int dscp); @Override - public void setVideoDscp(int dscp) { + public synchronized void setVideoDscp(int dscp) { setVideoDscp(nativePtr,dscp); } private native int getVideoDscp(long nativePtr); @Override - public int getVideoDscp() { + public synchronized int getVideoDscp() { return getVideoDscp(nativePtr); } private native long createInfoMessage(long nativeptr); @Override - public LinphoneInfoMessage createInfoMessage() { + public synchronized LinphoneInfoMessage createInfoMessage() { return new LinphoneInfoMessageImpl(createInfoMessage(nativePtr)); } private native Object subscribe(long coreptr, long addrptr, String eventname, int expires, String type, String subtype, byte data [], String encoding); @Override - public LinphoneEvent subscribe(LinphoneAddress resource, String eventname, + public synchronized LinphoneEvent subscribe(LinphoneAddress resource, String eventname, int expires, LinphoneContent content) { return (LinphoneEvent)subscribe(nativePtr, ((LinphoneAddressImpl)resource).nativePtr, eventname, expires, content!=null ? content.getType() : null, content!=null ? content.getSubtype() : null, content!=null ? content.getData() : null, @@ -1046,7 +1046,7 @@ class LinphoneCoreImpl implements LinphoneCore { } private native Object publish(long coreptr, long addrptr, String eventname, int expires, String type, String subtype, byte data [], String encoding); @Override - public LinphoneEvent publish(LinphoneAddress resource, String eventname, + public synchronized LinphoneEvent publish(LinphoneAddress resource, String eventname, int expires, LinphoneContent content) { return (LinphoneEvent)publish(nativePtr, ((LinphoneAddressImpl)resource).nativePtr, eventname, expires, content!=null ? content.getType() : null, content!=null ? content.getSubtype() : null, content!=null ? content.getData() : null, @@ -1055,18 +1055,18 @@ class LinphoneCoreImpl implements LinphoneCore { private native Object createSubscribe(long core, long addr, String event, int expires); @Override - public LinphoneEvent createSubscribe(LinphoneAddress resource, + public synchronized LinphoneEvent createSubscribe(LinphoneAddress resource, String event, int expires) { return (LinphoneEvent)createSubscribe(nativePtr, ((LinphoneAddressImpl)resource).nativePtr, event, expires); } private native Object createPublish(long core, long addr, String event, int expires); @Override - public LinphoneEvent createPublish(LinphoneAddress resource, + public synchronized LinphoneEvent createPublish(LinphoneAddress resource, String event, int expires) { return (LinphoneEvent)createPublish(nativePtr, ((LinphoneAddressImpl)resource).nativePtr, event, expires); } - public void setChatDatabasePath(String path) { + public synchronized void setChatDatabasePath(String path) { setChatDatabasePath(nativePtr, path); } @@ -1082,7 +1082,7 @@ class LinphoneCoreImpl implements LinphoneCore { return proxies; } - public LinphoneAuthInfo[] getAuthInfosList() { + public synchronized LinphoneAuthInfo[] getAuthInfosList() { long[] typesPtr = getAuthInfosList(nativePtr); if (typesPtr == null) return null; @@ -1095,7 +1095,7 @@ class LinphoneCoreImpl implements LinphoneCore { return authInfos; } - public LinphoneAuthInfo findAuthInfo(String username, String realm, String domain) { + public synchronized LinphoneAuthInfo findAuthInfo(String username, String realm, String domain) { long ptr = findAuthInfos(nativePtr, username, realm, domain); if (ptr == 0) return null; @@ -1104,7 +1104,7 @@ class LinphoneCoreImpl implements LinphoneCore { } private native LinphoneCall startReferedCall(long corePtr, long callptr, long paramsPtr); @Override - public LinphoneCall startReferedCall(LinphoneCall call, + public synchronized LinphoneCall startReferedCall(LinphoneCall call, LinphoneCallParams params) { long ptrParams =((LinphoneCallParamsImpl)params).nativePtr; return startReferedCall(nativePtr, getCallPtr(call), ptrParams); @@ -1112,58 +1112,73 @@ class LinphoneCoreImpl implements LinphoneCore { private native String[] listSupportedVideoResolutions(long ptr); @Override - public String[] getSupportedVideoSizes() { + public synchronized String[] getSupportedVideoSizes() { return listSupportedVideoResolutions(nativePtr); } @Override - public int migrateToMultiTransport() { + public synchronized int migrateToMultiTransport() { return migrateToMultiTransport(nativePtr); } private native boolean acceptEarlyMedia(long lc, long call); @Override - public boolean acceptEarlyMedia(LinphoneCall call) { + public synchronized boolean acceptEarlyMedia(LinphoneCall call) { return acceptEarlyMedia(nativePtr, getCallPtr(call)); } private native boolean acceptEarlyMediaWithParams(long lc, long call, long params); @Override - public boolean acceptEarlyMediaWithParams(LinphoneCall call, + public synchronized boolean acceptEarlyMediaWithParams(LinphoneCall call, LinphoneCallParams params) { long ptrParams = params != null ? ((LinphoneCallParamsImpl) params).nativePtr : 0; return acceptEarlyMediaWithParams(nativePtr, getCallPtr(call), ptrParams); } @Override - public LinphoneProxyConfig createProxyConfig() { + public synchronized LinphoneProxyConfig createProxyConfig() { return new LinphoneProxyConfigImpl(createProxyConfig(nativePtr)); } @Override - public void setCallErrorTone(Reason reason, String path) { + public synchronized void setCallErrorTone(Reason reason, String path) { setCallErrorTone(nativePtr, reason.mValue, path); } private native void setMtu(long nativePtr, int mtu); @Override - public void setMtu(int mtu) { + public synchronized void setMtu(int mtu) { setMtu(nativePtr,mtu); } private native int getMtu(long nativePtr); @Override - public int getMtu() { + public synchronized int getMtu() { return getMtu(nativePtr); } @Override - public void enableSdp200Ack(boolean enable) { + public synchronized void enableSdp200Ack(boolean enable) { enableSdp200Ack(nativePtr,enable); } @Override - public boolean isSdp200AckEnabled() { + public synchronized boolean isSdp200AckEnabled() { return isSdp200AckEnabled(nativePtr); } private native void setTone(long nativePtr, int id, String wavfile); @Override - public void setTone(ToneID id, String wavfile) { + public synchronized void setTone(ToneID id, String wavfile) { setTone(nativePtr, id.mValue, wavfile); } + private native void disableChat(long ptr, int denycode); + @Override + public synchronized void disableChat(Reason denycode) { + disableChat(nativePtr,denycode.mValue); + } + private native void enableChat(long ptr); + @Override + public synchronized void enableChat() { + enableChat(nativePtr); + } + private native boolean chatEnabled(long ptr); + @Override + public synchronized boolean chatEnabled() { + return chatEnabled(nativePtr); + } } From 21319737c9ab566f03f2c20f1bc3d9a0a41bd93b Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Tue, 25 Mar 2014 17:51:52 +0100 Subject: [PATCH 28/55] MS2:downgrade speex resampler quality to min in case of arm with no neon --- .cproject | 2 +- mediastreamer2 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.cproject b/.cproject index 45790510b..07ef2412f 100644 --- a/.cproject +++ b/.cproject @@ -22,7 +22,7 @@ - + diff --git a/mediastreamer2 b/mediastreamer2 index 8663a08ed..771991709 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 8663a08ed7bed3ceccaadd72e4ae3b9d5c568f31 +Subproject commit 77199170953e84b4301ad42eeebde9cd7f338b12 From 838a3c3ed4590cd1e3b5056d3f35f0d9e330e06a Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Tue, 25 Mar 2014 18:11:04 +0100 Subject: [PATCH 29/55] MS2:fix for android build in msresampler --- mediastreamer2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediastreamer2 b/mediastreamer2 index 771991709..6530cce9c 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 77199170953e84b4301ad42eeebde9cd7f338b12 +Subproject commit 6530cce9c2062bdbbfdd0e01feac32243c3310f2 From 250495034edf5837cb0a652fd6dfd1232f060918 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Tue, 25 Mar 2014 22:47:35 +0100 Subject: [PATCH 30/55] rely on belle-sip ability to choose SIP transport random port using bind(). --- coreapi/bellesip_sal/sal_impl.c | 16 ++++++++++---- coreapi/linphonecore.c | 37 +++++++++++---------------------- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index be3c9ba17..ff6c0c17a 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -537,10 +537,18 @@ int sal_transport_available(Sal *sal, SalTransport t){ int sal_add_listen_port(Sal *ctx, SalAddress* addr){ int result; - belle_sip_listening_point_t* lp = belle_sip_stack_create_listening_point(ctx->stack - ,sal_address_get_domain(addr) - ,sal_address_get_port(addr) - ,sal_transport_to_string(sal_address_get_transport(addr))); + belle_sip_listening_point_t* lp = belle_sip_stack_create_listening_point(ctx->stack, + sal_address_get_domain(addr), + sal_address_get_port(addr), + sal_transport_to_string(sal_address_get_transport(addr))); + if (sal_address_get_port(addr)==-1 && lp==NULL){ + int random_port=(0xDFFF&random())+1024; + ms_warning("This version of belle-sip doesn't support random port, choosing one here."); + lp = belle_sip_stack_create_listening_point(ctx->stack, + sal_address_get_domain(addr), + random_port, + sal_transport_to_string(sal_address_get_transport(addr))); + } if (lp) { belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive); result = belle_sip_provider_add_listening_point(ctx->prov,lp); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 9cd36d0fd..b5cda087b 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1918,25 +1918,23 @@ static int apply_transports(LinphoneCore *lc){ anyaddr="0.0.0.0"; sal_unlisten_ports(sal); - if (tr->udp_port>0){ + if (tr->udp_port!=0){ if (sal_listen_port (sal,anyaddr,tr->udp_port,SalTransportUDP,FALSE)!=0){ transport_error(lc,"udp",tr->udp_port); return -1; } } - if (tr->tcp_port>0){ + if (tr->tcp_port!=0){ if (sal_listen_port (sal,anyaddr,tr->tcp_port,SalTransportTCP,FALSE)!=0){ transport_error(lc,"tcp",tr->tcp_port); } } - if (tr->tls_port>0){ + if (tr->tls_port!=0){ if (sal_listen_port (sal,anyaddr,tr->tls_port,SalTransportTLS,TRUE)!=0){ transport_error(lc,"tls",tr->tls_port); } } - apply_user_agent(lc); - return 0; } @@ -1957,31 +1955,20 @@ bool_t linphone_core_sip_transport_supported(const LinphoneCore *lc, LinphoneTra **/ int linphone_core_set_sip_transports(LinphoneCore *lc, const LCSipTransports * tr_config /*config to be saved*/){ LCSipTransports tr=*tr_config; - int random_port=(0xDFFF&random())+1024; if (lp_config_get_int(lc->config,"sip","sip_random_port",0)==1) { /*legacy random mode*/ if (tr.udp_port>0){ - tr.udp_port=random_port; - tr.tls_port=tr.tcp_port=0; /*make sure only one transport is active at a time*/ - }else if (tr.tcp_port>0){ - tr.tcp_port=random_port; - tr.tls_port=tr.udp_port=0; /*make sure only one transport is active at a time*/ - }else if (tr.tls_port>0){ - tr.tls_port=random_port; - tr.udp_port=tr.tcp_port=0; /*make sure only one transport is active at a time*/ - } else { - tr.udp_port=random_port; + tr.udp_port=LC_SIP_TRANSPORT_RANDOM; + } + if (tr.tcp_port>0){ + tr.tcp_port=LC_SIP_TRANSPORT_RANDOM; + } + if (tr.tls_port>0){ + tr.tls_port=LC_SIP_TRANSPORT_RANDOM; + }else { + tr.udp_port=LC_SIP_TRANSPORT_RANDOM; } - } - if (tr.udp_port == LC_SIP_TRANSPORT_RANDOM) { - tr.udp_port=random_port; - } - if (tr.tcp_port == LC_SIP_TRANSPORT_RANDOM) { - tr.tcp_port=random_port; - } - if (tr.tls_port == LC_SIP_TRANSPORT_RANDOM) { - tr.tls_port=random_port+1; } if (tr.udp_port==0 && tr.tcp_port==0 && tr.tls_port==0){ From 266207c5f09467696f4da70828e392190731155d Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Wed, 26 Mar 2014 11:30:07 +0100 Subject: [PATCH 31/55] change behavior of linphone_core_get_sip_transports() if random port selection was specified. Only linphone_core_get_sip_transports_used() will return the real port if random port selection was specified. --- coreapi/bellesip_sal/sal_impl.c | 14 +++++++++++++- coreapi/linphonecore.c | 26 +++++++++++++++++++------- coreapi/linphonecore.h | 2 ++ include/sal/sal.h | 1 + 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index ff6c0c17a..04a3e093d 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -569,22 +569,34 @@ int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int i sal_address_destroy(sal_addr); return result; } + static void remove_listening_point(belle_sip_listening_point_t* lp,belle_sip_provider_t* prov) { belle_sip_provider_remove_listening_point(prov,lp); } + +int sal_get_listening_port(Sal *ctx, SalTransport tr){ + const char *tpn=sal_transport_to_string(tr); + belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(ctx->prov, tpn); + if (lp){ + return belle_sip_listening_point_get_port(lp); + } + return 0; +} + int sal_unlisten_ports(Sal *ctx){ const belle_sip_list_t * lps = belle_sip_provider_get_listening_points(ctx->prov); belle_sip_list_t * tmp_list = belle_sip_list_copy(lps); belle_sip_list_for_each2 (tmp_list,(void (*)(void*,void*))remove_listening_point,ctx->prov); belle_sip_list_free(tmp_list); - ms_message("sal_unlisten_ports done"); return 0; } + ortp_socket_t sal_get_socket(Sal *ctx){ ms_warning("sal_get_socket is deprecated"); return -1; } + void sal_set_user_agent(Sal *ctx, const char *user_agent){ belle_sip_header_user_agent_set_products(ctx->user_agent,NULL); belle_sip_header_user_agent_add_product(ctx->user_agent,user_agent); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index b5cda087b..69680e9d2 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1521,7 +1521,7 @@ static void update_primary_contact(LinphoneCore *lc){ lc->sip_conf.loopback_only=TRUE; }else lc->sip_conf.loopback_only=FALSE; linphone_address_set_domain(url,tmp); - linphone_address_set_port(url,linphone_core_get_sip_port (lc)); + linphone_address_set_port(url,linphone_core_get_sip_port(lc)); guessed=linphone_address_as_string(url); lc->sip_conf.guessed_contact=guessed; linphone_address_destroy(url); @@ -1833,8 +1833,9 @@ void linphone_core_set_use_rfc2833_for_dtmf(LinphoneCore *lc,bool_t use_rfc2833) **/ int linphone_core_get_sip_port(LinphoneCore *lc) { - LCSipTransports *tr=&lc->sip_conf.transports; - return tr->udp_port>0 ? tr->udp_port : (tr->tcp_port > 0 ? tr->tcp_port : tr->tls_port); + LCSipTransports tr; + linphone_core_get_sip_transports_used(lc,&tr); + return tr.udp_port>0 ? tr.udp_port : (tr.tcp_port > 0 ? tr.tcp_port : tr.tls_port); } #if !USE_BELLE_SIP @@ -1949,7 +1950,7 @@ bool_t linphone_core_sip_transport_supported(const LinphoneCore *lc, LinphoneTra * Sets the ports to be used for each of transport (UDP or TCP) * * A zero value port for a given transport means the transport - * is not used. + * is not used. A value of LC_SIP_TRANSPORT_RANDOM (-1) means the port is to be choosen randomly by the system. * * @ingroup network_parameters **/ @@ -1990,9 +1991,9 @@ int linphone_core_set_sip_transports(LinphoneCore *lc, const LCSipTransports * t } /** - * Retrieves the ports used for each transport (udp, tcp). + * Retrieves the port configuration used for each transport (udp, tcp, tls). * A zero value port for a given transport means the transport - * is not used. + * is not used. A value of LC_SIP_TRANSPORT_RANDOM (-1) means the port is to be choosen randomly by the system. * @ingroup network_parameters **/ int linphone_core_get_sip_transports(LinphoneCore *lc, LCSipTransports *tr){ @@ -2000,6 +2001,18 @@ int linphone_core_get_sip_transports(LinphoneCore *lc, LCSipTransports *tr){ return 0; } +/** + * Retrieves the real port number assigned for each sip transport (udp, tcp, tls). + * A zero value means that the transport is not activated. + * If LC_SIP_TRANSPORT_RANDOM was passed to linphone_core_set_sip_transports(), the random port choosed by the system is returned. + * @ingroup network_parameters + * @param tr a LCSipTransports structure. +**/ +void linphone_core_get_sip_transports_used(LinphoneCore *lc, LCSipTransports *tr){ + tr->udp_port=sal_get_listening_port(lc->sal,SalTransportUDP); + tr->tcp_port=sal_get_listening_port(lc->sal,SalTransportTCP); + tr->tls_port=sal_get_listening_port(lc->sal,SalTransportTLS); +} /** * Sets the UDP port to be used by SIP. * @@ -2770,7 +2783,6 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const lc->vtable.display_warning(lc,_("Sorry, we have reached the maximum number of simultaneous calls")); return NULL; } - linphone_core_get_default_proxy(lc,&proxy); real_url=linphone_address_as_string(addr); proxy=linphone_core_lookup_known_proxy(lc,addr); diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 927b46a43..12b550a6f 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -1722,6 +1722,8 @@ LINPHONE_PUBLIC int linphone_core_set_sip_transports(LinphoneCore *lc, const LCS LINPHONE_PUBLIC int linphone_core_get_sip_transports(LinphoneCore *lc, LCSipTransports *transports); +LINPHONE_PUBLIC void linphone_core_get_sip_transports_used(LinphoneCore *lc, LCSipTransports *tr); + LINPHONE_PUBLIC bool_t linphone_core_sip_transport_supported(const LinphoneCore *lc, LinphoneTransportType tp); /** * diff --git a/include/sal/sal.h b/include/sal/sal.h index 9990d099e..5bc5264a2 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -501,6 +501,7 @@ void sal_signing_key_delete(SalSigningKey *key); void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs); int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure); +int sal_get_listening_port(Sal *ctx, SalTransport tr); int sal_unlisten_ports(Sal *ctx); int sal_transport_available(Sal *ctx, SalTransport t); void sal_set_dscp(Sal *ctx, int dscp); From 1c3714327f4cd9fe75229179ae8344d76804a2da Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Wed, 26 Mar 2014 16:58:13 +0100 Subject: [PATCH 32/55] Do not use raw attributes to get values. --- coreapi/bellesip_sal/sal_sdp.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/coreapi/bellesip_sal/sal_sdp.c b/coreapi/bellesip_sal/sal_sdp.c index 3faa7a063..b2f106cef 100644 --- a/coreapi/bellesip_sal/sal_sdp.c +++ b/coreapi/bellesip_sal/sal_sdp.c @@ -321,8 +321,7 @@ static void sdp_parse_payload_types(belle_sdp_media_description_t *media_desc, S static void sdp_parse_media_crypto_parameters(belle_sdp_media_description_t *media_desc, SalStreamDescription *stream) { belle_sip_list_t *attribute_it; - const belle_sdp_attribute_t *attribute; - const belle_sdp_raw_attribute_t *raw_attribute; + belle_sdp_attribute_t *attribute; char tmp[256], tmp2[256]; int valid_count = 0; int nb; @@ -332,10 +331,9 @@ static void sdp_parse_media_crypto_parameters(belle_sdp_media_description_t *med ; valid_count < SAL_CRYPTO_ALGO_MAX && attribute_it!=NULL; attribute_it=attribute_it->next ) { attribute=BELLE_SDP_ATTRIBUTE ( attribute_it->data ); - raw_attribute=BELLE_SDP_RAW_ATTRIBUTE(attribute); - if ( keywordcmp ( "crypto",belle_sdp_attribute_get_name ( attribute ) ) ==0 && belle_sdp_raw_attribute_get_value ( raw_attribute ) !=NULL ) { - nb = sscanf ( belle_sdp_raw_attribute_get_value ( raw_attribute ), "%d %256s inline:%256s", + if ( keywordcmp ( "crypto",belle_sdp_attribute_get_name ( attribute ) ) ==0 && belle_sdp_attribute_get_value ( attribute ) !=NULL ) { + nb = sscanf ( belle_sdp_attribute_get_value ( attribute ), "%d %256s inline:%256s", &stream->crypto[valid_count].tag, tmp, tmp2 ); @@ -362,7 +360,7 @@ static void sdp_parse_media_crypto_parameters(belle_sdp_media_description_t *med valid_count++; } } else { - ms_warning ( "sdp has a strange a= line (%s) nb=%i",belle_sdp_raw_attribute_get_value ( raw_attribute ),nb ); + ms_warning ( "sdp has a strange a= line (%s) nb=%i",belle_sdp_attribute_get_value ( attribute ),nb ); } } } @@ -371,17 +369,15 @@ static void sdp_parse_media_crypto_parameters(belle_sdp_media_description_t *med static void sdp_parse_media_ice_parameters(belle_sdp_media_description_t *media_desc, SalStreamDescription *stream) { belle_sip_list_t *attribute_it; - const belle_sdp_attribute_t *attribute; - const belle_sdp_raw_attribute_t *raw_attribute; + belle_sdp_attribute_t *attribute; const char *att_name; const char *value; int nb_ice_candidates = 0; for (attribute_it = belle_sdp_media_description_get_attributes(media_desc); attribute_it != NULL; attribute_it=attribute_it->next) { attribute=BELLE_SDP_ATTRIBUTE(attribute_it->data); - raw_attribute=BELLE_SDP_RAW_ATTRIBUTE(attribute); att_name = belle_sdp_attribute_get_name(attribute); - value = belle_sdp_raw_attribute_get_value(raw_attribute); + value = belle_sdp_attribute_get_value(attribute); if ((keywordcmp("candidate", att_name) == 0) && (value != NULL)) { SalIceCandidate *candidate = &stream->ice_candidates[nb_ice_candidates]; @@ -473,8 +469,7 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md, SalStreamDescription *stream; belle_sdp_connection_t* cnx; belle_sdp_media_t* media; - const belle_sdp_attribute_t* attribute; - const belle_sdp_raw_attribute_t* raw_attribute; + belle_sdp_attribute_t* attribute; const char* value; const char *mtype,*proto; @@ -536,8 +531,7 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md, stream->rtcp_port = stream->rtp_port + 1; snprintf(stream->rtcp_addr, sizeof(stream->rtcp_addr), "%s", stream->rtp_addr); attribute=belle_sdp_media_description_get_attribute(media_desc,"rtcp"); - raw_attribute=BELLE_SDP_RAW_ATTRIBUTE(attribute); - if (attribute && (value=belle_sdp_raw_attribute_get_value(raw_attribute))!=NULL){ + if (attribute && (value=belle_sdp_attribute_get_value(attribute))!=NULL){ char tmp[256]; int nb = sscanf(value, "%d IN IP4 %s", &stream->rtcp_port, tmp); if (nb == 1) { From 8a292b30ccd1236b472f0665187a92156c951ec5 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Wed, 26 Mar 2014 17:09:02 +0100 Subject: [PATCH 33/55] fix generic publishes not properly terminated. --- coreapi/event.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/coreapi/event.c b/coreapi/event.c index e4d66db3e..731412153 100644 --- a/coreapi/event.c +++ b/coreapi/event.c @@ -107,6 +107,9 @@ void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState s if (lc->vtable.publish_state_changed){ lc->vtable.publish_state_changed(lev->lc,lev,state); } + if (state==LinphonePublishCleared){ + linphone_event_unref(lev); + } } } @@ -291,7 +294,8 @@ void linphone_event_terminate(LinphoneEvent *lev){ if (lev->publish_state!=LinphonePublishNone){ if (lev->publish_state==LinphonePublishOk){ sal_publish(lev->op,NULL,NULL,NULL,0,NULL); - } + }else sal_op_stop_refreshing(lev->op); + linphone_event_set_publish_state(lev,LinphonePublishCleared); return; } From 3013fd8ae240ffafc4ec25e7d375bc4ea9d8b737 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Wed, 26 Mar 2014 17:51:47 +0100 Subject: [PATCH 34/55] allow configuration of root_ca before provisioning, so that it can be used for https fetching --- coreapi/bellesip_sal/sal_impl.c | 2 +- coreapi/linphonecore.c | 27 ++++++++++++++++++++++++--- coreapi/lpconfig.c | 3 ++- coreapi/private.h | 1 + 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 04a3e093d..c0340e56a 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -552,7 +552,7 @@ int sal_add_listen_port(Sal *ctx, SalAddress* addr){ if (lp) { belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive); result = belle_sip_provider_add_listening_point(ctx->prov,lp); - set_tls_properties(ctx); + if (sal_address_get_transport(addr)==SalTransportTLS) set_tls_properties(ctx); } else { return -1; } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 69680e9d2..e5eaea9ca 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -615,11 +615,13 @@ static void sound_config_read(LinphoneCore *lc) static void certificates_config_read(LinphoneCore *lc) { + const char *rootca; #ifdef __linux - sal_set_root_ca(lc->sal, lp_config_get_string(lc->config,"sip","root_ca", "/etc/ssl/certs")); + rootca=lp_config_get_string(lc->config,"sip","root_ca", "/etc/ssl/certs"); #else - sal_set_root_ca(lc->sal, lp_config_get_string(lc->config,"sip","root_ca", ROOT_CA_FILE)); + rootca=lp_config_get_string(lc->config,"sip","root_ca", ROOT_CA_FILE); #endif + linphone_core_set_root_ca(lc,rootca); linphone_core_verify_server_certificates(lc,lp_config_get_int(lc->config,"sip","verify_server_certs",TRUE)); linphone_core_verify_server_cn(lc,lp_config_get_int(lc->config,"sip","verify_server_cn",TRUE)); } @@ -1369,6 +1371,8 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab lc->network_last_status = FALSE; lc->http_provider = belle_sip_stack_create_http_provider(sal_get_belle_sip_stack(lc->sal), "0.0.0.0"); + lc->http_verify_policy = belle_tls_verify_policy_new(); + belle_http_provider_set_tls_verify_policy(lc->http_provider,lc->http_verify_policy); certificates_config_read(lc); @@ -4347,6 +4351,10 @@ const char *linphone_core_get_ring(const LinphoneCore *lc){ **/ void linphone_core_set_root_ca(LinphoneCore *lc,const char *path){ sal_set_root_ca(lc->sal, path); + if (lc->http_verify_policy){ + belle_tls_verify_policy_set_root_ca(lc->http_verify_policy,path); + } + lp_config_set_string(lc->config,"sip","root_ca",path); } /** @@ -4357,7 +4365,7 @@ void linphone_core_set_root_ca(LinphoneCore *lc,const char *path){ * @ingroup initializing **/ const char *linphone_core_get_root_ca(LinphoneCore *lc){ - return sal_get_root_ca(lc->sal); + return lp_config_get_string(lc->config,"sip","root_ca",NULL); } /** @@ -4367,6 +4375,10 @@ const char *linphone_core_get_root_ca(LinphoneCore *lc){ **/ void linphone_core_verify_server_certificates(LinphoneCore *lc, bool_t yesno){ sal_verify_server_certificates(lc->sal,yesno); + if (lc->http_verify_policy){ + belle_tls_verify_policy_set_exceptions(lc->http_verify_policy, yesno ? 0 : BELLE_TLS_VERIFY_ANY_REASON); + } + lp_config_set_int(lc->config,"sip","verify_server_certs",yesno); } /** @@ -4375,6 +4387,10 @@ void linphone_core_verify_server_certificates(LinphoneCore *lc, bool_t yesno){ **/ void linphone_core_verify_server_cn(LinphoneCore *lc, bool_t yesno){ sal_verify_server_cn(lc->sal,yesno); + if (lc->http_verify_policy){ + belle_tls_verify_policy_set_exceptions(lc->http_verify_policy, yesno ? 0 : BELLE_TLS_VERIFY_CN_MISMATCH); + } + lp_config_set_int(lc->config,"sip","verify_server_cn",yesno); } static void notify_end_of_ring(void *ud, MSFilter *f, unsigned int event, void *arg){ @@ -5613,6 +5629,11 @@ void net_config_uninit(LinphoneCore *lc) if (lc->http_provider) { belle_sip_object_unref(lc->http_provider); + lc->http_provider=NULL; + } + if (lc->http_verify_policy){ + belle_sip_object_unref(lc->http_verify_policy); + lc->http_verify_policy=NULL; } if (config->stun_server!=NULL){ ms_free(config->stun_server); diff --git a/coreapi/lpconfig.c b/coreapi/lpconfig.c index feaff8cd1..8df196df2 100644 --- a/coreapi/lpconfig.c +++ b/coreapi/lpconfig.c @@ -324,8 +324,9 @@ int lp_config_read_file(LpConfig *lpconfig, const char *filename){ } void lp_item_set_value(LpItem *item, const char *value){ - ortp_free(item->value); + char *prev_value=item->value; item->value=ortp_strdup(value); + ortp_free(prev_value); } diff --git a/coreapi/private.h b/coreapi/private.h index a9bd1f0bf..6f421e95e 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -680,6 +680,7 @@ struct _LinphoneCore UpnpContext *upnp; #endif //BUILD_UPNP belle_http_provider_t *http_provider; + belle_tls_verify_policy_t *http_verify_policy; MSList *tones; LinphoneReason chat_deny_code; }; From fe3a59ed6924c3ddde17053a25e86b2eb161782e Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 27 Mar 2014 10:32:57 +0100 Subject: [PATCH 35/55] destroy http provider before sal is destroyed, otherwise the belle_sip_stack is already destroyed when destroying the provider. --- coreapi/linphonecore.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index e5eaea9ca..52ef011c0 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -5627,14 +5627,6 @@ void net_config_uninit(LinphoneCore *lc) { net_config_t *config=&lc->net_conf; - if (lc->http_provider) { - belle_sip_object_unref(lc->http_provider); - lc->http_provider=NULL; - } - if (lc->http_verify_policy){ - belle_sip_object_unref(lc->http_verify_policy); - lc->http_verify_policy=NULL; - } if (config->stun_server!=NULL){ ms_free(config->stun_server); } @@ -5709,6 +5701,14 @@ void sip_config_uninit(LinphoneCore *lc) sal_reset_transports(lc->sal); sal_unlisten_ports(lc->sal); /*to make sure no new messages are received*/ + if (lc->http_provider) { + belle_sip_object_unref(lc->http_provider); + lc->http_provider=NULL; + } + if (lc->http_verify_policy){ + belle_sip_object_unref(lc->http_verify_policy); + lc->http_verify_policy=NULL; + } sal_iterate(lc->sal); /*make sure event are purged*/ sal_uninit(lc->sal); lc->sal=NULL; From 4341b43ff0fcacd4a98be5dfc2846f2dca3a81f1 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 27 Mar 2014 11:29:23 +0100 Subject: [PATCH 36/55] update ms2 --- mediastreamer2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediastreamer2 b/mediastreamer2 index 6530cce9c..17471b986 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 6530cce9c2062bdbbfdd0e01feac32243c3310f2 +Subproject commit 17471b98625bc6096427351ba78f290740d15265 From a191c392244a8e49046419c799e150f06cd331ff Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 27 Mar 2014 17:19:01 +0100 Subject: [PATCH 37/55] fix bug around legacy sip_random_port property --- coreapi/linphonecore.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 52ef011c0..fa94234a1 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1971,8 +1971,6 @@ int linphone_core_set_sip_transports(LinphoneCore *lc, const LCSipTransports * t } if (tr.tls_port>0){ tr.tls_port=LC_SIP_TRANSPORT_RANDOM; - }else { - tr.udp_port=LC_SIP_TRANSPORT_RANDOM; } } From 1a05114e49a01a9c9317967ce66c67c5c7d59aaf Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 28 Mar 2014 14:25:32 +0100 Subject: [PATCH 38/55] Use #define instead of enum. --- coreapi/linphonecall.c | 8 ++++---- coreapi/linphonecore.h | 15 +++------------ 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 4ff3537fb..2d200c8cf 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -2706,7 +2706,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp); call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp = evd->packet; evd->packet = NULL; - call->stats[LINPHONE_CALL_STATS_VIDEO].updated = LinphoneCallStatsReceivedRTCPUpdate; + call->stats[LINPHONE_CALL_STATS_VIDEO].updated = LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE; update_local_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO],(MediaStream*)call->videostream); if (lc->vtable.call_stats_updated) lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]); @@ -2716,7 +2716,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp); call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp = evd->packet; evd->packet = NULL; - call->stats[LINPHONE_CALL_STATS_VIDEO].updated = LinphoneCallStatsSentRTCPUpdate; + call->stats[LINPHONE_CALL_STATS_VIDEO].updated = LINPHONE_CALL_STATS_SENT_RTCP_UPDATE; update_local_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO],(MediaStream*)call->videostream); if (lc->vtable.call_stats_updated) lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]); @@ -2751,7 +2751,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp); call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp = evd->packet; evd->packet = NULL; - call->stats[LINPHONE_CALL_STATS_AUDIO].updated = LinphoneCallStatsReceivedRTCPUpdate; + call->stats[LINPHONE_CALL_STATS_AUDIO].updated = LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE; update_local_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO],(MediaStream*)call->audiostream); if (lc->vtable.call_stats_updated) lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]); @@ -2761,7 +2761,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp); call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp = evd->packet; evd->packet = NULL; - call->stats[LINPHONE_CALL_STATS_AUDIO].updated = LinphoneCallStatsSentRTCPUpdate; + call->stats[LINPHONE_CALL_STATS_AUDIO].updated = LINPHONE_CALL_STATS_SENT_RTCP_UPDATE; update_local_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO],(MediaStream*)call->audiostream); if (lc->vtable.call_stats_updated) lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]); diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 12b550a6f..f4f34b8c6 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -577,19 +577,10 @@ enum _LinphoneUpnpState{ **/ typedef enum _LinphoneUpnpState LinphoneUpnpState; -/** - * Enum describing what has been updated in a LinphoneCallStats object. -**/ -enum _LinphoneCallStatsRTCPUpdate { - LinphoneCallStatsReceivedRTCPUpdate, /**< received_rtcp field of LinphoneCallStats object has been updated */ - LinphoneCallStatsSentRTCPUpdate /**< sent_rtcp field of LinphoneCallStats object has been updated */ -}; -/** - * Enum describing what has been updated in a LinphoneCallStats object. -**/ +#define LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE (1 << 0) /**< received_rtcp field of LinphoneCallStats object has been updated */ +#define LINPHONE_CALL_STATS_SENT_RTCP_UPDATE (1 << 1) /**< sent_rtcp field of LinphoneCallStats object has been updated */ -typedef enum _LinphoneCallStatsRTCPUpdate LinphoneCallStatsRTCPUpdate; /** * The LinphoneCallStats objects carries various statistic informations regarding quality of audio or video streams. @@ -621,7 +612,7 @@ struct _LinphoneCallStats { float upload_bandwidth; /** Date: Fri, 28 Mar 2014 17:12:49 +0100 Subject: [PATCH 39/55] fix bad enum cast and invalid enum translation --- coreapi/callbacks.c | 2 +- coreapi/misc.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 0daf09cd2..cb88095c7 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -882,7 +882,7 @@ static void text_received(SalOp *op, const SalMessage *msg){ if (lc->chat_deny_code==LinphoneReasonNone && is_duplicate_msg(lc,msg->message_id)==FALSE){ linphone_core_message_received(lc,op,msg); } - sal_message_reply(op,lc->chat_deny_code); + sal_message_reply(op,linphone_reason_to_sal(lc->chat_deny_code)); if (!call) sal_op_release(op); } diff --git a/coreapi/misc.c b/coreapi/misc.c index 53a4811a9..4c9834053 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -1100,9 +1100,9 @@ int linphone_core_get_local_ip_for(int type, const char *dest, char *result){ SalReason linphone_reason_to_sal(LinphoneReason reason){ switch(reason){ case LinphoneReasonNone: - return SalReasonUnknown; + return SalReasonNone; case LinphoneReasonNoResponse: - return SalReasonUnknown; + return SalReasonRequestTimeout; case LinphoneReasonForbidden: return SalReasonForbidden; case LinphoneReasonDeclined: From 9ff080e19cdf70c6a065cb10dbdd837663c767e3 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 1 Apr 2014 14:01:28 +0200 Subject: [PATCH 40/55] Update oRTP and ms2 submodules for RTCP XR. --- mediastreamer2 | 2 +- oRTP | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mediastreamer2 b/mediastreamer2 index 17471b986..9753c73f3 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 17471b98625bc6096427351ba78f290740d15265 +Subproject commit 9753c73f37f302ef3c813c7d973da03a7c31b5bb diff --git a/oRTP b/oRTP index c0418933b..cbfd8bd5c 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit c0418933b7ce4765993b7304809e43df6ed392dd +Subproject commit cbfd8bd5c475259ddf828417e520fb7c58dcb854 From 97ef67377cfb3ee4efade953b9bc3b3023c402ac Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Tue, 1 Apr 2014 22:43:23 +0200 Subject: [PATCH 41/55] update ms2 and oRTP, add documentation for zrtp related functions. Fix bug about sesion name not taken into SDP answers. --- coreapi/linphonecall.c | 15 +++++++++++++++ coreapi/offeranswer.c | 2 ++ mediastreamer2 | 2 +- oRTP | 2 +- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 2d200c8cf..e4cac3a33 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -82,6 +82,14 @@ const char* linphone_call_get_authentication_token(LinphoneCall *call){ return call->auth_token; } +/** + * Returns whether ZRTP authentication token is verified. + * If not, it must be verified by users as described in ZRTP procedure. + * Once done, the application must inform of the results with linphone_call_set_authentication_token_verified(). + * @param call the LinphoneCall + * @return TRUE if authentication token is verifed, false otherwise. + * @ingroup call_control +**/ bool_t linphone_call_get_authentication_token_verified(LinphoneCall *call){ return call->auth_token_verified; } @@ -172,6 +180,13 @@ static void linphone_call_audiostream_auth_token_ready(void *data, const char* a ms_message("Authentication token is %s (%s)", auth_token, verified?"verified":"unverified"); } +/** + * Set the result of ZRTP short code verification by user. + * If remote party also does the same, it will update the ZRTP cache so that user's verification will not be required for the two users. + * @param call the LinphoneCall + * @param verified whether the ZRTP SAS is verified. + * @ingroup call_control +**/ void linphone_call_set_authentication_token_verified(LinphoneCall *call, bool_t verified){ if (call->audiostream==NULL){ ms_error("linphone_call_set_authentication_token_verified(): No audio stream"); diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c index b9f8d4c82..caece9835 100644 --- a/coreapi/offeranswer.c +++ b/coreapi/offeranswer.c @@ -388,6 +388,8 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities strcpy(result->ice_ufrag, local_capabilities->ice_ufrag); result->ice_lite = local_capabilities->ice_lite; result->ice_completed = local_capabilities->ice_completed; + + strcpy(result->name,local_capabilities->name); // Handle session RTCP XR attribute memset(&result->rtcp_xr, 0, sizeof(result->rtcp_xr)); diff --git a/mediastreamer2 b/mediastreamer2 index fa2231095..c3593dcba 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit fa22310955303f6a2185fec8c5610aa6f24b46fb +Subproject commit c3593dcba131ae28837f10d9f01c0500f1ebffe9 diff --git a/oRTP b/oRTP index dc4197cfc..5008a70e0 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit dc4197cfceb4074018a0b7ad22a3c24fa454c129 +Subproject commit 5008a70e077b3706de4a48374f162f93071b4d08 From d26a93eaacc545792fd6a1683bddc5a33293c80c Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 2 Apr 2014 11:57:26 +0200 Subject: [PATCH 42/55] Fix crash on Android --- coreapi/linphonecore_jni.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index fc793f2c5..f5cc41bb9 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -805,8 +805,8 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setChatDatabasePath(JNIE } extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPrimaryContact(JNIEnv* env, jobject thiz, jlong lc, jstring jdisplayname, jstring jusername) { - const char* displayname = env->GetStringUTFChars(jdisplayname, NULL); - const char* username = env->GetStringUTFChars(jusername, NULL); + const char* displayname = jdisplayname ? env->GetStringUTFChars(jdisplayname, NULL) : NULL; + const char* username = jusername ? env->GetStringUTFChars(jusername, NULL) : NULL; LinphoneAddress *parsed = linphone_core_get_primary_contact_parsed((LinphoneCore*)lc); if (parsed != NULL) { @@ -816,8 +816,8 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPrimaryContact(JNIEnv linphone_core_set_primary_contact((LinphoneCore*)lc, contact); } - env->ReleaseStringUTFChars(jdisplayname, displayname); - env->ReleaseStringUTFChars(jusername, username); + if (jdisplayname) env->ReleaseStringUTFChars(jdisplayname, displayname); + if (jusername) env->ReleaseStringUTFChars(jusername, username); } extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getPrimaryContactUsername(JNIEnv* env, jobject thiz, jlong lc) { From 34561b414eaf7de09e40ab86d1aa8f93ad9c233b Mon Sep 17 00:00:00 2001 From: Guillaume Beraudo Date: Wed, 2 Apr 2014 13:30:13 +0200 Subject: [PATCH 43/55] Real early media switch to console. Allow using the real hardware to stream early media. --- console/linphonec.c | 15 ++++++++++++++- coreapi/linphonecore.c | 1 - 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/console/linphonec.c b/console/linphonec.c index 4385dbb09..f08c0f94d 100644 --- a/console/linphonec.c +++ b/console/linphonec.c @@ -148,6 +148,7 @@ static char last_in_history[256]; #endif //auto answer (-a) option static bool_t auto_answer=FALSE; +static bool_t real_early_media_sending=FALSE; static bool_t answer_call=FALSE; static bool_t vcap_enabled=FALSE; static bool_t display_enabled=FALSE; @@ -362,10 +363,17 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L linphone_call_enable_camera (call,linphonec_camera_enabled); id=(long)linphone_call_get_user_pointer (call); linphonec_set_caller(from); + linphonec_out("Receiving new incoming call from %s, assigned id %i\n", from,id); if ( auto_answer) { answer_call=TRUE; + } else if (real_early_media_sending) { + linphonec_out("Sending early media using real hardware\n"); + LinphoneCallParams* callparams = linphone_core_create_default_call_parameters(lc); + linphone_call_params_enable_early_media_sending(callparams, TRUE); + if (vcap_enabled) linphone_call_params_enable_video(callparams, TRUE); + linphone_core_accept_early_media_with_params(lc, call, callparams); + linphone_call_params_destroy(callparams); } - linphonec_out("Receiving new incoming call from %s, assigned id %i\n", from,id); break; case LinphoneCallOutgoingInit: linphonec_call_identify(call); @@ -906,6 +914,7 @@ print_usage (int exit_status) " -l logfile specify the log file for your SIP phone\n" " -s sipaddress specify the sip call to do at startup\n" " -a enable auto answering for incoming calls\n" +" --real-early-media enable sending early media using real audio/video (beware of privacy issue)\n" " -V enable video features globally (disabled by default)\n" " -C enable video capture only (disabled by default)\n" " -D enable video display only (disabled by default)\n" @@ -1229,6 +1238,10 @@ linphonec_parse_cmdline(int argc, char **argv) { auto_answer = TRUE; } + else if (strncmp ("--real-early-media", argv[arg_num], 2) == 0) + { + real_early_media_sending = TRUE; + } else if (strncmp ("-C", argv[arg_num], 2) == 0) { vcap_enabled = TRUE; diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index fa94234a1..ce09625ce 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -3038,7 +3038,6 @@ int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall* // if parameters are passed, update the media description if ( params ) { - md = sal_call_get_remote_media_description ( call->op ); _linphone_call_params_copy ( &call->params,params ); linphone_call_make_local_media_description ( lc,call ); sal_call_set_local_media_description ( call->op,call->localdesc ); From 0aaac5f6058e45dd5ffbadd9572d0d1f32ad2741 Mon Sep 17 00:00:00 2001 From: Guillaume Beraudo Date: Wed, 2 Apr 2014 13:47:00 +0200 Subject: [PATCH 44/55] Coma separated list of user defined alsa devices Config alsadev; patch from Ingo Krabbe. --- coreapi/linphonecore.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index ce09625ce..cad98f51e 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -536,8 +536,25 @@ static void sound_config_read(LinphoneCore *lc) /*alsadev let the user use custom alsa device within linphone*/ devid=lp_config_get_string(lc->config,"sound","alsadev",NULL); if (devid){ - MSSndCard *card=ms_alsa_card_new_custom(devid,devid); - ms_snd_card_manager_add_card(ms_snd_card_manager_get(),card); + MSSndCard* card; + const char* delim=","; + size_t l=strlen(devid); + char* d=malloc(l+1); + char* i; + memcpy(d,devid,l+1); + for (l=0,i=strpbrk(d+l,delim);i;i=strpbrk(d+l,delim)){ + char s=*i; + *i='\0'; + card=ms_alsa_card_new_custom(d+l,d+l); + ms_snd_card_manager_add_card(ms_snd_card_manager_get(),card); + *i=s; + l=i-d+1; + } + if(d[l]!='\0') { + card=ms_alsa_card_new_custom(d+l,d+l); + ms_snd_card_manager_add_card(ms_snd_card_manager_get(),card); + } + free(d); } tmp=lp_config_get_int(lc->config,"sound","alsa_forced_rate",-1); if (tmp>0) ms_alsa_card_set_forced_sample_rate(tmp); From 75529783cfff97abcc5bb2eda2535a935bf14d7d Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Wed, 2 Apr 2014 17:24:49 +0200 Subject: [PATCH 45/55] bzrtp integration for android --- build/android/Android.mk | 7 +++---- java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java | 4 ---- oRTP | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/build/android/Android.mk b/build/android/Android.mk index f009cf295..c2b04b389 100755 --- a/build/android/Android.mk +++ b/build/android/Android.mk @@ -199,13 +199,12 @@ LOCAL_SRC_FILES += $(LIBLINPHONE_EXTENDED_SRC_FILES) LOCAL_CFLAGS += $(LIBLINPHONE_EXTENDED_CFLAGS) -ifeq ($(BUILD_GPLV3_ZRTP),1) - LOCAL_SHARED_LIBRARIES += libssl-linphone libcrypto-linphone - LOCAL_SHARED_LIBRARIES += libbzrtp +ifeq ($(BUILD_ZRTP),1) + LOCAL_STATIC_LIBRARIES += libbzrtp endif ifeq ($(BUILD_SRTP),1) - LOCAL_SHARED_LIBRARIES += libsrtp + LOCAL_STATIC_LIBRARIES += libsrtp endif ifeq ($(BUILD_SQLITE),1) diff --git a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java index 8b1527b09..85bff8ffa 100644 --- a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java @@ -57,10 +57,6 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory { loadOptionalLibrary("avcodec-linphone-arm"); } - // Secure RTP and key negotiation - loadOptionalLibrary("srtp-" + eabi); - loadOptionalLibrary("zrtpcpp-" + eabi); // GPLv3+ - //Main library System.loadLibrary("linphone-" + eabi); diff --git a/oRTP b/oRTP index 5008a70e0..393857c0e 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 5008a70e077b3706de4a48374f162f93071b4d08 +Subproject commit 393857c0e8e5cab10a8d647cc89c8390355745a7 From 274d50168e63f8071250d8abf4f6a32fac86ef6e Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Wed, 2 Apr 2014 22:23:04 +0200 Subject: [PATCH 46/55] implement digest authentication for anonymous calls (with id privacy) --- coreapi/bellesip_sal/sal_impl.c | 8 +++- coreapi/bellesip_sal/sal_op_impl.c | 9 ++++- tester/call_tester.c | 60 ++++++++++++++++++++++++++++++ tester/flexisip.conf | 2 +- 4 files changed, 75 insertions(+), 4 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index c0340e56a..e4d72e834 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -115,7 +115,13 @@ void sal_process_authentication(SalOp *op) { belle_sip_list_t* auth_list=NULL; belle_sip_auth_event_t* auth_event; belle_sip_response_t *response=belle_sip_transaction_get_response((belle_sip_transaction_t*)op->pending_auth_transaction); + belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(initial_request,belle_sip_header_from_t); + belle_sip_uri_t *from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)from); + if (strcasecmp(belle_sip_uri_get_host(from_uri),"anonymous.invalid")==0){ + /*prefer using the from from the SalOp*/ + from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)sal_op_get_from_address(op)); + } if (op->dialog && belle_sip_dialog_get_state(op->dialog)==BELLE_SIP_DIALOG_CONFIRMED) { new_request = belle_sip_dialog_create_request_from(op->dialog,initial_request); @@ -132,7 +138,7 @@ void sal_process_authentication(SalOp *op) { return; } - if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,&auth_list)) { + if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,from_uri,&auth_list)) { if (is_within_dialog) { sal_op_send_request(op,new_request); } else { diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 3e5ebe2a5..a6020791e 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -90,18 +90,23 @@ SalAuthInfo * sal_op_get_auth_requested(SalOp *op){ belle_sip_header_contact_t* sal_op_create_contact(SalOp *op){ belle_sip_header_contact_t* contact_header; belle_sip_uri_t* contact_uri; + if (sal_op_get_contact_address(op)) { contact_header = belle_sip_header_contact_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_contact_address(op))); } else { contact_header= belle_sip_header_contact_new(); } + if (!(contact_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_header)))) { /*no uri, just creating a new one*/ contact_uri=belle_sip_uri_new(); belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact_header),contact_uri); } + belle_sip_uri_set_secure(contact_uri,sal_op_is_secure(op)); - + if (op->privacy!=SalPrivacyNone){ + belle_sip_uri_set_user(contact_uri,NULL); + } belle_sip_header_contact_set_automatic(contact_header,op->base.root->auto_contacts); if (op->base.root->uuid){ if (belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance")==0){ @@ -299,7 +304,7 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req if (!belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION) && !belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION)) { /*hmm just in case we already have authentication param in cache*/ - belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL); + belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL,NULL); } result = belle_sip_client_transaction_send_request_to(client_transaction,next_hop_uri/*might be null*/); diff --git a/tester/call_tester.c b/tester/call_tester.c index ed44faa9e..419def8cc 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -886,6 +886,65 @@ static void call_with_privacy(void) { linphone_core_manager_destroy(pauline); } +/*this ones makes call with privacy without previous registration*/ +static void call_with_privacy2(void) { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new2( "pauline_rc",FALSE); + LinphoneCall *c1,*c2; + LinphoneCallParams *params; + LinphoneProxyConfig* pauline_proxy; + params=linphone_core_create_default_call_parameters(pauline->lc); + linphone_call_params_set_privacy(params,LinphonePrivacyId); + + linphone_core_get_default_proxy(pauline->lc,&pauline_proxy); + linphone_proxy_config_edit(pauline_proxy); + linphone_proxy_config_enable_register(pauline_proxy,FALSE); + linphone_proxy_config_done(pauline_proxy); + + CU_ASSERT_TRUE(call_with_caller_params(pauline,marie,params)); + linphone_call_params_destroy(params); + + c1=linphone_core_get_current_call(pauline->lc); + c2=linphone_core_get_current_call(marie->lc); + + CU_ASSERT_PTR_NOT_NULL(c1); + CU_ASSERT_PTR_NOT_NULL(c2); + + /*make sure local identity is unchanged*/ + CU_ASSERT_TRUE(linphone_address_weak_equal(linphone_call_log_get_from(linphone_call_get_call_log(c1)),pauline->identity)); + + /*make sure remote identity is hidden*/ + CU_ASSERT_FALSE(linphone_address_weak_equal(linphone_call_get_remote_address(c2),pauline->identity)); + + CU_ASSERT_EQUAL(linphone_call_params_get_privacy(linphone_call_get_current_params(c2)),LinphonePrivacyId); + + /*just to sleep*/ + linphone_core_terminate_all_calls(pauline->lc); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1)); + + /*test proxy config privacy*/ + linphone_proxy_config_set_privacy(pauline_proxy,LinphonePrivacyId); + + CU_ASSERT_TRUE(call(pauline,marie)); + c1=linphone_core_get_current_call(pauline->lc); + c2=linphone_core_get_current_call(marie->lc); + + CU_ASSERT_PTR_NOT_NULL(c1); + CU_ASSERT_PTR_NOT_NULL(c2); + + /*make sure remote identity is hidden*/ + CU_ASSERT_FALSE(linphone_address_weak_equal(linphone_call_get_remote_address(c2),pauline->identity)); + + CU_ASSERT_EQUAL(linphone_call_params_get_privacy(linphone_call_get_current_params(c2)),LinphonePrivacyId); + /*just to sleep*/ + linphone_core_terminate_all_calls(pauline->lc); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,2)); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,2)); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} static void call_waiting_indication_with_param(bool_t enable_caller_privacy) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); @@ -1801,6 +1860,7 @@ test_t call_tests[] = { { "SRTP ice call", srtp_ice_call }, #endif { "Call with privacy", call_with_privacy }, + { "Call with privacy 2", call_with_privacy2 }, { "Call rejected because of wrong credential", call_rejected_because_wrong_credentials}, { "Call rejected without 403 because of wrong credential", call_rejected_without_403_because_wrong_credentials}, { "Call rejected without 403 because of wrong credential and no auth req cb", call_rejected_without_403_because_wrong_credentials_no_auth_req_cb}, diff --git a/tester/flexisip.conf b/tester/flexisip.conf index a5cac58fc..48f4a054b 100755 --- a/tester/flexisip.conf +++ b/tester/flexisip.conf @@ -128,7 +128,7 @@ no-403=user-agent contains 'tester-no-403' # in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org') # && (user-agent == 'Linphone v2') # Default value: -filter= from.uri.domain contains 'sip.example.org' || from.uri.domain contains 'auth.example.org' || from.uri.domain contains 'auth1.example.org' || from.uri.domain contains 'auth2.example.org' +filter= from.uri.domain contains 'sip.example.org' || from.uri.domain contains 'auth.example.org' || from.uri.domain contains 'auth1.example.org' || from.uri.domain contains 'auth2.example.org' || from.uri.domain contains 'anonymous.invalid' # List of whitespace separated domain names to challenge. Others # are denied. From 5bd12799c70ae7684b229318afec22f9a48d0a57 Mon Sep 17 00:00:00 2001 From: Guillaume BIENKOWSKI Date: Thu, 3 Apr 2014 10:12:02 +0200 Subject: [PATCH 47/55] Update mediastreamer2 to enable HD on more devices --- mediastreamer2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediastreamer2 b/mediastreamer2 index c3593dcba..90026398a 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit c3593dcba131ae28837f10d9f01c0500f1ebffe9 +Subproject commit 90026398ae7463ffc8ec0d5538905310cce51f5e From ef08558c02133f376e952a702c9ff46fd634ebda Mon Sep 17 00:00:00 2001 From: Margaux Clerc Date: Fri, 4 Apr 2014 11:30:03 +0200 Subject: [PATCH 48/55] Update README rpm --- build/redhat/README | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/build/redhat/README b/build/redhat/README index 7831df9c8..a38bc3143 100644 --- a/build/redhat/README +++ b/build/redhat/README @@ -16,13 +16,16 @@ Download and install the repo rpmforge : $ sudo yum install ffmpeg-devel $ sudo yum install openldap-devel +- Install antlr3 + $ git clone git://git.linphone.org/antlr3.git + $ cd antlr3 + $ sudo cp antlr-3.4-complete.jar /usr/share/java/antlr3.jar + - Download and install packages $ sudo rpm -Uhv ftp://ftp.icm.edu.pl/vol/rzm2/linux-fedora/linux/epel/6/x86_64/polarssl-1.3.2-1.el6.x86_64.rpm $ sudo rpm -Uvh ftp://ftp.icm.edu.pl/vol/rzm2/linux-fedora/linux/epel/6/x86_64/polarssl-devel-1.3.2-1.el6.x86_64.rpm $ sudo rpm -Uhv ftp://ftp.pbone.net/mirror/archive.fedoraproject.org/fedora/linux/releases/15/Everything/x86_64/os/Packages/antlr3-C-3.2-14.fc15.x86_64.rpm $ sudo rpm -Uhv ftp://ftp.pbone.net/mirror/archive.fedoraproject.org/fedora/linux/releases/15/Everything/x86_64/os/Packages/antlr3-C-devel-3.2-14.fc15.x86_64.rpm - $ sudo rpm -Uhv ftp://ftp.pbone.net/mirror/archive.fedoraproject.org/fedora/linux/releases/15/Everything/x86_64/os/Packages/antlr3-tool-3.2-14.fc15.noarch.rpm - $ sudo rpm -Uhv ftp://ftp.pbone.net/mirror/archive.fedoraproject.org/fedora/linux/releases/15/Fedora/i386/os/Packages/antlr3-java-3.2-14.fc15.noarch.rpm - Git repository @@ -41,6 +44,9 @@ Download and install the repo rpmforge : $ ./configure $ make && make rpm +- Compile msx264 + $ ./autogen.sh && ./configure && make + $ make rpm -Create yum repo : $ cd rpmbuild/RPMS/*arch*/ From e42d96d797634afe73c53adb9588e4c4ccc235d4 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 4 Apr 2014 11:43:57 +0200 Subject: [PATCH 49/55] update ms2 (audiomixer bugfix) --- mediastreamer2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediastreamer2 b/mediastreamer2 index 90026398a..449077d8a 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 90026398ae7463ffc8ec0d5538905310cce51f5e +Subproject commit 449077d8af498c6d91a6dde236fd07e5a7f74b03 From 248bc24ab8869680700e3c482936ee2a5fffed7a Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 4 Apr 2014 12:36:28 +0200 Subject: [PATCH 50/55] update ms1 --- mediastreamer2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediastreamer2 b/mediastreamer2 index 449077d8a..a33899b52 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 449077d8af498c6d91a6dde236fd07e5a7f74b03 +Subproject commit a33899b52d15236fe99b5399242ab9d8c2a0f24e From 9b4197fef965a5994071dbbdada5865d3fa9fa9b Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Sat, 5 Apr 2014 09:45:06 +0200 Subject: [PATCH 51/55] add retry algo for vfu request + enable opus cbr by default --- coreapi/bellesip_sal/sal_op_call.c | 19 +++++++++++++++++-- coreapi/linphonecore.c | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index a77acafd0..e6262c60a 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -168,7 +168,12 @@ static void cancelling_invite(SalOp* op ){ sal_op_send_request(op,cancel); op->state=SalOpStateTerminating; } - +static int vfu_retry (void *user_data, unsigned int events) { + SalOp *op=(SalOp *)user_data; + sal_call_send_vfu_request(op); + sal_op_unref(op); + return BELLE_SIP_STOP; +} static void call_process_response(void *op_base, const belle_sip_response_event_t *event){ SalOp* op = (SalOp*)op_base; belle_sip_request_t* ack; @@ -177,6 +182,7 @@ static void call_process_response(void *op_base, const belle_sip_response_event_ belle_sip_request_t* req; belle_sip_response_t* response=belle_sip_response_event_get_response(event); int code = belle_sip_response_get_status_code(response); + belle_sip_header_content_type_t *header_content_type=NULL; if (!client_transaction) { @@ -247,7 +253,16 @@ static void call_process_response(void *op_base, const belle_sip_response_event_ op->state=SalOpStateActive; } else if (code >= 300 && strcmp("INVITE",belle_sip_request_get_method(req))==0){ call_set_error(op,response); - } else { + } else if (code == 491 + && strcmp("INFO",belle_sip_request_get_method(req)) == 0 + && (header_content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t)) + && strcmp("application",belle_sip_header_content_type_get_type(header_content_type))==0 + && strcmp("media_control+xml",belle_sip_header_content_type_get_subtype(header_content_type))==0) { + unsigned int retry_in =1000*((float)rand()/RAND_MAX); + belle_sip_source_t *s=sal_create_timer(op->base.root,vfu_retry,sal_op_ref(op), retry_in, "vfu request retry"); + ms_message("Rejected vfu request on op [%p], just retry in [%ui] ms",op,retry_in); + belle_sip_object_unref(s); + }else { /*ignoring*/ } break; diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index cad98f51e..8fccd7561 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1369,7 +1369,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab linphone_core_assign_payload_type(lc,&payload_type_g729,18,"annexb=no"); linphone_core_assign_payload_type(lc,&payload_type_aaceld_22k,-1,"config=F8EE2000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5"); linphone_core_assign_payload_type(lc,&payload_type_aaceld_44k,-1,"config=F8E82000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5"); - linphone_core_assign_payload_type(lc,&payload_type_opus,-1,"useinbandfec=1; usedtx=1"); + linphone_core_assign_payload_type(lc,&payload_type_opus,-1,"useinbandfec=1; usedtx=0; cbr=1"); linphone_core_assign_payload_type(lc,&payload_type_isac,-1,NULL); linphone_core_handle_static_payloads(lc); From 5e01d28d2bb5388a82de982fa274ba1e9f843ef1 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 7 Apr 2014 11:57:59 +0200 Subject: [PATCH 52/55] Added linphonecore stop ringing JNI wrapper --- coreapi/linphonecore_jni.cc | 4 ++++ java/common/org/linphone/core/LinphoneCore.java | 5 +++++ java/impl/org/linphone/core/LinphoneCoreImpl.java | 6 ++++++ 3 files changed, 15 insertions(+) diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index f5cc41bb9..f7c8f46eb 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -798,6 +798,10 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneCallImpl_sendInfoMessage(J return linphone_call_send_info_message((LinphoneCall*)callptr,(LinphoneInfoMessage*)infoptr); } +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_stopRinging(JNIEnv* env, jobject thiz, jlong lc) { + linphone_core_stop_ringing((LinphoneCore*)lc); +} + extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setChatDatabasePath(JNIEnv* env, jobject thiz, jlong lc, jstring jpath) { const char* path = env->GetStringUTFChars(jpath, NULL); linphone_core_set_chat_database_path((LinphoneCore*)lc, path); diff --git a/java/common/org/linphone/core/LinphoneCore.java b/java/common/org/linphone/core/LinphoneCore.java index 72164a3fe..3d22e10ba 100644 --- a/java/common/org/linphone/core/LinphoneCore.java +++ b/java/common/org/linphone/core/LinphoneCore.java @@ -1585,4 +1585,9 @@ public interface LinphoneCore { **/ public boolean chatEnabled(); + /** + * Whenever the liblinphone is playing a ring to advertise an incoming call or ringback of an outgoing call, this function stops the ringing. + * Typical use is to stop ringing when the user requests to ignore the call. + **/ + public void stopRinging(); } diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java index 16ca38e36..7a28a0867 100644 --- a/java/impl/org/linphone/core/LinphoneCoreImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java @@ -149,6 +149,7 @@ class LinphoneCoreImpl implements LinphoneCore { private native void setCallErrorTone(long nativePtr, int reason, String path); private native void enableSdp200Ack(long nativePtr,boolean enable); private native boolean isSdp200AckEnabled(long nativePtr); + private native void stopRinging(long nativePtr); LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig, File factoryConfig, Object userdata) throws IOException { mListener = listener; @@ -1181,4 +1182,9 @@ class LinphoneCoreImpl implements LinphoneCore { return chatEnabled(nativePtr); } + @Override + public void stopRinging() { + stopRinging(nativePtr); + } + } From 90b51017647087cc3fb1656a8c933bec5623934b Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Mon, 7 Apr 2014 12:48:00 +0200 Subject: [PATCH 53/55] Changes to add support of OpenH264 on Android. --- build/android/Android.mk | 8 ++++++++ coreapi/linphonecore_jni.cc | 10 ++++++++++ mediastreamer2 | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/build/android/Android.mk b/build/android/Android.mk index c2b04b389..18fbbdbfd 100755 --- a/build/android/Android.mk +++ b/build/android/Android.mk @@ -87,6 +87,9 @@ LOCAL_CFLAGS += -DVIDEO_ENABLED ifeq ($(BUILD_X264),1) LOCAL_CFLAGS += -DHAVE_X264 endif +ifeq ($(BUILD_OPENH264),1) +LOCAL_CFLAGS += -DHAVE_OPENH264 +endif endif ifeq ($(BUILD_CONTACT_HEADER),1) @@ -175,6 +178,11 @@ LOCAL_STATIC_LIBRARIES += \ libmsx264 \ libx264 endif +ifeq ($(BUILD_OPENH264),1) +LOCAL_STATIC_LIBRARIES += \ + libmsopenh264 \ + libwels +endif endif ifeq ($(BUILD_UPNP),1) diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index f7c8f46eb..824852418 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern "C" { #include "mediastreamer2/mediastream.h" +#include "mediastreamer2/mscommon.h" } #include "mediastreamer2/msjava.h" #include "private.h" @@ -39,6 +40,9 @@ extern "C" void libmsilbc_init(); #ifdef HAVE_X264 extern "C" void libmsx264_init(); #endif +#ifdef HAVE_OPENH264 +extern "C" void libmsopenh264_init(); +#endif #ifdef HAVE_AMR extern "C" void libmsamr_init(); #endif @@ -742,12 +746,17 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_newLinphoneCore(JNIEnv* const char* factoryConfig = jfactoryConfig?env->GetStringUTFChars(jfactoryConfig, NULL):NULL; LinphoneCoreData* ldata = new LinphoneCoreData(env,thiz,jlistener,juserdata); + ms_init(); // Initialize mediastreamer2 before loading the plugins + #ifdef HAVE_ILBC libmsilbc_init(); // requires an fpu #endif #ifdef HAVE_X264 libmsx264_init(); #endif +#ifdef HAVE_OPENH264 + libmsopenh264_init(); +#endif #ifdef HAVE_AMR libmsamr_init(); #endif @@ -776,6 +785,7 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_delete(JNIEnv* env ,jlong lc) { LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data((LinphoneCore*)lc); linphone_core_destroy((LinphoneCore*)lc); + ms_exit(); delete lcData; } diff --git a/mediastreamer2 b/mediastreamer2 index a33899b52..7111661bd 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit a33899b52d15236fe99b5399242ab9d8c2a0f24e +Subproject commit 7111661bd810352ed7a4ecc9c30c7754d3006a92 From affd021540f6f0245803105b9e129521f6ff2a62 Mon Sep 17 00:00:00 2001 From: Guillaume BIENKOWSKI Date: Mon, 7 Apr 2014 13:43:38 +0200 Subject: [PATCH 54/55] Add the ability to use a file:// protocol for provisioning --- coreapi/remote_provisioning.c | 63 +++++++++++++++++------ tester/rcfiles/marie_remote_localfile2_rc | 11 ++++ tester/rcfiles/marie_remote_localfile_rc | 3 ++ tester/remote_provisioning_tester.c | 43 ++++++++++------ 4 files changed, 88 insertions(+), 32 deletions(-) create mode 100644 tester/rcfiles/marie_remote_localfile2_rc create mode 100644 tester/rcfiles/marie_remote_localfile_rc diff --git a/coreapi/remote_provisioning.c b/coreapi/remote_provisioning.c index 7deb4d5e6..96ee2a6dd 100644 --- a/coreapi/remote_provisioning.c +++ b/coreapi/remote_provisioning.c @@ -52,11 +52,32 @@ static void linphone_remote_provisioning_apply(LinphoneCore *lc, const char *xml } } +static int linphone_remote_provisioning_load_file( LinphoneCore* lc, const char* file_path){ + int status = -1; + FILE* f = fopen(file_path, "r"); + + if( f ){ + fseek(f, 0, SEEK_END); + long fsize = ftell(f); + fseek(f, 0, SEEK_SET); + + char* provisioning = ms_malloc(fsize + 1); + fread(provisioning, fsize, 1, f); + fclose(f); + linphone_remote_provisioning_apply(lc, provisioning); + status = 0; + } else { + ms_error("Couldn't open file %s for provisioning", file_path); + } + + return status; +} + static void belle_request_process_response_event(void *ctx, const belle_http_response_event_t *event) { LinphoneCore *lc = (LinphoneCore *)ctx; belle_sip_message_t *body = BELLE_SIP_MESSAGE(event->response); const char *message = belle_sip_message_get_body(body); - + if (belle_http_response_get_status_code(event->response) == 200) { linphone_remote_provisioning_apply(lc, message); } else { @@ -80,23 +101,31 @@ static void belle_request_process_auth_requested(void *ctx, belle_sip_auth_event } int linphone_remote_provisioning_download_and_apply(LinphoneCore *lc, const char *remote_provisioning_uri) { - belle_generic_uri_t *uri=belle_generic_uri_parse(remote_provisioning_uri); - belle_http_request_listener_callbacks_t belle_request_listener = { - belle_request_process_response_event, - belle_request_process_io_error, - belle_request_process_timeout, - belle_request_process_auth_requested - }; - belle_http_request_listener_t *listener = belle_http_request_listener_create_from_callbacks(&belle_request_listener, lc); - belle_http_request_t *request; - - if (uri==NULL) { - belle_sip_error("Invalid provisioning URI [%s]",remote_provisioning_uri); - return -1; + const char* file_path = strstr(remote_provisioning_uri, "file://"); + + if( file_path == remote_provisioning_uri ){ + // We allow for 'local remote-provisioning' in case the file is to be opened from the hard drive + file_path += strlen("file://"); + return linphone_remote_provisioning_load_file(lc, file_path); + } else { + belle_generic_uri_t *uri=belle_generic_uri_parse(remote_provisioning_uri); + belle_http_request_listener_callbacks_t belle_request_listener = { + belle_request_process_response_event, + belle_request_process_io_error, + belle_request_process_timeout, + belle_request_process_auth_requested + }; + belle_http_request_listener_t *listener = belle_http_request_listener_create_from_callbacks(&belle_request_listener, lc); + belle_http_request_t *request; + + if (uri==NULL) { + belle_sip_error("Invalid provisioning URI [%s]",remote_provisioning_uri); + return -1; + } + request=belle_http_request_create("GET",uri, NULL); + belle_http_provider_send_request(lc->http_provider, request, listener); + return 0; } - request=belle_http_request_create("GET",uri, NULL); - belle_http_provider_send_request(lc->http_provider, request, listener); - return 0; } void linphone_core_set_provisioning_uri(LinphoneCore *lc, const char *uri) { diff --git a/tester/rcfiles/marie_remote_localfile2_rc b/tester/rcfiles/marie_remote_localfile2_rc new file mode 100644 index 000000000..d41ca4c8d --- /dev/null +++ b/tester/rcfiles/marie_remote_localfile2_rc @@ -0,0 +1,11 @@ + + +
+ 0 + 1 +
+
+ 1 + 1 +
+
diff --git a/tester/rcfiles/marie_remote_localfile_rc b/tester/rcfiles/marie_remote_localfile_rc new file mode 100644 index 000000000..b2f947607 --- /dev/null +++ b/tester/rcfiles/marie_remote_localfile_rc @@ -0,0 +1,3 @@ +[misc] +config-uri=file://./rcfiles/marie_remote_localfile2_rc + diff --git a/tester/remote_provisioning_tester.c b/tester/remote_provisioning_tester.c index f38ab9a67..99bfbcc6a 100644 --- a/tester/remote_provisioning_tester.c +++ b/tester/remote_provisioning_tester.c @@ -1,19 +1,19 @@ /* - liblinphone_tester - liblinphone test suite - Copyright (C) 2013 Belledonne Communications SARL + liblinphone_tester - liblinphone test suite + Copyright (C) 2013 Belledonne Communications SARL - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #include @@ -29,9 +29,9 @@ void linphone_configuration_status(LinphoneCore *lc, LinphoneConfiguringState st if (status == LinphoneConfiguringSkipped) { counters->number_of_LinphoneConfiguringSkipped++; } else if (status == LinphoneConfiguringFailed) { - counters->number_of_LinphoneConfiguringFailed++; + counters->number_of_LinphoneConfiguringFailed++; } else if (status == LinphoneConfiguringSuccessful) { - counters->number_of_LinphoneConfiguringSuccessful++; + counters->number_of_LinphoneConfiguringSuccessful++; } } @@ -89,6 +89,18 @@ static void remote_provisioning_default_values(void) { linphone_core_manager_destroy(marie); } +static void remote_provisioning_file(void) { + LinphoneCoreManager* marie = linphone_core_manager_new2("marie_remote_localfile_rc", FALSE); + const LpConfig* conf; + CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphoneConfiguringSuccessful,1)); + + conf = linphone_core_get_config( marie->lc ); + CU_ASSERT_EQUAL( lp_config_get_int(conf,"misc","tester_file_ok", 0), 1 ); + + linphone_core_manager_destroy(marie); +} + + test_t remote_provisioning_tests[] = { { "Remote provisioning skipped", remote_provisioning_skipped }, { "Remote provisioning successful behind http", remote_provisioning_http }, @@ -96,7 +108,8 @@ test_t remote_provisioning_tests[] = { { "Remote provisioning 404 not found", remote_provisioning_not_found }, { "Remote provisioning invalid", remote_provisioning_invalid }, { "Remote provisioning transient successful", remote_provisioning_transient }, - { "Remote provisioning default values", remote_provisioning_default_values } + { "Remote provisioning default values", remote_provisioning_default_values }, + { "Remote provisioning from file", remote_provisioning_file } }; test_suite_t remote_provisioning_test_suite = { From 7bd50e004faa0cb55ff39a477f766c07efb1a7d9 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Mon, 7 Apr 2014 17:36:51 +0200 Subject: [PATCH 55/55] allow usage of system-choosen random ports. Implies a lot of refactoring in streams management. --- coreapi/callbacks.c | 7 +- coreapi/linphonecall.c | 259 ++++++++++++++++++++--------------------- coreapi/linphonecore.c | 25 ++-- coreapi/misc.c | 25 ++-- coreapi/private.h | 9 +- mediastreamer2 | 2 +- oRTP | 2 +- tester/call_tester.c | 62 +++++++++- tester/stun_tester.c | 4 +- 9 files changed, 230 insertions(+), 165 deletions(-) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index cb88095c7..efd17aab6 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -58,14 +58,14 @@ void linphone_core_update_streams_destinations(LinphoneCore *lc, LinphoneCall *c rtp_addr = (new_audiodesc->rtp_addr[0] != '\0') ? new_audiodesc->rtp_addr : new_md->addr; rtcp_addr = (new_audiodesc->rtcp_addr[0] != '\0') ? new_audiodesc->rtcp_addr : new_md->addr; ms_message("Change audio stream destination: RTP=%s:%d RTCP=%s:%d", rtp_addr, new_audiodesc->rtp_port, rtcp_addr, new_audiodesc->rtcp_port); - rtp_session_set_remote_addr_full(call->audiostream->ms.session, rtp_addr, new_audiodesc->rtp_port, rtcp_addr, new_audiodesc->rtcp_port); + rtp_session_set_remote_addr_full(call->audiostream->ms.sessions.rtp_session, rtp_addr, new_audiodesc->rtp_port, rtcp_addr, new_audiodesc->rtcp_port); } #ifdef VIDEO_ENABLED if (call->videostream && new_videodesc) { rtp_addr = (new_videodesc->rtp_addr[0] != '\0') ? new_videodesc->rtp_addr : new_md->addr; rtcp_addr = (new_videodesc->rtcp_addr[0] != '\0') ? new_videodesc->rtcp_addr : new_md->addr; ms_message("Change video stream destination: RTP=%s:%d RTCP=%s:%d", rtp_addr, new_videodesc->rtp_port, rtcp_addr, new_videodesc->rtcp_port); - rtp_session_set_remote_addr_full(call->videostream->ms.session, rtp_addr, new_videodesc->rtp_port, rtcp_addr, new_videodesc->rtcp_port); + rtp_session_set_remote_addr_full(call->videostream->ms.sessions.rtp_session, rtp_addr, new_videodesc->rtp_port, rtcp_addr, new_videodesc->rtcp_port); } #else (void)new_videodesc; @@ -97,7 +97,7 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia sal_media_description_ref(new_md); call->expect_media_in_ack=FALSE; call->resultdesc=new_md; - if ((call->audiostream && call->audiostream->ms.ticker) || (call->videostream && call->videostream->ms.ticker)){ + if ((call->audiostream && call->audiostream->ms.state==MSStreamStarted) || (call->videostream && call->videostream->ms.state==MSStreamStarted)){ /* we already started media: check if we really need to restart it*/ if (oldmd){ int md_changed = media_parameters_changed(call, oldmd, new_md); @@ -671,7 +671,6 @@ static void call_failure(SalOp *op){ !linphone_core_is_media_encryption_mandatory(lc)) { int i; ms_message("Outgoing call [%p] failed with SRTP (SAVP) enabled",call); - linphone_call_stop_media_streams(call); if (call->state==LinphoneCallOutgoingInit || call->state==LinphoneCallOutgoingProgress || call->state==LinphoneCallOutgoingRinging /*push case*/ diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index e4cac3a33..c5f3ef3f2 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -191,13 +191,13 @@ void linphone_call_set_authentication_token_verified(LinphoneCall *call, bool_t if (call->audiostream==NULL){ ms_error("linphone_call_set_authentication_token_verified(): No audio stream"); } - if (call->audiostream->ms.zrtp_context==NULL){ + if (call->audiostream->ms.sessions.zrtp_context==NULL){ ms_error("linphone_call_set_authentication_token_verified(): No zrtp context."); } if (!call->auth_token_verified && verified){ - ortp_zrtp_sas_verified(call->audiostream->ms.zrtp_context); + ortp_zrtp_sas_verified(call->audiostream->ms.sessions.zrtp_context); }else if (call->auth_token_verified && !verified){ - ortp_zrtp_sas_reset_verified(call->audiostream->ms.zrtp_context); + ortp_zrtp_sas_reset_verified(call->audiostream->ms.sessions.zrtp_context); } call->auth_token_verified=verified; propagate_encryption_changed(call); @@ -333,8 +333,8 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall * 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].rtp_port=call->media_ports[0].rtp_port; + md->streams[0].rtcp_port=call->media_ports[0].rtcp_port; md->streams[0].proto=(call->params.media_encryption == LinphoneMediaEncryptionSRTP) ? SalProtoRtpSavp : SalProtoRtpAvp; md->streams[0].type=SalAudio; @@ -350,8 +350,8 @@ 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].rtp_port=call->media_ports[1].rtp_port; + md->streams[1].rtcp_port=call->media_ports[1].rtcp_port; md->streams[1].proto=md->streams[0].proto; md->streams[1].type=SalVideo; l=make_codec_list(lc,lc->codecs_conf.video_codecs,0,NULL,-1); @@ -393,34 +393,19 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall * } } -static int find_port_offset(LinphoneCore *lc, SalStreamType type){ +static int find_port_offset(LinphoneCore *lc, int stream_index, int base_port){ int offset; MSList *elem; int tried_port; int existing_port; bool_t already_used=FALSE; + for(offset=0;offset<100;offset+=2){ - switch (type) { - default: - case SalAudio: - tried_port=linphone_core_get_audio_port (lc)+offset; - break; - case SalVideo: - tried_port=linphone_core_get_video_port (lc)+offset; - break; - } + tried_port=base_port+offset; already_used=FALSE; for(elem=lc->calls;elem!=NULL;elem=elem->next){ LinphoneCall *call=(LinphoneCall*)elem->data; - switch (type) { - default: - case SalAudio: - existing_port = call->audio_port; - break; - case SalVideo: - existing_port = call->video_port; - break; - } + existing_port=call->media_ports[stream_index].rtp_port; if (existing_port==tried_port) { already_used=TRUE; break; @@ -435,37 +420,19 @@ static int find_port_offset(LinphoneCore *lc, SalStreamType type){ return offset; } -static int select_random_port(LinphoneCore *lc, SalStreamType type) { +static int select_random_port(LinphoneCore *lc, int stream_index, int min_port, int max_port) { MSList *elem; int nb_tries; int tried_port = 0; int existing_port = 0; - int min_port = 0, max_port = 0; bool_t already_used = FALSE; - switch (type) { - default: - case SalAudio: - linphone_core_get_audio_port_range(lc, &min_port, &max_port); - break; - case SalVideo: - linphone_core_get_video_port_range(lc, &min_port, &max_port); - break; - } tried_port = (rand() % (max_port - min_port) + min_port) & ~0x1; if (tried_port < min_port) tried_port = min_port + 2; for (nb_tries = 0; nb_tries < 100; nb_tries++) { for (elem = lc->calls; elem != NULL; elem = elem->next) { LinphoneCall *call = (LinphoneCall *)elem->data; - switch (type) { - default: - case SalAudio: - existing_port = call->audio_port; - break; - case SalVideo: - existing_port = call->video_port; - break; - } + existing_port=call->media_ports[stream_index].rtp_port; if (existing_port == tried_port) { already_used = TRUE; break; @@ -480,8 +447,31 @@ static int select_random_port(LinphoneCore *lc, SalStreamType type) { return tried_port; } -static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){ +static void port_config_set_random(LinphoneCall *call, int stream_index){ + call->media_ports[stream_index].rtp_port=-1; + call->media_ports[stream_index].rtcp_port=-1; +} + +static void port_config_set(LinphoneCall *call, int stream_index, int min_port, int max_port){ int port_offset; + if (min_port>0 && max_port>0){ + if (min_port == max_port) { + /* Used fixed RTP audio port. */ + port_offset=find_port_offset(call->core, stream_index, min_port); + if (port_offset==-1) { + port_config_set_random(call, stream_index); + return; + } + call->media_ports[stream_index].rtp_port=min_port+port_offset; + } else { + /* Select random RTP audio port in the specified range. */ + call->media_ports[stream_index].rtp_port = select_random_port(call->core, stream_index, min_port, max_port); + } + call->media_ports[stream_index].rtcp_port=call->media_ports[stream_index].rtp_port+1; + }else port_config_set_random(call,stream_index); +} + +static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){ int min_port, max_port; call->magic=linphone_call_magic; @@ -494,25 +484,11 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, call->camera_enabled=TRUE; linphone_core_get_audio_port_range(call->core, &min_port, &max_port); - if (min_port == max_port) { - /* Used fixed RTP audio port. */ - port_offset=find_port_offset (call->core, SalAudio); - if (port_offset==-1) return; - call->audio_port=linphone_core_get_audio_port(call->core)+port_offset; - } else { - /* Select random RTP audio port in the specified range. */ - call->audio_port = select_random_port(call->core, SalAudio); - } + port_config_set(call,0,min_port,max_port); + linphone_core_get_video_port_range(call->core, &min_port, &max_port); - if (min_port == max_port) { - /* Used fixed RTP video port. */ - port_offset=find_port_offset (call->core, SalVideo); - if (port_offset==-1) return; - call->video_port=linphone_core_get_video_port(call->core)+port_offset; - } else { - /* Select random RTP video port in the specified range. */ - call->video_port = select_random_port(call->core, SalVideo); - } + port_config_set(call,1,min_port,max_port); + linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO], LINPHONE_CALL_STATS_AUDIO); linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO], LINPHONE_CALL_STATS_VIDEO); } @@ -663,20 +639,22 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro // In this case WE chose the media parameters according to policy. call->params.has_video &= linphone_core_media_description_contains_video_stream(md); } - + /*create the ice session now if ICE is required*/ + if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseIce){ + call->ice_session = ice_session_new(); + ice_session_set_role(call->ice_session, IR_Controlled); + } + /*reserve the sockets immediately*/ + linphone_call_init_media_streams(call); switch (linphone_core_get_firewall_policy(call->core)) { case LinphonePolicyUseIce: - call->ice_session = ice_session_new(); - ice_session_set_role(call->ice_session, IR_Controlled); + /*start ICE gathering*/ linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(op)); - if (call->ice_session != NULL) { - linphone_call_init_media_streams(call); - linphone_call_start_media_streams_for_ice_gathering(call); - if (linphone_core_gather_ice_candidates(call->core,call)<0) { - /* Ice candidates gathering failed, proceed with the call anyway. */ - linphone_call_delete_ice_session(call); - linphone_call_stop_media_streams_for_ice_gathering(call); - } + linphone_call_start_media_streams_for_ice_gathering(call); + if (linphone_core_gather_ice_candidates(call->core,call)<0) { + /* Ice candidates gathering failed, proceed with the call anyway. */ + linphone_call_delete_ice_session(call); + linphone_call_stop_media_streams_for_ice_gathering(call); } break; case LinphonePolicyUseStun: @@ -688,7 +666,6 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro if(!lc->rtp_conf.disable_upnp) { call->upnp_session = linphone_upnp_session_new(call); if (call->upnp_session != NULL) { - linphone_call_init_media_streams(call); if (linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(op))<0) { /* uPnP port mappings failed, proceed with the call anyway. */ linphone_call_delete_upnp_session(call); @@ -714,6 +691,11 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro static void linphone_call_set_terminated(LinphoneCall *call){ LinphoneCore *lc=call->core; + linphone_call_stop_media_streams(call); + ms_media_stream_sessions_uninit(&call->sessions[0]); + ms_media_stream_sessions_uninit(&call->sessions[1]); + linphone_call_delete_upnp_session(call); + linphone_call_delete_ice_session(call); linphone_core_update_allocated_audio_bandwidth(lc); call->owns_call_log=FALSE; @@ -856,11 +838,6 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const static void linphone_call_destroy(LinphoneCall *obj) { ms_message("Call [%p] freed.",obj); - linphone_call_stop_media_streams(obj); -#ifdef BUILD_UPNP - linphone_call_delete_upnp_session(obj); -#endif //BUILD_UPNP - linphone_call_delete_ice_session(obj); if (obj->op!=NULL) { sal_op_release(obj->op); obj->op=NULL; @@ -1444,17 +1421,31 @@ void linphone_call_set_next_video_frame_decoded_callback(LinphoneCall *call, Lin call->nextVideoFrameDecoded._func = cb; call->nextVideoFrameDecoded._user_data = user_data; #ifdef VIDEO_ENABLED - ms_filter_call_method_noarg(call->videostream->ms.decoder, MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION); + if (call->videostream && call->videostream->ms.decoder) + ms_filter_call_method_noarg(call->videostream->ms.decoder, MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION); #endif } +static void port_config_set_random_choosed(LinphoneCall *call, int stream_index, RtpSession *session){ + call->media_ports[stream_index].rtp_port=rtp_session_get_local_port(session); + call->media_ports[stream_index].rtcp_port=rtp_session_get_local_rtcp_port(session); +} + void linphone_call_init_audio_stream(LinphoneCall *call){ LinphoneCore *lc=call->core; AudioStream *audiostream; int dscp; if (call->audiostream != NULL) return; - call->audiostream=audiostream=audio_stream_new(call->audio_port,call->audio_port+1,call->af==AF_INET6); + if (call->sessions[0].rtp_session==NULL){ + call->audiostream=audiostream=audio_stream_new(call->media_ports[0].rtp_port,call->media_ports[0].rtcp_port,call->af==AF_INET6); + }else{ + call->audiostream=audio_stream_new_with_sessions(&call->sessions[0]); + } + audiostream=call->audiostream; + if (call->media_ports[0].rtp_port==-1){ + port_config_set_random_choosed(call,0,audiostream->ms.sessions.rtp_session); + } dscp=linphone_core_get_audio_dscp(lc); if (dscp!=-1) audio_stream_set_dscp(audiostream,dscp); @@ -1486,69 +1477,73 @@ void linphone_call_init_audio_stream(LinphoneCall *call){ audio_stream_set_features(audiostream,linphone_core_get_audio_features(lc)); if (lc->rtptf){ - RtpTransport *artp=lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->audio_port); - RtpTransport *artcp=lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->audio_port+1); - rtp_session_set_transports(audiostream->ms.session,artp,artcp); + RtpTransport *artp=lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->media_ports[0].rtp_port); + RtpTransport *artcp=lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->media_ports[0].rtcp_port); + rtp_session_set_transports(audiostream->ms.sessions.rtp_session,artp,artcp); } if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ - rtp_session_set_pktinfo(audiostream->ms.session, TRUE); - rtp_session_set_symmetric_rtp(audiostream->ms.session, FALSE); + rtp_session_set_pktinfo(audiostream->ms.sessions.rtp_session, TRUE); + rtp_session_set_symmetric_rtp(audiostream->ms.sessions.rtp_session, FALSE); if (ice_session_check_list(call->ice_session, 0) == NULL) { ice_session_add_check_list(call->ice_session, ice_check_list_new()); } audiostream->ms.ice_check_list = ice_session_check_list(call->ice_session, 0); - ice_check_list_set_rtp_session(audiostream->ms.ice_check_list, audiostream->ms.session); + ice_check_list_set_rtp_session(audiostream->ms.ice_check_list, audiostream->ms.sessions.rtp_session); } call->audiostream_app_evq = ortp_ev_queue_new(); - rtp_session_register_event_queue(audiostream->ms.session,call->audiostream_app_evq); + rtp_session_register_event_queue(audiostream->ms.sessions.rtp_session,call->audiostream_app_evq); } void linphone_call_init_video_stream(LinphoneCall *call){ #ifdef VIDEO_ENABLED LinphoneCore *lc=call->core; - if (!call->params.has_video) { - linphone_call_stop_video_stream(call); - return; - } - if (call->videostream != NULL) return; - if ((lc->video_conf.display || lc->video_conf.capture) && call->params.has_video){ + if (call->videostream == NULL){ int video_recv_buf_size=lp_config_get_int(lc->config,"video","recv_buf_size",0); int dscp=linphone_core_get_video_dscp(lc); const char *display_filter=linphone_core_get_video_display_filter(lc); - - call->videostream=video_stream_new(call->video_port,call->video_port+1,call->af==AF_INET6); + + if (call->sessions[1].rtp_session==NULL){ + call->videostream=video_stream_new(call->media_ports[1].rtp_port,call->media_ports[1].rtcp_port, call->af==AF_INET6); + }else{ + call->videostream=video_stream_new_with_sessions(&call->sessions[1]); + } + if (call->media_ports[1].rtp_port==-1){ + port_config_set_random_choosed(call,1,call->videostream->ms.sessions.rtp_session); + } if (dscp!=-1) video_stream_set_dscp(call->videostream,dscp); video_stream_enable_display_filter_auto_rotate(call->videostream, lp_config_get_int(lc->config,"video","display_filter_auto_rotate",0)); - if (video_recv_buf_size>0) rtp_session_set_recv_buf_size(call->videostream->ms.session,video_recv_buf_size); + if (video_recv_buf_size>0) rtp_session_set_recv_buf_size(call->videostream->ms.sessions.rtp_session,video_recv_buf_size); if (display_filter != NULL) video_stream_set_display_filter_name(call->videostream,display_filter); video_stream_set_event_callback(call->videostream,video_stream_event_cb, call); if (lc->rtptf){ - RtpTransport *vrtp=lc->rtptf->video_rtp_func(lc->rtptf->video_rtp_func_data, call->video_port); - RtpTransport *vrtcp=lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->video_port+1); - rtp_session_set_transports(call->videostream->ms.session,vrtp,vrtcp); + RtpTransport *vrtp=lc->rtptf->video_rtp_func(lc->rtptf->video_rtp_func_data, call->media_ports[1].rtp_port); + RtpTransport *vrtcp=lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->media_ports[1].rtcp_port); + rtp_session_set_transports(call->videostream->ms.sessions.rtp_session,vrtp,vrtcp); } - if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ - rtp_session_set_pktinfo(call->videostream->ms.session, TRUE); - rtp_session_set_symmetric_rtp(call->videostream->ms.session, FALSE); - if (ice_session_check_list(call->ice_session, 1) == NULL) { - ice_session_add_check_list(call->ice_session, ice_check_list_new()); - } - call->videostream->ms.ice_check_list = ice_session_check_list(call->ice_session, 1); - ice_check_list_set_rtp_session(call->videostream->ms.ice_check_list, call->videostream->ms.session); - ms_message ("creating new ice video check list [%p] for session [%p]",call->videostream->ms.ice_check_list,call->videostream->ms.session); - } - - call->videostream_app_evq = ortp_ev_queue_new(); - rtp_session_register_event_queue(call->videostream->ms.session,call->videostream_app_evq); + call->videostream_app_evq = ortp_ev_queue_new(); + rtp_session_register_event_queue(call->videostream->ms.sessions.rtp_session,call->videostream_app_evq); #ifdef TEST_EXT_RENDERER video_stream_set_render_callback(call->videostream,rendercb,NULL); #endif } + /*eventually re-create the ICE check list that may have been destroyed if the stream wasn't used recently*/ + if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ + rtp_session_set_pktinfo(call->videostream->ms.sessions.rtp_session, TRUE); + rtp_session_set_symmetric_rtp(call->videostream->ms.sessions.rtp_session, FALSE); + if (ice_session_check_list(call->ice_session, 1) == NULL) { + ice_session_add_check_list(call->ice_session, ice_check_list_new()); + } + call->videostream->ms.ice_check_list = ice_session_check_list(call->ice_session, 1); + ice_check_list_set_rtp_session(call->videostream->ms.ice_check_list, call->videostream->ms.sessions.rtp_session); + ms_message ("creating new ice video check list [%p] for session [%p]",call->videostream->ms.ice_check_list,call->videostream->ms.sessions.rtp_session); + } + + #else call->videostream=NULL; #endif @@ -1779,9 +1774,9 @@ static void configure_rtp_session_for_rtcp_xr(LinphoneCore *lc, LinphoneCall *ca memcpy(¤tconfig, remoteconfig, sizeof(currentconfig)); } if (type == SalAudio) { - session = call->audiostream->ms.session; + session = call->audiostream->ms.sessions.rtp_session; } else { - session = call->videostream->ms.session; + session = call->videostream->ms.sessions.rtp_session; } rtp_session_configure_rtcp_xr(session, ¤tconfig); if (currentconfig.rcvr_rtt_mode != OrtpRtcpXrRcvrRttNone) { @@ -2166,14 +2161,16 @@ void linphone_call_delete_ice_session(LinphoneCall *call){ } } -#ifdef BUILD_UPNP + void linphone_call_delete_upnp_session(LinphoneCall *call){ +#ifdef BUILD_UPNP if(call->upnp_session!=NULL) { linphone_upnp_session_destroy(call->upnp_session); call->upnp_session=NULL; } -} #endif //BUILD_UPNP +} + static void linphone_call_log_fill_stats(LinphoneCallLog *log, MediaStream *st){ float quality=media_stream_get_average_quality_rating(st); @@ -2186,7 +2183,8 @@ static void linphone_call_log_fill_stats(LinphoneCallLog *log, MediaStream *st){ void linphone_call_stop_audio_stream(LinphoneCall *call) { if (call->audiostream!=NULL) { - rtp_session_unregister_event_queue(call->audiostream->ms.session,call->audiostream_app_evq); + media_stream_reclaim_sessions(&call->audiostream->ms,&call->sessions[0]); + rtp_session_unregister_event_queue(call->audiostream->ms.sessions.rtp_session,call->audiostream_app_evq); ortp_ev_queue_flush(call->audiostream_app_evq); ortp_ev_queue_destroy(call->audiostream_app_evq); call->audiostream_app_evq=NULL; @@ -2213,7 +2211,8 @@ void linphone_call_stop_audio_stream(LinphoneCall *call) { void linphone_call_stop_video_stream(LinphoneCall *call) { #ifdef VIDEO_ENABLED if (call->videostream!=NULL){ - rtp_session_unregister_event_queue(call->videostream->ms.session,call->videostream_app_evq); + media_stream_reclaim_sessions(&call->videostream->ms,&call->sessions[1]); + rtp_session_unregister_event_queue(call->videostream->ms.sessions.rtp_session,call->videostream_app_evq); ortp_ev_queue_flush(call->videostream_app_evq); ortp_ev_queue_destroy(call->videostream_app_evq); call->videostream_app_evq=NULL; @@ -2684,12 +2683,12 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse if ((call->state==LinphoneCallStreamsRunning || call->state==LinphoneCallOutgoingEarlyMedia || call->state==LinphoneCallIncomingEarlyMedia) && one_second_elapsed){ float audio_load=0, video_load=0; if (call->audiostream!=NULL){ - if (call->audiostream->ms.ticker) - audio_load=ms_ticker_get_average_load(call->audiostream->ms.ticker); + if (call->audiostream->ms.sessions.ticker) + audio_load=ms_ticker_get_average_load(call->audiostream->ms.sessions.ticker); } if (call->videostream!=NULL){ - if (call->videostream->ms.ticker) - video_load=ms_ticker_get_average_load(call->videostream->ms.ticker); + if (call->videostream->ms.sessions.ticker) + video_load=ms_ticker_get_average_load(call->videostream->ms.sessions.ticker); } report_bandwidth(call,(MediaStream*)call->audiostream,(MediaStream*)call->videostream); ms_message("Thread processing load: audio=%f\tvideo=%f",audio_load,video_load); @@ -2716,7 +2715,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){ linphone_call_videostream_encryption_changed(call, evd->info.zrtp_stream_encrypted); } else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) { - call->stats[LINPHONE_CALL_STATS_VIDEO].round_trip_delay = rtp_session_get_round_trip_propagation(call->videostream->ms.session); + call->stats[LINPHONE_CALL_STATS_VIDEO].round_trip_delay = rtp_session_get_round_trip_propagation(call->videostream->ms.sessions.rtp_session); if(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp != NULL) freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp); call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp = evd->packet; @@ -2726,7 +2725,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse if (lc->vtable.call_stats_updated) lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]); } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) { - memcpy(&call->stats[LINPHONE_CALL_STATS_VIDEO].jitter_stats, rtp_session_get_jitter_stats(call->videostream->ms.session), sizeof(jitter_stats_t)); + memcpy(&call->stats[LINPHONE_CALL_STATS_VIDEO].jitter_stats, rtp_session_get_jitter_stats(call->videostream->ms.sessions.rtp_session), sizeof(jitter_stats_t)); if(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp != NULL) freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp); call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp = evd->packet; @@ -2761,7 +2760,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse } else if (evt == ORTP_EVENT_ZRTP_SAS_READY) { linphone_call_audiostream_auth_token_ready(call, evd->info.zrtp_sas.sas, evd->info.zrtp_sas.verified); } else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) { - call->stats[LINPHONE_CALL_STATS_AUDIO].round_trip_delay = rtp_session_get_round_trip_propagation(call->audiostream->ms.session); + call->stats[LINPHONE_CALL_STATS_AUDIO].round_trip_delay = rtp_session_get_round_trip_propagation(call->audiostream->ms.sessions.rtp_session); if(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp != NULL) freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp); call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp = evd->packet; @@ -2771,7 +2770,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse if (lc->vtable.call_stats_updated) lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]); } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) { - memcpy(&call->stats[LINPHONE_CALL_STATS_AUDIO].jitter_stats, rtp_session_get_jitter_stats(call->audiostream->ms.session), sizeof(jitter_stats_t)); + memcpy(&call->stats[LINPHONE_CALL_STATS_AUDIO].jitter_stats, rtp_session_get_jitter_stats(call->audiostream->ms.sessions.rtp_session), sizeof(jitter_stats_t)); if(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp != NULL) freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp); call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp = evd->packet; diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 8fccd7561..6c609d037 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1755,6 +1755,8 @@ void linphone_core_set_rtp_no_xmit_on_audio_mute(LinphoneCore *lc,bool_t rtp_no_ /** * Sets the UDP port used for audio streaming. + * A value if -1 will request the system to allocate the local port randomly. + * This is recommended in order to avoid firewall warnings. * * @ingroup network_parameters **/ @@ -1775,6 +1777,8 @@ void linphone_core_set_audio_port_range(LinphoneCore *lc, int min_port, int max_ /** * Sets the UDP port used for video streaming. + * A value if -1 will request the system to allocate the local port randomly. + * This is recommended in order to avoid firewall warnings. * * @ingroup network_parameters **/ @@ -2604,6 +2608,10 @@ int linphone_core_proceed_with_invite_if_ready(LinphoneCore *lc, LinphoneCall *c int linphone_core_restart_invite(LinphoneCore *lc, LinphoneCall *call){ linphone_call_create_op(call); + linphone_call_stop_media_streams(call); + ms_media_stream_sessions_uninit(&call->sessions[0]); + ms_media_stream_sessions_uninit(&call->sessions[1]); + linphone_call_init_media_streams(call); return linphone_core_start_invite(lc,call, NULL); } @@ -2615,7 +2623,6 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, const Linph linphone_call_set_contact_op(call); linphone_core_stop_dtmf_stream(lc); - linphone_call_init_media_streams(call); linphone_call_make_local_media_description(lc,call); if (lc->ringstream==NULL) { @@ -2826,9 +2833,9 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const /* this call becomes now the current one*/ lc->current_call=call; linphone_call_set_state (call,LinphoneCallOutgoingInit,"Starting outgoing call"); + linphone_call_init_media_streams(call); if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) { /* Defer the start of the call after the ICE gathering process. */ - linphone_call_init_media_streams(call); linphone_call_start_media_streams_for_ice_gathering(call); call->log->start_date_time=time(NULL); if (linphone_core_gather_ice_candidates(lc,call)<0) { @@ -2841,7 +2848,6 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const } else if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) { #ifdef BUILD_UPNP - linphone_call_init_media_streams(call); call->log->start_date_time=time(NULL); if (linphone_core_update_upnp(lc,call)<0) { /* uPnP port mappings failed, proceed with the call anyway. */ @@ -3280,6 +3286,7 @@ int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const } return _linphone_core_accept_call_update(lc, call, params); } + int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){ SalMediaDescription *remote_desc; bool_t keep_sdp_version; @@ -3310,13 +3317,13 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons call->params.has_video = FALSE; } call->params.has_video &= linphone_core_media_description_contains_video_stream(remote_desc); + linphone_call_init_media_streams(call); /*so that video stream is initialized if necessary*/ linphone_call_make_local_media_description(lc,call); if (call->ice_session != NULL) { linphone_core_update_ice_from_remote_media_description(call, remote_desc); #ifdef VIDEO_ENABLED - if ((call->ice_session != NULL) &&!ice_session_candidates_gathered(call->ice_session)) { + if ((call->ice_session != NULL) && !ice_session_candidates_gathered(call->ice_session)) { if ((call->params.has_video) && (call->params.has_video != old_has_video)) { - linphone_call_init_video_stream(call); video_stream_prepare_video(call->videostream); if (linphone_core_gather_ice_candidates(lc,call)<0) { /* Ice candidates gathering failed, proceed with the call anyway. */ @@ -3332,7 +3339,6 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(call->op)); #ifdef VIDEO_ENABLED if ((call->params.has_video) && (call->params.has_video != old_has_video)) { - linphone_call_init_video_stream(call); video_stream_prepare_video(call->videostream); if (linphone_core_update_upnp(lc, call)<0) { /* uPnP update failed, proceed with the call anyway. */ @@ -3435,9 +3441,6 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, sal_op_set_sent_custom_header(call->op,params->custom_headers); } - if (call->audiostream==NULL) - linphone_call_init_media_streams(call); - /*give a chance a set card prefered sampling frequency*/ if (call->localdesc->streams[0].max_rate>0) { ms_message ("configuring prefered card sampling rate to [%i]",call->localdesc->streams[0].max_rate); @@ -3447,7 +3450,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, ms_snd_card_set_preferred_sample_rate(lc->sound_conf.capt_sndcard, call->localdesc->streams[0].max_rate); } - if (!was_ringing && call->audiostream->ms.ticker==NULL){ + if (!was_ringing && call->audiostream->ms.state==MSStreamInitialized){ audio_stream_prepare_sound(call->audiostream,lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard); } @@ -5366,7 +5369,7 @@ void linphone_core_set_play_file(LinphoneCore *lc, const char *file){ } if (file!=NULL) { lc->play_file=ms_strdup(file); - if (call && call->audiostream && call->audiostream->ms.ticker) + if (call && call->audiostream && call->audiostream->ms.state==MSStreamStarted) audio_stream_play(call->audiostream,file); } } diff --git a/coreapi/misc.c b/coreapi/misc.c index 4c9834053..37198490e 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -375,6 +375,10 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ ms_warning("stun support is not implemented for ipv6"); return -1; } + if (call->media_ports[0].rtp_port==-1){ + ms_warning("Stun-only support not available for system random port"); + return -1; + } if (server!=NULL){ const struct addrinfo *ai=linphone_core_get_stun_server_addrinfo(lc); ortp_socket_t sock1=-1, sock2=-1; @@ -394,10 +398,10 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ lc->vtable.display_status(lc,_("Stun lookup in progress...")); /*create the two audio and video RTP sockets, and send STUN message to our stun server */ - sock1=create_socket(call->audio_port); + sock1=create_socket(call->media_ports[0].rtp_port); if (sock1==-1) return -1; if (video_enabled){ - sock2=create_socket(call->video_port); + sock2=create_socket(call->media_ports[1].rtp_port); if (sock2==-1) return -1; } got_audio=FALSE; @@ -581,14 +585,14 @@ int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call) return -1; } if ((ice_check_list_state(audio_check_list) != ICL_Completed) && (ice_check_list_candidates_gathered(audio_check_list) == FALSE)) { - ice_add_local_candidate(audio_check_list, "host", local_addr, call->audio_port, 1, NULL); - ice_add_local_candidate(audio_check_list, "host", local_addr, call->audio_port + 1, 2, NULL); + ice_add_local_candidate(audio_check_list, "host", local_addr, call->media_ports[0].rtp_port, 1, NULL); + ice_add_local_candidate(audio_check_list, "host", local_addr, call->media_ports[0].rtcp_port, 2, NULL); call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateInProgress; } - if (call->params.has_video && (video_check_list != NULL) + if (linphone_core_video_enabled(lc) && (video_check_list != NULL) && (ice_check_list_state(video_check_list) != ICL_Completed) && (ice_check_list_candidates_gathered(video_check_list) == FALSE)) { - ice_add_local_candidate(video_check_list, "host", local_addr, call->video_port, 1, NULL); - ice_add_local_candidate(video_check_list, "host", local_addr, call->video_port + 1, 2, NULL); + ice_add_local_candidate(video_check_list, "host", local_addr, call->media_ports[1].rtp_port, 1, NULL); + ice_add_local_candidate(video_check_list, "host", local_addr, call->media_ports[1].rtcp_port, 2, NULL); call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateInProgress; } @@ -883,7 +887,12 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call, } } for (i = ice_session_nb_check_lists(call->ice_session); i > md->n_active_streams; i--) { - ice_session_remove_check_list(call->ice_session, ice_session_check_list(call->ice_session, i - 1)); + IceCheckList *removed=ice_session_check_list(call->ice_session, i - 1); + ice_session_remove_check_list(call->ice_session, removed); + if (call->audiostream && call->audiostream->ms.ice_check_list==removed) + call->audiostream->ms.ice_check_list=NULL; + if (call->videostream && call->videostream->ms.ice_check_list==removed) + call->videostream->ms.ice_check_list=NULL; } ice_session_check_mismatch(call->ice_session); } else { diff --git a/coreapi/private.h b/coreapi/private.h index 6f421e95e..9fa89dd3a 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -155,6 +155,11 @@ typedef struct StunCandidate{ }StunCandidate; +typedef struct _PortConfig{ + int rtp_port; + int rtcp_port; +}PortConfig; + struct _LinphoneCall { int magic; /*used to distinguish from proxy config*/ @@ -178,8 +183,8 @@ struct _LinphoneCall LinphoneProxyConfig *dest_proxy; int refcnt; void * user_pointer; - int audio_port; - int video_port; + PortConfig media_ports[2]; + MSMediaStreamSessions sessions[2]; /*the rtp, srtp, zrtp contexts for each stream*/ StunCandidate ac,vc; /*audio video ip/port discovered by STUN*/ struct _AudioStream *audiostream; /**/ struct _VideoStream *videostream; diff --git a/mediastreamer2 b/mediastreamer2 index 7111661bd..da5d1de60 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 7111661bd810352ed7a4ecc9c30c7754d3006a92 +Subproject commit da5d1de606699162f48751f006d9219321069545 diff --git a/oRTP b/oRTP index 393857c0e..5008a70e0 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 393857c0e8e5cab10a8d647cc89c8390355745a7 +Subproject commit 5008a70e077b3706de4a48374f162f93071b4d08 diff --git a/tester/call_tester.c b/tester/call_tester.c index 419def8cc..be60fd8af 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -519,7 +519,7 @@ static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee return success; } -static void call_with_ice(void) { +static void _call_with_ice(bool_t random_ports) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); @@ -527,6 +527,13 @@ static void call_with_ice(void) { linphone_core_set_stun_server(marie->lc,"stun.linphone.org"); linphone_core_set_firewall_policy(pauline->lc,LinphonePolicyUseIce); linphone_core_set_stun_server(pauline->lc,"stun.linphone.org"); + + if (random_ports){ + linphone_core_set_audio_port(marie->lc,-1); + linphone_core_set_video_port(marie->lc,-1); + linphone_core_set_audio_port(pauline->lc,-1); + linphone_core_set_video_port(pauline->lc,-1); + } CU_ASSERT_TRUE(call(pauline,marie)); @@ -536,8 +543,6 @@ static void call_with_ice(void) { CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2)); liblinphone_tester_check_rtcp(marie,pauline); - - /*then close the call*/ linphone_core_terminate_all_calls(pauline->lc); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); @@ -547,6 +552,14 @@ static void call_with_ice(void) { linphone_core_manager_destroy(pauline); } +static void call_with_ice(void){ + _call_with_ice(FALSE); +} + +static void call_with_ice_random_ports(void){ + _call_with_ice(TRUE); +} + static void call_with_custom_headers(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); @@ -718,6 +731,7 @@ static bool_t add_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee) return wait_for(caller->lc,callee->lc,&callee->stat.number_of_IframeDecoded,initial_callee_stat.number_of_IframeDecoded+1); } else return 0; } + static void call_with_video_added(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); @@ -733,7 +747,26 @@ static void call_with_video_added(void) { linphone_core_manager_destroy(pauline); } +static void call_with_video_added_random_ports(void) { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + + linphone_core_set_audio_port(marie->lc,-1); + linphone_core_set_video_port(marie->lc,-1); + linphone_core_set_audio_port(pauline->lc,-1); + linphone_core_set_video_port(pauline->lc,-1); + + CU_ASSERT_TRUE(call(pauline,marie)); + CU_ASSERT_TRUE(add_video(pauline,marie)); + /*just to sleep*/ + linphone_core_terminate_all_calls(pauline->lc); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1)); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} static void call_with_declined_video(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); @@ -808,19 +841,26 @@ static void video_call(void) { } #endif /*VIDEO_ENABLED*/ -static void call_with_media_relay(void) { +static void _call_with_media_relay(bool_t random_ports) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); linphone_core_set_user_agent(marie->lc,"Natted Linphone",NULL); linphone_core_set_user_agent(pauline->lc,"Natted Linphone",NULL); + + if (random_ports){ + linphone_core_set_audio_port(marie->lc,-1); + linphone_core_set_video_port(marie->lc,-1); + linphone_core_set_audio_port(pauline->lc,-1); + linphone_core_set_video_port(pauline->lc,-1); + } + CU_ASSERT_TRUE(call(pauline,marie)); liblinphone_tester_check_rtcp(pauline,marie); - + #ifdef VIDEO_ENABLED CU_ASSERT_TRUE(add_video(pauline,marie)); liblinphone_tester_check_rtcp(pauline,marie); #endif - /*just to sleep*/ linphone_core_terminate_all_calls(pauline->lc); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); @@ -828,7 +868,14 @@ static void call_with_media_relay(void) { linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); +} +static void call_with_media_relay(void) { + _call_with_media_relay(FALSE); +} + +static void call_with_media_relay_random_ports(void) { + _call_with_media_relay(TRUE); } static void call_with_privacy(void) { @@ -1839,6 +1886,7 @@ test_t call_tests[] = { { "Call failed because of codecs", call_failed_because_of_codecs }, { "Simple call", simple_call }, { "Call with media relay", call_with_media_relay}, + { "Call with media relay (random ports)", call_with_media_relay_random_ports}, { "Simple call compatibility mode", simple_call_compatibility_mode }, { "Early-media call", early_media_call }, { "Early-media call with ringing", early_media_call_with_ringing }, @@ -1855,6 +1903,7 @@ test_t call_tests[] = { { "Simple video call",video_call}, { "SRTP ice video call", srtp_video_ice_call }, { "Call with video added", call_with_video_added }, + { "Call with video added (random ports)", call_with_video_added_random_ports }, { "Call with video declined",call_with_declined_video}, #else { "SRTP ice call", srtp_ice_call }, @@ -1872,6 +1921,7 @@ test_t call_tests[] = { { "Unattended call transfer with error", unattended_call_transfer_with_error }, { "Call transfer existing call outgoing call", call_transfer_existing_call_outgoing_call }, { "Call with ICE", call_with_ice }, + { "Call with ICE (random ports)", call_with_ice_random_ports }, { "Call with custom headers",call_with_custom_headers}, { "Call established with rejected INFO",call_established_with_rejected_info}, { "Call established with rejected RE-INVITE",call_established_with_rejected_reinvite}, diff --git a/tester/stun_tester.c b/tester/stun_tester.c index e416fa02c..d19650f06 100644 --- a/tester/stun_tester.c +++ b/tester/stun_tester.c @@ -73,8 +73,8 @@ static void linphone_stun_test_grab_ip() int tmp=0; memset(&dummy_call, 0, sizeof(LinphoneCall)); - dummy_call.audio_port = 7078; - dummy_call.audio_port = 9078; + dummy_call.media_ports[0].rtp_port = 7078; + dummy_call.media_ports[1].rtp_port = 9078; linphone_core_set_stun_server(lc_stun->lc, stun_address); CU_ASSERT_STRING_EQUAL(stun_address, linphone_core_get_stun_server(lc_stun->lc));