TunnelManager.cc 17.1 KB
Newer Older
Guillaume Beraudo's avatar
Guillaume Beraudo committed
1 2 3
/*
 *  C Implementation: tunnel
 *
4
 * Description:
Guillaume Beraudo's avatar
Guillaume Beraudo committed
5 6 7 8 9 10 11 12 13 14 15 16
 *
 *
 * Author: Simon Morlat <simon.morlat@linphone.org>, (C) 2009
 *
 * Copyright (C) 2010  Belledonne Comunications, Grenoble, France
 *
 */


#include "TunnelManager.hh"

#include "ortp/rtpsession.h"
17 18
#include "linphone/core.h"
#include "linphone/core_utils.h"
19
#include "private.h"
Guillaume Beraudo's avatar
Guillaume Beraudo committed
20

21
#ifdef __ANDROID__
Guillaume Beraudo's avatar
Guillaume Beraudo committed
22 23 24
#include <android/log.h>
#endif

25
belledonnecomm::TunnelManager *bcTunnel(const LinphoneTunnel *tunnel);
Guillaume Beraudo's avatar
Guillaume Beraudo committed
26 27

using namespace belledonnecomm;
28
using namespace ::std;
Guillaume Beraudo's avatar
Guillaume Beraudo committed
29 30

void TunnelManager::addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay) {
31 32
	if (ip == NULL) {
		ms_warning("Adding tunnel server with empty ip, it will not work!");
33
		return;
34
	}
Guillaume Beraudo's avatar
Guillaume Beraudo committed
35
	addServer(ip,port);
36
	mUdpMirrorClients.push_back(UdpMirrorClient(ServerAddr(ip, (int)udpMirrorPort), delay));
Guillaume Beraudo's avatar
Guillaume Beraudo committed
37 38 39
}

void TunnelManager::addServer(const char *ip, int port) {
40 41
	if (ip == NULL) {
		ms_warning("Adding tunnel server with empty ip, it will not work!");
42
		return;
43
	}
44 45 46 47
	if (mUseDualClient) {
		ms_warning("TunnelManager is configured in dual mode, use addServerPair instead");
		return;
	}
48

Guillaume Beraudo's avatar
Guillaume Beraudo committed
49
	mServerAddrs.push_back(ServerAddr(ip,port));
50
	if (mTunnelClient && !mTunnelClient->isDualTunnelClient()) {
51
		static_cast<TunnelClient*>(mTunnelClient)->addServer(ip,port);
52 53 54
	}
}

55 56 57 58 59 60
void TunnelManager::addServerPair(const char *ip1, int port1, const char *ip2, int port2, unsigned int udpMirrorPort, unsigned int delay) {
	if (ip1 == NULL || ip2 == NULL) {
		ms_warning("Adding tunnel server with empty ip, it will not work!");
		return;
	}
	addServerPair(ip1, port1, ip2, port2);
61
	mUdpMirrorClients.push_back(UdpMirrorClient(ServerAddr(ip1, (int)udpMirrorPort), delay));
62 63
}

64 65 66 67 68 69 70 71 72
void TunnelManager::addServerPair(const char *ip1, int port1, const char *ip2, int port2) {
	if (ip1 == NULL || ip2 == NULL) {
		ms_warning("Adding tunnel server with empty ip, it will not work!");
		return;
	}
	if (!mUseDualClient) {
		ms_warning("TunnelManager is configured in single mode, use addServer instead");
		return;
	}
73

74
	mDualServerAddrs.push_back(DualServerAddr(ip1, port1, ip2, port2));
75
	if (mTunnelClient && mTunnelClient->isDualTunnelClient()) {
76
		static_cast<DualTunnelClient*>(mTunnelClient)->addServerPair(ip1, port1, ip2, port2);
77
	}
Guillaume Beraudo's avatar
Guillaume Beraudo committed
78 79 80 81
}

void TunnelManager::cleanServers() {
	mServerAddrs.clear();
82
	mDualServerAddrs.clear();
83 84 85 86
	if (mLongRunningTaskId > 0) {
		sal_end_background_task(mLongRunningTaskId);
		mLongRunningTaskId = 0;
	}
87 88
	for (auto &udpMirrorClient : mUdpMirrorClients)
		udpMirrorClient.stop();
Guillaume Beraudo's avatar
Guillaume Beraudo committed
89
	mUdpMirrorClients.clear();
90
	mCurrentUdpMirrorClient = mUdpMirrorClients.end();
Guillaume Beraudo's avatar
Guillaume Beraudo committed
91 92 93
	if (mTunnelClient) mTunnelClient->cleanServers();
}

