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)
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
if BUILD_WIZARD
AM_CFLAGS+= -DBUILD_WIZARD
endif
+
+AM_CXXFLAGS=$(AM_CFLAGS)
+
#include <android/log.h>
#endif
-#ifdef recvfrom
-#undef recvfrom
-#endif
-#ifdef sendto
-#undef sendto
-#endif
-#ifdef select
-#undef select
-#endif
using namespace belledonnecomm;
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();
,mCallback(NULL)
,mEnabled(false)
,mTunnelClient(NULL)
-,mAutoDetectStarted(false) {
+,mAutoDetectStarted(false)
+,mHttpProxyPort(0){
mExosipTransport.data=this;
mExosipTransport.recvfrom=eXosipRecvfrom;
}
}
+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){
//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){
- 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);
- }
+ waitUnRegistration();
- //make sure unregister is sent
- linphone_core_iterate(mCore);
+ mEnabled=false;
+ stopClient();
linphone_core_set_rtp_transport_factories(mCore,NULL);
//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);
}
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;
}
* 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();
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;
bool mAutoDetectStarted;
LinphoneRtpTransportFactories mTransportFactories;
std::string mHttpUserName;
- std::string mHttpPasswd;
+ std::string mHttpPasswd;
+ std::string mHttpProxyHost;
+ int mHttpProxyPort;
};
/**
#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);
}
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();
}
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;
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
+
+
+
+
#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
+
}
*/
-bool_t linphone_core_tunnel_available(){
+bool_t linphone_core_tunnel_available(void){
#ifdef TUNNEL_ENABLED
return TRUE;
#else
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"));
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);
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;
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;
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")));
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);
}