From bf20329191979a80a1bec9d54ee2020b4d91e74f Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 12 May 2016 12:17:29 +0200 Subject: [PATCH 1/6] fix LinphoneCore.muteMic() ! --- coreapi/linphonecore_jni.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 084869204..e0b8ef53f 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -1790,7 +1790,7 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_muteMic( JNIEnv* env ,jobject thiz ,jlong lc ,jboolean isMuted) { - linphone_core_enable_mic((LinphoneCore*)lc,isMuted); + linphone_core_enable_mic((LinphoneCore*)lc, !isMuted); } extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_interpretUrl( JNIEnv* env From 7e36a186efdfdfe67e7939f9769654fcd002b35a Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 12 May 2016 13:19:31 +0200 Subject: [PATCH 2/6] Fix daemon command call-mute as well --- daemon/commands/call-mute.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/daemon/commands/call-mute.cc b/daemon/commands/call-mute.cc index c5f79b2b6..918552159 100644 --- a/daemon/commands/call-mute.cc +++ b/daemon/commands/call-mute.cc @@ -29,9 +29,9 @@ void CallMute::exec(Daemon* app, const char* args) } if (sscanf(args, "%i", &muted) == 1) { - linphone_core_enable_mic(lc, (muted != 0)); + linphone_core_enable_mic(lc, !muted); } else { - linphone_core_enable_mic(lc, (muted != 0)); + linphone_core_enable_mic(lc, !muted); } app->sendResponse(Response(muted?"Microphone Muted" From db76eba44bfe4d6d83c618d7d387cef4504083a5 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Thu, 12 May 2016 14:07:28 +0200 Subject: [PATCH 3/6] belle_sip_freeaddrinfo() is now bctbx_freeaddrinfo(). --- coreapi/misc.c | 2 +- coreapi/private.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/coreapi/misc.c b/coreapi/misc.c index 0ab5a04fa..835acb6e9 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -572,7 +572,7 @@ void linphone_core_adapt_to_network(LinphoneCore *lc, int ping_time_ms, Linphone static void stun_server_resolved(LinphoneCore *lc, const char *name, struct addrinfo *addrinfo){ if (lc->net_conf.stun_addrinfo){ - belle_sip_freeaddrinfo(lc->net_conf.stun_addrinfo); + bctbx_freeaddrinfo(lc->net_conf.stun_addrinfo); lc->net_conf.stun_addrinfo=NULL; } if (addrinfo){ diff --git a/coreapi/private.h b/coreapi/private.h index 412e39ed7..935066238 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -37,6 +37,7 @@ #include "ringtoneplayer.h" #include "vcard.h" +#include #include #include From 39a5ed99eb2067368bd4fcc512250e0430300acf Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Thu, 12 May 2016 14:41:24 +0200 Subject: [PATCH 4/6] belle_sip_ip_address_to_addrinfo() is now bctbx_ip_address_to_addrinfo(). --- tester/tester.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tester/tester.c b/tester/tester.c index ec253ba2e..9e4e5bfb1 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -436,7 +436,7 @@ void linphone_core_manager_destroy(LinphoneCoreManager* mgr) { } int liblinphone_tester_ipv6_available(void){ - struct addrinfo *ai=belle_sip_ip_address_to_addrinfo(AF_INET6,"2a01:e00::2",53); + struct addrinfo *ai=bctbx_ip_address_to_addrinfo(AF_INET6,"2a01:e00::2",53); if (ai){ struct sockaddr_storage ss; struct addrinfo src; @@ -446,7 +446,7 @@ int liblinphone_tester_ipv6_available(void){ belle_sip_get_src_addr_for(ai->ai_addr,(socklen_t)ai->ai_addrlen,(struct sockaddr*) &ss,&slen,4444); src.ai_addr=(struct sockaddr*) &ss; src.ai_addrlen=slen; - belle_sip_addrinfo_to_ip(&src,localip, sizeof(localip),&port); + bctbx_addrinfo_to_ip_address(&src,localip, sizeof(localip),&port); freeaddrinfo(ai); return strcmp(localip,"::1")!=0; } From 5de034898db55521547dc89d6fd160225709a203 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Thu, 12 May 2016 21:37:59 +0200 Subject: [PATCH 5/6] update ms2 --- mediastreamer2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediastreamer2 b/mediastreamer2 index 2076bcda9..57f7b9526 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 2076bcda91d98388f475727ea3234505679caa38 +Subproject commit 57f7b95267f1b943f15b7dd00b3ccaeb43fb373f From 62703c016c4a75755ba074eda9e4b7a58d1241cd Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 12 May 2016 23:33:33 +0200 Subject: [PATCH 6/6] robustize IPv6 support for heterogenous cases. Also, the RTP sockets are now always IPv6 when ipv6 is enabled in LinphoneCore, independently of what is finally proposed in SDP, so that these sockets can always send and recv with both versions. This is consistent with what is already done in belle-sip for SIP sockets. --- coreapi/linphonecall.c | 30 +++++++++++--- coreapi/sal.c | 18 ++++++++ include/sal/sal.h | 2 + tester/flexisip_tester.c | 83 +++++++++++++++++++++++++++---------- tester/liblinphone_tester.h | 2 +- tester/tester.c | 7 +--- 6 files changed, 107 insertions(+), 35 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 403a9c7b0..516bc0150 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -625,7 +625,8 @@ static void transfer_already_assigned_payload_types(SalMediaDescription *old, Sa } static const char *linphone_call_get_bind_ip_for_stream(LinphoneCall *call, int stream_index){ - const char *bind_ip = lp_config_get_string(call->core->config,"rtp","bind_address",call->af==AF_INET6 ? "::0" : "0.0.0.0"); + const char *bind_ip = lp_config_get_string(call->core->config,"rtp","bind_address", + linphone_core_ipv6_enabled(call->core) ? "::0" : "0.0.0.0"); if (stream_index<2 && call->media_ports[stream_index].multicast_ip[0]!='\0'){ if (call->dir==LinphoneCallOutgoing){ @@ -1025,7 +1026,7 @@ void linphone_call_create_op(LinphoneCall *call){ } /* - * Choose IP version we are going to use for RTP socket. + * Choose IP version we are going to use for RTP streams IP address advertised in SDP. * The algorithm is as follows: * - if ipv6 is disabled at the core level, it is always AF_INET * - Otherwise, if the destination address for the call is an IPv6 address, use IPv6. @@ -1164,9 +1165,19 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr return call; } -static void linphone_call_incoming_select_ip_version(LinphoneCall *call){ +/*Select IP version to use for advertising local addresses of RTP streams, for an incoming call. + *If the call is received through a know proxy that is IPv6, use IPv6. + *Otherwise check the remote contact address. + *If later the resulting media description tells that we have to send IPv4, it won't be a problem because the RTP sockets + * are dual stack. + */ +static void linphone_call_incoming_select_ip_version(LinphoneCall *call, LinphoneProxyConfig *cfg){ if (linphone_core_ipv6_enabled(call->core)){ - call->af=sal_op_is_ipv6(call->op) ? AF_INET6 : AF_INET; + if (cfg && cfg->op){ + call->af=sal_op_is_ipv6(cfg->op) ? AF_INET6 : AF_INET; + }else{ + call->af=sal_op_is_ipv6(call->op) ? AF_INET6 : AF_INET; + } }else call->af=AF_INET; } @@ -1192,6 +1203,10 @@ void linphone_call_set_compatible_incoming_call_parameters(LinphoneCall *call, S }else if (call->params->media_encryption != LinphoneMediaEncryptionZRTP){ call->params->media_encryption = LinphoneMediaEncryptionNone; } + if (!sal_media_description_has_ipv6(md)){ + ms_message("The remote SDP doesn't seem to offer any IPv6 connectivity, so disabling IPv6 for this call."); + call->af = AF_INET; + } linphone_call_fix_call_parameters(call, md); } @@ -1305,7 +1320,11 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro call->op=op; call->core=lc; - linphone_call_incoming_select_ip_version(call); + call->dest_proxy = linphone_core_lookup_known_proxy(call->core, to); + linphone_call_incoming_select_ip_version(call, call->dest_proxy); + /*note that the choice of IP version for streams is later refined by + * linphone_call_set_compatible_incoming_call_parameters() when examining the remote offer, if any. + * If the remote offer contains IPv4 addresses, we should propose IPv4 as well*/ sal_op_cnx_ip_to_0000_if_sendonly_enable(op,lp_config_get_default_int(lc->config,"sip","cnx_ip_to_0000_if_sendonly_enabled",0)); @@ -1336,7 +1355,6 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro call->params = linphone_call_params_new(); linphone_call_init_common(call, from, to); call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/ - call->dest_proxy = linphone_core_lookup_known_proxy(call->core, to); linphone_core_init_default_params(lc, call->params); /* diff --git a/coreapi/sal.c b/coreapi/sal.c index 6a53b61d7..0f43d1a1d 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -220,6 +220,10 @@ bool_t sal_stream_description_has_avpf(const SalStreamDescription *sd) { return FALSE; } +bool_t sal_stream_description_has_ipv6(const SalStreamDescription *sd){ + return strchr(sd->rtp_addr,':') != NULL; +} + bool_t sal_stream_description_has_implicit_avpf(const SalStreamDescription *sd){ return sd->implicit_rtcp_fb; } @@ -309,6 +313,20 @@ bool_t sal_media_description_has_zrtp(const SalMediaDescription *md) { return TRUE; } +bool_t sal_media_description_has_ipv6(const SalMediaDescription *md){ + int i; + if (md->nb_streams == 0) return FALSE; + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + if (!sal_stream_description_active(&md->streams[i])) continue; + if (md->streams[i].rtp_addr[0] != '\0'){ + if (!sal_stream_description_has_ipv6(&md->streams[i])) return FALSE; + }else{ + if (strchr(md->addr,':') == NULL) return FALSE; + } + } + return TRUE; +} + /* static bool_t fmtp_equals(const char *p1, const char *p2){ if (p1 && p2 && strcmp(p1,p2)==0) return TRUE; diff --git a/include/sal/sal.h b/include/sal/sal.h index 9b3b979cf..057c9d1b5 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -326,11 +326,13 @@ bool_t sal_stream_description_has_avpf(const SalStreamDescription *sd); bool_t sal_stream_description_has_implicit_avpf(const SalStreamDescription *sd); bool_t sal_stream_description_has_srtp(const SalStreamDescription *sd); bool_t sal_stream_description_has_dtls(const SalStreamDescription *sd); +bool_t sal_stream_description_has_ipv6(const SalStreamDescription *md); bool_t sal_media_description_has_avpf(const SalMediaDescription *md); bool_t sal_media_description_has_implicit_avpf(const SalMediaDescription *md); bool_t sal_media_description_has_srtp(const SalMediaDescription *md); bool_t sal_media_description_has_dtls(const SalMediaDescription *md); bool_t sal_media_description_has_zrtp(const SalMediaDescription *md); +bool_t sal_media_description_has_ipv6(const SalMediaDescription *md); int sal_media_description_get_nb_active_streams(const SalMediaDescription *md); struct SalOpBase; diff --git a/tester/flexisip_tester.c b/tester/flexisip_tester.c index 944cec912..2a9dea118 100644 --- a/tester/flexisip_tester.c +++ b/tester/flexisip_tester.c @@ -683,10 +683,34 @@ static void call_with_sips_not_achievable(void){ } } -static void call_with_ipv6(void) { + + +static bool_t is_sending_ipv6(RtpSession *session, bool_t rtcp){ + const struct sockaddr *dest = rtcp ? (struct sockaddr*)&session->rtcp.gs.rem_addr : (struct sockaddr*)&session->rtp.gs.rem_addr; + struct sockaddr_in6 *in6=(struct sockaddr_in6*)dest; + return dest->sa_family == AF_INET6 && !IN6_IS_ADDR_V4MAPPED(&in6->sin6_addr); +} +static bool_t is_remote_contact_ipv6(LinphoneCall *call){ + const char *contact=linphone_call_get_remote_contact(call); + LinphoneAddress *ct_addr; + bool_t ret = FALSE; + + BC_ASSERT_PTR_NOT_NULL(contact); + if (contact){ + ct_addr=linphone_address_new(contact); + BC_ASSERT_PTR_NOT_NULL(ct_addr); + if (ct_addr){ + ret = strchr(linphone_address_get_domain(ct_addr),':') != NULL; + } + linphone_address_destroy(ct_addr); + } + return ret; +} + +static void _call_with_ipv6(bool_t caller_with_ipv6, bool_t callee_with_ipv6) { LinphoneCoreManager* marie; LinphoneCoreManager* pauline; - LinphoneCall *pauline_call; + LinphoneCall *pauline_call, *marie_call; /*calling ortp_init() here is done to have WSAStartup() done, otherwise liblinphone_tester_ipv6_available() will not work.*/ ortp_init(); @@ -696,41 +720,54 @@ static void call_with_ipv6(void) { return; } - liblinphone_tester_enable_ipv6(TRUE); - marie = linphone_core_manager_new( "marie_rc"); - pauline = linphone_core_manager_new( transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + marie = linphone_core_manager_new2( "marie_rc", FALSE); + linphone_core_enable_ipv6(marie->lc, caller_with_ipv6); + linphone_core_manager_start(marie, TRUE); + + pauline = linphone_core_manager_new2( transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc", FALSE); + linphone_core_enable_ipv6(pauline->lc, callee_with_ipv6); + linphone_core_manager_start(pauline, TRUE); linphone_core_set_user_agent(marie->lc,"Natted Linphone",NULL); linphone_core_set_user_agent(pauline->lc,"Natted Linphone",NULL); BC_ASSERT_TRUE(call(marie,pauline)); - pauline_call=linphone_core_get_current_call(pauline->lc); + pauline_call = linphone_core_get_current_call(pauline->lc); + marie_call = linphone_core_get_current_call(marie->lc); BC_ASSERT_PTR_NOT_NULL(pauline_call); - if (pauline_call){ + BC_ASSERT_PTR_NOT_NULL(marie_call); + if (pauline_call && marie_call){ /*check that the remote contact is IPv6*/ - const char *contact=linphone_call_get_remote_contact(pauline_call); - LinphoneAddress *ct_addr; - - BC_ASSERT_PTR_NOT_NULL(contact); - if (contact){ - ct_addr=linphone_address_new(contact); - BC_ASSERT_PTR_NOT_NULL(ct_addr); - if (ct_addr){ - BC_ASSERT_PTR_NOT_NULL(strchr(linphone_address_get_domain(ct_addr),':')); - } - linphone_address_destroy(ct_addr); - } - + BC_ASSERT_EQUAL(is_remote_contact_ipv6(pauline_call), caller_with_ipv6, int, "%i"); + BC_ASSERT_EQUAL(is_remote_contact_ipv6(marie_call), callee_with_ipv6, int, "%i"); + + /*check that the RTP destinations are IPv6 (flexisip should propose an IPv6 relay for parties with IPv6)*/ + BC_ASSERT_EQUAL(is_sending_ipv6(marie_call->sessions[0].rtp_session, FALSE), caller_with_ipv6, int, "%i"); + BC_ASSERT_EQUAL(is_sending_ipv6(marie_call->sessions[0].rtp_session, TRUE), caller_with_ipv6, int, "%i"); + BC_ASSERT_EQUAL(is_sending_ipv6(pauline_call->sessions[0].rtp_session, FALSE), callee_with_ipv6, int, "%i"); + BC_ASSERT_EQUAL(is_sending_ipv6(pauline_call->sessions[0].rtp_session, TRUE), callee_with_ipv6, int, "%i"); + } liblinphone_tester_check_rtcp(marie,pauline); end_call(marie,pauline); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); - liblinphone_tester_enable_ipv6(FALSE); ortp_exit(); } +static void call_with_ipv6(void){ + _call_with_ipv6(TRUE, TRUE); +} + +static void call_ipv4_to_ipv6(void){ + _call_with_ipv6(FALSE, TRUE); +} + +static void call_ipv6_to_ipv4(void){ + _call_with_ipv6(TRUE, FALSE); +} + static void file_transfer_message_rcs_to_external_body_client(void) { if (transport_supported(LinphoneTransportTls)) { LinphoneChatRoom* chat_room; @@ -1143,7 +1180,9 @@ test_t flexisip_tests[] = { TEST_NO_TAG("Early-media call forking", early_media_call_forking), TEST_NO_TAG("Call with sips", call_with_sips), TEST_ONE_TAG("Call with sips not achievable", call_with_sips_not_achievable, "LeaksMemory"), - TEST_NO_TAG("Call with ipv6", call_with_ipv6), + TEST_NO_TAG("Call ipv6 to ipv6", call_with_ipv6), + TEST_NO_TAG("Call ipv6 to ipv4", call_ipv6_to_ipv4), + TEST_NO_TAG("Call ipv4 to ipv6", call_ipv4_to_ipv6), TEST_ONE_TAG("Subscribe Notify with sipp publisher", test_subscribe_notify_with_sipp_publisher, "LeaksMemory"), /*TEST_ONE_TAG("Subscribe Notify with sipp double publish", test_subscribe_notify_with_sipp_publisher_double_publish, "LeaksMemory"),*/ TEST_NO_TAG("Publish/unpublish", test_publish_unpublish), diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index eb1d21561..9718e3b1b 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -339,7 +339,7 @@ bool_t liblinphone_tester_clock_elapsed(const MSTimeSpec *start, int value_ms); void linphone_core_manager_check_accounts(LinphoneCoreManager *m); void account_manager_destroy(void); LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char* path, const char* file, void* user_data); -void liblinphone_tester_enable_ipv6(bool_t enabled); + void linphone_call_iframe_decoded_cb(LinphoneCall *call,void * user_data); void call_paused_resumed_base(bool_t multicast,bool_t with_losses); void simple_call_base(bool_t enable_multicast_recv_side); diff --git a/tester/tester.c b/tester/tester.c index 9e4e5bfb1..4ddd07cd6 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -39,7 +39,7 @@ #define unlink _unlink #endif -static bool_t liblinphone_tester_ipv6_enabled=FALSE; + static int liblinphone_tester_keep_accounts_flag = 0; static int liblinphone_tester_keep_record_files = FALSE; static int liblinphone_tester_leak_detector_disabled = FALSE; @@ -77,9 +77,6 @@ bool_t liblinphone_tester_clock_elapsed(const MSTimeSpec *start, int value_ms){ return FALSE; } -void liblinphone_tester_enable_ipv6(bool_t enabled){ - liblinphone_tester_ipv6_enabled=enabled; -} LinphoneAddress * create_linphone_address(const char * domain) { LinphoneAddress *addr = linphone_address_new(NULL); @@ -156,8 +153,6 @@ LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char* path, c sal_set_dns_user_hosts_file(lc->sal, dnsuserhostspath); linphone_core_set_static_picture(lc,nowebcampath); - linphone_core_enable_ipv6(lc, liblinphone_tester_ipv6_enabled); - ms_free(ringpath); ms_free(ringbackpath); ms_free(nowebcampath);