94 95 96 97 98 99 100 101
void TunnelManager::enableDualMode(bool enable) {
	mUseDualClient = enable;
}

bool TunnelManager::isDualModeEnabled() {
	return mUseDualClient;
}

Guillaume Beraudo's avatar
Guillaume Beraudo committed
102 103 104 105 106
void TunnelManager::reconnect(){
	if (mTunnelClient)
		mTunnelClient->reconnect();
}

107
static void sCloseRtpTransport(RtpTransport *t){
108 109 110 111 112 113 114
	DualSocket *ds = (DualSocket *)t->data;
	TunnelSocket *sendSocket = ds->sendSocket;
	TunnelSocket *recvSocket = ds->recvSocket;
	TunnelManager *manager=(TunnelManager*)sendSocket->getUserPointer();
	manager->closeRtpTransport(t, sendSocket);
	manager->closeRtpTransport(t, recvSocket);
	ms_free(ds);
Guillaume Beraudo's avatar
Guillaume Beraudo committed
115
}
116 117
void TunnelManager::closeRtpTransport(RtpTransport *t, TunnelSocket *s){
	mTunnelClient->closeSocket(s);
Guillaume Beraudo's avatar
Guillaume Beraudo committed
118 119 120
}

static RtpTransport *sCreateRtpTransport(void* userData, int port){
Simon Morlat's avatar
Simon Morlat committed
121
	return ((TunnelManager *) userData)->createRtpTransport(port);
Guillaume Beraudo's avatar
Guillaume Beraudo committed
122 123
}

124 125 126 127
void sDestroyRtpTransport(RtpTransport *t){
	ms_free(t);
}

Guillaume Beraudo's avatar
Guillaume Beraudo committed
128
RtpTransport *TunnelManager::createRtpTransport(int port){
129 130 131 132 133 134 135 136 137 138 139 140
	DualSocket *dualSocket = ms_new0(DualSocket, 1);
	if (!mUseDualClient) {
		TunnelSocket *socket = ((TunnelClient *)mTunnelClient)->createSocket(port);
		socket->setUserPointer(this);
		dualSocket->sendSocket = socket;
		dualSocket->recvSocket = socket;
	} else {
		dualSocket->sendSocket = ((DualTunnelClient *)mTunnelClient)->createSocket(TunnelSendOnly, port);
		dualSocket->sendSocket->setUserPointer(this);
		dualSocket->recvSocket = ((DualTunnelClient *)mTunnelClient)->createSocket(TunnelRecvOnly, port);
		dualSocket->recvSocket->setUserPointer(this);
	}
141

142
	RtpTransport *t = ms_new0(RtpTransport,1);
Guillaume Beraudo's avatar
Guillaume Beraudo committed
143 144 145
	t->t_getsocket=NULL;
	t->t_recvfrom=customRecvfrom;
	t->t_sendto=customSendto;
146
	t->t_close=sCloseRtpTransport;
147
	t->t_destroy=sDestroyRtpTransport;
148
	t->data=dualSocket;
149
	ms_message("Creating tunnel RTP transport for local virtual port %i", port);
Guillaume Beraudo's avatar
Guillaume Beraudo committed
150 151 152
	return t;
}

