summaryrefslogtreecommitdiff
path: root/src/components/connection_handler
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/connection_handler')
-rw-r--r--src/components/connection_handler/CMakeLists.txt23
-rw-r--r--src/components/connection_handler/include/connection_handler/connection.h298
-rw-r--r--src/components/connection_handler/include/connection_handler/connection_handler.h151
-rw-r--r--src/components/connection_handler/include/connection_handler/connection_handler_impl.h423
-rw-r--r--src/components/connection_handler/include/connection_handler/connection_handler_observer.h108
-rw-r--r--src/components/connection_handler/include/connection_handler/device.h115
-rw-r--r--src/components/connection_handler/include/connection_handler/devices_discovery_starter.h72
-rw-r--r--src/components/connection_handler/include/connection_handler/heartbeat_monitor.h114
-rw-r--r--src/components/connection_handler/src/connection.cc360
-rw-r--r--src/components/connection_handler/src/connection_handler_impl.cc863
-rw-r--r--src/components/connection_handler/src/device.cc74
-rw-r--r--src/components/connection_handler/src/heartbeat_monitor.cc169
12 files changed, 2770 insertions, 0 deletions
diff --git a/src/components/connection_handler/CMakeLists.txt b/src/components/connection_handler/CMakeLists.txt
new file mode 100644
index 0000000000..18946ac349
--- /dev/null
+++ b/src/components/connection_handler/CMakeLists.txt
@@ -0,0 +1,23 @@
+include_directories (
+ ./include/
+ ../protocol_handler/include/
+ ../config_profile/include/
+ ../utils/include/
+ ${ENCRYPTION_INCLUDE_DIRECTORY}
+ ${LOG4CXX_INCLUDE_DIRECTORY}
+)
+
+set (SOURCES
+ ./src/connection_handler_impl.cc
+ ./src/connection.cc
+ ./src/device.cc
+ ./src/heartbeat_monitor.cc
+)
+
+set(LIBRARIES
+ ConfigProfile
+ ProtocolLibrary
+)
+
+add_library(connectionHandler ${SOURCES})
+target_link_libraries(connectionHandler encryption)
diff --git a/src/components/connection_handler/include/connection_handler/connection.h b/src/components/connection_handler/include/connection_handler/connection.h
new file mode 100644
index 0000000000..6bcbc3fdcd
--- /dev/null
+++ b/src/components/connection_handler/include/connection_handler/connection.h
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2014, 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_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_CONNECTION_H_
+#define SRC_COMPONENTS_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_CONNECTION_H_
+
+#include <map>
+#include <vector>
+
+#include "utils/lock.h"
+#include "connection_handler/device.h"
+#include "connection_handler/heartbeat_monitor.h"
+#include "protocol/service_type.h"
+
+#ifdef ENABLE_SECURITY
+namespace security_manager {
+class SSLContext;
+} // namespace security_manager
+#endif // ENABLE_SECURITY
+
+/**
+ * \namespace connection_handler
+ * \brief SmartDeviceLink connection_handler namespace.
+ */
+namespace connection_handler {
+
+class ConnectionHandler;
+
+/**
+ * \brief Type for ConnectionHandle
+ */
+typedef int32_t ConnectionHandle;
+
+/**
+ * \brief Type for Connections map
+ * Key is ConnectionHandle which is unique
+ */
+typedef std::map<int32_t, Connection*> ConnectionList;
+
+/**
+ * \brief ServiceType
+ */
+struct Service {
+ protocol_handler::ServiceType service_type;
+ bool is_protected_;
+ Service()
+ : service_type(protocol_handler::kInvalidServiceType),
+ is_protected_(false) {
+ }
+ explicit Service(protocol_handler::ServiceType service_type)
+ : service_type(service_type),
+ is_protected_(false) {
+ }
+ bool operator==(const protocol_handler::ServiceType service_type) const {
+ return this->service_type == service_type;
+ }
+};
+
+/**
+ * \brief Type for Session Services
+ */
+typedef std::vector<Service> ServiceList;
+
+struct Session {
+ ServiceList service_list;
+ uint8_t protocol_version;
+#ifdef ENABLE_SECURITY
+ security_manager::SSLContext *ssl_context;
+#endif // ENABLE_SECURITY
+ Session()
+ : service_list()
+#ifdef ENABLE_SECURITY
+ , ssl_context(NULL)
+#endif // ENABLE_SECURITY
+ {}
+ explicit Session(const ServiceList &services, uint8_t protocol_version)
+ : service_list(services),
+ protocol_version(protocol_version)
+#ifdef ENABLE_SECURITY
+ , ssl_context(NULL)
+#endif // ENABLE_SECURITY
+ {}
+ Service *FindService(const protocol_handler::ServiceType &service_type);
+ const Service *FindService(const protocol_handler::ServiceType &service_type) const;
+};
+
+/**
+ * \brief Type for Session map
+ */
+typedef std::map<uint8_t, Session> SessionMap;
+
+/**
+ * \class Connection
+ * \brief Stores connection information
+ */
+class Connection {
+ public:
+ /**
+ * \brief Class constructor
+ */
+ Connection(ConnectionHandle connection_handle,
+ DeviceHandle connection_device_handle,
+ ConnectionHandler *connection_handler,
+ int32_t heartbeat_timeout);
+
+ /**
+ * \brief Destructor
+ */
+ ~Connection();
+
+ /**
+ * \brief Returns device handle
+ * \return DeviceHandle
+ */
+ ConnectionHandle connection_handle() const;
+
+ /**
+ * \brief Returns connection device handle
+ * \return ConnectionDeviceHandle
+ */
+ DeviceHandle connection_device_handle();
+
+ /**
+ * \brief Adds session to connection
+ * \return new session id or 0 in case of issues
+ */
+ uint32_t AddNewSession();
+
+ /**
+ * \brief Removes session from connection
+ * \param session session ID
+ * \return session_id or 0 in case of issues
+ */
+ uint32_t RemoveSession(uint8_t session_id);
+
+ /**
+ * \brief Adds uprotected service to session or
+ * check protection to service has been started before
+ * \param session_id session ID
+ * \param service_type Type of service
+ * \param is_protected protection state
+ * \return TRUE on success, otherwise FALSE
+ */
+ bool AddNewService(uint8_t session_id,
+ protocol_handler::ServiceType service_type,
+ const bool is_protected);
+ /**
+ * \brief Removes service from session
+ * \param session_id session ID
+ * \param service_type Type of service
+ * \return TRUE on success, otherwise FALSE
+ */
+ bool RemoveService(uint8_t session_id,
+ protocol_handler::ServiceType service_type);
+#ifdef ENABLE_SECURITY
+ /**
+ * \brief Sets crypto context of service
+ * \param session_id Identifier of the session
+ * \param context SSL for connection
+ * \return \c true in case of service is protected or \c false otherwise
+ */
+ int SetSSLContext(uint8_t session_id,
+ security_manager::SSLContext *context);
+ /**
+ * \brief Gets crypto context of session, use service_type to get NULL
+ * SSLContext for not protected services or ControlService (0x0)
+ * to get current SSLContext of connection
+ * \param session_id Identifier of the session
+ * \param service_type Type of service
+ * \return \ref SSLContext of connection
+ */
+ security_manager::SSLContext *GetSSLContext(
+ const uint8_t session_id,
+ const protocol_handler::ServiceType &service_type) const;
+ /**
+ * \brief Set protection flag to service in session by key
+ * to get current SSLContext of connection
+ * \param session_id Identifier of the session
+ * \param service_type Type of service
+ */
+ void SetProtectionFlag(
+ const uint8_t session_id,
+ const protocol_handler::ServiceType &service_type);
+#endif // ENABLE_SECURITY
+ /**
+ * \brief Returns map of sessions which have been opened in
+ * current connection.
+ */
+ const SessionMap session_map() const;
+
+ /**
+ * \brief Close session
+ * \param session_id session id
+ */
+ void CloseSession(uint8_t session_id);
+
+ /**
+ * \brief Prevent session from being closed by heartbeat timeout
+ * \param session_id session id
+ */
+ void KeepAlive(uint8_t session_id);
+
+ /**
+ * \brief Start heartbeat for specified session
+ * \param session_id session id
+ */
+ void StartHeartBeat(uint8_t session_id);
+
+ /**
+ * \brief Send heartbeat to mobile app
+ * \param session_id session id
+ */
+ void SendHeartBeat(uint8_t session_id);
+
+ /**
+ * Sets heart beat timeout
+ * @param timeout in seconds
+ */
+ void SetHeartBeatTimeout(int32_t timeout);
+
+ /**
+ * \brief changes protocol version in session
+ * \param session_id session id
+ * \param protocol_version protocol version registered application
+ */
+ void UpdateProtocolVersionSession(uint8_t session_id, uint8_t protocol_version);
+
+ /**
+ * \brief checks if session supports heartbeat
+ * \param session_id session id
+ * \return TRUE on success, otherwise FALSE
+ */
+ bool SupportHeartBeat(uint8_t session_id);
+
+
+ private:
+ /**
+ * \brief Current connection handler.
+ */
+ ConnectionHandler *connection_handler_;
+
+ /**
+ * \brief Current connection handle.
+ */
+ ConnectionHandle connection_handle_;
+
+ /**
+ * \brief DeviceHandle of this connection.
+ */
+ DeviceHandle connection_device_handle_;
+
+ /**
+ * \brief session/services map
+ */
+ SessionMap session_map_;
+
+ mutable sync_primitives::Lock session_map_lock_;
+
+ /**
+ * \brief monitor that closes connection if there is no traffic over it
+ */
+ HeartBeatMonitor *heartbeat_monitor_;
+ threads::Thread *heart_beat_monitor_thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(Connection);
+};
+
+} // namespace connection_handler
+#endif // SRC_COMPONENTS_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_CONNECTION_H_
diff --git a/src/components/connection_handler/include/connection_handler/connection_handler.h b/src/components/connection_handler/include/connection_handler/connection_handler.h
new file mode 100644
index 0000000000..08bef97155
--- /dev/null
+++ b/src/components/connection_handler/include/connection_handler/connection_handler.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2014, 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_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_CONNECTION_HANDLER_H_
+#define SRC_COMPONENTS_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_CONNECTION_HANDLER_H_
+
+#include "transport_manager/transport_manager_listener.h"
+#include "protocol_handler/session_observer.h"
+#include "connection_handler/connection_handler_observer.h"
+#include "connection_handler/device.h"
+#include "connection_handler/connection.h"
+#include "connection_handler/devices_discovery_starter.h"
+
+/**
+ * \namespace connection_handler
+ * \brief SmartDeviceLink connection_handler namespace.
+ */
+namespace connection_handler {
+/**
+ * \class ConnectionHandler
+ * \brief SmartDeviceLink ConnectionHandler interface class
+ */
+class ConnectionHandler {
+ public:
+ /**
+ * \brief Sets observer pointer for ConnectionHandler.
+ * \param observer Pointer to observer object.
+ **/
+ virtual void set_connection_handler_observer(
+ ConnectionHandlerObserver *observer) = 0;
+
+ /**
+ * \brief Sets pointer to TransportManager.
+ * \param transportManager Pointer to TransportManager object.
+ **/
+ virtual void set_transport_manager(
+ transport_manager::TransportManager *transport_manager) = 0;
+
+ virtual void StartTransportManager() = 0;
+
+ virtual void ConnectToDevice(
+ connection_handler::DeviceHandle device_handle) = 0;
+
+ virtual void ConnectToAllDevices() = 0;
+
+ /**
+ * @brief Close the connection revoked by Policy
+ * @param connection_key pair of connection and session id
+ */
+ virtual void CloseRevokedConnection(uint32_t connection_key) = 0;
+
+ /**
+ * \brief Close all associated sessions and close the connection pointed by handle
+ */
+ virtual void CloseConnection(ConnectionHandle connection_handle) = 0;
+
+ /**
+ * \brief Return count of session for specified connection
+ * \param connection_key pair of connection handle and session id
+ */
+ virtual uint32_t GetConnectionSessionsCount(uint32_t connection_key) = 0;
+
+ /**
+ * Gets device id by mac address
+ * @param mac_address
+ * @return true if successfully
+ */
+ virtual bool GetDeviceID(const std::string &mac_address,
+ DeviceHandle *device_handle) = 0;
+
+ /**
+ * Close session associated with the key
+ */
+ virtual void CloseSession(uint32_t key) = 0;
+
+ /**
+ * Close session
+ */
+ virtual void CloseSession(ConnectionHandle connection_handle,
+ uint8_t session_id) = 0;
+
+ /**
+ * \brief Start heartbeat for specified session
+ *
+ * \param connection_key pair of connection and session id
+ */
+ virtual void StartSessionHeartBeat(uint32_t connection_key) = 0;
+
+ /**
+ * \brief Send heartbeat to mobile app
+ */
+ virtual void SendHeartBeat(ConnectionHandle connection_handle,
+ uint8_t session_id) = 0;
+
+ /**
+ * Sets heart beat timeout for specified session
+ * @param connection_key pair of connection and session id
+ * @param timeout in seconds
+ */
+ virtual void SetHeartBeatTimeout(uint32_t connection_key,
+ int32_t timeout) = 0;
+
+ /**
+ * \brief binds protocol version with session
+ *
+ * \param connection_key pair of connection and session id
+ * \param protocol_version contains protocol version of
+ * \registered application.
+ */
+ virtual void BindProtocolVersionWithSession(uint32_t connection_key,
+ uint8_t protocol_version) = 0;
+
+ protected:
+ /**
+ * \brief Destructor
+ */
+ virtual ~ConnectionHandler() {
+ }
+};
+} // namespace connection_handler
+
+#endif // SRC_COMPONENTS_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_CONNECTION_HANDLER_H_
diff --git a/src/components/connection_handler/include/connection_handler/connection_handler_impl.h b/src/components/connection_handler/include/connection_handler/connection_handler_impl.h
new file mode 100644
index 0000000000..00ebdf0ab5
--- /dev/null
+++ b/src/components/connection_handler/include/connection_handler/connection_handler_impl.h
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2014, 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_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_CONNECTION_HANDLER_IMPL_H_
+#define SRC_COMPONENTS_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_CONNECTION_HANDLER_IMPL_H_
+
+#include <map>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "transport_manager/transport_manager_listener_empty.h"
+#include "protocol_handler/session_observer.h"
+#include "protocol_handler/protocol_handler.h"
+#include "connection_handler/connection_handler_observer.h"
+#include "connection_handler/device.h"
+#include "connection_handler/connection.h"
+#include "connection_handler/devices_discovery_starter.h"
+#include "connection_handler/connection_handler.h"
+#include "utils/logger.h"
+#include "utils/macro.h"
+#include "utils/lock.h"
+#include "utils/stl_utils.h"
+#include "utils/singleton.h"
+
+/**
+ * \namespace connection_handler
+ * \brief SmartDeviceLink connection_handler namespace.
+ */
+namespace connection_handler {
+/**
+ * \class ConnectionHandlerImpl
+ * \brief SmartDeviceLink connection_handler main class
+ * Observes TransportManager and ProtocolHandler,
+ * stores information regarding connections
+ * and sessions and provides it to AppManager.
+ */
+class ConnectionHandlerImpl : public ConnectionHandler,
+ public transport_manager::TransportManagerListenerEmpty,
+ public protocol_handler::SessionObserver,
+ public DevicesDiscoveryStarter,
+ public utils::Singleton<ConnectionHandlerImpl> {
+ public:
+ /**
+ * \brief Destructor
+ */
+ virtual ~ConnectionHandlerImpl();
+
+ void Stop();
+ /**
+ * \brief Sets observer pointer for connection_handler.
+ * \param observer Pointer to observer object.
+ */
+ virtual void set_connection_handler_observer(
+ ConnectionHandlerObserver *observer);
+
+ /**
+ * \brief Sets pointer to TransportManager.
+ * \param transport_mngr Pointer to TransportManager object.
+ **/
+ virtual void set_transport_manager(
+ transport_manager::TransportManager *transport_mngr);
+
+ /**
+ * \brief Sets pointer to ProtocolHandler.
+ * \param protocol_handler Pointer to ProtocolHandler object.
+ **/
+ void set_protocol_handler(
+ protocol_handler::ProtocolHandler *protocol_handler);
+
+ /**
+ * \brief Connects to all services of device
+ * \param deviceHandle Handle of device to connect to
+ */
+ virtual void ConnectToDevice(connection_handler::DeviceHandle device_handle);
+
+ virtual void ConnectToAllDevices();
+
+ virtual void StartTransportManager();
+
+ virtual void OnDeviceListUpdated(
+ const std::vector<transport_manager::DeviceInfo> &);
+
+ virtual void OnFindNewApplicationsRequest();
+
+ /**
+ * \brief Available devices list updated.
+ *
+ * Called when device scanning initiated with scanForNewDevices
+ * is completed or devices connected via background procedures.
+ *
+ * \param DeviceList New list of available devices.
+ **/
+ virtual void OnDeviceFound(const transport_manager::DeviceInfo &device_info);
+ virtual void OnDeviceAdded(const transport_manager::DeviceInfo &device_info);
+ virtual void OnDeviceRemoved(const transport_manager::DeviceInfo &device_info);
+
+ virtual void OnScanDevicesFinished();
+ virtual void OnScanDevicesFailed(
+ const transport_manager::SearchDeviceError &error);
+
+ /**
+ * \brief Notifies about established connection.
+ *
+ * \param connection_id ID of new connection.
+ **/
+ virtual void OnConnectionEstablished(
+ const transport_manager::DeviceInfo &device_info,
+ const transport_manager::ConnectionUID &connection_id);
+ virtual void OnConnectionFailed(
+ const transport_manager::DeviceInfo &device_info,
+ const transport_manager::ConnectError &error);
+ virtual void OnConnectionClosed(
+ transport_manager::ConnectionUID connection_id);
+ virtual void OnConnectionClosedFailure(
+ transport_manager::ConnectionUID connection_id,
+ const transport_manager::DisconnectError &error);
+ virtual void OnUnexpectedDisconnect(
+ transport_manager::ConnectionUID connection_id,
+ const transport_manager::CommunicationError &error);
+ virtual void OnDeviceConnectionLost(
+ const connection_handler::DeviceHandle &device,
+ const transport_manager::DisconnectDeviceError &error);
+ /**
+ * \brief Informs about failure during DisconnectDevice procedure of TM
+ * \param device Information about disconnected device
+ * \param error Information about possible reason of loosing connection
+ */
+ virtual void OnDisconnectFailed(
+ const connection_handler::DeviceHandle &device,
+ const transport_manager::DisconnectDeviceError &error);
+
+ /**
+ * \brief Callback function used by ProtocolHandler
+ * when Mobile Application initiates start of new session.
+ * \param connection_handle Connection identifier within which session has to be started.
+ * \param session_id Identifier of the session to be started
+ * \param service_type Type of service
+ * \param is_protected would be service protected
+ * \param hash_id pointer for session hash identifier
+ * \return uint32_t Id (number) of new session if successful, otherwise 0.
+ */
+ virtual uint32_t OnSessionStartedCallback(const transport_manager::ConnectionUID &connection_handle,
+ const uint8_t session_id,
+ const protocol_handler::ServiceType &service_type,
+ const bool is_protected, uint32_t* hash_id);
+
+ /**
+ * \brief Callback function used by ProtocolHandler
+ * when Mobile Application initiates session ending.
+ * \param connection_handle Connection identifier within which session exists
+ * \param sessionId Identifier of the session to be ended
+ * \param hashCode Hash used only in second version of SmartDeviceLink protocol.
+ * If not equal to hash assigned to session on start then operation fails.
+ * \return uint32_t 0 if operation fails, session key otherwise
+ */
+ virtual uint32_t OnSessionEndedCallback(
+ const transport_manager::ConnectionUID &connection_handle,
+ const uint8_t session_id, const uint32_t &hashCode,
+ const protocol_handler::ServiceType &service_type);
+
+ /**
+ * \brief Creates unique identifier of session (can be used as hash)
+ * from given connection identifier
+ * within which session exists and session number.
+ * \param connection_handle Connection identifier within which session exists
+ * \param sessionId Identifier of the session
+ * \return int32_t Unique key for session
+ */
+ virtual uint32_t KeyFromPair(
+ transport_manager::ConnectionUID connection_handle,
+ uint8_t session_id);
+
+ /**
+ * \brief Returns connection identifier and session number from given session key
+ * \param key Unique key used by other components as session identifier
+ * \param connection_handle Returned: Connection identifier within which session exists
+ * \param sessionId Returned: Number of session
+ */
+ virtual void PairFromKey(uint32_t key,
+ transport_manager::ConnectionUID *connection_handle,
+ uint8_t *session_id);
+
+ /**
+ * \brief information about given Connection Key.
+ * \param key Unique key used by other components as session identifier
+ * \param app_id Returned: ApplicationID
+ * \param sessions_list Returned: List of session keys
+ * \param device_id Returned: DeviceID
+ * \return int32_t -1 in case of error or 0 in case of success
+ */
+ virtual int32_t GetDataOnSessionKey(uint32_t key, uint32_t *app_id = 0,
+ std::list<int32_t> *sessions_list = NULL,
+ uint32_t *device_id = 0);
+
+ /**
+ * \brief information about device
+ * \param device_handle
+ * \param device_name Returned: name of device
+ * \param applications_list Returned: applications on device
+ * \param mac_address Returned: List of session keys
+ * \param connection_type Returned: type of connection (USB, BT, etc.)
+ * \return int32_t -1 in case of error or 0 in case of success
+ */
+ virtual int32_t GetDataOnDeviceID(connection_handler::DeviceHandle device_handle,
+ std::string *device_name = NULL,
+ std::list<uint32_t> *applications_list = NULL,
+ std::string *mac_address = NULL,
+ std::string* connection_type = NULL);
+#ifdef ENABLE_SECURITY
+ /**
+ * \brief Sets crypto context of connection
+ * \param key Unique key used by other components as session identifier
+ * \param context SSLContext to be set
+ * \return \c SecurityQuery::ProtectSessionResult value
+ */
+ int SetSSLContext(
+ const uint32_t &key,
+ security_manager::SSLContext *context) OVERRIDE;
+
+ /**
+ * \brief Gets crypto context of connection, use service_type to get NULL
+ * SSLContext for not protected services or ControlService (0x0)
+ * to get current SSLContext of connection
+ * \param key Unique key used by other components as session identifier
+ * \param service_type Type of service
+ * \return \ref SSLContext of connection
+ */
+ security_manager::SSLContext *GetSSLContext(
+ const uint32_t &key,
+ const protocol_handler::ServiceType &service_type) OVERRIDE;
+ /**
+ * \brief Set protection flag to service in session by key
+ * \param key Unique key used by other components as session identifier
+ * \param service_type Type of service
+ */
+ void SetProtectionFlag(
+ const uint32_t &key,
+ const protocol_handler::ServiceType &service_type) OVERRIDE;
+#endif // ENABLE_SECURITY
+
+ /**
+ * \brief Get device handle by mac address
+ * \param mac_address uniq address
+ * \param device_handle
+ * \return true on sucess otherwise false.
+ */
+ virtual bool GetDeviceID(const std::string &mac_address,
+ DeviceHandle *device_handle);
+
+ /**
+ * \brief Method which should start devices discovering
+ */
+ virtual void StartDevicesDiscovery();
+
+ /**
+ * @brief Close the connection revoked by Policy
+ * @param connection_key pair of connection and session id
+ */
+ virtual void CloseRevokedConnection(uint32_t connection_key);
+
+ /**
+ * @brief Close the connection pointed by handle
+ * @param connection_handle Connection unique id
+ */
+ virtual void CloseConnection(ConnectionHandle connection_handle) OVERRIDE;
+
+ /**
+ * \brief Close session associated with the key
+ * \param key Unique key used by other components as session identifier
+ */
+ virtual void CloseSession(uint32_t key);
+
+ /**
+ * \brief Function used by HearbeatMonitior to close session on HB timeout
+ * \param connection_handle Connection handler within which session exists
+ * \param session_id Identifier of the session to be ended
+ */
+ virtual void CloseSession(ConnectionHandle connection_handle,
+ uint8_t session_id);
+
+ /**
+ * \brief Return count of session for specified connection
+ * \param connection_key pair of connection handle and session id
+ */
+ virtual uint32_t GetConnectionSessionsCount(uint32_t connection_key);
+
+ /**
+ * \brief Send heartbeat message to mobile app
+ */
+ virtual void SendHeartBeat(ConnectionHandle connection_handle,
+ uint8_t session_id);
+
+ /**
+ * \brief Start heartbeat for specified session
+ *
+ * \param connection_key pair of connection and session id
+ */
+ virtual void StartSessionHeartBeat(uint32_t connection_key);
+
+ /**
+ * Sets heart beat timeout for specified session
+ * @param connection_key pair of connection and session id
+ * @param timeout in seconds
+ */
+ virtual void SetHeartBeatTimeout(uint32_t connection_key, int32_t timeout);
+
+ /**
+ * \brief Keep connection associated with the key from being closed by heartbeat monitor
+ */
+ void KeepConnectionAlive(uint32_t connection_key, uint8_t session_id);
+
+ /**
+ * \brief binds protocol version with session
+ *
+ * \param connection_key pair of connection and session id
+ * \param protocol_version contains protocol version of
+ * \registered application.
+ */
+ virtual void BindProtocolVersionWithSession(uint32_t connection_key,
+ uint8_t protocol_version);
+
+ /**
+ * \brief returns TRUE if session supports sending HEART BEAT ACK to mobile side
+ * \param connection_handle Connection identifier whithin which session exists
+ * \param sessionId Identifier of the session
+ * \return TRUE if session has protocol version which supports heartbeat otherwise returns FALSE
+ */
+ virtual bool IsHeartBeatSupported(
+ transport_manager::ConnectionUID connection_handle,
+ uint8_t session_id);
+ private:
+ /**
+ * \brief Default class constructor
+ */
+ ConnectionHandlerImpl();
+
+ /**
+ * \brief Disconnect application.
+ *
+ * \param device_handle DeviceHandle of disconnected device.
+ * \param connection_handle Connection handle.
+ **/
+ void RemoveConnection(const ConnectionHandle connection_handle);
+
+ void OnConnectionEnded(
+ const transport_manager::ConnectionUID &connection_id);
+
+ /**
+ * \brief Pointer to observer
+ */
+ ConnectionHandlerObserver *connection_handler_observer_;
+
+ /**
+ * \brief Pointer to TransportManager
+ */
+ transport_manager::TransportManager *transport_manager_;
+
+ protocol_handler::ProtocolHandler *protocol_handler_;
+
+ /**
+ * \brief List of devices
+ */
+ DeviceMap device_list_;
+
+ /**
+ * \brief List of connections
+ */
+ ConnectionList connection_list_;
+
+ /**
+ * \brief Lock for applications list
+ */
+ mutable sync_primitives::Lock connection_list_lock_;
+
+ /**
+ * \brief Cleans connection list on destruction
+ */
+ utils::StlMapDeleter<ConnectionList> connection_list_deleter_;
+
+#ifdef BUILD_TESTS
+ // Methods for test usage
+ public:
+ ConnectionList &getConnectionList();
+ void addDeviceConnection(
+ const transport_manager::DeviceInfo &device_info,
+ const transport_manager::ConnectionUID &connection_id);
+#endif
+ private:
+ FRIEND_BASE_SINGLETON_CLASS(ConnectionHandlerImpl);
+ DISALLOW_COPY_AND_ASSIGN(ConnectionHandlerImpl);
+};
+} // namespace connection_handler
+#endif // SRC_COMPONENTS_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_CONNECTION_HANDLER_IMPL_H_
diff --git a/src/components/connection_handler/include/connection_handler/connection_handler_observer.h b/src/components/connection_handler/include/connection_handler/connection_handler_observer.h
new file mode 100644
index 0000000000..cd419c124a
--- /dev/null
+++ b/src/components/connection_handler/include/connection_handler/connection_handler_observer.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, 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_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_CONNECTION_HANDLER_OBSERVER_H_
+#define SRC_COMPONENTS_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_CONNECTION_HANDLER_OBSERVER_H_
+
+#include "connection_handler/device.h"
+#include "connection_handler/connection.h"
+#include "protocol/service_type.h"
+
+/**
+ * \namespace connection_handler
+ * \brief SmartDeviceLink connection_handler namespace.
+ */
+namespace connection_handler {
+
+/**
+ * \class ConnectionHandlerObserver
+ * \brief ConnectionHandlerObserver class
+ */
+class ConnectionHandlerObserver {
+ public:
+ /**
+ * \brief Available devices list updated.
+ *
+ * Called when device scanning initiated with scanForNewDevices
+ * is completed.
+ *
+ * \param DeviceList New list of available devices.
+ **/
+ virtual void OnDeviceListUpdated(
+ const connection_handler::DeviceMap &device_list) = 0;
+
+ /**
+ * @brief Reaction to "Find new applications" request
+ */
+ virtual void OnFindNewApplicationsRequest() = 0;
+
+ /**
+ * \brief Removes device.
+ *
+ * Called when device has been removed from a list.
+ *
+ * \param DeviceHandle Handle of removed device.
+ **/
+ virtual void RemoveDevice(
+ const connection_handler::DeviceHandle &device_handle) = 0;
+
+ /**
+ * \brief Callback function used by connection_handler
+ * when Mobile Application initiates start of new service.
+ * \param deviceHandle Device identifier within which session has to be started.
+ * \param sessionKey Key of started session.
+ * \param type Established service type
+ */
+ virtual bool OnServiceStartedCallback(
+ const connection_handler::DeviceHandle &device_handle,
+ const int32_t &session_key,
+ const protocol_handler::ServiceType &type) = 0;
+
+ /**
+ * \brief Callback function used by connection_handler
+ * when Mobile Application initiates service ending.
+ * \param sessionKey Key of session which should be ended
+ */
+ virtual void OnServiceEndedCallback(
+ const int32_t &session_key,
+ const protocol_handler::ServiceType &type) = 0;
+
+ protected:
+ /**
+ * \brief Destructor
+ */
+ virtual ~ConnectionHandlerObserver() {
+ }
+};
+} // namespace connection_handler
+
+#endif // SRC_COMPONENTS_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_CONNECTION_HANDLER_OBSERVER_H_
diff --git a/src/components/connection_handler/include/connection_handler/device.h b/src/components/connection_handler/include/connection_handler/device.h
new file mode 100644
index 0000000000..c37c4cc62c
--- /dev/null
+++ b/src/components/connection_handler/include/connection_handler/device.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2014, 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_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_DEVICE_H_
+#define SRC_COMPONENTS_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_DEVICE_H_
+
+#include <string>
+#include <map>
+#include <vector>
+
+/**
+ * \namespace connection_handler
+ * \brief SmartDeviceLink connection_handler namespace.
+ */
+namespace connection_handler {
+
+/**
+ * \brief Type for DeviceHandle
+ */
+typedef uint32_t DeviceHandle;
+typedef std::vector<int32_t> AppList;
+
+/**
+ * \class Device
+ * \brief Connection class
+ */
+class Device {
+ public:
+ /**
+ * \brief Class constructor
+ */
+ Device(DeviceHandle device_handle, const std::string &user_friendly_name,
+ const std::string &mac_address = "", const std::string& connection_type = "");
+
+ /**
+ * \brief Returns device handle
+ * \return DeviceHandle
+ */
+ DeviceHandle device_handle() const;
+
+ /**
+ * \brief Returns user frendly device name
+ * \return UserFriendlyName
+ */
+ std::string user_friendly_name() const;
+
+ /**
+ *\brief Also should be used for iOS USB connections
+ *(better not know why this same method)
+ */
+ std::string mac_address() const;
+
+ /**
+ * @brief The type of connection used by device.
+ * @return connection type (USB_serial, BTMAC, etc.)
+ */
+ std::string connection_type() const;
+
+ private:
+ /**
+ * \brief Uniq device handle.
+ */
+ DeviceHandle device_handle_;
+
+ /**
+ * \brief User-friendly device name.
+ */
+ std::string user_friendly_name_;
+
+ /**
+ * \brief Mac address of device if available
+ */
+ std::string mac_address_;
+
+ /**
+ * \brief The type of connection used by device.
+ */
+ std::string connection_type_;
+};
+
+/**
+ * \brief Type for Devices map
+ */
+typedef std::map<int32_t, Device> DeviceMap;
+} // namespace connection_handler
+#endif // SRC_COMPONENTS_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_DEVICE_H_
diff --git a/src/components/connection_handler/include/connection_handler/devices_discovery_starter.h b/src/components/connection_handler/include/connection_handler/devices_discovery_starter.h
new file mode 100644
index 0000000000..bd5885a273
--- /dev/null
+++ b/src/components/connection_handler/include/connection_handler/devices_discovery_starter.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, 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_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_DEVICES_DISCOVERY_STARTER_H_
+#define SRC_COMPONENTS_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_DEVICES_DISCOVERY_STARTER_H_
+
+#include "connection_handler/device.h"
+
+/**
+ * \namespace connection_handler
+ * \brief SmartDeviceLink connection_handler namespace.
+ */
+namespace connection_handler {
+/**
+ * \class DevicesDiscoveryStarter
+ * \brief Starter of devices discovering process class
+ */
+class DevicesDiscoveryStarter {
+ public:
+ /**
+ * \brief Method which should start devices discoveryng
+ */
+ virtual void StartDevicesDiscovery()=0;
+
+ /**
+ * \brief Connects to all services of device
+ * \param deviceHandle Handle of device to connect to
+ */
+ virtual void ConnectToDevice(
+ connection_handler::DeviceHandle device_handle) = 0;
+
+ virtual void StartTransportManager() = 0;
+
+ protected:
+ /**
+ * \brief Destructor
+ */
+ virtual ~DevicesDiscoveryStarter() {
+ }
+};
+} // namespace connection_handler
+
+#endif // SRC_COMPONENTS_CONNECTION_HANDLER_INCLUDE_CONNECTION_HANDLER_DEVICES_DISCOVERY_STARTER_H_
diff --git a/src/components/connection_handler/include/connection_handler/heartbeat_monitor.h b/src/components/connection_handler/include/connection_handler/heartbeat_monitor.h
new file mode 100644
index 0000000000..9b641ce01c
--- /dev/null
+++ b/src/components/connection_handler/include/connection_handler/heartbeat_monitor.h
@@ -0,0 +1,114 @@
+/*
+ * 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_CONNECTION_HANDLER_INCLUDE_HEARTBEAT_MONITOR_H_
+#define SRC_COMPONENTS_CONNECTION_HANDLER_INCLUDE_HEARTBEAT_MONITOR_H_
+
+#include <stdint.h>
+#include <map>
+
+#include "utils/threads/thread.h"
+#include "utils/threads/thread_delegate.h"
+#include "utils/date_time.h"
+#include "utils/macro.h"
+#include "utils/lock.h"
+
+namespace connection_handler {
+
+class Connection;
+
+/*
+ * Starts hearbeat timer for session and when it elapses closes it
+ */
+class HeartBeatMonitor: public threads::ThreadDelegate {
+ public:
+ HeartBeatMonitor(int32_t heartbeat_timeout_seconds,
+ Connection *connection);
+
+ /**
+ * Thread procedure.
+ */
+ virtual void threadMain();
+
+ /**
+ * \brief add and remove session
+ */
+ void AddSession(uint8_t session_id);
+ void RemoveSession(uint8_t session_id);
+
+ /**
+ * \brief Resets timer preventing session from being killed
+ */
+ void KeepAlive(uint8_t session_id);
+
+ /**
+ * \brief Thread exit procedure.
+ */
+ virtual bool exitThreadMain();
+
+ void set_heartbeat_timeout_seconds(int32_t timeout);
+
+ private:
+ struct SessionState;
+ typedef std::map<uint8_t, SessionState> SessionMap;
+
+ // \brief Heartbeat timeout, should be read from profile
+ int32_t heartbeat_timeout_seconds_;
+ // \brief Connection that must be closed when timeout elapsed
+ Connection *connection_;
+
+ static const int32_t kDefaultCycleTimeout = 100000;
+
+ struct SessionState {
+ TimevalStruct heartbeat_expiration;
+ bool is_heartbeat_sent;
+ };
+
+ // \brief monitored sessions collection
+
+ SessionMap sessions_;
+
+ sync_primitives::Lock sessions_list_lock_; // recurcive
+ sync_primitives::Lock main_thread_lock_;
+ mutable sync_primitives::Lock heartbeat_timeout_seconds_lock_;
+
+ volatile bool run_;
+
+ void Process();
+ void RefreshExpiration(TimevalStruct* expiration) const;
+ inline bool HasTimeoutElapsed(const TimevalStruct& expiration) const;
+
+ DISALLOW_COPY_AND_ASSIGN(HeartBeatMonitor);
+};
+
+} // namespace connection_handler
+
+#endif // SRC_COMPONENTS_CONNECTION_HANDLER_INCLUDE_HEARTBEAT_MONITOR_H_
diff --git a/src/components/connection_handler/src/connection.cc b/src/components/connection_handler/src/connection.cc
new file mode 100644
index 0000000000..bd8b478ba5
--- /dev/null
+++ b/src/components/connection_handler/src/connection.cc
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include <limits.h>
+
+#include <algorithm>
+
+#include "connection_handler/connection.h"
+#include "connection_handler/connection_handler.h"
+#include "protocol_handler/protocol_packet.h"
+#include "utils/logger.h"
+#include "utils/macro.h"
+
+#ifdef ENABLE_SECURITY
+#include "security_manager/ssl_context.h"
+#include "security_manager/security_manager.h"
+#endif // ENABLE_SECURITY
+
+/**
+ * \namespace connection_handler
+ * \brief SmartDeviceLink ConnectionHandler namespace.
+ */
+namespace connection_handler {
+
+CREATE_LOGGERPTR_GLOBAL(logger_, "ConnectionHandler")
+
+Service *Session::FindService(const protocol_handler::ServiceType &service_type) {
+ ServiceList::iterator service_it =
+ std::find(service_list.begin(), service_list.end(), service_type);
+ if(service_it != service_list.end()){
+ return &(*service_it);
+ }
+ return NULL;
+}
+
+const Service *Session::FindService(const protocol_handler::ServiceType &service_type) const {
+ ServiceList::const_iterator service_it =
+ std::find(service_list.begin(), service_list.end(), service_type);
+ if(service_it != service_list.end()){
+ return &(*service_it);
+ }
+ return NULL;
+}
+
+Connection::Connection(ConnectionHandle connection_handle,
+ DeviceHandle connection_device_handle,
+ ConnectionHandler *connection_handler,
+ int32_t heartbeat_timeout)
+ : connection_handler_(connection_handler),
+ connection_handle_(connection_handle),
+ connection_device_handle_(connection_device_handle) {
+ LOG4CXX_TRACE_ENTER(logger_);
+ DCHECK(connection_handler_);
+
+ heartbeat_monitor_ = new HeartBeatMonitor(heartbeat_timeout, this);
+ heart_beat_monitor_thread_ = new threads::Thread("HeartBeatMonitor",
+ heartbeat_monitor_);
+ heart_beat_monitor_thread_->start();
+}
+
+Connection::~Connection() {
+ LOG4CXX_TRACE_ENTER(logger_);
+ heart_beat_monitor_thread_->stop();
+ delete heart_beat_monitor_thread_;
+ sync_primitives::AutoLock lock(session_map_lock_);
+ session_map_.clear();
+ LOG4CXX_TRACE_EXIT(logger_);
+}
+
+// Finds a key not presented in std::map<unsigned char, T>
+// Returns 0 if that key not found
+namespace {
+template <class T>
+uint32_t findGap(const std::map<unsigned char, T> &map) {
+ for (uint32_t i = 1; i <= UCHAR_MAX; ++i) {
+ if (map.find(i) == map.end()) {
+ return i;
+ }
+ }
+ return 0;
+}
+} // namespace
+
+uint32_t Connection::AddNewSession() {
+ LOG4CXX_TRACE_ENTER(logger_);
+ sync_primitives::AutoLock lock(session_map_lock_);
+ const uint32_t session_id = findGap(session_map_);
+ if (session_id > 0) {
+ Session& new_session = session_map_[session_id];
+ new_session.protocol_version = ::protocol_handler::PROTOCOL_VERSION_2;
+ new_session.service_list.push_back(Service(protocol_handler::kRpc));
+ new_session.service_list.push_back(Service(protocol_handler::kBulk));
+ }
+ return session_id;
+}
+
+uint32_t Connection::RemoveSession(uint8_t session_id) {
+ sync_primitives::AutoLock lock(session_map_lock_);
+ SessionMap::iterator it = session_map_.find(session_id);
+ if (session_map_.end() == it) {
+ LOG4CXX_WARN(logger_, "Session not found in this connection!");
+ return 0;
+ }
+ heartbeat_monitor_->RemoveSession(session_id);
+ session_map_.erase(session_id);
+ return session_id;
+}
+
+bool Connection::AddNewService(uint8_t session_id,
+ protocol_handler::ServiceType service_type,
+ const bool request_protection) {
+ // Ignore wrong services
+ if (protocol_handler::kControl == service_type ||
+ protocol_handler::kInvalidServiceType == service_type ) {
+ LOG4CXX_WARN(logger_, "Wrong service " << static_cast<int>(service_type));
+ return false;
+ }
+ sync_primitives::AutoLock lock(session_map_lock_);
+
+ SessionMap::iterator session_it = session_map_.find(session_id);
+ if (session_it == session_map_.end()) {
+ LOG4CXX_WARN(logger_, "Session not found in this connection!");
+ return false;
+ }
+ Session &session = session_it->second;
+ Service *service = session.FindService(service_type);
+ // if service already exists
+ if (service) {
+#ifdef ENABLE_SECURITY
+ if(!request_protection) {
+ LOG4CXX_WARN(logger_, "Session " << static_cast<int>(session_id) <<
+ " already has unprotected service "<< static_cast<int>(service_type));
+ return false;
+ }
+ if (service->is_protected_) {
+ LOG4CXX_WARN(logger_, "Session " << static_cast<int>(session_id) <<
+ " already has protected service "<< static_cast<int>(service_type));
+ return false;
+ }
+ // For unproteced service could be start protection
+ return true;
+#else
+ // Service already exists
+ return false;
+#endif // ENABLE_SECURITY
+ }
+ // id service is not exists
+ session.service_list.push_back(Service(service_type));
+ return true;
+}
+
+inline bool is_incorrect_for_remove_service(
+ const protocol_handler::ServiceType service_type) {
+ return
+ // Control type is internal part of session
+ protocol_handler::kControl == service_type ||
+ // RPC and bulk service is necessary part of session
+ protocol_handler::kRpc == service_type ||
+ protocol_handler::kBulk == service_type ||
+ // Invalid service is not part of session
+ protocol_handler::kInvalidServiceType == service_type;
+}
+
+bool Connection::RemoveService(
+ uint8_t session_id, protocol_handler::ServiceType service_type) {
+ // Ignore wrong and required for Session services
+ if (is_incorrect_for_remove_service(service_type)) {
+ LOG4CXX_WARN(logger_, "Could not remove service "
+ << static_cast<int>(service_type));
+ return false;
+ }
+ sync_primitives::AutoLock lock(session_map_lock_);
+
+ SessionMap::iterator session_it = session_map_.find(session_id);
+ if (session_map_.end() == session_it) {
+ LOG4CXX_WARN(logger_, "Session not found in this connection!");
+ return false;
+ }
+
+ ServiceList &service_list = session_it->second.service_list;
+ ServiceList::iterator service_it =
+ find(service_list.begin(), service_list.end(), service_type);
+ if (service_list.end() == service_it) {
+ LOG4CXX_WARN(logger_, "Session " << session_id << " didn't established"
+ " service " << service_type);
+ return false;
+ }
+ service_list.erase(service_it);
+ return true;
+}
+
+#ifdef ENABLE_SECURITY
+int Connection::SetSSLContext(uint8_t session_id,
+ security_manager::SSLContext *context) {
+ sync_primitives::AutoLock lock(session_map_lock_);
+ SessionMap::iterator session_it = session_map_.find(session_id);
+ if (session_it == session_map_.end()) {
+ LOG4CXX_WARN(logger_, "Session not found in this connection!");
+ return security_manager::SecurityManager::ERROR_INTERNAL;
+ }
+ Session &session = session_it->second;
+ session.ssl_context = context;
+ return security_manager::SecurityManager::ERROR_SUCCESS;
+}
+
+security_manager::SSLContext *Connection::GetSSLContext(
+ const uint8_t session_id, const protocol_handler::ServiceType &service_type) const {
+ LOG4CXX_TRACE(logger_, "Connection::GetSSLContext");
+ sync_primitives::AutoLock lock(session_map_lock_);
+ SessionMap::const_iterator session_it = session_map_.find(session_id);
+ if (session_it == session_map_.end()) {
+ LOG4CXX_WARN(logger_, "Session not found in this connection!");
+ return NULL;
+ }
+ const Session &session = session_it->second;
+ // for control services return current SSLContext value
+ if (protocol_handler::kControl == service_type)
+ return session.ssl_context;
+ const Service *service = session.FindService(service_type);
+ if (!service) {
+ LOG4CXX_WARN(logger_, "Service not found in this session!");
+ return NULL;
+ }
+ if (!service->is_protected_)
+ return NULL;
+ LOG4CXX_TRACE(logger_, "SSLContext is " << session.ssl_context);
+ return session.ssl_context;
+}
+
+void Connection::SetProtectionFlag(
+ const uint8_t session_id, const protocol_handler::ServiceType &service_type) {
+ LOG4CXX_TRACE(logger_, "Connection::SetProtectionFlag");
+ sync_primitives::AutoLock lock(session_map_lock_);
+ SessionMap::iterator session_it = session_map_.find(session_id);
+ if (session_it == session_map_.end()) {
+ LOG4CXX_WARN(logger_, "Session not found in this connection!");
+ return;
+ }
+ Session &session = session_it->second;
+ Service *service = session.FindService(service_type);
+ if (!service) {
+ LOG4CXX_WARN(logger_, "Service not found in this session!");
+ return;
+ }
+ service->is_protected_ = true;
+ // Rpc and bulk shall be protected as one service
+ if (service->service_type == protocol_handler::kRpc) {
+ Service *service_bulk = session.FindService(protocol_handler::kBulk);
+ DCHECK(service_bulk);
+ service_bulk->is_protected_ = true;
+ } else if (service->service_type == protocol_handler::kBulk) {
+ Service *service_rpc = session.FindService(protocol_handler::kRpc);
+ DCHECK(service_rpc);
+ service_rpc->is_protected_ = true;
+ }
+}
+#endif // ENABLE_SECURITY
+
+ConnectionHandle Connection::connection_handle() const {
+ return connection_handle_;
+}
+
+DeviceHandle Connection::connection_device_handle() {
+ return connection_device_handle_;
+}
+
+const SessionMap Connection::session_map() const {
+ sync_primitives::AutoLock lock(session_map_lock_);
+ return session_map_;
+}
+
+void Connection::CloseSession(uint8_t session_id) {
+ size_t size;
+ {
+ sync_primitives::AutoLock lock(session_map_lock_);
+
+ SessionMap::iterator session_it = session_map_.find(session_id);
+ if (session_it == session_map_.end()) {
+ return;
+ }
+ size = session_map_.size();
+ }
+
+ connection_handler_->CloseSession(connection_handle_, session_id);
+
+ //Close connection if it is last session
+ if (1 == size) {
+ connection_handler_->CloseConnection(connection_handle_);
+ }
+}
+
+void Connection::UpdateProtocolVersionSession(
+ uint8_t session_id, uint8_t protocol_version) {
+ sync_primitives::AutoLock lock(session_map_lock_);
+ SessionMap::iterator session_it = session_map_.find(session_id);
+ if (session_map_.end() == session_it) {
+ LOG4CXX_WARN(logger_, "Session not found in this connection!");
+ return;
+ }
+ Session &session = session_it->second;
+ session.protocol_version = protocol_version;
+}
+
+bool Connection::SupportHeartBeat(uint8_t session_id) {
+ sync_primitives::AutoLock lock(session_map_lock_);
+ SessionMap::iterator session_it = session_map_.find(session_id);
+ if (session_map_.end() == session_it) {
+ LOG4CXX_WARN(logger_, "Session not found in this connection!");
+ return false;
+ }
+ Session &session = session_it->second;
+ return ::protocol_handler::PROTOCOL_VERSION_3 == session.protocol_version;
+}
+
+void Connection::StartHeartBeat(uint8_t session_id) {
+ heartbeat_monitor_->AddSession(session_id);
+}
+
+void Connection::SendHeartBeat(uint8_t session_id) {
+ connection_handler_->SendHeartBeat(connection_handle_, session_id);
+}
+
+void Connection::KeepAlive(uint8_t session_id) {
+ heartbeat_monitor_->KeepAlive(session_id);
+}
+
+void Connection::SetHeartBeatTimeout(int32_t timeout) {
+ heartbeat_monitor_->set_heartbeat_timeout_seconds(timeout);
+}
+
+} // namespace connection_handler
diff --git a/src/components/connection_handler/src/connection_handler_impl.cc b/src/components/connection_handler/src/connection_handler_impl.cc
new file mode 100644
index 0000000000..f1dae841a6
--- /dev/null
+++ b/src/components/connection_handler/src/connection_handler_impl.cc
@@ -0,0 +1,863 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+#include <strings.h>
+
+#include <string>
+#include <list>
+#include <algorithm>
+
+#include "connection_handler/connection_handler_impl.h"
+#include "transport_manager/info.h"
+#include "config_profile/profile.h"
+
+#ifdef ENABLE_SECURITY
+#include "security_manager/security_manager.h"
+#endif // ENABLE_SECURITY
+
+namespace {
+int32_t HeartBeatTimeout() {
+ return profile::Profile::instance()->heart_beat_timeout();
+}
+} // namespace
+
+/**
+ * \namespace connection_handler
+ * \brief SmartDeviceLink ConnectionHandler namespace.
+ */
+namespace connection_handler {
+
+CREATE_LOGGERPTR_GLOBAL(logger_, "ConnectionHandler")
+
+ConnectionHandle HandleFromConnectionUID(transport_manager::ConnectionUID uid) {
+ return ConnectionHandle(uid);
+}
+
+transport_manager::ConnectionUID ConnectionUIDFromHandle(
+ ConnectionHandle handle) {
+ return transport_manager::ConnectionUID(handle);
+}
+
+ConnectionHandlerImpl::ConnectionHandlerImpl()
+ : connection_handler_observer_(NULL),
+ transport_manager_(NULL),
+ protocol_handler_(NULL),
+ connection_list_deleter_(&connection_list_) {
+}
+
+ConnectionHandlerImpl::~ConnectionHandlerImpl() {
+ LOG4CXX_TRACE(logger_, "Destructing ConnectionHandlerImpl.");
+}
+
+void ConnectionHandlerImpl::Stop() {
+ LOG4CXX_TRACE_ENTER(logger_);
+ ConnectionList::iterator itr = connection_list_.begin();
+ while (itr != connection_list_.end()) {
+ RemoveConnection(itr->second->connection_handle());
+ itr = connection_list_.begin();
+ }
+ LOG4CXX_TRACE_EXIT(logger_);
+}
+
+void ConnectionHandlerImpl::set_connection_handler_observer(
+ ConnectionHandlerObserver *observer) {
+ LOG4CXX_DEBUG(logger_, "ConnectionHandlerImpl::set_connection_handler_observer() "
+ << observer);
+ if (!observer) {
+ LOG4CXX_WARN(logger_, "Set Null pointer to observer.");
+ }
+ connection_handler_observer_ = observer;
+}
+
+void ConnectionHandlerImpl::set_transport_manager(
+ transport_manager::TransportManager *transport_mngr) {
+ LOG4CXX_DEBUG(logger_, "ConnectionHandlerImpl::set_transport_manager() "
+ << transport_mngr);
+ if (!transport_mngr) {
+ LOG4CXX_ERROR(logger_, "Null pointer to TransportManager.");
+ return;
+ }
+ transport_manager_ = transport_mngr;
+}
+
+void ConnectionHandlerImpl::set_protocol_handler(
+ protocol_handler::ProtocolHandler *protocol_handler) {
+ LOG4CXX_DEBUG(logger_, "ConnectionHandlerImpl::set_protocol_handler()"
+ << protocol_handler);
+ if (!protocol_handler) {
+ LOG4CXX_WARN(logger_, "Set Null pointer to protocol handler.");
+ }
+ protocol_handler_ = protocol_handler;
+}
+
+void ConnectionHandlerImpl::OnDeviceListUpdated(
+ const std::vector<transport_manager::DeviceInfo>&) {
+ LOG4CXX_TRACE(logger_, "ConnectionHandlerImpl::OnDeviceListUpdated()");
+ if (connection_handler_observer_) {
+ connection_handler_observer_->OnDeviceListUpdated(device_list_);
+ }
+}
+
+void ConnectionHandlerImpl::OnFindNewApplicationsRequest() {
+ if (connection_handler_observer_) {
+ connection_handler_observer_->OnFindNewApplicationsRequest();
+ }
+}
+
+void ConnectionHandlerImpl::OnDeviceFound(
+ const transport_manager::DeviceInfo&) {
+ LOG4CXX_TRACE(logger_, "ConnectionHandlerImpl::OnDeviceFound()");
+}
+
+void ConnectionHandlerImpl::OnDeviceAdded(
+ const transport_manager::DeviceInfo &device_info) {
+ LOG4CXX_TRACE(logger_, "ConnectionHandlerImpl::OnDeviceAdded()");
+ device_list_.insert(
+ DeviceMap::value_type(
+ device_info.device_handle(),
+ Device(device_info.device_handle(), device_info.name(),
+ device_info.mac_address(), device_info.connection_type())));
+ if (connection_handler_observer_) {
+ connection_handler_observer_->OnDeviceListUpdated(device_list_);
+ }
+}
+
+void ConnectionHandlerImpl::OnDeviceRemoved(
+ const transport_manager::DeviceInfo &device_info) {
+ LOG4CXX_TRACE(logger_, "ConnectionHandlerImpl::OnDeviceRemoved()");
+ // Device has been removed. Perform all needed actions.
+ // 1. Delete all the connections and sessions of this device
+ // 2. Delete device from a list
+ // 3. Let observer know that device has been deleted.
+
+ std::vector<ConnectionHandle> connections_to_remove;
+ {
+ sync_primitives::AutoLock lock(connection_list_lock_);
+ for (ConnectionList::iterator it = connection_list_.begin();
+ it != connection_list_.end(); ++it) {
+ if (device_info.device_handle() ==
+ (*it).second->connection_device_handle()) {
+ connections_to_remove.push_back((*it).first);
+ }
+ }
+ }
+
+ std::vector<ConnectionHandle>::iterator it = connections_to_remove.begin();
+ for (; it != connections_to_remove.end(); ++it) {
+ RemoveConnection(*it);
+ }
+
+ device_list_.erase(device_info.device_handle());
+ if (connection_handler_observer_) {
+ connection_handler_observer_->RemoveDevice(device_info.device_handle());
+ connection_handler_observer_->OnDeviceListUpdated(device_list_);
+ }
+}
+
+void ConnectionHandlerImpl::OnScanDevicesFinished() {
+ LOG4CXX_TRACE(logger_, "Scan devices finished successfully.");
+}
+
+void ConnectionHandlerImpl::OnScanDevicesFailed(
+ const transport_manager::SearchDeviceError &error) {
+ LOG4CXX_WARN(logger_, "Scan devices failed. " << error.text());
+}
+
+void ConnectionHandlerImpl::OnConnectionEstablished(
+ const transport_manager::DeviceInfo &device_info,
+ const transport_manager::ConnectionUID &connection_id) {
+ LOG4CXX_TRACE(logger_, "ConnectionHandlerImpl::OnConnectionEstablished()");
+
+ DeviceMap::iterator it = device_list_.find(device_info.device_handle());
+ if (device_list_.end() == it) {
+ LOG4CXX_ERROR(logger_, "Unknown device!");
+ return;
+ }
+ LOG4CXX_INFO(logger_, "Add Connection:" << connection_id << " to the list.");
+ sync_primitives::AutoLock lock(connection_list_lock_);
+ connection_list_.insert(
+ ConnectionList::value_type(
+ connection_id,
+ new Connection(connection_id, device_info.device_handle(), this,
+ HeartBeatTimeout())));
+}
+
+void ConnectionHandlerImpl::OnConnectionFailed(
+ const transport_manager::DeviceInfo &device_info,
+ const transport_manager::ConnectError &error) {
+ // TODO(PV): implement
+ LOG4CXX_ERROR(logger_, "Failed connecting.");
+}
+
+void ConnectionHandlerImpl::OnConnectionClosed(
+ transport_manager::ConnectionUID connection_id) {
+ LOG4CXX_INFO(logger_, "ConnectionHandlerImpl::OnConnectionClosed");
+
+ OnConnectionEnded(connection_id);
+}
+
+void ConnectionHandlerImpl::OnConnectionClosedFailure(
+ transport_manager::ConnectionUID connection_id,
+ const transport_manager::DisconnectError &error) {
+ // TODO(PV): implement
+ LOG4CXX_ERROR(logger_, "ConnectionHandlerImpl::OnConnectionClosedFailure");
+}
+
+void ConnectionHandlerImpl::OnUnexpectedDisconnect(
+ transport_manager::ConnectionUID connection_id,
+ const transport_manager::CommunicationError &error) {
+ LOG4CXX_ERROR(logger_, "ConnectionHandlerImpl::OnUnexpectedDisconnect");
+
+ OnConnectionEnded(connection_id);
+}
+
+void ConnectionHandlerImpl::OnDeviceConnectionLost(
+ const transport_manager::DeviceHandle &device,
+ const transport_manager::DisconnectDeviceError &error) {
+ // TODO(PV): implement
+ LOG4CXX_ERROR(logger_, "Lost connection with device " << device);
+}
+
+void ConnectionHandlerImpl::OnDisconnectFailed(
+ const transport_manager::DeviceHandle &device,
+ const transport_manager::DisconnectDeviceError &error) {
+ // TODO(PV): implement
+ LOG4CXX_ERROR(logger_, "Trying to Disconnect device failed.");
+}
+
+void ConnectionHandlerImpl::RemoveConnection(
+ const ConnectionHandle connection_handle) {
+ LOG4CXX_INFO(logger_, "ConnectionHandlerImpl::RemoveConnection()");
+
+ OnConnectionEnded(connection_handle);
+}
+
+#ifdef ENABLE_SECURITY
+namespace {
+bool AllowProtection(const protocol_handler::ServiceType &service_type,
+ const bool is_protected) {
+ if (is_protected) {
+ // Check deliver-specific services (which shall not be protected)
+ const std::list<int> force_unprotected_list =
+ profile::Profile::instance()->ReadIntContainer(
+ "Security Manager", "ForceUnprotectedService", NULL);
+ if (std::find(force_unprotected_list.begin(), force_unprotected_list.end(), service_type) !=
+ force_unprotected_list.end()) {
+ LOG4CXX_ERROR(logger_, "Service " << static_cast<int>(service_type)
+ << " is forbidden to be protected");
+ return false;
+ }
+ } else {
+ // Check deliver-specific services (which shall be protected)
+ const std::list<int> force_protected_list =
+ profile::Profile::instance()->ReadIntContainer(
+ "Security Manager", "ForceProtectedService", NULL);
+ if (std::find(force_protected_list.begin(), force_protected_list.end(), service_type) !=
+ force_protected_list.end()) {
+ LOG4CXX_ERROR(logger_, "Service " << static_cast<int>(service_type)
+ << " shall be protected");
+ return false;
+ }
+ }
+ return true;
+}
+} // namespace
+#endif // ENABLE_SECURITY
+
+uint32_t ConnectionHandlerImpl::OnSessionStartedCallback(
+ const transport_manager::ConnectionUID &connection_handle,
+ const uint8_t session_id, const protocol_handler::ServiceType &service_type,
+ const bool is_protected, uint32_t* hash_id) {
+ LOG4CXX_TRACE_ENTER(logger_);
+
+ if (hash_id) {
+ *hash_id = protocol_handler::HASH_ID_WRONG;
+ }
+#ifdef ENABLE_SECURITY
+ if (!AllowProtection(service_type, is_protected)) {
+ return 0;
+ }
+#endif // ENABLE_SECURITY
+
+ sync_primitives::AutoLock lock(connection_list_lock_);
+ ConnectionList::iterator it = connection_list_.find(connection_handle);
+ if (connection_list_.end() == it) {
+ LOG4CXX_ERROR(logger_, "Unknown connection!");
+ LOG4CXX_TRACE_EXIT(logger_);
+ return 0;
+ }
+ uint32_t new_session_id = 0;
+
+ Connection *connection = it->second;
+ if ((0 == session_id) && (protocol_handler::kRpc == service_type)) {
+ new_session_id = connection->AddNewSession();
+ if (0 == new_session_id) {
+ LOG4CXX_ERROR(logger_, "Couldn't start new session!");
+ LOG4CXX_TRACE_EXIT(logger_);
+ return 0;
+ }
+ if (hash_id) {
+ *hash_id = KeyFromPair(connection_handle, new_session_id);
+ }
+ } else { // Could be create new service or protected exists one
+ if (!connection->AddNewService(session_id, service_type, is_protected)) {
+ LOG4CXX_ERROR(logger_, "Couldn't establish "
+#ifdef ENABLE_SECURITY
+ << (is_protected ? "protected" : "non-protected")
+#endif // ENABLE_SECURITY
+ << " service " << static_cast<int>(service_type)
+ << " for session " << static_cast<int>(session_id));
+ LOG4CXX_TRACE_EXIT(logger_);
+ return 0;
+ }
+ new_session_id = session_id;
+ if (hash_id) {
+ *hash_id = protocol_handler::HASH_ID_NOT_SUPPORTED;
+ }
+ }
+
+ if (connection_handler_observer_) {
+ const uint32_t session_key = KeyFromPair(connection_handle, new_session_id);
+ const bool success = connection_handler_observer_->OnServiceStartedCallback(
+ connection->connection_device_handle(), session_key, service_type);
+ if (!success) {
+ if (protocol_handler::kRpc == service_type) {
+ connection->RemoveSession(new_session_id);
+ } else {
+ connection->RemoveService(session_id, service_type);
+ }
+ LOG4CXX_TRACE_EXIT(logger_);
+ return 0;
+ }
+ }
+ LOG4CXX_TRACE_EXIT(logger_);
+ return new_session_id;
+}
+
+uint32_t ConnectionHandlerImpl::OnSessionEndedCallback(
+ const uint32_t &connection_handle, const uint8_t session_id,
+ const uint32_t &hashCode,
+ const protocol_handler::ServiceType &service_type) {
+ LOG4CXX_TRACE(logger_, "ConnectionHandlerImpl::OnSessionEndedCallback()");
+
+ sync_primitives::AutoLock lock(connection_list_lock_);
+ ConnectionList::iterator it = connection_list_.find(connection_handle);
+ if (connection_list_.end() == it) {
+ LOG4CXX_WARN(logger_, "Unknown connection!");
+ return 0;
+ }
+ Connection *connection = it->second;
+ const uint32_t session_key = KeyFromPair(connection_handle, session_id);
+
+ if (protocol_handler::kRpc == service_type) {
+ LOG4CXX_INFO(logger_, "Session " << static_cast<uint32_t>(session_id)
+ << " to be removed");
+ // old version of protocol doesn't support hash
+ if (protocol_handler::HASH_ID_NOT_SUPPORTED != hashCode) {
+ if (protocol_handler::HASH_ID_WRONG == hashCode ||
+ session_key != hashCode) {
+ LOG4CXX_WARN(logger_, "Wrong hash_id for session "
+ << static_cast<uint32_t>(session_id));
+ return 0;
+ }
+ }
+ if (!connection->RemoveSession(session_id)) {
+ LOG4CXX_WARN(logger_, "Couldn't remove session "
+ << static_cast<uint32_t>(session_id));
+ return 0;
+ }
+ } else {
+ LOG4CXX_INFO(logger_, "Service " << static_cast<uint32_t>(service_type)
+ << " to be removed");
+ if (!connection->RemoveService(session_id, service_type)) {
+ LOG4CXX_WARN(logger_, "Couldn't remove service "
+ << static_cast<uint32_t>(service_type));
+ return 0;
+ }
+ }
+
+ if (connection_handler_observer_) {
+ connection_handler_observer_->OnServiceEndedCallback(session_key,
+ service_type);
+ }
+ return session_key;
+}
+
+uint32_t ConnectionHandlerImpl::KeyFromPair(
+ transport_manager::ConnectionUID connection_handle, uint8_t session_id) {
+ const uint32_t key = connection_handle | (session_id << 16);
+ LOG4CXX_TRACE(logger_, "Key for ConnectionHandle:"
+ << static_cast<uint32_t>(connection_handle)
+ << " Session:" << static_cast<uint32_t>(session_id)
+ << " is: " << static_cast<uint32_t>(key));
+ if (protocol_handler::HASH_ID_WRONG == key) {
+ LOG4CXX_ERROR(logger_, "Connection key is WRONG_HASH_ID "
+ "(session id shall be greater 0)");
+ }
+ return key;
+}
+
+void ConnectionHandlerImpl::PairFromKey(uint32_t key,
+ uint32_t *connection_handle,
+ uint8_t *session_id) {
+ *connection_handle = key & 0xFF00FFFF;
+ *session_id = key >> 16;
+ LOG4CXX_TRACE(logger_, "ConnectionHandle:"
+ << static_cast<int32_t>(*connection_handle)
+ << " Session:" << static_cast<int32_t>(*session_id)
+ << " for key:" << static_cast<int32_t>(key));
+}
+
+int32_t ConnectionHandlerImpl::GetDataOnSessionKey(
+ uint32_t key, uint32_t *app_id, std::list<int32_t> *sessions_list,
+ uint32_t *device_id) {
+ LOG4CXX_TRACE(logger_, "ConnectionHandlerImpl::GetDataOnSessionKey");
+
+ int32_t result = -1;
+ transport_manager::ConnectionUID conn_handle = 0;
+ uint8_t session_id = 0;
+ PairFromKey(key, &conn_handle, &session_id);
+ ConnectionList::iterator it = connection_list_.find(conn_handle);
+
+ if (connection_list_.end() == it) {
+ LOG4CXX_ERROR(logger_, "Unknown connection!");
+ return result;
+ }
+
+ Connection &connection = *it->second;
+ if (device_id) {
+ *device_id = connection.connection_device_handle();
+ }
+
+ if (sessions_list) {
+ sessions_list->clear();
+ }
+
+ if (0 == session_id) {
+ LOG4CXX_WARN(
+ logger_,
+ "No sessions in connection " << static_cast<int32_t>(conn_handle));
+ if (app_id) {
+ *app_id = 0;
+ }
+ } else {
+ if (app_id) {
+ *app_id = KeyFromPair(conn_handle, session_id);
+ }
+
+ LOG4CXX_INFO(logger_, "Connection "
+ << static_cast<int32_t>(conn_handle)
+ << " has " << connection.session_map().size()
+ << " sessions.");
+
+ if (sessions_list) {
+ const SessionMap session_map = connection.session_map();
+ for (SessionMap::const_iterator session_it = session_map.begin();
+ session_map.end() != session_it; ++session_it) {
+ sessions_list->push_back(KeyFromPair(conn_handle, it->first));
+ }
+ }
+
+ result = 0;
+ }
+
+ return result;
+}
+
+struct CompareMAC {
+ explicit CompareMAC(const std::string &mac) : mac_(mac) {}
+ bool operator() (const DeviceMap::value_type &device) {
+ return strcasecmp(device.second.mac_address().c_str(), mac_.c_str()) == 0;
+ }
+ private:
+ std::string mac_;
+};
+
+bool ConnectionHandlerImpl::GetDeviceID(const std::string &mac_address,
+ DeviceHandle *device_handle) {
+ DeviceMap::const_iterator it = std::find_if(device_list_.begin(),
+ device_list_.end(),
+ CompareMAC(mac_address));
+ if (it != device_list_.end()) {
+ if (device_handle) {
+ *device_handle = it->first;
+ }
+ return true;
+ }
+ return false;
+}
+
+int32_t ConnectionHandlerImpl::GetDataOnDeviceID(
+ DeviceHandle device_handle,
+ std::string *device_name,
+ std::list<uint32_t> *applications_list, std::string *mac_address,
+ std::string* connection_type ) {
+ LOG4CXX_TRACE(logger_, "ConnectionHandlerImpl::GetDataOnDeviceID");
+
+ int32_t result = -1;
+ DeviceMap::iterator it = device_list_.find(device_handle);
+ if (device_list_.end() == it) {
+ LOG4CXX_ERROR(logger_, "Device not found!");
+ return result;
+ }
+
+ if (device_name) {
+ *device_name = it->second.user_friendly_name();
+ }
+ if (connection_type) {
+ *connection_type = it->second.connection_type();
+ }
+ if (applications_list) {
+ applications_list->clear();
+ sync_primitives::AutoLock connection_list_lock(connection_list_lock_);
+ for (ConnectionList::iterator itr = connection_list_.begin();
+ itr != connection_list_.end(); ++itr) {
+ if (device_handle == (*itr).second->connection_device_handle()) {
+ const SessionMap &session_map = (itr->second)->session_map();
+ for (SessionMap::const_iterator session_it = session_map.begin();
+ session_map.end() != session_it; ++session_it) {
+ const transport_manager::ConnectionUID &connection_handle = itr->first;
+ const uint32_t session_id = session_it->first;
+ const uint32_t application_id = KeyFromPair(connection_handle, session_id);
+ applications_list->push_back(application_id);
+ }
+ }
+ }
+ }
+
+ if (mac_address) {
+ *mac_address = it->second.mac_address();
+ }
+
+ result = 0;
+
+ return result;
+}
+#ifdef ENABLE_SECURITY
+int ConnectionHandlerImpl::SetSSLContext(
+ const uint32_t &key, security_manager::SSLContext *context) {
+ LOG4CXX_TRACE(logger_, "ConnectionHandlerImpl::SetSSLContext");
+ transport_manager::ConnectionUID connection_handle = 0;
+ uint8_t session_id = 0;
+ PairFromKey(key, &connection_handle, &session_id);
+
+ sync_primitives::AutoLock lock(connection_list_lock_);
+ ConnectionList::iterator it = connection_list_.find(connection_handle);
+ if (connection_list_.end() == it) {
+ LOG4CXX_ERROR(logger_, "Unknown connection!");
+ return security_manager::SecurityManager::ERROR_INTERNAL;
+ }
+ Connection &connection = *it->second;
+ return connection.SetSSLContext(session_id, context);
+}
+
+security_manager::SSLContext *ConnectionHandlerImpl::GetSSLContext(
+ const uint32_t &key, const protocol_handler::ServiceType &service_type) {
+ LOG4CXX_TRACE(logger_, "ConnectionHandlerImpl::GetSSLContext");
+ transport_manager::ConnectionUID connection_handle = 0;
+ uint8_t session_id = 0;
+ PairFromKey(key, &connection_handle, &session_id);
+
+ sync_primitives::AutoLock lock(connection_list_lock_);
+ ConnectionList::iterator it = connection_list_.find(connection_handle);
+ if (connection_list_.end() == it) {
+ LOG4CXX_ERROR(logger_, "Unknown connection!");
+ return NULL;
+ }
+ Connection &connection = *it->second;
+ return connection.GetSSLContext(session_id, service_type);
+}
+
+void ConnectionHandlerImpl::SetProtectionFlag(
+ const uint32_t &key, const protocol_handler::ServiceType &service_type) {
+ LOG4CXX_TRACE(logger_, "ConnectionHandlerImpl::SetProtectionFlag");
+ transport_manager::ConnectionUID connection_handle = 0;
+ uint8_t session_id = 0;
+ PairFromKey(key, &connection_handle, &session_id);
+
+ sync_primitives::AutoLock lock(connection_list_lock_);
+ ConnectionList::iterator it = connection_list_.find(connection_handle);
+ if (connection_list_.end() == it) {
+ LOG4CXX_ERROR(logger_, "Unknown connection!");
+ return;
+ }
+ Connection &connection = *it->second;
+ connection.SetProtectionFlag(session_id, service_type);
+}
+#endif // ENABLE_SECURITY
+
+void ConnectionHandlerImpl::StartDevicesDiscovery() {
+ LOG4CXX_TRACE(logger_, "ConnectionHandlerImpl::StartDevicesDiscovery()");
+
+ if (NULL == transport_manager_) {
+ LOG4CXX_ERROR(logger_, "Null pointer to TransportManager.");
+ return;
+ }
+ transport_manager_->SearchDevices();
+ if (connection_handler_observer_) {
+ connection_handler_observer_->OnDeviceListUpdated(device_list_);
+ }
+}
+
+void ConnectionHandlerImpl::ConnectToDevice(
+ connection_handler::DeviceHandle device_handle) {
+ connection_handler::DeviceMap::const_iterator it_in;
+ it_in = device_list_.find(device_handle);
+ if (device_list_.end() != it_in) {
+ LOG4CXX_INFO_EXT(logger_,
+ "Connecting to device with handle " << device_handle);
+ if (transport_manager_) {
+ if (transport_manager::E_SUCCESS
+ != transport_manager_->ConnectDevice(device_handle)) {
+ LOG4CXX_WARN(logger_, "Can't connect to device");
+ }
+ } else {
+ LOG4CXX_ERROR(logger_, "Null pointer to TransportManager.");
+ }
+ } else {
+ LOG4CXX_ERROR(
+ logger_, "Application Manager wanted to connect to non-existing device");
+ }
+}
+
+void ConnectionHandlerImpl::ConnectToAllDevices() {
+ for (DeviceMap::iterator i = device_list_.begin(); i != device_list_.end(); ++i) {
+ connection_handler::DeviceHandle device_handle = i->first;
+ ConnectToDevice(device_handle);
+ }
+}
+
+void ConnectionHandlerImpl::StartTransportManager() {
+ LOG4CXX_INFO(logger_, "ConnectionHandlerImpl::StartTransportManager()");
+ if (NULL == transport_manager_) {
+ LOG4CXX_ERROR(logger_, "Null pointer to TransportManager.");
+ return;
+ }
+
+ transport_manager_->Visibility(true);
+}
+
+void ConnectionHandlerImpl::CloseRevokedConnection(uint32_t connection_key) {
+ LOG4CXX_TRACE(logger_, "ConnectionHandlerImpl::CloseRevokedConnection");
+
+ uint32_t connection_handle = 0;
+ uint8_t session_id = 0;
+ PairFromKey(connection_key, &connection_handle, &session_id);
+
+ CloseConnection(connection_handle);
+}
+
+void ConnectionHandlerImpl::CloseConnection(
+ ConnectionHandle connection_handle) {
+ LOG4CXX_TRACE(logger_, "ConnectionHandlerImpl::CloseConnection");
+ if (!transport_manager_) {
+ LOG4CXX_ERROR(logger_, "Null pointer to TransportManager.");
+ return;
+ }
+ transport_manager::ConnectionUID connection_uid =
+ ConnectionUIDFromHandle(connection_handle);
+ transport_manager_->DisconnectForce(connection_uid);
+}
+
+uint32_t ConnectionHandlerImpl::GetConnectionSessionsCount(
+ uint32_t connection_key) {
+ uint32_t connection_handle = 0;
+ uint8_t session_id = 0;
+ PairFromKey(connection_key, &connection_handle, &session_id);
+
+ sync_primitives::AutoLock lock(connection_list_lock_);
+ ConnectionList::iterator itr = connection_list_.find(connection_handle);
+
+ if (connection_list_.end() != itr) {
+ return itr->second->session_map().size();
+ }
+
+ return 0;
+}
+
+void ConnectionHandlerImpl::CloseSession(uint32_t key) {
+ LOG4CXX_TRACE(logger_, "ConnectionHandlerImpl::CloseSession");
+
+ uint32_t connection_handle = 0;
+ uint8_t session_id = 0;
+ PairFromKey(key, &connection_handle, &session_id);
+
+ CloseSession(connection_handle, session_id);
+}
+
+void ConnectionHandlerImpl::CloseSession(ConnectionHandle connection_handle,
+ uint8_t session_id) {
+ if (protocol_handler_) {
+ protocol_handler_->SendEndSession(connection_handle, session_id);
+ }
+
+ transport_manager::ConnectionUID connection_id =
+ ConnectionUIDFromHandle(connection_handle);
+
+ sync_primitives::AutoLock connection_list_lock(connection_list_lock_);
+ ConnectionList::iterator itr = connection_list_.find(connection_id);
+
+ if (connection_list_.end() != itr) {
+ if (connection_handler_observer_) {
+ SessionMap session_map = itr->second->session_map();
+ SessionMap::iterator session_it = session_map.find(session_id);
+ if (session_it != session_map.end()) {
+ const Session &session = session_it->second;
+ const ServiceList &service_list = session.service_list;
+ ServiceList::const_iterator it = service_list.begin();
+ for (;it != service_list.end(); ++it) {
+ const uint32_t session_key = KeyFromPair(connection_id, session_id);
+ const protocol_handler::ServiceType service_type = it->service_type;
+ connection_handler_observer_->OnServiceEndedCallback(session_key,
+ service_type);
+ }
+ }
+ }
+ itr->second->RemoveSession(session_id);
+ }
+}
+
+void ConnectionHandlerImpl::StartSessionHeartBeat(uint32_t connection_key) {
+ uint32_t connection_handle = 0;
+ uint8_t session_id = 0;
+ PairFromKey(connection_key, &connection_handle, &session_id);
+
+ sync_primitives::AutoLock lock(connection_list_lock_);
+ ConnectionList::iterator it = connection_list_.find(connection_handle);
+ if (connection_list_.end() != it) {
+ it->second->StartHeartBeat(session_id);
+ }
+}
+
+void ConnectionHandlerImpl::SetHeartBeatTimeout(uint32_t connection_key,
+ int32_t timeout) {
+ uint32_t connection_handle = 0;
+ uint8_t session_id = 0;
+ PairFromKey(connection_key, &connection_handle, &session_id);
+ sync_primitives::AutoLock lock(connection_list_lock_);
+ ConnectionList::iterator it = connection_list_.find(connection_handle);
+ if (connection_list_.end() != it) {
+ it->second->SetHeartBeatTimeout(timeout);
+ }
+}
+
+void ConnectionHandlerImpl::SendHeartBeat(ConnectionHandle connection_handle,
+ uint8_t session_id) {
+ transport_manager::ConnectionUID connection_uid =
+ ConnectionUIDFromHandle(connection_handle);
+ if (protocol_handler_) {
+ protocol_handler_->SendHeartBeat(connection_uid, session_id);
+ }
+}
+
+void ConnectionHandlerImpl::KeepConnectionAlive(uint32_t connection_key,
+ uint8_t session_id) {
+ sync_primitives::AutoLock lock(connection_list_lock_);
+
+ ConnectionList::iterator it = connection_list_.find(connection_key);
+ if (connection_list_.end() != it) {
+ it->second->KeepAlive(session_id);
+ }
+}
+
+void ConnectionHandlerImpl::OnConnectionEnded(
+ const transport_manager::ConnectionUID &connection_id) {
+ LOG4CXX_INFO(logger_, "Delete Connection: " << static_cast<int32_t>(connection_id)
+ << " from the list.");
+
+ sync_primitives::AutoLock lock(connection_list_lock_);
+ ConnectionList::iterator itr = connection_list_.find(connection_id);
+ if (connection_list_.end() == itr) {
+ LOG4CXX_ERROR(logger_, "Connection not found!");
+ return;
+ }
+
+ if (connection_handler_observer_) {
+ const Connection *connection = itr->second;
+ const SessionMap session_map = connection->session_map();
+
+ for (SessionMap::const_iterator session_it = session_map.begin();
+ session_map.end() != session_it; ++session_it) {
+ const uint32_t session_key = KeyFromPair(connection_id, session_it->first);
+ const ServiceList &service_list = session_it->second.service_list;
+ for (ServiceList::const_iterator service_it = service_list.begin(), end =
+ service_list.end(); service_it != end; ++service_it) {
+ connection_handler_observer_->OnServiceEndedCallback(
+ session_key, service_it->service_type);
+ }
+ }
+ }
+ delete itr->second;
+ connection_list_.erase(itr);
+}
+
+void ConnectionHandlerImpl::BindProtocolVersionWithSession(
+ uint32_t connection_key, uint8_t protocol_version) {
+ LOG4CXX_INFO(logger_, "ConnectionHandlerImpl::BindProtocolVersionWithSession()");
+ uint32_t connection_handle = 0;
+ uint8_t session_id = 0;
+ PairFromKey(connection_key, &connection_handle, &session_id);
+
+ sync_primitives::AutoLock lock(connection_list_lock_);
+ ConnectionList::iterator it = connection_list_.find(connection_handle);
+ if (connection_list_.end() != it) {
+ it->second->UpdateProtocolVersionSession(session_id, protocol_version);
+ }
+}
+
+bool ConnectionHandlerImpl::IsHeartBeatSupported(
+ transport_manager::ConnectionUID connection_handle,uint8_t session_id) {
+ LOG4CXX_INFO(logger_, "ConnectionHandlerImpl::IsHeartBeatSupported()");
+ sync_primitives::AutoLock lock(connection_list_lock_);
+ uint32_t connection = static_cast<uint32_t>(connection_handle);
+ ConnectionList::iterator it = connection_list_.find(connection);
+ if (connection_list_.end() == it) {
+ LOG4CXX_WARN(logger_, "Connection not found !");
+ return false;
+ }
+ return it->second->SupportHeartBeat(session_id);
+}
+
+#ifdef BUILD_TESTS
+ConnectionList &ConnectionHandlerImpl::getConnectionList() {
+ return connection_list_;
+}
+
+void ConnectionHandlerImpl::addDeviceConnection(
+ const transport_manager::DeviceInfo &device_info,
+ const transport_manager::ConnectionUID &connection_id) {
+ // Add Device
+ OnDeviceAdded(device_info);
+ // Add connection
+ OnConnectionEstablished(device_info, connection_id);
+}
+#endif // BUILD_TESTS
+} // namespace connection_handler
diff --git a/src/components/connection_handler/src/device.cc b/src/components/connection_handler/src/device.cc
new file mode 100644
index 0000000000..93638bd370
--- /dev/null
+++ b/src/components/connection_handler/src/device.cc
@@ -0,0 +1,74 @@
+/**
+ * \file Device.cpp
+ * \brief Device class implementation.
+ *
+ * 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.
+ */
+
+#include "connection_handler/device.h"
+#include "encryption/hashing.h"
+#include "utils/logger.h"
+
+/**
+ * \namespace connection_handler
+ * \brief SmartDeviceLink ConnectionHandler namespace.
+ */
+namespace connection_handler {
+
+CREATE_LOGGERPTR_GLOBAL(logger_, "ConnectionHandler")
+
+Device::Device(DeviceHandle device_handle,
+ const std::string &user_friendly_name,
+ const std::string &mac_address, const std::string& connection_type)
+ : device_handle_(device_handle),
+ user_friendly_name_(user_friendly_name),
+ mac_address_(mac_address),
+ connection_type_(connection_type){
+ mac_address_ = encryption::MakeHash(mac_address);
+}
+
+DeviceHandle Device::device_handle() const {
+ return device_handle_;
+}
+
+std::string Device::user_friendly_name() const {
+ return user_friendly_name_;
+}
+
+std::string Device::mac_address() const {
+ return mac_address_;
+}
+
+std::string Device::connection_type() const {
+ return connection_type_;
+}
+
+} // namespace connection_handler
diff --git a/src/components/connection_handler/src/heartbeat_monitor.cc b/src/components/connection_handler/src/heartbeat_monitor.cc
new file mode 100644
index 0000000000..6a5a9e723e
--- /dev/null
+++ b/src/components/connection_handler/src/heartbeat_monitor.cc
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2013-2014, 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.
+ */
+#include "connection_handler/heartbeat_monitor.h"
+
+#include <unistd.h>
+
+#include "utils/logger.h"
+#include "connection_handler/connection.h"
+
+namespace connection_handler {
+
+using namespace sync_primitives;
+
+CREATE_LOGGERPTR_GLOBAL(logger_, "HeartBeatMonitor")
+
+HeartBeatMonitor::HeartBeatMonitor(int32_t heartbeat_timeout_seconds,
+ Connection *connection)
+ : heartbeat_timeout_seconds_(heartbeat_timeout_seconds),
+ connection_(connection),
+ sessions_list_lock_(true),
+ run_(true) {
+}
+
+bool HeartBeatMonitor::HasTimeoutElapsed(const TimevalStruct& expiration) const {
+ TimevalStruct now = date_time::DateTime::getCurrentTime();
+ return date_time::DateTime::Greater(now, expiration);
+}
+
+void HeartBeatMonitor::Process() {
+ AutoLock auto_lock(sessions_list_lock_);
+
+ SessionMap::iterator it = sessions_.begin();
+ while (it != sessions_.end()) {
+ SessionState &state = it->second;
+ if (HasTimeoutElapsed(state.heartbeat_expiration)) {
+ const uint8_t session_id = it->first;
+ if (state.is_heartbeat_sent) {
+ LOG4CXX_DEBUG(logger_,
+ "Session with id " << static_cast<int32_t>(session_id) << " timed out, closing");
+ connection_->CloseSession(session_id);
+ it = sessions_.begin();
+ continue;
+ } else {
+ LOG4CXX_DEBUG(logger_,
+ "Send heart beat into session with id " << static_cast<int32_t>(session_id));
+ RefreshExpiration(&state.heartbeat_expiration);
+ connection_->SendHeartBeat(it->first);
+ state.is_heartbeat_sent = true;
+ }
+ }
+
+ ++it;
+ }
+}
+
+void HeartBeatMonitor::RefreshExpiration(TimevalStruct* expiration) const {
+ LOG4CXX_TRACE_ENTER(logger_);
+ sync_primitives::AutoLock locker(heartbeat_timeout_seconds_lock_);
+ DCHECK(expiration);
+ *expiration = date_time::DateTime::getCurrentTime();
+ expiration->tv_sec += heartbeat_timeout_seconds_;
+ LOG4CXX_TRACE_EXIT(logger_);
+}
+
+void HeartBeatMonitor::threadMain() {
+ AutoLock main_lock(main_thread_lock_);
+ LOG4CXX_DEBUG(
+ logger_,
+ "Start heart beat monitor. Timeout is " << heartbeat_timeout_seconds_);
+ while (run_) {
+ usleep(kDefaultCycleTimeout);
+ Process();
+ }
+}
+
+void HeartBeatMonitor::AddSession(uint8_t session_id) {
+ LOG4CXX_DEBUG(logger_, "Add session with id " << static_cast<int32_t>(session_id));
+ AutoLock auto_lock(sessions_list_lock_);
+ if (sessions_.end() != sessions_.find(session_id)) {
+ LOG4CXX_WARN(
+ logger_,
+ "Session with id " << static_cast<int32_t>(session_id) << " already exists");
+ return;
+ }
+ SessionState session_state;
+ RefreshExpiration(&session_state.heartbeat_expiration);
+ session_state.is_heartbeat_sent = false;
+ sessions_[session_id] = session_state;
+
+ LOG4CXX_INFO(
+ logger_,
+ "Start heartbeat for session " << static_cast<int32_t>(session_id));
+}
+
+void HeartBeatMonitor::RemoveSession(uint8_t session_id) {
+ AutoLock auto_lock(sessions_list_lock_);
+
+ if (sessions_.end() != sessions_.find(session_id)) {
+ LOG4CXX_INFO(logger_,
+ "Remove session with id " << static_cast<int32_t>(session_id));
+ sessions_.erase(session_id);
+ }
+}
+
+void HeartBeatMonitor::KeepAlive(uint8_t session_id) {
+ AutoLock auto_lock(sessions_list_lock_);
+
+ if (sessions_.end() != sessions_.find(session_id)) {
+ LOG4CXX_INFO(
+ logger_,
+ "Resetting heart beat timer for session with id " << static_cast<int32_t>(session_id));
+
+ RefreshExpiration(&sessions_[session_id].heartbeat_expiration);
+ sessions_[session_id].is_heartbeat_sent = false;
+ }
+}
+
+bool HeartBeatMonitor::exitThreadMain() {
+ LOG4CXX_TRACE_ENTER(logger_);
+ run_ = false;
+ AutoLock main_lock(main_thread_lock_);
+ LOG4CXX_TRACE_EXIT(logger_);
+ return true;
+}
+
+void HeartBeatMonitor::set_heartbeat_timeout_seconds(int32_t timeout) {
+ LOG4CXX_DEBUG(logger_, "Set new heart beat timeout " << timeout);
+ {
+ AutoLock locker(heartbeat_timeout_seconds_lock_);
+ heartbeat_timeout_seconds_ = timeout;
+ }
+
+ AutoLock session_locker(sessions_list_lock_);
+ for (SessionMap::iterator i = sessions_.begin(); i != sessions_.end(); ++i) {
+ SessionState& session_state = i->second;
+ RefreshExpiration(&session_state.heartbeat_expiration);
+ }
+}
+
+} // namespace connection_handler