diff options
author | JackLivio <jack@livio.io> | 2019-01-23 16:34:29 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-23 16:34:29 -0500 |
commit | 709a6584202d23fae54037902df51e132c4e8acb (patch) | |
tree | 24bec23ca3fd01c4e8a37ac567d2c3f63d327697 | |
parent | 9d16c63644d88380aaee1791b5141579ea50c826 (diff) | |
parent | 5676f89293d1e5a1a95c06a714072564138a47c4 (diff) | |
download | sdl_core-709a6584202d23fae54037902df51e132c4e8acb.tar.gz |
Merge pull request #2782 from smartdevicelink/feature/cloud_app_connection_status_disconnect
Cloud App Handle Disconnect
15 files changed, 149 insertions, 33 deletions
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 8c062f9016..5989605281 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 @@ -367,6 +367,10 @@ class ApplicationManagerImpl const transport_manager::DeviceInfo& device_info, connection_handler::DeviceHandle device_id); + void SetPendingApplicationState( + const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info); + /** * @brief Notifies the applicaiton manager that a cloud connection status has * updated and should trigger an UpdateAppList RPC to the HMI diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index 621d404669..7b2475a4e0 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -842,9 +842,9 @@ void ApplicationManagerImpl::RefreshCloudAppInformation() { auto old_device_it = old_device_map.find(endpoint); if (old_device_it != old_device_map.end()) { old_device_map.erase(old_device_it); - continue; } + // If the device was disconnected, this will reinitialize the device connection_handler().AddCloudAppDevice(endpoint, cloud_transport_type); } pending_device_map_lock_ptr_->Release(); @@ -911,6 +911,7 @@ void ApplicationManagerImpl::CreatePendingApplication( pending_device_map_lock_ptr_->Acquire(); auto it = pending_device_map_.find(name); if (it == pending_device_map_.end()) { + pending_device_map_lock_ptr_->Release(); return; } pending_device_map_lock_ptr_->Release(); @@ -988,6 +989,36 @@ void ApplicationManagerImpl::CreatePendingApplication( SendUpdateAppList(); } +void ApplicationManagerImpl::SetPendingApplicationState( + const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info) { + std::string name = device_info.name(); + pending_device_map_lock_ptr_->Acquire(); + auto it = pending_device_map_.find(name); + if (it == pending_device_map_.end()) { + pending_device_map_lock_ptr_->Release(); + return; + } + pending_device_map_lock_ptr_->Release(); + + const std::string policy_app_id = it->second; + auto app = application_by_policy_id(policy_app_id); + + if (!app) { + return; + } + LOG4CXX_DEBUG(logger_, + "Unregister application and move into apps_to_register"); + { + sync_primitives::AutoLock lock(apps_to_register_list_lock_ptr_); + apps_to_register_.insert(app); + } + + UnregisterApplication( + app->app_id(), mobile_apis::Result::INVALID_ENUM, true, true); + app->MarkUnregistered(); +} + void ApplicationManagerImpl::OnConnectionStatusUpdated() { SendUpdateAppList(); } @@ -1232,6 +1263,7 @@ void ApplicationManagerImpl::OnDeviceListUpdated( so_to_send[jhs::S_PARAMS][jhs::S_CORRELATION_ID] = GetNextHMICorrelationID(); so_to_send[jhs::S_MSG_PARAMS] = *msg_params; rpc_service_->ManageHMICommand(update_list); + RefreshCloudAppInformation(); } void ApplicationManagerImpl::OnFindNewApplicationsRequest() { @@ -2708,6 +2740,7 @@ void ApplicationManagerImpl::UnregisterApplication( logger_, "There is no more SDL4 apps with device handle: " << handle); RemoveAppsWaitingForRegistration(handle); + RefreshCloudAppInformation(); SendUpdateAppList(); } } diff --git a/src/components/connection_handler/src/connection_handler_impl.cc b/src/components/connection_handler/src/connection_handler_impl.cc index 16dbab4117..b58700834f 100644 --- a/src/components/connection_handler/src/connection_handler_impl.cc +++ b/src/components/connection_handler/src/connection_handler_impl.cc @@ -286,6 +286,9 @@ void ConnectionHandlerImpl::OnConnectionPending( connection_handler_observer_->CreatePendingApplication( connection_id, device_info, device_id); + } else { + connection_handler_observer_->SetPendingApplicationState(connection_id, + device_info); } } diff --git a/src/components/include/connection_handler/connection_handler_observer.h b/src/components/include/connection_handler/connection_handler_observer.h index f683318ada..b9d6a18926 100644 --- a/src/components/include/connection_handler/connection_handler_observer.h +++ b/src/components/include/connection_handler/connection_handler_observer.h @@ -168,6 +168,10 @@ class ConnectionHandlerObserver { const transport_manager::DeviceInfo& device_info, connection_handler::DeviceHandle device_id) = 0; + virtual void SetPendingApplicationState( + const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info) = 0; + protected: /** * \brief Destructor 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 0a8e71c085..552be4bee0 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 @@ -79,6 +79,9 @@ class MockConnectionHandlerObserver void(const transport_manager::ConnectionUID connection_id, const transport_manager::DeviceInfo& device_info, connection_handler::DeviceHandle device_id)); + MOCK_METHOD2(SetPendingApplicationState, + void(const transport_manager::ConnectionUID connection_id, + const transport_manager::DeviceInfo& device_info)); }; } // namespace connection_handler_test 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 index da3a80e1b2..d4319dfe0f 100644 --- 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 @@ -42,6 +42,7 @@ #include <boost/asio/connect.hpp> #include <boost/asio/ip/tcp.hpp> #include <boost/asio/ssl/stream.hpp> +#include <boost/asio/thread_pool.hpp> #include <cstdlib> #include <functional> #include <iostream> @@ -170,6 +171,8 @@ class WebsocketClientConnection const DeviceUID device_uid_; const ApplicationHandle app_handle_; + + boost::asio::thread_pool io_pool_; }; } // namespace transport_adapter 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 6d97a55a70..7a0a37758c 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 @@ -88,6 +88,10 @@ class TransportAdapterController { */ virtual DeviceSptr FindDevice(const DeviceUID& device_handle) const = 0; + virtual ConnectionSPtr FindPendingConnection( + const DeviceUID& device_handle, + const ApplicationHandle& app_handle) const = 0; + /** * @brief Create connection and fill its parameters. * 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 68d5ba3067..b30f1e35b2 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 @@ -264,6 +264,10 @@ class TransportAdapterImpl : public TransportAdapter, */ DeviceSptr FindDevice(const DeviceUID& device_handle) const OVERRIDE; + ConnectionSPtr FindPendingConnection( + const DeviceUID& device_handle, + const ApplicationHandle& app_handle) const OVERRIDE; + /** * @brief Search for device in container of devices, if it is not there - adds *it. 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 index cdc27ed8ef..0d9fda6fe5 100644 --- a/src/components/transport_manager/src/cloud/cloud_websocket_connection_factory.cc +++ b/src/components/transport_manager/src/cloud/cloud_websocket_connection_factory.cc @@ -56,11 +56,15 @@ TransportAdapter::Error CloudWebsocketConnectionFactory::Init() { 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(); + auto connection = controller_->FindPendingConnection(device_uid, app_handle); + + std::shared_ptr<WebsocketClientConnection> ws_connection = + std::dynamic_pointer_cast<WebsocketClientConnection>(connection); + if (ws_connection.use_count() == 0) { + return TransportAdapter::Error::BAD_PARAM; + } + + TransportAdapter::Error error = ws_connection->Start(); if (TransportAdapter::OK != error) { LOG4CXX_ERROR( logger_, 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 index 5093e6c2af..9f2b8e6ade 100644 --- a/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc +++ b/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc @@ -64,6 +64,12 @@ bool CloudWebsocketTransportAdapter::Restore() { } void CloudWebsocketTransportAdapter::CreateDevice(const std::string& uid) { + // If the device has already been created, just ignore the request + DeviceSptr device = FindDevice(uid); + if (device.use_count() != 0) { + return; + } + boost::regex pattern( "(wss?):\\/\\/([A-Z\\d\\.-]{2,})\\.?([A-Z]{2,})?(:\\d{2,4})\\/", boost::regex::icase); diff --git a/src/components/transport_manager/src/cloud/websocket_client_connection.cc b/src/components/transport_manager/src/cloud/websocket_client_connection.cc index e001e8877d..2947c510ff 100644 --- a/src/components/transport_manager/src/cloud/websocket_client_connection.cc +++ b/src/components/transport_manager/src/cloud/websocket_client_connection.cc @@ -53,13 +53,12 @@ WebsocketClientConnection::WebsocketClientConnection( , thread_delegate_(new LoopThreadDelegate(&message_queue_, this)) , write_thread_(threads::CreateThread("WS Async Send", thread_delegate_)) , device_uid_(device_uid) - , app_handle_(app_handle) {} + , app_handle_(app_handle) + , io_pool_(1) {} WebsocketClientConnection::~WebsocketClientConnection() { ioc_.stop(); - if (io_service_thread_.joinable()) { - io_service_thread_.join(); - } + io_pool_.join(); } TransportAdapter::Error WebsocketClientConnection::Start() { @@ -73,7 +72,6 @@ TransportAdapter::Error WebsocketClientConnection::Start() { 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); @@ -82,7 +80,6 @@ TransportAdapter::Error WebsocketClientConnection::Start() { LOG4CXX_ERROR(logger_, "Could not connect to websocket: " << host << ":" << port); LOG4CXX_ERROR(logger_, str_err); - Shutdown(); return TransportAdapter::FAIL; } ws_.handshake(host, "/", ec); @@ -92,7 +89,6 @@ TransportAdapter::Error WebsocketClientConnection::Start() { "Could not complete handshake with host/port: " << host << ":" << port); LOG4CXX_ERROR(logger_, str_err); - Shutdown(); return TransportAdapter::FAIL; } ws_.binary(true); @@ -106,16 +102,11 @@ TransportAdapter::Error WebsocketClientConnection::Start() { 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"); - }); + boost::asio::post(io_pool_, [&]() { ioc_.run(); }); LOG4CXX_DEBUG(logger_, "Successfully started websocket connection @: " << host << ":" << port); - return TransportAdapter::OK; } @@ -144,14 +135,12 @@ void WebsocketClientConnection::OnRead(boost::system::error_code ec, if (ec) { std::string str_err = "ErrorMessage: " + ec.message(); LOG4CXX_ERROR(logger_, str_err); + ws_.lowest_layer().close(); + ioc_.stop(); 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*>( @@ -224,7 +213,6 @@ void WebsocketClientConnection::LoopThreadDelegate::DrainQueue() { 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, 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 34d5a29abd..335770bea7 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 @@ -233,7 +233,9 @@ TransportAdapter::Error TransportAdapterImpl::Connect( server_connection_factory_->CreateConnection(device_id, app_handle); if (TransportAdapter::OK != err) { connections_lock_.AcquireForWriting(); - connections_.erase(std::make_pair(device_id, app_handle)); + if (!pending_app) { + connections_.erase(std::make_pair(device_id, app_handle)); + } connections_lock_.Release(); } LOG4CXX_TRACE(logger_, "exit with error: " << err); @@ -819,6 +821,26 @@ void TransportAdapterImpl::DeviceSwitched(const DeviceUID& device_handle) { UNUSED(device_handle); } +ConnectionSPtr TransportAdapterImpl::FindPendingConnection( + const DeviceUID& device_id, const ApplicationHandle& app_handle) const { + LOG4CXX_TRACE(logger_, + "enter. device_id: " << &device_id + << ", app_handle: " << &app_handle); + ConnectionSPtr connection; + connections_lock_.AcquireForReading(); + ConnectionMap::const_iterator it = + connections_.find(std::make_pair(device_id, app_handle)); + if (it != connections_.end()) { + const ConnectionInfo& info = it->second; + if (info.state == ConnectionInfo::PENDING) { + connection = info.connection; + } + } + connections_lock_.Release(); + LOG4CXX_TRACE(logger_, "exit with Connection: " << connection); + return connection; +} + DeviceSptr TransportAdapterImpl::FindDevice(const DeviceUID& device_id) const { LOG4CXX_TRACE(logger_, "enter. device_id: " << &device_id); DeviceSptr ret; @@ -836,7 +858,8 @@ DeviceSptr TransportAdapterImpl::FindDevice(const DeviceUID& device_id) const { void TransportAdapterImpl::ConnectPending(const DeviceUID& device_id, const ApplicationHandle& app_handle) { - connections_lock_.AcquireForReading(); + LOG4CXX_AUTO_TRACE(logger_); + connections_lock_.AcquireForWriting(); ConnectionMap::iterator it_conn = connections_.find(std::make_pair(device_id, app_handle)); if (it_conn != connections_.end()) { @@ -845,6 +868,14 @@ void TransportAdapterImpl::ConnectPending(const DeviceUID& device_id, } connections_lock_.Release(); + DeviceSptr device = FindDevice(device_id); + if (device.use_count() == 0) { + LOG4CXX_ERROR( + logger_, "Unable to find device, cannot set connection pending status"); + } else { + device->set_connection_status(ConnectionStatus::PENDING); + } + for (TransportAdapterListenerList::iterator it = listeners_.begin(); it != listeners_.end(); ++it) { diff --git a/src/components/transport_manager/src/transport_manager_impl.cc b/src/components/transport_manager/src/transport_manager_impl.cc index 301132d26f..0b8724ff85 100644 --- a/src/components/transport_manager/src/transport_manager_impl.cc +++ b/src/components/transport_manager/src/transport_manager_impl.cc @@ -1002,19 +1002,42 @@ void TransportManagerImpl::Handle(TransportAdapterEvent event) { case EventTypeEnum::ON_CONNECT_PENDING: { const DeviceHandle device_handle = converter_.UidToHandle( event.device_uid, event.transport_adapter->GetConnectionType()); - AddConnection(ConnectionInternal(this, - event.transport_adapter, - ++connection_id_counter_, - event.device_uid, - event.application_id, - device_handle)); + 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::OnConnectionPending, DeviceInfo(device_handle, event.device_uid, event.transport_adapter->DeviceName(event.device_uid), event.transport_adapter->GetConnectionType()), - connection_id_counter_); + connection_id); LOG4CXX_DEBUG(logger_, "event_type = ON_CONNECT_PENDING"); break; } diff --git a/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h b/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h index 642c193d63..1de5eac702 100644 --- a/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h +++ b/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h @@ -55,6 +55,9 @@ class MockTransportAdapterController : public TransportAdapterController { void(ConnectionSPtr connection, const DeviceUID& device_handle, const ApplicationHandle& app_handle)); + MOCK_CONST_METHOD2(FindPendingConnection, + ConnectionSPtr(const DeviceUID& device_handle, + const ApplicationHandle& app_handle)); MOCK_METHOD2(ConnectDone, void(const DeviceUID& device_handle, const ApplicationHandle& app_handle)); 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 f44f8785aa..1f4a17cf6c 100644 --- a/src/components/transport_manager/test/tcp_client_listener_test.cc +++ b/src/components/transport_manager/test/tcp_client_listener_test.cc @@ -69,6 +69,9 @@ class MockTransportAdapterController : public TransportAdapterController { MOCK_METHOD1(SearchDeviceDone, void(const DeviceVector& devices)); MOCK_METHOD1(SearchDeviceFailed, void(const SearchDeviceError& error)); MOCK_CONST_METHOD1(FindDevice, DeviceSptr(const DeviceUID& device_handle)); + MOCK_CONST_METHOD2(FindPendingConnection, + ConnectionSPtr(const DeviceUID& device_handle, + const ApplicationHandle& app_handle)); MOCK_METHOD3(ConnectionCreated, void(ConnectionSPtr connection, const DeviceUID& device_handle, |