refine tunnel implementation

- API cleanups
- add http proxy support
- add stubs to avoid using conditional defines.
This commit is contained in:
Simon Morlat 2012-02-15 14:53:27 +01:00
parent 844484d460
commit 5ad81af695
9 changed files with 218 additions and 158 deletions

View file

@ -478,7 +478,7 @@ AC_ARG_ENABLE(tunnel,
esac],[enable_tunnel=false])
AM_CONDITIONAL(BUILD_TUNNEL, test x$enable_tunnel = xtrue)
if test x$enable_tunnel = xtrue; then
PKG_CHECK_MODULES(TUNNEL, tunnel >= 0.3.1)
PKG_CHECK_MODULES(TUNNEL, tunnel >= 0.3.3)
TUNNEL_CFLAGS+="-DTUNNEL_ENABLED"
AC_SUBST(TUNNEL_CFLAGS)
AC_SUBST(TUNNEL_LIBS)

View file

@ -40,13 +40,15 @@ liblinphone_la_SOURCES=\
siplogin.c \
lsd.c linphonecore_utils.h \
ec-calibrator.c \
conference.c
conference.c \
linphone_tunnel.cc
if BUILD_WIZARD
liblinphone_la_SOURCES+=sipwizard.c
endif
if BUILD_TUNNEL
liblinphone_la_SOURCES+=TunnelManager.cc TunnelManager.hh linphone_tunnel.cc
liblinphone_la_SOURCES+=TunnelManager.cc TunnelManager.hh
endif
@ -89,3 +91,6 @@ AM_CFLAGS=$(STRICT_OPTIONS) -DIN_LINPHONE \
if BUILD_WIZARD
AM_CFLAGS+= -DBUILD_WIZARD
endif
AM_CXXFLAGS=$(AM_CFLAGS)

View file

@ -23,15 +23,6 @@
#include <android/log.h>
#endif
#ifdef recvfrom
#undef recvfrom
#endif
#ifdef sendto
#undef sendto
#endif
#ifdef select
#undef select
#endif
using namespace belledonnecomm;
@ -176,9 +167,7 @@ void TunnelManager::start() {
const ServerAddr &addr=*it;
mTunnelClient->addServer(addr.mAddr.c_str(), addr.mPort);
}
if(!mHttpUserName.empty()) {
mTunnelClient->setHttpProxyAuthInfo(mHttpUserName.c_str(), mHttpPasswd.c_str());
}
mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str());
}
mTunnelClient->start();
@ -214,7 +203,8 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController()
,mCallback(NULL)
,mEnabled(false)
,mTunnelClient(NULL)
,mAutoDetectStarted(false) {
,mAutoDetectStarted(false)
,mHttpProxyPort(0){
mExosipTransport.data=this;
mExosipTransport.recvfrom=eXosipRecvfrom;
@ -281,6 +271,25 @@ void TunnelManager::processTunnelEvent(){
}
}
void TunnelManager::waitUnRegistration(){
LinphoneProxyConfig* lProxy;
linphone_core_get_default_proxy(mCore, &lProxy);
if (lProxy && linphone_proxy_config_get_state(lProxy)==LinphoneRegistrationOk) {
int i;
linphone_proxy_config_edit(lProxy);
//make sure unregister is sent and authenticated
do{
linphone_core_iterate(mCore);
ms_usleep(20000);
if (i>100){
ms_message("tunnel: timeout for unregistration expired, giving up");
break;
}
i++;
}while(linphone_proxy_config_get_state(lProxy)!=LinphoneRegistrationCleared);
}
}
void TunnelManager::enable(bool isEnable) {
ms_message("Turning tunnel [%s]",(isEnable?"on":"off"));
if (isEnable && !mEnabled){
@ -288,29 +297,15 @@ void TunnelManager::enable(bool isEnable) {
//1 save transport
linphone_core_get_sip_transports(mCore, &mRegularTransport);
//2 unregister
LinphoneProxyConfig* lProxy;
linphone_core_get_default_proxy(mCore, &lProxy);
if (lProxy) {
linphone_proxy_config_edit(lProxy);
//make sure unregister is sent
linphone_core_iterate(mCore);
}
waitUnRegistration();
//3 insert tunnel
start();
}else if (!isEnable && mEnabled){
//1 unregister
waitUnRegistration();
mEnabled=false;
stopClient();
//1 unregister
LinphoneProxyConfig* lProxy;
linphone_core_get_default_proxy(mCore, &lProxy);
if (lProxy) {
linphone_proxy_config_edit(lProxy);
//make sure unregister is sent
linphone_core_iterate(mCore);
}
//make sure unregister is sent
linphone_core_iterate(mCore);
linphone_core_set_rtp_transport_factories(mCore,NULL);
@ -318,6 +313,8 @@ void TunnelManager::enable(bool isEnable) {
//Restore transport
linphone_core_set_sip_transports(mCore, &mRegularTransport);
//register
LinphoneProxyConfig* lProxy;
linphone_core_get_default_proxy(mCore, &lProxy);
if (lProxy) {
linphone_proxy_config_done(lProxy);
}
@ -420,6 +417,14 @@ void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd
if (mTunnelClient) mTunnelClient->setHttpProxyAuthInfo(username,passwd);
}
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);
}
LinphoneCore *TunnelManager::getLinphoneCore(){
return mCore;
}

View file

@ -128,6 +128,7 @@ class UdpMirrorClient;
* Get associated Linphone Core.
*/
LinphoneCore *getLinphoneCore();
virtual void setHttpProxy(const char *host,int port, const char *username, const char *passwd);
private:
typedef std::list<UdpMirrorClient> UdpMirrorClientList;
virtual bool isStarted();
@ -140,7 +141,7 @@ class UdpMirrorClient;
static void tunnelCallback(bool connected, TunnelManager *zis);
static void sOnIterate(TunnelManager *zis);
static void UdpMirrorClientListener(bool result, void* data);
void waitUnRegistration();
void processTunnelEvent();
LinphoneCore* mCore;
LCSipTransports mRegularTransport;
@ -159,7 +160,9 @@ class UdpMirrorClient;
bool mAutoDetectStarted;
LinphoneRtpTransportFactories mTransportFactories;
std::string mHttpUserName;
std::string mHttpPasswd;
std::string mHttpPasswd;
std::string mHttpProxyHost;
int mHttpProxyPort;
};
/**

View file

@ -29,36 +29,64 @@
#include "private.h"
#include "lpconfig.h"
LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){
return lc->tunnel;
}
#ifdef TUNNEL_ENABLED
static inline belledonnecomm::TunnelManager *bcTunnel(LinphoneTunnel *tunnel){
return (belledonnecomm::TunnelManager *)tunnel;
}
static inline _LpConfig *config(LinphoneTunnel *tunnel){
return ((belledonnecomm::TunnelManager *)tunnel)->getLinphoneCore()->config;
}
extern "C" LinphoneTunnel* linphone_core_tunnel_new(LinphoneCore *lc){
LinphoneTunnel* tunnel= (LinphoneTunnel*) new belledonnecomm::TunnelManager(lc);
return tunnel;
}
LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){
return lc->tunnel;
}
void linphone_tunnel_destroy(LinphoneTunnel *tunnel){
delete bcTunnel(tunnel);
}
static void add_server_to_config(LinphoneTunnel *tunnel, const char *host, int port){
const char *orig=lp_config_get_string(config(tunnel),"tunnel","server_addresses", NULL);
char *tmp;
if (orig){
tmp=ms_strdup_printf("%s %s:%i",orig,host,port);
}else tmp=ms_strdup_printf("%s:%i",host, port);
lp_config_set_string(config(tunnel),"tunnel","server_addresses",tmp);
ms_free(tmp);
}
void linphone_tunnel_add_server(LinphoneTunnel *tunnel, const char *host, int port){
bcTunnel(tunnel)->addServer(host, port);
add_server_to_config(tunnel,host,port);
}
void linphone_tunnel_add_server_and_mirror(LinphoneTunnel *tunnel, const char *host, int port, int remote_udp_mirror, int delay){
bcTunnel(tunnel)->addServer(host, port, remote_udp_mirror, delay);
/*FIXME, udp-mirror feature not saved in config*/
add_server_to_config(tunnel,host,port);
}
char *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){
const char *tmp=lp_config_get_string(config(tunnel),"tunnel","server_addresses",NULL);
if (tmp) return ms_strdup(tmp);
return NULL;
}
void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){
bcTunnel(tunnel)->cleanServers();
lp_config_set_string(config(tunnel),"tunnel","server_addresses",NULL);
}
void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){
lp_config_set_int(config(tunnel),"tunnel","enabled",(int)enabled);
bcTunnel(tunnel)->enable(enabled);
}
@ -66,18 +94,64 @@ bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){
return bcTunnel(tunnel)->isEnabled();
}
void linphone_tunnel_enable_logs(LinphoneTunnel *tunnel, bool_t enabled){
bcTunnel(tunnel)->enableLogs(enabled);
static OrtpLogFunc tunnelOrtpLogHandler=NULL;
/*
#define TUNNEL_DEBUG (1)
#define TUNNEL_INFO (1<<1)
#define TUNNEL_NOTICE (1<<2)
#define TUNNEL_WARN (1<<3)
#define TUNNEL_ERROR (1<<4)
#define TUNNEL_ALERT (1<<5)
#define TUNNEL_FATAL (1<<6)
*/
static void tunnelLogHandler(int level, const char *fmt, va_list l){
if (tunnelOrtpLogHandler){
OrtpLogLevel ortp_level=ORTP_DEBUG;
switch(level){
case TUNNEL_DEBUG:
ortp_level=ORTP_DEBUG;
break;
case TUNNEL_INFO:
ortp_level=ORTP_MESSAGE;
break;
case TUNNEL_NOTICE:
ortp_level=ORTP_MESSAGE;
break;
case TUNNEL_WARN:
ortp_level=ORTP_WARNING;
break;
case TUNNEL_ERROR:
ortp_level=ORTP_ERROR;
break;
case TUNNEL_ALERT:
ortp_level=ORTP_ERROR;
break;
case TUNNEL_FATAL:
ortp_level=ORTP_FATAL;
break;
default:
ms_fatal("Unexepcted tunnel log %i: %s",level,fmt);
break;
}
tunnelOrtpLogHandler(ortp_level,fmt,l);
}
}
void linphone_tunnel_enable_logs_with_handler(LinphoneTunnel *tunnel, bool_t enabled, LogHandler logHandler){
bcTunnel(tunnel)->enableLogs(enabled, logHandler);
void linphone_tunnel_enable_logs_with_handler(LinphoneTunnel *tunnel, bool_t enabled, OrtpLogFunc logHandler){
tunnelOrtpLogHandler=logHandler;
bcTunnel(tunnel)->enableLogs(enabled, tunnelLogHandler);
}
void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel *tunnel, const char* username,const char* passwd){
bcTunnel(tunnel)->setHttpProxyAuthInfo(username, passwd);
}
void linphone_tunnel_set_http_proxy(LinphoneTunnel*tunnel, const char *host, int port, const char* username,const char* passwd){
bcTunnel(tunnel)->setHttpProxy(host, port, username, passwd);
}
void linphone_tunnel_reconnect(LinphoneTunnel *tunnel){
bcTunnel(tunnel)->reconnect();
}
@ -86,56 +160,6 @@ void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){
bcTunnel(tunnel)->autoDetect();
}
static inline _LpConfig *config(LinphoneTunnel *tunnel){
return ((belledonnecomm::TunnelManager *)tunnel)->getLinphoneCore()->config;
}
/**
* Set tunnel server addresses. "host1:port1 host2:port2 host3:port3"
**/
void linphone_tunnel_set_server_addresses(LinphoneTunnel *tunnel, const char *addresses){
lp_config_set_string(config(tunnel),"tunnel","server_addresses",addresses);
}
/**
* Get tunnel server addresses. "host1:port1 host2:port2 host3:port3"
**/
const char *linphone_tunnel_get_server_addresses(LinphoneTunnel *tunnel){
return lp_config_get_string(config(tunnel),"tunnel","server_addresses", NULL);
}
/**
* Set tunnel state.
**/
void linphone_tunnel_set_state(LinphoneTunnel *tunnel, LinphoneTunnelState state){
switch (state) {
case LinphoneTunnelEnabled:
lp_config_set_string(config(tunnel),"tunnel","tunnel_state","enabled");
break;
case LinphoneTunnelDisabled:
lp_config_set_string(config(tunnel),"tunnel","tunnel_state","disabled");
break;
case LinphoneTunnelAuto:
lp_config_set_string(config(tunnel),"tunnel","tunnel_state","auto");
break;
}
}
/**
* Get tunnel state.
**/
LinphoneTunnelState linphone_tunnel_get_state(LinphoneTunnel *tunnel){
const char *state=lp_config_get_string(config(tunnel),"tunnel","tunnel_state","disabled");
if (0==strcmp("enabled", state)){
return LinphoneTunnelEnabled;
} else if (0==strcmp("auto", state)){
return LinphoneTunnelAuto;
} else {
return LinphoneTunnelDisabled;
}
}
static void tunnel_add_servers_from_config(LinphoneTunnel *tunnel, const char* confaddress){
char *addresses=(char*)ms_strdup(confaddress);
char *str1;
@ -151,19 +175,79 @@ static void tunnel_add_servers_from_config(LinphoneTunnel *tunnel, const char* c
ms_free(addresses);
}
static void my_ortp_logv(OrtpLogLevel level, const char *fmt, va_list args){
ortp_logv(level,fmt,args);
}
/**
* Update tunnel using configuration.
* Startup tunnel using configuration.
* Called internally from linphonecore at startup.
*/
void linphone_tunnel_update(LinphoneTunnel *tunnel){
bool_t enabled;
const char* addresses=linphone_tunnel_get_server_addresses(tunnel);
void linphone_tunnel_configure(LinphoneTunnel *tunnel){
bool_t enabled=(bool_t)lp_config_get_int(config(tunnel),"tunnel","enabled",FALSE);
const char* addresses=lp_config_get_string(config(tunnel),"tunnel","server_addresses", NULL);
linphone_tunnel_enable_logs_with_handler(tunnel,TRUE,my_ortp_logv);
linphone_tunnel_clean_servers(tunnel);
if (addresses){
tunnel_add_servers_from_config(tunnel,addresses);
}
enabled=linphone_tunnel_get_state(tunnel)==LinphoneTunnelEnabled && addresses!=NULL;
linphone_tunnel_enable(tunnel, enabled);
}
#else
/*stubs to avoid to have #ifdef TUNNEL_ENABLED in upper layers*/
void linphone_tunnel_destroy(LinphoneTunnel *tunnel){
}
void linphone_tunnel_add_server(LinphoneTunnel *tunnel, const char *host, int port){
}
void linphone_tunnel_add_server_and_mirror(LinphoneTunnel *tunnel, const char *host, int port, int remote_udp_mirror, int delay){
}
char *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){
return NULL;
}
void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){
}
void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){
}
bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){
return FALSE;
}
void linphone_tunnel_enable_logs(LinphoneTunnel *tunnel, bool_t enabled){
}
void linphone_tunnel_enable_logs_with_handler(LinphoneTunnel *tunnel, bool_t enabled, OrtpLogFunc logHandler){
}
void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel *tunnel, const char* username,const char* passwd){
}
void linphone_tunnel_set_http_proxy(LinphoneTunnel*tunnel, const char *host, int port, const char* username,const char* passwd){
}
void linphone_tunnel_reconnect(LinphoneTunnel *tunnel){
}
void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){
}
void linphone_tunnel_configure(LinphoneTunnel *tunnel){
}
#endif

View file

@ -28,62 +28,33 @@
#include "linphonecore.h"
/*
* Linphone VoIP tunnel extension API
**/
#ifdef __cplusplus
extern "C"
{
#endif
typedef void (*LogHandler)(int log_level, const char *str, va_list l);
void linphone_tunnel_add_server(LinphoneTunnel *tunnel, const char *host, int port);
void linphone_tunnel_add_server_and_mirror(LinphoneTunnel *tunnel, const char *host, int port, int remote_udp_mirror, int delay);
/*returns a string of space separated list of host:port of tunnel server addresses*/
char *linphone_tunnel_get_servers(LinphoneTunnel *tunnel);
void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel);
void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled);
bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel);
void linphone_tunnel_enable_logs(LinphoneTunnel *tunnel, bool_t enabled);
void linphone_tunnel_enable_logs_with_handler(LinphoneTunnel *tunnel, bool_t enabled, LogHandler logHandler);
void linphone_tunnel_reconnect(LinphoneTunnel *tunnel);
void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel);
void linphone_tunnel_set_http_proxy(LinphoneTunnel *tunnel, const char *host, int port, const char* username,const char* passwd);
void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel*tunnel, const char* username,const char* passwd);
/**
* LinphoneTunnelState describes the tunnel activation states.
*/
typedef enum _LinphoneTunnelState{
LinphoneTunnelDisabled, /**<The tunnel is always off */
LinphoneTunnelEnabled, /**<The tunnel is always on */
LinphoneTunnelAuto /**<The tunnel is active if needed */
}LinphoneTunnelState;
/**
* Set tunnel addresses.
**/
void linphone_tunnel_set_server_addresses(LinphoneTunnel *tunnel, const char *lists);
/**
* Get tunnel addresses.
**/
const char *linphone_tunnel_get_server_addresses(LinphoneTunnel *tunnel);
/**
* Set tunnel state.
**/
void linphone_tunnel_set_state(LinphoneTunnel *tunnel, LinphoneTunnelState state);
/**
* Get tunnel state.
**/
LinphoneTunnelState linphone_tunnel_get_state(LinphoneTunnel *tunnel);
/**
* Update tunnel connection after setting new server addresses.
**/
void linphone_tunnel_update(LinphoneTunnel *tunnel);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -810,7 +810,7 @@ static void autoreplier_config_init(LinphoneCore *lc)
}
*/
bool_t linphone_core_tunnel_available(){
bool_t linphone_core_tunnel_available(void){
#ifdef TUNNEL_ENABLED
return TRUE;
#else
@ -1099,7 +1099,7 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta
ui_config_read(lc);
#ifdef TUNNEL_ENABLED
lc->tunnel=linphone_core_tunnel_new(lc);
if (lc->tunnel) linphone_tunnel_update(lc->tunnel);
if (lc->tunnel) linphone_tunnel_configure(lc->tunnel);
#endif
if (lc->vtable.display_status)
lc->vtable.display_status(lc,_("Ready"));

View file

@ -480,6 +480,8 @@ struct _LinphoneCore
LinphoneTunnel *linphone_core_tunnel_new(LinphoneCore *lc);
void linphone_tunnel_destroy(LinphoneTunnel *tunnel);
void linphone_tunnel_configure(LinphoneTunnel *tunnel);
void linphone_tunnel_enable_logs_with_handler(LinphoneTunnel *tunnel, bool_t enabled, OrtpLogFunc logHandler);
bool_t linphone_core_can_we_add_call(LinphoneCore *lc);
int linphone_core_add_call( LinphoneCore *lc, LinphoneCall *call);

View file

@ -1003,7 +1003,7 @@ void linphone_gtk_edit_tunnel_closed(GtkWidget *button){
gtk_widget_destroy(pb);
}
#ifdef TUNNEL_ENABLED
static void tunnel_get_server_host_and_port(LinphoneTunnel *tunnel, char *host, int size, int *port){
char *colon;
char *addresses;
@ -1011,7 +1011,7 @@ static void tunnel_get_server_host_and_port(LinphoneTunnel *tunnel, char *host,
char *address;
const char* configured_addresses;
configured_addresses=linphone_tunnel_get_server_addresses(tunnel);
configured_addresses=linphone_tunnel_get_servers(tunnel);
if (configured_addresses==NULL){
host[0]=0;
@ -1030,39 +1030,35 @@ static void tunnel_get_server_host_and_port(LinphoneTunnel *tunnel, char *host,
ms_free(addresses);
}
#endif
void linphone_gtk_edit_tunnel(GtkButton *button){
GtkWidget *w=linphone_gtk_create_window("tunnel_config");
#ifdef TUNNEL_ENABLED
LinphoneCore *lc=linphone_gtk_get_core();
LinphoneTunnel *tunnel=linphone_core_get_tunnel(lc);
char host[128]={'\0'};
int port=0;
if (!tunnel) return;
tunnel_get_server_host_and_port(tunnel, host, sizeof(host), &port);
LinphoneTunnelState state=linphone_tunnel_get_state(tunnel);
gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"host")),host);
if (port==0) port=443;
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"port")), port);
if (state == LinphoneTunnelEnabled){
if (linphone_tunnel_enabled(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);
}
g_object_weak_ref(G_OBJECT(w),(GWeakNotify)linphone_gtk_edit_tunnel_closed,w);
#endif
gtk_widget_show(w);
}
void linphone_gtk_tunnel_ok(GtkButton *button){
GtkWidget *w=gtk_widget_get_toplevel(GTK_WIDGET(button));
// Save information to config file
#ifdef TUNNEL_ENABLED
LinphoneCore *lc=linphone_gtk_get_core();
char address[128]={'\0'};
LinphoneTunnel *tunnel=linphone_core_get_tunnel(lc);
gint port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"port")));
@ -1070,16 +1066,10 @@ void linphone_gtk_tunnel_ok(GtkButton *button){
const char *host=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"host")));
if (tunnel==NULL) return;
snprintf(address, sizeof address, "%s:%i", host, port);
linphone_tunnel_set_server_addresses(tunnel, address);
if (enabled){
linphone_tunnel_set_state(tunnel, LinphoneTunnelEnabled);
} else{
linphone_tunnel_set_state(tunnel,LinphoneTunnelDisabled);
}
linphone_tunnel_update(tunnel);
#endif
if (host && *host=='\0') host=NULL;
linphone_tunnel_clean_servers(tunnel);
linphone_tunnel_add_server(tunnel,host,port);
linphone_tunnel_enable(tunnel,enabled);
gtk_widget_destroy(w);
}