X-Git-Url: http://sjero.net/git/?p=linphone;a=blobdiff_plain;f=coreapi%2FTunnelManager.cc;h=409f9c42a83635c41ba6ff2890b7166aae46d9f6;hp=b8f1dae4890e4ca453c435d1bbf964cc3931218c;hb=5f0d5793b7e65a518076de6f8e253770503f8824;hpb=6068c49f486f546bcb08102223fd79e49f2e0172 diff --git a/coreapi/TunnelManager.cc b/coreapi/TunnelManager.cc index b8f1dae4..409f9c42 100644 --- a/coreapi/TunnelManager.cc +++ b/coreapi/TunnelManager.cc @@ -25,20 +25,22 @@ using namespace belledonnecomm; +using namespace ::std; 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){ @@ -57,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; @@ -100,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); } @@ -179,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){ @@ -204,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; @@ -240,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)) { @@ -268,6 +280,7 @@ void TunnelManager::processTunnelEvent(){ linphone_proxy_config_edit(lProxy); linphone_core_iterate(mCore); } + mReady=false; } } @@ -275,7 +288,7 @@ void TunnelManager::waitUnRegistration(){ LinphoneProxyConfig* lProxy; linphone_core_get_default_proxy(mCore, &lProxy); if (lProxy && linphone_proxy_config_get_state(lProxy)==LinphoneRegistrationOk) { - int i; + int i=0; linphone_proxy_config_edit(lProxy); //make sure unregister is sent and authenticated do{ @@ -294,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 @@ -306,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); @@ -323,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; @@ -343,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*/ @@ -356,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 @@ -372,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() { @@ -407,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); }