summaryrefslogtreecommitdiff
path: root/SDL_Core/src/components/transport_manager/include/transport_manager/transport_manager_impl.h
diff options
context:
space:
mode:
Diffstat (limited to 'SDL_Core/src/components/transport_manager/include/transport_manager/transport_manager_impl.h')
-rwxr-xr-xSDL_Core/src/components/transport_manager/include/transport_manager/transport_manager_impl.h495
1 files changed, 495 insertions, 0 deletions
diff --git a/SDL_Core/src/components/transport_manager/include/transport_manager/transport_manager_impl.h b/SDL_Core/src/components/transport_manager/include/transport_manager/transport_manager_impl.h
new file mode 100755
index 000000000..c46301758
--- /dev/null
+++ b/SDL_Core/src/components/transport_manager/include/transport_manager/transport_manager_impl.h
@@ -0,0 +1,495 @@
+/**
+ * \file transport_manager_impl.h
+ * \brief TransportManagerImpl class header file.
+ * Copyright (c) 2013, 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_TRANSPORT_MANAGER_IMPL_H_
+#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_TRANSPORT_MANAGER_IMPL_H_
+
+#include <pthread.h>
+
+#ifdef RWLOCK_SUPPORT
+# if (defined(OS_LINUX) && (defined(__USE_UNIX98) || defined(__USE_XOPEN2K))) || \
+ (defined(OS_QNX) && (defined(__EXT_POSIX1_200112)))
+# define USE_RWLOCK
+# endif
+#endif
+
+#include <queue>
+#include <map>
+#include <list>
+#include <algorithm>
+#include <memory>
+
+#include "utils/logger.h"
+#include "utils/timer_thread.h"
+#include "transport_manager/common.h"
+#include "transport_manager/transport_manager.h"
+#include "transport_manager/transport_manager_listener.h"
+#include "transport_manager/transport_adapter/transport_adapter_listener_impl.h"
+
+using ::transport_manager::transport_adapter::TransportAdapterListener;
+
+namespace transport_manager {
+
+/**
+ * @enum Transport manager states.
+ */
+enum {
+ E_SUCCESS = 0,
+ E_TM_IS_NOT_INITIALIZED,
+ E_INVALID_HANDLE,
+ E_CONNECTION_IS_TO_SHUTDOWN,
+ E_CONNECTION_EXISTS,
+ E_ADAPTER_EXISTS,
+ E_ADAPTERS_FAIL,
+ E_INTERNAL_ERROR
+};
+
+/**
+ * @brief Implementation of transport manager.
+ */
+class TransportManagerImpl : public TransportManager {
+ public:
+ /**
+ * @brief Hold connection parameters.
+ */
+ struct Connection {
+ ConnectionUID id;
+ DeviceUID device;
+ ApplicationHandle application;
+ };
+
+ private:
+ /**
+ * @brief Structure that contains internal connection parameters
+ */
+ struct ConnectionInternal: public Connection {
+ TransportManagerImpl* transport_manager;
+ TransportAdapter* transport_adapter;
+ typedef timer::TimerThread<ConnectionInternal> TimerInternal;
+ typedef utils::SharedPtr<TimerInternal> TimerInternalSharedPointer;
+ TimerInternalSharedPointer timer;
+ bool shutDown;
+ int messages_count;
+
+ ConnectionInternal(TransportManagerImpl* transport_manager,
+ TransportAdapter* transport_adapter,
+ const ConnectionUID& id, const DeviceUID& dev_id,
+ const ApplicationHandle& app_id)
+ : transport_manager(transport_manager),
+ transport_adapter(transport_adapter),
+ timer(new TimerInternal(this, &ConnectionInternal::DisconnectFailedRoutine)),
+ shutDown(false),
+ messages_count(0) {
+ Connection::id = id;
+ Connection::device = dev_id;
+ Connection::application = app_id;
+ }
+
+ void DisconnectFailedRoutine() {
+ LOG4CXX_INFO(logger_, "Disconnection failed");
+ transport_manager->RaiseEvent(&TransportManagerListener::OnDisconnectFailed,
+ transport_manager->converter_.UidToHandle(device),
+ DisconnectDeviceError());
+ shutDown = false;
+ timer->stop();
+ }
+
+ };
+ public:
+
+ /**
+ * @brief Destructor.
+ **/
+ virtual ~TransportManagerImpl(void);
+
+ /**
+ * @brief Initialize transport manager.
+ *
+ * @return Code error.
+ */
+ virtual int Init();
+
+ /**
+ * @brief Start scanning for new devices.
+ *
+ * @return Code error.
+ **/
+ virtual int SearchDevices(void);
+
+ /**
+ * @brief Connect to all applications discovered on device.
+ *
+ * @param device_id Handle of device to connect to.
+ *
+ * @return Code error.
+ **/
+ virtual int ConnectDevice(const DeviceHandle& device_id);
+
+ /**
+ * @brief Disconnect from all applications connected on device.
+ *
+ * @param device_id Handle of device to Disconnect from.
+ *
+ * @return Code error.
+ **/
+ virtual int DisconnectDevice(const DeviceHandle& device_id);
+
+ /**
+ * @brief Disconnect from applications connected on device by connection
+ *unique identifier.
+ *
+ * @param connection Connection unique identifier.
+ *
+ * @return Code error.
+ **/
+ virtual int Disconnect(const ConnectionUID& connection_id);
+
+ /**
+ * @brief Disconnect and clear all unreceived data.
+ *
+ * @param connection Connection unique identifier.
+ */
+ virtual int DisconnectForce(const ConnectionUID& connection_id);
+ /**
+ * @brief Post new message in queue for massages destined to device.
+ *
+ * @param message Smart pointer to the raw massage.
+ *
+ * @return Code error.
+ **/
+ virtual int SendMessageToDevice(const RawMessageSptr message);
+
+ /**
+ * @brief Post event in the event queue.
+ *
+ * @param event Current event information.
+ *
+ * @return Code error.
+ **/
+ virtual int ReceiveEventFromDevice(const TransportAdapterEvent& event);
+
+ /**
+ * @brief Post listener to the container of transport manager listeners.
+ *
+ * @param listener Pointer to the transport manager listener.
+ *
+ * @return Code error.
+ **/
+ virtual int AddEventListener(TransportManagerListener* listener);
+
+ virtual int Stop();
+
+ /**
+ * @brief Add device adapter to the container of device adapters.
+ *
+ * @param transport_adapter Smart pointer to the device adapter.
+ *
+ * @return Code error.
+ **/
+ virtual int AddTransportAdapter(
+ transport_adapter::TransportAdapter* transport_adapter);
+
+ /**
+ * @brief Remove device from the container that hold devices.
+ *
+ * @param device Handle of device.
+ *
+ * @return Code error.
+ **/
+ virtual int RemoveDevice(const DeviceHandle& device);
+
+ /**
+ * @brief Turns on or off visibility of SDL to mobile devices
+ * when visibility is ON (on_off = true) mobile devices are able to connect
+ * otherwise ((on_off = false)) SDL is not visible from outside
+ *
+ * @return Code error.
+ */
+ virtual int Visibility(const bool& on_off) const;
+
+ /**
+ * @brief Updates total device list with info from specific transport adapter.
+ * @param ta Transport adapter
+ */
+ void UpdateDeviceList(TransportAdapter* ta);
+
+ /**
+ * @brief Constructor.
+ **/
+ TransportManagerImpl();
+
+ protected:
+
+ template <class Proc, class... Args>
+ void RaiseEvent(Proc proc, Args... args) {
+ for (TransportManagerListenerList::iterator it =
+ transport_manager_listener_.begin();
+ it != transport_manager_listener_.end(); ++it) {
+ ((*it)->*proc)(args...);
+ }
+ }
+
+ /**
+ * @brief Put massage in the container of massages.
+ *
+ * @param message Smart pointer to the raw massage.
+ **/
+ void PostMessage(const RawMessageSptr message);
+
+ /**
+ * @brief update message in queue
+ *
+ * @param message shared pointer to raw massage
+ *
+ * @see @ref components_transportmanager_client_connection_management
+ **/
+ /*not clear when this function shall be used
+ * void updateMessage(const RawMessageSptr old_message, const RawMessageSptr
+ * new_message);*/
+
+ /**
+ * @brief Remove message from the container of massages.
+ *
+ * @param message Smart pointer to the raw massage.
+ **/
+ void RemoveMessage(const RawMessageSptr message);
+
+ /**
+ * @brief Post event to the container of events.
+ *
+ * @param event Event of device adapter.
+ **/
+ void PostEvent(const TransportAdapterEvent& event);
+
+ /**
+ * @brief Type definition of container that holds smart pointer to the raw
+ *massages.
+ **/
+ typedef std::list<RawMessageSptr> MessageQueue;
+
+ /**
+ * @brief Type definition of container that holds events of device adapters.
+ **/
+ typedef std::vector<TransportAdapterEvent> EventQueue;
+
+ static void* MessageQueueStartThread(void* data);
+
+ /**
+ * @brief Scan message's queue and pull messages according to priority and
+ *serial number
+ *
+ * @param
+ *
+ * @see @ref components_transportmanager_client_connection_management
+ */
+ void MessageQueueThread(void);
+
+ /**
+ * @brief Launch EventListenerThread(void).
+ */
+ static void* EventListenerStartThread(void*);
+ /**
+ * @brief wait until event happens
+ *
+ * @param
+ *
+ * @see @ref components_transportmanager_client_connection_management
+ */
+ void EventListenerThread(void);
+
+ /**
+ * \brief For logging.
+ */
+ static log4cxx::LoggerPtr logger_;
+
+ /**
+ * @brief store messages
+ *
+ * @param
+ *
+ * @see @ref components_transportmanager_client_connection_management
+ **/
+ MessageQueue message_queue_;
+
+ /**
+ * @brief Mutex restricting access to messages.
+ **/
+#ifdef USE_RWLOCK
+ mutable pthread_rwlock_t message_queue_rwlock_;
+#endif
+ mutable pthread_mutex_t message_queue_mutex_;
+
+ pthread_cond_t message_queue_cond_;
+
+ /**
+ * @brief store events from comming device
+ *
+ * @param
+ *
+ * @see @ref components_transportmanager_client_connection_management
+ **/
+ EventQueue event_queue_;
+
+ /**
+ * @brief flag that indicates that thread is active
+ * if it is false then threads exist main loop
+ **/
+ volatile bool all_thread_active_;
+
+ typedef std::list<TransportManagerListener*> TransportManagerListenerList;
+ /**
+ * @brief listener that would be called when TM's event happened.
+ **/
+ TransportManagerListenerList transport_manager_listener_;
+
+ /**
+ * @brief ID of message queue processing thread
+ **/
+ pthread_t message_queue_thread_;
+
+ /**
+ * @brief Conditional event thread
+ **/
+ pthread_t event_queue_thread_;
+
+ /**
+ * @brief Condition variable to wake up event
+ **/
+ pthread_cond_t device_listener_thread_wakeup_;
+
+ /**
+ * @brief Mutex restricting access to events.
+ **/
+#ifdef USE_RWLOCK
+ mutable pthread_rwlock_t event_queue_rwlock_;
+#endif
+ mutable pthread_mutex_t event_queue_mutex_;
+
+ /**
+ * @brief Flag that TM is initialized
+ */
+ bool is_initialized_;
+
+ private:
+ /**
+ * @brief Returns size of frame to be formed from raw bytes.
+ * expects first bytes of message which will be treated as frame header.
+ */
+ // TODO this function should be moved outside of TM to protocol handler or
+ // somewhere else
+ unsigned int GetPacketSize(unsigned int size, unsigned char* data);
+
+ /**
+ * @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) {
+ 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)
+ }
+ is_new = true;
+ conversion_table_.push_back(dev_uid);
+ return conversion_table_.size(); // handle begin since 1 (one)
+ }
+
+ DeviceUID HandleToUid(DeviceHandle handle) {
+ if (handle == 0 || handle > conversion_table_.size()) {
+ return DeviceUID();
+ }
+ return conversion_table_[handle - 1]; // handle begin since 1 (one)
+ }
+
+ ConversionTable conversion_table_;
+ };
+
+ /**
+ * @brief Converter variable (Device ID -> Device Handle; Device Handle ->
+ * Device ID)
+ */
+ Handle2GUIDConverter converter_;
+
+ explicit TransportManagerImpl(const TransportManagerImpl&);
+ int connection_id_counter_;
+ std::vector<ConnectionInternal> connections_;
+ std::map<DeviceUID, TransportAdapter*> device_to_adapter_map_;
+ std::vector<TransportAdapter*> transport_adapters_;
+ /** For keep listeners which were add TMImpl */
+ std::map<TransportAdapter*, TransportAdapterListenerImpl*>
+ transport_adapter_listeners_;
+
+ typedef std::vector<std::pair<const TransportAdapter*, DeviceInfo> >
+ DeviceList;
+ DeviceList device_list_;
+
+ class IncomingDataHandler;
+ std::auto_ptr<IncomingDataHandler> incoming_data_handler_;
+
+ void AddConnection(const ConnectionInternal& c);
+ void RemoveConnection(int id);
+ ConnectionInternal* GetConnection(const ConnectionUID& id);
+ ConnectionInternal* GetConnection(const DeviceUID& device,
+ const ApplicationHandle& application);
+
+ void AddDataToContainer(
+ ConnectionUID id,
+ std::map<ConnectionUID, std::pair<unsigned int, unsigned char*> >&
+ container,
+ unsigned char* data, unsigned int data_size);
+ bool GetFrameSize(unsigned char* data, unsigned int data_size,
+ unsigned int& frame_size);
+ bool GetFrame(std::map<ConnectionUID,
+ std::pair<unsigned int, unsigned char*> >& container,
+ ConnectionUID id, unsigned int frame_size,
+ unsigned char** frame);
+
+ void OnDeviceListUpdated(TransportAdapter* ta);
+ static Connection convert(ConnectionInternal& p);
+};
+// class ;
+
+} // namespace transport_manager
+
+#endif