From ba13a9baf7c9b460ebfdcdbafb295a1dadc16294 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Wed, 3 Sep 2014 13:54:11 +0200 Subject: [PATCH] Fix tunnel bug: reset 'enable register' option in proxy config after enabling/disabling the tunnel --- coreapi/TunnelManager.cc | 114 ++++++++++++++++++++++----------------- coreapi/TunnelManager.hh | 16 +++--- 2 files changed, 74 insertions(+), 56 deletions(-) diff --git a/coreapi/TunnelManager.cc b/coreapi/TunnelManager.cc index 2bc8cd3e0..ebbad9de3 100644 --- a/coreapi/TunnelManager.cc +++ b/coreapi/TunnelManager.cc @@ -1,7 +1,7 @@ /* * C Implementation: tunnel * - * Description: + * Description: * * * Author: Simon Morlat , (C) 2009 @@ -136,13 +136,14 @@ int TunnelManager::customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flag TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController() -,mCore(lc) -,mCallback(NULL) -,mEnabled(false) -,mTunnelClient(NULL) -,mAutoDetectStarted(false) -,mReady(false) -,mHttpProxyPort(0){ + ,mCore(lc) + ,mCallback(NULL) + ,mEnabled(false) + ,mTunnelClient(NULL) + ,mAutoDetectStarted(false) + ,mReady(false) + ,mHttpProxyPort(0) + ,mPreviousRegistrationEnabled(false){ linphone_core_add_iterate_hook(mCore,(LinphoneCoreIterateHook)sOnIterate,this); mTransportFactories.audio_rtcp_func=sCreateRtpTransport; @@ -167,22 +168,36 @@ void TunnelManager::stopClient(){ } } -void TunnelManager::processTunnelEvent(const Event &ev){ +void TunnelManager::registration(){ LinphoneProxyConfig* lProxy; - linphone_core_get_default_proxy(mCore, &lProxy); - if (mEnabled && mTunnelClient->isReady()){ - ms_message("Tunnel is up, registering now"); + // tunnel was enabled + if (isReady()){ linphone_core_set_firewall_policy(mCore,LinphonePolicyNoFirewall); linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories); sal_enable_tunnel(mCore->sal, mTunnelClient); + // tunnel was disabled + } else { + linphone_core_set_sip_transports(mCore, &mRegularTransport); + linphone_core_set_firewall_policy(mCore, mPreviousFirewallPolicy); + } - //register - if (lProxy) { - linphone_proxy_config_refresh_register(lProxy); - } + // registration occurs always after an unregistation has been made. First we + // need to reset the previous registration mode + linphone_core_get_default_proxy(mCore, &lProxy); + if (lProxy) { + linphone_proxy_config_edit(lProxy); + linphone_proxy_config_enable_register(lProxy,mPreviousRegistrationEnabled); + linphone_proxy_config_done(lProxy); + } +} + +void TunnelManager::processTunnelEvent(const Event &ev){ + if (mEnabled && mTunnelClient->isReady()){ mReady=true; + ms_message("Tunnel is up, registering now"); + registration(); }else if (mEnabled && !mTunnelClient->isReady()){ /* we got disconnected from the tunnel */ mReady=false; @@ -191,27 +206,37 @@ void TunnelManager::processTunnelEvent(const Event &ev){ void TunnelManager::waitUnRegistration(){ LinphoneProxyConfig* lProxy; + linphone_core_get_default_proxy(mCore, &lProxy); - if (lProxy && linphone_proxy_config_get_state(lProxy)==LinphoneRegistrationOk) { - int i=0; - linphone_proxy_config_edit(lProxy); - linphone_proxy_config_enable_register(lProxy,FALSE); - linphone_proxy_config_done(lProxy); - //make sure unregister is sent and authenticated - do{ - linphone_core_iterate(mCore); - ms_usleep(20000); - if (i>100){ - ms_message("tunnel: timeout for unregistration expired, giving up"); - break; - } - i++; - }while(linphone_proxy_config_get_state(lProxy)!=LinphoneRegistrationCleared); - } + if (lProxy){ + mPreviousRegistrationEnabled=linphone_proxy_config_register_enabled(lProxy); + if (linphone_proxy_config_is_registered(lProxy)) { + int i=0; + linphone_proxy_config_edit(lProxy); + linphone_proxy_config_enable_register(lProxy,FALSE); + linphone_proxy_config_done(lProxy); + sal_unregister(lProxy->op); + //make sure unregister is sent and authenticated + do{ + linphone_core_iterate(mCore); + ms_usleep(20000); + if (i>100){ + ms_message("tunnel: timeout for unregistration expired, giving up"); + break; + } + i++; + }while(linphone_proxy_config_is_registered(lProxy)); + ms_message("Unregistration %s", linphone_proxy_config_is_registered(lProxy)?"failed":"succeeded"); + }else{ + ms_message("No registration pending"); + } + } } +/*Each time tunnel is enabled/disabled, we need to unregister previous session and re-register. Since tunnel initialization +is asynchronous, we temporary disable auto register while tunnel sets up, and reenable it when re-registering. */ void TunnelManager::enable(bool isEnable) { - ms_message("Turning tunnel [%s]",(isEnable?"on":"off")); + ms_message("Turning tunnel [%s]", isEnable ?"on" : "off"); if (isEnable && !mEnabled){ mEnabled=true; //1 save transport and firewall policy @@ -224,7 +249,8 @@ void TunnelManager::enable(bool isEnable) { }else if (!isEnable && mEnabled){ //1 unregister waitUnRegistration(); - + + // 2 stop tunnel mEnabled=false; stopClient(); mReady=false; @@ -239,18 +265,8 @@ void TunnelManager::enable(bool isEnable) { lTransport.dtls_port = 0; linphone_core_set_sip_transports(mCore, &lTransport); - //Restore transport and firewall policy - linphone_core_set_sip_transports(mCore, &mRegularTransport); - linphone_core_set_firewall_policy(mCore, mPreviousFirewallPolicy); - //register - LinphoneProxyConfig* lProxy; - linphone_core_get_default_proxy(mCore, &lProxy); - if (lProxy) { - linphone_proxy_config_edit(lProxy); - linphone_proxy_config_enable_register(lProxy,TRUE); - linphone_proxy_config_done(lProxy); - } - + // register + registration(); } } @@ -320,7 +336,7 @@ void TunnelManager::enableLogs(bool isEnabled,LogHandler logHandler) { SetLogLevel(TUNNEL_ERROR|TUNNEL_WARN); } } - + bool TunnelManager::isEnabled() { return mEnabled; @@ -336,7 +352,7 @@ void TunnelManager::processUdpMirrorEvent(const Event &ev){ if (mCurrentUdpMirrorClient !=mUdpMirrorClients.end()) { // enable tunnel but also try backup server LOGI("Tunnel is required, enabling; Trying backup udp mirror"); - + UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient; lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this); } else { @@ -375,7 +391,7 @@ void TunnelManager::autoDetect() { mCurrentUdpMirrorClient =mUdpMirrorClients.begin(); UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient; lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this); - + } void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) { diff --git a/coreapi/TunnelManager.hh b/coreapi/TunnelManager.hh index 9ca29ad86..adf4fa954 100644 --- a/coreapi/TunnelManager.hh +++ b/coreapi/TunnelManager.hh @@ -1,7 +1,7 @@ /* * C Implementation: tunnel * - * Description: + * Description: * * * @@ -25,22 +25,22 @@ namespace belledonnecomm { class TunnelClient; class UdpMirrorClient; /** - * @addtogroup tunnel_client + * @addtogroup tunnel_client * @{ **/ /** - * The TunnelManager class extends the LinphoneCore functionnality in order to provide an easy to use API to + * 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. @@ -61,13 +61,13 @@ class UdpMirrorClient; 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. @@ -156,6 +156,7 @@ class UdpMirrorClient; static void tunnelCallback(bool connected, TunnelManager *zis); static void sOnIterate(TunnelManager *zis); static void sUdpMirrorClientCallback(bool result, void* data); + void registration(); void waitUnRegistration(); void processTunnelEvent(const Event &ev); void processUdpMirrorEvent(const Event &ev); @@ -185,6 +186,7 @@ class UdpMirrorClient; std::string mHttpProxyHost; int mHttpProxyPort; LinphoneFirewallPolicy mPreviousFirewallPolicy; + bool mPreviousRegistrationEnabled; }; /**