Allow the tunnel mode to work with any proxy config (except for sips destinations)

fix the tunnel tests, that were not working correctly.
This commit is contained in:
Simon Morlat 2014-11-14 20:16:50 +01:00
parent c828b54b33
commit d0095948b9
13 changed files with 104 additions and 100 deletions

View file

@ -106,6 +106,7 @@ void TunnelManager::startClient() {
}
mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str());
mTunnelClient->start();
sal_set_tunnel(mCore->sal, mTunnelClient);
}
bool TunnelManager::isConnected() const {
@ -185,12 +186,13 @@ void TunnelManager::processTunnelEvent(const Event &ev){
ms_message("TunnelManager: tunnel is connected");
if(mState == connecting) {
linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
mState = ready;
if(mTunnelizeSipPackets) {
doUnregistration();
sal_enable_tunnel(mCore->sal, mTunnelClient);
_linphone_core_apply_transports(mCore);
doRegistration();
}
mState = ready;
}
} else {
ms_error("TunnelManager: tunnel has been disconnected");
@ -219,17 +221,15 @@ void TunnelManager::setMode(LinphoneTunnelMode mode) {
case LinphoneTunnelModeDisable:
if(mState == ready) {
linphone_core_set_rtp_transport_factories(mCore,NULL);
if(mTunnelizeSipPackets) {
doUnregistration();
sal_disable_tunnel(mCore->sal);
}
delete mTunnelClient;
mTunnelClient=NULL;
if(mTunnelizeSipPackets) {
doRegistration();
}
mState = disabled;
mMode = mode;
if(mTunnelizeSipPackets) {
doUnregistration();
_linphone_core_apply_transports(mCore);
}
sal_set_tunnel(mCore->sal,NULL);
delete mTunnelClient;
mTunnelClient=NULL;
} else {
ms_error("TunnelManager: could not change mode. Bad state");
}
@ -385,6 +385,18 @@ bool TunnelManager::startAutoDetection() {
return true;
}
bool TunnelManager::isActivated() const{
switch(getMode()){
case LinphoneTunnelModeAuto:
return !mState==disabled;
case LinphoneTunnelModeDisable:
return false;
case LinphoneTunnelModeEnable:
return true;
}
return false;
}
void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) {
mHttpUserName=username?username:"";
mHttpPasswd=passwd?passwd:"";
@ -392,7 +404,7 @@ void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd
}
void TunnelManager::tunnelizeSipPackets(bool enable){
mTunnelizeSipPackets = enable;
mTunnelizeSipPackets = enable;
}
bool TunnelManager::tunnelizeSipPacketsEnabled() const {

View file

@ -142,6 +142,7 @@ namespace belledonnecomm {
*/
bool isConnected() const;
bool isActivated() const;
private:
enum State {
disabled,
@ -199,10 +200,6 @@ namespace belledonnecomm {
LinphoneRtpTransportFactories mTransportFactories;
Mutex mMutex;
std::queue<Event> mEvq;
#ifndef USE_BELLESIP
TunnelSocket *mSipSocket;
eXosip_transport_hooks_t mExosipTransport;
#endif
};
/**

View file

@ -554,19 +554,24 @@ int sal_transport_available(Sal *sal, SalTransport t){
return FALSE;
}
int sal_add_listen_port(Sal *ctx, SalAddress* addr){
static int sal_add_listen_port(Sal *ctx, SalAddress* addr, bool_t is_tunneled){
int result;
belle_sip_listening_point_t* lp = belle_sip_stack_create_listening_point(ctx->stack,
belle_sip_listening_point_t* lp;
if (is_tunneled){
if (sal_address_get_transport(addr)!=SalTransportUDP){
ms_error("Tunneled mode is only available for UDP kind of transports.");
return -1;
}
lp = belle_sip_tunnel_listening_point_new(ctx->stack, ctx->tunnel_client);
if (!lp){
ms_error("Could not create tunnel listening point.");
return -1;
}
}else{
lp = belle_sip_stack_create_listening_point(ctx->stack,
sal_address_get_domain(addr),
sal_address_get_port(addr),
sal_transport_to_string(sal_address_get_transport(addr)));
if (sal_address_get_port(addr)==-1 && lp==NULL){
int random_port=(0xDFFF&ortp_random())+1024;
ms_warning("This version of belle-sip doesn't support random port, choosing one here.");
lp = belle_sip_stack_create_listening_point(ctx->stack,
sal_address_get_domain(addr),
random_port,
sal_transport_to_string(sal_address_get_transport(addr)));
}
if (lp) {
belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive);
@ -578,13 +583,13 @@ int sal_add_listen_port(Sal *ctx, SalAddress* addr){
return result;
}
int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure) {
int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_tunneled) {
SalAddress* sal_addr = sal_address_new(NULL);
int result;
sal_address_set_domain(sal_addr,addr);
sal_address_set_port(sal_addr,port);
sal_address_set_transport(sal_addr,tr);
result = sal_add_listen_port(ctx,sal_addr);
result = sal_add_listen_port(ctx, sal_addr, is_tunneled);
sal_address_destroy(sal_addr);
return result;
}
@ -646,43 +651,15 @@ void sal_set_keepalive_period(Sal *ctx,unsigned int value){
}
}
}
int sal_enable_tunnel(Sal *ctx, void *tunnelclient) {
int sal_set_tunnel(Sal *ctx, void *tunnelclient) {
#ifdef TUNNEL_ENABLED
belle_sip_listening_point_t *lp_udp = NULL;
if(ctx->lp_tunnel != NULL) {
ortp_error("sal_enable_tunnel(): tunnel is already enabled");
return -1;
}
while((lp_udp = belle_sip_provider_get_listening_point(ctx->prov, "udp")) != NULL) {
belle_sip_object_ref(lp_udp);
belle_sip_provider_remove_listening_point(ctx->prov, lp_udp);
ctx->udp_listening_points = ms_list_append(ctx->udp_listening_points, lp_udp);
}
ctx->lp_tunnel = belle_sip_tunnel_listening_point_new(ctx->stack, tunnelclient);
if(ctx->lp_tunnel == NULL) return -1;
belle_sip_listening_point_set_keep_alive(ctx->lp_tunnel, ctx->keep_alive);
belle_sip_provider_add_listening_point(ctx->prov, ctx->lp_tunnel);
belle_sip_object_ref(ctx->lp_tunnel);
ctx->tunnel_client=tunnelclient;
return 0;
#else
return 0;
#endif
}
void sal_disable_tunnel(Sal *ctx) {
#ifdef TUNNEL_ENABLED
MSList *it;
if(ctx->lp_tunnel) {
belle_sip_provider_remove_listening_point(ctx->prov, ctx->lp_tunnel);
belle_sip_object_unref(ctx->lp_tunnel);
ctx->lp_tunnel = NULL;
for(it=ctx->udp_listening_points; it!=NULL; it=it->next) {
belle_sip_provider_add_listening_point(ctx->prov, (belle_sip_listening_point_t *)it->data);
}
ms_list_free_with_data(ctx->udp_listening_points, belle_sip_object_unref);
ctx->udp_listening_points = NULL;
}
return -1;
#endif
}
/**
* returns keepalive period in ms
* 0 desactiaved

View file

@ -33,8 +33,7 @@ struct Sal{
belle_sip_provider_t *prov;
belle_sip_header_user_agent_t* user_agent;
belle_sip_listener_t *listener;
belle_sip_listening_point_t *lp_tunnel;
MSList *udp_listening_points;
void *tunnel_client;
void *up; /*user pointer*/
int session_expires;
unsigned int keep_alive;

View file

@ -285,6 +285,7 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
const MSList *elem=sal_op_get_route_addresses(op);
const char *transport;
const char *method=belle_sip_request_get_method(request);
belle_sip_listening_point_t *udplp=belle_sip_provider_get_listening_point(prov,"UDP");
if (elem) {
outbound_proxy=belle_sip_header_address_get_uri((belle_sip_header_address_t*)elem->data);
@ -297,7 +298,7 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
/*compatibility mode: by default it should be udp as not explicitely set and if no udp listening point is available, then use
* the first available transport*/
if (!belle_sip_uri_is_secure(next_hop_uri)){
if (belle_sip_provider_get_listening_point(prov,"UDP")==0){
if (udplp==NULL){
if (belle_sip_provider_get_listening_point(prov,"TCP")!=NULL){
transport="tcp";
}else if (belle_sip_provider_get_listening_point(prov,"TLS")!=NULL ){
@ -309,6 +310,11 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
belle_sip_uri_set_transport_param(next_hop_uri,transport);
}
}
}else{
if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(udplp,belle_sip_tunnel_listening_point_t)){
/* our tunnel mode only supports UDP. Force transport to be set to UDP */
belle_sip_uri_set_transport_param(next_hop_uri,"udp");
}
}
if ((strcmp(method,"REGISTER")==0 || strcmp(method,"SUBSCRIBE")==0) && transport &&
(strcasecmp(transport,"TCP")==0 || strcasecmp(transport,"TLS")==0)){

View file

@ -246,6 +246,10 @@ bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel){
return bcTunnel(tunnel)->isConnected();
}
bool_t linphone_tunnel_get_activated(const LinphoneTunnel *tunnel){
return bcTunnel(tunnel)->isActivated();
}
static OrtpLogFunc tunnelOrtpLogHandler=NULL;
/*

View file

@ -188,6 +188,15 @@ LINPHONE_PUBLIC void linphone_tunnel_set_mode(LinphoneTunnel *tunnel, LinphoneTu
**/
LINPHONE_PUBLIC LinphoneTunnelMode linphone_tunnel_get_mode(const LinphoneTunnel *tunnel);
/**
* Returns whether the tunnel is activated. If mode is set to auto, this gives indication whether the automatic detection determined
* that tunnel was necessary or not.
* @param tunnel the tunnel
* @return TRUE if tunnel is in use, FALSE otherwise.
**/
LINPHONE_PUBLIC bool_t linphone_tunnel_get_activated(const LinphoneTunnel *tunnel);
/**
* Check whether the tunnel is connected
* @param tunnel LinphoneTunnel object

View file

@ -2975,7 +2975,8 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
linphone_call_handle_stream_events(call,0);
linphone_call_handle_stream_events(call,1);
if (call->state==LinphoneCallStreamsRunning && one_second_elapsed && call->audiostream!=NULL && disconnect_timeout>0 )
if (call->state==LinphoneCallStreamsRunning && one_second_elapsed && call->audiostream!=NULL
&& call->audiostream->ms.state==MSStreamStarted && disconnect_timeout>0 )
disconnected=!audio_stream_alive(call->audiostream,disconnect_timeout);
if (disconnected)
linphone_core_disconnected(call->core,call);

View file

@ -2151,7 +2151,7 @@ static bool_t transports_unchanged(const LCSipTransports * tr1, const LCSipTrans
tr2->tls_port==tr1->tls_port;
}
static int apply_transports(LinphoneCore *lc){
int _linphone_core_apply_transports(LinphoneCore *lc){
Sal *sal=lc->sal;
const char *anyaddr;
LCSipTransports *tr=&lc->sip_conf.transports;
@ -2165,20 +2165,26 @@ static int apply_transports(LinphoneCore *lc){
anyaddr="0.0.0.0";
sal_unlisten_ports(sal);
if (tr->udp_port!=0){
if (sal_listen_port (sal,anyaddr,tr->udp_port,SalTransportUDP,FALSE)!=0){
transport_error(lc,"udp",tr->udp_port);
if (lc->tunnel && linphone_tunnel_sip_enabled(lc->tunnel) && linphone_tunnel_get_activated(lc->tunnel)){
if (sal_listen_port(sal,anyaddr,tr->udp_port,SalTransportUDP,TRUE)!=0){
transport_error(lc,"udp+tunnel",tr->udp_port);
}
}
if (tr->tcp_port!=0){
if (sal_listen_port (sal,anyaddr,tr->tcp_port,SalTransportTCP,FALSE)!=0){
transport_error(lc,"tcp",tr->tcp_port);
}else{
if (tr->udp_port!=0){
if (sal_listen_port(sal,anyaddr,tr->udp_port,SalTransportUDP,FALSE)!=0){
transport_error(lc,"udp",tr->udp_port);
}
}
}
if (linphone_core_sip_transport_supported(lc,LinphoneTransportTls)){
if (tr->tls_port!=0){
if (sal_listen_port (sal,anyaddr,tr->tls_port,SalTransportTLS,TRUE)!=0){
transport_error(lc,"tls",tr->tls_port);
if (tr->tcp_port!=0){
if (sal_listen_port (sal,anyaddr,tr->tcp_port,SalTransportTCP,FALSE)!=0){
transport_error(lc,"tcp",tr->tcp_port);
}
}
if (linphone_core_sip_transport_supported(lc,LinphoneTransportTls)){
if (tr->tls_port!=0){
if (sal_listen_port (sal,anyaddr,tr->tls_port,SalTransportTLS,FALSE)!=0){
transport_error(lc,"tls",tr->tls_port);
}
}
}
}
@ -2231,7 +2237,7 @@ int linphone_core_set_sip_transports(LinphoneCore *lc, const LCSipTransports * t
}
if (lc->sal==NULL) return 0;
return apply_transports(lc);
return _linphone_core_apply_transports(lc);
}
/**
@ -2296,7 +2302,7 @@ void linphone_core_enable_ipv6(LinphoneCore *lc, bool_t val){
lc->sip_conf.ipv6_enabled=val;
if (lc->sal){
/* we need to update the sip stack */
apply_transports(lc);
_linphone_core_apply_transports(lc);
}
/*update the localip immediately for the network monitor to avoid to "discover" later that we switched to ipv6*/
linphone_core_get_local_ip(lc,AF_UNSPEC,NULL,lc->localip);
@ -6830,7 +6836,7 @@ void linphone_core_set_sip_dscp(LinphoneCore *lc, int dscp){
sal_set_dscp(lc->sal,dscp);
if (linphone_core_ready(lc)){
lp_config_set_int_hex(lc->config,"sip","dscp",dscp);
apply_transports(lc);
_linphone_core_apply_transports(lc);
}
}

View file

@ -414,7 +414,7 @@ void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call);
void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md);
void linphone_call_update_remote_session_id_and_ver(LinphoneCall *call);
void linphone_call_set_state_base(LinphoneCall *call, LinphoneCallState cstate, const char *message,bool_t silently);
int _linphone_core_apply_transports(LinphoneCore *lc);
const char * linphone_core_get_identity(LinphoneCore *lc);
void linphone_core_start_waiting(LinphoneCore *lc, const char *purpose);

View file

@ -65,7 +65,7 @@ typedef enum {
SalTransportUDP, /*UDP*/
SalTransportTCP, /*TCP*/
SalTransportTLS, /*TLS*/
SalTransportDTLS /*DTLS*/
SalTransportDTLS, /*DTLS*/
}SalTransport;
#define SAL_MEDIA_DESCRIPTION_UNCHANGED 0x00
@ -516,7 +516,7 @@ void sal_signing_key_delete(SalSigningKey *key);
void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs);
int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure);
int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_tunneled);
int sal_get_listening_port(Sal *ctx, SalTransport tr);
int sal_unlisten_ports(Sal *ctx);
int sal_transport_available(Sal *ctx, SalTransport t);
@ -533,8 +533,7 @@ void sal_append_stack_string_to_user_agent(Sal *ctx);
/*keepalive period in ms*/
void sal_set_keepalive_period(Sal *ctx,unsigned int value);
void sal_use_tcp_tls_keepalive(Sal *ctx, bool_t enabled);
int sal_enable_tunnel(Sal *ctx, void *tunnelclient);
void sal_disable_tunnel(Sal *ctx);
int sal_set_tunnel(Sal *ctx, void *tunnelclient);
/*Default value is true*/
void sal_enable_sip_update_method(Sal *ctx,bool_t value);

