From 9551c9118a660453a3d01f2ffee8ae8750be66be Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 1 Feb 2017 11:14:37 +0100 Subject: [PATCH] Improvements on tunnel to make udp mirror and dual mode cohabitate + JNI wrapper --- coreapi/TunnelManager.cc | 9 +++ coreapi/TunnelManager.hh | 12 ++++ coreapi/linphone_tunnel.cc | 39 +++++++++--- coreapi/linphonecore_jni.cc | 62 +++++++++++++++++++ .../org/linphone/core/LinphoneCore.java | 12 ++++ .../org/linphone/core/TunnelConfig.java | 21 +++++++ .../org/linphone/core/LinphoneCoreImpl.java | 12 ++++ .../org/linphone/core/TunnelConfigImpl.java | 20 ++++++ 8 files changed, 177 insertions(+), 10 deletions(-) diff --git a/coreapi/TunnelManager.cc b/coreapi/TunnelManager.cc index 8640563a0..ede8ca7e7 100644 --- a/coreapi/TunnelManager.cc +++ b/coreapi/TunnelManager.cc @@ -52,6 +52,15 @@ void TunnelManager::addServer(const char *ip, int port) { } } +void TunnelManager::addServerPair(const char *ip1, int port1, const char *ip2, int port2, unsigned int udpMirrorPort, unsigned int delay) { + if (ip1 == NULL || ip2 == NULL) { + ms_warning("Adding tunnel server with empty ip, it will not work!"); + return; + } + addServerPair(ip1, port1, ip2, port2); + mUdpMirrorClients.push_back(UdpMirrorClient(ServerAddr(ip1, udpMirrorPort), delay)); +} + void TunnelManager::addServerPair(const char *ip1, int port1, const char *ip2, int port2) { if (ip1 == NULL || ip2 == NULL) { ms_warning("Adding tunnel server with empty ip, it will not work!"); diff --git a/coreapi/TunnelManager.hh b/coreapi/TunnelManager.hh index 45ed3be3a..d51ccf73c 100644 --- a/coreapi/TunnelManager.hh +++ b/coreapi/TunnelManager.hh @@ -63,6 +63,18 @@ namespace belledonnecomm { * @param delay udp packet round trip delay in ms considered as acceptable. recommended value is 1000 ms. */ void addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay); + /** + * Add a tunnel server couple. At least one should be provided to be able to connect. + * This is used when using the dual socket mode where one client will connect to one ip and the other client to the other ip. + * + * @param ip1 server ip address n°1 + * @param port1 tunnel server tls port, recommended value is 443 + * @param ip2 server ip address n°2 + * @param port2 tunnel server tls port, recommended value is 443 + * @param udpMirrorPort remote port on the tunnel server 1 side used to test udp reachability + * @param delay udp packet round trip delay in ms considered as acceptable. recommended value is 1000 ms. + */ + void addServerPair(const char *ip1, int port1, const char *ip2, int port2, unsigned int udpMirrorPort, unsigned int delay); /** * Add a tunnel server couple. At least one should be provided to be able to connect. * This is used when using the dual socket mode where one client will connect to one ip and the other client to the other ip. diff --git a/coreapi/linphone_tunnel.cc b/coreapi/linphone_tunnel.cc index 448ba87d2..8bae4965b 100644 --- a/coreapi/linphone_tunnel.cc +++ b/coreapi/linphone_tunnel.cc @@ -66,11 +66,21 @@ static char *linphone_tunnel_config_to_string(const LinphoneTunnelConfig *tunnel const char *host2 = linphone_tunnel_config_get_host2(tunnel_config); if(host != NULL) { if(linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) != -1) { - str = ms_strdup_printf("%s:%d:%d:%d", - linphone_tunnel_config_get_host(tunnel_config), - linphone_tunnel_config_get_port(tunnel_config), - linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config), - linphone_tunnel_config_get_delay(tunnel_config)); + if (host2 != NULL) { + str = ms_strdup_printf("%s:%d:%d:%d/%s:%d", + linphone_tunnel_config_get_host(tunnel_config), + linphone_tunnel_config_get_port(tunnel_config), + linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config), + linphone_tunnel_config_get_delay(tunnel_config), + linphone_tunnel_config_get_host2(tunnel_config), + linphone_tunnel_config_get_port2(tunnel_config)); + } else { + str = ms_strdup_printf("%s:%d:%d:%d", + linphone_tunnel_config_get_host(tunnel_config), + linphone_tunnel_config_get_port(tunnel_config), + linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config), + linphone_tunnel_config_get_delay(tunnel_config)); + } } else if (host2 != NULL) { str = ms_strdup_printf("%s:%d/%s:%d", linphone_tunnel_config_get_host(tunnel_config), @@ -198,11 +208,20 @@ static void linphone_tunnel_save_config(const LinphoneTunnel *tunnel) { static void linphone_tunnel_add_server_intern(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config) { - if(linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) != -1) { - bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config), - linphone_tunnel_config_get_port(tunnel_config), - linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config), - linphone_tunnel_config_get_delay(tunnel_config)); + if (linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) != -1) { + if (linphone_tunnel_config_get_host2(tunnel_config) != NULL) { + bcTunnel(tunnel)->addServerPair(linphone_tunnel_config_get_host(tunnel_config), + linphone_tunnel_config_get_port(tunnel_config), + linphone_tunnel_config_get_host2(tunnel_config), + linphone_tunnel_config_get_port2(tunnel_config), + linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config), + linphone_tunnel_config_get_delay(tunnel_config)); + } else { + bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config), + linphone_tunnel_config_get_port(tunnel_config), + linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config), + linphone_tunnel_config_get_delay(tunnel_config)); + } } else if (linphone_tunnel_config_get_host2(tunnel_config) != NULL) { bcTunnel(tunnel)->addServerPair(linphone_tunnel_config_get_host(tunnel_config), linphone_tunnel_config_get_port(tunnel_config), diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 33d76dec6..b6fe8961f 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -5607,6 +5607,22 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_tunnelSipEnabled(JNI } } +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelEnableDualMode(JNIEnv *env, jobject thiz, jlong pCore, jboolean enable) { + LinphoneTunnel *tunnel = ((LinphoneCore *)pCore)->tunnel; + if(tunnel != NULL) { + linphone_tunnel_enable_dual_mode(tunnel, (bool_t)enable); + } +} + +extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_tunnelDualModeEnabled(JNIEnv *env, jobject thiz, jlong pCore) { + LinphoneTunnel *tunnel = ((LinphoneCore *)pCore)->tunnel; + if(tunnel != NULL) { + return (jboolean)linphone_tunnel_dual_mode_enabled(tunnel); + } else { + return JNI_FALSE; + } +} + extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setUserAgent(JNIEnv *env,jobject thiz,jlong pCore, jstring name, jstring version){ const char* cname = GetStringUTFChars(env, name); const char* cversion = GetStringUTFChars(env, version); @@ -7622,6 +7638,52 @@ JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_setPort(JNIEnv *e linphone_tunnel_config_set_port(cfg, port); } +/* + * Class: org_linphone_core_TunnelConfigImpl + * Method: getHost + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_linphone_core_TunnelConfigImpl_getHost2(JNIEnv *env, jobject obj, jlong ptr){ + LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; + const char *host = linphone_tunnel_config_get_host2(cfg); + if (host){ + return env->NewStringUTF(host); + } + return NULL; +} + +/* + * Class: org_linphone_core_TunnelConfigImpl + * Method: setHost + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_setHost2(JNIEnv *env, jobject obj, jlong ptr, jstring jstr){ + LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; + const char* host = GetStringUTFChars(env, jstr); + linphone_tunnel_config_set_host2(cfg, host); + ReleaseStringUTFChars(env, jstr, host); +} + +/* + * Class: org_linphone_core_TunnelConfigImpl + * Method: getPort + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_linphone_core_TunnelConfigImpl_getPort2(JNIEnv *env, jobject jobj, jlong ptr){ + LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; + return linphone_tunnel_config_get_port2(cfg); +} + +/* + * Class: org_linphone_core_TunnelConfigImpl + * Method: setPort + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_setPort2(JNIEnv *env, jobject jobj, jlong ptr, jint port){ + LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; + linphone_tunnel_config_set_port2(cfg, port); +} + /* * Class: org_linphone_core_TunnelConfigImpl * Method: getRemoteUdpMirrorPort diff --git a/java/common/org/linphone/core/LinphoneCore.java b/java/common/org/linphone/core/LinphoneCore.java index d6c89dc11..43da962cc 100644 --- a/java/common/org/linphone/core/LinphoneCore.java +++ b/java/common/org/linphone/core/LinphoneCore.java @@ -1744,6 +1744,18 @@ public interface LinphoneCore { */ boolean tunnelSipEnabled(); + /** + * Set whether to use two tunnel client to connect to the same tunnel server but on two different IPs + * @param enable If true, two tunnel clients will be created + */ + void tunnelEnableDualMode(boolean enable); + + /** + * Check whether dual tunnel client mode is enabled + * @return true means two tunnel clients will be created + */ + boolean tunnelDualModeEnabled(); + /** * @deprecated Use tunnelSetMode instaead * Enable tunnel if the mirror RTP session cannot be established diff --git a/java/common/org/linphone/core/TunnelConfig.java b/java/common/org/linphone/core/TunnelConfig.java index a7eb28c3f..56695af8b 100644 --- a/java/common/org/linphone/core/TunnelConfig.java +++ b/java/common/org/linphone/core/TunnelConfig.java @@ -27,6 +27,27 @@ public interface TunnelConfig { * @param port */ void setPort(int port); + /** + * Get the hostname of the second tunnel server + * @return + */ + String getHost2(); + /** + * Set the hostname (or ip address) of the second tunnel server. + * @param host + */ + void setHost2(String host); + /** + * Get the port where to connect to the second tunnel server. + * @return + */ + int getPort2(); + /** + * Set the port where to connect to the second tunnel server. + * When not set, the default value is used (443). + * @param port + */ + void setPort2(int port); /** * Get the remote udp mirror port, which is used to check udp connectivity of the network. * @return diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java index e71cb4119..4220601f4 100644 --- a/java/impl/org/linphone/core/LinphoneCoreImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java @@ -961,6 +961,18 @@ class LinphoneCoreImpl implements LinphoneCore { return tunnelSipEnabled(nativePtr); } + private native void tunnelEnableDualMode(long nativePtr, boolean enable); + @Override + public void tunnelEnableDualMode(boolean enable) { + tunnelEnableDualMode(nativePtr, enable); + } + + private native boolean tunnelDualModeEnabled(long nativePtr); + @Override + public boolean tunnelDualModeEnabled() { + return tunnelDualModeEnabled(nativePtr); + } + @Override public native boolean isTunnelAvailable(); diff --git a/java/impl/org/linphone/core/TunnelConfigImpl.java b/java/impl/org/linphone/core/TunnelConfigImpl.java index d7fd0c873..8c0cbf575 100644 --- a/java/impl/org/linphone/core/TunnelConfigImpl.java +++ b/java/impl/org/linphone/core/TunnelConfigImpl.java @@ -25,6 +25,26 @@ public class TunnelConfigImpl implements TunnelConfig{ public void setPort(int port) { setPort(mNativePtr, port); } + private native String getHost2(long nativePtr); + @Override + public String getHost2() { + return getHost2(mNativePtr); + } + private native void setHost2(long nativePtr, String host); + @Override + public void setHost2(String host) { + setHost2(mNativePtr, host); + } + private native int getPort2(long nativePtr); + @Override + public int getPort2() { + return getPort2(mNativePtr); + } + private native void setPort2(long nativePtr, int port); + @Override + public void setPort2(int port) { + setPort2(mNativePtr, port); + } private native int getRemoteUdpMirrorPort(long nativePtr); @Override public int getRemoteUdpMirrorPort() {