From b70085becb6f6838589d0179172366db6de20069 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Mon, 17 Sep 2012 15:57:11 +0200 Subject: [PATCH] set processing of tunnel udp mirror callback on main thread. --- coreapi/TunnelManager.cc | 68 +++++++++++++++++++++++++++------------ coreapi/TunnelManager.hh | 23 ++++++++++--- coreapi/linphone_tunnel.h | 27 ++++++++++++++-- 3 files changed, 91 insertions(+), 27 deletions(-) diff --git a/coreapi/TunnelManager.cc b/coreapi/TunnelManager.cc index e3c7e6595..2165a2bf4 100644 --- a/coreapi/TunnelManager.cc +++ b/coreapi/TunnelManager.cc @@ -212,7 +212,6 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController() 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; @@ -242,7 +241,7 @@ void TunnelManager::stopClient(){ } } -void TunnelManager::processTunnelEvent(){ +void TunnelManager::processTunnelEvent(const Event &ev){ LinphoneProxyConfig* lProxy; linphone_core_get_default_proxy(mCore, &lProxy); @@ -325,15 +324,31 @@ 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 @@ -374,26 +389,39 @@ 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 + 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() { @@ -409,7 +437,7 @@ void TunnelManager::autoDetect() { mAutoDetectStarted=true; mCurrentUdpMirrorClient =mUdpMirrorClients.begin(); UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient; - lUdpMirrorClient.start(TunnelManager::UdpMirrorClientListener,(void*)this); + lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this); } diff --git a/coreapi/TunnelManager.hh b/coreapi/TunnelManager.hh index 1fb55429e..6df99192a 100644 --- a/coreapi/TunnelManager.hh +++ b/coreapi/TunnelManager.hh @@ -130,9 +130,21 @@ class UdpMirrorClient; LinphoneCore *getLinphoneCore(); virtual void setHttpProxy(const char *host,int port, const char *username, const char *passwd); private: + enum EventType{ + UdpMirrorClientEvent, + TunnelEvent, + }; + struct Event{ + EventType mType; + union EventData{ + bool mConnected; + bool mHaveUdp; + }mData; + }; typedef std::list UdpMirrorClientList; virtual bool isStarted(); virtual bool isReady() const; + void onIterate(); 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); @@ -140,9 +152,11 @@ class UdpMirrorClient; 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); + static void sUdpMirrorClientCallback(bool result, void* data); void waitUnRegistration(); - void processTunnelEvent(); + void processTunnelEvent(const Event &ev); + void processUdpMirrorEvent(const Event &ev); + void postEvent(const Event &ev); LinphoneCore* mCore; LCSipTransports mRegularTransport; TunnelSocket *mSipSocket; @@ -150,19 +164,20 @@ class UdpMirrorClient; StateCallback mCallback; void * mCallbackData; bool mEnabled; - bool mStateChanged; + std::queue mEvq; std::list mServerAddrs; UdpMirrorClientList mUdpMirrorClients; UdpMirrorClientList::iterator mCurrentUdpMirrorClient; TunnelClient* mTunnelClient; void stopClient(); + Mutex mMutex; static Mutex sMutex; bool mAutoDetectStarted; LinphoneRtpTransportFactories mTransportFactories; std::string mHttpUserName; std::string mHttpPasswd; std::string mHttpProxyHost; - int mHttpProxyPort; + int mHttpProxyPort; }; /** diff --git a/coreapi/linphone_tunnel.h b/coreapi/linphone_tunnel.h index 5d78fe8f6..bb343008a 100644 --- a/coreapi/linphone_tunnel.h +++ b/coreapi/linphone_tunnel.h @@ -62,10 +62,10 @@ void linphone_tunnel_add_server(LinphoneTunnel *tunnel, const char *host, int po * @param tunnel object * @param host tunnel server ip address * @param port tunnel server tls port, recommended value is 443 - * @param remote_udp_mirror remote port on the tunnel server side used to test udp reachability + * @param remote_udp_mirror_port remote port on the tunnel server side used to test udp reachability * @param delay udp packet round trip delay in ms considered as acceptable. recommended value is 1000 ms. */ -void linphone_tunnel_add_server_and_mirror(LinphoneTunnel *tunnel, const char *host, int port, int remote_udp_mirror, int delay); +void linphone_tunnel_add_server_and_mirror(LinphoneTunnel *tunnel, const char *host, int port, int remote_udp_mirror_port, int delay); /** * @param tunnel object * returns a string of space separated list of host:port of tunnel server addresses @@ -98,16 +98,37 @@ bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel); **/ void linphone_tunnel_reconnect(LinphoneTunnel *tunnel); /** + * Start tunnel need detection. * @param tunnel object * 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 linphone_tunnel_auto_detect(LinphoneTunnel *tunnel); + +/** + * Set an optional http proxy to go through when connecting to tunnel server. + * @param tunnel LinphoneTunnel object + * @param host Http proxy host. + * @param port http proxy port. + * @param username optional http proxy username if the proxy request authentication. Currently only basic authentication is supported. Use NULL if not needed. + * @param password optional http proxy password. Use NULL if not needed. + **/ void linphone_tunnel_set_http_proxy(LinphoneTunnel *tunnel, const char *host, int port, const char* username,const char* passwd); -void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel*tunnel, const char* username,const char* passwd); + +/** + * Retrieve optional http proxy configuration previously set with linphone_tunnel_set_http_proxy(). + * @param tunnel LinphoneTunnel object + * @param host Http proxy host. + * @param port http proxy port. + * @param username optional http proxy username if the proxy request authentication. Currently only basic authentication is supported. Use NULL if not needed. + * @param password optional http proxy password. Use NULL if not needed. + **/ void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const char **host, int *port, const char **username, const char **passwd); +void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel*tunnel, const char* username,const char* passwd); + + void linphone_tunnel_enable_logs(LinphoneTunnel *tunnel, bool_t enabled); /**