]> sjero.net Git - linphone/blobdiff - coreapi/TunnelManager.cc
- do not register outside of tunnel when tunnel is activated but not yet connected.
[linphone] / coreapi / TunnelManager.cc
index 44d12251cc06d392ebcef0ebade6596d1aade5a2..409f9c42a83635c41ba6ff2890b7166aae46d9f6 100644 (file)
@@ -31,15 +31,16 @@ 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
+               return len;
        }
-       err=lTunnelMgr->mSipSocket->sendto(buf,len,to,tolen);
+       lTunnelMgr->mSipSocket->sendto(buf,len,to,tolen);
        sMutex.unlock();
-       return err;
+       //ignore the error in all cases, retransmissions might be successful.
+       return len;
 }
 
 int TunnelManager::eXosipRecvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen,void* userdata){
@@ -58,12 +59,12 @@ int TunnelManager::eXosipRecvfrom(int fd, void *buf, size_t len, int flags, stru
 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){
+       if (s1 && tv!=0 && tv->tv_sec){
                /*this is the select from udp.c, the one that is interesting to us*/
                NativeSocket udp_fd=(NativeSocket)eXosip_get_udp_socket();
                NativeSocket controlfd=(NativeSocket)eXosip_get_control_fd();
 
-               FD_ZERO(s1);            
+               FD_ZERO(s1);
                gettimeofday(&begin,NULL);
                do{
                        struct timeval abit;
@@ -101,11 +102,19 @@ int TunnelManager::eXosipSelect(int max_fds, fd_set *s1, fd_set *s2, fd_set *s3,
 
 
 void TunnelManager::addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay) {
+       if (ip == NULL) {
+               ip = "";
+               ms_warning("Adding tunnel server with empty ip, it will not work!");
+       }
        addServer(ip,port);
        mUdpMirrorClients.push_back(UdpMirrorClient(ServerAddr(ip,udpMirrorPort),delay));
 }
 
 void TunnelManager::addServer(const char *ip, int port) {
+       if (ip == NULL) {
+               ip = "";
+               ms_warning("Adding tunnel server with empty ip, it will not work!");
+       }
        mServerAddrs.push_back(ServerAddr(ip,port));
        if (mTunnelClient) mTunnelClient->addServer(ip,port);
 }
@@ -180,7 +189,7 @@ bool TunnelManager::isStarted() {
 }
 
 bool TunnelManager::isReady() const {
-       return mTunnelClient && mTunnelClient->isReady();
+       return mTunnelClient && mTunnelClient->isReady() && mReady;
 }
 
 int TunnelManager::customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen){
@@ -205,13 +214,13 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController()
 ,mEnabled(false)
 ,mTunnelClient(NULL)
 ,mAutoDetectStarted(false)
+,mReady(false)
 ,mHttpProxyPort(0){
 
        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;
@@ -241,27 +250,29 @@ void TunnelManager::stopClient(){
        }
 }
 
-void TunnelManager::processTunnelEvent(){
+void TunnelManager::processTunnelEvent(const Event &ev){
        LinphoneProxyConfig* lProxy;
        linphone_core_get_default_proxy(mCore, &lProxy);
 
        if (mEnabled && mTunnelClient->isReady()){
-               ms_message("Tunnel is up, registering now");            
+               ms_message("Tunnel is up, registering now");
+               linphone_core_set_firewall_policy(mCore,LinphonePolicyNoFirewall);
                linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
                eXosip_transport_hook_register(&mExosipTransport);
                //force transport to udp
                LCSipTransports lTransport;
                
-               lTransport.udp_port=15060;
+               lTransport.udp_port=(0xDFFF&random())+1024;
                lTransport.tcp_port=0;
                lTransport.tls_port=0;
                lTransport.dtls_port=0;
                
-               linphone_core_set_sip_transports(mCore, &lTransport);           
+               linphone_core_set_sip_transports(mCore, &lTransport);
                //register
                if (lProxy) {
                        linphone_proxy_config_done(lProxy);
                }
+               mReady=true;
        }else if (mEnabled && !mTunnelClient->isReady()){
                /* we got disconnected from the tunnel */
                if (lProxy && linphone_proxy_config_is_registered(lProxy)) {
@@ -269,6 +280,7 @@ void TunnelManager::processTunnelEvent(){
                        linphone_proxy_config_edit(lProxy);
                        linphone_core_iterate(mCore);
                }
+               mReady=false;
        }
 }
 
@@ -295,8 +307,9 @@ void TunnelManager::enable(bool isEnable) {
        ms_message("Turning tunnel [%s]",(isEnable?"on":"off"));
        if (isEnable && !mEnabled){
                mEnabled=true;
-               //1 save transport 
+               //1 save transport and firewall policy
                linphone_core_get_sip_transports(mCore, &mRegularTransport);
+               mPreviousFirewallPolicy=linphone_core_get_firewall_policy(mCore);
                //2 unregister
                waitUnRegistration();
                //3 insert tunnel
@@ -307,12 +320,13 @@ void TunnelManager::enable(bool isEnable) {
                
                mEnabled=false;
                stopClient();
-               
+               mReady=false;
                linphone_core_set_rtp_transport_factories(mCore,NULL);
 
                eXosip_transport_hook_register(NULL);
-               //Restore transport
+               //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);
@@ -324,19 +338,36 @@ void TunnelManager::enable(bool isEnable) {
 }
 
 void TunnelManager::tunnelCallback(bool connected, TunnelManager *zis){
-       zis->mStateChanged=true;
+       Event ev;
+       ev.mType=TunnelEvent;
+       ev.mData.mConnected=connected;
+       zis->postEvent(ev);
+}
+
+void TunnelManager::onIterate(){
+       mMutex.lock();
+       while(!mEvq.empty()){
+               Event ev=mEvq.front();
+               mEvq.pop();
+               mMutex.unlock();
+               if (ev.mType==TunnelEvent)
+                       processTunnelEvent(ev);
+               else if (ev.mType==UdpMirrorClientEvent){
+                       processUdpMirrorEvent(ev);
+               }
+               mMutex.lock();
+       }
+       mMutex.unlock();
 }
 
 /*invoked from linphone_core_iterate() */
 void TunnelManager::sOnIterate(TunnelManager *zis){
-       if (zis->mStateChanged){
-               zis->mStateChanged=false;
-               zis->processTunnelEvent();
-       }
+       zis->onIterate();
 }
 
 #ifdef ANDROID
-static void linphone_android_log_handler(int lev, const char *fmt, va_list args){
+extern void linphone_android_log_handler(int prio, const char *fmt, va_list args);
+static void linphone_android_tunnel_log_handler(int lev, const char *fmt, va_list args) {
        int prio;
        switch(lev){
        case TUNNEL_DEBUG:      prio = ANDROID_LOG_DEBUG;       break;
@@ -344,9 +375,9 @@ static void linphone_android_log_handler(int lev, const char *fmt, va_list args)
        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;
+       default:                prio = ANDROID_LOG_DEFAULT;     break;
        }
-       __android_log_vprint(prio, LOG_DOMAIN, fmt, args);
+       linphone_android_log_handler(prio, fmt, args);
 }
 #endif /*ANDROID*/
 
@@ -357,7 +388,7 @@ void TunnelManager::enableLogs(bool value) {
 void TunnelManager::enableLogs(bool isEnabled,LogHandler logHandler) {
        if (logHandler != NULL) SetLogHandler(logHandler);
 #ifdef ANDROID
-       else SetLogHandler(linphone_android_log_handler);
+       else SetLogHandler(linphone_android_tunnel_log_handler);
 #else
        else SetLogHandler(default_log_handler);
 #endif
@@ -373,26 +404,40 @@ void TunnelManager::enableLogs(bool isEnabled,LogHandler logHandler) {
 bool TunnelManager::isEnabled() {
        return mEnabled;
 }
-void TunnelManager::UdpMirrorClientListener(bool isUdpAvailable, void* data) {
-       TunnelManager* thiz = (TunnelManager*)data;
-       if (isUdpAvailable) {
+
+void TunnelManager::processUdpMirrorEvent(const Event &ev){
+       if (ev.mData.mHaveUdp) {
                LOGI("Tunnel is not required, disabling");
-               thiz->enable(false);
-               thiz->mAutoDetectStarted = false;
+               enable(false);
+               mAutoDetectStarted = false;
        } else {
-               if (++thiz->mCurrentUdpMirrorClient !=thiz->mUdpMirrorClients.end()) {
-                       //1 enable tunnable but also try backup server
+               mCurrentUdpMirrorClient++;
+               if (mCurrentUdpMirrorClient !=mUdpMirrorClients.end()) {
+                       // enable tunnel but also try backup server
                        LOGI("Tunnel is required, enabling; Trying backup udp mirror");
                        
-                       UdpMirrorClient &lUdpMirrorClient=*thiz->mCurrentUdpMirrorClient;
-                       lUdpMirrorClient.start(TunnelManager::UdpMirrorClientListener,(void*)thiz);
+                       UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
+                       lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
                } else {
                        LOGI("Tunnel is required, enabling; no backup udp mirror available");
-                       thiz->mAutoDetectStarted = false;
+                       mAutoDetectStarted = false;
                }
-               thiz->enable(true);
+               enable(true);
        }
-       return;
+}
+
+void TunnelManager::postEvent(const Event &ev){
+       mMutex.lock();
+       mEvq.push(ev);
+       mMutex.unlock();
+}
+
+void TunnelManager::sUdpMirrorClientCallback(bool isUdpAvailable, void* data) {
+       TunnelManager* thiz = (TunnelManager*)data;
+       Event ev;
+       ev.mType=UdpMirrorClientEvent;
+       ev.mData.mHaveUdp=isUdpAvailable;
+       thiz->postEvent(ev);
 }
 
 void TunnelManager::autoDetect() {
@@ -408,7 +453,7 @@ void TunnelManager::autoDetect() {
        mAutoDetectStarted=true;
        mCurrentUdpMirrorClient =mUdpMirrorClients.begin();
        UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
-       lUdpMirrorClient.start(TunnelManager::UdpMirrorClientListener,(void*)this);
+       lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
        
 }