2
oRTP

@ -1 +1 @@
Subproject commit 99edd188a5f0c708bf044d4c39da1aac436acba4
Subproject commit 497960634594593bd5441804fc548587b06389c6

View file

@ -61,7 +61,6 @@ static char* get_public_contact_ip(LinphoneCore* lc) {
}
static void call_with_transport_base(LinphoneTunnelMode tunnel_mode, bool_t with_sip, LinphoneMediaEncryption encryption) {
if (linphone_core_tunnel_available()){
char *tmp_char;
LinphoneCoreManager *pauline = linphone_core_manager_new( "pauline_rc");
LinphoneCoreManager *marie = linphone_core_manager_new( "marie_rc");
LinphoneCall *pauline_call;
@ -81,28 +80,23 @@ static void call_with_transport_base(LinphoneTunnelMode tunnel_mode, bool_t with
LinphoneTunnel *tunnel = linphone_core_get_tunnel(pauline->lc);
LinphoneTunnelConfig *config = linphone_tunnel_config_new();
/*tunnel works only in UDP mode*/
linphone_proxy_config_edit(proxy);
linphone_address_set_transport(server_addr, LinphoneTransportUdp);
linphone_address_set_transport(route, LinphoneTransportUdp);
tmp_char = linphone_address_as_string(server_addr);
linphone_proxy_config_set_server_addr(proxy, tmp_char);
ms_free(tmp_char);
tmp_char = linphone_address_as_string(route);
linphone_proxy_config_set_route(proxy, tmp_char);
ms_free(tmp_char);
linphone_tunnel_config_set_host(config, "tunnel.linphone.org");
linphone_tunnel_config_set_port(config, 443);
linphone_tunnel_config_set_remote_udp_mirror_port(config, 12345);
linphone_tunnel_add_server(tunnel, config);
linphone_tunnel_set_mode(tunnel, tunnel_mode);
linphone_tunnel_enable_sip(tunnel, with_sip);
linphone_proxy_config_done(proxy);
/*enabling the tunnel cause another REGISTER to be made*/
CU_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneRegistrationOk,2));
/*
* Enabling the tunnel with sip cause another REGISTER to be made.
* In automatic mode, the udp test should conclude (assuming we have a normal network), that no
* tunnel is needed. Thus the number of registrations should stay to 1.
* The library is missing a notification of "tunnel connectivity test finished" to enable the
* full testing of the automatic mode.
*/
if(tunnel_mode == LinphoneTunnelModeEnable) {
if(tunnel_mode == LinphoneTunnelModeEnable && with_sip) {
CU_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneRegistrationOk,2));
/* Ensure that we did use the tunnel. If so, we should see contact changed from:
Contact: <sip:pauline@192.168.0.201>;.[...]
To: