diff options
Diffstat (limited to 'src/components/transport_manager/include/transport_manager')
6 files changed, 357 insertions, 56 deletions
diff --git a/src/components/transport_manager/include/transport_manager/iap2_emulation/iap2_transport_adapter.h b/src/components/transport_manager/include/transport_manager/iap2_emulation/iap2_transport_adapter.h new file mode 100644 index 0000000000..36a2b374dd --- /dev/null +++ b/src/components/transport_manager/include/transport_manager/iap2_emulation/iap2_transport_adapter.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2017, Ford Motor Company + * 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_IAP2_EMULATION_IAP2_TRANSPORT_ADAPTER_H_ +#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_IAP2_EMULATION_IAP2_TRANSPORT_ADAPTER_H_ + +#include "transport_manager/tcp/tcp_transport_adapter.h" +#include "transport_manager/transport_manager_settings.h" +#include "resumption/last_state.h" +#include "utils/macro.h" +#include "utils/threads/thread_delegate.h" + +namespace threads { +class Thread; +} + +namespace transport_manager { +namespace transport_adapter { + +/** + * @brief The IAP2BluetoothEmulationTransportAdapter class implements iAP2 + * Bluetooth transport over TCP + */ +class IAP2BluetoothEmulationTransportAdapter : public TcpTransportAdapter { + public: + /** + * @brief IAP2BluetoothEmulationTransportAdapter constructor + * @param port TCP port to listen on + * @param last_state LastState instance reference + * @param settings Settings reference + */ + IAP2BluetoothEmulationTransportAdapter( + const uint16_t port, + resumption::LastState& last_state, + const TransportManagerSettings& settings); + + /** + * @brief DeviceSwitched is called during switching from iAP2 Bluetooth to + * iAP2 USB transport. + * Currently there is no logic to switch back from iAP2 USB to iAP2 Bluetooth + * due to Bluetooth reconnection takes much time and this violates some Apple + * restrictions for iAP2 protocol, so if this method will be called - assert + * will be called + * @param device_handle Device handle of switched device + */ + void DeviceSwitched(const DeviceUID& device_handle) OVERRIDE; + + protected: + /** + * @brief GetDeviceType Provides SDL device type for transport adapter + * @return Device type + */ + DeviceType GetDeviceType() const OVERRIDE; +}; + +/** + * @brief The IAP2USBEmulationTransportAdapter class implements emulation of + * iAP2 USB transport over TCP + */ +class IAP2USBEmulationTransportAdapter : public TcpTransportAdapter { + public: + /** + * @brief IAP2USBEmulationTransportAdapter constructor + * @param port TCP port to listen on + * @param last_state LastState instance reference + * @param settings Settings reference + */ + IAP2USBEmulationTransportAdapter(const uint16_t port, + resumption::LastState& last_state, + const TransportManagerSettings& settings); + + /** + * Destructor + */ + ~IAP2USBEmulationTransportAdapter(); + + /** + * @brief DeviceSwitched is called during switching from iAP2 Bluetooth to + * iAP2 USB transport. Sends ACK signal for switching request. + * @param device_handle Device handle of switched device + */ + void DeviceSwitched(const DeviceUID& device_handle) OVERRIDE; + + protected: + /** + * @brief GetDeviceType Provides SDL device type for transport adapter + * @return Device type + */ + DeviceType GetDeviceType() const OVERRIDE; + + private: + /** + * @brief The IAPSignalHandlerDelegate class handles signals from the system + * to start transport switching flow + */ + class IAPSignalHandlerDelegate : public threads::ThreadDelegate { + public: + /** + * @brief IAPSignalHandlerDelegate Constructor + * @param adapter Pointer to iAP2 USB adapter + */ + IAPSignalHandlerDelegate(IAP2USBEmulationTransportAdapter& adapter); + + /** + * @brief threadMain Main loop to track incoming signals + */ + void threadMain() OVERRIDE; + + /** + * @brief exitThreadMain Stops main loop + */ + void exitThreadMain() OVERRIDE; + + private: + /** + * @brief adapter_ Reference to owning adapter + */ + IAP2USBEmulationTransportAdapter& adapter_; + + /** + * @brief run_flag_ Flag defines whether main loop is active + */ + bool run_flag_; + + /** + * @brief in_ Input signals channel descriptor + */ + int in_; + }; + + threads::Thread* signal_handler_; + int out_; +}; +} // namespace transport_adapter +} // namespace transport_manager +#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_IAP2_EMULATION_IAP2_TRANSPORT_ADAPTER_H_ diff --git a/src/components/transport_manager/include/transport_manager/tcp/tcp_device.h b/src/components/transport_manager/include/transport_manager/tcp/tcp_device.h index 981ba9f6ee..7aa0b72687 100644 --- a/src/components/transport_manager/include/transport_manager/tcp/tcp_device.h +++ b/src/components/transport_manager/include/transport_manager/tcp/tcp_device.h @@ -66,6 +66,18 @@ class TcpDevice : public Device { **/ TcpDevice(const in_addr_t& in_addr, const std::string& name); +#if defined(BUILD_TESTS) + /** + * @brief TcpDevice + * @param in_addr IP address of device + * @param device_uid Unique device id + * @param transport_switch_id Id used for transport switching + */ + TcpDevice(const in_addr_t& in_addr, + const std::string& device_uid, + const std::string& transport_switch_id); +#endif + virtual ~TcpDevice(); /** 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 d4c97d5233..2b1ada79ad 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 @@ -400,6 +400,26 @@ class TransportAdapterImpl : public TransportAdapter, const DataSendError& error) OVERRIDE; /** + * @brief DoTransportSwitch notifies listeners of transport adapter events + * that transport switching is requested by system + */ + void DoTransportSwitch() const OVERRIDE; + + /** + * @brief DeviceSwitched Notifies system on successful transport switch for + * particular device + * @param device_handle Device handle of switched device + */ + void DeviceSwitched(const DeviceUID& device_handle) OVERRIDE; + + /** + * @brief GetSwitchableDevices Provides list of devices able to switch their + * transport (e.g. iAP2 Bluetooth to iAP2 USB). + * @return + */ + SwitchableDevices GetSwitchableDevices() const OVERRIDE; + + /** * @brief Return name of device. * * @param device_id Device unique identifier. @@ -409,6 +429,13 @@ class TransportAdapterImpl : public TransportAdapter, std::string DeviceName(const DeviceUID& device_id) const OVERRIDE; /** + * @brief StopDevice looks for specific device in devices list and calls + * Stop() interface of that device + * @param device_id unique device identifier that has to be stopped. + */ + void StopDevice(const DeviceUID& device_id) const OVERRIDE; + + /** * @brief Allows to obtain connection type used by device. * @return connection type. */ 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 0a1eeb6b4a..424fa53dea 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 @@ -146,6 +146,7 @@ class TransportAdapterListener { const DeviceUID& device_handle, const ApplicationHandle& app_handle, const CommunicationError& error) = 0; + /** * @brief Search specified device adapter in the container of shared pointers *to device adapters to be sure it is available, @@ -269,6 +270,13 @@ class TransportAdapterListener { virtual void OnCommunicationError(const TransportAdapter* transport_adapter, const DeviceUID& device_handle, const ApplicationHandle& app_handle) = 0; + /** + * @brief OnTransportSwitchRequested notifies on received signal to start + * transport switching flow (at the moment Bluetooth to USB only) + * @param transport_adapter Transport adapter who received the signal + */ + virtual void OnTransportSwitchRequested( + const TransportAdapter* transport_adapter) = 0; }; } // transport_adapter namespace 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 a7cd544563..8a8031c3cf 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 @@ -49,26 +49,6 @@ class TransportAdapterListenerImpl : public transport_adapter::TransportAdapterListener { public: /** - * @enum Available types of events. - */ - enum EventTypeEnum { - ON_SEARCH_DONE = 0, - ON_SEARCH_FAIL, - ON_DEVICE_LIST_UPDATED, - ON_FIND_NEW_APPLICATIONS_REQUEST, - ON_CONNECT_DONE, - ON_CONNECT_FAIL, - ON_DISCONNECT_DONE, - ON_DISCONNECT_FAIL, - ON_SEND_DONE, - ON_SEND_FAIL, - ON_RECEIVED_DONE, - ON_RECEIVED_FAIL, - ON_COMMUNICATION_ERROR, - ON_UNEXPECTED_DISCONNECT - }; - - /** * @brief Constructor. * * @param manager Pointer to the transport manager class. @@ -283,7 +263,14 @@ class TransportAdapterListenerImpl */ virtual void OnCommunicationError(const TransportAdapter* adapter, const DeviceUID& device, - const ApplicationHandle& app_id); + const ApplicationHandle& app_id) OVERRIDE; + + /** + * @brief OnTransportSwitchRequested notifies on received signal to start + * transport switching flow (at the moment Bluetooth to USB only) + * @param transport_adapter Transport adapter who received the signal + */ + void OnTransportSwitchRequested(const TransportAdapter* adapter) OVERRIDE; private: TransportManager* 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 4dd74086be..eaa71ce3bb 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 @@ -39,6 +39,8 @@ #include <vector> #include <utility> #include <algorithm> +#include <tuple> +#include <functional> #include "utils/timer.h" #include "utils/timer_task_impl.h" @@ -63,6 +65,7 @@ typedef threads::MessageLoopThread<std::queue<protocol_handler::RawMessagePtr> > typedef threads::MessageLoopThread<std::queue<TransportAdapterEvent> > TransportAdapterEventLoopThread; typedef utils::SharedPtr<timer::Timer> TimerSPtr; +typedef std::map<DeviceUID, TransportAdapter*> DeviceToAdapterMap; /** * @brief Implementation of transport manager.s @@ -94,6 +97,7 @@ class TransportManagerImpl bool shutdown_; DeviceHandle device_handle_; int messages_count; + bool active_; ConnectionInternal(TransportManagerImpl* transport_manager, TransportAdapter* transport_adapter, @@ -241,11 +245,20 @@ class TransportManagerImpl int Visibility(const bool& on_off) const OVERRIDE; /** + * DEPRECATED + * Must be moved under 'private' section * @brief Updates total device list with info from specific transport adapter. * @param ta Transport adapter */ void UpdateDeviceList(TransportAdapter* ta); + /** + * @brief OnDeviceListUpdated updates device list and sends appropriate + * notifications to listeners in case of something is changed + * @param ta Transport adapter to check for updated devices state + */ + void OnDeviceListUpdated(TransportAdapter* ta); + #ifdef TELEMETRY_MONITOR /** * @brief Setup observer for time metric. @@ -307,44 +320,53 @@ class TransportManagerImpl private: /** - * @brief Structure that contains conversion functions (Device ID -> Device - * Handle; Device Handle -> Device ID) - */ + * @brief Structure that contains conversion functions (Device ID -> Device + * Handle; Device Handle -> Device ID) + */ struct Handle2GUIDConverter { - typedef std::vector<DeviceUID> ConversionTable; - - DeviceHandle UidToHandle(const DeviceUID& dev_uid) { - bool is_new = true; - return UidToHandle(dev_uid, is_new); - } - - DeviceHandle UidToHandle(const DeviceUID& dev_uid, bool& is_new) { - { - sync_primitives::AutoReadLock lock(conversion_table_lock); - ConversionTable::iterator it = std::find( - conversion_table_.begin(), conversion_table_.end(), dev_uid); - if (it != conversion_table_.end()) { - is_new = false; - return std::distance(conversion_table_.begin(), it) + - 1; // handle begin since 1 (one) - } + /** + * @brief ConversionTable Records uid/connection type/handle + */ + typedef std::vector<std::tuple<DeviceUID, std::string, DeviceHandle> > + ConversionTable; + + /** + * @brief The HandleFinder struct helper to search for hanlde in coversion + * table + */ + struct HandleFinder { + explicit HandleFinder(const DeviceHandle& look_for) + : look_for_(look_for) {} + + bool operator()(const ConversionTable::value_type value) const { + return look_for_ == std::get<2>(value); } - is_new = true; - sync_primitives::AutoWriteLock lock(conversion_table_lock); - conversion_table_.push_back(dev_uid); - return conversion_table_.size(); // handle begin since 1 (one) - } - - DeviceUID HandleToUid(const DeviceHandle handle) { - sync_primitives::AutoReadLock lock(conversion_table_lock); - if (handle == 0 || handle > conversion_table_.size()) { - return DeviceUID(); - } - return conversion_table_[handle - 1]; // handle begin since 1 (one) - } + const DeviceHandle look_for_; + }; + + /** + * @brief UidToHandle Converts UID to handle considering connection type as + * UID may be the same in case device is connected over Bluetooth/USB (e.g. + * for IAP2) + * @param dev_uid Device UID + * @param connection_type Connection type + * @return Device handle + */ + DeviceHandle UidToHandle(const DeviceUID& dev_uid, + const std::string& connection_type); + + /** + * @brief HandleToUid Converts handle to device UID + * @param handle Device handle + * @return Device UID + */ + DeviceUID HandleToUid(const DeviceHandle handle); + + private: ConversionTable conversion_table_; - sync_primitives::RWLock conversion_table_lock; + std::hash<std::string> hash_function_; + sync_primitives::RWLock conversion_table_lock_; }; /** @@ -353,6 +375,15 @@ class TransportManagerImpl */ Handle2GUIDConverter converter_; +#ifdef BUILD_TESTS + public: + Handle2GUIDConverter& get_converter() { + return converter_; + } + + private: +#endif // BUILD_TESTS + explicit TransportManagerImpl(const TransportManagerImpl&); int connection_id_counter_; sync_primitives::RWLock connections_lock_; @@ -372,13 +403,70 @@ class TransportManagerImpl sync_primitives::RWLock device_list_lock_; DeviceInfoList device_list_; + timer::Timer device_switch_timer_; + sync_primitives::Lock device_lock_; + DeviceUID device_to_reconnect_; + + /** + * @brief Adds new incoming connection to connections list + * @param c New connection + */ void AddConnection(const ConnectionInternal& c); + + /** + * @brief Removes connection from connections list + * @param id Identifier of connection to be removed + * @param transport_adapter Pointer to transport adapter + * that holds connection + */ void RemoveConnection(const uint32_t id, transport_adapter::TransportAdapter* transport_adapter); + + /** + * @brief Deactivates all connections related to certain device + * @param device_uid Device unique identifier + */ + void DeactivateDeviceConnections(const DeviceUID& device_uid); + /** + * @brief Returns connection from connections list by connection identifier + * @param id Connection identifier + * @return Pointer to connection or NULL if connection could not be found + */ ConnectionInternal* GetConnection(const ConnectionUID id); + + /** + * @brief Returns connection from connections list by device unique id + * and application handle + * @param device Device unique identifier + * @param application Application handle + * @return Pointer to connection or NULL if connection could not be found + */ ConnectionInternal* GetConnection(const DeviceUID& device, const ApplicationHandle& application); + /** + * @brief Returns active connection from connections list by device unique + * id + * and application handle + * (this method returns only active connections as opposed to previous one) + * @param device Device unique identifier + * @param application Application handle + * @return Pointer to connection or NULL if connection could not be found + */ + ConnectionInternal* GetActiveConnection(const DeviceUID& device, + const ApplicationHandle& application); + + /** + * @brief TryDeviceSwitch in case USB device is connected and there is + * appropriate Bluetooth device with same UUID stops Bluetooth device and + * initiates switching sequence for upper layers. Also starts timer to wait + * for sequence to complete. + * @param ta Transport adapter having device to try switching sequence + * At the moment implementation implies only IAP2-Bluetooth to IAP2-USB + * switching + */ + void TryDeviceSwitch(TransportAdapter* ta); + void AddDataToContainer( ConnectionUID id, std::map<ConnectionUID, std::pair<unsigned int, unsigned char*> >& @@ -394,11 +482,25 @@ class TransportManagerImpl unsigned int frame_size, unsigned char** frame); - void OnDeviceListUpdated(TransportAdapter* ta); void DisconnectAllDevices(); void TerminateAllAdapters(); int InitAllAdapters(); static Connection convert(const ConnectionInternal& p); + + /** + * @brief ReconnectionTimeout notifies upper layers on switching sequence + * timeout expiration + */ + void ReconnectionTimeout(); + + /** + * @brief UpdateDeviceMapping handles internal device-to-adapter mapping, + * performs its update on adding/removal of devices. Also used by IAP2 + * switching flow to substitute BT with USB transport + * @param ta Pointer to transport adapter + * @return True if mapping has been updated, otherwise - false + */ + bool UpdateDeviceMapping(TransportAdapter* ta); }; // class TransportManagerImpl } // namespace transport_manager #endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_TRANSPORT_MANAGER_IMPL_H_ |