Commit 3a1dacbd authored by Simon Morlat's avatar Simon Morlat
Browse files

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.
parent b0549207
......@@ -879,7 +879,7 @@ AC_ARG_ENABLE(tunnel,
)
AM_CONDITIONAL(BUILD_TUNNEL, test x$enable_tunnel = xtrue)
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])
fi
......@@ -938,12 +938,12 @@ if test x$enable_sqlite_storage != xfalse; then
if test "$build_macos" = "yes" -o "$ios_found" = "yes"; then
SQLITE3_LIBS+=" -liconv"
fi
enable_msg_storage=true
enable_sqlite_storage=true
else
if test x$enable_sqlite_storage = xtrue; then
AC_MSG_ERROR([sqlite3, required for storage, not found])
fi
enable_msg_storage=false
enable_sqlite_storage=false
fi
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) {
if (ip == NULL) {
ip = "";
ms_warning("Adding tunnel server with empty ip, it will not work!");
return;
}
addServer(ip,port);
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) {
if (ip == NULL) {
ip = "";
ms_warning("Adding tunnel server with empty ip, it will not work!");
return;
}
mServerAddrs.push_back(ServerAddr(ip,port));
if (mTunnelClient) mTunnelClient->addServer(ip,port);
......@@ -57,6 +57,7 @@ void TunnelManager::cleanServers() {
s.stop();
}
mUdpMirrorClients.clear();
mCurrentUdpMirrorClient = mUdpMirrorClients.end();
if (mTunnelClient) mTunnelClient->cleanServers();
}
......@@ -98,8 +99,12 @@ RtpTransport *TunnelManager::createRtpTransport(int port){
void TunnelManager::startClient() {
ms_message("TunnelManager: Starting tunnel client");
mTunnelClient = new TunnelClient(TRUE);
mTunnelClient->setCallback((TunnelClientController::StateCallback)tunnelCallback,this);
if (!mTunnelClient){
mTunnelClient = new TunnelClient(TRUE);
sal_set_tunnel(mCore->sal, mTunnelClient);
mTunnelClient->setCallback(tunnelCallback,this);
}
if (mVerifyServerCertificate) {
const char *rootCertificatePath = linphone_core_get_root_ca(mCore);
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");
}
}
mTunnelClient->cleanServers();
list<ServerAddr>::iterator it;
for(it=mServerAddrs.begin();it!=mServerAddrs.end();++it){
const ServerAddr &addr=*it;
mTunnelClient->addServer(addr.mAddr.c_str(), addr.mPort);
}
mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str());
mTunnelClient->start();
sal_set_tunnel(mCore->sal, mTunnelClient);
if (!mTunnelClient->isStarted())
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 {
......@@ -145,8 +165,6 @@ int TunnelManager::customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flag
TunnelManager::TunnelManager(LinphoneCore* lc) :
mCore(lc),
mMode(LinphoneTunnelModeDisable),
mState(disabled),
mTunnelizeSipPackets(true),
mTunnelClient(NULL),
mHttpProxyPort(0),
mVTable(NULL),
......@@ -166,6 +184,11 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :
mVTable->network_reachable = networkReachableCb;
linphone_core_add_listener(mCore, mVTable);
linphone_core_get_local_ip_for(AF_INET, NULL, mLocalAddr);
mAutodetectionRunning = false;
mState = Off;
mTargetState = Off;
mStarted = false;
mTunnelizeSipPackets = true;
}
TunnelManager::~TunnelManager(){
......@@ -176,7 +199,11 @@ TunnelManager::~TunnelManager(){
for(UdpMirrorClientList::iterator udpMirror = mUdpMirrorClients.begin(); udpMirror != mUdpMirrorClients.end(); udpMirror++) {
udpMirror->stop();
}
if(mTunnelClient) delete mTunnelClient;
stopClient();
if (mTunnelClient) {
mTunnelClient->stop();
delete mTunnelClient;
}
sal_set_tunnel(mCore->sal,NULL);
linphone_core_remove_listener(mCore, 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){
if (ev.mData.mConnected){
ms_message("TunnelManager: tunnel is connected");
if(mState == connecting) {
linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
mState = ready;
if(mTunnelizeSipPackets) {
doUnregistration();
_linphone_core_apply_transports(mCore);
doRegistration();
}
}
applyState();
} else {
ms_error("TunnelManager: tunnel has been disconnected");
}
}
void TunnelManager::setMode(LinphoneTunnelMode mode) {
if(mMode == mode) return;
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) {
void TunnelManager::applyMode() {
switch(mMode) {
case LinphoneTunnelModeEnable:
if(mState == disabled) {
startClient();
mState = connecting;
mMode = mode;
} else {
ms_error("TunnelManager: could not change mode. Bad state");
}
stopAutoDetection();
setState(On);
break;
case LinphoneTunnelModeDisable:
if(mState == ready) {
linphone_core_set_rtp_transport_factories(mCore,NULL);
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");
}
stopAutoDetection();
setState(Off);
break;
case LinphoneTunnelModeAuto:
if(mState == disabled || mState == ready) {
if(startAutoDetection()) {
mState = autodetecting;
mMode = mode;
}
} else {
ms_error("TunnelManager: could not change mode. Bad state");
}
if (linphone_core_is_network_reachable(mCore)) startAutoDetection();
break;
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;
if (zis->mLongRunningTaskId > 0) {
sal_end_background_task(zis->mLongRunningTaskId);
zis->mLongRunningTaskId = 0;
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();
}
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.mData.mConnected=connected;
zis->postEvent(ev);
......@@ -344,7 +390,7 @@ LinphoneTunnelMode TunnelManager::getMode() const {
}
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) {
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++;
if (mCurrentUdpMirrorClient !=mUdpMirrorClients.end()) {
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;
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
mAutodetectionRunning = true;
return;
} else {
ms_message("TunnelManager: all UDP mirror tests failed");
if(mTunnelClient==NULL) {
startClient();
mState = connecting;
} else {
mState = ready;
}
setState(On);
}
} else {
ms_message("TunnelManager: UDP mirror test succeed on %s:%d", mCurrentUdpMirrorClient->getServerAddress().mAddr.c_str(), mCurrentUdpMirrorClient->getServerAddress().mPort);
if(mTunnelClient) {
if(mTunnelizeSipPackets) doUnregistration();
sal_set_tunnel(mCore->sal,NULL);
delete mTunnelClient;
mTunnelClient = NULL;
if(mTunnelizeSipPackets) doRegistration();
}
mState = disabled;
ms_message("TunnelManager: UDP mirror test success on %s:%d", mCurrentUdpMirrorClient->getServerAddress().mAddr.c_str(), mCurrentUdpMirrorClient->getServerAddress().mPort);
setState(Off);
}
mAutodetectionRunning = false;
stopLongRunningTask();
}
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) {
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");
tunnel->startAutoDetection();
tunnel->mState = autodetecting;
} else if (!reachable && tunnel->mState == autodetecting) {
// if network is no more reachable, cancel autodetection
for(UdpMirrorClientList::iterator udpMirror = tunnel->mUdpMirrorClients.begin(); udpMirror != tunnel->mUdpMirrorClients.end(); udpMirror++) {
if (reachable) {
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) {
// 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();
}
tunnel->mState = disabled;
mAutodetectionRunning = false;
stopLongRunningTask();
}
linphone_core_get_local_ip_for(AF_INET, NULL,tunnel->mLocalAddr);
}
bool TunnelManager::startAutoDetection() {
......@@ -420,20 +470,13 @@ bool TunnelManager::startAutoDetection() {
if (mLongRunningTaskId == 0)
mLongRunningTaskId = sal_begin_background_task("Tunnel auto detect", NULL, NULL);
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
mAutodetectionRunning = true;
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
return true;
}
bool TunnelManager::isActivated() const{
switch(getMode()){
case LinphoneTunnelModeAuto:
return !(mState==disabled);
case LinphoneTunnelModeDisable:
return false;
case LinphoneTunnelModeEnable:
return true;
}
return false;
return mState == On;
}
void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) {
......
......@@ -159,13 +159,6 @@ namespace belledonnecomm {
void simulateUdpLoss(bool enabled);
private:
enum State {
disabled,
connecting,
ready,
autodetecting
};
enum EventType{
UdpMirrorClientEvent,
TunnelEvent,
......@@ -180,15 +173,16 @@ namespace belledonnecomm {
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 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 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 tunnelCallback(bool connected, void *zis);
static void sOnIterate(TunnelManager *zis);
static void sUdpMirrorClientCallback(bool result, void* data);
static void networkReachableCb(LinphoneCore *lc, bool_t reachable);
private:
enum State{
Off, /*no tunneling */
On /*tunneling activated*/
};
void onIterate();
void doRegistration();
void doUnregistration();
......@@ -197,13 +191,18 @@ namespace belledonnecomm {
void processTunnelEvent(const Event &ev);
void processUdpMirrorEvent(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:
LinphoneCore* mCore;
LinphoneTunnelMode mMode;
State mState;
bool mTunnelizeSipPackets;
bool mVerifyServerCertificate;
TunnelClient* mTunnelClient;
std::string mHttpUserName;
std::string mHttpPasswd;
......@@ -218,6 +217,12 @@ namespace belledonnecomm {
std::queue<Event> mEvq;
char mLocalAddr[64];
unsigned long mLongRunningTaskId;
State mTargetState;
State mState;
bool mVerifyServerCertificate;
bool mStarted;
bool mAutodetectionRunning;
bool mTunnelizeSipPackets;
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);
/**
* Sets whether tunneling of SIP and RTP is required.
* @param tunnel object
......
......@@ -1802,10 +1802,16 @@ void linphone_gtk_edit_tunnel(GtkButton *button){
if (port==0) port=443;
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"port")), port);
if (linphone_tunnel_get_mode(tunnel)){
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_enable")),1);
} else{
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_disable")),1);
switch(linphone_tunnel_get_mode(tunnel)){
case LinphoneTunnelModeDisable:
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;
......@@ -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")));
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 *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")));
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")));
LinphoneTunnelMode mode = LinphoneTunnelModeDisable;
if (tunnel==NULL) return;
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_port(config, port);
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);
gtk_widget_destroy(w);
......
......@@ -52,7 +52,7 @@
<property name="visible">True</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="n_rows">4</property>
<property name="n_rows">5</property>
<property name="n_columns">2</property>
<property name="homogeneous">True</property>
<child>
......@@ -113,7 +113,7 @@
</child>
<child>
<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="can_focus">True</property>
<property name="receives_default">False</property>
......@@ -132,7 +132,7 @@
</child>
<child>
<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="can_focus">True</property>
<property name="receives_default">False</property>
......@@ -140,6 +140,26 @@
<property name="xalign">0</property>
<property name="active">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>
<packing>
<property name="left_attach">1</property>
......@@ -154,6 +174,9 @@
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
......@@ -170,7 +193,7 @@
<property name="visible">True</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="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>
</object>
</child>
......@@ -315,7 +338,7 @@
<object class="GtkLabel" id="label2">
<property name="visible">True</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>
</object>
</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_enable_payload_type(pauline->lc,
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);
}