From 886d80bb6d8ac916d6cc0cf635ce25e82ff1f051 Mon Sep 17 00:00:00 2001 From: Guillaume Beraudo Date: Thu, 15 Dec 2011 16:31:55 +0100 Subject: [PATCH] Tunnel manager. --- .gitignore | 11 + build/android/Android.mk | 13 +- configure.ac | 29 ++ coreapi/Makefile.am | 22 +- coreapi/TunnelManager.cc | 435 ++++++++++++++++++ coreapi/TunnelManager.hh | 171 +++++++ coreapi/linphone_tunnel_manager.cc | 126 +++++ coreapi/linphone_tunnel_manager.h | 85 ++++ coreapi/linphonecall.c | 18 +- coreapi/linphonecore.c | 52 ++- coreapi/linphonecore.h | 25 +- coreapi/linphonecore_jni.cc | 46 ++ coreapi/private.h | 16 +- gtk/Makefile.am | 4 +- gtk/parameters.ui | 413 +++-------------- gtk/propertybox.c | 84 ++++ gtk/tunnel_config.ui | 202 ++++++++ .../org/linphone/core/LinphoneCore.java | 14 +- oRTP | 2 +- 19 files changed, 1399 insertions(+), 369 deletions(-) create mode 100644 coreapi/TunnelManager.cc create mode 100644 coreapi/TunnelManager.hh create mode 100644 coreapi/linphone_tunnel_manager.cc create mode 100644 coreapi/linphone_tunnel_manager.h create mode 100644 gtk/tunnel_config.ui diff --git a/.gitignore b/.gitignore index a89057829..df1c80316 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,15 @@ Specfile .anjuta_sym_db.db gtk-glade/version_date.h share/linphone.desktop +Debug/ +build/macos/Info-linphone.plist +coreapi/help/Doxyfile +coreapi/help/buddy_status +coreapi/help/chatroom +coreapi/help/doc/ +coreapi/help/helloworld +coreapi/help/registration +coreapi/test_ecc +coreapi/test_lsd +gtk/version_date.h diff --git a/build/android/Android.mk b/build/android/Android.mk index 096f94464..944f23611 100755 --- a/build/android/Android.mk +++ b/build/android/Android.mk @@ -66,7 +66,6 @@ LOCAL_CFLAGS += \ LOCAL_CFLAGS += -DIN_LINPHONE - ifeq ($(LINPHONE_VIDEO),1) LOCAL_CFLAGS += -DVIDEO_ENABLED ifeq ($(BUILD_X264),1) @@ -94,6 +93,18 @@ LOCAL_STATIC_LIBRARIES := \ libosip2 \ libgsm +ifeq ($(BUILD_TUNNEL),1) +LOCAL_CFLAGS +=-DTUNNEL_ENABLED +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../tunnel/include +LOCAL_SRC_FILES += linphone_tunnel_manager.cc TunnelManager.cc +ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) +LOCAL_SHARED_LIBRARIES += libtunnelclient +else +LOCAL_STATIC_LIBRARIES += libtunnelclient +endif +endif + + ifneq ($(BUILD_AMR),0) LOCAL_CFLAGS += -DHAVE_AMR diff --git a/configure.ac b/configure.ac index 568f46b73..2f206354b 100644 --- a/configure.ac +++ b/configure.ac @@ -37,6 +37,7 @@ AC_CONFIG_MACRO_DIR([m4]) AC_SUBST([mkdir_p]) AC_ISC_POSIX AC_PROG_CC +AC_PROG_CXX AC_C_INLINE AM_PROG_CC_STDC AC_HEADER_STDC @@ -460,6 +461,32 @@ AC_SUBST(MEDIASTREAMER_LIBS) AC_SUBST([MS2_VERSION]) AC_SUBST([MS2_DIR]) + + +AC_ARG_ENABLE(tunnel, + [ --enable-tunnel=[yes/no] Turn on compilation of tunnel support [default=no]], + [case "${enableval}" in + yes) enable_tunnel=true ;; + no) enable_tunnel=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-tunnel) ;; + esac],[enable_tunnel=false]) +AM_CONDITIONAL(BUILD_TUNNEL, test x$enable_tunnel = xtrue) +if test x$enable_tunnel = xtrue; then + PKG_CHECK_MODULES(TUNNEL, tunnel >= 0.3.1) + TUNNEL_CFLAGS+="-DTUNNEL_ENABLED" + AC_SUBST(TUNNEL_CFLAGS) + AC_SUBST(TUNNEL_LIBS) +fi + + + + + + + + + + dnl check for db2html (docbook) to generate html user manual AC_CHECK_PROG(have_sgmltools,sgmltools, yes, no) AM_CONDITIONAL(ENABLE_MANUAL, test x$have_sgmltools$build_manual = xyesyes ) @@ -517,6 +544,8 @@ AC_ARG_ENABLE(tests_enabled, esac],[tests_enabled=false]) AM_CONDITIONAL(ENABLE_TESTS, test x$tests_enabled = xyes) + + dnl ################################################## dnl # Check for doxygen dnl ################################################## diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index 316b6f036..301c05976 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -10,7 +10,8 @@ linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonecore_utils.h .. INCLUDES = \ -I$(top_srcdir)\ - $(MEDIASTREAMER_CFLAGS) + $(MEDIASTREAMER_CFLAGS)\ + $(TUNNEL_CFLAGS) lib_LTLIBRARIES=liblinphone.la @@ -37,7 +38,13 @@ liblinphone_la_SOURCES=\ siplogin.c \ lsd.c linphonecore_utils.h \ ec-calibrator.c \ - conference.c + conference.c \ + linphone_tunnel_manager.h + +if BUILD_TUNNEL +liblinphone_la_SOURCES+=TunnelManager.cc TunnelManager.hh linphone_tunnel_manager.c +endif + liblinphone_la_LDFLAGS= -version-info $(LIBLINPHONE_SO_VERSION) -no-undefined @@ -45,7 +52,8 @@ liblinphone_la_LDFLAGS= -version-info $(LIBLINPHONE_SO_VERSION) -no-undefined liblinphone_la_LIBADD= \ $(EXOSIP_LIBS) \ $(MEDIASTREAMER_LIBS) \ - $(ORTP_LIBS) $(OPENSSL_LIBS) + $(ORTP_LIBS) $(OPENSSL_LIBS) \ + $(TUNNEL_LIBS) if BUILD_WIN32 liblinphone_la_LIBADD+=$(top_builddir)/oRTP/src/libortp.la @@ -70,6 +78,8 @@ AM_CFLAGS=$(STRICT_OPTIONS) -DIN_LINPHONE \ $(EXOSIP_CFLAGS) \ -DENABLE_TRACE \ -DLOG_DOMAIN=\"LinphoneCore\" \ - $(IPV6_CFLAGS) \ - -DORTP_INET6 \ - $(VIDEO_CFLAGS) + $(IPV6_CFLAGS) \ + -DORTP_INET6 \ + $(VIDEO_CFLAGS) \ + $(TUNNEL_CFLAGS) + diff --git a/coreapi/TunnelManager.cc b/coreapi/TunnelManager.cc new file mode 100644 index 000000000..f1fa17bf7 --- /dev/null +++ b/coreapi/TunnelManager.cc @@ -0,0 +1,435 @@ +/* + * C Implementation: tunnel + * + * Description: + * + * + * Author: Simon Morlat , (C) 2009 + * + * Copyright (C) 2010 Belledonne Comunications, Grenoble, France + * + */ + + +#include "TunnelManager.hh" + +#include "ortp/rtpsession.h" +#include "linphonecore.h" +#include "linphonecore_utils.h" +#include "eXosip2/eXosip_transport_hook.h" +#include "tunnel/udp_mirror.hh" + +#ifdef ANDROID +#include +#endif + +#ifdef recvfrom +#undef recvfrom +#endif +#ifdef sendto +#undef sendto +#endif +#ifdef select +#undef select +#endif + +using namespace belledonnecomm; + +Mutex TunnelManager::sMutex; + +int TunnelManager::eXosipSendto(int fd,const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen,void* userdata){ + TunnelManager* lTunnelMgr=(TunnelManager*)userdata; + int err; + sMutex.lock(); + if (lTunnelMgr->mSipSocket==NULL){ + sMutex.unlock(); + return len;//let ignore the error + } + err=lTunnelMgr->mSipSocket->sendto(buf,len,to,tolen); + sMutex.unlock(); + return err; +} + +int TunnelManager::eXosipRecvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen,void* userdata){ + TunnelManager* lTunnelMgr=(TunnelManager*)userdata; + int err; + sMutex.lock(); + if (lTunnelMgr->mSipSocket==NULL){ + sMutex.unlock(); + return 0;//let ignore the error + } + err=lTunnelMgr->mSipSocket->recvfrom(buf,len,from,*fromlen); + sMutex.unlock(); + return err; +} + +int TunnelManager::eXosipSelect(int max_fds, fd_set *s1, fd_set *s2, fd_set *s3, struct timeval *tv,void* userdata){ + struct timeval begin,cur; + TunnelManager* lTunnelMgr=(TunnelManager*)userdata; + if (tv!=0 && tv->tv_sec){ + /*this is the select from udp.c, the one that is interesting to us*/ + unsigned int i; + fd_set tmp; + int udp_fd=eXosip_get_udp_socket(); + int controlfd=-1; + + /* + Find the udp fd and the control fd + */ + for(i=0;imSipSocket!=NULL){ + if (lTunnelMgr->mSipSocket->hasData()) { + sMutex.unlock(); + /* we make exosip believe that it has udp data to read*/ + FD_SET(udp_fd,s1); + return 1; + } + } + sMutex.unlock(); + gettimeofday(&cur,NULL); + if (cur.tv_sec-begin.tv_sec>tv->tv_sec) { + FD_SET(controlfd,s1); + FD_SET(udp_fd,s1); + return 0; + } + FD_ZERO(s1); + FD_SET(controlfd,s1); + if (select(max_fds,s1,s2,s3,&abit)==1) { + return 1; + } + }while(1); + + }else{ + /*select called from other places, only the control fd is present */ + return select(max_fds,s1,s2,s3,tv); + } +} + + +void TunnelManager::addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay) { + addServer(ip,port); + mUdpMirrorClients.push_back(UdpMirrorClient(ServerAddr(ip,udpMirrorPort),delay)); +} + +void TunnelManager::addServer(const char *ip, int port) { + mServerAddrs.push_back(ServerAddr(ip,port)); + if (mTunnelClient) mTunnelClient->addServer(ip,port); +} + +void TunnelManager::cleanServers() { + mServerAddrs.clear(); + + UdpMirrorClientList::iterator it; + mAutoDetectStarted=false; + for (it = mUdpMirrorClients.begin(); it != mUdpMirrorClients.end();) { + UdpMirrorClient& s=*it++; + s.stop(); + } + mUdpMirrorClients.clear(); + if (mTunnelClient) mTunnelClient->cleanServers(); +} + +void TunnelManager::reconnect(){ + if (mTunnelClient) + mTunnelClient->reconnect(); +} + +void TunnelManager::setCallback(StateCallback cb, void *userdata) { + mCallback=cb; + mCallbackData=userdata; +} + +static void sCloseRtpTransport(void *userData, RtpTransport *t){ + ((TunnelManager::TunnelManager *) userData)->closeRtpTransport(t); +} +void TunnelManager::closeRtpTransport(RtpTransport *t){ + TunnelSocket *socket=(TunnelSocket *) t->data; + mTransports.remove(t); + mTunnelClient->closeSocket(socket); + ms_free(t); +} + +static RtpTransport *sCreateRtpTransport(void* userData, int port){ + return ((TunnelManager::TunnelManager *) userData)->createRtpTransport(port); +} + +RtpTransport *TunnelManager::createRtpTransport(int port){ + RtpTransport *t=ms_new0(RtpTransport,1); + t->data=mTunnelClient->createSocket(port); + t->t_getsocket=NULL; + t->t_recvfrom=customRecvfrom; + t->t_sendto=customSendto; + t->close_fn=sCloseRtpTransport; + t->close_data=this; + mTransports.push_back(t); + return t; +} + +void TunnelManager::start() { + if (!mTunnelClient) { + mTunnelClient = new TunnelClient(); + mTunnelClient->setCallback((StateCallback)tunnelCallback,this); + std::list::iterator it; + for(it=mServerAddrs.begin();it!=mServerAddrs.end();++it){ + const ServerAddr &addr=*it; + mTunnelClient->addServer(addr.mAddr.c_str(), addr.mPort); + } + } + mTunnelClient->start(); + + if (mSipSocket == NULL) mSipSocket =mTunnelClient->createSocket(5060); +} + +bool TunnelManager::isStarted() { + return mTunnelClient != 0 && mTunnelClient->isStarted(); +} + +bool TunnelManager::isReady() const { + return mTunnelClient && mTunnelClient->isReady(); +} + +int TunnelManager::customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen){ + int size; + msgpullup(msg,-1); + size=msgdsize(msg); + ((TunnelSocket*)t->data)->sendto(msg->b_rptr,size,to,tolen); + return size; +} + +int TunnelManager::customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen){ + int err=((TunnelSocket*)t->data)->recvfrom(msg->b_wptr,msg->b_datap->db_lim-msg->b_datap->db_base,from,*fromlen); + if (err>0) return err; + return 0; +} + + +TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController() +,mCore(lc) +,mEnabled(false) +,mSipSocket(NULL) +,mCallback(NULL) +,mTunnelClient(NULL) +,mAutoDetectStarted(false) { + + mExosipTransport.data=this; + mExosipTransport.recvfrom=eXosipRecvfrom; + mExosipTransport.sendto=eXosipSendto; + mExosipTransport.select=eXosipSelect; + mStateChanged=false; + linphone_core_add_iterate_hook(mCore,(LinphoneCoreIterateHook)sOnIterate,this); + mTransportFactories.audio_rtcp_func=sCreateRtpTransport; + mTransportFactories.audio_rtcp_func_data=this; + mTransportFactories.audio_rtp_func=sCreateRtpTransport; + mTransportFactories.audio_rtp_func_data=this; + mTransportFactories.video_rtcp_func=sCreateRtpTransport; + mTransportFactories.video_rtcp_func_data=this; + mTransportFactories.video_rtp_func=sCreateRtpTransport; + mTransportFactories.video_rtp_func_data=this; +} + +TunnelManager::~TunnelManager(){ + stopClient(); +} + +void TunnelManager::stopClient(){ + eXosip_transport_hook_register(NULL); + if (mSipSocket != NULL){ + sMutex.lock(); + mTunnelClient->closeSocket(mSipSocket); + mSipSocket = NULL; + sMutex.unlock(); + } + if (mTunnelClient){ + delete mTunnelClient; + mTunnelClient=NULL; + } +} + +void TunnelManager::processTunnelEvent(){ + LinphoneProxyConfig* lProxy; + linphone_core_get_default_proxy(mCore, &lProxy); + + if (mEnabled && mTunnelClient->isReady()){ + ms_message("Tunnel is up, registering now"); + linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories); + eXosip_transport_hook_register(&mExosipTransport); + //force transport to udp + LCSipTransports lTransport; + + lTransport.udp_port=15060; + lTransport.tcp_port=0; + lTransport.tls_port=0; + lTransport.dtls_port=0; + + linphone_core_set_sip_transports(mCore, &lTransport); + //register + if (lProxy) { + linphone_proxy_config_done(lProxy); + } + }else if (mEnabled && !mTunnelClient->isReady()){ + /* we got disconnected from the tunnel */ + if (lProxy && linphone_proxy_config_is_registered(lProxy)) { + /*forces de-registration so that we register again when the tunnel is up*/ + linphone_proxy_config_edit(lProxy); + linphone_core_iterate(mCore); + } + } +} + +void TunnelManager::enable(bool isEnable) { + ms_message("Turning tunnel [%s]",(isEnable?"on":"off")); + if (isEnable && !mEnabled){ + mEnabled=true; + //1 save transport + linphone_core_get_sip_transports(mCore, &mRegularTransport); + //2 unregister + LinphoneProxyConfig* lProxy; + linphone_core_get_default_proxy(mCore, &lProxy); + if (lProxy) { + linphone_proxy_config_edit(lProxy); + //make sure unregister is sent + linphone_core_iterate(mCore); + } + //3 insert tunnel + start(); + }else if (!isEnable && mEnabled){ + mEnabled=false; + stopClient(); + //1 unregister + LinphoneProxyConfig* lProxy; + linphone_core_get_default_proxy(mCore, &lProxy); + if (lProxy) { + linphone_proxy_config_edit(lProxy); + //make sure unregister is sent + linphone_core_iterate(mCore); + } + + //make sure unregister is sent + linphone_core_iterate(mCore); + + linphone_core_set_rtp_transport_factories(mCore,NULL); + + eXosip_transport_hook_register(NULL); + //Restore transport + linphone_core_set_sip_transports(mCore, &mRegularTransport); + //register + if (lProxy) { + linphone_proxy_config_done(lProxy); + } + + } +} + +void TunnelManager::tunnelCallback(bool connected, TunnelManager *zis){ + zis->mStateChanged=true; +} + +/*invoked from linphone_core_iterate() */ +void TunnelManager::sOnIterate(TunnelManager *zis){ + if (zis->mStateChanged){ + zis->mStateChanged=false; + zis->processTunnelEvent(); + } +} + +#ifdef ANDROID +static void linphone_android_log_handler(int lev, const char *fmt, va_list args){ + int prio; + switch(lev){ + case TUNNEL_DEBUG: prio = ANDROID_LOG_DEBUG; break; + case TUNNEL_INFO: prio = ANDROID_LOG_INFO; break; + case TUNNEL_NOTICE: prio = ANDROID_LOG_INFO; break; + case TUNNEL_WARN: prio = ANDROID_LOG_WARN; break; + case TUNNEL_ERROR: prio = ANDROID_LOG_ERROR; break; + default: prio = ANDROID_LOG_DEFAULT; break; + } + __android_log_vprint(prio, LOG_DOMAIN, fmt, args); +} +#endif /*ANDROID*/ + +void TunnelManager::enableLogs(bool value) { + enableLogs(value,NULL); +} + +void TunnelManager::enableLogs(bool isEnabled,LogHandler logHandler) { + if (logHandler != NULL) SetLogHandler(logHandler); +#ifdef ANDROID + else SetLogHandler(linphone_android_log_handler); +#else + else SetLogHandler(default_log_handler); +#endif + + if (isEnabled) { + SetLogLevel(TUNNEL_ERROR|TUNNEL_WARN|TUNNEL_INFO); + } else { + SetLogLevel(TUNNEL_ERROR|TUNNEL_WARN); + } +} + + +bool TunnelManager::isEnabled() { + return mEnabled; +} +void TunnelManager::UdpMirrorClientListener(bool isUdpAvailable, void* data) { + TunnelManager* thiz = (TunnelManager*)data; + if (isUdpAvailable) { + LOGI("Tunnel is not required, disabling"); + thiz->enable(false); + thiz->mAutoDetectStarted = false; + } else { + if (++thiz->mCurrentUdpMirrorClient !=thiz->mUdpMirrorClients.end()) { + //1 enable tunnable but also try backup server + LOGI("Tunnel is required, enabling; Trying backup udp mirror"); + + UdpMirrorClient &lUdpMirrorClient=*thiz->mCurrentUdpMirrorClient; + lUdpMirrorClient.start(TunnelManager::UdpMirrorClientListener,(void*)thiz); + } else { + LOGI("Tunnel is required, enabling; no backup udp mirror available"); + thiz->mAutoDetectStarted = false; + } + thiz->enable(true); + } + return; +} + +void TunnelManager::autoDetect() { + // first check if udp mirrors was provisionned + if (mUdpMirrorClients.empty()) { + LOGE("No UDP mirror server configured aborting auto detection"); + return; + } + if (mAutoDetectStarted) { + LOGE("auto detection already in progress, restarting"); + (*mCurrentUdpMirrorClient).stop(); + } + mAutoDetectStarted=true; + mCurrentUdpMirrorClient =mUdpMirrorClients.begin(); + UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient; + lUdpMirrorClient.start(TunnelManager::UdpMirrorClientListener,(void*)this); + +} + +void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) { + mTunnelClient->setHttpProxyAuthInfo(username,passwd); +} + +LinphoneCore *TunnelManager::getLinphoneCore(){ + return mCore; +} diff --git a/coreapi/TunnelManager.hh b/coreapi/TunnelManager.hh new file mode 100644 index 000000000..20bb75d3d --- /dev/null +++ b/coreapi/TunnelManager.hh @@ -0,0 +1,171 @@ +/* + * C Implementation: tunnel + * + * Description: + * + * + * + *Copyright (C) 2011 Belledonne Comunications, Grenoble, France + */ + +#ifndef __TUNNEL_CLIENT_MANAGER_H__ +#define __TUNNEL_CLIENT_MANAGER_H__ +#include +#include "linphonecore.h" +#include "tunnel/client.hh" +extern "C" { + #include "eXosip2/eXosip_transport_hook.h" +} +namespace belledonnecomm { +class TunnelClient; +class UdpMirrorClient; +/** + * @addtogroup tunnel_client + * @{ +**/ + + /** + * The TunnelManager class extends the LinphoneCore functionnality in order to provide an easy to use API to + * - provision tunnel servers ip addresses and ports + * - start/stop the tunneling service + * - be informed of of connection and disconnection events to the tunnel server + * - perform auto-detection whether tunneling is required, based on a test of sending/receiving a flow of UDP packets. + * + * It takes in charge automatically the SIP registration procedure when connecting or disconnecting to a tunnel server. + * No other action on LinphoneCore is required to enable full operation in tunnel mode. + **/ + class TunnelManager : public TunnelClientController{ + + public: + /** + * Add a tunnel server. At least one should be provided to be able to connect. + * When several addresses are provided, the tunnel client may try each of them until it gets connected. + * + * @param ip tunnMethod definition for '-isInitialStateOn' not foundel server ip address + * @param port tunnel server tls port, recommended value is 443 + */ + void addServer(const char *ip, int port); + /** + *Add tunnel server with auto detection capabilities + * + * @param ip tunnel server ip address + * @param port tunnel server tls port, recommended value is 443 + * @param udpMirrorPort remote port on the tunnel server side used to test udp reachability + * @param delay udp packet round trip delay in ms considered as acceptable. recommanded value is 1000 ms. + */ + void addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay); + /** + * Removes all tunnel server address previously entered with addServer() + **/ + void cleanServers(); + /** + * Register a state callback to be notified whenever the tunnel client is connected or disconnected to the tunnel server. + * @param cb application callback function to use for notifying of connection/disconnection events. + * @param userdata An opaque pointer passed to the callback, used optionally by the application to retrieve a context. + **/ + void setCallback(StateCallback cb, void *userdata); + /** + * Start connecting to a tunnel server. + * At this step, nothing is tunneled yet. The enable() method must be used to state whether SIP and RTP traffic + * need to be tunneled or not. + **/ + void start(); + /** + * Forces reconnection to the tunnel server. + * This method is useful when the device switches from wifi to Edge/3G or vice versa. In most cases the tunnel client socket + * won't be notified promptly that its connection is now zombie, so it is recommended to call this method that will cause + * the lost connection to be closed and new connection to be issued. + **/ + void reconnect(); + /** + * Sets whether tunneling of SIP and RTP is required. + * @param isEnabled If true enter in tunneled mode, if false exits from tunneled mode. + * The TunnelManager takes care of refreshing SIP registration when switching on or off the tunneled mode. + * + **/ + void enable(bool isEnabled); + /** + * In auto detect mode, the tunnel manager try to establish a real time rtp cummunication with the tunnel server on specified port. + *
In case of success, the tunnel is automatically turned off. Otherwise, if no udp commmunication is feasible, tunnel mode is turned on. + *
Call this method each time to run the auto detection algorithm + */ + void autoDetect(); + /** + * Returns a boolean indicating whether tunneled operation is enabled. + **/ + bool isEnabled(); + /** + * Enables debug logs of the Tunnel subsystem. + **/ + void enableLogs(bool isEnabled); + /** + * Enables debugs logs of the Tunnel subsystem and specify a callback where to receive the debug messages. + **/ + void enableLogs(bool isEnabled,LogHandler logHandler); + /** + * iOS only feature: specify http proxy credentials. + * When the iOS device has an http proxy configured in the iOS settings, the tunnel client will connect to the server + * through this http proxy. Credentials might be needed depending on the proxy configuration. + * @param username The username. + * @param passwd The password. + **/ + void setHttpProxyAuthInfo(const char* username,const char* passwd); + ~TunnelManager(); + TunnelManager(LinphoneCore* lc); + /** + * Destroy the given RtpTransport. + */ + void closeRtpTransport(RtpTransport *t); + + /** + * Create an RtpTransport. + */ + RtpTransport *createRtpTransport(int port); + + /** + * Get associated Linphone Core. + */ + LinphoneCore *getLinphoneCore(); + private: + typedef std::list UdpMirrorClientList; + typedef std::list RtpTransportList; + virtual bool isStarted(); + virtual bool isReady() const; + static int customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen); + static int customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen); + static int eXosipSendto(int fd,const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen,void* userdata); + static int eXosipRecvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen,void* userdata); + static int eXosipSelect(int nfds, fd_set *s1, fd_set *s2, fd_set *s3, struct timeval *tv,void* userdata); + static void tunnelCallback(bool connected, TunnelManager *zis); + static void sOnIterate(TunnelManager *zis); + static void UdpMirrorClientListener(bool result, void* data); + + void processTunnelEvent(); + LinphoneCore* mCore; + LCSipTransports mRegularTransport; + TunnelSocket *mSipSocket; + eXosip_transport_hooks_t mExosipTransport; + StateCallback mCallback; + void * mCallbackData; + bool mEnabled; + bool mStateChanged; + std::list mServerAddrs; + UdpMirrorClientList mUdpMirrorClients; + UdpMirrorClientList::iterator mCurrentUdpMirrorClient; + TunnelClient* mTunnelClient; + void stopClient(); + static Mutex sMutex; + bool mAutoDetectStarted; + RtpTransportList mTransports; + LinphoneRtpTransportFactories mTransportFactories; + }; + +/** + * @} +**/ + +} + + + +#endif /*__TUNNEL_CLIENT_MANAGER_H__*/ diff --git a/coreapi/linphone_tunnel_manager.cc b/coreapi/linphone_tunnel_manager.cc new file mode 100644 index 000000000..49bf70015 --- /dev/null +++ b/coreapi/linphone_tunnel_manager.cc @@ -0,0 +1,126 @@ +/*************************************************************************** + * linphone_tunnel_manager.cc + * + * Fri Dec 9, 2011 + * Copyright 2011 Belledonne Communications + * Author: Guillaume Beraudo + * Email: guillaume dot beraudo at linphone dot 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 "linphone_tunnel_manager.h" +#include "TunnelManager.hh" +#include "linphonecore.h" +#include "private.h" +#include "lpconfig.h" + +static inline belledonnecomm::TunnelManager *bcTunnel(LinphoneTunnelManager *tunnel){ + return (belledonnecomm::TunnelManager *)tunnel; +} + +extern "C" LinphoneTunnelManager* linphone_core_tunnel_new(LinphoneCore *lc){ + LinphoneTunnelManager* tunnel= (LinphoneTunnelManager*) new belledonnecomm::TunnelManager(lc); + return tunnel; +} + +LinphoneTunnelManager* linphone_tunnel_get(LinphoneCore *lc){ + return lc->tunnel; +} + +void linphone_tunnel_destroy(LinphoneTunnelManager *tunnel){ + delete bcTunnel(tunnel); +} + +void linphone_tunnel_add_server(LinphoneTunnelManager *tunnel, const char *host, int port){ + bcTunnel(tunnel)->addServer(host, port); +} + +void linphone_tunnel_add_server_and_mirror(LinphoneTunnelManager *tunnel, const char *host, int port, int remote_udp_mirror, int delay){ + bcTunnel(tunnel)->addServer(host, port, remote_udp_mirror, delay); +} + +void linphone_tunnel_clean_servers(LinphoneTunnelManager *tunnel){ + bcTunnel(tunnel)->cleanServers(); +} + +void linphone_tunnel_enable(LinphoneTunnelManager *tunnel, bool_t enabled){ + bcTunnel(tunnel)->enable(enabled); +} + +bool_t linphone_tunnel_enabled(LinphoneTunnelManager *tunnel){ + return bcTunnel(tunnel)->isEnabled(); +} + +void linphone_tunnel_enable_logs(LinphoneTunnelManager *tunnel, bool_t enabled){ + bcTunnel(tunnel)->enableLogs(enabled); +} + +void linphone_tunnel_auto_detect(LinphoneTunnelManager *tunnel){ + bcTunnel(tunnel)->autoDetect(); +} + + +static inline _LpConfig *config(LinphoneTunnelManager *tunnel){ + return ((belledonnecomm::TunnelManager *)tunnel)->getLinphoneCore()->config; +} + +/** + * Set tunnel server addresses. "host1:port1 host2:port2 host3:port3" +**/ +void linphone_tunnel_set_server_addresses(LinphoneTunnelManager *tunnel, const char *addresses){ + lp_config_set_string(config(tunnel),"tunnel","server_addresses",addresses); +} + +/** + * Get tunnel server addresses. "host1:port1 host2:port2 host3:port3" +**/ +const char *linphone_tunnel_get_server_addresses(LinphoneTunnelManager *tunnel){ + return lp_config_get_string(config(tunnel),"tunnel","server_addresses", NULL); +} + +/** + * Set tunnel state. +**/ +void linphone_tunnel_set_state(LinphoneTunnelManager *tunnel, LinphoneTunnelState state){ + switch (state) { + case LinphoneTunnelEnabled: + lp_config_set_string(config(tunnel),"tunnel","tunnel_state","enabled"); + break; + case LinphoneTunnelDisabled: + lp_config_set_string(config(tunnel),"tunnel","tunnel_state","disabled"); + break; + case LinphoneTunnelAuto: + lp_config_set_string(config(tunnel),"tunnel","tunnel_state","auto"); + break; + } +} + +/** + * Get tunnel state. +**/ +LinphoneTunnelState linphone_tunnel_get_state(LinphoneTunnelManager *tunnel){ + const char *state=lp_config_get_string(config(tunnel),"tunnel","tunnel_state","disabled"); + if (0==strcmp("enabled", state)){ + return LinphoneTunnelEnabled; + } else if (0==strcmp("auto", state)){ + return LinphoneTunnelAuto; + } else { + return LinphoneTunnelDisabled; + } +} diff --git a/coreapi/linphone_tunnel_manager.h b/coreapi/linphone_tunnel_manager.h new file mode 100644 index 000000000..6f901ac56 --- /dev/null +++ b/coreapi/linphone_tunnel_manager.h @@ -0,0 +1,85 @@ +/*************************************************************************** + * linphone_tunnel_manager.h + * + * Fri Dec 9, 2011 + * Copyright 2011 Belledonne Communications + * Author: Guillaume Beraudo + * Email: guillaume dot beraudo at linphone dot 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. + */ + +#ifndef LINPHONETUNNELMANAGER_H +#define LINPHONETUNNELMANAGER_H + +#include "linphonecore.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef struct LinphoneTunnelManager LinphoneTunnelManager; + +LinphoneTunnelManager *linphone_tunnel_get(LinphoneCore *lc); +void linphone_tunnel_destroy(LinphoneTunnelManager *tunnel); +void linphone_tunnel_add_server(LinphoneTunnelManager *tunnel, const char *host, int port); +void linphone_tunnel_add_server_and_mirror(LinphoneTunnelManager *tunnel, const char *host, int port, int remote_udp_mirror, int delay); +void linphone_tunnel_clean_servers(LinphoneTunnelManager *tunnel); +void linphone_tunnel_enable(LinphoneTunnelManager *tunnel, bool_t enabled); +bool_t linphone_tunnel_enabled(LinphoneTunnelManager *tunnel); +void linphone_tunnel_enable_logs(LinphoneTunnelManager *tunnel, bool_t enabled); +void linphone_tunnel_auto_detect(LinphoneTunnelManager *tunnel); + + + +/** + * LinphoneTunnelState describes the tunnel activation states. + */ +typedef enum _LinphoneTunnelState{ + LinphoneTunnelDisabled, /**a_rtp) - rtp_session_set_transports(audiostream->session,lc->a_rtp,lc->a_rtcp); + 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->session,artp,artcp); + } call->audiostream_app_evq = ortp_ev_queue_new(); rtp_session_register_event_queue(audiostream->session,call->audiostream_app_evq); @@ -858,8 +861,11 @@ void linphone_call_init_media_streams(LinphoneCall *call){ if( lc->video_conf.displaytype != NULL) video_stream_set_display_filter_name(call->videostream,lc->video_conf.displaytype); video_stream_set_event_callback(call->videostream,video_stream_event_cb, call); - if (lc->v_rtp) - rtp_session_set_transports(call->videostream->session,lc->v_rtp,lc->v_rtcp); + 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->session,vrtp,vrtcp); + } call->videostream_app_evq = ortp_ev_queue_new(); rtp_session_register_event_queue(call->videostream->session,call->videostream_app_evq); #ifdef TEST_EXT_RENDERER @@ -1039,7 +1045,7 @@ static bool_t linphone_call_sound_resources_available(LinphoneCall *call){ return !linphone_core_is_in_conference(lc) && (current==NULL || current==call); } -static int find_crypto_index_from_tag(SalSrtpCryptoAlgo crypto[],unsigned char tag) { +static int find_crypto_index_from_tag(const SalSrtpCryptoAlgo crypto[],unsigned char tag) { int i; for(i=0; iaudiostream->ec,MS_ECHO_CANCELLER_GET_STATE_STRING,&state_str); if (state_str){ - ms_message("Writing echo canceller state, %i bytes",(int)strlen(state_str)); + ms_message("Writing echo canceler state, %i bytes",(int)strlen(state_str)); lp_config_set_string(call->core->config,"sound","ec_state",state_str); } } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 55e01193e..aa1362cc0 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -810,6 +810,14 @@ static void autoreplier_config_init(LinphoneCore *lc) } */ +bool_t linphone_core_tunnel_available(){ +#ifdef TUNNEL_ENABLED + return TRUE; +#else + return FALSE; +#endif +} + /** * Enable adaptive rate control (experimental feature, audio-only). * @@ -989,6 +997,36 @@ static void misc_config_read (LinphoneCore *lc) { lc->max_calls=lp_config_get_int(config,"misc","max_calls",NB_MAX_CALLS); } +#ifdef TUNNEL_ENABLED +static void tunnel_add_servers_from_config(LinphoneTunnelManager *tunnel, const char* confaddress){ + char *addresses=(char*)ms_strdup(confaddress); + char *str1; + for(str1=addresses;;str1=NULL){ + char *port; + char *address=strtok(str1," "); // Not thread safe + if (!address) break; + port=strchr(address, ':'); + if (!port) ms_fatal("Bad tunnel address %s", address); + *port++='\0'; + linphone_tunnel_add_server(tunnel, address, atoi(port)); + } + ms_free(addresses); +} +#endif + +void linphone_core_update_tunnel(LinphoneCore *lc){ +#ifdef TUNNEL_ENABLED + bool_t enabled; + const char* addresses=linphone_tunnel_get_server_addresses(lc->tunnel); + if (addresses){ + linphone_tunnel_clean_servers(lc->tunnel); + tunnel_add_servers_from_config(lc->tunnel,addresses); + } + enabled=linphone_tunnel_get_state(lc->tunnel)==LinphoneTunnelEnabled && addresses!=NULL; + linphone_tunnel_enable(lc->tunnel, enabled); +#endif +} + static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vtable, const char *config_path, const char *factory_config_path, void * userdata) { @@ -1084,6 +1122,10 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta lc->presence_mode=LinphoneStatusOnline; misc_config_read(lc); ui_config_read(lc); +#ifdef TUNNEL_ENABLED + lc->tunnel=linphone_core_tunnel_new(lc); + linphone_core_update_tunnel(lc); +#endif if (lc->vtable.display_status) lc->vtable.display_status(lc,_("Ready")); lc->auto_net_state_mon=lc->sip_conf.auto_net_state_mon; @@ -3874,14 +3916,8 @@ void linphone_core_stop_waiting(LinphoneCore *lc){ } } -void linphone_core_set_audio_transports(LinphoneCore *lc, RtpTransport *rtp, RtpTransport *rtcp){ - lc->a_rtp=rtp; - lc->a_rtcp=rtcp; -} - -void linphone_core_set_video_transports(LinphoneCore *lc, RtpTransport *rtp, RtpTransport *rtcp){ - lc->v_rtp=rtp; - lc->v_rtcp=rtcp; +void linphone_core_set_rtp_transport_factories(LinphoneCore* lc, LinphoneRtpTransportFactories *factories){ + lc->rtptf=factories; } /** diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 68d658694..e32c4d0fa 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -344,6 +344,16 @@ typedef enum _LinphoneRegistrationState{ */ const char *linphone_registration_state_to_string(LinphoneRegistrationState cs); +/** + * True if tunnel support was compiled. + */ +bool_t linphone_core_tunnel_available(); + +/** + * Update tunnel using configuration. + */ +void linphone_core_update_tunnel(LinphoneCore *lc); + LinphoneProxyConfig *linphone_proxy_config_new(void); int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *server_addr); int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity); @@ -1006,9 +1016,20 @@ const MSList * linphone_core_get_sip_setups(LinphoneCore *lc); void linphone_core_destroy(LinphoneCore *lc); /*for advanced users:*/ -void linphone_core_set_audio_transports(LinphoneCore *lc, RtpTransport *rtp, RtpTransport *rtcp); -void linphone_core_set_video_transports(LinphoneCore *lc, RtpTransport *rtp, RtpTransport *rtcp); +typedef RtpTransport * (*LinphoneRtpTransportFactoryFunc)(void *data, int port); +struct _LinphoneRtpTransportFactories{ + LinphoneRtpTransportFactoryFunc audio_rtp_func; + void *audio_rtp_func_data; + LinphoneRtpTransportFactoryFunc audio_rtcp_func; + void *audio_rtcp_func_data; + LinphoneRtpTransportFactoryFunc video_rtp_func; + void *video_rtp_func_data; + LinphoneRtpTransportFactoryFunc video_rtcp_func; + void *video_rtcp_func_data; +}; +typedef struct _LinphoneRtpTransportFactories LinphoneRtpTransportFactories; +void linphone_core_set_rtp_transport_factories(LinphoneCore* lc, LinphoneRtpTransportFactories *factories); int linphone_core_get_current_call_stats(LinphoneCore *lc, rtp_stats_t *local, rtp_stats_t *remote); diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 4552a0523..eca9152f4 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -20,6 +20,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "linphonecore_utils.h" #include +#ifdef TUNNEL_ENABLED +#include "linphone_tunnel_manager.h" +#endif + extern "C" { #include "mediastreamer2/mediastream.h" } @@ -1591,3 +1595,45 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getMaxCalls(JNIEnv *env, extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setMaxCalls(JNIEnv *env,jobject thiz,jlong pCore, jint max) { linphone_core_set_max_calls((LinphoneCore *) pCore, (int) max); } + +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelAddServerAndMirror(JNIEnv *env,jobject thiz,jlong pCore, + jstring jHost, jint port, jint mirror, jint delay) { +#ifdef TUNNEL_ENABLED + LinphoneTunnelManager *tunnel=((LinphoneCore *) pCore)->tunnel; if (!tunnel) return; + const char* cHost=env->GetStringUTFChars(jHost, NULL); + linphone_tunnel_add_server_and_mirror(tunnel, cHost, port, mirror, delay); + env->ReleaseStringUTFChars(jHost, cHost); +#endif +} + +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelAutoDetect(JNIEnv *env,jobject thiz,jlong pCore) { +#ifdef TUNNEL_ENABLED + LinphoneTunnelManager *tunnel=((LinphoneCore *) pCore)->tunnel; if (!tunnel) return; + linphone_tunnel_auto_detect(tunnel); +#endif +} + +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelCleanServers(JNIEnv *env,jobject thiz,jlong pCore) { +#ifdef TUNNEL_ENABLED + LinphoneTunnelManager *tunnel=((LinphoneCore *) pCore)->tunnel; if (!tunnel) return; + linphone_tunnel_clean_servers(tunnel); +#endif +} + +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelEnable(JNIEnv *env,jobject thiz,jlong pCore, jboolean enable) { +#ifdef TUNNEL_ENABLED + LinphoneTunnelManager *tunnel=((LinphoneCore *) pCore)->tunnel; if (!tunnel) return; + linphone_tunnel_enable(tunnel, enable); +#endif +} + +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelEnableLogs(JNIEnv *env,jobject thiz,jlong pCore, jboolean enable) { +#ifdef TUNNEL_ENABLED + LinphoneTunnelManager *tunnel=((LinphoneCore *) pCore)->tunnel; if (!tunnel) return; + linphone_tunnel_enable_logs(tunnel, enable); +#endif +} + +extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isTunnelAvailable(JNIEnv *env,jobject thiz){ + return linphone_core_tunnel_available(); +} diff --git a/coreapi/private.h b/coreapi/private.h index 3561a4126..bda52f016 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -24,8 +24,11 @@ #ifndef _PRIVATE_H #define _PRIVATE_H - +#ifdef __cplusplus +extern "C" { +#endif #include "linphonecore.h" +#include "linphone_tunnel_manager.h" #include "linphonecore_utils.h" #include "sal.h" @@ -442,8 +445,7 @@ struct _LinphoneCore int missed_calls; VideoPreview *previewstream; struct _MSEventQueue *msevq; - RtpTransport *a_rtp,*a_rtcp; - RtpTransport *v_rtp,*v_rtcp; + LinphoneRtpTransportFactories *rtptf; MSList *bl_reqs; MSList *subscribers; /* unknown subscribers */ int minutes_away; @@ -474,8 +476,11 @@ struct _LinphoneCore int device_rotation; bool_t ringstream_autorelease; int max_calls; + LinphoneTunnelManager *tunnel; }; +LinphoneTunnelManager *linphone_core_tunnel_new(LinphoneCore *lc); + bool_t linphone_core_can_we_add_call(LinphoneCore *lc); int linphone_core_add_call( LinphoneCore *lc, LinphoneCall *call); int linphone_core_del_call( LinphoneCore *lc, LinphoneCall *call); @@ -538,4 +543,9 @@ void __linphone_core_invalidate_registers(LinphoneCore* lc); #define NB_MAX_CALLS (10) #endif void call_logs_write_to_config_file(LinphoneCore *lc); + +#ifdef __cplusplus +} +#endif + #endif /* _PRIVATE_H */ diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 2d62217ac..42d5ff838 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -8,6 +8,7 @@ UI_FILES= about.ui \ call_logs.ui \ log.ui \ buddylookup.ui \ + tunnel_config.ui \ waiting.ui PIXMAPS= \ @@ -74,7 +75,8 @@ endif AM_CFLAGS= -DIN_LINPHONE -I$(top_srcdir)/coreapi/ \ $(MEDIASTREAMER_CFLAGS) \ $(ORTP_CFLAGS) \ - $(STRICT_OPTIONS) $(LIBGTK_CFLAGS) $(LIBGTKMAC_CFLAGS) $(IPV6_CFLAGS) + $(STRICT_OPTIONS) $(LIBGTK_CFLAGS) $(LIBGTKMAC_CFLAGS) $(IPV6_CFLAGS) \ + $(TUNNEL_CFLAGS) version_date.h: $(top_srcdir)/configure.ac diff --git a/gtk/parameters.ui b/gtk/parameters.ui index 400622632..2403b3316 100644 --- a/gtk/parameters.ui +++ b/gtk/parameters.ui @@ -1,30 +1,31 @@ - + + + 500 500 3001 - 500 1 10 + 1 1 65535 - 1 1 10 + 1 1 65535 - 1 1 10 - 65535 1 + 65535 1 10 @@ -41,15 +42,15 @@ 10 + 5060 1 65535 - 5060 1 9.9999999995529656 - 65535 1 + 65535 1 10 @@ -152,14 +153,12 @@ - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Settings linphone2.png True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK @@ -169,42 +168,34 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 none True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 12 True - False True - False Set Maximum Transmission Unit: True True False - False True - + - True - True 0 @@ -212,21 +203,15 @@ True True - False - False adjustment1 - + - True - True 1 - True - True 0 @@ -236,13 +221,10 @@ True True False - False True - + - True - True 1 @@ -253,13 +235,10 @@ True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False True - + - True - True 2 @@ -270,7 +249,6 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>Transport</b> True @@ -279,34 +257,29 @@ False - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 none True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 12 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 4 + 5 2 True - False model8 @@ -320,10 +293,8 @@ True True - + True - False - False adjustment7 @@ -336,12 +307,10 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - + True - False - False adjustment2 - + 1 @@ -355,12 +324,10 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - + True - False - False adjustment3 - + 1 @@ -372,7 +339,6 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Video RTP/UDP: right @@ -385,7 +351,6 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Audio RTP/UDP: right @@ -398,7 +363,6 @@ True - False Media encryption type @@ -409,7 +373,6 @@ True - False 0 @@ -419,6 +382,29 @@ 4 + + + Tunnel + + + 4 + 5 + + + + + edit + True + True + + + + 1 + 2 + 4 + 5 + + @@ -426,7 +412,6 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>Network protocol and ports</b> True @@ -435,31 +420,27 @@ False - True 1 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 none True - False Direct connection to the Internet True True False - False True True - + False @@ -470,41 +451,33 @@ True - False Behind NAT / Firewall (specify gateway IP below) True True False - False True True no_nat - + - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Public IP address: right - True - True 0 @@ -513,20 +486,14 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - False - + - True - True 1 - True - True 1 @@ -540,41 +507,33 @@ True - False Behind NAT / Firewall (use STUN to resolve) True True False - False True True no_nat - + - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Stun server: right - True - True 0 @@ -583,20 +542,14 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - False - + - True - True 1 - True - True 1 @@ -612,7 +565,6 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>NAT and Firewall</b> True @@ -621,7 +573,6 @@ False - True 2 @@ -630,31 +581,24 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-network - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Network settings - True - True 1 @@ -666,43 +610,35 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 none True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 12 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 6 2 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - + - True - True 0 @@ -713,13 +649,10 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False True - + - True - True 1 @@ -735,7 +668,6 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Ring sound: right @@ -750,9 +682,7 @@ True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - False - + 1 @@ -765,10 +695,9 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK model1 - + @@ -787,10 +716,9 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK model2 - + @@ -808,7 +736,6 @@ - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK ALSA special device (optional): right @@ -822,7 +749,6 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Capture device: right @@ -836,7 +762,6 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Ring device: right @@ -850,7 +775,6 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Playback device: right @@ -863,10 +787,9 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK model3 - + @@ -887,9 +810,8 @@ True True False - False True - + 1 @@ -908,7 +830,6 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>Audio</b> True @@ -916,32 +837,26 @@ - True - True 0 True - False 0 none True - False 12 True - False 2 2 True - False Video input device: right @@ -952,9 +867,8 @@ True - False model4 - + @@ -971,7 +885,6 @@ True - False Prefered video resolution: @@ -982,10 +895,9 @@ True - False model5 0 - + @@ -1007,14 +919,12 @@ True - False <b>Video</b> True - True False 1 @@ -1027,31 +937,24 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-media-play - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Multimedia settings - True - True 1 @@ -1064,12 +967,10 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK This section defines your SIP address when not using a SIP account 0 @@ -1077,20 +978,17 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 12 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 3 2 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Your display name (eg: John Doe): @@ -1100,9 +998,7 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - False - + 1 @@ -1112,7 +1008,6 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Your username: @@ -1124,7 +1019,6 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Your resulting SIP address: @@ -1138,9 +1032,7 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - False - + 1 @@ -1155,8 +1047,6 @@ True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False - False - False 1 @@ -1172,7 +1062,6 @@ True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>Default identity</b> True @@ -1180,28 +1069,23 @@ - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 none True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 12 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK @@ -1213,22 +1097,16 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK @@ -1236,36 +1114,28 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - + True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-add - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Add - True - True 1 @@ -1284,36 +1154,28 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - + True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-edit - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Edit - True - True 1 @@ -1332,36 +1194,28 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - + True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-delete - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Remove - True - True 1 @@ -1378,34 +1232,26 @@ True True - False - + True - False True - False gtk-network - True - True 0 True - False Register to FONICS virtual network ! - True - True 1 @@ -1432,7 +1278,6 @@ virtual network ! True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>Proxy accounts</b> True @@ -1440,28 +1285,23 @@ virtual network ! - True - True 1 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 none True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 12 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK @@ -1469,36 +1309,28 @@ virtual network ! True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - + True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-delete - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Erase all passwords - True - True 1 @@ -1518,7 +1350,6 @@ virtual network ! True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>Privacy</b> True @@ -1526,8 +1357,6 @@ virtual network ! - True - True 2 @@ -1539,31 +1368,24 @@ virtual network ! True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK stock_people.png - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Manage SIP Accounts - True - True 1 @@ -1576,34 +1398,29 @@ virtual network ! True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 none True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 12 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK model6 0 - + @@ -1613,14 +1430,12 @@ virtual network ! False - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK @@ -1634,22 +1449,16 @@ virtual network ! True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - - - - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK @@ -1658,9 +1467,8 @@ virtual network ! True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False True - + False @@ -1675,9 +1483,8 @@ virtual network ! True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False True - + False @@ -1691,36 +1498,28 @@ virtual network ! True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - + True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-yes - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Enable - True - True 1 @@ -1739,36 +1538,28 @@ virtual network ! True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - + True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-no - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Disable - True - True 1 @@ -1784,14 +1575,11 @@ virtual network ! False - True 1 - True - True 1 @@ -1802,7 +1590,6 @@ virtual network ! True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>Codecs</b> True @@ -1810,28 +1597,23 @@ virtual network ! - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 none True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 12 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 3 2 @@ -1841,10 +1623,8 @@ virtual network ! True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 stands for "unlimited" - False - False adjustment5 - + 1 @@ -1861,10 +1641,8 @@ virtual network ! True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 stands for "unlimited" - False - False adjustment6 - + 1 @@ -1876,7 +1654,6 @@ virtual network ! True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Upload speed limit in Kbit/sec: right @@ -1889,7 +1666,6 @@ virtual network ! True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Download speed limit in Kbit/sec: right @@ -1901,10 +1677,9 @@ virtual network ! True True False - False 0 True - + 1 @@ -1918,7 +1693,6 @@ virtual network ! True - False <i>Adaptive rate control is a technique to dynamically guess the available bandwidth during a call.</i> True True @@ -1937,7 +1711,6 @@ virtual network ! True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>Bandwidth control</b> True @@ -1945,8 +1718,6 @@ virtual network ! - True - True 1 @@ -1958,31 +1729,24 @@ virtual network ! True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-execute - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Codecs - True - True 1 @@ -1995,24 +1759,20 @@ virtual network ! True - False True - False 0 none True - False 12 True - False model7 - + @@ -2026,7 +1786,6 @@ virtual network ! True - False <b>Language</b> True @@ -2034,20 +1793,17 @@ virtual network ! False - True 0 True - False 0 none True - False 12 @@ -2055,9 +1811,8 @@ virtual network ! True True False - False True - + @@ -2065,7 +1820,6 @@ virtual network ! True - False <b>Level</b> True @@ -2073,7 +1827,6 @@ virtual network ! False - True 1 @@ -2085,29 +1838,22 @@ virtual network ! True - False True - False gtk-properties 3 - True - True 0 True - False User interface - True - True 1 @@ -2119,15 +1865,12 @@ virtual network ! - True - True 0 True - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK end @@ -2136,33 +1879,25 @@ virtual network ! True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - + True - False True - False gtk-apply - True - True 0 True - False Done - True - True 1 @@ -2178,8 +1913,6 @@ virtual network ! - True - True 5 1 diff --git a/gtk/propertybox.c b/gtk/propertybox.c index 8bacff9f5..7c414dc83 100644 --- a/gtk/propertybox.c +++ b/gtk/propertybox.c @@ -18,6 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "linphone.h" +#include "linphone_tunnel_manager.h" typedef enum { CAP_IGNORE, @@ -986,5 +987,88 @@ void linphone_gtk_show_parameters(void){ g_signal_connect(G_OBJECT(linphone_gtk_get_widget(pb,"proto_port")),"value-changed",(GCallback)linphone_gtk_update_my_port,NULL); g_signal_connect(G_OBJECT(linphone_gtk_get_widget(pb,"proto_combo")),"changed",(GCallback)linphone_gtk_proto_changed,NULL); + + + if (linphone_core_tunnel_available(lc)){ + gtk_widget_set_visible(GTK_WIDGET(linphone_gtk_get_widget(pb,"tunnel_edit_button")), TRUE); + gtk_widget_set_visible(GTK_WIDGET(linphone_gtk_get_widget(pb,"tunnel_label")), TRUE); + } + gtk_widget_show(pb); } + + +void linphone_gtk_edit_tunnel_closed(GtkWidget *button){ + GtkWidget *pb=gtk_widget_get_toplevel(button); + gtk_widget_destroy(pb); +} + +#ifdef TUNNEL_ENABLED +static void tunnel_get_server_host_and_port(LinphoneTunnelManager *tunnel, char *host, int size, int *port){ + char *colon; + char *addresses=(char*)ms_strdup(linphone_tunnel_get_server_addresses(tunnel)); + char *str1=addresses; + char *address=strtok(str1," "); // Not thread safe + if (!address) return; + colon=strchr(address, ':'); + if (!colon) return; + *colon++='\0'; + *port=atoi(colon); + memcpy(host,address,size); + ms_free(addresses); +} +#endif + +void linphone_gtk_edit_tunnel(GtkButton *button){ +#ifdef TUNNEL_ENABLED + LinphoneCore *lc=linphone_gtk_get_core(); + GtkWidget *w=linphone_gtk_create_window("tunnel_config"); + LinphoneTunnelManager *tunnel=linphone_tunnel_get(lc); + char host[50]={'\0'}; + int port=0; + tunnel_get_server_host_and_port(tunnel, host, sizeof(host), &port); + LinphoneTunnelState state=linphone_tunnel_get_state(tunnel); + + gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"host")),host); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"port")), port); + + if (state == LinphoneTunnelEnabled){ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_enable")),1); + } else{ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_disable")),1); + } + + g_object_weak_ref(G_OBJECT(w),(GWeakNotify)linphone_gtk_edit_tunnel_closed,w); + + gtk_widget_show(w); +#endif +} + +void linphone_gtk_tunnel_ok(GtkButton *button){ +#ifdef TUNNEL_ENABLED + // Save information to config file + LinphoneCore *lc=linphone_gtk_get_core(); + GtkWidget *w=gtk_widget_get_toplevel(GTK_WIDGET(button)); + char address[50]={'\0'}; + LinphoneTunnelManager *tunnel=linphone_tunnel_get(lc); + + gint port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"port"))); + gboolean enabled=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_enable"))); + const char *host=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"host"))); + + snprintf(address, sizeof address, "%s:%i", host, port); + linphone_tunnel_set_server_addresses(tunnel, address); + if (enabled){ + linphone_tunnel_set_state(tunnel, LinphoneTunnelEnabled); + } else{ + linphone_tunnel_set_state(tunnel,LinphoneTunnelDisabled); + } + linphone_core_update_tunnel(lc); + gtk_widget_destroy(w); +#endif +} + + +void linphone_gtk_tunnel_cancel(GtkButton *button){ + +} diff --git a/gtk/tunnel_config.ui b/gtk/tunnel_config.ui new file mode 100644 index 000000000..c10ddf257 --- /dev/null +++ b/gtk/tunnel_config.ui @@ -0,0 +1,202 @@ + + + + + + 3600 + 100000 + 1 + 10 + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Linphone - Configure a SIP account + center-on-parent + linphone2.png + dialog + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + none + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 4 + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Host + right + + + + + 275 + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + 1 + 2 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Port + right + + + 1 + 2 + + + + + Enable + True + True + False + True + True + + + 1 + 2 + 2 + 3 + + + + + Disable + True + True + False + True + True + radio_enable + + + 1 + 2 + 3 + 4 + + + + + True + True + + adjustment1 + + + 1 + 2 + 1 + 2 + + + + + + + + + + + 0 + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Configure tunnel + True + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + end + + + gtk-ok + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + + False + False + 0 + + + + + gtk-cancel + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + + False + False + 1 + + + + + False + end + 0 + + + + + + button6 + button7 + + + diff --git a/java/common/org/linphone/core/LinphoneCore.java b/java/common/org/linphone/core/LinphoneCore.java index b3c25b4b7..a9629cce1 100644 --- a/java/common/org/linphone/core/LinphoneCore.java +++ b/java/common/org/linphone/core/LinphoneCore.java @@ -707,5 +707,17 @@ public interface LinphoneCore { * @param path path to music file played to remote side when on hold. */ void setPlayFile(String path); - + void tunnelEnable(boolean enable); + void tunnelAutoDetect(); + void tunnelEnableLogs(boolean enable); + void tunnelCleanServers(); + /** + * @param host tunnel server ip address + * @param port tunnel server tls port, recommended value is 443 + * @param udpMirrorPort remote port on the tunnel server side used to test udp reachability + * @param roundTripDelay udp packet round trip delay in ms considered as acceptable. recommended value is 1000 ms + */ + void tunnelAddServerAndMirror(String host, int port, int udpMirrorPort, int roundTripDelay); + + boolean isTunnelAvailable(); } diff --git a/oRTP b/oRTP index 758150c3c..729f35e54 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 758150c3cd0f5a3a7a087247d6ff2dd198435fe7 +Subproject commit 729f35e54053154d92fe3eaf7bdb86bc10aec262