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:
Simon Morlat 2016-08-18 18:48:20 +02:00
parent b05492078d
commit 3a1dacbdf4
7 changed files with 214 additions and 135 deletions

View file

@ -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)

View file

@ -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");
if (!mTunnelClient){
mTunnelClient = new TunnelClient(TRUE); mTunnelClient = new TunnelClient(TRUE);
mTunnelClient->setCallback((TunnelClientController::StateCallback)tunnelCallback,this); 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());
if (!mTunnelClient->isStarted())
mTunnelClient->start(); mTunnelClient->start();
sal_set_tunnel(mCore->sal, mTunnelClient); 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::processTunnelEvent(const Event &ev){ void TunnelManager::tunnelizeLiblinphone(){
if (ev.mData.mConnected){ ms_message("LinphoneCore goes into tunneled mode.");
ms_message("TunnelManager: tunnel is connected"); mState = On; /*do this first because _linphone_core_apply_transports() will use it to know if tunnel listening point is to be used*/
if(mState == connecting) {
linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories); linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
mState = ready;
if (mTunnelizeSipPackets) { if (mTunnelizeSipPackets) {
doUnregistration(); doUnregistration();
_linphone_core_apply_transports(mCore); _linphone_core_apply_transports(mCore);
doRegistration(); 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){
if (ev.mData.mConnected){
ms_message("TunnelManager: tunnel is connected");
applyState();
} 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) {
linphone_core_get_local_ip_for(AF_INET, NULL,tunnel->mLocalAddr);
if (tunnel->getMode() == LinphoneTunnelModeAuto){
tunnel->startAutoDetection(); tunnel->startAutoDetection();
tunnel->mState = autodetecting; /*autodetection will call applyState() when finished*/
} else if (!reachable && tunnel->mState == autodetecting) { }else{
// if network is no more reachable, cancel autodetection tunnel->applyState();
for(UdpMirrorClientList::iterator udpMirror = tunnel->mUdpMirrorClients.begin(); udpMirror != tunnel->mUdpMirrorClients.end(); udpMirror++) { }
} 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) {

View file

@ -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;
}; };

View file

@ -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

View file

@ -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);

View file

@ -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">&lt;b&gt;Configure tunnel&lt;/b&gt;</property> <property name="label" translatable="yes">&lt;b&gt;VoIP anti-blocking (tunnel server)&lt;/b&gt;</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">&lt;b&gt;Configure http proxy (optional)&lt;/b&gt;</property> <property name="label" translatable="yes">&lt;b&gt;Http proxy (optional)&lt;/b&gt;</property>
<property name="use_markup">True</property> <property name="use_markup">True</property>
</object> </object>
</child> </child>

View file

@ -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){