mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-30 01:39:20 +00:00
Tunnel manager.
This commit is contained in:
parent
27a5dd7e77
commit
886d80bb6d
19 changed files with 1399 additions and 369 deletions
11
.gitignore
vendored
11
.gitignore
vendored
|
|
@ -41,4 +41,15 @@ Specfile
|
|||
.anjuta_sym_db.db
|
||||
gtk-glade/version_date.h
|
||||
share/linphone.desktop
|
||||
Debug/
|
||||
build/macos/Info-linphone.plist
|
||||
coreapi/help/Doxyfile
|
||||
coreapi/help/buddy_status
|
||||
coreapi/help/chatroom
|
||||
coreapi/help/doc/
|
||||
coreapi/help/helloworld
|
||||
coreapi/help/registration
|
||||
coreapi/test_ecc
|
||||
coreapi/test_lsd
|
||||
gtk/version_date.h
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@ LOCAL_CFLAGS += \
|
|||
|
||||
LOCAL_CFLAGS += -DIN_LINPHONE
|
||||
|
||||
|
||||
ifeq ($(LINPHONE_VIDEO),1)
|
||||
LOCAL_CFLAGS += -DVIDEO_ENABLED
|
||||
ifeq ($(BUILD_X264),1)
|
||||
|
|
@ -94,6 +93,18 @@ LOCAL_STATIC_LIBRARIES := \
|
|||
libosip2 \
|
||||
libgsm
|
||||
|
||||
ifeq ($(BUILD_TUNNEL),1)
|
||||
LOCAL_CFLAGS +=-DTUNNEL_ENABLED
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../tunnel/include
|
||||
LOCAL_SRC_FILES += linphone_tunnel_manager.cc TunnelManager.cc
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
LOCAL_SHARED_LIBRARIES += libtunnelclient
|
||||
else
|
||||
LOCAL_STATIC_LIBRARIES += libtunnelclient
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
|
||||
ifneq ($(BUILD_AMR),0)
|
||||
LOCAL_CFLAGS += -DHAVE_AMR
|
||||
|
|
|
|||
29
configure.ac
29
configure.ac
|
|
@ -37,6 +37,7 @@ AC_CONFIG_MACRO_DIR([m4])
|
|||
AC_SUBST([mkdir_p])
|
||||
AC_ISC_POSIX
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_C_INLINE
|
||||
AM_PROG_CC_STDC
|
||||
AC_HEADER_STDC
|
||||
|
|
@ -460,6 +461,32 @@ AC_SUBST(MEDIASTREAMER_LIBS)
|
|||
AC_SUBST([MS2_VERSION])
|
||||
AC_SUBST([MS2_DIR])
|
||||
|
||||
|
||||
|
||||
AC_ARG_ENABLE(tunnel,
|
||||
[ --enable-tunnel=[yes/no] Turn on compilation of tunnel support [default=no]],
|
||||
[case "${enableval}" in
|
||||
yes) enable_tunnel=true ;;
|
||||
no) enable_tunnel=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --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)
|
||||
TUNNEL_CFLAGS+="-DTUNNEL_ENABLED"
|
||||
AC_SUBST(TUNNEL_CFLAGS)
|
||||
AC_SUBST(TUNNEL_LIBS)
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
dnl check for db2html (docbook) to generate html user manual
|
||||
AC_CHECK_PROG(have_sgmltools,sgmltools, yes, no)
|
||||
AM_CONDITIONAL(ENABLE_MANUAL, test x$have_sgmltools$build_manual = xyesyes )
|
||||
|
|
@ -517,6 +544,8 @@ AC_ARG_ENABLE(tests_enabled,
|
|||
esac],[tests_enabled=false])
|
||||
AM_CONDITIONAL(ENABLE_TESTS, test x$tests_enabled = xyes)
|
||||
|
||||
|
||||
|
||||
dnl ##################################################
|
||||
dnl # Check for doxygen
|
||||
dnl ##################################################
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonecore_utils.h ..
|
|||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)\
|
||||
$(MEDIASTREAMER_CFLAGS)
|
||||
$(MEDIASTREAMER_CFLAGS)\
|
||||
$(TUNNEL_CFLAGS)
|
||||
|
||||
|
||||
lib_LTLIBRARIES=liblinphone.la
|
||||
|
|
@ -37,7 +38,13 @@ liblinphone_la_SOURCES=\
|
|||
siplogin.c \
|
||||
lsd.c linphonecore_utils.h \
|
||||
ec-calibrator.c \
|
||||
conference.c
|
||||
conference.c \
|
||||
linphone_tunnel_manager.h
|
||||
|
||||
if BUILD_TUNNEL
|
||||
liblinphone_la_SOURCES+=TunnelManager.cc TunnelManager.hh linphone_tunnel_manager.c
|
||||
endif
|
||||
|
||||
|
||||
|
||||
liblinphone_la_LDFLAGS= -version-info $(LIBLINPHONE_SO_VERSION) -no-undefined
|
||||
|
|
@ -45,7 +52,8 @@ liblinphone_la_LDFLAGS= -version-info $(LIBLINPHONE_SO_VERSION) -no-undefined
|
|||
liblinphone_la_LIBADD= \
|
||||
$(EXOSIP_LIBS) \
|
||||
$(MEDIASTREAMER_LIBS) \
|
||||
$(ORTP_LIBS) $(OPENSSL_LIBS)
|
||||
$(ORTP_LIBS) $(OPENSSL_LIBS) \
|
||||
$(TUNNEL_LIBS)
|
||||
|
||||
if BUILD_WIN32
|
||||
liblinphone_la_LIBADD+=$(top_builddir)/oRTP/src/libortp.la
|
||||
|
|
@ -70,6 +78,8 @@ AM_CFLAGS=$(STRICT_OPTIONS) -DIN_LINPHONE \
|
|||
$(EXOSIP_CFLAGS) \
|
||||
-DENABLE_TRACE \
|
||||
-DLOG_DOMAIN=\"LinphoneCore\" \
|
||||
$(IPV6_CFLAGS) \
|
||||
-DORTP_INET6 \
|
||||
$(VIDEO_CFLAGS)
|
||||
$(IPV6_CFLAGS) \
|
||||
-DORTP_INET6 \
|
||||
$(VIDEO_CFLAGS) \
|
||||
$(TUNNEL_CFLAGS)
|
||||
|
||||
|
|
|
|||
435
coreapi/TunnelManager.cc
Normal file
435
coreapi/TunnelManager.cc
Normal file
|
|
@ -0,0 +1,435 @@
|
|||
/*
|
||||
* C Implementation: tunnel
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
*
|
||||
* Author: Simon Morlat <simon.morlat@linphone.org>, (C) 2009
|
||||
*
|
||||
* Copyright (C) 2010 Belledonne Comunications, Grenoble, France
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "TunnelManager.hh"
|
||||
|
||||
#include "ortp/rtpsession.h"
|
||||
#include "linphonecore.h"
|
||||
#include "linphonecore_utils.h"
|
||||
#include "eXosip2/eXosip_transport_hook.h"
|
||||
#include "tunnel/udp_mirror.hh"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
#ifdef recvfrom
|
||||
#undef recvfrom
|
||||
#endif
|
||||
#ifdef sendto
|
||||
#undef sendto
|
||||
#endif
|
||||
#ifdef select
|
||||
#undef select
|
||||
#endif
|
||||
|
||||
using namespace belledonnecomm;
|
||||
|
||||
Mutex TunnelManager::sMutex;
|
||||
|
||||
int TunnelManager::eXosipSendto(int fd,const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen,void* userdata){
|
||||
TunnelManager* lTunnelMgr=(TunnelManager*)userdata;
|
||||
int err;
|
||||
sMutex.lock();
|
||||
if (lTunnelMgr->mSipSocket==NULL){
|
||||
sMutex.unlock();
|
||||
return len;//let ignore the error
|
||||
}
|
||||
err=lTunnelMgr->mSipSocket->sendto(buf,len,to,tolen);
|
||||
sMutex.unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
int TunnelManager::eXosipRecvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen,void* userdata){
|
||||
TunnelManager* lTunnelMgr=(TunnelManager*)userdata;
|
||||
int err;
|
||||
sMutex.lock();
|
||||
if (lTunnelMgr->mSipSocket==NULL){
|
||||
sMutex.unlock();
|
||||
return 0;//let ignore the error
|
||||
}
|
||||
err=lTunnelMgr->mSipSocket->recvfrom(buf,len,from,*fromlen);
|
||||
sMutex.unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
int TunnelManager::eXosipSelect(int max_fds, fd_set *s1, fd_set *s2, fd_set *s3, struct timeval *tv,void* userdata){
|
||||
struct timeval begin,cur;
|
||||
TunnelManager* lTunnelMgr=(TunnelManager*)userdata;
|
||||
if (tv!=0 && tv->tv_sec){
|
||||
/*this is the select from udp.c, the one that is interesting to us*/
|
||||
unsigned int i;
|
||||
fd_set tmp;
|
||||
int udp_fd=eXosip_get_udp_socket();
|
||||
int controlfd=-1;
|
||||
|
||||
/*
|
||||
Find the udp fd and the control fd
|
||||
*/
|
||||
for(i=0;i<max_fds;++i){
|
||||
if (FD_ISSET(i,s1) && i!=udp_fd){
|
||||
controlfd=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (controlfd==-1){
|
||||
ms_error("Could not find control fd !");
|
||||
return -1;
|
||||
}
|
||||
FD_ZERO(s1);
|
||||
gettimeofday(&begin,NULL);
|
||||
do{
|
||||
struct timeval abit;
|
||||
|
||||
abit.tv_sec=0;
|
||||
abit.tv_usec=20000;
|
||||
sMutex.lock();
|
||||
if (lTunnelMgr->mSipSocket!=NULL){
|
||||
if (lTunnelMgr->mSipSocket->hasData()) {
|
||||
sMutex.unlock();
|
||||
/* we make exosip believe that it has udp data to read*/
|
||||
FD_SET(udp_fd,s1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
sMutex.unlock();
|
||||
gettimeofday(&cur,NULL);
|
||||
if (cur.tv_sec-begin.tv_sec>tv->tv_sec) {
|
||||
FD_SET(controlfd,s1);
|
||||
FD_SET(udp_fd,s1);
|
||||
return 0;
|
||||
}
|
||||
FD_ZERO(s1);
|
||||
FD_SET(controlfd,s1);
|
||||
if (select(max_fds,s1,s2,s3,&abit)==1) {
|
||||
return 1;
|
||||
}
|
||||
}while(1);
|
||||
|
||||
}else{
|
||||
/*select called from other places, only the control fd is present */
|
||||
return select(max_fds,s1,s2,s3,tv);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TunnelManager::addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay) {
|
||||
addServer(ip,port);
|
||||
mUdpMirrorClients.push_back(UdpMirrorClient(ServerAddr(ip,udpMirrorPort),delay));
|
||||
}
|
||||
|
||||
void TunnelManager::addServer(const char *ip, int port) {
|
||||
mServerAddrs.push_back(ServerAddr(ip,port));
|
||||
if (mTunnelClient) mTunnelClient->addServer(ip,port);
|
||||
}
|
||||
|
||||
void TunnelManager::cleanServers() {
|
||||
mServerAddrs.clear();
|
||||
|
||||
UdpMirrorClientList::iterator it;
|
||||
mAutoDetectStarted=false;
|
||||
for (it = mUdpMirrorClients.begin(); it != mUdpMirrorClients.end();) {
|
||||
UdpMirrorClient& s=*it++;
|
||||
s.stop();
|
||||
}
|
||||
mUdpMirrorClients.clear();
|
||||
if (mTunnelClient) mTunnelClient->cleanServers();
|
||||
}
|
||||
|
||||
void TunnelManager::reconnect(){
|
||||
if (mTunnelClient)
|
||||
mTunnelClient->reconnect();
|
||||
}
|
||||
|
||||
void TunnelManager::setCallback(StateCallback cb, void *userdata) {
|
||||
mCallback=cb;
|
||||
mCallbackData=userdata;
|
||||
}
|
||||
|
||||
static void sCloseRtpTransport(void *userData, RtpTransport *t){
|
||||
((TunnelManager::TunnelManager *) userData)->closeRtpTransport(t);
|
||||
}
|
||||
void TunnelManager::closeRtpTransport(RtpTransport *t){
|
||||
TunnelSocket *socket=(TunnelSocket *) t->data;
|
||||
mTransports.remove(t);
|
||||
mTunnelClient->closeSocket(socket);
|
||||
ms_free(t);
|
||||
}
|
||||
|
||||
static RtpTransport *sCreateRtpTransport(void* userData, int port){
|
||||
return ((TunnelManager::TunnelManager *) userData)->createRtpTransport(port);
|
||||
}
|
||||
|
||||
RtpTransport *TunnelManager::createRtpTransport(int port){
|
||||
RtpTransport *t=ms_new0(RtpTransport,1);
|
||||
t->data=mTunnelClient->createSocket(port);
|
||||
t->t_getsocket=NULL;
|
||||
t->t_recvfrom=customRecvfrom;
|
||||
t->t_sendto=customSendto;
|
||||
t->close_fn=sCloseRtpTransport;
|
||||
t->close_data=this;
|
||||
mTransports.push_back(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
void TunnelManager::start() {
|
||||
if (!mTunnelClient) {
|
||||
mTunnelClient = new TunnelClient();
|
||||
mTunnelClient->setCallback((StateCallback)tunnelCallback,this);
|
||||
std::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->start();
|
||||
|
||||
if (mSipSocket == NULL) mSipSocket =mTunnelClient->createSocket(5060);
|
||||
}
|
||||
|
||||
bool TunnelManager::isStarted() {
|
||||
return mTunnelClient != 0 && mTunnelClient->isStarted();
|
||||
}
|
||||
|
||||
bool TunnelManager::isReady() const {
|
||||
return mTunnelClient && mTunnelClient->isReady();
|
||||
}
|
||||
|
||||
int TunnelManager::customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen){
|
||||
int size;
|
||||
msgpullup(msg,-1);
|
||||
size=msgdsize(msg);
|
||||
((TunnelSocket*)t->data)->sendto(msg->b_rptr,size,to,tolen);
|
||||
return size;
|
||||
}
|
||||
|
||||
int TunnelManager::customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen){
|
||||
int err=((TunnelSocket*)t->data)->recvfrom(msg->b_wptr,msg->b_datap->db_lim-msg->b_datap->db_base,from,*fromlen);
|
||||
if (err>0) return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController()
|
||||
,mCore(lc)
|
||||
,mEnabled(false)
|
||||
,mSipSocket(NULL)
|
||||
,mCallback(NULL)
|
||||
,mTunnelClient(NULL)
|
||||
,mAutoDetectStarted(false) {
|
||||
|
||||
mExosipTransport.data=this;
|
||||
mExosipTransport.recvfrom=eXosipRecvfrom;
|
||||
mExosipTransport.sendto=eXosipSendto;
|
||||
mExosipTransport.select=eXosipSelect;
|
||||
mStateChanged=false;
|
||||
linphone_core_add_iterate_hook(mCore,(LinphoneCoreIterateHook)sOnIterate,this);
|
||||
mTransportFactories.audio_rtcp_func=sCreateRtpTransport;
|
||||
mTransportFactories.audio_rtcp_func_data=this;
|
||||
mTransportFactories.audio_rtp_func=sCreateRtpTransport;
|
||||
mTransportFactories.audio_rtp_func_data=this;
|
||||
mTransportFactories.video_rtcp_func=sCreateRtpTransport;
|
||||
mTransportFactories.video_rtcp_func_data=this;
|
||||
mTransportFactories.video_rtp_func=sCreateRtpTransport;
|
||||
mTransportFactories.video_rtp_func_data=this;
|
||||
}
|
||||
|
||||
TunnelManager::~TunnelManager(){
|
||||
stopClient();
|
||||
}
|
||||
|
||||
void TunnelManager::stopClient(){
|
||||
eXosip_transport_hook_register(NULL);
|
||||
if (mSipSocket != NULL){
|
||||
sMutex.lock();
|
||||
mTunnelClient->closeSocket(mSipSocket);
|
||||
mSipSocket = NULL;
|
||||
sMutex.unlock();
|
||||
}
|
||||
if (mTunnelClient){
|
||||
delete mTunnelClient;
|
||||
mTunnelClient=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelManager::processTunnelEvent(){
|
||||
LinphoneProxyConfig* lProxy;
|
||||
linphone_core_get_default_proxy(mCore, &lProxy);
|
||||
|
||||
if (mEnabled && mTunnelClient->isReady()){
|
||||
ms_message("Tunnel is up, registering now");
|
||||
linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
|
||||
eXosip_transport_hook_register(&mExosipTransport);
|
||||
//force transport to udp
|
||||
LCSipTransports lTransport;
|
||||
|
||||
lTransport.udp_port=15060;
|
||||
lTransport.tcp_port=0;
|
||||
lTransport.tls_port=0;
|
||||
lTransport.dtls_port=0;
|
||||
|
||||
linphone_core_set_sip_transports(mCore, &lTransport);
|
||||
//register
|
||||
if (lProxy) {
|
||||
linphone_proxy_config_done(lProxy);
|
||||
}
|
||||
}else if (mEnabled && !mTunnelClient->isReady()){
|
||||
/* we got disconnected from the tunnel */
|
||||
if (lProxy && linphone_proxy_config_is_registered(lProxy)) {
|
||||
/*forces de-registration so that we register again when the tunnel is up*/
|
||||
linphone_proxy_config_edit(lProxy);
|
||||
linphone_core_iterate(mCore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelManager::enable(bool isEnable) {
|
||||
ms_message("Turning tunnel [%s]",(isEnable?"on":"off"));
|
||||
if (isEnable && !mEnabled){
|
||||
mEnabled=true;
|
||||
//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);
|
||||
}
|
||||
//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);
|
||||
}
|
||||
|
||||
//make sure unregister is sent
|
||||
linphone_core_iterate(mCore);
|
||||
|
||||
linphone_core_set_rtp_transport_factories(mCore,NULL);
|
||||
|
||||
eXosip_transport_hook_register(NULL);
|
||||
//Restore transport
|
||||
linphone_core_set_sip_transports(mCore, &mRegularTransport);
|
||||
//register
|
||||
if (lProxy) {
|
||||
linphone_proxy_config_done(lProxy);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelManager::tunnelCallback(bool connected, TunnelManager *zis){
|
||||
zis->mStateChanged=true;
|
||||
}
|
||||
|
||||
/*invoked from linphone_core_iterate() */
|
||||
void TunnelManager::sOnIterate(TunnelManager *zis){
|
||||
if (zis->mStateChanged){
|
||||
zis->mStateChanged=false;
|
||||
zis->processTunnelEvent();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
static void linphone_android_log_handler(int lev, const char *fmt, va_list args){
|
||||
int prio;
|
||||
switch(lev){
|
||||
case TUNNEL_DEBUG: prio = ANDROID_LOG_DEBUG; break;
|
||||
case TUNNEL_INFO: prio = ANDROID_LOG_INFO; break;
|
||||
case TUNNEL_NOTICE: prio = ANDROID_LOG_INFO; break;
|
||||
case TUNNEL_WARN: prio = ANDROID_LOG_WARN; break;
|
||||
case TUNNEL_ERROR: prio = ANDROID_LOG_ERROR; break;
|
||||
default: prio = ANDROID_LOG_DEFAULT; break;
|
||||
}
|
||||
__android_log_vprint(prio, LOG_DOMAIN, fmt, args);
|
||||
}
|
||||
#endif /*ANDROID*/
|
||||
|
||||
void TunnelManager::enableLogs(bool value) {
|
||||
enableLogs(value,NULL);
|
||||
}
|
||||
|
||||
void TunnelManager::enableLogs(bool isEnabled,LogHandler logHandler) {
|
||||
if (logHandler != NULL) SetLogHandler(logHandler);
|
||||
#ifdef ANDROID
|
||||
else SetLogHandler(linphone_android_log_handler);
|
||||
#else
|
||||
else SetLogHandler(default_log_handler);
|
||||
#endif
|
||||
|
||||
if (isEnabled) {
|
||||
SetLogLevel(TUNNEL_ERROR|TUNNEL_WARN|TUNNEL_INFO);
|
||||
} else {
|
||||
SetLogLevel(TUNNEL_ERROR|TUNNEL_WARN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool TunnelManager::isEnabled() {
|
||||
return mEnabled;
|
||||
}
|
||||
void TunnelManager::UdpMirrorClientListener(bool isUdpAvailable, void* data) {
|
||||
TunnelManager* thiz = (TunnelManager*)data;
|
||||
if (isUdpAvailable) {
|
||||
LOGI("Tunnel is not required, disabling");
|
||||
thiz->enable(false);
|
||||
thiz->mAutoDetectStarted = false;
|
||||
} else {
|
||||
if (++thiz->mCurrentUdpMirrorClient !=thiz->mUdpMirrorClients.end()) {
|
||||
//1 enable tunnable but also try backup server
|
||||
LOGI("Tunnel is required, enabling; Trying backup udp mirror");
|
||||
|
||||
UdpMirrorClient &lUdpMirrorClient=*thiz->mCurrentUdpMirrorClient;
|
||||
lUdpMirrorClient.start(TunnelManager::UdpMirrorClientListener,(void*)thiz);
|
||||
} else {
|
||||
LOGI("Tunnel is required, enabling; no backup udp mirror available");
|
||||
thiz->mAutoDetectStarted = false;
|
||||
}
|
||||
thiz->enable(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void TunnelManager::autoDetect() {
|
||||
// first check if udp mirrors was provisionned
|
||||
if (mUdpMirrorClients.empty()) {
|
||||
LOGE("No UDP mirror server configured aborting auto detection");
|
||||
return;
|
||||
}
|
||||
if (mAutoDetectStarted) {
|
||||
LOGE("auto detection already in progress, restarting");
|
||||
(*mCurrentUdpMirrorClient).stop();
|
||||
}
|
||||
mAutoDetectStarted=true;
|
||||
mCurrentUdpMirrorClient =mUdpMirrorClients.begin();
|
||||
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
|
||||
lUdpMirrorClient.start(TunnelManager::UdpMirrorClientListener,(void*)this);
|
||||
|
||||
}
|
||||
|
||||
void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) {
|
||||
mTunnelClient->setHttpProxyAuthInfo(username,passwd);
|
||||
}
|
||||
|
||||
LinphoneCore *TunnelManager::getLinphoneCore(){
|
||||
return mCore;
|
||||
}
|
||||
171
coreapi/TunnelManager.hh
Normal file
171
coreapi/TunnelManager.hh
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* C Implementation: tunnel
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
*
|
||||
*
|
||||
*Copyright (C) 2011 Belledonne Comunications, Grenoble, France
|
||||
*/
|
||||
|
||||
#ifndef __TUNNEL_CLIENT_MANAGER_H__
|
||||
#define __TUNNEL_CLIENT_MANAGER_H__
|
||||
#include <list>
|
||||
#include "linphonecore.h"
|
||||
#include "tunnel/client.hh"
|
||||
extern "C" {
|
||||
#include "eXosip2/eXosip_transport_hook.h"
|
||||
}
|
||||
namespace belledonnecomm {
|
||||
class TunnelClient;
|
||||
class UdpMirrorClient;
|
||||
/**
|
||||
* @addtogroup tunnel_client
|
||||
* @{
|
||||
**/
|
||||
|
||||
/**
|
||||
* The TunnelManager class extends the LinphoneCore functionnality in order to provide an easy to use API to
|
||||
* - provision tunnel servers ip addresses and ports
|
||||
* - start/stop the tunneling service
|
||||
* - be informed of of connection and disconnection events to the tunnel server
|
||||
* - perform auto-detection whether tunneling is required, based on a test of sending/receiving a flow of UDP packets.
|
||||
*
|
||||
* It takes in charge automatically the SIP registration procedure when connecting or disconnecting to a tunnel server.
|
||||
* No other action on LinphoneCore is required to enable full operation in tunnel mode.
|
||||
**/
|
||||
class TunnelManager : public TunnelClientController{
|
||||
|
||||
public:
|
||||
/**
|
||||
* Add a tunnel server. At least one should be provided to be able to connect.
|
||||
* When several addresses are provided, the tunnel client may try each of them until it gets connected.
|
||||
*
|
||||
* @param ip tunnMethod definition for '-isInitialStateOn' not foundel server ip address
|
||||
* @param port tunnel server tls port, recommended value is 443
|
||||
*/
|
||||
void addServer(const char *ip, int port);
|
||||
/**
|
||||
*Add tunnel server with auto detection capabilities
|
||||
*
|
||||
* @param ip tunnel server ip address
|
||||
* @param port tunnel server tls port, recommended value is 443
|
||||
* @param udpMirrorPort remote port on the tunnel server side used to test udp reachability
|
||||
* @param delay udp packet round trip delay in ms considered as acceptable. recommanded value is 1000 ms.
|
||||
*/
|
||||
void addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay);
|
||||
/**
|
||||
* Removes all tunnel server address previously entered with addServer()
|
||||
**/
|
||||
void cleanServers();
|
||||
/**
|
||||
* Register a state callback to be notified whenever the tunnel client is connected or disconnected to the tunnel server.
|
||||
* @param cb application callback function to use for notifying of connection/disconnection events.
|
||||
* @param userdata An opaque pointer passed to the callback, used optionally by the application to retrieve a context.
|
||||
**/
|
||||
void setCallback(StateCallback cb, void *userdata);
|
||||
/**
|
||||
* Start connecting to a tunnel server.
|
||||
* At this step, nothing is tunneled yet. The enable() method must be used to state whether SIP and RTP traffic
|
||||
* need to be tunneled or not.
|
||||
**/
|
||||
void start();
|
||||
/**
|
||||
* Forces reconnection to the tunnel server.
|
||||
* This method is useful when the device switches from wifi to Edge/3G or vice versa. In most cases the tunnel client socket
|
||||
* won't be notified promptly that its connection is now zombie, so it is recommended to call this method that will cause
|
||||
* the lost connection to be closed and new connection to be issued.
|
||||
**/
|
||||
void reconnect();
|
||||
/**
|
||||
* Sets whether tunneling of SIP and RTP is required.
|
||||
* @param isEnabled If true enter in tunneled mode, if false exits from tunneled mode.
|
||||
* The TunnelManager takes care of refreshing SIP registration when switching on or off the tunneled mode.
|
||||
*
|
||||
**/
|
||||
void enable(bool isEnabled);
|
||||
/**
|
||||
* In auto detect mode, the tunnel manager try to establish a real time rtp cummunication with the tunnel server on specified port.
|
||||
*<br>In case of success, the tunnel is automatically turned off. Otherwise, if no udp commmunication is feasible, tunnel mode is turned on.
|
||||
*<br> Call this method each time to run the auto detection algorithm
|
||||
*/
|
||||
void autoDetect();
|
||||
/**
|
||||
* Returns a boolean indicating whether tunneled operation is enabled.
|
||||
**/
|
||||
bool isEnabled();
|
||||
/**
|
||||
* Enables debug logs of the Tunnel subsystem.
|
||||
**/
|
||||
void enableLogs(bool isEnabled);
|
||||
/**
|
||||
* Enables debugs logs of the Tunnel subsystem and specify a callback where to receive the debug messages.
|
||||
**/
|
||||
void enableLogs(bool isEnabled,LogHandler logHandler);
|
||||
/**
|
||||
* iOS only feature: specify http proxy credentials.
|
||||
* When the iOS device has an http proxy configured in the iOS settings, the tunnel client will connect to the server
|
||||
* through this http proxy. Credentials might be needed depending on the proxy configuration.
|
||||
* @param username The username.
|
||||
* @param passwd The password.
|
||||
**/
|
||||
void setHttpProxyAuthInfo(const char* username,const char* passwd);
|
||||
~TunnelManager();
|
||||
TunnelManager(LinphoneCore* lc);
|
||||
/**
|
||||
* Destroy the given RtpTransport.
|
||||
*/
|
||||
void closeRtpTransport(RtpTransport *t);
|
||||
|
||||
/**
|
||||
* Create an RtpTransport.
|
||||
*/
|
||||
RtpTransport *createRtpTransport(int port);
|
||||
|
||||
/**
|
||||
* Get associated Linphone Core.
|
||||
*/
|
||||
LinphoneCore *getLinphoneCore();
|
||||
private:
|
||||
typedef std::list<UdpMirrorClient> UdpMirrorClientList;
|
||||
typedef std::list<RtpTransport*> RtpTransportList;
|
||||
virtual bool isStarted();
|
||||
virtual bool isReady() const;
|
||||
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 sOnIterate(TunnelManager *zis);
|
||||
static void UdpMirrorClientListener(bool result, void* data);
|
||||
|
||||
void processTunnelEvent();
|
||||
LinphoneCore* mCore;
|
||||
LCSipTransports mRegularTransport;
|
||||
TunnelSocket *mSipSocket;
|
||||
eXosip_transport_hooks_t mExosipTransport;
|
||||
StateCallback mCallback;
|
||||
void * mCallbackData;
|
||||
bool mEnabled;
|
||||
bool mStateChanged;
|
||||
std::list <ServerAddr> mServerAddrs;
|
||||
UdpMirrorClientList mUdpMirrorClients;
|
||||
UdpMirrorClientList::iterator mCurrentUdpMirrorClient;
|
||||
TunnelClient* mTunnelClient;
|
||||
void stopClient();
|
||||
static Mutex sMutex;
|
||||
bool mAutoDetectStarted;
|
||||
RtpTransportList mTransports;
|
||||
LinphoneRtpTransportFactories mTransportFactories;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
**/
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /*__TUNNEL_CLIENT_MANAGER_H__*/
|
||||
126
coreapi/linphone_tunnel_manager.cc
Normal file
126
coreapi/linphone_tunnel_manager.cc
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/***************************************************************************
|
||||
* linphone_tunnel_manager.cc
|
||||
*
|
||||
* Fri Dec 9, 2011
|
||||
* Copyright 2011 Belledonne Communications
|
||||
* Author: Guillaume Beraudo
|
||||
* Email: guillaume dot beraudo at linphone dot org
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "linphone_tunnel_manager.h"
|
||||
#include "TunnelManager.hh"
|
||||
#include "linphonecore.h"
|
||||
#include "private.h"
|
||||
#include "lpconfig.h"
|
||||
|
||||
static inline belledonnecomm::TunnelManager *bcTunnel(LinphoneTunnelManager *tunnel){
|
||||
return (belledonnecomm::TunnelManager *)tunnel;
|
||||
}
|
||||
|
||||
extern "C" LinphoneTunnelManager* linphone_core_tunnel_new(LinphoneCore *lc){
|
||||
LinphoneTunnelManager* tunnel= (LinphoneTunnelManager*) new belledonnecomm::TunnelManager(lc);
|
||||
return tunnel;
|
||||
}
|
||||
|
||||
LinphoneTunnelManager* linphone_tunnel_get(LinphoneCore *lc){
|
||||
return lc->tunnel;
|
||||
}
|
||||
|
||||
void linphone_tunnel_destroy(LinphoneTunnelManager *tunnel){
|
||||
delete bcTunnel(tunnel);
|
||||
}
|
||||
|
||||
void linphone_tunnel_add_server(LinphoneTunnelManager *tunnel, const char *host, int port){
|
||||
bcTunnel(tunnel)->addServer(host, port);
|
||||
}
|
||||
|
||||
void linphone_tunnel_add_server_and_mirror(LinphoneTunnelManager *tunnel, const char *host, int port, int remote_udp_mirror, int delay){
|
||||
bcTunnel(tunnel)->addServer(host, port, remote_udp_mirror, delay);
|
||||
}
|
||||
|
||||
void linphone_tunnel_clean_servers(LinphoneTunnelManager *tunnel){
|
||||
bcTunnel(tunnel)->cleanServers();
|
||||
}
|
||||
|
||||
void linphone_tunnel_enable(LinphoneTunnelManager *tunnel, bool_t enabled){
|
||||
bcTunnel(tunnel)->enable(enabled);
|
||||
}
|
||||
|
||||
bool_t linphone_tunnel_enabled(LinphoneTunnelManager *tunnel){
|
||||
return bcTunnel(tunnel)->isEnabled();
|
||||
}
|
||||
|
||||
void linphone_tunnel_enable_logs(LinphoneTunnelManager *tunnel, bool_t enabled){
|
||||
bcTunnel(tunnel)->enableLogs(enabled);
|
||||
}
|
||||
|
||||
void linphone_tunnel_auto_detect(LinphoneTunnelManager *tunnel){
|
||||
bcTunnel(tunnel)->autoDetect();
|
||||
}
|
||||
|
||||
|
||||
static inline _LpConfig *config(LinphoneTunnelManager *tunnel){
|
||||
return ((belledonnecomm::TunnelManager *)tunnel)->getLinphoneCore()->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set tunnel server addresses. "host1:port1 host2:port2 host3:port3"
|
||||
**/
|
||||
void linphone_tunnel_set_server_addresses(LinphoneTunnelManager *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(LinphoneTunnelManager *tunnel){
|
||||
return lp_config_get_string(config(tunnel),"tunnel","server_addresses", NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set tunnel state.
|
||||
**/
|
||||
void linphone_tunnel_set_state(LinphoneTunnelManager *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(LinphoneTunnelManager *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;
|
||||
}
|
||||
}
|
||||
85
coreapi/linphone_tunnel_manager.h
Normal file
85
coreapi/linphone_tunnel_manager.h
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/***************************************************************************
|
||||
* linphone_tunnel_manager.h
|
||||
*
|
||||
* Fri Dec 9, 2011
|
||||
* Copyright 2011 Belledonne Communications
|
||||
* Author: Guillaume Beraudo
|
||||
* Email: guillaume dot beraudo at linphone dot org
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef LINPHONETUNNELMANAGER_H
|
||||
#define LINPHONETUNNELMANAGER_H
|
||||
|
||||
#include "linphonecore.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct LinphoneTunnelManager LinphoneTunnelManager;
|
||||
|
||||
LinphoneTunnelManager *linphone_tunnel_get(LinphoneCore *lc);
|
||||
void linphone_tunnel_destroy(LinphoneTunnelManager *tunnel);
|
||||
void linphone_tunnel_add_server(LinphoneTunnelManager *tunnel, const char *host, int port);
|
||||
void linphone_tunnel_add_server_and_mirror(LinphoneTunnelManager *tunnel, const char *host, int port, int remote_udp_mirror, int delay);
|
||||
void linphone_tunnel_clean_servers(LinphoneTunnelManager *tunnel);
|
||||
void linphone_tunnel_enable(LinphoneTunnelManager *tunnel, bool_t enabled);
|
||||
bool_t linphone_tunnel_enabled(LinphoneTunnelManager *tunnel);
|
||||
void linphone_tunnel_enable_logs(LinphoneTunnelManager *tunnel, bool_t enabled);
|
||||
void linphone_tunnel_auto_detect(LinphoneTunnelManager *tunnel);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* LinphoneTunnelState describes the tunnel activation states.
|
||||
*/
|
||||
typedef enum _LinphoneTunnelState{
|
||||
LinphoneTunnelDisabled, /**<The tunnel is always on */
|
||||
LinphoneTunnelEnabled, /**<The tunnel is always off */
|
||||
LinphoneTunnelAuto /**<The tunnel is active if needed */
|
||||
}LinphoneTunnelState;
|
||||
|
||||
/**
|
||||
* Set tunnel addresses.
|
||||
**/
|
||||
void linphone_tunnel_set_server_addresses(LinphoneTunnelManager *tunnel, const char *lists);
|
||||
|
||||
/**
|
||||
* Get tunnel addresses.
|
||||
**/
|
||||
const char *linphone_tunnel_get_server_addresses(LinphoneTunnelManager *tunnel);
|
||||
|
||||
/**
|
||||
* Set tunnel state.
|
||||
**/
|
||||
void linphone_tunnel_set_state(LinphoneTunnelManager *tunnel, LinphoneTunnelState state);
|
||||
|
||||
/**
|
||||
* Get tunnel state.
|
||||
**/
|
||||
LinphoneTunnelState linphone_tunnel_get_state(LinphoneTunnelManager *tunnel);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -845,8 +845,11 @@ void linphone_call_init_media_streams(LinphoneCall *call){
|
|||
audio_stream_enable_noise_gate(audiostream,enabled);
|
||||
}
|
||||
|
||||
if (lc->a_rtp)
|
||||
rtp_session_set_transports(audiostream->session,lc->a_rtp,lc->a_rtcp);
|
||||
if (lc->rtptf){
|
||||
RtpTransport *artp=lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->audio_port);
|
||||
RtpTransport *artcp=lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->audio_port+1);
|
||||
rtp_session_set_transports(audiostream->session,artp,artcp);
|
||||
}
|
||||
|
||||
call->audiostream_app_evq = ortp_ev_queue_new();
|
||||
rtp_session_register_event_queue(audiostream->session,call->audiostream_app_evq);
|
||||
|
|
@ -858,8 +861,11 @@ void linphone_call_init_media_streams(LinphoneCall *call){
|
|||
if( lc->video_conf.displaytype != NULL)
|
||||
video_stream_set_display_filter_name(call->videostream,lc->video_conf.displaytype);
|
||||
video_stream_set_event_callback(call->videostream,video_stream_event_cb, call);
|
||||
if (lc->v_rtp)
|
||||
rtp_session_set_transports(call->videostream->session,lc->v_rtp,lc->v_rtcp);
|
||||
if (lc->rtptf){
|
||||
RtpTransport *vrtp=lc->rtptf->video_rtp_func(lc->rtptf->video_rtp_func_data, call->video_port);
|
||||
RtpTransport *vrtcp=lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->video_port+1);
|
||||
rtp_session_set_transports(call->videostream->session,vrtp,vrtcp);
|
||||
}
|
||||
call->videostream_app_evq = ortp_ev_queue_new();
|
||||
rtp_session_register_event_queue(call->videostream->session,call->videostream_app_evq);
|
||||
#ifdef TEST_EXT_RENDERER
|
||||
|
|
@ -1039,7 +1045,7 @@ static bool_t linphone_call_sound_resources_available(LinphoneCall *call){
|
|||
return !linphone_core_is_in_conference(lc) &&
|
||||
(current==NULL || current==call);
|
||||
}
|
||||
static int find_crypto_index_from_tag(SalSrtpCryptoAlgo crypto[],unsigned char tag) {
|
||||
static int find_crypto_index_from_tag(const SalSrtpCryptoAlgo crypto[],unsigned char tag) {
|
||||
int i;
|
||||
for(i=0; i<SAL_CRYPTO_ALGO_MAX; i++) {
|
||||
if (crypto[i].tag == tag) {
|
||||
|
|
@ -1313,7 +1319,7 @@ void linphone_call_stop_media_streams(LinphoneCall *call){
|
|||
const char *state_str=NULL;
|
||||
ms_filter_call_method(call->audiostream->ec,MS_ECHO_CANCELLER_GET_STATE_STRING,&state_str);
|
||||
if (state_str){
|
||||
ms_message("Writing echo canceller state, %i bytes",(int)strlen(state_str));
|
||||
ms_message("Writing echo canceler state, %i bytes",(int)strlen(state_str));
|
||||
lp_config_set_string(call->core->config,"sound","ec_state",state_str);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -810,6 +810,14 @@ static void autoreplier_config_init(LinphoneCore *lc)
|
|||
}
|
||||
*/
|
||||
|
||||
bool_t linphone_core_tunnel_available(){
|
||||
#ifdef TUNNEL_ENABLED
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable adaptive rate control (experimental feature, audio-only).
|
||||
*
|
||||
|
|
@ -989,6 +997,36 @@ static void misc_config_read (LinphoneCore *lc) {
|
|||
lc->max_calls=lp_config_get_int(config,"misc","max_calls",NB_MAX_CALLS);
|
||||
}
|
||||
|
||||
#ifdef TUNNEL_ENABLED
|
||||
static void tunnel_add_servers_from_config(LinphoneTunnelManager *tunnel, const char* confaddress){
|
||||
char *addresses=(char*)ms_strdup(confaddress);
|
||||
char *str1;
|
||||
for(str1=addresses;;str1=NULL){
|
||||
char *port;
|
||||
char *address=strtok(str1," "); // Not thread safe
|
||||
if (!address) break;
|
||||
port=strchr(address, ':');
|
||||
if (!port) ms_fatal("Bad tunnel address %s", address);
|
||||
*port++='\0';
|
||||
linphone_tunnel_add_server(tunnel, address, atoi(port));
|
||||
}
|
||||
ms_free(addresses);
|
||||
}
|
||||
#endif
|
||||
|
||||
void linphone_core_update_tunnel(LinphoneCore *lc){
|
||||
#ifdef TUNNEL_ENABLED
|
||||
bool_t enabled;
|
||||
const char* addresses=linphone_tunnel_get_server_addresses(lc->tunnel);
|
||||
if (addresses){
|
||||
linphone_tunnel_clean_servers(lc->tunnel);
|
||||
tunnel_add_servers_from_config(lc->tunnel,addresses);
|
||||
}
|
||||
enabled=linphone_tunnel_get_state(lc->tunnel)==LinphoneTunnelEnabled && addresses!=NULL;
|
||||
linphone_tunnel_enable(lc->tunnel, enabled);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vtable, const char *config_path,
|
||||
const char *factory_config_path, void * userdata)
|
||||
{
|
||||
|
|
@ -1084,6 +1122,10 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta
|
|||
lc->presence_mode=LinphoneStatusOnline;
|
||||
misc_config_read(lc);
|
||||
ui_config_read(lc);
|
||||
#ifdef TUNNEL_ENABLED
|
||||
lc->tunnel=linphone_core_tunnel_new(lc);
|
||||
linphone_core_update_tunnel(lc);
|
||||
#endif
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Ready"));
|
||||
lc->auto_net_state_mon=lc->sip_conf.auto_net_state_mon;
|
||||
|
|
@ -3874,14 +3916,8 @@ void linphone_core_stop_waiting(LinphoneCore *lc){
|
|||
}
|
||||
}
|
||||
|
||||
void linphone_core_set_audio_transports(LinphoneCore *lc, RtpTransport *rtp, RtpTransport *rtcp){
|
||||
lc->a_rtp=rtp;
|
||||
lc->a_rtcp=rtcp;
|
||||
}
|
||||
|
||||
void linphone_core_set_video_transports(LinphoneCore *lc, RtpTransport *rtp, RtpTransport *rtcp){
|
||||
lc->v_rtp=rtp;
|
||||
lc->v_rtcp=rtcp;
|
||||
void linphone_core_set_rtp_transport_factories(LinphoneCore* lc, LinphoneRtpTransportFactories *factories){
|
||||
lc->rtptf=factories;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -344,6 +344,16 @@ typedef enum _LinphoneRegistrationState{
|
|||
*/
|
||||
const char *linphone_registration_state_to_string(LinphoneRegistrationState cs);
|
||||
|
||||
/**
|
||||
* True if tunnel support was compiled.
|
||||
*/
|
||||
bool_t linphone_core_tunnel_available();
|
||||
|
||||
/**
|
||||
* Update tunnel using configuration.
|
||||
*/
|
||||
void linphone_core_update_tunnel(LinphoneCore *lc);
|
||||
|
||||
LinphoneProxyConfig *linphone_proxy_config_new(void);
|
||||
int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *server_addr);
|
||||
int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity);
|
||||
|
|
@ -1006,9 +1016,20 @@ const MSList * linphone_core_get_sip_setups(LinphoneCore *lc);
|
|||
void linphone_core_destroy(LinphoneCore *lc);
|
||||
|
||||
/*for advanced users:*/
|
||||
void linphone_core_set_audio_transports(LinphoneCore *lc, RtpTransport *rtp, RtpTransport *rtcp);
|
||||
void linphone_core_set_video_transports(LinphoneCore *lc, RtpTransport *rtp, RtpTransport *rtcp);
|
||||
typedef RtpTransport * (*LinphoneRtpTransportFactoryFunc)(void *data, int port);
|
||||
struct _LinphoneRtpTransportFactories{
|
||||
LinphoneRtpTransportFactoryFunc audio_rtp_func;
|
||||
void *audio_rtp_func_data;
|
||||
LinphoneRtpTransportFactoryFunc audio_rtcp_func;
|
||||
void *audio_rtcp_func_data;
|
||||
LinphoneRtpTransportFactoryFunc video_rtp_func;
|
||||
void *video_rtp_func_data;
|
||||
LinphoneRtpTransportFactoryFunc video_rtcp_func;
|
||||
void *video_rtcp_func_data;
|
||||
};
|
||||
typedef struct _LinphoneRtpTransportFactories LinphoneRtpTransportFactories;
|
||||
|
||||
void linphone_core_set_rtp_transport_factories(LinphoneCore* lc, LinphoneRtpTransportFactories *factories);
|
||||
|
||||
int linphone_core_get_current_call_stats(LinphoneCore *lc, rtp_stats_t *local, rtp_stats_t *remote);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "linphonecore_utils.h"
|
||||
#include <ortp/zrtp.h>
|
||||
|
||||
#ifdef TUNNEL_ENABLED
|
||||
#include "linphone_tunnel_manager.h"
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include "mediastreamer2/mediastream.h"
|
||||
}
|
||||
|
|
@ -1591,3 +1595,45 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getMaxCalls(JNIEnv *env,
|
|||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setMaxCalls(JNIEnv *env,jobject thiz,jlong pCore, jint max) {
|
||||
linphone_core_set_max_calls((LinphoneCore *) pCore, (int) max);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelAddServerAndMirror(JNIEnv *env,jobject thiz,jlong pCore,
|
||||
jstring jHost, jint port, jint mirror, jint delay) {
|
||||
#ifdef TUNNEL_ENABLED
|
||||
LinphoneTunnelManager *tunnel=((LinphoneCore *) pCore)->tunnel; if (!tunnel) return;
|
||||
const char* cHost=env->GetStringUTFChars(jHost, NULL);
|
||||
linphone_tunnel_add_server_and_mirror(tunnel, cHost, port, mirror, delay);
|
||||
env->ReleaseStringUTFChars(jHost, cHost);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelAutoDetect(JNIEnv *env,jobject thiz,jlong pCore) {
|
||||
#ifdef TUNNEL_ENABLED
|
||||
LinphoneTunnelManager *tunnel=((LinphoneCore *) pCore)->tunnel; if (!tunnel) return;
|
||||
linphone_tunnel_auto_detect(tunnel);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelCleanServers(JNIEnv *env,jobject thiz,jlong pCore) {
|
||||
#ifdef TUNNEL_ENABLED
|
||||
LinphoneTunnelManager *tunnel=((LinphoneCore *) pCore)->tunnel; if (!tunnel) return;
|
||||
linphone_tunnel_clean_servers(tunnel);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelEnable(JNIEnv *env,jobject thiz,jlong pCore, jboolean enable) {
|
||||
#ifdef TUNNEL_ENABLED
|
||||
LinphoneTunnelManager *tunnel=((LinphoneCore *) pCore)->tunnel; if (!tunnel) return;
|
||||
linphone_tunnel_enable(tunnel, enable);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelEnableLogs(JNIEnv *env,jobject thiz,jlong pCore, jboolean enable) {
|
||||
#ifdef TUNNEL_ENABLED
|
||||
LinphoneTunnelManager *tunnel=((LinphoneCore *) pCore)->tunnel; if (!tunnel) return;
|
||||
linphone_tunnel_enable_logs(tunnel, enable);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isTunnelAvailable(JNIEnv *env,jobject thiz){
|
||||
return linphone_core_tunnel_available();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,11 @@
|
|||
|
||||
#ifndef _PRIVATE_H
|
||||
#define _PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "linphonecore.h"
|
||||
#include "linphone_tunnel_manager.h"
|
||||
#include "linphonecore_utils.h"
|
||||
#include "sal.h"
|
||||
|
||||
|
|
@ -442,8 +445,7 @@ struct _LinphoneCore
|
|||
int missed_calls;
|
||||
VideoPreview *previewstream;
|
||||
struct _MSEventQueue *msevq;
|
||||
RtpTransport *a_rtp,*a_rtcp;
|
||||
RtpTransport *v_rtp,*v_rtcp;
|
||||
LinphoneRtpTransportFactories *rtptf;
|
||||
MSList *bl_reqs;
|
||||
MSList *subscribers; /* unknown subscribers */
|
||||
int minutes_away;
|
||||
|
|
@ -474,8 +476,11 @@ struct _LinphoneCore
|
|||
int device_rotation;
|
||||
bool_t ringstream_autorelease;
|
||||
int max_calls;
|
||||
LinphoneTunnelManager *tunnel;
|
||||
};
|
||||
|
||||
LinphoneTunnelManager *linphone_core_tunnel_new(LinphoneCore *lc);
|
||||
|
||||
bool_t linphone_core_can_we_add_call(LinphoneCore *lc);
|
||||
int linphone_core_add_call( LinphoneCore *lc, LinphoneCall *call);
|
||||
int linphone_core_del_call( LinphoneCore *lc, LinphoneCall *call);
|
||||
|
|
@ -538,4 +543,9 @@ void __linphone_core_invalidate_registers(LinphoneCore* lc);
|
|||
#define NB_MAX_CALLS (10)
|
||||
#endif
|
||||
void call_logs_write_to_config_file(LinphoneCore *lc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ UI_FILES= about.ui \
|
|||
call_logs.ui \
|
||||
log.ui \
|
||||
buddylookup.ui \
|
||||
tunnel_config.ui \
|
||||
waiting.ui
|
||||
|
||||
PIXMAPS= \
|
||||
|
|
@ -74,7 +75,8 @@ endif
|
|||
AM_CFLAGS= -DIN_LINPHONE -I$(top_srcdir)/coreapi/ \
|
||||
$(MEDIASTREAMER_CFLAGS) \
|
||||
$(ORTP_CFLAGS) \
|
||||
$(STRICT_OPTIONS) $(LIBGTK_CFLAGS) $(LIBGTKMAC_CFLAGS) $(IPV6_CFLAGS)
|
||||
$(STRICT_OPTIONS) $(LIBGTK_CFLAGS) $(LIBGTKMAC_CFLAGS) $(IPV6_CFLAGS) \
|
||||
$(TUNNEL_CFLAGS)
|
||||
|
||||
|
||||
version_date.h: $(top_srcdir)/configure.ac
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -18,6 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
*/
|
||||
|
||||
#include "linphone.h"
|
||||
#include "linphone_tunnel_manager.h"
|
||||
|
||||
typedef enum {
|
||||
CAP_IGNORE,
|
||||
|
|
@ -986,5 +987,88 @@ void linphone_gtk_show_parameters(void){
|
|||
|
||||
g_signal_connect(G_OBJECT(linphone_gtk_get_widget(pb,"proto_port")),"value-changed",(GCallback)linphone_gtk_update_my_port,NULL);
|
||||
g_signal_connect(G_OBJECT(linphone_gtk_get_widget(pb,"proto_combo")),"changed",(GCallback)linphone_gtk_proto_changed,NULL);
|
||||
|
||||
|
||||
if (linphone_core_tunnel_available(lc)){
|
||||
gtk_widget_set_visible(GTK_WIDGET(linphone_gtk_get_widget(pb,"tunnel_edit_button")), TRUE);
|
||||
gtk_widget_set_visible(GTK_WIDGET(linphone_gtk_get_widget(pb,"tunnel_label")), TRUE);
|
||||
}
|
||||
|
||||
gtk_widget_show(pb);
|
||||
}
|
||||
|
||||
|
||||
void linphone_gtk_edit_tunnel_closed(GtkWidget *button){
|
||||
GtkWidget *pb=gtk_widget_get_toplevel(button);
|
||||
gtk_widget_destroy(pb);
|
||||
}
|
||||
|
||||
#ifdef TUNNEL_ENABLED
|
||||
static void tunnel_get_server_host_and_port(LinphoneTunnelManager *tunnel, char *host, int size, int *port){
|
||||
char *colon;
|
||||
char *addresses=(char*)ms_strdup(linphone_tunnel_get_server_addresses(tunnel));
|
||||
char *str1=addresses;
|
||||
char *address=strtok(str1," "); // Not thread safe
|
||||
if (!address) return;
|
||||
colon=strchr(address, ':');
|
||||
if (!colon) return;
|
||||
*colon++='\0';
|
||||
*port=atoi(colon);
|
||||
memcpy(host,address,size);
|
||||
ms_free(addresses);
|
||||
}
|
||||
#endif
|
||||
|
||||
void linphone_gtk_edit_tunnel(GtkButton *button){
|
||||
#ifdef TUNNEL_ENABLED
|
||||
LinphoneCore *lc=linphone_gtk_get_core();
|
||||
GtkWidget *w=linphone_gtk_create_window("tunnel_config");
|
||||
LinphoneTunnelManager *tunnel=linphone_tunnel_get(lc);
|
||||
char host[50]={'\0'};
|
||||
int port=0;
|
||||
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);
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"port")), port);
|
||||
|
||||
if (state == LinphoneTunnelEnabled){
|
||||
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);
|
||||
|
||||
gtk_widget_show(w);
|
||||
#endif
|
||||
}
|
||||
|
||||
void linphone_gtk_tunnel_ok(GtkButton *button){
|
||||
#ifdef TUNNEL_ENABLED
|
||||
// Save information to config file
|
||||
LinphoneCore *lc=linphone_gtk_get_core();
|
||||
GtkWidget *w=gtk_widget_get_toplevel(GTK_WIDGET(button));
|
||||
char address[50]={'\0'};
|
||||
LinphoneTunnelManager *tunnel=linphone_tunnel_get(lc);
|
||||
|
||||
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")));
|
||||
const char *host=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"host")));
|
||||
|
||||
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_core_update_tunnel(lc);
|
||||
gtk_widget_destroy(w);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void linphone_gtk_tunnel_cancel(GtkButton *button){
|
||||
|
||||
}
|
||||
|
|
|
|||
202
gtk/tunnel_config.ui
Normal file
202
gtk/tunnel_config.ui
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<requires lib="gtk+" version="2.18"/>
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkAdjustment" id="adjustment1">
|
||||
<property name="value">3600</property>
|
||||
<property name="upper">100000</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
</object>
|
||||
<object class="GtkDialog" id="tunnel_config">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">Linphone - Configure a SIP account</property>
|
||||
<property name="window_position">center-on-parent</property>
|
||||
<property name="icon">linphone2.png</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkVBox" id="dialog-vbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkFrame" id="frame15">
|
||||
<property name="visible">True</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_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment15">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox11">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="table6">
|
||||
<property name="visible">True</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_columns">2</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label38">
|
||||
<property name="visible">True</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">Host</property>
|
||||
<property name="justify">right</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="host">
|
||||
<property name="width_request">275</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label39">
|
||||
<property name="visible">True</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">Port</property>
|
||||
<property name="justify">right</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="radio_enable">
|
||||
<property name="label" translatable="yes">Enable</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="radio_disable">
|
||||
<property name="label" translatable="yes">Disable</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</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">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="port">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
<property name="adjustment">adjustment1</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="label42">
|
||||
<property name="visible">True</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">Configure tunnel</property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkHButtonBox" id="dialog-action_area2">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="button6">
|
||||
<property name="label">gtk-ok</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="linphone_gtk_tunnel_ok"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button7">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="linphone_gtk_proxy_cancel"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="0">button6</action-widget>
|
||||
<action-widget response="0">button7</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
</interface>
|
||||
|
|
@ -707,5 +707,17 @@ public interface LinphoneCore {
|
|||
* @param path path to music file played to remote side when on hold.
|
||||
*/
|
||||
void setPlayFile(String path);
|
||||
|
||||
void tunnelEnable(boolean enable);
|
||||
void tunnelAutoDetect();
|
||||
void tunnelEnableLogs(boolean enable);
|
||||
void tunnelCleanServers();
|
||||
/**
|
||||
* @param host tunnel server ip address
|
||||
* @param port tunnel server tls port, recommended value is 443
|
||||
* @param udpMirrorPort remote port on the tunnel server side used to test udp reachability
|
||||
* @param roundTripDelay udp packet round trip delay in ms considered as acceptable. recommended value is 1000 ms
|
||||
*/
|
||||
void tunnelAddServerAndMirror(String host, int port, int udpMirrorPort, int roundTripDelay);
|
||||
|
||||
boolean isTunnelAvailable();
|
||||
}
|
||||
|
|
|
|||
2
oRTP
2
oRTP
|
|
@ -1 +1 @@
|
|||
Subproject commit 758150c3cd0f5a3a7a087247d6ff2dd198435fe7
|
||||
Subproject commit 729f35e54053154d92fe3eaf7bdb86bc10aec262
|
||||
Loading…
Add table
Reference in a new issue