mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-04-20 19:18:31 +00:00
big rework of Tunnel management
- better integration with network reachability callback - fix crashes (mTunnelClient can no longer be NULL) - avoid useless operations during transcient states - clarify source code - allow the application to set root_ca before the tunnel connection actually starts.
This commit is contained in:
parent
b05492078d
commit
3a1dacbdf4
7 changed files with 214 additions and 135 deletions
|
|
@ -879,7 +879,7 @@ AC_ARG_ENABLE(tunnel,
|
||||||
)
|
)
|
||||||
AM_CONDITIONAL(BUILD_TUNNEL, test x$enable_tunnel = xtrue)
|
AM_CONDITIONAL(BUILD_TUNNEL, test x$enable_tunnel = xtrue)
|
||||||
if test x$enable_tunnel = xtrue; then
|
if test x$enable_tunnel = xtrue; then
|
||||||
PKG_CHECK_MODULES(TUNNEL, tunnel >= 0.3.3)
|
PKG_CHECK_MODULES(TUNNEL, tunnel >= 0.6.0)
|
||||||
AC_DEFINE(TUNNEL_ENABLED,1,[Tells tunnel extension is built-in])
|
AC_DEFINE(TUNNEL_ENABLED,1,[Tells tunnel extension is built-in])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -938,12 +938,12 @@ if test x$enable_sqlite_storage != xfalse; then
|
||||||
if test "$build_macos" = "yes" -o "$ios_found" = "yes"; then
|
if test "$build_macos" = "yes" -o "$ios_found" = "yes"; then
|
||||||
SQLITE3_LIBS+=" -liconv"
|
SQLITE3_LIBS+=" -liconv"
|
||||||
fi
|
fi
|
||||||
enable_msg_storage=true
|
enable_sqlite_storage=true
|
||||||
else
|
else
|
||||||
if test x$enable_sqlite_storage = xtrue; then
|
if test x$enable_sqlite_storage = xtrue; then
|
||||||
AC_MSG_ERROR([sqlite3, required for storage, not found])
|
AC_MSG_ERROR([sqlite3, required for storage, not found])
|
||||||
fi
|
fi
|
||||||
enable_msg_storage=false
|
enable_sqlite_storage=false
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_SUBST(SQLITE3_CFLAGS)
|
AC_SUBST(SQLITE3_CFLAGS)
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ using namespace ::std;
|
||||||
|
|
||||||
void TunnelManager::addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay) {
|
void TunnelManager::addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay) {
|
||||||
if (ip == NULL) {
|
if (ip == NULL) {
|
||||||
ip = "";
|
|
||||||
ms_warning("Adding tunnel server with empty ip, it will not work!");
|
ms_warning("Adding tunnel server with empty ip, it will not work!");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
addServer(ip,port);
|
addServer(ip,port);
|
||||||
mUdpMirrorClients.push_back(UdpMirrorClient(ServerAddr(ip,udpMirrorPort),delay));
|
mUdpMirrorClients.push_back(UdpMirrorClient(ServerAddr(ip,udpMirrorPort),delay));
|
||||||
|
|
@ -38,8 +38,8 @@ void TunnelManager::addServer(const char *ip, int port,unsigned int udpMirrorPor
|
||||||
|
|
||||||
void TunnelManager::addServer(const char *ip, int port) {
|
void TunnelManager::addServer(const char *ip, int port) {
|
||||||
if (ip == NULL) {
|
if (ip == NULL) {
|
||||||
ip = "";
|
|
||||||
ms_warning("Adding tunnel server with empty ip, it will not work!");
|
ms_warning("Adding tunnel server with empty ip, it will not work!");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
mServerAddrs.push_back(ServerAddr(ip,port));
|
mServerAddrs.push_back(ServerAddr(ip,port));
|
||||||
if (mTunnelClient) mTunnelClient->addServer(ip,port);
|
if (mTunnelClient) mTunnelClient->addServer(ip,port);
|
||||||
|
|
@ -57,6 +57,7 @@ void TunnelManager::cleanServers() {
|
||||||
s.stop();
|
s.stop();
|
||||||
}
|
}
|
||||||
mUdpMirrorClients.clear();
|
mUdpMirrorClients.clear();
|
||||||
|
mCurrentUdpMirrorClient = mUdpMirrorClients.end();
|
||||||
if (mTunnelClient) mTunnelClient->cleanServers();
|
if (mTunnelClient) mTunnelClient->cleanServers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,8 +99,12 @@ RtpTransport *TunnelManager::createRtpTransport(int port){
|
||||||
|
|
||||||
void TunnelManager::startClient() {
|
void TunnelManager::startClient() {
|
||||||
ms_message("TunnelManager: Starting tunnel client");
|
ms_message("TunnelManager: Starting tunnel client");
|
||||||
mTunnelClient = new TunnelClient(TRUE);
|
if (!mTunnelClient){
|
||||||
mTunnelClient->setCallback((TunnelClientController::StateCallback)tunnelCallback,this);
|
mTunnelClient = new TunnelClient(TRUE);
|
||||||
|
sal_set_tunnel(mCore->sal, mTunnelClient);
|
||||||
|
mTunnelClient->setCallback(tunnelCallback,this);
|
||||||
|
}
|
||||||
|
|
||||||
if (mVerifyServerCertificate) {
|
if (mVerifyServerCertificate) {
|
||||||
const char *rootCertificatePath = linphone_core_get_root_ca(mCore);
|
const char *rootCertificatePath = linphone_core_get_root_ca(mCore);
|
||||||
if (rootCertificatePath != NULL) {
|
if (rootCertificatePath != NULL) {
|
||||||
|
|
@ -109,14 +114,29 @@ void TunnelManager::startClient() {
|
||||||
ms_warning("TunnelManager is set to verify server certificate but no root certificate is available in linphoneCore");
|
ms_warning("TunnelManager is set to verify server certificate but no root certificate is available in linphoneCore");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mTunnelClient->cleanServers();
|
||||||
list<ServerAddr>::iterator it;
|
list<ServerAddr>::iterator it;
|
||||||
for(it=mServerAddrs.begin();it!=mServerAddrs.end();++it){
|
for(it=mServerAddrs.begin();it!=mServerAddrs.end();++it){
|
||||||
const ServerAddr &addr=*it;
|
const ServerAddr &addr=*it;
|
||||||
mTunnelClient->addServer(addr.mAddr.c_str(), addr.mPort);
|
mTunnelClient->addServer(addr.mAddr.c_str(), addr.mPort);
|
||||||
}
|
}
|
||||||
mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str());
|
mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str());
|
||||||
mTunnelClient->start();
|
if (!mTunnelClient->isStarted())
|
||||||
sal_set_tunnel(mCore->sal, mTunnelClient);
|
mTunnelClient->start();
|
||||||
|
else
|
||||||
|
mTunnelClient->reconnect(); /*force a reconnection to take into account new parameters*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunnelManager::stopClient(){
|
||||||
|
if (linphone_core_get_calls_nb(mCore) == 0){
|
||||||
|
/*if no calls are running, we can decide to stop the client completely, so that the connection to the tunnel server is terminated.*/
|
||||||
|
if (mTunnelClient) {
|
||||||
|
ms_message("TunnelManager: stoppping tunnel client");
|
||||||
|
mTunnelClient->stop();
|
||||||
|
}
|
||||||
|
/*otherwise, it doesn't really matter if the tunnel connection is kept alive even if it is not used anymore by the liblinphone.*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TunnelManager::isConnected() const {
|
bool TunnelManager::isConnected() const {
|
||||||
|
|
@ -145,8 +165,6 @@ int TunnelManager::customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flag
|
||||||
TunnelManager::TunnelManager(LinphoneCore* lc) :
|
TunnelManager::TunnelManager(LinphoneCore* lc) :
|
||||||
mCore(lc),
|
mCore(lc),
|
||||||
mMode(LinphoneTunnelModeDisable),
|
mMode(LinphoneTunnelModeDisable),
|
||||||
mState(disabled),
|
|
||||||
mTunnelizeSipPackets(true),
|
|
||||||
mTunnelClient(NULL),
|
mTunnelClient(NULL),
|
||||||
mHttpProxyPort(0),
|
mHttpProxyPort(0),
|
||||||
mVTable(NULL),
|
mVTable(NULL),
|
||||||
|
|
@ -166,6 +184,11 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :
|
||||||
mVTable->network_reachable = networkReachableCb;
|
mVTable->network_reachable = networkReachableCb;
|
||||||
linphone_core_add_listener(mCore, mVTable);
|
linphone_core_add_listener(mCore, mVTable);
|
||||||
linphone_core_get_local_ip_for(AF_INET, NULL, mLocalAddr);
|
linphone_core_get_local_ip_for(AF_INET, NULL, mLocalAddr);
|
||||||
|
mAutodetectionRunning = false;
|
||||||
|
mState = Off;
|
||||||
|
mTargetState = Off;
|
||||||
|
mStarted = false;
|
||||||
|
mTunnelizeSipPackets = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TunnelManager::~TunnelManager(){
|
TunnelManager::~TunnelManager(){
|
||||||
|
|
@ -176,7 +199,11 @@ TunnelManager::~TunnelManager(){
|
||||||
for(UdpMirrorClientList::iterator udpMirror = mUdpMirrorClients.begin(); udpMirror != mUdpMirrorClients.end(); udpMirror++) {
|
for(UdpMirrorClientList::iterator udpMirror = mUdpMirrorClients.begin(); udpMirror != mUdpMirrorClients.end(); udpMirror++) {
|
||||||
udpMirror->stop();
|
udpMirror->stop();
|
||||||
}
|
}
|
||||||
if(mTunnelClient) delete mTunnelClient;
|
stopClient();
|
||||||
|
if (mTunnelClient) {
|
||||||
|
mTunnelClient->stop();
|
||||||
|
delete mTunnelClient;
|
||||||
|
}
|
||||||
sal_set_tunnel(mCore->sal,NULL);
|
sal_set_tunnel(mCore->sal,NULL);
|
||||||
linphone_core_remove_listener(mCore, mVTable);
|
linphone_core_remove_listener(mCore, mVTable);
|
||||||
linphone_core_v_table_destroy(mVTable);
|
linphone_core_v_table_destroy(mVTable);
|
||||||
|
|
@ -199,80 +226,99 @@ void TunnelManager::doUnregistration() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void TunnelManager::processTunnelEvent(const Event &ev){
|
void TunnelManager::processTunnelEvent(const Event &ev){
|
||||||
if (ev.mData.mConnected){
|
if (ev.mData.mConnected){
|
||||||
ms_message("TunnelManager: tunnel is connected");
|
ms_message("TunnelManager: tunnel is connected");
|
||||||
if(mState == connecting) {
|
applyState();
|
||||||
linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
|
|
||||||
mState = ready;
|
|
||||||
if(mTunnelizeSipPackets) {
|
|
||||||
doUnregistration();
|
|
||||||
_linphone_core_apply_transports(mCore);
|
|
||||||
doRegistration();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ms_error("TunnelManager: tunnel has been disconnected");
|
ms_error("TunnelManager: tunnel has been disconnected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunnelManager::setMode(LinphoneTunnelMode mode) {
|
void TunnelManager::applyMode() {
|
||||||
if(mMode == mode) return;
|
switch(mMode) {
|
||||||
if((mode==LinphoneTunnelModeDisable && mState==disabled)
|
|
||||||
|| (mode==LinphoneTunnelModeEnable && mState==ready)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ms_message("TunnelManager: switching mode from %s to %s",
|
|
||||||
linphone_tunnel_mode_to_string(mMode),
|
|
||||||
linphone_tunnel_mode_to_string(mode));
|
|
||||||
switch(mode) {
|
|
||||||
case LinphoneTunnelModeEnable:
|
case LinphoneTunnelModeEnable:
|
||||||
if(mState == disabled) {
|
stopAutoDetection();
|
||||||
startClient();
|
setState(On);
|
||||||
mState = connecting;
|
|
||||||
mMode = mode;
|
|
||||||
} else {
|
|
||||||
ms_error("TunnelManager: could not change mode. Bad state");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case LinphoneTunnelModeDisable:
|
case LinphoneTunnelModeDisable:
|
||||||
if(mState == ready) {
|
stopAutoDetection();
|
||||||
linphone_core_set_rtp_transport_factories(mCore,NULL);
|
setState(Off);
|
||||||
mState = disabled;
|
|
||||||
mMode = mode;
|
|
||||||
if(mTunnelizeSipPackets) {
|
|
||||||
doUnregistration();
|
|
||||||
_linphone_core_apply_transports(mCore);
|
|
||||||
}
|
|
||||||
sal_set_tunnel(mCore->sal,NULL);
|
|
||||||
delete mTunnelClient;
|
|
||||||
mTunnelClient=NULL;
|
|
||||||
} else {
|
|
||||||
ms_error("TunnelManager: could not change mode. Bad state");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case LinphoneTunnelModeAuto:
|
case LinphoneTunnelModeAuto:
|
||||||
if(mState == disabled || mState == ready) {
|
if (linphone_core_is_network_reachable(mCore)) startAutoDetection();
|
||||||
if(startAutoDetection()) {
|
|
||||||
mState = autodetecting;
|
|
||||||
mMode = mode;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ms_error("TunnelManager: could not change mode. Bad state");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ms_error("TunnelManager::setMode(): invalid mode (%d)", mode);
|
ms_error("TunnelManager::setMode(): invalid mode (%d)", (int)mMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunnelManager::tunnelCallback(bool connected, TunnelManager *zis){
|
|
||||||
Event ev;
|
void TunnelManager::setMode(LinphoneTunnelMode mode) {
|
||||||
if (zis->mLongRunningTaskId > 0) {
|
if(mMode == mode) return;
|
||||||
sal_end_background_task(zis->mLongRunningTaskId);
|
ms_message("TunnelManager: switching mode from %s to %s",
|
||||||
zis->mLongRunningTaskId = 0;
|
linphone_tunnel_mode_to_string(mMode),
|
||||||
|
linphone_tunnel_mode_to_string(mode));
|
||||||
|
mMode = mode;
|
||||||
|
applyMode();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunnelManager::stopLongRunningTask() {
|
||||||
|
if (mLongRunningTaskId != 0) {
|
||||||
|
sal_end_background_task(mLongRunningTaskId);
|
||||||
|
mLongRunningTaskId = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TunnelManager::tunnelCallback(bool connected, void *user_pointer){
|
||||||
|
TunnelManager *zis = static_cast<TunnelManager*>(user_pointer);
|
||||||
|
Event ev;
|
||||||
|
|
||||||
ev.mType=TunnelEvent;
|
ev.mType=TunnelEvent;
|
||||||
ev.mData.mConnected=connected;
|
ev.mData.mConnected=connected;
|
||||||
zis->postEvent(ev);
|
zis->postEvent(ev);
|
||||||
|
|
@ -344,7 +390,7 @@ LinphoneTunnelMode TunnelManager::getMode() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunnelManager::processUdpMirrorEvent(const Event &ev){
|
void TunnelManager::processUdpMirrorEvent(const Event &ev){
|
||||||
if(mState != autodetecting) return;
|
if (mAutodetectionRunning == false) return; /*auto detection was cancelled, for example by switching to disabled state*/
|
||||||
if (mSimulateUdpLoss || !ev.mData.mHaveUdp) {
|
if (mSimulateUdpLoss || !ev.mData.mHaveUdp) {
|
||||||
if (mSimulateUdpLoss) {
|
if (mSimulateUdpLoss) {
|
||||||
ms_message("TunnelManager: simulate UDP lost on %s:%d", mCurrentUdpMirrorClient->getServerAddress().mAddr.c_str(), mCurrentUdpMirrorClient->getServerAddress().mPort);
|
ms_message("TunnelManager: simulate UDP lost on %s:%d", mCurrentUdpMirrorClient->getServerAddress().mAddr.c_str(), mCurrentUdpMirrorClient->getServerAddress().mPort);
|
||||||
|
|
@ -354,30 +400,20 @@ void TunnelManager::processUdpMirrorEvent(const Event &ev){
|
||||||
mCurrentUdpMirrorClient++;
|
mCurrentUdpMirrorClient++;
|
||||||
if (mCurrentUdpMirrorClient !=mUdpMirrorClients.end()) {
|
if (mCurrentUdpMirrorClient !=mUdpMirrorClients.end()) {
|
||||||
ms_message("TunnelManager: trying another UDP mirror on %s:%d", mCurrentUdpMirrorClient->getServerAddress().mAddr.c_str(), mCurrentUdpMirrorClient->getServerAddress().mPort);
|
ms_message("TunnelManager: trying another UDP mirror on %s:%d", mCurrentUdpMirrorClient->getServerAddress().mAddr.c_str(), mCurrentUdpMirrorClient->getServerAddress().mPort);
|
||||||
if (mLongRunningTaskId == 0)
|
|
||||||
mLongRunningTaskId = sal_begin_background_task("Tunnel auto detect", NULL, NULL);
|
|
||||||
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
|
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
|
||||||
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
|
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
|
||||||
|
mAutodetectionRunning = true;
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
ms_message("TunnelManager: all UDP mirror tests failed");
|
ms_message("TunnelManager: all UDP mirror tests failed");
|
||||||
if(mTunnelClient==NULL) {
|
setState(On);
|
||||||
startClient();
|
|
||||||
mState = connecting;
|
|
||||||
} else {
|
|
||||||
mState = ready;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ms_message("TunnelManager: UDP mirror test succeed on %s:%d", mCurrentUdpMirrorClient->getServerAddress().mAddr.c_str(), mCurrentUdpMirrorClient->getServerAddress().mPort);
|
ms_message("TunnelManager: UDP mirror test success on %s:%d", mCurrentUdpMirrorClient->getServerAddress().mAddr.c_str(), mCurrentUdpMirrorClient->getServerAddress().mPort);
|
||||||
if(mTunnelClient) {
|
setState(Off);
|
||||||
if(mTunnelizeSipPackets) doUnregistration();
|
|
||||||
sal_set_tunnel(mCore->sal,NULL);
|
|
||||||
delete mTunnelClient;
|
|
||||||
mTunnelClient = NULL;
|
|
||||||
if(mTunnelizeSipPackets) doRegistration();
|
|
||||||
}
|
|
||||||
mState = disabled;
|
|
||||||
}
|
}
|
||||||
|
mAutodetectionRunning = false;
|
||||||
|
stopLongRunningTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunnelManager::postEvent(const Event &ev){
|
void TunnelManager::postEvent(const Event &ev){
|
||||||
|
|
@ -396,18 +432,32 @@ void TunnelManager::sUdpMirrorClientCallback(bool isUdpAvailable, void* data) {
|
||||||
|
|
||||||
void TunnelManager::networkReachableCb(LinphoneCore *lc, bool_t reachable) {
|
void TunnelManager::networkReachableCb(LinphoneCore *lc, bool_t reachable) {
|
||||||
TunnelManager *tunnel = bcTunnel(linphone_core_get_tunnel(lc));
|
TunnelManager *tunnel = bcTunnel(linphone_core_get_tunnel(lc));
|
||||||
if(reachable && tunnel->getMode() == LinphoneTunnelModeAuto && tunnel->mState != connecting && tunnel->mState != autodetecting) {
|
|
||||||
LOGI("TunnelManager: Network is now reachable, starting auto detection");
|
if (reachable) {
|
||||||
tunnel->startAutoDetection();
|
linphone_core_get_local_ip_for(AF_INET, NULL,tunnel->mLocalAddr);
|
||||||
tunnel->mState = autodetecting;
|
if (tunnel->getMode() == LinphoneTunnelModeAuto){
|
||||||
} else if (!reachable && tunnel->mState == autodetecting) {
|
tunnel->startAutoDetection();
|
||||||
// if network is no more reachable, cancel autodetection
|
/*autodetection will call applyState() when finished*/
|
||||||
for(UdpMirrorClientList::iterator udpMirror = tunnel->mUdpMirrorClients.begin(); udpMirror != tunnel->mUdpMirrorClients.end(); udpMirror++) {
|
}else{
|
||||||
|
tunnel->applyState();
|
||||||
|
}
|
||||||
|
} else if (!reachable) {
|
||||||
|
// if network is no more reachable, cancel autodetection if any
|
||||||
|
tunnel->stopAutoDetection();
|
||||||
|
//turn off the tunnel connection
|
||||||
|
tunnel->stopClient();
|
||||||
|
tunnel->untunnelizeLiblinphone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunnelManager::stopAutoDetection(){
|
||||||
|
if (mAutodetectionRunning){
|
||||||
|
for(UdpMirrorClientList::iterator udpMirror = mUdpMirrorClients.begin(); udpMirror != mUdpMirrorClients.end(); udpMirror++) {
|
||||||
udpMirror->stop();
|
udpMirror->stop();
|
||||||
}
|
}
|
||||||
tunnel->mState = disabled;
|
mAutodetectionRunning = false;
|
||||||
|
stopLongRunningTask();
|
||||||
}
|
}
|
||||||
linphone_core_get_local_ip_for(AF_INET, NULL,tunnel->mLocalAddr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TunnelManager::startAutoDetection() {
|
bool TunnelManager::startAutoDetection() {
|
||||||
|
|
@ -420,20 +470,13 @@ bool TunnelManager::startAutoDetection() {
|
||||||
if (mLongRunningTaskId == 0)
|
if (mLongRunningTaskId == 0)
|
||||||
mLongRunningTaskId = sal_begin_background_task("Tunnel auto detect", NULL, NULL);
|
mLongRunningTaskId = sal_begin_background_task("Tunnel auto detect", NULL, NULL);
|
||||||
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
|
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
|
||||||
|
mAutodetectionRunning = true;
|
||||||
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
|
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TunnelManager::isActivated() const{
|
bool TunnelManager::isActivated() const{
|
||||||
switch(getMode()){
|
return mState == On;
|
||||||
case LinphoneTunnelModeAuto:
|
|
||||||
return !(mState==disabled);
|
|
||||||
case LinphoneTunnelModeDisable:
|
|
||||||
return false;
|
|
||||||
case LinphoneTunnelModeEnable:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) {
|
void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) {
|
||||||
|
|
|
||||||
|
|
@ -159,13 +159,6 @@ namespace belledonnecomm {
|
||||||
void simulateUdpLoss(bool enabled);
|
void simulateUdpLoss(bool enabled);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum State {
|
|
||||||
disabled,
|
|
||||||
connecting,
|
|
||||||
ready,
|
|
||||||
autodetecting
|
|
||||||
};
|
|
||||||
|
|
||||||
enum EventType{
|
enum EventType{
|
||||||
UdpMirrorClientEvent,
|
UdpMirrorClientEvent,
|
||||||
TunnelEvent,
|
TunnelEvent,
|
||||||
|
|
@ -180,15 +173,16 @@ namespace belledonnecomm {
|
||||||
typedef std::list<UdpMirrorClient> UdpMirrorClientList;
|
typedef std::list<UdpMirrorClient> UdpMirrorClientList;
|
||||||
static int customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen);
|
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 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);
|
static void tunnelCallback(bool connected, void *zis);
|
||||||
static int eXosipRecvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen,void* userdata);
|
|
||||||
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 sOnIterate(TunnelManager *zis);
|
||||||
static void sUdpMirrorClientCallback(bool result, void* data);
|
static void sUdpMirrorClientCallback(bool result, void* data);
|
||||||
static void networkReachableCb(LinphoneCore *lc, bool_t reachable);
|
static void networkReachableCb(LinphoneCore *lc, bool_t reachable);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum State{
|
||||||
|
Off, /*no tunneling */
|
||||||
|
On /*tunneling activated*/
|
||||||
|
};
|
||||||
void onIterate();
|
void onIterate();
|
||||||
void doRegistration();
|
void doRegistration();
|
||||||
void doUnregistration();
|
void doUnregistration();
|
||||||
|
|
@ -197,13 +191,18 @@ namespace belledonnecomm {
|
||||||
void processTunnelEvent(const Event &ev);
|
void processTunnelEvent(const Event &ev);
|
||||||
void processUdpMirrorEvent(const Event &ev);
|
void processUdpMirrorEvent(const Event &ev);
|
||||||
void postEvent(const Event &ev);
|
void postEvent(const Event &ev);
|
||||||
|
void stopClient();
|
||||||
|
void stopAutoDetection();
|
||||||
|
void stopLongRunningTask();
|
||||||
|
void applyMode();
|
||||||
|
void setState(State state);
|
||||||
|
void applyState();
|
||||||
|
void tunnelizeLiblinphone();
|
||||||
|
void untunnelizeLiblinphone();
|
||||||
private:
|
private:
|
||||||
|
|
||||||
LinphoneCore* mCore;
|
LinphoneCore* mCore;
|
||||||
LinphoneTunnelMode mMode;
|
LinphoneTunnelMode mMode;
|
||||||
State mState;
|
|
||||||
bool mTunnelizeSipPackets;
|
|
||||||
bool mVerifyServerCertificate;
|
|
||||||
TunnelClient* mTunnelClient;
|
TunnelClient* mTunnelClient;
|
||||||
std::string mHttpUserName;
|
std::string mHttpUserName;
|
||||||
std::string mHttpPasswd;
|
std::string mHttpPasswd;
|
||||||
|
|
@ -218,6 +217,12 @@ namespace belledonnecomm {
|
||||||
std::queue<Event> mEvq;
|
std::queue<Event> mEvq;
|
||||||
char mLocalAddr[64];
|
char mLocalAddr[64];
|
||||||
unsigned long mLongRunningTaskId;
|
unsigned long mLongRunningTaskId;
|
||||||
|
State mTargetState;
|
||||||
|
State mState;
|
||||||
|
bool mVerifyServerCertificate;
|
||||||
|
bool mStarted;
|
||||||
|
bool mAutodetectionRunning;
|
||||||
|
bool mTunnelizeSipPackets;
|
||||||
bool mSimulateUdpLoss;
|
bool mSimulateUdpLoss;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -322,6 +322,7 @@ LINPHONE_PUBLIC void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const
|
||||||
*/
|
*/
|
||||||
LINPHONE_PUBLIC void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel*tunnel, const char* username,const char* passwd);
|
LINPHONE_PUBLIC void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel*tunnel, const char* username,const char* passwd);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether tunneling of SIP and RTP is required.
|
* Sets whether tunneling of SIP and RTP is required.
|
||||||
* @param tunnel object
|
* @param tunnel object
|
||||||
|
|
|
||||||
|
|
@ -1802,10 +1802,16 @@ void linphone_gtk_edit_tunnel(GtkButton *button){
|
||||||
if (port==0) port=443;
|
if (port==0) port=443;
|
||||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"port")), port);
|
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"port")), port);
|
||||||
|
|
||||||
if (linphone_tunnel_get_mode(tunnel)){
|
switch(linphone_tunnel_get_mode(tunnel)){
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_enable")),1);
|
case LinphoneTunnelModeDisable:
|
||||||
} else{
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_disable")),1);
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_disable")),1);
|
break;
|
||||||
|
case LinphoneTunnelModeEnable:
|
||||||
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_enable")),1);
|
||||||
|
break;
|
||||||
|
case LinphoneTunnelModeAuto:
|
||||||
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"tunnel_autodetect")),1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const char *proxy=NULL,*username=NULL,*password=NULL;
|
const char *proxy=NULL,*username=NULL,*password=NULL;
|
||||||
|
|
@ -1833,11 +1839,13 @@ void linphone_gtk_tunnel_ok(GtkButton *button){
|
||||||
|
|
||||||
gint port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"port")));
|
gint port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"port")));
|
||||||
gboolean enabled=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_enable")));
|
gboolean enabled=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_enable")));
|
||||||
|
gboolean autodetect=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"tunnel_autodetect")));
|
||||||
const char *host=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"host")));
|
const char *host=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"host")));
|
||||||
const char *http_host=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"http_host")));
|
const char *http_host=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"http_host")));
|
||||||
gint http_port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"http_port")));
|
gint http_port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"http_port")));
|
||||||
const char *username=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"username")));
|
const char *username=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"username")));
|
||||||
const char *password=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"password")));
|
const char *password=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"password")));
|
||||||
|
LinphoneTunnelMode mode = LinphoneTunnelModeDisable;
|
||||||
|
|
||||||
if (tunnel==NULL) return;
|
if (tunnel==NULL) return;
|
||||||
if (host && *host=='\0') host=NULL;
|
if (host && *host=='\0') host=NULL;
|
||||||
|
|
@ -1846,7 +1854,13 @@ void linphone_gtk_tunnel_ok(GtkButton *button){
|
||||||
linphone_tunnel_config_set_host(config, host);
|
linphone_tunnel_config_set_host(config, host);
|
||||||
linphone_tunnel_config_set_port(config, port);
|
linphone_tunnel_config_set_port(config, port);
|
||||||
linphone_tunnel_add_server(tunnel, config);
|
linphone_tunnel_add_server(tunnel, config);
|
||||||
linphone_tunnel_set_mode(tunnel, (enabled ? LinphoneTunnelModeEnable : LinphoneTunnelModeDisable));
|
|
||||||
|
if (enabled){
|
||||||
|
mode = LinphoneTunnelModeEnable;
|
||||||
|
}else if (autodetect){
|
||||||
|
mode = LinphoneTunnelModeAuto;
|
||||||
|
}
|
||||||
|
linphone_tunnel_set_mode(tunnel, mode);
|
||||||
linphone_tunnel_set_http_proxy(tunnel,http_host,http_port,username,password);
|
linphone_tunnel_set_http_proxy(tunnel,http_host,http_port,username,password);
|
||||||
|
|
||||||
gtk_widget_destroy(w);
|
gtk_widget_destroy(w);
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="n_rows">4</property>
|
<property name="n_rows">5</property>
|
||||||
<property name="n_columns">2</property>
|
<property name="n_columns">2</property>
|
||||||
<property name="homogeneous">True</property>
|
<property name="homogeneous">True</property>
|
||||||
<child>
|
<child>
|
||||||
|
|
@ -113,7 +113,7 @@
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkRadioButton" id="radio_enable">
|
<object class="GtkRadioButton" id="radio_enable">
|
||||||
<property name="label" translatable="yes">Enable</property>
|
<property name="label" translatable="yes">Enabled</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">False</property>
|
<property name="receives_default">False</property>
|
||||||
|
|
@ -132,7 +132,7 @@
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkRadioButton" id="radio_disable">
|
<object class="GtkRadioButton" id="radio_disable">
|
||||||
<property name="label" translatable="yes">Disable</property>
|
<property name="label" translatable="yes">Disabled</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">False</property>
|
<property name="receives_default">False</property>
|
||||||
|
|
@ -140,6 +140,26 @@
|
||||||
<property name="xalign">0</property>
|
<property name="xalign">0</property>
|
||||||
<property name="active">True</property>
|
<property name="active">True</property>
|
||||||
<property name="draw_indicator">True</property>
|
<property name="draw_indicator">True</property>
|
||||||
|
<property name="group">radio_enable</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="right_attach">2</property>
|
||||||
|
<property name="top_attach">4</property>
|
||||||
|
<property name="bottom_attach">5</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkRadioButton" id="tunnel_autodetect">
|
||||||
|
<property name="label" translatable="yes">Enable on purpose</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">False</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="active">True</property>
|
||||||
|
<property name="draw_indicator">True</property>
|
||||||
|
<property name="group">radio_enable</property>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">1</property>
|
<property name="left_attach">1</property>
|
||||||
|
|
@ -154,6 +174,9 @@
|
||||||
<child>
|
<child>
|
||||||
<placeholder/>
|
<placeholder/>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">True</property>
|
<property name="expand">True</property>
|
||||||
|
|
@ -170,7 +193,7 @@
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="label" translatable="yes"><b>Configure tunnel</b></property>
|
<property name="label" translatable="yes"><b>VoIP anti-blocking (tunnel server)</b></property>
|
||||||
<property name="use_markup">True</property>
|
<property name="use_markup">True</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
|
@ -315,7 +338,7 @@
|
||||||
<object class="GtkLabel" id="label2">
|
<object class="GtkLabel" id="label2">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="label" translatable="yes"><b>Configure http proxy (optional)</b></property>
|
<property name="label" translatable="yes"><b>Http proxy (optional)</b></property>
|
||||||
<property name="use_markup">True</property>
|
<property name="use_markup">True</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
|
|
||||||
|
|
@ -80,13 +80,6 @@ static void call_with_tunnel_base(LinphoneTunnelMode tunnel_mode, bool_t with_si
|
||||||
linphone_core_find_payload_type(pauline->lc, "speex", 16000, 1), TRUE);
|
linphone_core_find_payload_type(pauline->lc, "speex", 16000, 1), TRUE);
|
||||||
linphone_core_enable_payload_type(pauline->lc,
|
linphone_core_enable_payload_type(pauline->lc,
|
||||||
linphone_core_find_payload_type(pauline->lc, "G722", 8000, 1), TRUE);
|
linphone_core_find_payload_type(pauline->lc, "G722", 8000, 1), TRUE);
|
||||||
linphone_core_enable_payload_type(marie->lc,
|
|
||||||
linphone_core_find_payload_type(marie->lc, "speex", 32000, 1), TRUE);
|
|
||||||
linphone_core_enable_payload_type(marie->lc,
|
|
||||||
linphone_core_find_payload_type(marie->lc, "speex", 16000, 1), TRUE);
|
|
||||||
linphone_core_enable_payload_type(marie->lc,
|
|
||||||
linphone_core_find_payload_type(marie->lc, "G722", 8000, 1), TRUE);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tunnel_mode != LinphoneTunnelModeDisable){
|
if (tunnel_mode != LinphoneTunnelModeDisable){
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue