2 * C Implementation: tunnel
7 * Author: Simon Morlat <simon.morlat@linphone.org>, (C) 2009
9 * Copyright (C) 2010 Belledonne Comunications, Grenoble, France
14 #include "TunnelManager.hh"
16 #include "ortp/rtpsession.h"
17 #include "linphonecore.h"
18 #include "linphonecore_utils.h"
19 #include "eXosip2/eXosip_transport_hook.h"
20 #include "tunnel/udp_mirror.hh"
23 #include <android/log.h>
27 using namespace belledonnecomm;
29 Mutex TunnelManager::sMutex;
31 int TunnelManager::eXosipSendto(int fd,const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen,void* userdata){
32 TunnelManager* lTunnelMgr=(TunnelManager*)userdata;
35 if (lTunnelMgr->mSipSocket==NULL){
37 return len;//let ignore the error
39 err=lTunnelMgr->mSipSocket->sendto(buf,len,to,tolen);
44 int TunnelManager::eXosipRecvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen,void* userdata){
45 TunnelManager* lTunnelMgr=(TunnelManager*)userdata;
48 if (lTunnelMgr->mSipSocket==NULL){
50 return 0;//let ignore the error
52 err=lTunnelMgr->mSipSocket->recvfrom(buf,len,from,*fromlen);
57 int TunnelManager::eXosipSelect(int max_fds, fd_set *s1, fd_set *s2, fd_set *s3, struct timeval *tv,void* userdata){
58 struct timeval begin,cur;
59 TunnelManager* lTunnelMgr=(TunnelManager*)userdata;
60 if (tv!=0 && tv->tv_sec){
61 /*this is the select from udp.c, the one that is interesting to us*/
62 NativeSocket udp_fd=(NativeSocket)eXosip_get_udp_socket();
63 NativeSocket controlfd=(NativeSocket)eXosip_get_control_fd();
66 gettimeofday(&begin,NULL);
73 if (lTunnelMgr->mSipSocket!=NULL){
74 if (lTunnelMgr->mSipSocket->hasData()) {
76 /* we make exosip believe that it has udp data to read*/
82 gettimeofday(&cur,NULL);
83 if (cur.tv_sec-begin.tv_sec>tv->tv_sec) {
90 if (select(max_fds,s1,s2,s3,&abit)==1) {
96 /*select called from other places, only the control fd is present */
97 return select(max_fds,s1,s2,s3,tv);
102 void TunnelManager::addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay) {
104 mUdpMirrorClients.push_back(UdpMirrorClient(ServerAddr(ip,udpMirrorPort),delay));
107 void TunnelManager::addServer(const char *ip, int port) {
108 mServerAddrs.push_back(ServerAddr(ip,port));
109 if (mTunnelClient) mTunnelClient->addServer(ip,port);
112 void TunnelManager::cleanServers() {
113 mServerAddrs.clear();
115 UdpMirrorClientList::iterator it;
116 mAutoDetectStarted=false;
117 for (it = mUdpMirrorClients.begin(); it != mUdpMirrorClients.end();) {
118 UdpMirrorClient& s=*it++;
121 mUdpMirrorClients.clear();
122 if (mTunnelClient) mTunnelClient->cleanServers();
125 void TunnelManager::reconnect(){
127 mTunnelClient->reconnect();
130 void TunnelManager::setCallback(StateCallback cb, void *userdata) {
132 mCallbackData=userdata;
135 static void sCloseRtpTransport(RtpTransport *t, void *userData){
136 TunnelSocket *s=(TunnelSocket*)userData;
137 TunnelManager *manager=(TunnelManager*)s->getUserPointer();
138 manager->closeRtpTransport(t, s);
140 void TunnelManager::closeRtpTransport(RtpTransport *t, TunnelSocket *s){
141 mTunnelClient->closeSocket(s);
145 static RtpTransport *sCreateRtpTransport(void* userData, int port){
146 return ((TunnelManager *) userData)->createRtpTransport(port);
149 RtpTransport *TunnelManager::createRtpTransport(int port){
150 TunnelSocket *socket=mTunnelClient->createSocket(port);
151 socket->setUserPointer(this);
152 RtpTransport *t=ms_new0(RtpTransport,1);
154 t->t_recvfrom=customRecvfrom;
155 t->t_sendto=customSendto;
156 t->t_close=sCloseRtpTransport;
161 void TunnelManager::start() {
162 if (!mTunnelClient) {
163 mTunnelClient = new TunnelClient();
164 mTunnelClient->setCallback((StateCallback)tunnelCallback,this);
165 std::list<ServerAddr>::iterator it;
166 for(it=mServerAddrs.begin();it!=mServerAddrs.end();++it){
167 const ServerAddr &addr=*it;
168 mTunnelClient->addServer(addr.mAddr.c_str(), addr.mPort);
170 mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str());
172 mTunnelClient->start();
174 if (mSipSocket == NULL) mSipSocket =mTunnelClient->createSocket(5060);
177 bool TunnelManager::isStarted() {
178 return mTunnelClient != 0 && mTunnelClient->isStarted();
181 bool TunnelManager::isReady() const {
182 return mTunnelClient && mTunnelClient->isReady();
185 int TunnelManager::customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen){
189 ((TunnelSocket*)t->data)->sendto(msg->b_rptr,size,to,tolen);
193 int TunnelManager::customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen){
194 int err=((TunnelSocket*)t->data)->recvfrom(msg->b_wptr,msg->b_datap->db_lim-msg->b_datap->db_base,from,*fromlen);
195 if (err>0) return err;
200 TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController()
206 ,mAutoDetectStarted(false)
209 mExosipTransport.data=this;
210 mExosipTransport.recvfrom=eXosipRecvfrom;
211 mExosipTransport.sendto=eXosipSendto;
212 mExosipTransport.select=eXosipSelect;
214 linphone_core_add_iterate_hook(mCore,(LinphoneCoreIterateHook)sOnIterate,this);
215 mTransportFactories.audio_rtcp_func=sCreateRtpTransport;
216 mTransportFactories.audio_rtcp_func_data=this;
217 mTransportFactories.audio_rtp_func=sCreateRtpTransport;
218 mTransportFactories.audio_rtp_func_data=this;
219 mTransportFactories.video_rtcp_func=sCreateRtpTransport;
220 mTransportFactories.video_rtcp_func_data=this;
221 mTransportFactories.video_rtp_func=sCreateRtpTransport;
222 mTransportFactories.video_rtp_func_data=this;
225 TunnelManager::~TunnelManager(){
229 void TunnelManager::stopClient(){
230 eXosip_transport_hook_register(NULL);
231 if (mSipSocket != NULL){
233 mTunnelClient->closeSocket(mSipSocket);
238 delete mTunnelClient;
243 void TunnelManager::processTunnelEvent(){
244 LinphoneProxyConfig* lProxy;
245 linphone_core_get_default_proxy(mCore, &lProxy);
247 if (mEnabled && mTunnelClient->isReady()){
248 ms_message("Tunnel is up, registering now");
249 linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
250 eXosip_transport_hook_register(&mExosipTransport);
251 //force transport to udp
252 LCSipTransports lTransport;
254 lTransport.udp_port=15060;
255 lTransport.tcp_port=0;
256 lTransport.tls_port=0;
257 lTransport.dtls_port=0;
259 linphone_core_set_sip_transports(mCore, &lTransport);
262 linphone_proxy_config_done(lProxy);
264 }else if (mEnabled && !mTunnelClient->isReady()){
265 /* we got disconnected from the tunnel */
266 if (lProxy && linphone_proxy_config_is_registered(lProxy)) {
267 /*forces de-registration so that we register again when the tunnel is up*/
268 linphone_proxy_config_edit(lProxy);
269 linphone_core_iterate(mCore);
274 void TunnelManager::waitUnRegistration(){
275 LinphoneProxyConfig* lProxy;
276 linphone_core_get_default_proxy(mCore, &lProxy);
277 if (lProxy && linphone_proxy_config_get_state(lProxy)==LinphoneRegistrationOk) {
279 linphone_proxy_config_edit(lProxy);
280 //make sure unregister is sent and authenticated
282 linphone_core_iterate(mCore);
285 ms_message("tunnel: timeout for unregistration expired, giving up");
289 }while(linphone_proxy_config_get_state(lProxy)!=LinphoneRegistrationCleared);
293 void TunnelManager::enable(bool isEnable) {
294 ms_message("Turning tunnel [%s]",(isEnable?"on":"off"));
295 if (isEnable && !mEnabled){
298 linphone_core_get_sip_transports(mCore, &mRegularTransport);
300 waitUnRegistration();
303 }else if (!isEnable && mEnabled){
305 waitUnRegistration();
310 linphone_core_set_rtp_transport_factories(mCore,NULL);
312 eXosip_transport_hook_register(NULL);
314 linphone_core_set_sip_transports(mCore, &mRegularTransport);
316 LinphoneProxyConfig* lProxy;
317 linphone_core_get_default_proxy(mCore, &lProxy);
319 linphone_proxy_config_done(lProxy);
325 void TunnelManager::tunnelCallback(bool connected, TunnelManager *zis){
326 zis->mStateChanged=true;
329 /*invoked from linphone_core_iterate() */
330 void TunnelManager::sOnIterate(TunnelManager *zis){
331 if (zis->mStateChanged){
332 zis->mStateChanged=false;
333 zis->processTunnelEvent();
338 static void linphone_android_log_handler(int lev, const char *fmt, va_list args){
341 case TUNNEL_DEBUG: prio = ANDROID_LOG_DEBUG; break;
342 case TUNNEL_INFO: prio = ANDROID_LOG_INFO; break;
343 case TUNNEL_NOTICE: prio = ANDROID_LOG_INFO; break;
344 case TUNNEL_WARN: prio = ANDROID_LOG_WARN; break;
345 case TUNNEL_ERROR: prio = ANDROID_LOG_ERROR; break;
346 default: prio = ANDROID_LOG_DEFAULT; break;
348 __android_log_vprint(prio, LOG_DOMAIN, fmt, args);
352 void TunnelManager::enableLogs(bool value) {
353 enableLogs(value,NULL);
356 void TunnelManager::enableLogs(bool isEnabled,LogHandler logHandler) {
357 if (logHandler != NULL) SetLogHandler(logHandler);
359 else SetLogHandler(linphone_android_log_handler);
361 else SetLogHandler(default_log_handler);
365 SetLogLevel(TUNNEL_ERROR|TUNNEL_WARN|TUNNEL_INFO);
367 SetLogLevel(TUNNEL_ERROR|TUNNEL_WARN);
372 bool TunnelManager::isEnabled() {
375 void TunnelManager::UdpMirrorClientListener(bool isUdpAvailable, void* data) {
376 TunnelManager* thiz = (TunnelManager*)data;
377 if (isUdpAvailable) {
378 LOGI("Tunnel is not required, disabling");
380 thiz->mAutoDetectStarted = false;
382 if (++thiz->mCurrentUdpMirrorClient !=thiz->mUdpMirrorClients.end()) {
383 //1 enable tunnable but also try backup server
384 LOGI("Tunnel is required, enabling; Trying backup udp mirror");
386 UdpMirrorClient &lUdpMirrorClient=*thiz->mCurrentUdpMirrorClient;
387 lUdpMirrorClient.start(TunnelManager::UdpMirrorClientListener,(void*)thiz);
389 LOGI("Tunnel is required, enabling; no backup udp mirror available");
390 thiz->mAutoDetectStarted = false;
397 void TunnelManager::autoDetect() {
398 // first check if udp mirrors was provisionned
399 if (mUdpMirrorClients.empty()) {
400 LOGE("No UDP mirror server configured aborting auto detection");
403 if (mAutoDetectStarted) {
404 LOGE("auto detection already in progress, restarting");
405 (*mCurrentUdpMirrorClient).stop();
407 mAutoDetectStarted=true;
408 mCurrentUdpMirrorClient =mUdpMirrorClients.begin();
409 UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
410 lUdpMirrorClient.start(TunnelManager::UdpMirrorClientListener,(void*)this);
414 void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) {
415 mHttpUserName=username?username:"";
416 mHttpPasswd=passwd?passwd:"";
417 if (mTunnelClient) mTunnelClient->setHttpProxyAuthInfo(username,passwd);
420 void TunnelManager::setHttpProxy(const char *host,int port, const char *username, const char *passwd){
421 mHttpUserName=username?username:"";
422 mHttpPasswd=passwd?passwd:"";
423 mHttpProxyPort=(port>0) ? port : 0;
424 mHttpProxyHost=host ? host : "";
425 if (mTunnelClient) mTunnelClient->setHttpProxy(host, port, username, passwd);
428 LinphoneCore *TunnelManager::getLinphoneCore(){