153
void TunnelManager::startClient() {
François Grisez's avatar
François Grisez committed
154
	ms_message("TunnelManager: Starting tunnel client");
155 156 157 158 159 160
	if (!mTunnelClient) {
		if (mUseDualClient) {
			mTunnelClient = DualTunnelClient::create(TRUE);
		} else {
			mTunnelClient = TunnelClient::create(TRUE);
		}
161

162
		mCore->sal->setTunnel(mTunnelClient);
163
		if (!mUseDualClient) {
164
			static_cast<TunnelClient*>(mTunnelClient)->setCallback(tunnelCallback,this);
165
		} else {
166
			static_cast<DualTunnelClient*>(mTunnelClient)->setCallback(tunnelCallback2,this);
167
		}
168
	}
169

170 171 172 173 174 175 176 177 178
	if (mVerifyServerCertificate) {
		const char *rootCertificatePath = linphone_core_get_root_ca(mCore);
		if (rootCertificatePath != NULL) {
			ms_message("TunnelManager: Load root certificate from %s", rootCertificatePath);
			mTunnelClient->setRootCertificate(rootCertificatePath); /* give the path to root certificate to the tunnel client in order to be able to verify the server certificate */
		} else {
			ms_warning("TunnelManager is set to verify server certificate but no root certificate is available in linphoneCore");
		}
	}
179
	mTunnelClient->cleanServers();
180
	if (mUseDualClient) {
181
		list<DualServerAddr>::iterator it;
182
		for(it=mDualServerAddrs.begin();it!=mDualServerAddrs.end();++it){
183 184
			const DualServerAddr &addr=*it;
			static_cast<DualTunnelClient*>(mTunnelClient)->addServerPair(addr.mAddr1.c_str(), addr.mPort1, addr.mAddr2.c_str(), addr.mPort2);
185 186 187 188 189
		}
	} else {
		list<ServerAddr>::iterator it;
		for(it=mServerAddrs.begin();it!=mServerAddrs.end();++it){
			const ServerAddr &addr=*it;
190
			static_cast<TunnelClient*>(mTunnelClient)->addServer(addr.mAddr.c_str(), addr.mPort);
191
		}
Guillaume Beraudo's avatar
Guillaume Beraudo committed
192
	}
193

194
	mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str());
195 196
	if (!mTunnelClient->isStarted()) {
		ms_message("Starting tunnel client");
197
		mTunnelClient->start();
198 199 200
	}
	else {
		ms_message("Reconnecting tunnel client");
201
		mTunnelClient->reconnect(); /*force a reconnection to take into account new parameters*/
202
	}
203 204 205
}

void TunnelManager::stopClient(){
206 207 208 209 210 211
	if (mTunnelClient) {
		ms_message("TunnelManager: stoppping tunnel client");
		mTunnelClient->stop();
		
		/* We only delete the tunnel client if there is no call running */
		if (linphone_core_get_calls_nb(mCore) == 0){
212 213
			delete mTunnelClient;
			mTunnelClient = NULL;
214 215
		}
	}
Guillaume Beraudo's avatar
Guillaume Beraudo committed
216 217
}

218
bool TunnelManager::isConnected() const {
219
	return mTunnelClient != NULL && mTunnelClient->isReady();
Guillaume Beraudo's avatar
Guillaume Beraudo committed
220 221 222 223
}

int TunnelManager::customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen){
	int size;
224
	DualSocket *ds = (DualSocket *)t->data;
225 226 227
	msgpullup(msg, (size_t)-1);
	size = (int)msgdsize(msg);
	ds->sendSocket->sendto(msg->b_rptr, (size_t)size, to, tolen);
Guillaume Beraudo's avatar
Guillaume Beraudo committed
228 229 230 231
	return size;
}

int TunnelManager::customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen){
232
	DualSocket *ds = (DualSocket *)t->data;
jehan's avatar
jehan committed
233
	memset(&msg->recv_addr,0,sizeof(msg->recv_addr));
234
	long err=ds->recvSocket->recvfrom(msg->b_wptr, (size_t)(dblk_lim(msg->b_datap) - dblk_base(msg->b_datap)), from, *fromlen);
jehan's avatar
jehan committed
235
	//to make ice happy
236
	inet_aton(((TunnelManager*)(ds->recvSocket)->getUserPointer())->mLocalAddr,&msg->recv_addr.addr.ipi_addr);
237
	msg->recv_addr.family = AF_INET;
238
	msg->recv_addr.port = htons((unsigned short)(ds->recvSocket)->getPort());
239
	if (err>0) return (int)err;
Guillaume Beraudo's avatar
Guillaume Beraudo committed
240 241 242
	return 0;
}

243 244
TunnelManager::TunnelManager(LinphoneCore* lc) :
	mCore(lc),
245
	mMode(LinphoneTunnelModeDisable),
246 247
	mTunnelClient(NULL),
	mHttpProxyPort(0),
248
	mVTable(NULL),
249
	mLongRunningTaskId(0),
250 251
	mSimulateUdpLoss(false),
	mUseDualClient(false)
252
{
Guillaume Beraudo's avatar
Guillaume Beraudo committed
253 254 255 256 257 258 259 260 261
	linphone_core_add_iterate_hook(mCore,(LinphoneCoreIterateHook)sOnIterate,this);
	mTransportFactories.audio_rtcp_func=sCreateRtpTransport;
	mTransportFactories.audio_rtcp_func_data=this;
	mTransportFactories.audio_rtp_func=sCreateRtpTransport;
	mTransportFactories.audio_rtp_func_data=this;
	mTransportFactories.video_rtcp_func=sCreateRtpTransport;
	mTransportFactories.video_rtcp_func_data=this;
	mTransportFactories.video_rtp_func=sCreateRtpTransport;
	mTransportFactories.video_rtp_func_data=this;
262
	mVTable = linphone_core_v_table_new();
263
	mVTable->network_reachable = networkReachableCb;
264
	linphone_core_add_listener(mCore, mVTable);
jehan's avatar
jehan committed
265
	linphone_core_get_local_ip_for(AF_INET, NULL, mLocalAddr);
266 267 268 269 270
	mAutodetectionRunning = false;
	mState = Off;
	mTargetState = Off;
	mStarted = false;
	mTunnelizeSipPackets = true;
Guillaume Beraudo's avatar
Guillaume Beraudo committed
271 272 273
}

TunnelManager::~TunnelManager(){
274 275 276 277
	if (mLongRunningTaskId > 0) {
		sal_end_background_task(mLongRunningTaskId);
		mLongRunningTaskId = 0;
	}
278 279 280
	for(UdpMirrorClientList::iterator udpMirror = mUdpMirrorClients.begin(); udpMirror != mUdpMirrorClients.end(); udpMirror++) {
		udpMirror->stop();
	}
281
	stopClient();
282
	mCore->sal->setTunnel(NULL);
283
	linphone_core_remove_listener(mCore, mVTable);
284
	linphone_core_v_table_destroy(mVTable);
Guillaume Beraudo's avatar
Guillaume Beraudo committed
285 286
}

287
void TunnelManager::doRegistration(){
288
	LinphoneProxyConfig* lProxy;
jehan's avatar
jehan committed
289
	lProxy = linphone_core_get_default_proxy_config(mCore);
290 291 292 293 294 295 296 297
	if (lProxy) {
		ms_message("TunnelManager: New registration");
		lProxy->commit = TRUE;
	}
}

void TunnelManager::doUnregistration() {
	LinphoneProxyConfig *lProxy;
jehan's avatar
jehan committed
298
	lProxy = linphone_core_get_default_proxy_config(mCore);
299 300
	if(lProxy) {
		_linphone_proxy_config_unregister(lProxy);
301 302 303
	}
}

304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
void TunnelManager::tunnelizeLiblinphone(){
	ms_message("LinphoneCore goes into tunneled mode.");
	mState = On; /*do this first because _linphone_core_apply_transports() will use it to know if tunnel listening point is to be used*/
	linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
	if (mTunnelizeSipPackets) {
		doUnregistration();
		_linphone_core_apply_transports(mCore);
		doRegistration();
	}
}

void TunnelManager::untunnelizeLiblinphone(){
	ms_message("LinphoneCore leaves tunneled mode.");
	mState = Off;
	linphone_core_set_rtp_transport_factories(mCore, NULL);
	if (mTunnelizeSipPackets) {
		doUnregistration();
		_linphone_core_apply_transports(mCore);
		doRegistration();
	}
}

void TunnelManager::applyState() {
	if (!linphone_core_is_network_reachable(mCore)) return;
	if (mTargetState == On && mState == Off){
		if (!mTunnelClient || !mTunnelClient->isStarted()){
			startClient();
		}
		if (mTunnelClient->isReady()) tunnelizeLiblinphone();
	}else if (mTargetState == Off && mState == On){
		untunnelizeLiblinphone();
		stopClient();
	}
}

void TunnelManager::setState ( TunnelManager::State state ) {
	mTargetState = state;
	applyState();
}

344
void TunnelManager::processTunnelEvent(const Event &ev){
345
	if (ev.mData.mConnected){
346
		ms_message("TunnelManager: tunnel is connected");
347
		applyState();
348
	} else {
349
		ms_error("TunnelManager: tunnel has been disconnected");
Guillaume Beraudo's avatar
Guillaume Beraudo committed
350 351 352
	}
}

