diff --git a/coreapi/TunnelManager.cc b/coreapi/TunnelManager.cc index 77e26fb1b..9b4cebda3 100644 --- a/coreapi/TunnelManager.cc +++ b/coreapi/TunnelManager.cc @@ -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 { diff --git a/coreapi/TunnelManager.hh b/coreapi/TunnelManager.hh index 58475aab3..0af89fce9 100644 --- a/coreapi/TunnelManager.hh +++ b/coreapi/TunnelManager.hh @@ -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 mEvq; -#ifndef USE_BELLESIP - TunnelSocket *mSipSocket; - eXosip_transport_hooks_t mExosipTransport; -#endif }; /** diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 875f09ad0..286fffc67 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -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 diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index ed19b19e3..21aeadc74 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -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; diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 2be6ce4eb..addb47ea9 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -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)){ diff --git a/coreapi/linphone_tunnel.cc b/coreapi/linphone_tunnel.cc index beabd43a8..9dd4e8adf 100644 --- a/coreapi/linphone_tunnel.cc +++ b/coreapi/linphone_tunnel.cc @@ -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; /* diff --git a/coreapi/linphone_tunnel.h b/coreapi/linphone_tunnel.h index 77d5e45b3..f071f3c37 100644 --- a/coreapi/linphone_tunnel.h +++ b/coreapi/linphone_tunnel.h @@ -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 diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index e02a358f8..a7d114ecc 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -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); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index c1f02e833..a476ab3e8 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -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); } } diff --git a/coreapi/private.h b/coreapi/private.h index ac274545a..314149860 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -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); diff --git a/include/sal/sal.h b/include/sal/sal.h index 74f1780bf..5fb0fbd92 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -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); diff --git a/oRTP b/oRTP index 99edd188a..497960634 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 99edd188a5f0c708bf044d4c39da1aac436acba4 +Subproject commit 497960634594593bd5441804fc548587b06389c6 diff --git a/tester/transport_tester.c b/tester/transport_tester.c index 8f0673d60..fdc4a194f 100644 --- a/tester/transport_tester.c +++ b/tester/transport_tester.c @@ -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: ;.[...] To: