diff options
author | JackLivio <jack@livio.io> | 2018-11-30 15:53:49 -0500 |
---|---|---|
committer | JackLivio <jack@livio.io> | 2018-11-30 15:53:49 -0500 |
commit | 64be1341b106c1b68c8adfb7018f4555d493be75 (patch) | |
tree | bb7398953b163593857884922d846260456bb110 | |
parent | 106abc1b824dc3b8c3033548b0803ac1f4563b1a (diff) | |
download | sdl_core-64be1341b106c1b68c8adfb7018f4555d493be75.tar.gz |
Set HMI None on disconnect. Add reconnection after disconnect.
15 files changed, 163 insertions, 55 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 a3e3cece72..797044993a 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/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/sdl_activate_app_request_test.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/sdl_activate_app_request_test.cc index 6adc9c8150..8543a201bf 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/sdl_activate_app_request_test.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/sdl_activate_app_request_test.cc @@ -460,7 +460,7 @@ TEST_F(SDLActivateAppRequestTest, WaitingCloudApplication_ConnectDevice) { const uint16_t kRetries = 3; const uint32_t kRetryTimeout = 2000; const uint32_t kMinimumTimeout = kRetries * kRetryTimeout; - + MockApplicationManagerSettings settings; EXPECT_CALL(settings, cloud_app_max_retry_attempts()) .WillOnce(Return(kRetries)); @@ -468,14 +468,14 @@ TEST_F(SDLActivateAppRequestTest, WaitingCloudApplication_ConnectDevice) { .WillOnce(Return(kRetryTimeout)); EXPECT_CALL(app_mngr_, get_settings()).WillOnce(ReturnRef(settings)); - EXPECT_CALL( - app_mngr_, - updateRequestTimeout(0, kCorrelationID, Gt(kMinimumTimeout))); + EXPECT_CALL(app_mngr_, + updateRequestTimeout(0, kCorrelationID, Gt(kMinimumTimeout))); MockConnectionHandler connection_handler; EXPECT_CALL(connection_handler, ConnectToDevice(kHandle)); - EXPECT_CALL(app_mngr_, connection_handler()).WillOnce(ReturnRef(connection_handler)); + EXPECT_CALL(app_mngr_, connection_handler()) + .WillOnce(ReturnRef(connection_handler)); command->Run(); } diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc index 938e994ba0..1c8be1deab 100644 --- a/src/components/application_manager/src/application_manager_impl.cc +++ b/src/components/application_manager/src/application_manager_impl.cc @@ -915,6 +915,33 @@ 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(); + auto it = pending_device_map_.find(name); + if (it == pending_device_map_.end()) { + return; + } + + 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(); } diff --git a/src/components/connection_handler/src/connection_handler_impl.cc b/src/components/connection_handler/src/connection_handler_impl.cc index 88d57e5d2c..0d6aabcae4 100644 --- a/src/components/connection_handler/src/connection_handler_impl.cc +++ b/src/components/connection_handler/src/connection_handler_impl.cc @@ -284,10 +284,12 @@ void ConnectionHandlerImpl::OnConnectionPending( connection_handler::DeviceHandle device_id = connection->connection_device_handle(); - // uint32_t app_id = KeyFromPair(connection_id, session_id); 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..f9a134b1fa 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> @@ -127,7 +128,7 @@ class WebsocketClientConnection TransportAdapterController* controller_; boost::asio::io_context ioc_; tcp::resolver resolver_; - websocket::stream<tcp::socket> ws_; + std::shared_ptr<websocket::stream<tcp::socket> > ws_; boost::beast::flat_buffer buffer_; std::string host_; std::string text_; @@ -170,6 +171,10 @@ class WebsocketClientConnection const DeviceUID device_uid_; const ApplicationHandle app_handle_; + + bool first_run_; + boost::asio::thread_pool io_pool_; + bool dead_; }; } // 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 8d03bdb2c7..f1f64ae53a 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 @@ -260,6 +260,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..3db97feed2 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) { + 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/websocket_client_connection.cc b/src/components/transport_manager/src/cloud/websocket_client_connection.cc index 0912a07999..f487a9a16a 100644 --- a/src/components/transport_manager/src/cloud/websocket_client_connection.cc +++ b/src/components/transport_manager/src/cloud/websocket_client_connection.cc @@ -48,18 +48,17 @@ WebsocketClientConnection::WebsocketClientConnection( TransportAdapterController* controller) : controller_(controller) , resolver_(ioc_) - , ws_(ioc_) + , ws_(std::make_shared<websocket::stream<tcp::socket> >(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) {} + , 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,49 +72,41 @@ 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); + 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); + 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); + 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"); - }); + ws_->async_read(buffer_, + std::bind(&WebsocketClientConnection::OnRead, + this, + std::placeholders::_1, + std::placeholders::_2)); + + boost::asio::post(io_pool_, [&]() { ioc_.run(); }); LOG4CXX_DEBUG(logger_, "Successfully started websocket connection @: " << host << ":" << port); - return TransportAdapter::OK; } @@ -131,11 +122,11 @@ void WebsocketClientConnection::Recv(boost::system::error_code ec) { return; } - ws_.async_read(buffer_, - std::bind(&WebsocketClientConnection::OnRead, - this, - std::placeholders::_1, - std::placeholders::_2)); + ws_->async_read(buffer_, + std::bind(&WebsocketClientConnection::OnRead, + this, + std::placeholders::_1, + std::placeholders::_2)); } void WebsocketClientConnection::OnRead(boost::system::error_code ec, @@ -144,14 +135,13 @@ 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()); + controller_->ConnectPending(device_uid_, app_handle_); 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*>( @@ -219,11 +209,10 @@ void WebsocketClientConnection::LoopThreadDelegate::DrainQueue() { message_queue_.pop(message_ptr); if (!shutdown_) { boost::system::error_code ec; - handler_.ws_.write( + 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, 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 8928ecb4d2..e25e21a95f 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); @@ -821,6 +823,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; @@ -838,15 +860,26 @@ DeviceSptr TransportAdapterImpl::FindDevice(const DeviceUID& device_id) const { void TransportAdapterImpl::ConnectPending(const DeviceUID& device_id, const ApplicationHandle& app_handle) { - connections_lock_.AcquireForReading(); + connections_lock_.AcquireForWriting(); ConnectionMap::iterator it_conn = connections_.find(std::make_pair(device_id, app_handle)); if (it_conn != connections_.end()) { ConnectionInfo& info = it_conn->second; + if (info.state == ConnectionInfo::ESTABLISHED) { + LOG4CXX_DEBUG(logger_, "Reset Connection Pointer"); + connections_.erase(std::make_pair(device_id, app_handle)); + + connections_lock_.Release(); + CreateDevice(device_id); + connections_lock_.AcquireForWriting(); + } info.state = ConnectionInfo::PENDING; } connections_lock_.Release(); + DeviceSptr device = FindDevice(device_id); + 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 518a5639db..43acd9a9a2 100644 --- a/src/components/transport_manager/src/transport_manager_impl.cc +++ b/src/components/transport_manager/src/transport_manager_impl.cc @@ -998,19 +998,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, |