353 354
void TunnelManager::applyMode() {
	switch(mMode) {
355
	case LinphoneTunnelModeEnable:
356 357
		stopAutoDetection();
		setState(On);
358 359
		break;
	case LinphoneTunnelModeDisable:
360 361
		stopAutoDetection();
		setState(Off);
362 363
		break;
	case LinphoneTunnelModeAuto:
364
		if (linphone_core_is_network_reachable(mCore)) startAutoDetection();
365 366
		break;
	default:
367
		ms_error("TunnelManager::setMode(): invalid mode (%d)", (int)mMode);
Guillaume Beraudo's avatar
Guillaume Beraudo committed
368 369 370
	}
}

371 372 373 374 375 376 377
void TunnelManager::setMode(LinphoneTunnelMode mode) {
	if(mMode == mode) return;
	ms_message("TunnelManager: switching mode from %s to %s",
			   linphone_tunnel_mode_to_string(mMode),
			   linphone_tunnel_mode_to_string(mode));
	mMode = mode;
	applyMode();
378

379 380 381 382 383 384
}

void TunnelManager::stopLongRunningTask() {
	if (mLongRunningTaskId != 0) {
		sal_end_background_task(mLongRunningTaskId);
		mLongRunningTaskId = 0;
385
	}
386 387 388 389 390
}

void TunnelManager::tunnelCallback(bool connected, void *user_pointer){
	TunnelManager *zis = static_cast<TunnelManager*>(user_pointer);
	Event ev;
391

392 393 394 395 396
	ev.mType=TunnelEvent;
	ev.mData.mConnected=connected;
	zis->postEvent(ev);
}

397 398 399
void TunnelManager::tunnelCallback2(TunnelDirection direction, bool connected, void *user_pointer){
	TunnelManager *zis = static_cast<TunnelManager*>(user_pointer);
	Event ev;
400

401 402 403 404 405
	ev.mType=TunnelEvent;
	ev.mData.mConnected=connected;
	zis->postEvent(ev);
}

406 407 408 409 410 411 412 413 414 415 416 417 418 419
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();
Guillaume Beraudo's avatar
Guillaume Beraudo committed
420 421 422
}

/*invoked from linphone_core_iterate() */
423
bool_t TunnelManager::sOnIterate(TunnelManager *zis){
424
	zis->onIterate();
425
	return TRUE;
Guillaume Beraudo's avatar
Guillaume Beraudo committed
426 427
}

428 429
LinphoneTunnelMode TunnelManager::getMode() const {
	return mMode;
Guillaume Beraudo's avatar
Guillaume Beraudo committed
430
}
431 432

void TunnelManager::processUdpMirrorEvent(const Event &ev){
433
	if (mAutodetectionRunning == false) return; /*auto detection was cancelled, for example by switching to disabled state*/
434 435 436 437 438
	if (mSimulateUdpLoss || !ev.mData.mHaveUdp) {
		if (mSimulateUdpLoss) {
			ms_message("TunnelManager: simulate UDP lost on %s:%d", mCurrentUdpMirrorClient->getServerAddress().mAddr.c_str(), mCurrentUdpMirrorClient->getServerAddress().mPort);
		} else {
			ms_message("TunnelManager: UDP mirror test failed on %s:%d", mCurrentUdpMirrorClient->getServerAddress().mAddr.c_str(), mCurrentUdpMirrorClient->getServerAddress().mPort);
439
		}
440
		mCurrentUdpMirrorClient++;
441
		if (mCurrentUdpMirrorClient !=mUdpMirrorClients.end()) {
442
			ms_message("TunnelManager: trying another UDP mirror on %s:%d", mCurrentUdpMirrorClient->getServerAddress().mAddr.c_str(), mCurrentUdpMirrorClient->getServerAddress().mPort);
443 444
			UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
			lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
445 446
			mAutodetectionRunning = true;
			return;
Guillaume Beraudo's avatar
Guillaume Beraudo committed
447
		} else {
448
			ms_message("TunnelManager: all UDP mirror tests failed");
449
			setState(On);
Guillaume Beraudo's avatar
Guillaume Beraudo committed
450
		}
451
	} else {
452 453
		ms_message("TunnelManager: UDP mirror test success on %s:%d", mCurrentUdpMirrorClient->getServerAddress().mAddr.c_str(), mCurrentUdpMirrorClient->getServerAddress().mPort);
		setState(Off);
Guillaume Beraudo's avatar
Guillaume Beraudo committed
454
	}
455 456
	mAutodetectionRunning = false;
	stopLongRunningTask();
457 458 459 460 461 462 463 464 465 466 467 468 469 470
}

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);
Guillaume Beraudo's avatar
Guillaume Beraudo committed
471 472
}

473 474
void TunnelManager::networkReachableCb(LinphoneCore *lc, bool_t reachable) {
	TunnelManager *tunnel = bcTunnel(linphone_core_get_tunnel(lc));
475

476
	if (reachable) {
477
		ms_message("TunnelManager: Network is reachable, starting tunnel client");
478 479 480 481 482 483 484 485
		linphone_core_get_local_ip_for(AF_INET, NULL,tunnel->mLocalAddr);
		if (tunnel->getMode() == LinphoneTunnelModeAuto){
			tunnel->startAutoDetection();
			/*autodetection will call applyState() when finished*/
		}else{
			tunnel->applyState();
		}
	} else if (!reachable) {
486
		ms_message("TunnelManager: Network is unreachable, stopping tunnel client");
487 488 489 490
		// if network is no more reachable, cancel autodetection if any
		tunnel->stopAutoDetection();
		//turn off the tunnel connection
		tunnel->untunnelizeLiblinphone();
491
		tunnel->stopClient();
492 493 494 495 496 497
	}
}

void TunnelManager::stopAutoDetection(){
	if (mAutodetectionRunning){
		for(UdpMirrorClientList::iterator udpMirror = mUdpMirrorClients.begin(); udpMirror != mUdpMirrorClients.end(); udpMirror++) {
498 499
			udpMirror->stop();
		}
500 501
		mAutodetectionRunning = false;
		stopLongRunningTask();
502 503 504
	}
}

505
bool TunnelManager::startAutoDetection() {
Guillaume Beraudo's avatar
Guillaume Beraudo committed
506
	if (mUdpMirrorClients.empty()) {
François Grisez's avatar
François Grisez committed
507
		ms_error("TunnelManager: No UDP mirror server configured aborting auto detection");
508
		return false;
Guillaume Beraudo's avatar
Guillaume Beraudo committed
509
	}
510
	ms_message("TunnelManager: Starting auto-detection");
511
	mCurrentUdpMirrorClient = mUdpMirrorClients.begin();
512 513
	if (mLongRunningTaskId == 0)
		 mLongRunningTaskId = sal_begin_background_task("Tunnel auto detect", NULL, NULL);
Guillaume Beraudo's avatar
Guillaume Beraudo committed
514
	UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
515
	mAutodetectionRunning = true;
516
	lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
517
	return true;
Guillaume Beraudo's avatar
Guillaume Beraudo committed
518 519
}

520
bool TunnelManager::isActivated() const{
521
	return mState == On;
522 523
}

Guillaume Beraudo's avatar
Guillaume Beraudo committed
524
void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) {
jehan's avatar
jehan committed
525 526 527
	mHttpUserName=username?username:"";
	mHttpPasswd=passwd?passwd:"";
	if (mTunnelClient) mTunnelClient->setHttpProxyAuthInfo(username,passwd);
Guillaume Beraudo's avatar
Guillaume Beraudo committed
528 529
}

530
void TunnelManager::tunnelizeSipPackets(bool enable){
531
	mTunnelizeSipPackets = enable;
532 533
}

534 535 536 537
bool TunnelManager::tunnelizeSipPacketsEnabled() const {
	return mTunnelizeSipPackets;
}

538 539 540 541 542 543 544 545
void TunnelManager::verifyServerCertificate(bool enable){
	mVerifyServerCertificate = enable;
}

bool TunnelManager::verifyServerCertificateEnabled() const {
	return mVerifyServerCertificate;
}

546 547 548 549 550 551 552 553
void TunnelManager::setHttpProxy(const char *host,int port, const char *username, const char *passwd){
	mHttpUserName=username?username:"";
	mHttpPasswd=passwd?passwd:"";
	mHttpProxyPort=(port>0) ? port : 0;
	mHttpProxyHost=host ? host : "";
	if (mTunnelClient) mTunnelClient->setHttpProxy(host, port, username, passwd);
}

554
LinphoneCore *TunnelManager::getLinphoneCore() const{
Guillaume Beraudo's avatar
Guillaume Beraudo committed
555 556
	return mCore;
}
557 558 559 560

void TunnelManager::simulateUdpLoss(bool enabled) {
	mSimulateUdpLoss = enabled;
}