diff options
5 files changed, 165 insertions, 3 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 index de8a3c0080..df8aa3a76f 100644 --- 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 @@ -36,6 +36,11 @@ #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 { @@ -93,8 +98,13 @@ class IAP2USBEmulationTransportAdapter : public TcpTransportAdapter { const TransportManagerSettings& settings); /** + * Destructor + */ + ~IAP2USBEmulationTransportAdapter(); + + /** * @brief DeviceSwitched is called during switching from iAP2 Bluetooth to - * iAP2 USB transport + * iAP2 USB transport. Sends ACK signal for switching request. * @param device_handle Device handle of switched device */ void DeviceSwitched(const DeviceUID& device_handle) OVERRIDE; @@ -105,6 +115,38 @@ class IAP2USBEmulationTransportAdapter : public TcpTransportAdapter { * @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: + IAP2USBEmulationTransportAdapter* adapter_; + bool run_flag_; + int in_; + }; + + threads::Thread* signal_handler_; + int out_; }; } } // namespace transport_manager::transport_adapter 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..6eb15b638e 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/src/iap2_emulation/iap2_transport_adapter.cc b/src/components/transport_manager/src/iap2_emulation/iap2_transport_adapter.cc index 20dc059385..1429a57e9e 100644 --- a/src/components/transport_manager/src/iap2_emulation/iap2_transport_adapter.cc +++ b/src/components/transport_manager/src/iap2_emulation/iap2_transport_adapter.cc @@ -32,6 +32,21 @@ #include "transport_manager/iap2_emulation/iap2_transport_adapter.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> + +#include "utils/threads/thread.h" +#include "utils/file_system.h" + +namespace { +mode_t mode = 0666; +const auto in_signals_channel = "iap_signals_in"; +const auto out_signals_channel = "iap_signals_out"; +} // namespace + namespace transport_manager { namespace transport_adapter { @@ -58,17 +73,86 @@ IAP2USBEmulationTransportAdapter::IAP2USBEmulationTransportAdapter( const uint16_t port, resumption::LastState& last_state, const TransportManagerSettings& settings) - : TcpTransportAdapter(port, last_state, settings) {} + : TcpTransportAdapter(port, last_state, settings), out_(0) { + auto delegate = new IAPSignalHandlerDelegate(this); + signal_handler_ = + threads::CreateThread("iAP signal handler", delegate); + signal_handler_->start(); + LOG4CXX_DEBUG(logger_, "Out signals channel creation result: " + << mkfifo(out_signals_channel, mode)); +} + +IAP2USBEmulationTransportAdapter::~IAP2USBEmulationTransportAdapter() { + signal_handler_->join(); + threads::DeleteThread(signal_handler_); + LOG4CXX_DEBUG(logger_, "Out close result: " << close(out_)); + LOG4CXX_DEBUG(logger_, "Out unlink result: " << unlink(out_signals_channel)); +} void IAP2USBEmulationTransportAdapter::DeviceSwitched( const DeviceUID& device_handle) { LOG4CXX_AUTO_TRACE(logger_); UNUSED(device_handle); + const auto switch_signal_ack = std::string("SDL_TRANSPORT_SWITCH_ACK\n"); + + auto out_ = open(out_signals_channel, O_WRONLY); + LOG4CXX_DEBUG(logger_, "Out channel descriptor: " << out_); + + const auto bytes = + write(out_, switch_signal_ack.c_str(), switch_signal_ack.size()); + LOG4CXX_DEBUG(logger_, "Written bytes to out: " << bytes); + + LOG4CXX_DEBUG(logger_, "Switching signal ACK is sent"); LOG4CXX_DEBUG(logger_, "iAP2 USB device is switched with iAP2 Bluetooth"); } DeviceType IAP2USBEmulationTransportAdapter::GetDeviceType() const { return IOS_USB; } + +IAP2USBEmulationTransportAdapter:: +IAPSignalHandlerDelegate::IAPSignalHandlerDelegate( + IAP2USBEmulationTransportAdapter* adapter) + : adapter_(adapter), + run_flag_(true), + in_(0) { + LOG4CXX_DEBUG(logger_, "In signals channel creation result: " + << mkfifo(in_signals_channel, mode)); +} + +void IAP2USBEmulationTransportAdapter::IAPSignalHandlerDelegate::threadMain() { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Signal handling is started"); + const auto switch_signal = "SDL_TRANSPORT_SWITCH"; + LOG4CXX_DEBUG(logger_, "Waiting for signal: " << switch_signal); + + in_ = open(in_signals_channel, O_RDONLY); + LOG4CXX_DEBUG(logger_, "In channel descriptor: " << in_); + + const auto size = 32; + while (run_flag_) { + char buffer[size]; + auto bytes = read(in_, &buffer, size); + if (!bytes) { + continue; + } + LOG4CXX_DEBUG(logger_, "Read in bytes: " << bytes); + std::string str(buffer); + if (std::string::npos != str.find(switch_signal)) { + LOG4CXX_DEBUG(logger_, "Switch signal received."); + adapter_->DoTransportSwitch(); + } + } +} + +void IAP2USBEmulationTransportAdapter:: +IAPSignalHandlerDelegate::exitThreadMain() { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, "Stopping signal handling."); + run_flag_ = false; + LOG4CXX_DEBUG(logger_, "In close result: " << close(in_)); + LOG4CXX_DEBUG(logger_, "In unlink result: " << unlink(in_signals_channel)); +} + } } // namespace transport_manager::transport_adapter diff --git a/src/components/transport_manager/src/tcp/tcp_client_listener.cc b/src/components/transport_manager/src/tcp/tcp_client_listener.cc index bce15e4e07..839eed9a5b 100644 --- a/src/components/transport_manager/src/tcp/tcp_client_listener.cc +++ b/src/components/transport_manager/src/tcp/tcp_client_listener.cc @@ -235,9 +235,16 @@ void TcpClientListener::Loop() { if (enable_keepalive_) { SetKeepaliveOptions(connection_fd); } - +#if defined (BUILD_TESTS) + const auto device_uid = device_name + + std::string(":") + + std::to_string(port_); + TcpDevice* tcp_device = + new TcpDevice(client_address.sin_addr.s_addr, device_uid, device_name); +#else TcpDevice* tcp_device = new TcpDevice(client_address.sin_addr.s_addr, device_name); +#endif // BUILD_TESTS DeviceSptr device = controller_->AddDevice(tcp_device); tcp_device = static_cast<TcpDevice*>(device.get()); const ApplicationHandle app_handle = diff --git a/src/components/transport_manager/src/tcp/tcp_device.cc b/src/components/transport_manager/src/tcp/tcp_device.cc index d3f132759a..1a0ca80d94 100644 --- a/src/components/transport_manager/src/tcp/tcp_device.cc +++ b/src/components/transport_manager/src/tcp/tcp_device.cc @@ -46,6 +46,23 @@ TcpDevice::TcpDevice(const in_addr_t& in_addr, const std::string& name) LOG4CXX_AUTO_TRACE(logger_); } +#if defined (BUILD_TESTS) +TcpDevice::TcpDevice(const in_addr_t& in_addr, + const std::string& device_uid, + const std::string& transport_switch_id) + : Device(device_uid, device_uid, transport_switch_id), + applications_mutex_(), + in_addr_(in_addr), + last_handle_(0) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, + "Device created with transport switch emulation support."); + LOG4CXX_DEBUG(logger_, + "Device parameters: " << device_uid + << " / " << transport_switch_id); +} +#endif // BUILD_TESTS + bool TcpDevice::IsSameAs(const Device* other) const { LOG4CXX_AUTO_TRACE(logger_); LOG4CXX_DEBUG(logger_, "Device: " << other); |