diff options
author | JackLivio <jack@livio.io> | 2019-01-22 13:27:43 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-22 13:27:43 -0500 |
commit | 8768bf96919413230d23f859b563bd95e6629e35 (patch) | |
tree | 924088cc34ba1ecb64a128e325ab0b5eaf41927b | |
parent | 8b15b81ea2a8e35d69c6c7cb9841b9b451ab0c11 (diff) | |
parent | 9f48c541b2ffefb0c34aacc22075cab849dcaea4 (diff) | |
download | sdl_core-8768bf96919413230d23f859b563bd95e6629e35.tar.gz |
Merge pull request #2742 from smartdevicelink/feature/cloud_app_connection_flow
Cloud app connection flow
52 files changed, 1647 insertions, 16 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a180b6cf9..f6ee77a143 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ option(EXTENDED_MEDIA_MODE "Turn on and off extended Madia Manager features rela option(BUILD_SHARED_LIBS "Build all libraries as shared (if ON) or static (if OFF)" OFF) option(BUILD_BT_SUPPORT "Bluetooth support" ON) option(BUILD_USB_SUPPORT "libusb support" ON) +option(BUILD_CLOUD_APP_SUPPORT "Cloud App Transport Support" ON) option(BUILD_BACKTRACE_SUPPORT "backtrace support" ON) option(BUILD_TESTS "Possibility to build and run tests" OFF) option(TELEMETRY_MONITOR "Enable profiling time test util" ON) @@ -315,6 +316,11 @@ if (BUILD_BT_SUPPORT) message(STATUS "Bluetooth support enabled") endif() +if (BUILD_CLOUD_APP_SUPPORT) + add_definitions(-DCLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT) + message(STATUS "Cloud app websocket support enabled") +endif() + if (BUILD_BACKTRACE_SUPPORT) add_definitions(-DBACKTRACE_SUPPORT) message(STATUS "Backtrace support enabled") diff --git a/src/3rd_party/CMakeLists.txt b/src/3rd_party/CMakeLists.txt index bdb96de417..60d68e9d60 100644 --- a/src/3rd_party/CMakeLists.txt +++ b/src/3rd_party/CMakeLists.txt @@ -209,7 +209,7 @@ else() ) endif() -find_package(Boost 1.66.0 COMPONENTS system thread date_time filesystem) +find_package(Boost 1.66.0 COMPONENTS system thread date_time filesystem regex) set(BOOST_LIB_SOURCE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/boost_src) set(BOOST_LIBS_DIRECTORY ${3RD_PARTY_INSTALL_PREFIX}/lib) SET_PROPERTY(GLOBAL PROPERTY GLOBAL_BOOST_LIBS ${BOOST_LIBS_DIRECTORY}) @@ -226,9 +226,9 @@ if (NOT ${Boost_FOUND}) URL https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.tar.gz DOWNLOAD_DIR ${BOOST_LIB_SOURCE_DIRECTORY} SOURCE_DIR ${BOOST_LIB_SOURCE_DIRECTORY} - CONFIGURE_COMMAND ./bootstrap.sh --with-libraries=system,thread,date_time,filesystem --prefix=${3RD_PARTY_INSTALL_PREFIX} + CONFIGURE_COMMAND ./bootstrap.sh --with-libraries=system,thread,date_time,filesystem,regex --prefix=${3RD_PARTY_INSTALL_PREFIX} BUILD_COMMAND ./b2 - INSTALL_COMMAND ${BOOST_INSTALL_COMMAND} --with-system --with-thread --with-date_time --with-filesystem --prefix=${3RD_PARTY_INSTALL_PREFIX} > boost_install.log + INSTALL_COMMAND ${BOOST_INSTALL_COMMAND} --with-system --with-thread --with-date_time --with-filesystem --with-regex --prefix=${3RD_PARTY_INSTALL_PREFIX} > boost_install.log INSTALL_DIR ${3RD_PARTY_INSTALL_PREFIX} BUILD_IN_SOURCE true ) diff --git a/src/appMain/smartDeviceLink.ini b/src/appMain/smartDeviceLink.ini index b0513c076f..ccb377d1e6 100644 --- a/src/appMain/smartDeviceLink.ini +++ b/src/appMain/smartDeviceLink.ini @@ -202,6 +202,12 @@ TCPAdapterPort = 12345 ; If the name is omitted, Core will listen on all network interfaces by binding to INADDR_ANY. TCPAdapterNetworkInterface = +[CloudAppConnections] +; Value in milliseconds for time between retry attempts on a failed websocket connection +CloudAppRetryTimeout = 1000 +; MaxNn number of retry attempts for a cloud websocket connection +CloudAppMaxRetryAttempts = 5 + [ProtocolHandler] ; SDL supported protocol version MaxSupportedProtocolVersion = 5 diff --git a/src/components/application_manager/include/application_manager/application.h b/src/components/application_manager/include/application_manager/application.h index ad7570955e..2abd2eaea0 100644 --- a/src/components/application_manager/include/application_manager/application.h +++ b/src/components/application_manager/include/application_manager/application.h @@ -946,6 +946,67 @@ class Application : public virtual InitialApplicationData, */ virtual const std::list<AppExtensionPtr>& Extensions() const = 0; + /** + * @brief Get cloud app endpoint for websocket connection + * @return cloud app endpoint + */ + virtual const std::string& cloud_app_endpoint() const = 0; + + /** + * @brief Get cloud app auth token to be used in connection handshake after + * websocket open. + * @return cloud app auth token + */ + virtual const std::string& cloud_app_auth_token() const = 0; + + /** + * @brief Get cloud app tranpsport type. Defines the type of websocket + * connection used. + * @return cloud app transport type + */ + virtual const std::string& cloud_app_transport_type() const = 0; + + /** + * @brief Get hybrid app preference. Defines behaviour for when a similar + * mobile and cloud app are connected simultaneously. + * @return hybrid app preference + */ + virtual const mobile_apis::HybridAppPreference::eType& hybrid_app_preference() + const = 0; + + /** + * @brief Get cloud app certificate. Used for secured websocket connections. + * @return cloud app certificate. + */ + virtual const std::string& cloud_app_certificate() const = 0; + + /** + * @brief Set cloud app endpoint + */ + virtual void set_cloud_app_endpoint(const std::string& endpoint) = 0; + + /** + * @brief Set cloud app auth token + */ + virtual void set_cloud_app_auth_token(const std::string& auth_token) = 0; + + /** + * @brief Set cloud app transport type + */ + virtual void set_cloud_app_transport_type( + const std::string& transport_type) = 0; + + /** + * @brief Set hybrid app preference + */ + virtual void set_hybrid_app_preference( + const mobile_apis::HybridAppPreference::eType& hybrid_app_preference) = 0; + + /** + * @brief Set cloud app certificate + */ + virtual void set_cloud_app_certificate(const std::string& certificate) = 0; + protected: mutable sync_primitives::Lock hmi_states_lock_; diff --git a/src/components/application_manager/include/application_manager/application_impl.h b/src/components/application_manager/include/application_manager/application_impl.h index 8dc3b2da20..0b43b014b6 100644 --- a/src/components/application_manager/include/application_manager/application_impl.h +++ b/src/components/application_manager/include/application_manager/application_impl.h @@ -409,6 +409,66 @@ class ApplicationImpl : public virtual Application, void SwapMobileMessageQueue(MobileMessageQueue& mobile_messages) OVERRIDE; + /** + * @brief Get cloud app endpoint for websocket connection + * @return cloud app endpoint + */ + const std::string& cloud_app_endpoint() const OVERRIDE; + + /** + * @brief Get cloud app auth token to be used in connection handshake after + * websocket open. + * @return cloud app auth token + */ + const std::string& cloud_app_auth_token() const OVERRIDE; + + /** + * @brief Get cloud app tranpsport type. Defines the type of websocket + * connection used. + * @return cloud app transport type + */ + const std::string& cloud_app_transport_type() const OVERRIDE; + + /** + * @brief Get hybrid app preference. Defines behaviour for when a similar + * mobile and cloud app are connected simultaneously. + * @return hybrid app preference + */ + const mobile_apis::HybridAppPreference::eType& hybrid_app_preference() + const OVERRIDE; + + /** + * @brief Get cloud app certificate. Used for secured websocket connections. + * @return cloud app certificate. + */ + const std::string& cloud_app_certificate() const OVERRIDE; + + /** + * @brief Set cloud app endpoint + */ + void set_cloud_app_endpoint(const std::string& endpoint) OVERRIDE; + + /** + * @brief Set cloud app auth token + */ + void set_cloud_app_auth_token(const std::string& auth_token) OVERRIDE; + + /** + * @brief Set cloud app transport type + */ + void set_cloud_app_transport_type(const std::string& transport_type) OVERRIDE; + + /** + * @brief Set hybrid app preference + */ + void set_hybrid_app_preference(const mobile_apis::HybridAppPreference::eType& + hybrid_app_preference) OVERRIDE; + + /** + * @brief Set cloud app certificate + */ + void set_cloud_app_certificate(const std::string& certificate) OVERRIDE; + protected: /** * @brief Clean up application folder. Persistent files will stay @@ -513,6 +573,13 @@ class ApplicationImpl : public virtual Application, std::list<AppExtensionPtr> extensions_; + // Cloud app properties + std::string endpoint_; + std::string auth_token_; + std::string cloud_transport_type_; + mobile_apis::HybridAppPreference::eType hybrid_app_preference_; + std::string certificate_; + /** * @brief Defines number per time in seconds limits */ diff --git a/src/components/application_manager/include/application_manager/application_manager_impl.h b/src/components/application_manager/include/application_manager/application_manager_impl.h index 6c111dbbb3..20b8c561a3 100644 --- a/src/components/application_manager/include/application_manager/application_manager_impl.h +++ b/src/components/application_manager/include/application_manager/application_manager_impl.h @@ -360,6 +360,13 @@ class ApplicationManagerImpl void ConnectToDevice(const std::string& device_mac) OVERRIDE; void OnHMIStartedCooperation() OVERRIDE; + void CollectCloudAppInformation(); + + void CreatePendingApplication( + const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info, + connection_handler::DeviceHandle device_id); + /* * @brief Returns unique correlation ID for HMI request * @@ -1449,6 +1456,8 @@ class ApplicationManagerImpl DeviceMap secondary_transport_devices_cache_; + std::map<std::string, std::string> pending_device_map_; + #ifdef TELEMETRY_MONITOR AMTelemetryObserver* metric_observer_; #endif // TELEMETRY_MONITOR diff --git a/src/components/application_manager/src/application_impl.cc b/src/components/application_manager/src/application_impl.cc index 8a611195c7..558a4638c1 100644 --- a/src/components/application_manager/src/application_impl.cc +++ b/src/components/application_manager/src/application_impl.cc @@ -1163,6 +1163,50 @@ const std::list<AppExtensionPtr>& ApplicationImpl::Extensions() const { return extensions_; } +const std::string& ApplicationImpl::cloud_app_endpoint() const { + return endpoint_; +} + +const std::string& ApplicationImpl::cloud_app_auth_token() const { + return auth_token_; +} + +const std::string& ApplicationImpl::cloud_app_transport_type() const { + return cloud_transport_type_; +} + +const mobile_apis::HybridAppPreference::eType& +ApplicationImpl::hybrid_app_preference() const { + return hybrid_app_preference_; +} + +const std::string& ApplicationImpl::cloud_app_certificate() const { + return certificate_; +} + +void ApplicationImpl::set_cloud_app_endpoint(const std::string& endpoint) { + endpoint_ = endpoint; +} + +void ApplicationImpl::set_cloud_app_auth_token(const std::string& auth_token) { + auth_token_ = auth_token; +} + +void ApplicationImpl::set_cloud_app_transport_type( + const std::string& transport_type) { + cloud_transport_type_ = transport_type; +} + +void ApplicationImpl::set_hybrid_app_preference( + const mobile_apis::HybridAppPreference::eType& hybrid_app_preference) { + hybrid_app_preference_ = hybrid_app_preference; +} + +void ApplicationImpl::set_cloud_app_certificate( + const std::string& certificate) { + certificate_ = certificate; +} + void ApplicationImpl::PushMobileMessage( smart_objects::SmartObjectSPtr mobile_message) { sync_primitives::AutoLock lock(mobile_message_lock_); diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index 24f27af2e2..3b5c1b2c7c 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -98,7 +98,9 @@ DeviceTypes devicesType = { std::make_pair(std::string("USB_IOS_DEVICE_MODE"), hmi_apis::Common_TransportType::USB_IOS), std::make_pair(std::string("CARPLAY_WIRELESS_IOS"), - hmi_apis::Common_TransportType::WIFI)}; + hmi_apis::Common_TransportType::WIFI), + std::make_pair(std::string("CLOUD_WEBSOCKET"), + hmi_apis::Common_TransportType::CLOUD_WEBSOCKET)}; } /** @@ -779,6 +781,120 @@ void ApplicationManagerImpl::OnHMIStartedCooperation() { *this)); rpc_service_->ManageHMICommand(mixing_audio_supported_request); resume_controller().ResetLaunchTime(); + + CollectCloudAppInformation(); +} + +void ApplicationManagerImpl::CollectCloudAppInformation() { + std::vector<std::string> cloud_app_id_vector; + GetPolicyHandler().GetEnabledCloudApps(cloud_app_id_vector); + std::vector<std::string>::iterator it = cloud_app_id_vector.begin(); + std::vector<std::string>::iterator end = cloud_app_id_vector.end(); + std::string endpoint = ""; + std::string certificate = ""; + std::string auth_token = ""; + std::string cloud_transport_type = ""; + std::string hybrid_app_preference = ""; + bool enabled = true; + for (; it != end; ++it) { + GetPolicyHandler().GetCloudAppParameters(*it, + enabled, + endpoint, + certificate, + auth_token, + cloud_transport_type, + hybrid_app_preference); + + pending_device_map_.insert( + std::pair<std::string, std::string>(endpoint, *it)); + + connection_handler().AddCloudAppDevice(endpoint, cloud_transport_type); + } +} + +void ApplicationManagerImpl::CreatePendingApplication( + const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info, + connection_handler::DeviceHandle device_id) { + LOG4CXX_AUTO_TRACE(logger_); + + std::string endpoint = ""; + std::string certificate = ""; + std::string auth_token = ""; + std::string cloud_transport_type = ""; + std::string hybrid_app_preference_str = ""; + bool enabled = true; + std::string name = device_info.name(); + auto it = pending_device_map_.find(name); + if (it == pending_device_map_.end()) { + return; + } + + const std::string policy_app_id = it->second; + + policy::StringArray nicknames; + policy::StringArray app_hmi_types; + + GetPolicyHandler().GetInitialAppData( + policy_app_id, &nicknames, &app_hmi_types); + + if (!nicknames.size()) { + LOG4CXX_ERROR(logger_, "Cloud App missing nickname"); + return; + } + + const std::string display_name = nicknames[0]; + + ApplicationSharedPtr application( + new ApplicationImpl(0, + policy_app_id, + device_info.mac_address(), + device_id, + custom_str::CustomString(display_name), + GetPolicyHandler().GetStatisticManager(), + *this)); + + if (!application) { + LOG4CXX_INFO(logger_, "Could not streate application"); + return; + } + + GetPolicyHandler().GetCloudAppParameters(policy_app_id, + enabled, + endpoint, + certificate, + auth_token, + cloud_transport_type, + hybrid_app_preference_str); + + mobile_apis::HybridAppPreference::eType hybrid_app_preference_enum; + + bool convert_result = smart_objects::EnumConversionHelper< + mobile_apis::HybridAppPreference::eType>:: + StringToEnum(hybrid_app_preference_str, &hybrid_app_preference_enum); + + if (!hybrid_app_preference_str.empty() && !convert_result) { + LOG4CXX_ERROR( + logger_, + "Could not convert string to enum: " << hybrid_app_preference_str); + return; + } + + application->set_hmi_application_id(GenerateNewHMIAppID()); + application->set_cloud_app_endpoint(endpoint); + application->set_cloud_app_auth_token(auth_token); + application->set_cloud_app_transport_type(cloud_transport_type); + application->set_hybrid_app_preference(hybrid_app_preference_enum); + application->set_cloud_app_certificate(certificate); + + sync_primitives::AutoLock lock(apps_to_register_list_lock_ptr_); + LOG4CXX_DEBUG(logger_, + "apps_to_register_ size before: " << apps_to_register_.size()); + apps_to_register_.insert(application); + LOG4CXX_DEBUG(logger_, + "apps_to_register_ size after: " << apps_to_register_.size()); + + SendUpdateAppList(); } uint32_t ApplicationManagerImpl::GetNextHMICorrelationID() { diff --git a/src/components/application_manager/test/include/application_manager/mock_application.h b/src/components/application_manager/test/include/application_manager/mock_application.h index fe16e8ce6e..9c9041284c 100644 --- a/src/components/application_manager/test/include/application_manager/mock_application.h +++ b/src/components/application_manager/test/include/application_manager/mock_application.h @@ -342,6 +342,20 @@ class MockApplication : public ::application_manager::Application { const std::list<application_manager::AppExtensionPtr>&()); MOCK_CONST_METHOD0(is_remote_control_supported, bool()); MOCK_METHOD1(set_remote_control_supported, void(const bool allow)); + MOCK_CONST_METHOD0(cloud_app_endpoint, const std::string&()); + MOCK_CONST_METHOD0(cloud_app_auth_token, const std::string&()); + MOCK_CONST_METHOD0(cloud_app_transport_type, const std::string&()); + MOCK_CONST_METHOD0(hybrid_app_preference, + const mobile_apis::HybridAppPreference::eType&()); + MOCK_CONST_METHOD0(cloud_app_certificate, const std::string&()); + MOCK_METHOD1(set_cloud_app_endpoint, void(const std::string& endpoint)); + MOCK_METHOD1(set_cloud_app_auth_token, void(const std::string& auth_token)); + MOCK_METHOD1(set_cloud_app_transport_type, + void(const std::string& transport_type)); + MOCK_METHOD1(set_hybrid_app_preference, + void(const mobile_apis::HybridAppPreference::eType& + hybrid_app_preference)); + MOCK_METHOD1(set_cloud_app_certificate, void(const std::string& certificate)); }; } // namespace application_manager_test diff --git a/src/components/config_profile/include/config_profile/profile.h b/src/components/config_profile/include/config_profile/profile.h index 57e925cd43..4846648b2b 100644 --- a/src/components/config_profile/include/config_profile/profile.h +++ b/src/components/config_profile/include/config_profile/profile.h @@ -413,6 +413,16 @@ class Profile : public protocol_handler::ProtocolHandlerSettings, const std::string& transport_manager_tcp_adapter_network_interface() const OVERRIDE; + /** + * @brief Returns retry timeout for cloud app connections + */ + uint32_t cloud_app_retry_timeout() const OVERRIDE; + + /** + * @brief Returns maximum retry attempts for cloud app connections + */ + uint16_t cloud_app_max_retry_attempts() const OVERRIDE; + // TransportManageMMESettings interface const std::string& event_mq_name() const OVERRIDE; @@ -960,6 +970,8 @@ class Profile : public protocol_handler::ProtocolHandlerSettings, std::string system_files_path_; uint16_t transport_manager_tcp_adapter_port_; std::string transport_manager_tcp_adapter_network_interface_; + uint32_t cloud_app_retry_timeout_; + uint16_t cloud_app_max_retry_attempts_; std::string tts_delimiter_; uint32_t audio_data_stopped_timeout_; uint32_t video_data_stopped_timeout_; diff --git a/src/components/config_profile/src/profile.cc b/src/components/config_profile/src/profile.cc index 57984324aa..38afdbf35b 100644 --- a/src/components/config_profile/src/profile.cc +++ b/src/components/config_profile/src/profile.cc @@ -81,6 +81,7 @@ const char* kMediaManagerSection = "MEDIA MANAGER"; const char* kGlobalPropertiesSection = "GLOBAL PROPERTIES"; const char* kVrCommandsSection = "VR COMMANDS"; const char* kTransportManagerSection = "TransportManager"; +const char* kCloudAppTransportSection = "CloudAppConnections"; const char* kApplicationManagerSection = "ApplicationManager"; const char* kFilesystemRestrictionsSection = "FILESYSTEM RESTRICTIONS"; const char* kIAPSection = "IAP"; @@ -154,6 +155,8 @@ const char* kMaxSupportedProtocolVersionKey = "MaxSupportedProtocolVersion"; const char* kUseLastStateKey = "UseLastState"; const char* kTCPAdapterPortKey = "TCPAdapterPort"; const char* kTCPAdapterNetworkInterfaceKey = "TCPAdapterNetworkInterface"; +const char* kCloudAppRetryTimeoutKey = "CloudAppRetryTimeout"; +const char* kCloudAppMaxRetryAttemptsKey = "CloudAppMaxRetryAttempts"; const char* kServerPortKey = "ServerPort"; const char* kVideoStreamingPortKey = "VideoStreamingPort"; const char* kAudioStreamingPortKey = "AudioStreamingPort"; @@ -318,6 +321,8 @@ const uint32_t kDefaultHubProtocolIndex = 0; const uint32_t kDefaultHeartBeatTimeout = 0; const uint16_t kDefaultMaxSupportedProtocolVersion = 5; const uint16_t kDefautTransportManagerTCPPort = 12345; +const uint16_t kDefaultCloudAppRetryTimeout = 1000; +const uint16_t kDefaultCloudAppMaxRetryAttempts = 5; const uint16_t kDefaultServerPort = 8087; const uint16_t kDefaultVideoStreamingPort = 5050; const uint16_t kDefaultAudioStreamingPort = 5080; @@ -452,6 +457,8 @@ Profile::Profile() , supported_diag_modes_() , system_files_path_(kDefaultSystemFilesPath) , transport_manager_tcp_adapter_port_(kDefautTransportManagerTCPPort) + , cloud_app_retry_timeout_(kDefaultCloudAppRetryTimeout) + , cloud_app_max_retry_attempts_(kDefaultCloudAppMaxRetryAttempts) , tts_delimiter_(kDefaultTtsDelimiter) , audio_data_stopped_timeout_(kDefaultAudioDataStoppedTimeout) , video_data_stopped_timeout_(kDefaultVideoDataStoppedTimeout) @@ -784,6 +791,14 @@ const std::string& Profile::transport_manager_tcp_adapter_network_interface() return transport_manager_tcp_adapter_network_interface_; } +uint32_t Profile::cloud_app_retry_timeout() const { + return cloud_app_retry_timeout_; +} + +uint16_t Profile::cloud_app_max_retry_attempts() const { + return cloud_app_max_retry_attempts_; +} + const std::string& Profile::tts_delimiter() const { return tts_delimiter_; } @@ -1769,6 +1784,24 @@ void Profile::UpdateValues() { kTCPAdapterNetworkInterfaceKey, kTransportManagerSection); + ReadUIntValue(&cloud_app_retry_timeout_, + kDefaultCloudAppRetryTimeout, + kCloudAppTransportSection, + kCloudAppRetryTimeoutKey); + + LOG_UPDATED_VALUE(cloud_app_retry_timeout_, + kCloudAppRetryTimeoutKey, + kCloudAppTransportSection); + + ReadUIntValue(&cloud_app_max_retry_attempts_, + kDefaultCloudAppMaxRetryAttempts, + kCloudAppTransportSection, + kCloudAppMaxRetryAttemptsKey); + + LOG_UPDATED_VALUE(cloud_app_max_retry_attempts_, + kCloudAppMaxRetryAttemptsKey, + kCloudAppTransportSection); + // Event MQ ReadStringValue( &event_mq_name_, kDefaultEventMQ, kTransportManagerSection, kEventMQKey); diff --git a/src/components/connection_handler/include/connection_handler/connection_handler_impl.h b/src/components/connection_handler/include/connection_handler/connection_handler_impl.h index 1ab70ce702..899d17995c 100644 --- a/src/components/connection_handler/include/connection_handler/connection_handler_impl.h +++ b/src/components/connection_handler/include/connection_handler/connection_handler_impl.h @@ -120,6 +120,9 @@ class ConnectionHandlerImpl void ConnectToAllDevices() OVERRIDE; + void AddCloudAppDevice(const std::string& endpoint, + const std::string& cloud_transport_type) OVERRIDE; + void StartTransportManager() OVERRIDE; void OnDeviceListUpdated( @@ -163,6 +166,14 @@ class ConnectionHandlerImpl const transport_manager::SearchDeviceError& error) OVERRIDE; /** + * \brief Notifies about pending connection. + * + * \param connection_id ID of new connection. + **/ + void OnConnectionPending( + const transport_manager::DeviceInfo& device_info, + const transport_manager::ConnectionUID connection_id) OVERRIDE; + /** * \brief Notifies about established connection. * * \param connection_id ID of new connection. diff --git a/src/components/connection_handler/src/connection_handler_impl.cc b/src/components/connection_handler/src/connection_handler_impl.cc index 478127c42a..9dc78613fc 100644 --- a/src/components/connection_handler/src/connection_handler_impl.cc +++ b/src/components/connection_handler/src/connection_handler_impl.cc @@ -142,6 +142,11 @@ void ConnectionHandlerImpl::OnDeviceAdded( LOG4CXX_AUTO_TRACE(logger_); auto handle = device_info.device_handle(); + LOG4CXX_DEBUG(logger_, + "OnDeviceAdded!!!: " << handle << " " << device_info.name() + << " " << device_info.mac_address() << " " + << device_info.connection_type()); + Device device(handle, device_info.name(), device_info.mac_address(), @@ -244,11 +249,51 @@ void ConnectionHandlerImpl::OnScanDevicesFailed( LOG4CXX_WARN(logger_, "Scan devices failed. " << error.text()); } -void ConnectionHandlerImpl::OnConnectionEstablished( +void ConnectionHandlerImpl::OnConnectionPending( const transport_manager::DeviceInfo& device_info, const transport_manager::ConnectionUID connection_id) { LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, + "OnConnectionEstablished!!!: " + << device_info.device_handle() << " " << device_info.name() + << " " << device_info.mac_address() << " " + << device_info.connection_type()); + DeviceMap::iterator it = device_list_.find(device_info.device_handle()); + if (device_list_.end() == it) { + LOG4CXX_ERROR(logger_, "Unknown device!"); + return; + } + LOG4CXX_DEBUG(logger_, + "Add Pending Connection #" << connection_id << " to the list."); + + sync_primitives::AutoWriteLock lock(connection_list_lock_); + if (connection_list_.find(connection_id) == connection_list_.end()) { + Connection* connection = + new Connection(connection_id, + device_info.device_handle(), + this, + get_settings().heart_beat_timeout()); + + connection_list_.insert( + ConnectionList::value_type(connection_id, connection)); + connection_handler::DeviceHandle device_id = + connection->connection_device_handle(); + + connection_handler_observer_->CreatePendingApplication( + connection_id, device_info, device_id); + } +} + +void ConnectionHandlerImpl::OnConnectionEstablished( + const transport_manager::DeviceInfo& device_info, + const transport_manager::ConnectionUID connection_id) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, + "OnConnectionEstablished!!!: " + << device_info.device_handle() << " " << device_info.name() + << " " << device_info.mac_address() << " " + << device_info.connection_type()); DeviceMap::iterator it = device_list_.find(device_info.device_handle()); if (device_list_.end() == it) { LOG4CXX_ERROR(logger_, "Unknown device!"); @@ -257,12 +302,14 @@ void ConnectionHandlerImpl::OnConnectionEstablished( LOG4CXX_DEBUG(logger_, "Add Connection #" << connection_id << " to the list."); sync_primitives::AutoWriteLock lock(connection_list_lock_); - connection_list_.insert(ConnectionList::value_type( - connection_id, - new Connection(connection_id, - device_info.device_handle(), - this, - get_settings().heart_beat_timeout()))); + if (connection_list_.find(connection_id) == connection_list_.end()) { + connection_list_.insert(ConnectionList::value_type( + connection_id, + new Connection(connection_id, + device_info.device_handle(), + this, + get_settings().heart_beat_timeout()))); + } } void ConnectionHandlerImpl::OnConnectionFailed( @@ -1267,6 +1314,11 @@ void ConnectionHandlerImpl::ConnectToAllDevices() { } } +void ConnectionHandlerImpl::AddCloudAppDevice( + const std::string& endpoint, const std::string& cloud_transport_type) { + transport_manager_.AddCloudDevice(endpoint, cloud_transport_type); +} + void ConnectionHandlerImpl::StartTransportManager() { LOG4CXX_AUTO_TRACE(logger_); transport_manager_.Visibility(true); diff --git a/src/components/include/connection_handler/connection_handler.h b/src/components/include/connection_handler/connection_handler.h index a50760b547..9ca9a8d144 100644 --- a/src/components/include/connection_handler/connection_handler.h +++ b/src/components/include/connection_handler/connection_handler.h @@ -93,6 +93,9 @@ class ConnectionHandler { virtual void ConnectToAllDevices() = 0; + virtual void AddCloudAppDevice(const std::string& endpoint, + const std::string& cloud_transport_type) = 0; + /** * @brief Close the connection revoked by Policy * @param connection_key pair of connection and session id diff --git a/src/components/include/connection_handler/connection_handler_observer.h b/src/components/include/connection_handler/connection_handler_observer.h index 154a2a8e34..298f98803a 100644 --- a/src/components/include/connection_handler/connection_handler_observer.h +++ b/src/components/include/connection_handler/connection_handler_observer.h @@ -161,6 +161,11 @@ class ConnectionHandlerObserver { */ virtual void OnSecondaryTransportEndedCallback(const int32_t session_key) = 0; + virtual void CreatePendingApplication( + const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info, + connection_handler::DeviceHandle device_id) = 0; + protected: /** * \brief Destructor diff --git a/src/components/include/test/connection_handler/mock_connection_handler.h b/src/components/include/test/connection_handler/mock_connection_handler.h index 2de3a0f9a7..cde835759f 100644 --- a/src/components/include/test/connection_handler/mock_connection_handler.h +++ b/src/components/include/test/connection_handler/mock_connection_handler.h @@ -63,6 +63,9 @@ class MockConnectionHandler : public connection_handler::ConnectionHandler { MOCK_CONST_METHOD2(RunAppOnDevice, void(const std::string&, const std::string&)); MOCK_METHOD0(ConnectToAllDevices, void()); + MOCK_METHOD2(AddCloudAppDevice, + void(const std::string& endpoint, + const std::string& cloud_transport_type)); MOCK_METHOD1(CloseRevokedConnection, void(uint32_t connection_key)); MOCK_METHOD1(CloseConnection, void(ConnectionHandle connection_handle)); MOCK_METHOD1(GetConnectionSessionsCount, uint32_t(uint32_t connection_key)); diff --git a/src/components/include/test/connection_handler/mock_connection_handler_observer.h b/src/components/include/test/connection_handler/mock_connection_handler_observer.h index a9e4349bec..2984b2e471 100644 --- a/src/components/include/test/connection_handler/mock_connection_handler_observer.h +++ b/src/components/include/test/connection_handler/mock_connection_handler_observer.h @@ -74,6 +74,10 @@ class MockConnectionHandlerObserver const int32_t session_key)); MOCK_METHOD1(OnSecondaryTransportEndedCallback, void(const int32_t session_key)); + MOCK_METHOD3(CreatePendingApplication, + void(const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info, + connection_handler::DeviceHandle device_id)); }; } // namespace connection_handler_test diff --git a/src/components/include/test/transport_manager/mock_transport_manager.h b/src/components/include/test/transport_manager/mock_transport_manager.h index cc8bd5ab85..e3f01fccb5 100644 --- a/src/components/include/test/transport_manager/mock_transport_manager.h +++ b/src/components/include/test/transport_manager/mock_transport_manager.h @@ -59,6 +59,9 @@ class MockTransportManager : public ::transport_manager::TransportManager, MOCK_METHOD1(Init, int(resumption::LastState& last_state)); MOCK_METHOD0(Reinit, int()); MOCK_METHOD0(SearchDevices, int()); + MOCK_METHOD2(AddCloudDevice, + void(const std::string& endpoint, + const std::string& cloud_transport_type)); MOCK_METHOD1(ConnectDevice, int(const DeviceHandle)); MOCK_METHOD1(DisconnectDevice, int(const DeviceHandle)); MOCK_METHOD1(Disconnect, int(const ConnectionUID)); diff --git a/src/components/include/test/transport_manager/mock_transport_manager_listener.h b/src/components/include/test/transport_manager/mock_transport_manager_listener.h index 133dabe732..734651f455 100644 --- a/src/components/include/test/transport_manager/mock_transport_manager_listener.h +++ b/src/components/include/test/transport_manager/mock_transport_manager_listener.h @@ -55,6 +55,9 @@ class MockTransportManagerListener : public TransportManagerListener { MOCK_METHOD1(OnDeviceRemoved, void(const DeviceInfo& device_info)); MOCK_METHOD0(OnScanDevicesFinished, void()); MOCK_METHOD1(OnScanDevicesFailed, void(const SearchDeviceError& error)); + MOCK_METHOD2(OnConnectionPending, + void(const DeviceInfo& device_info, + const ConnectionUID connection_id)); MOCK_METHOD2(OnConnectionEstablished, void(const DeviceInfo& device_info, const ConnectionUID connection_id)); diff --git a/src/components/include/test/transport_manager/mock_transport_manager_settings.h b/src/components/include/test/transport_manager/mock_transport_manager_settings.h index 3e7c8f36f7..bed0d5e6e6 100644 --- a/src/components/include/test/transport_manager/mock_transport_manager_settings.h +++ b/src/components/include/test/transport_manager/mock_transport_manager_settings.h @@ -63,6 +63,8 @@ class MockTransportManagerSettings MOCK_CONST_METHOD0(app_transport_change_timer_addition, uint32_t()); MOCK_CONST_METHOD0(transport_manager_tcp_adapter_network_interface, std::string&()); + MOCK_CONST_METHOD0(cloud_app_retry_timeout, uint32_t()); + MOCK_CONST_METHOD0(cloud_app_max_retry_attempts, uint16_t()); }; } // namespace transport_manager_test diff --git a/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h b/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h index eff0abdcd3..0be4da1063 100644 --- a/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h +++ b/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h @@ -105,6 +105,8 @@ class MockTransportAdapter transport_manager::SwitchableDevices()); MOCK_CONST_METHOD0(GetTransportConfiguration, transport_manager::transport_adapter::TransportConfig()); + MOCK_METHOD1(CreateDevice, void(const std::string& uid)); + #ifdef TELEMETRY_MONITOR MOCK_METHOD0(GetTelemetryObserver, ::transport_manager::TMTelemetryObserver*()); diff --git a/src/components/include/transport_manager/transport_adapter/transport_adapter.h b/src/components/include/transport_manager/transport_adapter/transport_adapter.h index ebbf7dae28..aae4a8b569 100644 --- a/src/components/include/transport_manager/transport_adapter/transport_adapter.h +++ b/src/components/include/transport_manager/transport_adapter/transport_adapter.h @@ -64,6 +64,7 @@ enum DeviceType { IOS_BT, IOS_USB, TCP, + CLOUD_WEBSOCKET, IOS_USB_HOST_MODE, IOS_USB_DEVICE_MODE, IOS_CARPLAY_WIRELESS, // running on iAP over Carplay wireless transport @@ -327,6 +328,8 @@ class TransportAdapter { */ virtual TransportConfig GetTransportConfiguration() const = 0; + virtual void CreateDevice(const std::string& uid) = 0; + #ifdef TELEMETRY_MONITOR /** * @brief Return Time metric observer diff --git a/src/components/include/transport_manager/transport_adapter/transport_adapter_event.h b/src/components/include/transport_manager/transport_adapter/transport_adapter_event.h index fd1d693067..921562333b 100644 --- a/src/components/include/transport_manager/transport_adapter/transport_adapter_event.h +++ b/src/components/include/transport_manager/transport_adapter/transport_adapter_event.h @@ -58,7 +58,8 @@ enum class EventTypeEnum { ON_COMMUNICATION_ERROR, ON_UNEXPECTED_DISCONNECT, ON_TRANSPORT_SWITCH_REQUESTED, - ON_TRANSPORT_CONFIG_UPDATED + ON_TRANSPORT_CONFIG_UPDATED, + ON_CONNECT_PENDING }; class TransportAdapterEvent { diff --git a/src/components/include/transport_manager/transport_manager.h b/src/components/include/transport_manager/transport_manager.h index 0847886c46..b5dfa3671b 100644 --- a/src/components/include/transport_manager/transport_manager.h +++ b/src/components/include/transport_manager/transport_manager.h @@ -75,6 +75,9 @@ class TransportManager { **/ virtual int SearchDevices() = 0; + virtual void AddCloudDevice(const std::string& endpoint, + const std::string& cloud_transport_type) = 0; + /** * @brief Connect to all applications discovered on device. * diff --git a/src/components/include/transport_manager/transport_manager_listener.h b/src/components/include/transport_manager/transport_manager_listener.h index 6c3f6e2eaa..7da4bcc2f5 100644 --- a/src/components/include/transport_manager/transport_manager_listener.h +++ b/src/components/include/transport_manager/transport_manager_listener.h @@ -101,6 +101,14 @@ class TransportManagerListener { virtual void OnScanDevicesFailed(const SearchDeviceError& error) = 0; /** + * @brief Reaction to the event, when connection is pending. + * + * @param devcie_info Variable that hold information about device. + * @param connection_id connection unique identifier. + */ + virtual void OnConnectionPending(const DeviceInfo& device_info, + const ConnectionUID connection_id) = 0; + /** * @brief Reaction to the event, when connection is established. * * @param devcie_info Variable that hold information about device. diff --git a/src/components/include/transport_manager/transport_manager_listener_empty.h b/src/components/include/transport_manager/transport_manager_listener_empty.h index 08b2b77c30..c0a713f38e 100644 --- a/src/components/include/transport_manager/transport_manager_listener_empty.h +++ b/src/components/include/transport_manager/transport_manager_listener_empty.h @@ -99,6 +99,15 @@ class TransportManagerListenerEmpty : public TransportManagerListener { void OnScanDevicesFailed(const SearchDeviceError& error) OVERRIDE {} /** + * @brief Reaction to the event, when connection is pending. + * + * @param devcie_info Variable that hold information about device. + * @param connection_id connection unique identifier. + */ + void OnConnectionPending(const DeviceInfo& device_info, + const ConnectionUID connection_id) OVERRIDE {} + + /** * @brief Reaction to the event, when connection is established. * * @param devcie_info Variable that hold information about device. diff --git a/src/components/include/transport_manager/transport_manager_settings.h b/src/components/include/transport_manager/transport_manager_settings.h index 3912bbe747..cbc1516c29 100644 --- a/src/components/include/transport_manager/transport_manager_settings.h +++ b/src/components/include/transport_manager/transport_manager_settings.h @@ -69,6 +69,16 @@ class TransportManagerSettings : public TransportManagerMMESettings { */ virtual const std::string& transport_manager_tcp_adapter_network_interface() const = 0; + + /** + * @brief Returns retry timeout for cloud app connections + */ + virtual uint32_t cloud_app_retry_timeout() const = 0; + + /** + * @brief Returns maximum retry attempts for cloud app connections + */ + virtual uint16_t cloud_app_max_retry_attempts() const = 0; }; } // namespace transport_manager #endif // SRC_COMPONENTS_INCLUDE_TRANSPORT_MANAGER_TRANSPORT_MANAGER_SETTINGS_H_ diff --git a/src/components/interfaces/HMI_API.xml b/src/components/interfaces/HMI_API.xml index 2d256423bd..a11cfbfd8a 100644 --- a/src/components/interfaces/HMI_API.xml +++ b/src/components/interfaces/HMI_API.xml @@ -72,6 +72,7 @@ <element name="USB_IOS"/> <element name="USB_AOA"/> <element name="WIFI"/> + <element name="CLOUD_WEBSOCKET"/> </enum> <enum name="ButtonName"> diff --git a/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h b/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h index 3e7d64e9d2..ccf6082a18 100644 --- a/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h +++ b/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h @@ -512,6 +512,10 @@ class ProtocolHandlerImpl void OnTMMessageSendFailed(const transport_manager::DataSendError& error, const RawMessagePtr message) OVERRIDE; + void OnConnectionPending( + const transport_manager::DeviceInfo& device_info, + const transport_manager::ConnectionUID connection_id) OVERRIDE; + void OnConnectionEstablished( const transport_manager::DeviceInfo& device_info, const transport_manager::ConnectionUID connection_id) OVERRIDE; diff --git a/src/components/protocol_handler/src/protocol_handler_impl.cc b/src/components/protocol_handler/src/protocol_handler_impl.cc index d03030b747..ee2dc73780 100644 --- a/src/components/protocol_handler/src/protocol_handler_impl.cc +++ b/src/components/protocol_handler/src/protocol_handler_impl.cc @@ -1087,6 +1087,10 @@ void ProtocolHandlerImpl::OnTMMessageSendFailed( << "Error_text: " << error.text()); } +void ProtocolHandlerImpl::OnConnectionPending( + const transport_manager::DeviceInfo& device_info, + const transport_manager::ConnectionUID connection_id) {} + void ProtocolHandlerImpl::OnConnectionEstablished( const transport_manager::DeviceInfo& device_info, const transport_manager::ConnectionUID connection_id) { diff --git a/src/components/transport_manager/CMakeLists.txt b/src/components/transport_manager/CMakeLists.txt index 2f734b3a05..286e62b795 100644 --- a/src/components/transport_manager/CMakeLists.txt +++ b/src/components/transport_manager/CMakeLists.txt @@ -72,6 +72,11 @@ else() ) endif() +if(BUILD_CLOUD_APP_SUPPORT) + GET_PROPERTY(BOOST_LIBS_DIRECTORY GLOBAL PROPERTY GLOBAL_BOOST_LIBS) + list(APPEND LIBRARIES boost_system boost_regex -L${BOOST_LIBS_DIRECTORY}) +endif() + if(BUILD_USB_SUPPORT) if (CMAKE_SYSTEM_NAME STREQUAL "Linux") set(EXCLUDE_PATHS @@ -129,3 +134,4 @@ endif() if(BUILD_TESTS) add_subdirectory(test) endif() + diff --git a/src/components/transport_manager/include/transport_manager/cloud/cloud_device.h b/src/components/transport_manager/include/transport_manager/cloud/cloud_device.h new file mode 100644 index 0000000000..47a82e7921 --- /dev/null +++ b/src/components/transport_manager/include/transport_manager/cloud/cloud_device.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, Livio + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file Cloud_device.h + * \brief CloudDevice class header file. + */ + +#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_CLOUD_DEVICE_H_ +#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_CLOUD_DEVICE_H_ + +#include "transport_manager/transport_adapter/device.h" + +namespace transport_manager { +namespace transport_adapter { + +class CloudDevice : public Device { + public: + CloudDevice(std::string& host, std::string& port, std::string& name); + + virtual const std::string& GetHost() const; + + virtual const std::string& GetPort() const; + + protected: + virtual bool IsSameAs(const Device* other_device) const; + + virtual ApplicationList GetApplicationList() const; + + private: + const std::string host_; + const std::string port_; +}; + +} // namespace transport_adapter +} // namespace transport_manager + +#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_CLOUD_DEVICE_H_ diff --git a/src/components/transport_manager/include/transport_manager/cloud/cloud_websocket_connection_factory.h b/src/components/transport_manager/include/transport_manager/cloud/cloud_websocket_connection_factory.h new file mode 100644 index 0000000000..ef1754a6e7 --- /dev/null +++ b/src/components/transport_manager/include/transport_manager/cloud/cloud_websocket_connection_factory.h @@ -0,0 +1,98 @@ +/* + * \file cloud_websocket_connection_factory.h + * \brief CloudWebsocketConnectionFactory class header file. + * + * Copyright (c) 2018, Livio + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_CLOUD_WEBSOCKET_CONNECTION_FACTORY_H_ +#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_CLOUD_WEBSOCKET_CONNECTION_FACTORY_H_ + +#include "transport_manager/transport_adapter/server_connection_factory.h" + +namespace transport_manager { +namespace transport_adapter { + +class TransportAdapterController; + +/** + * @brief Create connections. + */ +class CloudWebsocketConnectionFactory : public ServerConnectionFactory { + public: + /** + * @brief Constructor. + * + * @param controller Pointer to the device adapter controller. + */ + CloudWebsocketConnectionFactory(TransportAdapterController* controller); + + protected: + /** + * @brief Start cloud websocket connection factory. + */ + virtual TransportAdapter::Error Init(); + + /** + * @brief Create cloud boost websocket connection. + * + * @param device_uid Device unique identifier. + * @param ap_handle Handle of application. + */ + virtual TransportAdapter::Error CreateConnection( + const DeviceUID& device_uid, const ApplicationHandle& app_handle); + + /** + * @brief + */ + virtual void Terminate(); + + /** + * @brief Check for initialization. + * + * @return true - initialized. + * false - not initialized. + */ + virtual bool IsInitialised() const; + + /** + * @brief Destructor. + */ + virtual ~CloudWebsocketConnectionFactory(); + + private: + TransportAdapterController* controller_; +}; + +} // namespace transport_adapter +} // namespace transport_manager + +#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_CLOUD_WEBSOCKET_CONNECTION_FACTORY_H_ diff --git a/src/components/transport_manager/include/transport_manager/cloud/cloud_websocket_transport_adapter.h b/src/components/transport_manager/include/transport_manager/cloud/cloud_websocket_transport_adapter.h new file mode 100644 index 0000000000..d52e4b307d --- /dev/null +++ b/src/components/transport_manager/include/transport_manager/cloud/cloud_websocket_transport_adapter.h @@ -0,0 +1,89 @@ +/* + * \file cloud_websocket_transport_adapter.h + * \brief Cloud Websocket Transport Adapterclass header file. + * + * Copyright (c) 2018, Livio + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_CLOUD_WEBSOCKET_TRANSPORT_ADAPTER_H_ +#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_CLOUD_WEBSOCKET_TRANSPORT_ADAPTER_H_ + +#include "transport_manager/transport_adapter/transport_adapter_impl.h" + +namespace transport_manager { +namespace transport_adapter { + +/** + * @brief Cloud transport adapter that uses websockets. + */ +class CloudWebsocketTransportAdapter : public TransportAdapterImpl { + public: + /** + * @brief Constructor. + */ + explicit CloudWebsocketTransportAdapter( + resumption::LastState& last_state, + const TransportManagerSettings& settings); + + /** + * @brief Destructor. + */ + virtual ~CloudWebsocketTransportAdapter(); + + protected: + /** + * @brief Return type of device. + * + * @return String with device type. + */ + virtual DeviceType GetDeviceType() const; + + /** + * @brief Store adapter state in last state singleton + */ + virtual void Store() const; + + /** + * @brief Restore adapter state from last state singleton + * + * @return True on success false otherwise + */ + virtual bool Restore(); + + void CreateDevice(const std::string& uid) OVERRIDE; + + private: +}; + +} // namespace transport_adapter +} // namespace transport_manager + +#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_TCP_TCP_TRANSPORT_ADAPTER_H_ diff --git a/src/components/transport_manager/include/transport_manager/cloud/websocket_client_connection.h b/src/components/transport_manager/include/transport_manager/cloud/websocket_client_connection.h new file mode 100644 index 0000000000..da3a80e1b2 --- /dev/null +++ b/src/components/transport_manager/include/transport_manager/cloud/websocket_client_connection.h @@ -0,0 +1,178 @@ +/* + * \file websocket_client_connection.h + * \brief WebsocketClientConnection class header file. + * + * Copyright (c) 2018, Livio + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_WEBSOCKET_CLIENT_CONNECTION_H_ +#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_CLOUD_WEBSOCKET_CLIENT_CONNECTION_H_ + +#include <boost/beast/core.hpp> +#include <boost/beast/websocket.hpp> +#include <boost/beast/websocket/ssl.hpp> +#include <boost/asio/connect.hpp> +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/ssl/stream.hpp> +#include <cstdlib> +#include <functional> +#include <iostream> +#include <memory> +#include <string> +#include <thread> +#include "transport_manager/transport_adapter/connection.h" +#include "utils/threads/thread.h" +#include "utils/threads/message_loop_thread.h" +#include "utils/message_queue.h" + +using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp> +namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp> +namespace websocket = + boost::beast::websocket; // from <boost/beast/websocket.hpp> +using ::utils::MessageQueue; + +typedef std::queue<protocol_handler::RawMessagePtr> AsyncQueue; +typedef protocol_handler::RawMessagePtr Message; + +namespace transport_manager { +namespace transport_adapter { + +class TransportAdapterController; + +/** + * @brief Class responsible for communication over bluetooth sockets. + */ +class WebsocketClientConnection + : public std::enable_shared_from_this<WebsocketClientConnection>, + public Connection { + public: + /** + * @brief Constructor. + * + * @param device_uid Device unique identifier. + * @param app_handle Handle of device. + * @param controller Pointer to the device adapter controller. + */ + WebsocketClientConnection(const DeviceUID& device_uid, + const ApplicationHandle& app_handle, + TransportAdapterController* controller); + + /** + * @brief Destructor. + */ + virtual ~WebsocketClientConnection(); + + /** + * @brief Check if we can start the connection attempt and establish + *connection status. + * + * @param error contains information of any error that occurred during + *connection attempt. + * + * @return result that states whether we successfully connected or not. + */ + TransportAdapter::Error Start(); + + /** + * @brief Send data frame. + * + * @param message Smart pointer to the raw message. + * + * @return Error Information about possible reason of sending data failure. + */ + TransportAdapter::Error SendData(::protocol_handler::RawMessagePtr message); + + /** + * @brief Disconnect the current connection. + * + * @return Error Information about possible reason of Disconnect failure. + */ + TransportAdapter::Error Disconnect(); + + void Shutdown(); + + void Recv(boost::system::error_code ec); + + void OnRead(boost::system::error_code ec, std::size_t bytes_transferred); + + private: + TransportAdapterController* controller_; + boost::asio::io_context ioc_; + tcp::resolver resolver_; + websocket::stream<tcp::socket> ws_; + boost::beast::flat_buffer buffer_; + std::string host_; + std::string text_; + + std::atomic_bool shutdown_; + + typedef std::queue<protocol_handler::RawMessagePtr> FrameQueue; + FrameQueue frames_to_send_; + mutable sync_primitives::Lock frames_to_send_mutex_; + + MessageQueue<Message, AsyncQueue> message_queue_; + + class LoopThreadDelegate : public threads::ThreadDelegate { + public: + LoopThreadDelegate(MessageQueue<Message, AsyncQueue>* message_queue, + WebsocketClientConnection* handler); + + virtual void threadMain() OVERRIDE; + virtual void exitThreadMain() OVERRIDE; + + void OnWrite(); + + void SetShutdown(); + + private: + void DrainQueue(); + MessageQueue<Message, AsyncQueue>& message_queue_; + WebsocketClientConnection& handler_; + sync_primitives::Lock queue_lock_; + sync_primitives::ConditionalVariable queue_new_items_; + std::atomic_bool write_pending_; + std::atomic_bool shutdown_; + + sync_primitives::Lock write_lock_; + }; + + LoopThreadDelegate* thread_delegate_; + threads::Thread* write_thread_; + std::thread io_service_thread_; + + const DeviceUID device_uid_; + const ApplicationHandle app_handle_; +}; + +} // namespace transport_adapter +} // namespace transport_manager + +#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_BLUETOOTH_BLUETOOTH_SOCKET_CONNECTION_H_ diff --git a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_controller.h b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_controller.h index 69d76b4b2b..6d97a55a70 100644 --- a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_controller.h +++ b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_controller.h @@ -100,6 +100,16 @@ class TransportAdapterController { const ApplicationHandle& app_handle) = 0; /** + * @brief Set state of specified connection - PENDING and launch + *OnConnectPending event in device adapter listener. + * + * @param devcie_handle Device unique identifier. + * @param app_handle Handle of application. + */ + virtual void ConnectPending(const DeviceUID& device_handle, + const ApplicationHandle& app_handle) = 0; + + /** * @brief Make state of specified connection - ESTABLISHED and launch *OnConnectDone event in device adapter listener. * diff --git a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h index 078f93b32f..0af1f2b614 100644 --- a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h +++ b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h @@ -306,6 +306,16 @@ class TransportAdapterImpl : public TransportAdapter, const CommunicationError& error) OVERRIDE; /** + * @brief Set state of specified connection - PENDING and launch + *OnConnectPending event in device adapter listener. + * + * @param devcie_handle Device unique identifier. + * @param app_handle Handle of application. + */ + void ConnectPending(const DeviceUID& device_handle, + const ApplicationHandle& app_handle) OVERRIDE; + + /** * @brief Set state of specified connection - ESTABLISHED and launch *OnConnectDone event in device adapter listener. * @@ -434,6 +444,10 @@ class TransportAdapterImpl : public TransportAdapter, return TransportConfig(); } + void CreateDevice(const std::string& uid) OVERRIDE { + return; + } + /** * @brief Return name of device. * @@ -564,7 +578,7 @@ class TransportAdapterImpl : public TransportAdapter, ConnectionSPtr connection; DeviceUID device_id; ApplicationHandle app_handle; - enum { NEW, ESTABLISHED, FINALISING } state; + enum { NEW, ESTABLISHED, FINALISING, PENDING, RETRY } state; }; /** diff --git a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener.h b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener.h index 4606bac2d4..b0368869e7 100644 --- a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener.h +++ b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener.h @@ -93,6 +93,19 @@ class TransportAdapterListener { /** * @brief Search specified device adapter in the container of shared pointers + * to device adapters to be sure it is available, + * launch event ON_CONNECT_PENDING in transport manager. + * + * @param device_adater Pointer to the device adapter. + * @param device_handle Device unique identifier. + * @param app_id Handle of application. + */ + virtual void OnConnectPending(const TransportAdapter* adapter, + const DeviceUID& device_handle, + const ApplicationHandle& app_id) = 0; + + /** + * @brief Search specified device adapter in the container of shared pointers *to device adapters to be sure it is available, * launch event ON_CONNECT_DONE in transport manager. * diff --git a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener_impl.h b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener_impl.h index a744400279..76271229ad 100644 --- a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener_impl.h +++ b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_listener_impl.h @@ -89,6 +89,19 @@ class TransportAdapterListenerImpl /** * @brief Search specified device adapter in the container of shared pointers + * to device adapters to be sure it is available, + * launch event ON_CONNECT_PENDING in transport manager. + * + * @param device_adater Pointer to the device adapter. + * @param device_handle Device unique identifier. + * @param app_id Handle of application. + */ + virtual void OnConnectPending(const TransportAdapter* adapter, + const DeviceUID& device_handle, + const ApplicationHandle& app_id); + + /** + * @brief Search specified device adapter in the container of shared pointers *to device adapters to be sure it is available, * launch event ON_CONNECT_DONE in transport manager. * diff --git a/src/components/transport_manager/include/transport_manager/transport_manager_impl.h b/src/components/transport_manager/include/transport_manager/transport_manager_impl.h index c1df49f91b..dcb3b6922c 100644 --- a/src/components/transport_manager/include/transport_manager/transport_manager_impl.h +++ b/src/components/transport_manager/include/transport_manager/transport_manager_impl.h @@ -140,6 +140,9 @@ class TransportManagerImpl **/ int SearchDevices() OVERRIDE; + void AddCloudDevice(const std::string& endpoint, + const std::string& cloud_transport_type) OVERRIDE; + /** * @brief Connect to all applications discovered on device. * diff --git a/src/components/transport_manager/src/cloud/cloud_device.cc b/src/components/transport_manager/src/cloud/cloud_device.cc new file mode 100644 index 0000000000..90a485c069 --- /dev/null +++ b/src/components/transport_manager/src/cloud/cloud_device.cc @@ -0,0 +1,75 @@ +/* + * + * Copyright (c) 2018, Livio + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "transport_manager/cloud/cloud_device.h" + +#include "utils/logger.h" + +namespace transport_manager { +namespace transport_adapter { +CREATE_LOGGERPTR_GLOBAL(logger_, "TransportManager") + +CloudDevice::CloudDevice(std::string& host, + std::string& port, + std::string& name) + : Device(name, std::string(name)), host_(host), port_(port) {} + +bool CloudDevice::IsSameAs(const Device* other) const { + LOG4CXX_TRACE(logger_, "enter. device: " << other); + + const CloudDevice* other_cloud_device = + dynamic_cast<const CloudDevice*>(other); + + if (host_ != other_cloud_device->GetHost()) { + return false; + } + if (port_ != other_cloud_device->GetPort()) { + return false; + } + return true; +} + +ApplicationList CloudDevice::GetApplicationList() const { + return ApplicationList{100}; +} + +const std::string& CloudDevice::GetHost() const { + return host_; +} + +const std::string& CloudDevice::GetPort() const { + return port_; +} + +} // namespace transport_adapter +} // namespace transport_manager diff --git a/src/components/transport_manager/src/cloud/cloud_websocket_connection_factory.cc b/src/components/transport_manager/src/cloud/cloud_websocket_connection_factory.cc new file mode 100644 index 0000000000..cdc27ed8ef --- /dev/null +++ b/src/components/transport_manager/src/cloud/cloud_websocket_connection_factory.cc @@ -0,0 +1,81 @@ +/* + * \file cloud_websocket_connection_factory.cc + * \brief CloudWebsocketConnectionFactory class source file. + * + * Copyright (c) 2018, Livio + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "transport_manager/transport_adapter/transport_adapter_controller.h" +#include "transport_manager/cloud/cloud_websocket_connection_factory.h" +#include "transport_manager/cloud/websocket_client_connection.h" +#include "utils/logger.h" + +#include "transport_manager/cloud/cloud_device.h" + +namespace transport_manager { +namespace transport_adapter { + +CREATE_LOGGERPTR_GLOBAL(logger_, "TransportManager") + +CloudWebsocketConnectionFactory::CloudWebsocketConnectionFactory( + TransportAdapterController* controller) + : controller_(controller) {} + +TransportAdapter::Error CloudWebsocketConnectionFactory::Init() { + return TransportAdapter::OK; +} + +TransportAdapter::Error CloudWebsocketConnectionFactory::CreateConnection( + const DeviceUID& device_uid, const ApplicationHandle& app_handle) { + LOG4CXX_AUTO_TRACE(logger_); + std::shared_ptr<WebsocketClientConnection> connection = + std::make_shared<WebsocketClientConnection>( + device_uid, app_handle, controller_); + controller_->ConnectionCreated(connection, device_uid, app_handle); + TransportAdapter::Error error = connection->Start(); + if (TransportAdapter::OK != error) { + LOG4CXX_ERROR( + logger_, + "Cloud Websocket connection::Start() failed with error: " << error); + } + return error; +} + +void CloudWebsocketConnectionFactory::Terminate() {} + +bool CloudWebsocketConnectionFactory::IsInitialised() const { + return true; +} + +CloudWebsocketConnectionFactory::~CloudWebsocketConnectionFactory() {} + +} // namespace transport_adapter +} // namespace transport_manager diff --git a/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc b/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc new file mode 100644 index 0000000000..24efdfb2a4 --- /dev/null +++ b/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018, Livio + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "transport_manager/cloud/cloud_websocket_transport_adapter.h" +#include "transport_manager/cloud/cloud_websocket_connection_factory.h" + +#include "transport_manager/cloud/cloud_device.h" +#include "transport_manager/cloud/websocket_client_connection.h" + +#include <boost/regex.hpp> + +namespace transport_manager { +namespace transport_adapter { + +CREATE_LOGGERPTR_GLOBAL(logger_, "TransportManager") + +CloudWebsocketTransportAdapter::CloudWebsocketTransportAdapter( + resumption::LastState& last_state, const TransportManagerSettings& settings) + : TransportAdapterImpl(NULL, + new CloudWebsocketConnectionFactory(this), + NULL, + last_state, + settings) {} + +CloudWebsocketTransportAdapter::~CloudWebsocketTransportAdapter() {} + +DeviceType CloudWebsocketTransportAdapter::GetDeviceType() const { + return CLOUD_WEBSOCKET; +} + +void CloudWebsocketTransportAdapter::Store() const {} + +bool CloudWebsocketTransportAdapter::Restore() { + return true; +} + +void CloudWebsocketTransportAdapter::CreateDevice(const std::string& uid) { + boost::regex pattern( + "(wss?):\\/\\/([A-Z\\d\\.-]{2,})\\.?([A-Z]{2,})?(:\\d{2,4})\\/", + boost::regex::icase); + std::string str = uid; + if (!boost::regex_match(str, pattern)) { + LOG4CXX_DEBUG(logger_, "Invalid Endpoint: " << uid); + return; + } + + LOG4CXX_DEBUG(logger_, "Valid Endpoint: " << uid); + std::size_t pos = uid.find(":"); + pos = uid.find(":", pos + 1); + // std::size_t size = uid.length(); + std::string host = uid.substr(0, pos); + std::string port = uid.substr(pos + 1); + std::string device_id = uid; + + LOG4CXX_DEBUG(logger_, + "Creating Cloud Device For Host: " << host + << " and Port: " << port); + + auto cloud_device = std::make_shared<CloudDevice>(host, port, device_id); + + DeviceVector devices{cloud_device}; + + SearchDeviceDone(devices); + + // Create connection object, do not start until app is activated + std::shared_ptr<WebsocketClientConnection> connection = + std::make_shared<WebsocketClientConnection>(uid, 0, this); + + ConnectionCreated(connection, uid, 0); + ConnectPending(uid, 0); + + return; +} +} +}
\ No newline at end of file diff --git a/src/components/transport_manager/src/cloud/websocket_client_connection.cc b/src/components/transport_manager/src/cloud/websocket_client_connection.cc new file mode 100644 index 0000000000..4f585c8efb --- /dev/null +++ b/src/components/transport_manager/src/cloud/websocket_client_connection.cc @@ -0,0 +1,244 @@ +/* + * + * Copyright (c) 2018, Livio + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "transport_manager/cloud/websocket_client_connection.h" +#include "transport_manager/cloud/cloud_device.h" + +#include "transport_manager/transport_adapter/transport_adapter_controller.h" + +#include "utils/logger.h" + +namespace transport_manager { +namespace transport_adapter { +CREATE_LOGGERPTR_GLOBAL(logger_, "TransportManager") + +WebsocketClientConnection::WebsocketClientConnection( + const DeviceUID& device_uid, + const ApplicationHandle& app_handle, + TransportAdapterController* controller) + : controller_(controller) + , resolver_(ioc_) + , ws_(ioc_) + , shutdown_(false) + , thread_delegate_(new LoopThreadDelegate(&message_queue_, this)) + , write_thread_(threads::CreateThread("WS Async Send", thread_delegate_)) + , device_uid_(device_uid) + , app_handle_(app_handle) {} + +WebsocketClientConnection::~WebsocketClientConnection() { + ioc_.stop(); + if (io_service_thread_.joinable()) { + io_service_thread_.join(); + } +} + +TransportAdapter::Error WebsocketClientConnection::Start() { + LOG4CXX_AUTO_TRACE(logger_); + DeviceSptr device = controller_->FindDevice(device_uid_); + CloudDevice* cloud_device = static_cast<CloudDevice*>(device.get()); + auto const host = cloud_device->GetHost(); + auto const port = cloud_device->GetPort(); + boost::system::error_code ec; + auto const results = resolver_.resolve(host, port, ec); + if (ec) { + std::string str_err = "ErrorMessage: " + ec.message(); + LOG4CXX_ERROR(logger_, "Could not resolve host/port: " << str_err); + Shutdown(); + return TransportAdapter::FAIL; + } + boost::asio::connect(ws_.next_layer(), results.begin(), results.end(), ec); + if (ec) { + std::string str_err = "ErrorMessage: " + ec.message(); + LOG4CXX_ERROR(logger_, + "Could not connect to websocket: " << host << ":" << port); + LOG4CXX_ERROR(logger_, str_err); + Shutdown(); + return TransportAdapter::FAIL; + } + ws_.handshake(host, "/", ec); + if (ec) { + std::string str_err = "ErrorMessage: " + ec.message(); + LOG4CXX_ERROR(logger_, + "Could not complete handshake with host/port: " << host << ":" + << port); + LOG4CXX_ERROR(logger_, str_err); + Shutdown(); + return TransportAdapter::FAIL; + } + ws_.binary(true); + write_thread_->start(threads::ThreadOptions()); + controller_->ConnectDone(device_uid_, app_handle_); + + // Start async read + ws_.async_read(buffer_, + std::bind(&WebsocketClientConnection::OnRead, + this, + std::placeholders::_1, + std::placeholders::_2)); + + // Start IO Service thread. Allows for async reads without blocking. + io_service_thread_ = std::thread([&]() { + ioc_.run(); + LOG4CXX_DEBUG(logger_, "Ending Boost IO Thread"); + }); + + LOG4CXX_DEBUG(logger_, + "Successfully started websocket connection @: " << host << ":" + << port); + + return TransportAdapter::OK; +} + +void WebsocketClientConnection::Recv(boost::system::error_code ec) { + if (shutdown_) { + return; + } + + if (ec) { + std::string str_err = "ErrorMessage: " + ec.message(); + LOG4CXX_ERROR(logger_, str_err); + Shutdown(); + return; + } + + ws_.async_read(buffer_, + std::bind(&WebsocketClientConnection::OnRead, + this, + std::placeholders::_1, + std::placeholders::_2)); +} + +void WebsocketClientConnection::OnRead(boost::system::error_code ec, + std::size_t bytes_transferred) { + boost::ignore_unused(bytes_transferred); + if (ec) { + std::string str_err = "ErrorMessage: " + ec.message(); + LOG4CXX_ERROR(logger_, str_err); + Shutdown(); + controller_->ConnectionAborted( + device_uid_, app_handle_, CommunicationError()); + return; + } + + std::string data_str = boost::beast::buffers_to_string(buffer_.data()); + LOG4CXX_DEBUG(logger_, "Cloud Transport Received: " << data_str); + + ssize_t size = (ssize_t)buffer_.size(); + const uint8_t* data = boost::asio::buffer_cast<const uint8_t*>( + boost::beast::buffers_front(buffer_.data())); + + ::protocol_handler::RawMessagePtr frame( + new protocol_handler::RawMessage(0, 0, data, size)); + + controller_->DataReceiveDone(device_uid_, app_handle_, frame); + + buffer_.consume(buffer_.size()); + Recv(ec); +} + +TransportAdapter::Error WebsocketClientConnection::SendData( + ::protocol_handler::RawMessagePtr message) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock auto_lock(frames_to_send_mutex_); + message_queue_.push(message); + return TransportAdapter::OK; +} + +TransportAdapter::Error WebsocketClientConnection::Disconnect() { + LOG4CXX_AUTO_TRACE(logger_); + Shutdown(); + return TransportAdapter::OK; +} + +void WebsocketClientConnection::Shutdown() { + shutdown_ = true; + + if (thread_delegate_) { + thread_delegate_->SetShutdown(); + write_thread_->join(); + delete thread_delegate_; + } + if (buffer_.size()) { + buffer_.consume(buffer_.size()); + } +} + +WebsocketClientConnection::LoopThreadDelegate::LoopThreadDelegate( + MessageQueue<Message, AsyncQueue>* message_queue, + WebsocketClientConnection* handler) + : message_queue_(*message_queue), handler_(*handler), shutdown_(false) {} + +void WebsocketClientConnection::LoopThreadDelegate::threadMain() { + while (!message_queue_.IsShuttingDown() && !shutdown_) { + DrainQueue(); + message_queue_.wait(); + } + DrainQueue(); +} + +void WebsocketClientConnection::LoopThreadDelegate::exitThreadMain() { + shutdown_ = true; + if (!message_queue_.IsShuttingDown()) { + message_queue_.Shutdown(); + } +} + +void WebsocketClientConnection::LoopThreadDelegate::DrainQueue() { + while (!message_queue_.empty()) { + Message message_ptr; + message_queue_.pop(message_ptr); + if (!shutdown_) { + boost::system::error_code ec; + handler_.ws_.write( + boost::asio::buffer(message_ptr->data(), message_ptr->data_size())); + if (ec) { + LOG4CXX_ERROR(logger_, "Error writing to websocket"); + handler_.Shutdown(); + handler_.controller_->DataSendFailed(handler_.device_uid_, + handler_.app_handle_, + message_ptr, + DataSendError()); + } + } + } +} + +void WebsocketClientConnection::LoopThreadDelegate::SetShutdown() { + shutdown_ = true; + if (!message_queue_.IsShuttingDown()) { + message_queue_.Shutdown(); + } +} + +} // namespace transport_adapter +} // namespace transport_manager
\ No newline at end of file diff --git a/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc b/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc index 346139cbd2..38b9bd3998 100644 --- a/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc +++ b/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc @@ -60,7 +60,9 @@ DeviceTypes devicesType = { std::make_pair(DeviceType::IOS_USB_DEVICE_MODE, std::string("USB_IOS_DEVICE_MODE")), std::make_pair(DeviceType::IOS_CARPLAY_WIRELESS, - std::string("CARPLAY_WIRELESS_IOS"))}; + std::string("CARPLAY_WIRELESS_IOS")), + std::make_pair(DeviceType::CLOUD_WEBSOCKET, + std::string("CLOUD_WEBSOCKET"))}; } TransportAdapterImpl::TransportAdapterImpl( @@ -743,6 +745,24 @@ DeviceSptr TransportAdapterImpl::FindDevice(const DeviceUID& device_id) const { return ret; } +void TransportAdapterImpl::ConnectPending(const DeviceUID& device_id, + const ApplicationHandle& app_handle) { + connections_lock_.AcquireForReading(); + ConnectionMap::iterator it_conn = + connections_.find(std::make_pair(device_id, app_handle)); + if (it_conn != connections_.end()) { + ConnectionInfo& info = it_conn->second; + info.state = ConnectionInfo::PENDING; + } + connections_lock_.Release(); + + for (TransportAdapterListenerList::iterator it = listeners_.begin(); + it != listeners_.end(); + ++it) { + (*it)->OnConnectPending(this, device_id, app_handle); + } +} + void TransportAdapterImpl::ConnectDone(const DeviceUID& device_id, const ApplicationHandle& app_handle) { LOG4CXX_TRACE(logger_, diff --git a/src/components/transport_manager/src/transport_adapter/transport_adapter_listener_impl.cc b/src/components/transport_manager/src/transport_adapter/transport_adapter_listener_impl.cc index 544cdde999..73750fe2f3 100644 --- a/src/components/transport_manager/src/transport_adapter/transport_adapter_listener_impl.cc +++ b/src/components/transport_manager/src/transport_adapter/transport_adapter_listener_impl.cc @@ -116,6 +116,27 @@ void TransportAdapterListenerImpl::OnFindNewApplicationsRequest( LOG4CXX_TRACE(logger_, "exit"); } +void TransportAdapterListenerImpl::OnConnectPending( + const TransportAdapter* adapter, + const DeviceUID& device, + const ApplicationHandle& application_id) { + LOG4CXX_TRACE(logger_, + "enter adapter*: " << adapter << ", device: " << &device + << ", application_id: " << &application_id); + const TransportAdapterEvent event(EventTypeEnum::ON_CONNECT_PENDING, + transport_adapter_, + device, + application_id, + ::protocol_handler::RawMessagePtr(), + BaseErrorPtr(new BaseError())); + if (transport_manager_ != NULL && + transport_manager::E_SUCCESS != + transport_manager_->ReceiveEventFromDevice(event)) { + LOG4CXX_WARN(logger_, "Failed to receive event from device"); + } + LOG4CXX_TRACE(logger_, "exit"); +} + void TransportAdapterListenerImpl::OnConnectDone( const TransportAdapter* adapter, const DeviceUID& device, diff --git a/src/components/transport_manager/src/transport_manager_default.cc b/src/components/transport_manager/src/transport_manager_default.cc index 196ad09af4..bf692de24c 100644 --- a/src/components/transport_manager/src/transport_manager_default.cc +++ b/src/components/transport_manager/src/transport_manager_default.cc @@ -44,6 +44,10 @@ #include "transport_manager/usb/usb_aoa_adapter.h" #endif // USB_SUPPORT +#if defined(CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT) +#include "transport_manager/cloud/cloud_websocket_transport_adapter.h" +#endif + #if defined(BUILD_TESTS) #include "transport_manager/iap2_emulation/iap2_transport_adapter.h" #endif // BUILD_TEST @@ -101,6 +105,20 @@ int TransportManagerDefault::Init(resumption::LastState& last_state) { ta_usb = NULL; #endif // USB_SUPPORT +#if defined CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT + transport_adapter::TransportAdapterImpl* ta_cloud = + new transport_adapter::CloudWebsocketTransportAdapter( + last_state, get_settings()); // Todo add retry connection logic from + // ini to initializer. +#ifdef TELEMETRY_MONITOR + if (metric_observer_) { + ta_cloud->SetTelemetryObserver(metric_observer_); + } +#endif // TELEMETRY_MONITOR + AddTransportAdapter(ta_cloud); + ta_cloud = NULL; +#endif + #if defined BUILD_TESTS const uint16_t iap2_bt_emu_port = 23456; transport_adapter::IAP2BluetoothEmulationTransportAdapter* diff --git a/src/components/transport_manager/src/transport_manager_impl.cc b/src/components/transport_manager/src/transport_manager_impl.cc index 2b0296debb..300ed27718 100644 --- a/src/components/transport_manager/src/transport_manager_impl.cc +++ b/src/components/transport_manager/src/transport_manager_impl.cc @@ -129,6 +129,26 @@ void TransportManagerImpl::ReconnectionTimeout() { device_to_reconnect_); } +void TransportManagerImpl::AddCloudDevice( + const std::string& endpoint, const std::string& cloud_transport_type) { + // todo put conversion into own function + transport_adapter::DeviceType type = transport_adapter::DeviceType::UNKNOWN; + if (cloud_transport_type == "WS") { + type = transport_adapter::DeviceType::CLOUD_WEBSOCKET; + } else { + return; + } + + std::vector<TransportAdapter*>::iterator ta = transport_adapters_.begin(); + for (; ta != transport_adapters_.end(); ++ta) { + if ((*ta)->GetDeviceType() == type) { + (*ta)->CreateDevice(endpoint); + } + } + + return; +} + int TransportManagerImpl::ConnectDevice(const DeviceHandle device_handle) { LOG4CXX_TRACE(logger_, "enter. DeviceHandle: " << &device_handle); if (!this->is_initialized_) { @@ -954,7 +974,7 @@ void TransportManagerImpl::Handle(TransportAdapterEvent event) { LOG4CXX_DEBUG(logger_, "event_type = ON_FIND_NEW_APPLICATIONS_REQUEST"); break; } - case EventTypeEnum::ON_CONNECT_DONE: { + case EventTypeEnum::ON_CONNECT_PENDING: { const DeviceHandle device_handle = converter_.UidToHandle( event.device_uid, event.transport_adapter->GetConnectionType()); AddConnection(ConnectionInternal(this, @@ -964,12 +984,55 @@ void TransportManagerImpl::Handle(TransportAdapterEvent event) { event.application_id, device_handle)); RaiseEvent( - &TransportManagerListener::OnConnectionEstablished, + &TransportManagerListener::OnConnectionPending, DeviceInfo(device_handle, event.device_uid, event.transport_adapter->DeviceName(event.device_uid), event.transport_adapter->GetConnectionType()), connection_id_counter_); + LOG4CXX_DEBUG(logger_, "event_type = ON_CONNECT_PENDING"); + break; + } + case EventTypeEnum::ON_CONNECT_DONE: { + const DeviceHandle device_handle = converter_.UidToHandle( + event.device_uid, event.transport_adapter->GetConnectionType()); + + int connection_id = 0; + std::vector<ConnectionInternal>::iterator it = connections_.begin(); + std::vector<ConnectionInternal>::iterator end = connections_.end(); + for (; it != end; ++it) { + if (it->transport_adapter != event.transport_adapter) { + continue; + } else if (it->Connection::device != event.device_uid) { + continue; + } else if (it->Connection::application != event.application_id) { + continue; + } else if (it->device_handle_ != device_handle) { + continue; + } else { + LOG4CXX_DEBUG(logger_, "Connection Object Already Exists"); + connection_id = it->Connection::id; + break; + } + } + + if (it == end) { + AddConnection(ConnectionInternal(this, + event.transport_adapter, + ++connection_id_counter_, + event.device_uid, + event.application_id, + device_handle)); + connection_id = connection_id_counter_; + } + + RaiseEvent( + &TransportManagerListener::OnConnectionEstablished, + DeviceInfo(device_handle, + event.device_uid, + event.transport_adapter->DeviceName(event.device_uid), + event.transport_adapter->GetConnectionType()), + connection_id); LOG4CXX_DEBUG(logger_, "event_type = ON_CONNECT_DONE"); break; } diff --git a/src/components/transport_manager/test/CMakeLists.txt b/src/components/transport_manager/test/CMakeLists.txt index 240784436b..5288d8c697 100644 --- a/src/components/transport_manager/test/CMakeLists.txt +++ b/src/components/transport_manager/test/CMakeLists.txt @@ -75,6 +75,11 @@ if (BUILD_BT_SUPPORT) endif() endif() +if(BUILD_CLOUD_APP_SUPPORT) + GET_PROPERTY(BOOST_LIBS_DIRECTORY GLOBAL PROPERTY GLOBAL_BOOST_LIBS) + list(APPEND LIBRARIES boost_system boost_regex crypto ssl -L${BOOST_LIBS_DIRECTORY}) +endif() + create_test("transport_manager_test" "${SOURCES}" "${LIBRARIES}") file(COPY smartDeviceLink_test.ini DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/src/components/transport_manager/test/include/transport_manager/mock_transport_manager_listener.h b/src/components/transport_manager/test/include/transport_manager/mock_transport_manager_listener.h index 58e143342a..4eaf34d041 100644 --- a/src/components/transport_manager/test/include/transport_manager/mock_transport_manager_listener.h +++ b/src/components/transport_manager/test/include/transport_manager/mock_transport_manager_listener.h @@ -56,6 +56,9 @@ class MockTransportManagerListener : public TransportManagerListener { MOCK_METHOD1(OnDeviceRemoved, void(const DeviceInfo& device_info)); MOCK_METHOD0(OnScanDevicesFinished, void()); MOCK_METHOD1(OnScanDevicesFailed, void(const SearchDeviceError& error)); + MOCK_METHOD2(OnConnectionPending, + void(const DeviceInfo& device_info, + const ConnectionUID connection_id)); MOCK_METHOD2(OnConnectionEstablished, void(const DeviceInfo& device_info, const ConnectionUID connection_id)); diff --git a/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_listener.h b/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_listener.h index dce23189c8..81e133ec2b 100644 --- a/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_listener.h +++ b/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_listener.h @@ -59,6 +59,10 @@ class MockTransportAdapterListener : public TransportAdapterListener { const SearchDeviceError& error)); MOCK_METHOD1(OnFindNewApplicationsRequest, void(const TransportAdapter* adapter)); + MOCK_METHOD3(OnConnectPending, + void(const TransportAdapter* adapter, + const DeviceUID& device_handle, + const ApplicationHandle& app_id)); MOCK_METHOD1(OnDeviceListUpdated, void(const TransportAdapter* transport_adapter)); MOCK_METHOD3(OnConnectDone, diff --git a/src/components/transport_manager/test/tcp_client_listener_test.cc b/src/components/transport_manager/test/tcp_client_listener_test.cc index 5205d6ae3c..f44f8785aa 100644 --- a/src/components/transport_manager/test/tcp_client_listener_test.cc +++ b/src/components/transport_manager/test/tcp_client_listener_test.cc @@ -73,6 +73,9 @@ class MockTransportAdapterController : public TransportAdapterController { void(ConnectionSPtr connection, const DeviceUID& device_handle, const ApplicationHandle& app_handle)); + MOCK_METHOD2(ConnectPending, + void(const DeviceUID& device_handle, + const ApplicationHandle& app_handle)); MOCK_METHOD2(ConnectDone, void(const DeviceUID& device_handle, const ApplicationHandle& app_handle)); |