summaryrefslogtreecommitdiff
path: root/SDL_Core/src/components/TransportManager/src
diff options
context:
space:
mode:
Diffstat (limited to 'SDL_Core/src/components/TransportManager/src')
-rw-r--r--SDL_Core/src/components/TransportManager/src/CBluetoothAdapter.cpp573
-rw-r--r--SDL_Core/src/components/TransportManager/src/CBluetoothAdapter.hpp225
-rw-r--r--SDL_Core/src/components/TransportManager/src/CDeviceAdapter.cpp866
-rw-r--r--SDL_Core/src/components/TransportManager/src/CDeviceAdapter.hpp555
-rw-r--r--SDL_Core/src/components/TransportManager/src/CTCPAdapter.cpp317
-rw-r--r--SDL_Core/src/components/TransportManager/src/CTCPAdapter.hpp181
-rw-r--r--SDL_Core/src/components/TransportManager/src/CTransportManager.cpp1311
-rw-r--r--SDL_Core/src/components/TransportManager/src/CTransportManager.hpp837
-rw-r--r--SDL_Core/src/components/TransportManager/src/IDeviceAdapter.cpp39
-rw-r--r--SDL_Core/src/components/TransportManager/src/IDeviceAdapter.hpp109
-rw-r--r--SDL_Core/src/components/TransportManager/src/IDeviceAdapterListener.cpp59
-rw-r--r--SDL_Core/src/components/TransportManager/src/IDeviceAdapterListener.hpp126
-rw-r--r--SDL_Core/src/components/TransportManager/src/IHandleGenerator.cpp39
-rw-r--r--SDL_Core/src/components/TransportManager/src/IHandleGenerator.hpp79
-rw-r--r--SDL_Core/src/components/TransportManager/src/ITransportManager.cpp44
-rw-r--r--SDL_Core/src/components/TransportManager/src/ITransportManagerDataListener.cpp47
-rw-r--r--SDL_Core/src/components/TransportManager/src/ITransportManagerDeviceListener.cpp52
-rw-r--r--SDL_Core/src/components/TransportManager/src/SDeviceInfo.cpp67
-rw-r--r--SDL_Core/src/components/TransportManager/src/SInternalDeviceInfo.cpp49
-rw-r--r--SDL_Core/src/components/TransportManager/src/SInternalDeviceInfo.hpp88
-rw-r--r--SDL_Core/src/components/TransportManager/src/TransportManagerLoggerHelpers.hpp53
21 files changed, 5716 insertions, 0 deletions
diff --git a/SDL_Core/src/components/TransportManager/src/CBluetoothAdapter.cpp b/SDL_Core/src/components/TransportManager/src/CBluetoothAdapter.cpp
new file mode 100644
index 000000000..c914fee94
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/CBluetoothAdapter.cpp
@@ -0,0 +1,573 @@
+/**
+ * \file CBluetoothAdapter.cpp
+ * \brief Class CBluetoothAdapter.
+ * 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 <errno.h>
+#include <iomanip>
+#include <set>
+#include <unistd.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+#include <bluetooth/rfcomm.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "IDeviceAdapterListener.hpp"
+#include "IHandleGenerator.hpp"
+#include "CBluetoothAdapter.hpp"
+
+NsSmartDeviceLink::NsTransportManager::CBluetoothAdapter::SBluetoothDevice::SBluetoothDevice(const bdaddr_t & Address, const char * Name, const NsSmartDeviceLink::NsTransportManager::CBluetoothAdapter::tRFCOMMChannelVector & SmartDeviceLinkRFCOMMChannels):
+SDevice(Name),
+mAddress(Address),
+mSmartDeviceLinkRFCOMMChannels(SmartDeviceLinkRFCOMMChannels)
+{
+ mUniqueDeviceId = getUniqueDeviceId(Address);
+}
+
+bool NsSmartDeviceLink::NsTransportManager::CBluetoothAdapter::SBluetoothDevice::isSameAs(const NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SDevice * OtherDevice) const
+{
+ bool result = false;
+
+ if (true == SDevice::isSameAs(OtherDevice))
+ {
+ const SBluetoothDevice * otherBluetoothDevice = dynamic_cast<const SBluetoothDevice *>(OtherDevice);
+
+ if (0 != otherBluetoothDevice)
+ {
+ result = (0 == memcmp(&mAddress, &otherBluetoothDevice->mAddress, sizeof(bdaddr_t)));
+ }
+ }
+
+ return result;
+}
+
+NsSmartDeviceLink::NsTransportManager::CBluetoothAdapter::SRFCOMMConnection::SRFCOMMConnection(const NsSmartDeviceLink::NsTransportManager::tDeviceHandle DeviceHandle, const uint8_t RFCOMMChannel):
+SConnection(DeviceHandle),
+mRFCOMMChannel(RFCOMMChannel)
+{
+}
+
+bool NsSmartDeviceLink::NsTransportManager::CBluetoothAdapter::SRFCOMMConnection::isSameAs(const NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SConnection * OtherConnection) const
+{
+ bool result = false;
+
+ if (true == SConnection::isSameAs(OtherConnection))
+ {
+ const SRFCOMMConnection * otherRFCOMMConnection = dynamic_cast<const SRFCOMMConnection *>(OtherConnection);
+
+ if (0 != otherRFCOMMConnection)
+ {
+ result = (mRFCOMMChannel == otherRFCOMMConnection->mRFCOMMChannel);
+ }
+ }
+
+ return result;
+}
+
+NsSmartDeviceLink::NsTransportManager::CBluetoothAdapter::CBluetoothAdapter(NsSmartDeviceLink::NsTransportManager::IDeviceAdapterListener & Listener, IHandleGenerator & HandleGenerator):
+CDeviceAdapter(Listener, HandleGenerator),
+mSmartDeviceLinkServiceUUID()
+{
+ LOG4CPLUS_INFO(mLogger, "BluetoothAdapter constructed");
+
+ uint8_t SmartDeviceLinkServiceUUIDData[] = {0x93, 0x6D, 0xA0, 0x1F, 0x9A, 0xBD, 0x4D, 0x9D, 0x80, 0xC7, 0x02, 0xAF, 0x85, 0xC8, 0x22, 0xA8};
+ sdp_uuid128_create(&mSmartDeviceLinkServiceUUID, SmartDeviceLinkServiceUUIDData);
+}
+
+NsSmartDeviceLink::NsTransportManager::CBluetoothAdapter::~CBluetoothAdapter(void)
+{
+ LOG4CPLUS_INFO(mLogger, "BluetoothAdapter destructor");
+
+ waitForThreadsTermination();
+}
+
+NsSmartDeviceLink::NsTransportManager::EDeviceType NsSmartDeviceLink::NsTransportManager::CBluetoothAdapter::getDeviceType(void) const
+{
+ return DeviceBluetooth;
+}
+
+void NsSmartDeviceLink::NsTransportManager::CBluetoothAdapter::createConnectionsListForDevice(const NsSmartDeviceLink::NsTransportManager::tDeviceHandle DeviceHandle, std::vector< NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SConnection* >& ConnectionsList)
+{
+ bdaddr_t deviceAddress;
+ tRFCOMMChannelVector rfcommChannels;
+ bool isDeviceValid = false;
+
+ ConnectionsList.clear();
+
+ pthread_mutex_lock(&mDevicesMutex);
+
+ tDeviceMap::iterator deviceIterator = mDevices.find(DeviceHandle);
+
+ if (mDevices.end() != deviceIterator)
+ {
+ SBluetoothDevice * device = dynamic_cast<SBluetoothDevice*>(deviceIterator->second);
+
+ if (0 != device)
+ {
+ memcpy(&deviceAddress, &device->mAddress, sizeof(bdaddr_t));
+ rfcommChannels = device->mSmartDeviceLinkRFCOMMChannels;
+ isDeviceValid = true;
+ }
+ else
+ {
+ LOG4CPLUS_WARN(mLogger, "Device " << DeviceHandle << " is invalid");
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Device handle " << DeviceHandle << " is invalid");
+ }
+
+ pthread_mutex_unlock(&mDevicesMutex);
+
+ if (true == isDeviceValid)
+ {
+ if (false == rfcommChannels.empty())
+ {
+ pthread_mutex_lock(&mConnectionsMutex);
+
+ for (tConnectionMap::const_iterator connectionIterator = mConnections.begin(); connectionIterator != mConnections.end(); ++connectionIterator)
+ {
+ const SRFCOMMConnection * connection = dynamic_cast<SRFCOMMConnection*>(connectionIterator->second);
+
+ if (0 != connection)
+ {
+ rfcommChannels.erase(std::remove_if(rfcommChannels.begin(),
+ rfcommChannels.end(),
+ [&DeviceHandle, &connection] (const uint8_t & Channel)
+ {
+ return (connection->mDeviceHandle == DeviceHandle) &&
+ (connection->mRFCOMMChannel == Channel);
+ }
+ ),
+ rfcommChannels.end());
+ }
+ }
+
+ pthread_mutex_unlock(&mConnectionsMutex);
+
+ for (tRFCOMMChannelVector::const_iterator channelIterator = rfcommChannels.begin(); channelIterator != rfcommChannels.end(); ++channelIterator)
+ {
+ ConnectionsList.push_back(new SRFCOMMConnection(DeviceHandle, *channelIterator));
+ }
+ }
+ else
+ {
+ LOG4CPLUS_WARN(mLogger, "SmartDeviceLink service was not discovered on device " << DeviceHandle);
+ }
+ }
+}
+
+void NsSmartDeviceLink::NsTransportManager::CBluetoothAdapter::mainThread(void)
+{
+ LOG4CPLUS_INFO(mLogger, "Bluetooth adapter main thread initialized");
+
+ const size_t maxDevices = 256u;
+ inquiry_info * inquiryInfoList = new inquiry_info[maxDevices];
+
+ while (false == mShutdownFlag)
+ {
+ tDeviceMap newDevices;
+ tDeviceVector discoveredDevices;
+
+ bool deviceScanRequested = waitForDeviceScanRequest(0);
+
+ if (true == deviceScanRequested)
+ {
+ int deviceID = hci_get_route(0);
+
+ if (deviceID >= 0)
+ {
+ int deviceHandle = hci_open_dev(deviceID);
+
+ if (deviceHandle >= 0)
+ {
+ const uint8_t inquiryTime = 8u; // Time unit is 1.28 seconds
+
+ LOG4CPLUS_INFO(mLogger, "Starting hci_inquiry on device " << deviceID);
+
+ int numberOfDevices = hci_inquiry(deviceID, inquiryTime, maxDevices, 0, &inquiryInfoList, IREQ_CACHE_FLUSH);
+
+ if (numberOfDevices >= 0)
+ {
+ LOG4CPLUS_INFO(mLogger, "hci_inquiry: found " << numberOfDevices << " devices");
+
+ for (int i = 0; i < numberOfDevices; ++i)
+ {
+ tRFCOMMChannelVector SmartDeviceLinkRFCOMMChannels;
+ discoverSmartDeviceLinkRFCOMMChannels(inquiryInfoList[i].bdaddr, SmartDeviceLinkRFCOMMChannels);
+
+ if (false == SmartDeviceLinkRFCOMMChannels.empty())
+ {
+ char deviceName[256];
+
+ if (0 != hci_read_remote_name(deviceHandle, &inquiryInfoList[i].bdaddr, sizeof(deviceName) / sizeof(deviceName[0]), deviceName, 0))
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "hci_read_remote_name failed");
+ strncpy(deviceName, getUniqueDeviceId(inquiryInfoList[i].bdaddr).c_str(), sizeof(deviceName) / sizeof(deviceName[0]));
+ }
+
+ discoveredDevices.push_back(new SBluetoothDevice(inquiryInfoList[i].bdaddr, deviceName, SmartDeviceLinkRFCOMMChannels));
+ }
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "hci_inquiry failed");
+ }
+
+ close(deviceHandle);
+ }
+ }
+
+ for (tDeviceVector::iterator discoveredDeviceIterator = discoveredDevices.begin(); discoveredDeviceIterator != discoveredDevices.end(); ++discoveredDeviceIterator)
+ {
+ SDevice * discoveredDevice = *discoveredDeviceIterator;
+
+ if (0 != discoveredDevice)
+ {
+ tDeviceHandle deviceHandle = InvalidDeviceHandle;
+
+ pthread_mutex_lock(&mDevicesMutex);
+
+ for (tDeviceMap::iterator deviceIterator = mDevices.begin(); deviceIterator != mDevices.end(); ++deviceIterator)
+ {
+ SDevice * exisingDevice = deviceIterator->second;
+
+ if (true == discoveredDevice->isSameAs(exisingDevice))
+ {
+ deviceHandle = deviceIterator->first;
+ break;
+ }
+ }
+
+ pthread_mutex_unlock(&mDevicesMutex);
+
+ if (InvalidDeviceHandle == deviceHandle)
+ {
+ deviceHandle = mHandleGenerator.generateNewDeviceHandle();
+
+ LOG4CPLUS_INFO(mLogger, "Adding new device " << deviceHandle << " (\"" << discoveredDevice->mName << "\")");
+ }
+
+ newDevices[deviceHandle] = discoveredDevice;
+ }
+ }
+
+ pthread_mutex_lock(&mConnectionsMutex);
+
+ std::set<tDeviceHandle> connectedDevices;
+
+ for (tConnectionMap::const_iterator connectionIterator = mConnections.begin(); connectionIterator != mConnections.end(); ++connectionIterator)
+ {
+ const SConnection * connection = connectionIterator->second;
+
+ if (0 != connection)
+ {
+ if (connectedDevices.end() == connectedDevices.find(connection->mDeviceHandle))
+ {
+ connectedDevices.insert(connection->mDeviceHandle);
+ }
+ }
+ }
+
+ pthread_mutex_unlock(&mConnectionsMutex);
+
+ pthread_mutex_lock(&mDevicesMutex);
+
+ for (tDeviceMap::iterator deviceIterator = mDevices.begin(); deviceIterator != mDevices.end(); ++deviceIterator)
+ {
+ SDevice * device = deviceIterator->second;
+
+ if (0 != device)
+ {
+ if (newDevices.end() == newDevices.find(deviceIterator->first))
+ {
+ if (connectedDevices.end() != connectedDevices.find(deviceIterator->first))
+ {
+ newDevices[deviceIterator->first] = device;
+ device = 0;
+ }
+ }
+
+ if (0 != device)
+ {
+ delete device;
+ }
+ }
+ }
+
+ mDevices = newDevices;
+
+ pthread_mutex_unlock(&mDevicesMutex);
+
+ LOG4CPLUS_INFO(mLogger, "Discovered " << newDevices.size() << " device" << ((1u == newDevices.size()) ? "" : "s") << " with SmartDeviceLink service. New devices map:");
+
+ for (tDeviceMap::iterator deviceIterator = newDevices.begin(); deviceIterator != newDevices.end(); ++deviceIterator)
+ {
+ SDevice * device = deviceIterator->second;
+
+ if (0 != device)
+ {
+ LOG4CPLUS_INFO(mLogger, std::setw(10) << deviceIterator->first << std::setw(0) << ": " << device->mUniqueDeviceId << ", " << device->mName.c_str());
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, std::setw(10) << deviceIterator->first << std::setw(0) << ": Device is null");
+ }
+ }
+
+ mDeviceScanRequested = false;
+
+ updateClientDeviceList();
+ }
+ }
+
+ delete [] inquiryInfoList;
+
+ LOG4CPLUS_INFO(mLogger, "Bluetooth adapter main thread finished");
+}
+
+void NsSmartDeviceLink::NsTransportManager::CBluetoothAdapter::connectionThread(const NsSmartDeviceLink::NsTransportManager::tConnectionHandle ConnectionHandle)
+{
+ LOG4CPLUS_INFO(mLogger, "Connection thread started for connection " << ConnectionHandle);
+
+ tDeviceHandle deviceHandle = InvalidDeviceHandle;
+ struct sockaddr_rc remoteSocketAddress = {0};
+ remoteSocketAddress.rc_family = AF_BLUETOOTH;
+
+ pthread_mutex_lock(&mConnectionsMutex);
+
+ SRFCOMMConnection * connection = 0;
+ tConnectionMap::const_iterator connectionIterator = mConnections.find(ConnectionHandle);
+
+ if (connectionIterator != mConnections.end())
+ {
+ connection = dynamic_cast<SRFCOMMConnection*>(connectionIterator->second);
+
+ if (0 != connection)
+ {
+ deviceHandle = connection->mDeviceHandle;
+ remoteSocketAddress.rc_channel = connection->mRFCOMMChannel;
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Connection " << ConnectionHandle << " is not valid");
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Connection " << ConnectionHandle << " does not exist");
+ }
+
+ pthread_mutex_unlock(&mConnectionsMutex);
+
+ if (0 != connection)
+ {
+ if (InvalidDeviceHandle != deviceHandle)
+ {
+ bool isDeviceValid = false;
+
+ pthread_mutex_lock(&mDevicesMutex);
+
+ tDeviceMap::const_iterator deviceIterator = mDevices.find(deviceHandle);
+
+ if (deviceIterator != mDevices.end())
+ {
+ const SBluetoothDevice * device = dynamic_cast<const SBluetoothDevice*>(deviceIterator->second);
+
+ if (0 != device)
+ {
+ isDeviceValid = true;
+ memcpy(&remoteSocketAddress.rc_bdaddr, &device->mAddress, sizeof(bdaddr_t));
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Device " << deviceHandle << " is not valid");
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Device " << deviceHandle << " does not exist");
+ }
+
+ pthread_mutex_unlock(&mDevicesMutex);
+
+ if (true == isDeviceValid)
+ {
+ int rfcommSocket = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+
+ if (-1 != rfcommSocket)
+ {
+ if (0 == connect(rfcommSocket, (struct sockaddr *)&remoteSocketAddress, sizeof(remoteSocketAddress)))
+ {
+ connection->mConnectionSocket = rfcommSocket;
+ handleCommunication(ConnectionHandle);
+ }
+ else
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "Failed to connect to remote device " << getUniqueDeviceId(remoteSocketAddress.rc_bdaddr) << " for connection " << ConnectionHandle);
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "Failed to create RFCOMM socket for connection " << ConnectionHandle);
+ }
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Device handle for connection " << ConnectionHandle << " is invalid");
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Connection " << ConnectionHandle << " is null");
+ }
+
+ LOG4CPLUS_INFO(mLogger, "Removing connection " << ConnectionHandle << " from connection map");
+
+ pthread_mutex_lock(&mConnectionsMutex);
+ mConnections.erase(ConnectionHandle);
+ pthread_mutex_unlock(&mConnectionsMutex);
+
+ delete connection;
+
+ LOG4CPLUS_INFO(mLogger, "Connection thread finished for connection " << ConnectionHandle);
+}
+
+std::string NsSmartDeviceLink::NsTransportManager::CBluetoothAdapter::getUniqueDeviceId(const bdaddr_t & DeviceAddress)
+{
+ char deviceAddressString[32];
+
+ ba2str(&DeviceAddress, deviceAddressString);
+
+ return std::string("BT-") + deviceAddressString;
+}
+
+void NsSmartDeviceLink::NsTransportManager::CBluetoothAdapter::discoverSmartDeviceLinkRFCOMMChannels(const bdaddr_t & DeviceAddress, NsSmartDeviceLink::NsTransportManager::CBluetoothAdapter::tRFCOMMChannelVector & SmartDeviceLinkRFCOMMChannels)
+{
+ SmartDeviceLinkRFCOMMChannels.clear();
+
+ static bdaddr_t anyAddress = {{0, 0, 0, 0, 0, 0}};
+
+ sdp_session_t * sdpSession = sdp_connect(&anyAddress, &DeviceAddress, SDP_RETRY_IF_BUSY);
+
+ if (0 != sdpSession)
+ {
+ sdp_list_t * searchList = sdp_list_append(0, &mSmartDeviceLinkServiceUUID);
+ uint32_t range = 0x0000ffff;
+ sdp_list_t * attrList = sdp_list_append(0, &range);
+ sdp_list_t * responseList = 0;
+
+ if (0 == sdp_service_search_attr_req(sdpSession, searchList, SDP_ATTR_REQ_RANGE, attrList, &responseList))
+ {
+ for (sdp_list_t * r = responseList; 0 != r; r = r->next)
+ {
+ sdp_record_t * sdpRecord = static_cast<sdp_record_t*>(r->data);
+ sdp_list_t * protoList = 0;
+
+ if (0 == sdp_get_access_protos(sdpRecord, &protoList))
+ {
+ for (sdp_list_t * p = protoList; 0 != p; p = p->next)
+ {
+ sdp_list_t * pdsList = static_cast<sdp_list_t*>(p->data);
+
+ for (sdp_list_t * pds = pdsList; 0 != pds; pds = pds->next)
+ {
+ sdp_data_t * sdpData = static_cast<sdp_data_t*>(pds->data);
+ int proto = 0;
+
+ for (sdp_data_t * d = sdpData; 0 != d; d = d->next)
+ {
+ switch (d->dtd)
+ {
+ case SDP_UUID16:
+ case SDP_UUID32:
+ case SDP_UUID128:
+ proto = sdp_uuid_to_proto(&d->val.uuid);
+ break;
+
+ case SDP_UINT8:
+ if (RFCOMM_UUID == proto)
+ {
+ SmartDeviceLinkRFCOMMChannels.push_back(d->val.uint8);
+ }
+ break;
+ }
+ }
+ }
+
+ sdp_list_free(pdsList, 0);
+ }
+
+ sdp_list_free(protoList, 0);
+ }
+ }
+ }
+
+ sdp_list_free(searchList, 0);
+ sdp_list_free(attrList, 0);
+ sdp_list_free(responseList, 0);
+ sdp_close(sdpSession);
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Service discovery failed for " << getUniqueDeviceId(DeviceAddress));
+ }
+
+ if (false == SmartDeviceLinkRFCOMMChannels.empty())
+ {
+ std::stringstream rfcommChannelsString;
+
+ for (tRFCOMMChannelVector::const_iterator channelIterator = SmartDeviceLinkRFCOMMChannels.begin(); channelIterator != SmartDeviceLinkRFCOMMChannels.end(); ++channelIterator)
+ {
+ if (channelIterator != SmartDeviceLinkRFCOMMChannels.begin())
+ {
+ rfcommChannelsString << ", ";
+ }
+
+ rfcommChannelsString << static_cast<uint32_t>(*channelIterator);
+ }
+
+ LOG4CPLUS_INFO(mLogger, "SmartDeviceLink service was discovered on device " << getUniqueDeviceId(DeviceAddress) << " at channel(s): " << rfcommChannelsString.str().c_str());
+ }
+ else
+ {
+ LOG4CPLUS_INFO(mLogger, "SmartDeviceLink service was not discovered on device " << getUniqueDeviceId(DeviceAddress));
+ }
+}
diff --git a/SDL_Core/src/components/TransportManager/src/CBluetoothAdapter.hpp b/SDL_Core/src/components/TransportManager/src/CBluetoothAdapter.hpp
new file mode 100644
index 000000000..43f0b96ef
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/CBluetoothAdapter.hpp
@@ -0,0 +1,225 @@
+/**
+ * \file CBluetoothAdapter.hpp
+ * \brief Class CBluetoothAdapter header.
+ * 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 __TRANSPORTMANAGER_CBLUETOOTHADAPTER_HPP__
+#define __TRANSPORTMANAGER_CBLUETOOTHADAPTER_HPP__
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/sdp.h>
+#include <time.h>
+
+#include "Logger.hpp"
+
+#include "TransportManager/SDeviceInfo.hpp"
+
+#include "CDeviceAdapter.hpp"
+
+namespace NsSmartDeviceLink
+{
+ namespace NsTransportManager
+ {
+ /**
+ * @brief Bluetooth device adapter.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_bluetooth_adapter
+ **/
+ class CBluetoothAdapter: public CDeviceAdapter
+ {
+ public:
+ /**
+ * @brief Constructor.
+ *
+ * @param Listener Listener for device adapter notifications.
+ * @param HandleGenerator Handle generator implementation.
+ **/
+ CBluetoothAdapter(IDeviceAdapterListener & Listener, IHandleGenerator & HandleGenerator);
+
+ /**
+ * @brief Destructor.
+ **/
+ virtual ~CBluetoothAdapter(void);
+
+ /**
+ * @brief Get type of devices handled by this device adapter.
+ *
+ * @return Device type.
+ **/
+ virtual EDeviceType getDeviceType(void) const;
+
+ private:
+ /**
+ * @brief Vector of RFCOMM channels.
+ **/
+ typedef std::vector<uint8_t> tRFCOMMChannelVector;
+
+ /**
+ * @brief Internal structure describing bluetooth device.
+ **/
+ struct SBluetoothDevice: public SDevice
+ {
+ /**
+ * @brief Constructor.
+ *
+ * @param Address Bluetooth address.
+ * @param Name User-friendly device name.
+ * @param SmartDeviceLinkRFCOMMChannels List of RFCOMM channels where SmartDeviceLink service has been discovered.
+ **/
+ SBluetoothDevice(const bdaddr_t & Address, const char * Name, const tRFCOMMChannelVector & SmartDeviceLinkRFCOMMChannels);
+
+ /**
+ * @brief Compare devices.
+ *
+ * This method checks whether two SBluetoothDevice structures
+ * refer to the same device.
+ *
+ * @param OtherDevice Device to compare with.
+ *
+ * @return true if devices are equal, false otherwise.
+ **/
+ virtual bool isSameAs(const SDevice * OtherDevice) const;
+
+ /**
+ * @brief Device bluetooth address.
+ **/
+ bdaddr_t mAddress;
+
+ /**
+ * @brief List of RFCOMM channels where SmartDeviceLink service has been discovered.
+ **/
+ tRFCOMMChannelVector mSmartDeviceLinkRFCOMMChannels;
+ };
+
+ /**
+ * @brief RFCOMM connection.
+ **/
+ struct SRFCOMMConnection: public SConnection
+ {
+ /**
+ * @brief Constructor.
+ *
+ * @param DeviceHandle Device handle.
+ * @param RFCOMMChannel RFCOMM channel of SmartDeviceLink service on remote device.
+ **/
+ SRFCOMMConnection(const tDeviceHandle DeviceHandle, const uint8_t RFCOMMChannel);
+
+ /**
+ * @brief Compare connections.
+ *
+ * This method compares whether two SRFCOMMConnection structures
+ * refer to the same connection.
+ *
+ * @param OtherConnection Connection to compare with.
+ *
+ * @return true if connections are equal, false otherwise.
+ **/
+ virtual bool isSameAs(const SConnection * OtherConnection) const;
+
+ /**
+ * @brief RFCOMM channel of remote device.
+ **/
+ const uint8_t mRFCOMMChannel;
+ };
+
+ /**
+ * @brief Create list of connections possible for specified device.
+ *
+ * This method is called from connectDevice(). This implementation will
+ * perform service discovery and create connection structures for all
+ * RFCOMM channels where SmartDeviceLink service is discovered.
+ *
+ * @param DeviceHandle Device handle.
+ * @param ConnectionsList Reference to connections list that must be filled.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_bluetooth_adapter_connecting_devices
+ **/
+ virtual void createConnectionsListForDevice(const tDeviceHandle DeviceHandle, std::vector<SConnection*> & ConnectionsList);
+
+ /**
+ * @brief Device discovery thread.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_main_thread
+ * @see @ref components_transportmanager_internal_design_device_adapters_bluetooth_adapter_discovery
+ **/
+ virtual void mainThread(void);
+
+ /**
+ * @brief Connection thread.
+ *
+ * This method is responsible for establishing connection and communicating
+ * with remote device via specified connection. It must remove itself from
+ * connection map when connection is terminated before terminating connection thread.
+ *
+ * @param ConnectionHandle Connection handle.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_connection_thread
+ **/
+ virtual void connectionThread(const tConnectionHandle ConnectionHandle);
+
+ /**
+ * @brief Get unique device ID.
+ *
+ * Get TransportManager-unique identifier of
+ * bluetooth device based on its bluetooth address.
+ *
+ * @param DeviceAddress Address of device.
+ *
+ * @return Unique device identifier.
+ **/
+ static std::string getUniqueDeviceId(const bdaddr_t & DeviceAddress);
+
+ /**
+ * @brief Discover SmartDeviceLink RFCOMM channels.
+ *
+ * Run service discovery for specified remote bluetooth device
+ * and discover RFCOMM channels with SmartDeviceLink service.
+ *
+ * @param DeviceAddress Address of device.
+ * @param SmartDeviceLinkRFCOMMChannels Reference to variable that will
+ * receive list of RFCOMM channels
+ * with SmartDeviceLink service discovered.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_bluetooth_adapter_discovery
+ * @see @ref components_transportmanager_internal_design_device_adapters_bluetooth_adapter_connecting_devices
+ **/
+ void discoverSmartDeviceLinkRFCOMMChannels(const bdaddr_t & DeviceAddress, tRFCOMMChannelVector & SmartDeviceLinkRFCOMMChannels);
+
+ /**
+ * @brief UUID of SmartDeviceLink service.
+ **/
+ uuid_t mSmartDeviceLinkServiceUUID;
+ };
+ }
+}
+
+#endif
diff --git a/SDL_Core/src/components/TransportManager/src/CDeviceAdapter.cpp b/SDL_Core/src/components/TransportManager/src/CDeviceAdapter.cpp
new file mode 100644
index 000000000..32b9e6e88
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/CDeviceAdapter.cpp
@@ -0,0 +1,866 @@
+/**
+ * \file CDeviceAdapter.cpp
+ * \brief Class CDeviceAdapter.
+ * 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 <fcntl.h>
+#include <memory.h>
+#include <poll.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "IDeviceAdapterListener.hpp"
+#include "IHandleGenerator.hpp"
+#include "CDeviceAdapter.hpp"
+
+NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SFrame::SFrame(int UserData, const uint8_t* Data, const size_t DataSize):
+mUserData(UserData),
+mData(0),
+mDataSize(0)
+{
+ if ((0 != Data) &&
+ (0u != DataSize))
+ {
+ mData = new uint8_t[DataSize];
+
+ if (0 != mData)
+ {
+ mDataSize = DataSize;
+ memcpy(mData, Data, DataSize);
+ }
+ }
+}
+
+NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SFrame::~SFrame(void)
+{
+ if (0 != mData)
+ {
+ delete [] mData;
+ }
+}
+
+NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SDevice::SDevice(const char * Name):
+mName(Name),
+mUniqueDeviceId()
+{
+}
+
+NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SDevice::~SDevice(void)
+{
+}
+
+bool NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SDevice::isSameAs(const NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SDevice * OtherDevice) const
+{
+ return true;
+}
+
+NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SConnection::SConnection(const NsSmartDeviceLink::NsTransportManager::tDeviceHandle DeviceHandle):
+mDeviceHandle(DeviceHandle),
+mConnectionThread(),
+mNotificationPipeFds(),
+mConnectionSocket(-1),
+mFramesToSend(),
+mTerminateFlag(false)
+{
+}
+
+NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SConnection::~SConnection(void)
+{
+ while (false == mFramesToSend.empty())
+ {
+ delete mFramesToSend.front();
+ mFramesToSend.pop();
+ }
+}
+
+bool NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SConnection::isSameAs(const NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SConnection * OtherConnection) const
+{
+ bool result = false;
+
+ if (0 != OtherConnection)
+ {
+ result = (mDeviceHandle == OtherConnection->mDeviceHandle);
+ }
+
+ return result;
+}
+
+NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SConnectionThreadParameters::SConnectionThreadParameters(NsSmartDeviceLink::NsTransportManager::CDeviceAdapter & DeviceAdapter, NsSmartDeviceLink::NsTransportManager::tConnectionHandle ConnectionHandle):
+mDeviceAdapter(DeviceAdapter),
+mConnectionHandle(ConnectionHandle)
+{
+}
+
+NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::CDeviceAdapter(NsSmartDeviceLink::NsTransportManager::IDeviceAdapterListener& Listener, IHandleGenerator& HandleGenerator):
+mLogger(log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("TransportManager"))),
+mListener(Listener),
+mHandleGenerator(HandleGenerator),
+mDeviceScanRequested(false),
+mDeviceScanRequestedMutex(),
+mDeviceScanRequestedCond(),
+mDevices(),
+mDevicesMutex(),
+mConnections(),
+mConnectionsMutex(),
+mShutdownFlag(false),
+mMainThread(),
+mMainThreadStarted(false)
+{
+ pthread_cond_init(&mDeviceScanRequestedCond, 0);
+ pthread_mutex_init(&mDeviceScanRequestedMutex, 0);
+ pthread_mutex_init(&mDevicesMutex, 0);
+ pthread_mutex_init(&mConnectionsMutex, 0);
+}
+
+NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::~CDeviceAdapter(void)
+{
+ pthread_mutex_destroy(&mConnectionsMutex);
+ pthread_mutex_destroy(&mDevicesMutex);
+ pthread_mutex_destroy(&mDeviceScanRequestedMutex);
+ pthread_cond_destroy(&mDeviceScanRequestedCond);
+}
+
+void NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::run(void)
+{
+ LOG4CPLUS_INFO(mLogger, "Initializing device adapter");
+
+ int errorCode = pthread_create(&mMainThread, 0, &mainThreadStartRoutine, this);
+
+ if (0 == errorCode)
+ {
+ mMainThreadStarted = true;
+ LOG4CPLUS_INFO(mLogger, "Device adapter main thread started");
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Device adapter main thread start failed, error code " << errorCode);
+ }
+}
+
+void NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::scanForNewDevices(void)
+{
+ pthread_mutex_lock(&mDeviceScanRequestedMutex);
+
+ if (false == mDeviceScanRequested)
+ {
+ LOG4CPLUS_INFO(mLogger, "Requesting device scan");
+
+ mDeviceScanRequested = true;
+ pthread_cond_signal(&mDeviceScanRequestedCond);
+ }
+ else
+ {
+ LOG4CPLUS_INFO(mLogger, "Device scan is currently in progress");
+ }
+
+ pthread_mutex_unlock(&mDeviceScanRequestedMutex);
+}
+
+void NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::connectDevice(const NsSmartDeviceLink::NsTransportManager::tDeviceHandle DeviceHandle)
+{
+ bool isDeviceValid = false;
+
+ pthread_mutex_lock(&mDevicesMutex);
+
+ if (mDevices.end() != mDevices.find(DeviceHandle))
+ {
+ isDeviceValid = true;
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Device handle " << DeviceHandle << " is invalid");
+ }
+
+ pthread_mutex_unlock(&mDevicesMutex);
+
+ if (true == isDeviceValid)
+ {
+ std::vector<SConnection*> connections;
+ createConnectionsListForDevice(DeviceHandle, connections);
+
+ if (false == connections.empty())
+ {
+ LOG4CPLUS_INFO(mLogger, "Connecting device " << DeviceHandle);
+
+ for (std::vector<SConnection*>::iterator connectionIterator = connections.begin(); connectionIterator != connections.end(); ++connectionIterator)
+ {
+ startConnection(*connectionIterator);
+ }
+ }
+ else
+ {
+ LOG4CPLUS_WARN(mLogger, "No connections to establish on device " << DeviceHandle);
+ }
+ }
+}
+
+void NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::disconnectDevice(const NsSmartDeviceLink::NsTransportManager::tDeviceHandle DeviceHandle)
+{
+ bool isDeviceValid = false;
+
+ pthread_mutex_lock(&mDevicesMutex);
+
+ if (mDevices.end() != mDevices.find(DeviceHandle))
+ {
+ isDeviceValid = true;
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Device handle " << DeviceHandle << " is invalid");
+ }
+
+ pthread_mutex_unlock(&mDevicesMutex);
+
+ if (true == isDeviceValid)
+ {
+ std::vector<tConnectionHandle> connectionsToTerminate;
+
+ pthread_mutex_lock(&mConnectionsMutex);
+
+ for (tConnectionMap::const_iterator connectionIterator = mConnections.begin(); connectionIterator != mConnections.end(); ++connectionIterator)
+ {
+ SConnection * connection = connectionIterator->second;
+
+ if (0 != connection)
+ {
+ if (connection->mDeviceHandle == DeviceHandle)
+ {
+ connectionsToTerminate.push_back(connectionIterator->first);
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Connection " << connectionIterator->first << " is null");
+ }
+ }
+
+ pthread_mutex_unlock(&mConnectionsMutex);
+
+ for (std::vector<tConnectionHandle>::const_iterator connectionHandleIterator = connectionsToTerminate.begin(); connectionHandleIterator != connectionsToTerminate.end(); ++connectionHandleIterator)
+ {
+ stopConnection(*connectionHandleIterator);
+ }
+ }
+}
+
+void NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::sendFrame(NsSmartDeviceLink::NsTransportManager::tConnectionHandle ConnectionHandle, const uint8_t * Data, size_t DataSize, int UserData)
+{
+ if (0u == DataSize)
+ {
+ LOG4CPLUS_WARN(mLogger, "DataSize=0");
+ }
+ else if (0 == Data)
+ {
+ LOG4CPLUS_WARN(mLogger, "Data is null");
+ }
+ else
+ {
+ pthread_mutex_lock(&mConnectionsMutex);
+
+ tConnectionMap::iterator connectionIterator = mConnections.find(ConnectionHandle);
+
+ if (mConnections.end() == connectionIterator)
+ {
+ LOG4CPLUS_ERROR(mLogger, "Connection " << ConnectionHandle << " does not exist");
+ }
+ else
+ {
+ SConnection * connection = connectionIterator->second;
+
+ if (0 != connection)
+ {
+ connection->mFramesToSend.push(new SFrame(UserData, Data, DataSize));
+
+ if (-1 != connection->mNotificationPipeFds[1])
+ {
+ uint8_t c = 0;
+ if (1 != write(connection->mNotificationPipeFds[1], &c, 1))
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "Failed to wake up connection thread for connection " << connectionIterator->first);
+ }
+ }
+ }
+ }
+
+ pthread_mutex_unlock(&mConnectionsMutex);
+ }
+}
+
+void NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::waitForThreadsTermination(void)
+{
+ mShutdownFlag = true;
+
+ if (true == mMainThreadStarted)
+ {
+ LOG4CPLUS_INFO(mLogger, "Waiting for device adapter main thread termination");
+ pthread_join(mMainThread, 0);
+ LOG4CPLUS_INFO(mLogger, "Device adapter main thread terminated");
+ }
+
+ std::vector<pthread_t> connectionThreads;
+
+ pthread_mutex_lock(&mConnectionsMutex);
+
+ for (tConnectionMap::iterator connectionIterator = mConnections.begin(); connectionIterator != mConnections.end(); ++connectionIterator)
+ {
+ SConnection * connection = connectionIterator->second;
+
+ if (0 != connection)
+ {
+ connection->mTerminateFlag = true;
+ if (-1 != connection->mNotificationPipeFds[1])
+ {
+ uint8_t c = 0;
+ if (1 != write(connection->mNotificationPipeFds[1], &c, 1))
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "Failed to wake up connection thread for connection " << connectionIterator->first);
+ }
+ }
+ connectionThreads.push_back(connection->mConnectionThread);
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Connection " << connectionIterator->first << " is null");
+ }
+ }
+
+ pthread_mutex_unlock(&mConnectionsMutex);
+
+ LOG4CPLUS_INFO(mLogger, "Waiting for connection threads termination");
+
+ for (std::vector<pthread_t>::iterator connectionThreadIterator = connectionThreads.begin(); connectionThreadIterator != connectionThreads.end(); ++connectionThreadIterator)
+ {
+ pthread_join(*connectionThreadIterator, 0);
+ }
+
+ LOG4CPLUS_INFO(mLogger, "Connection threads terminated");
+}
+
+bool NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::startConnection(NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SConnection * Connection)
+{
+ bool isConnectionThreadStarted = false;
+
+ if (0 != Connection)
+ {
+ tConnectionHandle newConnectionHandle = mHandleGenerator.generateNewConnectionHandle();
+
+ pthread_mutex_lock(&mConnectionsMutex);
+
+ if (false == mShutdownFlag)
+ {
+ tConnectionMap::const_iterator connectionIterator;
+ for (connectionIterator = mConnections.begin(); connectionIterator != mConnections.end(); ++connectionIterator)
+ {
+ const SConnection * existingConnection = connectionIterator->second;
+
+ if (0 != existingConnection)
+ {
+ if (existingConnection->isSameAs(Connection))
+ {
+ LOG4CPLUS_WARN(mLogger, "Connection is already opened (" << connectionIterator->first << ")");
+
+ break;
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Connection " << connectionIterator->first << " is null");
+ }
+ }
+
+ if (mConnections.end() == connectionIterator)
+ {
+ std::pair<tConnectionMap::iterator, bool> insertResult = mConnections.insert(std::make_pair(newConnectionHandle, Connection));
+
+ if (true == insertResult.second)
+ {
+ SConnection * newConnection = insertResult.first->second;
+
+ if (0 != newConnection)
+ {
+ SConnectionThreadParameters * connectionThreadParameters = new SConnectionThreadParameters(*this, newConnectionHandle);
+
+ int errorCode = pthread_create(&newConnection->mConnectionThread, 0, &CDeviceAdapter::connectionThreadStartRoutine, static_cast<void*>(connectionThreadParameters));
+
+ if (0 == errorCode)
+ {
+ LOG4CPLUS_INFO(mLogger, "Connection thread started for connection " << newConnectionHandle << " (device " << newConnection->mDeviceHandle << ")");
+
+ isConnectionThreadStarted = true;
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Connection thread start failed for connection " << newConnectionHandle << " (device " << newConnection->mDeviceHandle << ")");
+
+ delete connectionThreadParameters;
+ mConnections.erase(insertResult.first);
+ delete newConnection;
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Failed to allocate connection " << newConnectionHandle);
+
+ mConnections.erase(newConnectionHandle);
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Connection handle " << newConnectionHandle << " already exists");
+ }
+ }
+ else
+ {
+ delete Connection;
+ }
+ }
+
+ pthread_mutex_unlock(&mConnectionsMutex);
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Connection is null");
+ }
+
+ return isConnectionThreadStarted;
+}
+
+void NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::stopConnection(NsSmartDeviceLink::NsTransportManager::tConnectionHandle ConnectionHandle)
+{
+ pthread_mutex_lock(&mConnectionsMutex);
+
+ tConnectionMap::iterator connectionIterator = mConnections.find(ConnectionHandle);
+
+ if (mConnections.end() != connectionIterator)
+ {
+ SConnection * connection = connectionIterator->second;
+
+ if (0 != connection)
+ {
+ if (false == connection->mTerminateFlag)
+ {
+ connection->mTerminateFlag = true;
+ if (-1 != connection->mNotificationPipeFds[1])
+ {
+ uint8_t c = 0;
+ if (1 != write(connection->mNotificationPipeFds[1], &c, 1))
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "Failed to wake up connection thread for connection " << connectionIterator->first);
+ }
+ }
+
+ LOG4CPLUS_INFO(mLogger, "Connection " << ConnectionHandle << "(device " << connection->mDeviceHandle << ") has been marked for termination");
+ }
+ else
+ {
+ LOG4CPLUS_WARN(mLogger, "Connection " << ConnectionHandle << " is already terminating");
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Connection " << ConnectionHandle << " is null");
+ }
+ }
+ else
+ {
+ LOG4CPLUS_WARN(mLogger, "Connection " << ConnectionHandle << " does not exist");
+ }
+
+ pthread_mutex_unlock(&mConnectionsMutex);
+}
+
+bool NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::waitForDeviceScanRequest(const time_t Timeout)
+{
+ bool deviceScanRequested = false;
+
+ pthread_mutex_lock(&mDeviceScanRequestedMutex);
+
+ if (false == mDeviceScanRequested)
+ {
+ if (0 == Timeout)
+ {
+ if (0 != pthread_cond_wait(&mDeviceScanRequestedCond, &mDeviceScanRequestedMutex))
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "pthread_cond_wait failed");
+ }
+ }
+ else
+ {
+ timespec timeoutTime;
+
+ if (0 == clock_gettime(CLOCK_REALTIME, &timeoutTime))
+ {
+ timeoutTime.tv_sec += Timeout;
+
+ while (0 == pthread_cond_timedwait(&mDeviceScanRequestedCond, &mDeviceScanRequestedMutex, &timeoutTime))
+ {
+ if (true == mDeviceScanRequested)
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "clock_gettime failed");
+
+ sleep(Timeout);
+ }
+ }
+ }
+
+ deviceScanRequested = mDeviceScanRequested;
+
+ pthread_mutex_unlock(&mDeviceScanRequestedMutex);
+
+ return deviceScanRequested;
+}
+
+void NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::handleCommunication(const NsSmartDeviceLink::NsTransportManager::tConnectionHandle ConnectionHandle)
+{
+ SConnection * connection = 0;
+ bool isPipeCreated = false;
+ int notificationPipeReadFd = -1;
+ int connectionSocket = -1;
+ tDeviceHandle deviceHandle = InvalidDeviceHandle;
+
+ pthread_mutex_lock(&mConnectionsMutex);
+
+ tConnectionMap::iterator connectionIterator = mConnections.find(ConnectionHandle);
+
+ if (mConnections.end() != connectionIterator)
+ {
+ connection = connectionIterator->second;
+
+ if (0 != connection)
+ {
+ isPipeCreated = (0 == pipe(connection->mNotificationPipeFds));
+ notificationPipeReadFd = connection->mNotificationPipeFds[0];
+ connectionSocket = connection->mConnectionSocket;
+ deviceHandle = connection->mDeviceHandle;
+ }
+ }
+
+ pthread_mutex_unlock(&mConnectionsMutex);
+
+ if (0 != connection)
+ {
+ if (-1 != connectionSocket)
+ {
+ if (InvalidDeviceHandle != deviceHandle)
+ {
+ bool isDeviceValid = false;
+ SDeviceInfo clientDeviceInfo;
+
+ pthread_mutex_lock(&mDevicesMutex);
+
+ tDeviceMap::const_iterator deviceIterator = mDevices.find(deviceHandle);
+
+ if (deviceIterator != mDevices.end())
+ {
+ const SDevice * device = deviceIterator->second;
+
+ if (0 != device)
+ {
+ isDeviceValid = true;
+
+ clientDeviceInfo.mDeviceHandle = deviceHandle;
+ clientDeviceInfo.mDeviceType = getDeviceType();
+ clientDeviceInfo.mUserFriendlyName = device->mName;
+ clientDeviceInfo.mUniqueDeviceId = device->mUniqueDeviceId;
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Device " << deviceHandle << " is not valid");
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Device " << deviceHandle << " does not exist");
+ }
+
+ pthread_mutex_unlock(&mDevicesMutex);
+
+ if (true == isDeviceValid)
+ {
+ if (true == isPipeCreated)
+ {
+ if (0 == fcntl(notificationPipeReadFd, F_SETFL, fcntl(notificationPipeReadFd, F_GETFL) | O_NONBLOCK))
+ {
+ LOG4CPLUS_INFO(mLogger, "Connection " << ConnectionHandle << " to remote device " << clientDeviceInfo.mUniqueDeviceId << " established");
+
+ mListener.onApplicationConnected(this, clientDeviceInfo, ConnectionHandle);
+
+ pollfd pollFds[2];
+ pollFds[0].fd = connectionSocket;
+ pollFds[0].events = POLLIN | POLLPRI;
+ pollFds[1].fd = connection->mNotificationPipeFds[0];
+ pollFds[1].events = POLLIN | POLLPRI;
+
+ while (false == connection->mTerminateFlag)
+ {
+ if (-1 != poll(pollFds, sizeof(pollFds) / sizeof(pollFds[0]), -1))
+ {
+ if (0 != (pollFds[0].revents & (POLLERR | POLLHUP | POLLNVAL)))
+ {
+ LOG4CPLUS_INFO(mLogger, "Connection " << ConnectionHandle << " terminated");
+
+ connection->mTerminateFlag = true;
+ }
+ else if (0 != (pollFds[1].revents & (POLLERR | POLLHUP | POLLNVAL)))
+ {
+ LOG4CPLUS_ERROR(mLogger, "Notification pipe for connection " << ConnectionHandle << " terminated");
+
+ connection->mTerminateFlag = true;
+ }
+ else
+ {
+ uint8_t buffer[4096];
+ ssize_t bytesRead = -1;
+
+ if (0 != pollFds[0].revents)
+ {
+ do
+ {
+ bytesRead = recv(connectionSocket, buffer, sizeof(buffer), MSG_DONTWAIT);
+
+ if (bytesRead > 0)
+ {
+ LOG4CPLUS_INFO(mLogger, "Received " << bytesRead << " bytes for connection " << ConnectionHandle);
+
+ mListener.onFrameReceived(this, ConnectionHandle, buffer, static_cast<size_t>(bytesRead));
+ }
+ else if (bytesRead < 0)
+ {
+ if ((EAGAIN != errno) &&
+ (EWOULDBLOCK != errno))
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "recv() failed for connection " << ConnectionHandle);
+
+ connection->mTerminateFlag = true;
+ }
+ }
+ else
+ {
+ LOG4CPLUS_INFO(mLogger, "Connection " << ConnectionHandle << " closed by remote peer");
+
+ connection->mTerminateFlag = true;
+ }
+ } while (bytesRead > 0);
+ }
+
+ if ((false == connection->mTerminateFlag) &&
+ (0 != pollFds[1].revents))
+ {
+ do
+ {
+ bytesRead = read(notificationPipeReadFd, buffer, sizeof(buffer));
+ } while (bytesRead > 0);
+
+ if ((bytesRead < 0) &&
+ (EAGAIN != errno))
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "Failed to clear notification pipe for connection " << ConnectionHandle);
+
+ connection->mTerminateFlag = true;
+ }
+
+ tFrameQueue framesToSend;
+
+ pthread_mutex_lock(&mConnectionsMutex);
+ framesToSend.swap(connection->mFramesToSend);
+ pthread_mutex_unlock(&mConnectionsMutex);
+
+ for (; false == framesToSend.empty(); framesToSend.pop())
+ {
+ SFrame * frame = framesToSend.front();
+ ESendStatus frameSendStatus = SendStatusUnknownError;
+
+ if (0 != frame)
+ {
+ if ((0 != frame->mData) &&
+ (0u != frame->mDataSize))
+ {
+ ssize_t bytesSent = send(connectionSocket, frame->mData, frame->mDataSize, 0);
+
+ if (static_cast<size_t>(bytesSent) == frame->mDataSize)
+ {
+ frameSendStatus = SendStatusOK;
+ }
+ else
+ {
+ if (bytesSent >= 0)
+ {
+ LOG4CPLUS_ERROR(mLogger, "Sent " << bytesSent << " bytes while " << frame->mDataSize << " had been requested for connection " << ConnectionHandle);
+ }
+ else
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "Send failed for connection " << ConnectionHandle);
+ }
+
+ frameSendStatus = SendStatusFailed;
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Frame data is invalid for connection " << ConnectionHandle);
+
+ frameSendStatus = SendStatusInternalError;
+ }
+
+ delete frame;
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Frame data is null for connection " << ConnectionHandle);
+
+ frameSendStatus = SendStatusInternalError;
+ }
+
+ mListener.onFrameSendCompleted(this, ConnectionHandle, frame->mUserData, frameSendStatus);
+ }
+ }
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "poll() failed for connection " << ConnectionHandle);
+
+ connection->mTerminateFlag = true;
+ }
+ }
+
+ mListener.onApplicationDisconnected(this, clientDeviceInfo, ConnectionHandle);
+ }
+ else
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "Failed to set O_NONBLOCK for notification pipe for connection " << ConnectionHandle);
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "Failed to create notification pipe for connection " << ConnectionHandle);
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Device for connection " << ConnectionHandle << " is invalid");
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Device handle for connection " << ConnectionHandle << " is invalid");
+ }
+
+ close(connectionSocket);
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Socket is invalid for connection " << ConnectionHandle);
+ }
+
+ if (true == isPipeCreated)
+ {
+ pthread_mutex_lock(&mConnectionsMutex);
+
+ close(connection->mNotificationPipeFds[0]);
+ close(connection->mNotificationPipeFds[1]);
+
+ connection->mNotificationPipeFds[0] = connection->mNotificationPipeFds[1] = -1;
+
+ pthread_mutex_unlock(&mConnectionsMutex);
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Connection " << ConnectionHandle << " is not valid");
+ }
+}
+
+void NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::updateClientDeviceList(void )
+{
+ LOG4CPLUS_INFO(mLogger, "Updating client device list");
+
+ tInternalDeviceList clientDeviceList;
+
+ pthread_mutex_lock(&mDevicesMutex);
+
+ for (tDeviceMap::const_iterator di = mDevices.begin(); di != mDevices.end(); ++di)
+ {
+ const SDevice * device = di->second;
+
+ if (0 != device)
+ {
+ clientDeviceList.push_back(SInternalDeviceInfo(di->first, device->mName, device->mUniqueDeviceId));
+ }
+ }
+
+ pthread_mutex_unlock(&mDevicesMutex);
+
+ mListener.onDeviceListUpdated(this, clientDeviceList);
+}
+
+void NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::createConnectionsListForDevice(const NsSmartDeviceLink::NsTransportManager::tDeviceHandle DeviceHandle, std::vector<NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SConnection *> & ConnectionsList)
+{
+ ConnectionsList.clear();
+}
+
+void * NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::mainThreadStartRoutine(void * Data)
+{
+ CDeviceAdapter * deviceAdapter = static_cast<CDeviceAdapter*>(Data);
+
+ if (0 != deviceAdapter)
+ {
+ deviceAdapter->mainThread();
+ }
+
+ return 0;
+}
+
+void * NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::connectionThreadStartRoutine(void * Data)
+{
+ SConnectionThreadParameters * connectionThreadParameters = static_cast<SConnectionThreadParameters*>(Data);
+
+ if (0 != connectionThreadParameters)
+ {
+ CDeviceAdapter & deviceAdapter(connectionThreadParameters->mDeviceAdapter);
+ tConnectionHandle connectionHandle(connectionThreadParameters->mConnectionHandle);
+
+ delete connectionThreadParameters;
+ connectionThreadParameters = 0;
+
+ deviceAdapter.connectionThread(connectionHandle);
+ }
+
+ return 0;
+}
diff --git a/SDL_Core/src/components/TransportManager/src/CDeviceAdapter.hpp b/SDL_Core/src/components/TransportManager/src/CDeviceAdapter.hpp
new file mode 100644
index 000000000..299197a36
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/CDeviceAdapter.hpp
@@ -0,0 +1,555 @@
+/**
+ * \file CDeviceAdapter.hpp
+ * \brief Class CDeviceAdapter header.
+ * 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 __TRANSPORTMANAGER_CDEVICEADAPTER_HPP__
+#define __TRANSPORTMANAGER_CDEVICEADAPTER_HPP__
+
+#include <pthread.h>
+#include <queue>
+#include <time.h>
+
+#include "Logger.hpp"
+
+#include "IDeviceAdapter.hpp"
+
+#define LOG4CPLUS_ERROR_WITH_ERRNO(logger, message) LOG4CPLUS_ERROR(logger, message << ", error code " << errno << " (" << strerror(errno) << ")")
+
+namespace NsSmartDeviceLink
+{
+ namespace NsTransportManager
+ {
+ class IDeviceAdapterListener;
+ class IHandleGenerator;
+
+ /**
+ * @brief Base class for @link components_transportmanager_internal_design_device_adapters device adapters @endlink.
+ **/
+ class CDeviceAdapter: public IDeviceAdapter
+ {
+ public:
+ /**
+ * @brief Constructor.
+ *
+ * @param Listener Listener for device adapter notifications.
+ * @param HandleGenerator Handle generator implementation.
+ **/
+ CDeviceAdapter(IDeviceAdapterListener & Listener, IHandleGenerator & HandleGenerator);
+
+ /**
+ * @brief Destructor.
+ **/
+ virtual ~CDeviceAdapter(void);
+
+ /**
+ * @brief Run device adapter.
+ *
+ * Called from transport manager to start device adapter.
+ **/
+ virtual void run(void);
+
+ /**
+ * @brief Start scanning for new devices.
+ *
+ * List of new devices will be supplied in onDeviceListUpdated callback.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_device_scan
+ **/
+ virtual void scanForNewDevices(void);
+
+ /**
+ * @brief Connect to all applications discovered on device.
+ *
+ * @param DeviceHandle Handle of device to connect to.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_connecting_devices
+ **/
+ virtual void connectDevice(const tDeviceHandle DeviceHandle);
+
+ /**
+ * @brief Disconnect from all applications connected on device.
+ *
+ * @param DeviceHandle Handle of device to disconnect from.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_disconnecting_devices
+ **/
+ virtual void disconnectDevice(const tDeviceHandle DeviceHandle);
+
+ /**
+ * @brief Send frame.
+ *
+ * @param ConnectionHandle Connection handle.
+ * @param Data Frame payload data.
+ * @param DataSize Size of data in bytes.
+ * @param UserData Any user data.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_handling_communication
+ **/
+ virtual void sendFrame(tConnectionHandle ConnectionHandle, const uint8_t * Data, size_t DataSize, int UserData);
+
+ protected:
+ /**
+ * @brief Frame.
+ *
+ * Used to store data frames that must be sent to remote device.
+ **/
+ struct SFrame
+ {
+ /**
+ * @brief Constructor.
+ *
+ * @param UserData User data
+ * @param Data Frame data. SFrame stores a copy of this data,
+ * i.e. data may be freed after SFrame object is constructed.
+ * @param DataSize Size of frame data in bytes.
+ **/
+ SFrame(int UserData, const uint8_t * Data, const size_t DataSize);
+
+ /**
+ * @brief Destructor.
+ *
+ * Frees stored frame data.
+ **/
+ ~SFrame(void);
+
+ /**
+ * @brief User data
+ **/
+ int mUserData;
+
+ /**
+ * @brief Frame data.
+ **/
+ uint8_t * mData;
+
+ /**
+ * @brief Frame data size in bytes.
+ **/
+ size_t mDataSize;
+ };
+
+ /**
+ * @brief Frame queue.
+ **/
+ typedef std::queue<SFrame*> tFrameQueue;
+
+ /**
+ * @brief Internal structure describing device.
+ **/
+ struct SDevice
+ {
+ /**
+ * @brief Constructor.
+ *
+ * @param Name User-friendly device name.
+ **/
+ SDevice(const char * Name);
+
+ /**
+ * @brief Destructor.
+ **/
+ virtual ~SDevice(void);
+
+ /**
+ * @brief Compare devices.
+ *
+ * This method checks whether two SDevice structures
+ * refer to the same device.
+ *
+ * @param OtherDevice Device to compare with.
+ *
+ * @return true if devices are equal, false otherwise.
+ **/
+ virtual bool isSameAs(const SDevice * OtherDevice) const;
+
+ /**
+ * @brief Device user-friendly name.
+ **/
+ std::string mName;
+
+ /**
+ * @brief Unique device identifier across all devices.
+ **/
+ std::string mUniqueDeviceId;
+ };
+
+ /**
+ * @brief Vector of devices.
+ **/
+ typedef std::vector<SDevice *> tDeviceVector;
+
+ /**
+ * @brief Devices map.
+ **/
+ typedef std::map<tDeviceHandle, SDevice *> tDeviceMap;
+
+ /**
+ * @brief Application connection.
+ **/
+ struct SConnection
+ {
+ /**
+ * @brief Constructor.
+ *
+ * @param DeviceHandle Device handle.
+ **/
+ SConnection(const tDeviceHandle DeviceHandle);
+
+ /**
+ * @brief Destructor.
+ *
+ * Clears map of frames to send.
+ **/
+ virtual ~SConnection(void);
+
+ /**
+ * @brief Compare connections.
+ *
+ * This method checks whether two SConnection structures
+ * refer to the same connection.
+ *
+ * @param OtherConnection Connection to compare with.
+ *
+ * @return true if connections are equal, false otherwise.
+ **/
+ virtual bool isSameAs(const SConnection * OtherConnection) const;
+
+ /**
+ * @brief Device handle.
+ **/
+ const tDeviceHandle mDeviceHandle;
+
+ /**
+ * @brief Thread that handles connection.
+ **/
+ pthread_t mConnectionThread;
+
+ /**
+ * @brief File descriptors of notification pipe.
+ *
+ * Notification pipe is used to wake up connection thread
+ * on external event (e.g. new data is available to send or
+ * connection is requested to be terminated).
+ *
+ * mNotificationPipeFds[0] is a descriptor of the read end of the pipe
+ * (the one that is used in poll() by connection thread) and
+ * mNotificationPipeFds[1] is a descriptor of the write end of the pipe
+ * (the one that is used in methods exposed to transport manager to
+ * wake up connection thread when necessary).
+ *
+ * @note eventfd cannot be used instead of a pipe because it does not
+ * conform to POSIX (eventfd is Linux-specific).
+ **/
+ int mNotificationPipeFds[2];
+
+ /**
+ * @brief Descriptor of connection socket.
+ **/
+ int mConnectionSocket;
+
+ /**
+ * @brief Frames that must be sent to remote device.
+ **/
+ tFrameQueue mFramesToSend;
+
+ /**
+ * @brief Terminate flag.
+ *
+ * This flag is set to notify connection thread that connection
+ * must be closed and connection thread must be terminated.
+ **/
+ bool mTerminateFlag;
+ };
+
+ /**
+ * @brief Parameters for starting connection thread.
+ **/
+ struct SConnectionThreadParameters
+ {
+ /**
+ * @brief Constructor.
+ *
+ * @param DeviceAdapter Reference to device adapter.
+ * @param ConnectionHandle Connection handle.
+ **/
+ SConnectionThreadParameters(CDeviceAdapter & DeviceAdapter, tConnectionHandle ConnectionHandle);
+
+ /**
+ * @brief Reference to device adapter.
+ **/
+ CDeviceAdapter & mDeviceAdapter;
+
+ /**
+ * @brief Connection handle.
+ **/
+ tConnectionHandle mConnectionHandle;
+ };
+
+ /**
+ * @brief Wait until all device adapter threads are terminated.
+ *
+ * Every device adapter must call this method in destructor to wait
+ * for other threads to terminate before destroying device adapter.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_threads_termination
+ **/
+ void waitForThreadsTermination(void);
+
+ /**
+ * @brief Start connection.
+ *
+ * Check if connection is not in connection map
+ * and if it's not, add it to map and start connection thread.
+ *
+ * @param Connection Connection to start.
+ *
+ * @return true if connection thread has been started, false otherwise.
+ **/
+ bool startConnection(SConnection * Connection);
+
+ /**
+ * @brief Stop connection.
+ *
+ * This method only initiates connection termination. It returns immediately
+ * without waiting for actual termination of the connection.
+ *
+ * @param ConnectionHandle Handle of connection to stop.
+ **/
+ void stopConnection(tConnectionHandle ConnectionHandle);
+
+ /**
+ * @brief Wait for device scan request.
+ *
+ * Wait until scanForNewDevices() is called or timeout
+ * expires.
+ *
+ * @param Timeout Timeout value in seconds. 0 means no
+ * timeout.
+ *
+ * @return true if scanForNewDevices() has been called,
+ * false if timeout expired.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_device_scan
+ **/
+ bool waitForDeviceScanRequest(const time_t Timeout);
+
+ /**
+ * @brief Handle communication.
+ *
+ * Handle communication for specified connection (send/receive data
+ * to/from connection socket).
+ *
+ * This method must be called from connection thread implementation
+ * when connection is established and connection socket descriptor
+ * is set for the connection.
+ *
+ * This methods returns when connection is terminated.
+ *
+ * @param ConnectionHandle Connection handle.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_handling_communication
+ **/
+ void handleCommunication(const tConnectionHandle ConnectionHandle);
+
+ /**
+ * @brief Update client device list.
+ *
+ * This method is called when list of devices is changed to
+ * notify device adapter listener about new list of devices.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_update_client_device_list
+ **/
+ void updateClientDeviceList(void);
+
+ /**
+ * @brief Create list of connections possible for specified device.
+ *
+ * This method is called from connectDevice(). Device adapter may implement
+ * this method to provide list of connections that must be running on
+ * connected device.
+ *
+ * @param DeviceHandle Device handle.
+ * @param ConnectionsList Reference to connections list that must be filled.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_connecting_devices
+ **/
+ virtual void createConnectionsListForDevice(const tDeviceHandle DeviceHandle, std::vector<SConnection*> & ConnectionsList);
+
+ /**
+ * @brief Device adapter main thread.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_main_thread
+ **/
+ virtual void mainThread(void) = 0;
+
+ /**
+ * @brief Connection thread.
+ *
+ * This method is responsible for establishing connection and communicating
+ * with remote device via specified connection. It must remove itself from
+ * connection map when connection is terminated before terminating connection thread.
+ *
+ * @param ConnectionHandle Connection handle.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_connection_thread
+ **/
+ virtual void connectionThread(const tConnectionHandle ConnectionHandle) = 0;
+
+ /**
+ * @brief Connections map.
+ **/
+ typedef std::map<tConnectionHandle, SConnection *> tConnectionMap;
+
+ /**
+ * @brief Logger.
+ **/
+ const log4cplus::Logger mLogger;
+
+ /**
+ * @brief Listener for device adapter notifications.
+ **/
+ IDeviceAdapterListener & mListener;
+
+ /**
+ * @brief Handle generator implementation.
+ **/
+ IHandleGenerator & mHandleGenerator;
+
+ /**
+ * @brief Flag indicating that device scan was requested.
+ *
+ * This flag is set in scanForNewDevices and reset after requested
+ * device scan is completed.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_device_scan
+ **/
+ bool mDeviceScanRequested;
+
+ /**
+ * @brief Mutex restricting access to DeviceScanRequested flag.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_device_scan
+ **/
+ pthread_mutex_t mDeviceScanRequestedMutex;
+
+ /**
+ * @brief Conditional variable for signaling discovery thread about requested device scan.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_device_scan
+ **/
+ pthread_cond_t mDeviceScanRequestedCond;
+
+ /**
+ * @brief Map of device handle to device.
+ *
+ * This map contains all currently available bluetooth devices.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_devices_map
+ **/
+ tDeviceMap mDevices;
+
+ /**
+ * @brief Mutex restricting access to device map.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_devices_map
+ **/
+ mutable pthread_mutex_t mDevicesMutex;
+
+ /**
+ * @brief Map of connections.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_connections_map
+ **/
+ tConnectionMap mConnections;
+
+ /**
+ * @brief Mutex restricting access to connections map.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_connections_map
+ **/
+ mutable pthread_mutex_t mConnectionsMutex;
+
+ /**
+ * @brief Shutdown flag.
+ *
+ * This flag is set to true on shutdown to inform all device adapter
+ * threads that device adapter shutdown is in progress. After setting
+ * this flag device adapter waits until all its threads are terminated.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_threads_termination
+ **/
+ bool mShutdownFlag;
+
+ private:
+ /**
+ * @brief Start routine for device adapter main thread.
+ *
+ * @param Data Must be pointer to CDeviceAdapter instance.
+ *
+ * @return Thread return value.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_main_thread
+ **/
+ static void * mainThreadStartRoutine(void * Data);
+
+ /**
+ * @brief Connection thread start routine.
+ *
+ * @param Data Must be pointer to SConnectionThreadParameters. Ownership
+ * of connection thread parameters is passed to connection thread, i.e.
+ * connection thread is responsible for freeing this object.
+ *
+ * @return Thread return value.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_connection_thread
+ **/
+ static void * connectionThreadStartRoutine(void * Data);
+
+ /**
+ * @brief ID of device adapter main thread.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_main_thread
+ **/
+ pthread_t mMainThread;
+
+ /**
+ * @brief Flag indicating whether the device adapter main thread has been started successfully.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_main_thread
+ **/
+ bool mMainThreadStarted;
+ };
+ }
+}
+
+#endif
diff --git a/SDL_Core/src/components/TransportManager/src/CTCPAdapter.cpp b/SDL_Core/src/components/TransportManager/src/CTCPAdapter.cpp
new file mode 100644
index 000000000..4f545356e
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/CTCPAdapter.cpp
@@ -0,0 +1,317 @@
+/**
+ * \file CTCPAdapter.cpp
+ * \brief Class CTCPAdapter.
+ * 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 <memory.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "CTCPAdapter.hpp"
+#include "IHandleGenerator.hpp"
+
+NsSmartDeviceLink::NsTransportManager::CTCPAdapter::STCPDevice::STCPDevice(const char* Name, const in_addr_t & Address):
+SDevice(Name),
+mAddress(Address)
+{
+}
+
+NsSmartDeviceLink::NsTransportManager::CTCPAdapter::STCPDevice::~STCPDevice(void)
+{
+}
+
+bool NsSmartDeviceLink::NsTransportManager::CTCPAdapter::STCPDevice::isSameAs(const NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SDevice * OtherDevice) const
+{
+ bool result = false;
+
+ if (true == SDevice::isSameAs(OtherDevice))
+ {
+ const STCPDevice * otherTCPDevice = dynamic_cast<const STCPDevice*>(OtherDevice);
+
+ if (0 != otherTCPDevice)
+ {
+ result = (mAddress == otherTCPDevice->mAddress);
+ }
+ }
+
+ return result;
+}
+
+NsSmartDeviceLink::NsTransportManager::CTCPAdapter::STCPConnection::STCPConnection(const NsSmartDeviceLink::NsTransportManager::tDeviceHandle DeviceHandle, int ConnectionSocket, const in_port_t Port):
+SConnection(DeviceHandle),
+mPort(Port)
+{
+ mConnectionSocket = ConnectionSocket;
+}
+
+NsSmartDeviceLink::NsTransportManager::CTCPAdapter::STCPConnection::~STCPConnection(void)
+{
+}
+
+bool NsSmartDeviceLink::NsTransportManager::CTCPAdapter::STCPConnection::isSameAs(const NsSmartDeviceLink::NsTransportManager::CDeviceAdapter::SConnection* OtherConnection) const
+{
+ bool result = false;
+
+ if (true == SConnection::isSameAs(OtherConnection))
+ {
+ const STCPConnection * otherTCPConnection = dynamic_cast<const STCPConnection*>(OtherConnection);
+
+ if (0 != otherTCPConnection)
+ {
+ result = (mPort == otherTCPConnection->mPort);
+ }
+ }
+
+ return result;
+}
+
+NsSmartDeviceLink::NsTransportManager::CTCPAdapter::CTCPAdapter(NsSmartDeviceLink::NsTransportManager::IDeviceAdapterListener & Listener, NsSmartDeviceLink::NsTransportManager::IHandleGenerator & HandleGenerator):
+CDeviceAdapter(Listener, HandleGenerator)
+{
+}
+
+NsSmartDeviceLink::NsTransportManager::CTCPAdapter::~CTCPAdapter(void)
+{
+ waitForThreadsTermination();
+}
+
+NsSmartDeviceLink::NsTransportManager::EDeviceType NsSmartDeviceLink::NsTransportManager::CTCPAdapter::getDeviceType(void) const
+{
+ return DeviceWiFi;
+}
+
+void NsSmartDeviceLink::NsTransportManager::CTCPAdapter::mainThread(void)
+{
+ LOG4CPLUS_INFO(mLogger, "Main thread initialized");
+
+ int socketFd = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (-1 != socketFd)
+ {
+ sockaddr_in serverAddress;
+
+ memset(&serverAddress, 0, sizeof(serverAddress));
+
+ serverAddress.sin_family = AF_INET;
+ serverAddress.sin_port = htons(cTCPAdapterPort);
+ serverAddress.sin_addr.s_addr = INADDR_ANY;
+
+ if (0 == bind(socketFd, (struct sockaddr*)&serverAddress, sizeof(serverAddress)))
+ {
+ if (0 == listen(socketFd, 128))
+ {
+ while (false == mShutdownFlag)
+ {
+ sockaddr_in clientAddress;
+ socklen_t clientAddressSize = sizeof(clientAddress);
+
+ int connectionFd = accept(socketFd, (struct sockaddr*)&clientAddress, &clientAddressSize);
+
+ if (connectionFd >= 0)
+ {
+ bool isConnectionThreadStarted = false;
+
+ if ((AF_INET == clientAddress.sin_family) &&
+ (sizeof(clientAddress) == clientAddressSize))
+ {
+ char deviceName[32];
+
+ strncpy(deviceName, inet_ntoa(clientAddress.sin_addr), sizeof(deviceName) / sizeof(deviceName[0]));
+
+ LOG4CPLUS_INFO(mLogger, "Connected client " << deviceName);
+
+ tDeviceHandle deviceHandle = InvalidDeviceHandle;
+
+ pthread_mutex_lock(&mDevicesMutex);
+
+ for (tDeviceMap::const_iterator deviceIterator = mDevices.begin(); deviceIterator != mDevices.end(); ++deviceIterator)
+ {
+ const STCPDevice * device = dynamic_cast<const STCPDevice *>(deviceIterator->second);
+
+ if (0 != device)
+ {
+ if (clientAddress.sin_addr.s_addr == device->mAddress)
+ {
+ deviceHandle = deviceIterator->first;
+ break;
+ }
+ }
+ }
+
+ pthread_mutex_unlock(&mDevicesMutex);
+
+ if (InvalidDeviceHandle == deviceHandle)
+ {
+ deviceHandle = mHandleGenerator.generateNewDeviceHandle();
+ STCPDevice * device = new STCPDevice(deviceName, clientAddress.sin_addr.s_addr);
+
+ pthread_mutex_lock(&mDevicesMutex);
+
+ if (true == mDevices.insert(std::make_pair(deviceHandle, device)).second)
+ {
+ device->mUniqueDeviceId = std::string("TCP-") + deviceName;
+
+ LOG4CPLUS_INFO(mLogger, "Added new device " << deviceHandle << ": " << device->mName << " (" << device->mUniqueDeviceId << ")");
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Device handle " << deviceHandle << " is already present in devices map");
+
+ deviceHandle = InvalidDeviceHandle;
+ delete device;
+ device = 0;
+ }
+
+ pthread_mutex_unlock(&mDevicesMutex);
+
+ if (0 != device)
+ {
+ updateClientDeviceList();
+ }
+ }
+
+ if (InvalidDeviceHandle != deviceHandle)
+ {
+ isConnectionThreadStarted = startConnection(new STCPConnection(deviceHandle, connectionFd, clientAddress.sin_port));
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Failed to insert new device into devices map");
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Address of connected client is invalid");
+ }
+
+ if (false == isConnectionThreadStarted)
+ {
+ close(connectionFd);
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "accept() failed");
+ }
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "listen() failed");
+ }
+ }
+ else
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "bind() failed");
+ }
+
+ close(socketFd);
+ }
+ else
+ {
+ LOG4CPLUS_ERROR_WITH_ERRNO(mLogger, "Failed to create socket");
+ }
+
+ LOG4CPLUS_INFO(mLogger, "Main thread finished");
+}
+
+void NsSmartDeviceLink::NsTransportManager::CTCPAdapter::connectionThread(const NsSmartDeviceLink::NsTransportManager::tConnectionHandle ConnectionHandle)
+{
+ handleCommunication(ConnectionHandle);
+
+ tDeviceHandle deviceHandle = InvalidDeviceHandle;
+
+ pthread_mutex_lock(&mConnectionsMutex);
+
+ tConnectionMap::iterator connectionIterator = mConnections.find(ConnectionHandle);
+
+ if (mConnections.end() != connectionIterator)
+ {
+ STCPConnection * connection = dynamic_cast<STCPConnection*>(connectionIterator->second);
+
+ if (0 != connection)
+ {
+ deviceHandle = connection->mDeviceHandle;
+
+ delete connection;
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Connection " << ConnectionHandle << " is invalid");
+ }
+
+ mConnections.erase(connectionIterator);
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Connection " << ConnectionHandle << " was not found in connections map");
+ }
+
+ for (connectionIterator = mConnections.begin(); connectionIterator != mConnections.end(); ++connectionIterator)
+ {
+ SConnection * connection = connectionIterator->second;
+
+ if (0 != connection)
+ {
+ if (deviceHandle == connection->mDeviceHandle)
+ {
+ deviceHandle = InvalidDeviceHandle;
+ break;
+ }
+ }
+ }
+
+ pthread_mutex_unlock(&mConnectionsMutex);
+
+ if (InvalidDeviceHandle != deviceHandle)
+ {
+ LOG4CPLUS_INFO(mLogger, "No connections left for device " << deviceHandle << ". Deleting device");
+
+ pthread_mutex_lock(&mDevicesMutex);
+
+ tDeviceMap::iterator deviceIterator = mDevices.find(deviceHandle);
+
+ if (mDevices.end() != deviceIterator)
+ {
+ delete deviceIterator->second;
+
+ mDevices.erase(deviceIterator);
+ }
+
+ pthread_mutex_unlock(&mDevicesMutex);
+
+ updateClientDeviceList();
+ }
+}
diff --git a/SDL_Core/src/components/TransportManager/src/CTCPAdapter.hpp b/SDL_Core/src/components/TransportManager/src/CTCPAdapter.hpp
new file mode 100644
index 000000000..14af2be24
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/CTCPAdapter.hpp
@@ -0,0 +1,181 @@
+/**
+ * \file CTCPAdapter.hpp
+ * \brief Class CTCPAdapter header.
+ * 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 __TRANSPORTMANAGER_CTCPADAPTER_HPP__
+#define __TRANSPORTMANAGER_CTCPADAPTER_HPP__
+
+#include <netinet/in.h>
+
+#include "CDeviceAdapter.hpp"
+
+namespace NsSmartDeviceLink
+{
+ namespace NsTransportManager
+ {
+ /**
+ * @brief Device adapter for TCP/IP connections.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_tcp_adapter
+ **/
+ class CTCPAdapter: public CDeviceAdapter
+ {
+ public:
+ /**
+ * @brief Constructor.
+ *
+ * @param Listener Listener for device adapter notifications.
+ * @param HandleGenerator Handle generator implementation.
+ **/
+ CTCPAdapter(IDeviceAdapterListener & Listener, IHandleGenerator & HandleGenerator);
+
+ /**
+ * @brief Destructor.
+ **/
+ virtual ~CTCPAdapter(void);
+
+ /**
+ * @brief Get type of devices handled by this device adapter.
+ *
+ * @return Device type.
+ **/
+ virtual EDeviceType getDeviceType(void) const;
+
+ private:
+ /**
+ * @brief TCP port for listening for incoming connections.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_tcp_adapter_listen
+ **/
+ static const uint16_t cTCPAdapterPort = 12345u;
+
+ /**
+ * @brief Internal structure describing TCP device.
+ **/
+ struct STCPDevice: public SDevice
+ {
+ /**
+ * @brief Constructor.
+ *
+ * @param Name User-friendly device name.
+ * @param Address Device IP address.
+ **/
+ STCPDevice(const char * Name, const in_addr_t & Address);
+
+ /**
+ * @brief Destructor.
+ **/
+ virtual ~STCPDevice(void);
+
+ /**
+ * @brief Compare devices.
+ *
+ * This method checks whether two STCPDevice structures
+ * refer to the same device.
+ *
+ * @param OtherDevice Device to compare with.
+ *
+ * @return true if devices are equal, false otherwise.
+ **/
+ virtual bool isSameAs(const SDevice * OtherDevice) const;
+
+ /**
+ * @brief Device IP address.
+ **/
+ in_addr_t mAddress;
+ };
+
+ /**
+ * @brief TCP connection.
+ **/
+ struct STCPConnection: public SConnection
+ {
+ /**
+ * @brief Constructor.
+ *
+ * @param DeviceHandle Device handle.
+ * @param ConnectionSocket Connection socket.
+ * @param Port TCP port.
+ **/
+ STCPConnection(const tDeviceHandle DeviceHandle, int ConnectionSocket, const in_port_t Port);
+
+ /**
+ * @brief Destructor.
+ **/
+ virtual ~STCPConnection(void);
+
+ /**
+ * @brief Compare connections.
+ *
+ * This method compares whether two STCPConnection structures
+ * refer to the same connection.
+ *
+ * @param OtherConnection Connection to compare with.
+ *
+ * @return true if connections are equal, false otherwise.
+ **/
+ virtual bool isSameAs(const SConnection * OtherConnection) const;
+
+ /**
+ * @brief TCP port of remote device.
+ **/
+ const in_port_t mPort;
+ };
+
+ /**
+ * @brief Device adapter main thread.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_tcp_adapter_listen
+ * @see @ref components_transportmanager_internal_design_device_adapters_tcp_adapter_accept
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_main_thread
+ **/
+ virtual void mainThread(void);
+
+ /**
+ * @brief Connection thread.
+ *
+ * This method is responsible for establishing connection and communicating
+ * with remote device via specified connection. It must remove itself from
+ * connection map when connection is terminated before terminating connection thread.
+ *
+ * @param ConnectionHandle Connection handle.
+ *
+ * @see @ref components_transportmanager_internal_design_device_adapters_tcp_adapter_disconnecting
+ * @see @ref components_transportmanager_internal_design_device_adapters_common_connection_thread
+ **/
+ virtual void connectionThread(const tConnectionHandle ConnectionHandle);
+ };
+ }
+}
+
+#endif
diff --git a/SDL_Core/src/components/TransportManager/src/CTransportManager.cpp b/SDL_Core/src/components/TransportManager/src/CTransportManager.cpp
new file mode 100644
index 000000000..c9c30332d
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/CTransportManager.cpp
@@ -0,0 +1,1311 @@
+/**
+ * \file CTransportManager.cpp
+ * \brief Class CTransportManager.
+ * 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 "LoggerHelper.hpp"
+
+#include "CTransportManager.hpp"
+#include "CBluetoothAdapter.hpp"
+#include "CTCPAdapter.hpp"
+#include "TransportManagerLoggerHelpers.hpp"
+
+#include <algorithm>
+
+using namespace NsSmartDeviceLink::NsTransportManager;
+
+NsSmartDeviceLink::NsTransportManager::CTransportManager::CTransportManager(void):
+mDeviceAdapters(),
+mLogger(log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("TransportManager"))),
+mDataListenersMutex(),
+mDeviceListenersMutex(),
+mDeviceHandleGenerationMutex(),
+mConnectionHandleGenerationMutex(),
+mDataListeners(),
+mDeviceListeners(),
+mLastUsedDeviceHandle(0),
+mLastUsedConnectionHandle(0),
+mApplicationCallbacksThread(),
+mDeviceListenersConditionVar(),
+mDeviceListenersCallbacks(),
+mTerminateFlag(false),
+mDevicesByAdapter(),
+mDevicesByAdapterMutex(),
+mConnections(),
+mClientInterfaceMutex()
+{
+ pthread_mutex_init(&mDataListenersMutex, 0);
+ pthread_mutex_init(&mDeviceListenersMutex, 0);
+ pthread_mutex_init(&mDeviceHandleGenerationMutex, 0);
+ pthread_mutex_init(&mConnectionHandleGenerationMutex, 0);
+ pthread_mutex_init(&mClientInterfaceMutex, 0);
+
+ pthread_cond_init(&mDeviceListenersConditionVar, NULL);
+
+ LOG4CPLUS_INFO(mLogger, "TransportManager constructed");
+}
+
+NsSmartDeviceLink::NsTransportManager::CTransportManager::~CTransportManager(void)
+{
+ LOG4CPLUS_INFO(mLogger, "TransportManager destructor");
+
+ mTerminateFlag = true;
+
+ // Terminating all threads
+ stopApplicationCallbacksThread();
+ LOG4CPLUS_INFO(mLogger, "Waiting for application callbacks thread termination");
+ pthread_join(mApplicationCallbacksThread, 0);
+ LOG4CPLUS_INFO(mLogger, "Application callbacks thread terminated");
+
+ pthread_mutex_lock(&mDataListenersMutex);
+ std::map<tConnectionHandle, pthread_t> dataThreads;
+ for (tConnectionsMap::iterator ConnectionsIterator = mConnections.begin(); ConnectionsIterator != mConnections.end(); ++ConnectionsIterator)
+ {
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionsIterator->first, "Stopping connection");
+ dataThreads[ConnectionsIterator->first] = ConnectionsIterator->second->mConnectionThread;
+ stopConnection(ConnectionsIterator->second->mConnectionHandle);
+ }
+ pthread_mutex_unlock(&mDataListenersMutex);
+
+ for (std::map<tConnectionHandle, pthread_t>::iterator threadsIterator = dataThreads.begin(); threadsIterator != dataThreads.end(); ++threadsIterator)
+ {
+ TM_CH_LOG4CPLUS_INFO(mLogger, threadsIterator->first, "Waiting for thread stoping");
+ pthread_join(threadsIterator->second, 0);
+ TM_CH_LOG4CPLUS_INFO(mLogger, threadsIterator->first, "Thread terminated");
+ }
+
+ LOG4CPLUS_INFO(mLogger, "All data callbacks threads terminated. Terminating device adapters");
+
+ for (std::vector<IDeviceAdapter*>::iterator di = mDeviceAdapters.begin(); di != mDeviceAdapters.end(); ++di)
+ {
+ removeDeviceAdapter((*di));
+ delete (*di);
+ }
+
+ LOG4CPLUS_INFO(mLogger, "All device adapters removed");
+
+ pthread_mutex_destroy(&mDataListenersMutex);
+ pthread_mutex_destroy(&mDeviceListenersMutex);
+ pthread_mutex_destroy(&mDeviceHandleGenerationMutex);
+ pthread_mutex_destroy(&mConnectionHandleGenerationMutex);
+ pthread_mutex_destroy(&mClientInterfaceMutex);
+
+ pthread_cond_destroy(&mDeviceListenersConditionVar);
+
+ LOG4CPLUS_INFO(mLogger, "Component terminated");
+}
+
+void NsSmartDeviceLink::NsTransportManager::CTransportManager::run(void)
+{
+ pthread_mutex_lock(&mClientInterfaceMutex);
+ initializeDeviceAdapters();
+
+ LOG4CPLUS_INFO(mLogger, "Starting device adapters");
+ for (std::vector<IDeviceAdapter*>::iterator di = mDeviceAdapters.begin(); di != mDeviceAdapters.end(); ++di)
+ {
+ (*di)->run();
+ }
+
+ startApplicationCallbacksThread();
+ pthread_mutex_unlock(&mClientInterfaceMutex);
+}
+
+void NsSmartDeviceLink::NsTransportManager::CTransportManager::scanForNewDevices(void)
+{
+ pthread_mutex_lock(&mClientInterfaceMutex);
+ LOG4CPLUS_INFO(mLogger, "Scanning new devices on all registered device adapters");
+ for (std::vector<IDeviceAdapter*>::iterator di = mDeviceAdapters.begin(); di != mDeviceAdapters.end(); ++di)
+ {
+ LOG4CPLUS_INFO(mLogger, "Initiating scanning of new devices on adapter: " <<(*di)->getDeviceType());
+ (*di)->scanForNewDevices();
+ LOG4CPLUS_INFO(mLogger, "Scanning of new devices initiated on adapter: " <<(*di)->getDeviceType());
+ }
+ LOG4CPLUS_INFO(mLogger, "Scanning of new devices initiated");
+ pthread_mutex_unlock(&mClientInterfaceMutex);
+}
+
+void NsSmartDeviceLink::NsTransportManager::CTransportManager::connectDevice(const NsSmartDeviceLink::NsTransportManager::tDeviceHandle DeviceHandle)
+{
+ pthread_mutex_lock(&mClientInterfaceMutex);
+ connectDisconnectDevice(DeviceHandle, true);
+ pthread_mutex_unlock(&mClientInterfaceMutex);
+}
+
+void NsSmartDeviceLink::NsTransportManager::CTransportManager::disconnectDevice(const NsSmartDeviceLink::NsTransportManager::tDeviceHandle DeviceHandle)
+{
+ pthread_mutex_lock(&mClientInterfaceMutex);
+ connectDisconnectDevice(DeviceHandle, false);
+ pthread_mutex_unlock(&mClientInterfaceMutex);
+}
+
+void NsSmartDeviceLink::NsTransportManager::CTransportManager::addDataListener(NsSmartDeviceLink::NsTransportManager::ITransportManagerDataListener * Listener)
+{
+ pthread_mutex_lock(&mClientInterfaceMutex);
+ mDataListeners.push_back(Listener);
+ pthread_mutex_unlock(&mClientInterfaceMutex);
+}
+
+void NsSmartDeviceLink::NsTransportManager::CTransportManager::removeDataListener(NsSmartDeviceLink::NsTransportManager::ITransportManagerDataListener * Listener)
+{
+ pthread_mutex_lock(&mClientInterfaceMutex);
+ mDataListeners.erase(std::remove(mDataListeners.begin(), mDataListeners.end(), Listener), mDataListeners.end());
+ pthread_mutex_unlock(&mClientInterfaceMutex);
+}
+
+void NsSmartDeviceLink::NsTransportManager::CTransportManager::addDeviceListener(NsSmartDeviceLink::NsTransportManager::ITransportManagerDeviceListener * Listener)
+{
+ pthread_mutex_lock(&mClientInterfaceMutex);
+ mDeviceListeners.push_back(Listener);
+ pthread_mutex_unlock(&mClientInterfaceMutex);
+}
+
+void NsSmartDeviceLink::NsTransportManager::CTransportManager::removeDeviceListener(NsSmartDeviceLink::NsTransportManager::ITransportManagerDeviceListener * Listener)
+{
+ pthread_mutex_lock(&mClientInterfaceMutex);
+ mDeviceListeners.erase(std::remove(mDeviceListeners.begin(), mDeviceListeners.end(), Listener), mDeviceListeners.end());
+ pthread_mutex_unlock(&mClientInterfaceMutex);
+}
+
+void NsSmartDeviceLink::NsTransportManager::CTransportManager::sendFrame(tConnectionHandle ConnectionHandle, const uint8_t* Data, size_t DataSize, const int UserData)
+{
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "sendFrame called. DataSize: "<<DataSize);
+
+ if(InvalidConnectionHandle == ConnectionHandle)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "sendFrame received with invalid connection handle");
+ return;
+ }
+
+ bool bIncomingParamsValid = true;
+ if(0 == Data)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "sendFrame with empty data");
+ bIncomingParamsValid = false;
+ }
+
+ if(0 == DataSize)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "sendFrame with DataSize=0");
+ bIncomingParamsValid = false;
+ }
+
+ if(false == bIncomingParamsValid)
+ {
+ SDataListenerCallback newCallback(CTransportManager::DataListenerCallbackType_FrameSendCompleted, ConnectionHandle, UserData, SendStatusInvalidParametersError);
+
+ pthread_mutex_lock(&mDataListenersMutex);
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Sending callback");
+ sendDataCallback(newCallback);
+ pthread_mutex_unlock(&mDataListenersMutex);
+ return;
+ }
+
+ // Searching device adapter
+ pthread_mutex_lock(&mDataListenersMutex);
+ SConnectionInfo* connectionInfo = getConnection(ConnectionHandle);
+ pthread_mutex_unlock(&mDataListenersMutex);
+
+ if(0 != connectionInfo)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "Device adapter found (type: "<<connectionInfo->mpDeviceAdapter.getDeviceType()<<"). Sending frame to it");
+ connectionInfo->mpDeviceAdapter.sendFrame(ConnectionHandle, Data, DataSize, UserData);
+ }
+ else
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "Device adapter that handles Connection Handle was not found");
+ }
+}
+
+NsSmartDeviceLink::NsTransportManager::tDeviceHandle NsSmartDeviceLink::NsTransportManager::CTransportManager::generateNewDeviceHandle(void)
+{
+ tDeviceHandle outputDeviceHandle;
+
+ pthread_mutex_lock(&mDeviceHandleGenerationMutex);
+ ++mLastUsedDeviceHandle;
+ outputDeviceHandle = mLastUsedDeviceHandle;
+ pthread_mutex_unlock(&mDeviceHandleGenerationMutex);
+
+ return outputDeviceHandle;
+}
+
+NsSmartDeviceLink::NsTransportManager::tConnectionHandle NsSmartDeviceLink::NsTransportManager::CTransportManager::generateNewConnectionHandle(void)
+{
+ tConnectionHandle outputConnectionHandle;
+
+ pthread_mutex_lock(&mConnectionHandleGenerationMutex);
+ ++mLastUsedConnectionHandle;
+ outputConnectionHandle = mLastUsedConnectionHandle;
+ pthread_mutex_unlock(&mConnectionHandleGenerationMutex);
+
+ return outputConnectionHandle;
+}
+
+void CTransportManager::onDeviceListUpdated(IDeviceAdapter * DeviceAdapter, const tInternalDeviceList & DeviceList)
+{
+ if(0 == DeviceAdapter)
+ {
+ LOG4CPLUS_WARN(mLogger, "DeviceAdapter=0");
+ }
+ else
+ {
+ LOG4CPLUS_INFO(mLogger, "Device adapter type is: "<<DeviceAdapter->getDeviceType() << ", number of devices is: "<<DeviceList.size());
+ pthread_mutex_lock(&mDevicesByAdapterMutex);
+
+ tDevicesByAdapterMap::iterator devicesIterator = mDevicesByAdapter.find(DeviceAdapter);
+ if(devicesIterator == mDevicesByAdapter.end())
+ {
+ LOG4CPLUS_WARN(mLogger, "Invalid adapter initialization. No devices vector available for adapter: "<<DeviceAdapter->getDeviceType());
+ pthread_mutex_unlock(&mDevicesByAdapterMutex);
+ }
+ else
+ {
+ // Updating devices for adapter
+ tInternalDeviceList *pDevices = devicesIterator->second;
+ pDevices->clear();
+ std::copy(DeviceList.begin(), DeviceList.end(), std::back_inserter(*pDevices));
+
+ LOG4CPLUS_INFO(mLogger, "Devices list for adapter is updated. Adapter type is: "<<DeviceAdapter->getDeviceType());
+
+ pthread_mutex_unlock(&mDevicesByAdapterMutex);
+
+ // Calling callback with new device list to subscribers
+ sendDeviceListUpdatedCallback();
+ }
+ }
+}
+
+void CTransportManager::onApplicationConnected(IDeviceAdapter * DeviceAdapter, const SDeviceInfo & ConnectedDevice, const tConnectionHandle ConnectionHandle)
+{
+ TM_CH_LOG4CPLUS_TRACE(mLogger, ConnectionHandle, "onApplicationConnected");
+
+ if(0 == DeviceAdapter)
+ {
+ TM_CH_LOG4CPLUS_ERROR(mLogger, ConnectionHandle, "ApplicationConnected received from invalid device adapter");
+ return;
+ }
+
+ if(InvalidConnectionHandle == ConnectionHandle)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "ApplicationConnected received with invalid connection handle");
+ return;
+ }
+
+ if(InvalidDeviceHandle == ConnectedDevice.mDeviceHandle)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "ApplicationConnected received with invalid device handle: "<<ConnectedDevice.mDeviceHandle);
+ return;
+ }
+
+ if(DeviceAdapter->getDeviceType() != ConnectedDevice.mDeviceType)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "ApplicationConnected received but connected device type("<<ConnectedDevice.mDeviceType<<") differs from device adapters type: "<<DeviceAdapter->getDeviceType());
+ return;
+ }
+
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Before mDevicesByAdapterMutex mutex lock");
+
+ pthread_mutex_lock(&mDevicesByAdapterMutex);
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Right after mDevicesByAdapterMutex mutex lock");
+ tDevicesByAdapterMap::iterator devicesIterator = mDevicesByAdapter.find(DeviceAdapter);
+ if(devicesIterator == mDevicesByAdapter.end())
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "Invalid device adapter initialization. No devices vector available for adapter: "<<DeviceAdapter->getDeviceType());
+ pthread_mutex_unlock(&mDevicesByAdapterMutex);
+ return;
+ }
+
+ tInternalDeviceList *pDevices = devicesIterator->second;
+ bool connectionHandleFound = false;
+ for(tInternalDeviceList::const_iterator deviceIterator = pDevices->begin(); deviceIterator != pDevices->end(); ++deviceIterator)
+ {
+ if(deviceIterator->mDeviceHandle == ConnectedDevice.mDeviceHandle)
+ {
+ connectionHandleFound = true;
+ }
+ }
+
+ pthread_mutex_unlock(&mDevicesByAdapterMutex);
+
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "After mDevicesByAdapterMutex mutex unlock");
+
+ if(false == connectionHandleFound)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "Connected device handle ("<<ConnectedDevice.mDeviceHandle<<") was not found in devices list for adapter of type: "<<DeviceAdapter->getDeviceType());
+ return;
+ }
+
+ startConnection(ConnectionHandle, *DeviceAdapter);
+
+ TM_CH_LOG4CPLUS_TRACE(mLogger, ConnectionHandle, "Sending callback");
+
+ // Sending callback
+ SDeviceListenerCallback cb(CTransportManager::DeviceListenerCallbackType_ApplicationConnected, ConnectedDevice, ConnectionHandle);
+ sendDeviceCallback(cb);
+
+ TM_CH_LOG4CPLUS_TRACE(mLogger, ConnectionHandle, "END of onApplicationConnected");
+}
+
+void CTransportManager::onApplicationDisconnected(IDeviceAdapter* DeviceAdapter, const SDeviceInfo& DisconnectedDevice, const tConnectionHandle ConnectionHandle)
+{
+ TM_CH_LOG4CPLUS_TRACE(mLogger, ConnectionHandle, "onApplicationDisconnected");
+
+ if(0 == DeviceAdapter)
+ {
+ TM_CH_LOG4CPLUS_ERROR(mLogger, ConnectionHandle, "ApplicationDisconnected received from invalid device adapter");
+ return;
+ }
+
+ if(InvalidConnectionHandle == ConnectionHandle)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "ApplicationDisconnected received with invalid connection handle");
+ return;
+ }
+
+ if(InvalidDeviceHandle == DisconnectedDevice.mDeviceHandle)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "ApplicationDisconnected received with invalid device handle: "<<DisconnectedDevice.mDeviceHandle);
+ return;
+ }
+
+ if(DeviceAdapter->getDeviceType() != DisconnectedDevice.mDeviceType)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "ApplicationDisconnected received but disconnected device type("<<DisconnectedDevice.mDeviceType<<") differs from device adapters type: "<<DeviceAdapter->getDeviceType());
+ return;
+ }
+
+ pthread_mutex_lock(&mDevicesByAdapterMutex);
+ tDevicesByAdapterMap::iterator devicesIterator = mDevicesByAdapter.find(DeviceAdapter);
+ if(devicesIterator == mDevicesByAdapter.end())
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "Invalid device adapter initialization. No devices vector available for adapter: "<<DeviceAdapter->getDeviceType());
+ pthread_mutex_unlock(&mDevicesByAdapterMutex);
+ return;
+ }
+
+ tInternalDeviceList *pDevices = devicesIterator->second;
+ bool connectionHandleFound = false;
+ for(tInternalDeviceList::const_iterator deviceIterator = pDevices->begin(); deviceIterator != pDevices->end(); ++deviceIterator)
+ {
+ if(deviceIterator->mDeviceHandle == DisconnectedDevice.mDeviceHandle)
+ {
+ connectionHandleFound = true;
+ }
+ }
+
+ pthread_mutex_unlock(&mDevicesByAdapterMutex);
+
+ if(false == connectionHandleFound)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "Disconnected device handle ("<<DisconnectedDevice.mDeviceHandle<<") was not found in devices list for adapter of type: "<<DeviceAdapter->getDeviceType());
+ return;
+ }
+
+ pthread_mutex_lock(&mDataListenersMutex);
+ SConnectionInfo* pConnection = getConnection(ConnectionHandle);
+ pthread_mutex_unlock(&mDataListenersMutex);
+
+ if(0 == pConnection)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "Thread for connection does not exist");
+ return;
+ }
+
+ pthread_mutex_lock(&mDataListenersMutex);
+ if(true == pConnection->mTerminateFlag)
+ {
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Connection is already in shutdown state.");
+ pthread_mutex_unlock(&mDataListenersMutex);
+ }
+ else
+ {
+ stopConnection(ConnectionHandle);
+ pthread_mutex_unlock(&mDataListenersMutex);
+
+ // Sending callback
+ SDeviceListenerCallback cb(CTransportManager::DeviceListenerCallbackType_ApplicationDisconnected, DisconnectedDevice, ConnectionHandle);
+ sendDeviceCallback(cb);
+ }
+
+ TM_CH_LOG4CPLUS_TRACE(mLogger, ConnectionHandle, "END of onApplicationDisconnected");
+}
+
+void CTransportManager::onFrameReceived(IDeviceAdapter * DeviceAdapter, tConnectionHandle ConnectionHandle, const uint8_t * Data, size_t DataSize)
+{
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "onFrameReceived called. DA: "<<DeviceAdapter<<", DataSize: "<<DataSize);
+
+ if(0 == DeviceAdapter)
+ {
+ TM_CH_LOG4CPLUS_ERROR(mLogger, ConnectionHandle, "onFrameReceived received from invalid device adapter");
+ return;
+ }
+
+ if(0 == Data)
+ {
+ TM_CH_LOG4CPLUS_ERROR(mLogger, ConnectionHandle, "onFrameReceived with empty data");
+ return;
+ }
+
+ if(0 == DataSize)
+ {
+ TM_CH_LOG4CPLUS_ERROR(mLogger, ConnectionHandle, "onFrameReceived with DataSize=0");
+ return;
+ }
+
+ if(InvalidConnectionHandle == ConnectionHandle)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "onFrameReceived received with invalid connection handle");
+ return;
+ }
+
+ pthread_mutex_lock(&mDevicesByAdapterMutex);
+ tDevicesByAdapterMap::iterator devicesIterator = mDevicesByAdapter.find(DeviceAdapter);
+ if(devicesIterator == mDevicesByAdapter.end())
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "onFrameReceived. Invalid device adapter initialization. No devices vector available for adapter: "<<DeviceAdapter->getDeviceType());
+ pthread_mutex_unlock(&mDevicesByAdapterMutex);
+ return;
+ }
+ pthread_mutex_unlock(&mDevicesByAdapterMutex);
+
+ pthread_mutex_lock(&mDataListenersMutex);
+ SConnectionInfo* connectionInfo = getConnection(ConnectionHandle);
+ pthread_mutex_unlock(&mDataListenersMutex);
+
+ if(0 == connectionInfo)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "onFrameReceived. Connection information for connection does not exist");
+ return;
+ }
+
+ pthread_mutex_lock(&mDataListenersMutex);
+ connectionInfo->mFrameData.appendFrameData(Data, DataSize);
+
+ uint8_t *pFramePacketData = 0;
+ size_t FramePacketSize = 0;
+
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Starting frame extraction");
+ while(true == connectionInfo->mFrameData.extractFrame(pFramePacketData, FramePacketSize))
+ {
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Frame extracted. Size is: "<< FramePacketSize);
+ SDataListenerCallback newCallback(CTransportManager::DataListenerCallbackType_FrameReceived, ConnectionHandle, pFramePacketData, FramePacketSize);
+ sendDataCallback(newCallback);
+ delete pFramePacketData;
+ FramePacketSize = 0;
+ }
+
+ pthread_mutex_unlock(&mDataListenersMutex);
+
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "onFrameReceived processed");
+}
+
+void CTransportManager::onFrameSendCompleted(IDeviceAdapter * DeviceAdapter, tConnectionHandle ConnectionHandle, int UserData, ESendStatus SendStatus)
+{
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "onFrameSendCompleted called. DA: "<<DeviceAdapter<<", UserData: "<<UserData <<", SendStatus: " <<SendStatus);
+
+ if(0 == DeviceAdapter)
+ {
+ TM_CH_LOG4CPLUS_ERROR(mLogger, ConnectionHandle, "onFrameSendCompleted received from invalid device adapter");
+ return;
+ }
+
+ if(InvalidConnectionHandle == ConnectionHandle)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "onFrameSendCompleted received with invalid connection handle");
+ return;
+ }
+
+ pthread_mutex_lock(&mDevicesByAdapterMutex);
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "searching for devices for adapter");
+ tDevicesByAdapterMap::iterator devicesIterator = mDevicesByAdapter.find(DeviceAdapter);
+ if(devicesIterator == mDevicesByAdapter.end())
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "onFrameSendCompleted. Invalid device adapter initialization. No devices vector available for adapter: "<<DeviceAdapter->getDeviceType());
+ pthread_mutex_unlock(&mDevicesByAdapterMutex);
+ return;
+ }
+ pthread_mutex_unlock(&mDevicesByAdapterMutex);
+
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Checking connection information availability");
+
+ pthread_mutex_lock(&mDataListenersMutex);
+ bool bThreadExist = isConnectionAvailable(ConnectionHandle);
+ pthread_mutex_unlock(&mDataListenersMutex);
+
+ if(false == bThreadExist)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "onFrameSendCompleted. Connection is not available");
+ return;
+ }
+
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Connection is available. Preparing callback");
+
+ SDataListenerCallback newCallback(CTransportManager::DataListenerCallbackType_FrameSendCompleted, ConnectionHandle, UserData, SendStatus);
+
+ pthread_mutex_lock(&mDataListenersMutex);
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Sending callback");
+ sendDataCallback(newCallback);
+ pthread_mutex_unlock(&mDataListenersMutex);
+}
+
+CTransportManager::SDeviceListenerCallback::SDeviceListenerCallback(CTransportManager::EDeviceListenerCallbackType CallbackType, const tDeviceList& DeviceList)
+: mCallbackType(CallbackType)
+, mDeviceList(DeviceList)
+, mDeviceInfo()
+, mConnectionHandle()
+{
+}
+
+CTransportManager::SDeviceListenerCallback::SDeviceListenerCallback(CTransportManager::EDeviceListenerCallbackType CallbackType, const SDeviceInfo& DeviceInfo, const tConnectionHandle& ConnectionHandle)
+: mCallbackType(CallbackType)
+, mDeviceList()
+, mDeviceInfo(DeviceInfo)
+, mConnectionHandle(ConnectionHandle)
+{
+}
+
+CTransportManager::SDeviceListenerCallback::SDeviceListenerCallback(const SDeviceListenerCallback& other)
+: mCallbackType(other.mCallbackType)
+, mDeviceList(other.mDeviceList)
+, mDeviceInfo(other.mDeviceInfo)
+, mConnectionHandle(other.mConnectionHandle)
+{
+}
+
+bool CTransportManager::SDeviceListenerCallback::operator==( const SDeviceListenerCallback& i_other ) const
+{
+ return ( (mCallbackType == i_other.mCallbackType)
+ && (mDeviceList == i_other.mDeviceList)
+ && (mDeviceInfo == i_other.mDeviceInfo)
+ && (mConnectionHandle == i_other.mConnectionHandle));
+}
+
+CTransportManager::SDeviceListenerCallback::~SDeviceListenerCallback(void )
+{
+}
+
+CTransportManager::SDataListenerCallback::SDataListenerCallback(CTransportManager::EDataListenerCallbackType CallbackType, tConnectionHandle ConnectionHandle, const uint8_t* Data, size_t DataSize)
+: mCallbackType(CallbackType)
+, mConnectionHandle(ConnectionHandle)
+, mData(0)
+, mDataSize(DataSize)
+, mUserData()
+, mSendStatus(NsSmartDeviceLink::NsTransportManager::SendStatusUnknownError)
+{
+ if ((0 != Data) &&
+ (0u != DataSize))
+ {
+ mData = new uint8_t[DataSize];
+
+ if (0 != mData)
+ {
+ memcpy(mData, Data, DataSize);
+ }
+ }
+}
+
+CTransportManager::SDataListenerCallback::SDataListenerCallback(CTransportManager::EDataListenerCallbackType CallbackType, tConnectionHandle ConnectionHandle, int UserData, ESendStatus SendStatus)
+: mCallbackType(CallbackType)
+, mConnectionHandle(ConnectionHandle)
+, mData(0)
+, mDataSize(0)
+, mUserData(UserData)
+, mSendStatus(SendStatus)
+{
+
+}
+
+NsSmartDeviceLink::NsTransportManager::CTransportManager::SDataListenerCallback::SDataListenerCallback(const SDataListenerCallback& other)
+: mCallbackType(other.mCallbackType)
+, mConnectionHandle(other.mConnectionHandle)
+, mData(0)
+, mDataSize(other.mDataSize)
+, mUserData(other.mUserData)
+, mSendStatus(other.mSendStatus)
+{
+ if ((0 != other.mData) &&
+ (0u != other.mDataSize))
+ {
+ mData = new uint8_t[other.mDataSize];
+
+ if (0 != mData)
+ {
+ mDataSize = other.mDataSize;
+ memcpy(mData, other.mData, mDataSize);
+ }
+ }
+}
+
+bool NsSmartDeviceLink::NsTransportManager::CTransportManager::SDataListenerCallback::operator==( const SDataListenerCallback& i_other ) const
+{
+ return ( (mCallbackType == i_other.mCallbackType)
+ && (mConnectionHandle == i_other.mConnectionHandle)
+ && (mDataSize == i_other.mDataSize)
+ && (mUserData == i_other.mUserData)
+ && (mSendStatus == i_other.mSendStatus)
+ && (0 == memcmp(mData, i_other.mData, i_other.mDataSize)));
+}
+
+CTransportManager::SDataListenerCallback::~SDataListenerCallback(void )
+{
+ if (0 != mData)
+ {
+ delete[] mData;
+ }
+}
+
+CTransportManager::SDataThreadStartupParams::SDataThreadStartupParams(CTransportManager* TransportManager, tConnectionHandle ConnectionHandle)
+: mTransportManager(TransportManager)
+, mConnectionHandle(ConnectionHandle)
+{
+}
+
+
+void CTransportManager::applicationCallbacksThread()
+{
+ LOG4CPLUS_INFO(mLogger, "Started application callbacks thread");
+
+ while(false == mTerminateFlag)
+ {
+ pthread_mutex_lock(&mDeviceListenersMutex);
+
+ while(mDeviceListenersCallbacks.empty() && (false == mTerminateFlag))
+ {
+ LOG4CPLUS_INFO(mLogger, "No callbacks to process. Waiting");
+ pthread_cond_wait(&mDeviceListenersConditionVar, &mDeviceListenersMutex);
+ LOG4CPLUS_INFO(mLogger, "Callbacks processing triggered");
+ }
+
+ if(mTerminateFlag)
+ {
+ LOG4CPLUS_INFO(mLogger, "Shutdown is on progress. Skipping callback processing.");
+ pthread_mutex_unlock(&mDeviceListenersMutex);
+ break;
+ }
+
+ LOG4CPLUS_INFO(mLogger, "Copying callbacks and device listeners to process");
+
+ std::vector<SDeviceListenerCallback> callbacksToProcess(mDeviceListenersCallbacks);
+ mDeviceListenersCallbacks.clear();
+
+ std::vector<ITransportManagerDeviceListener*> deviceListenersToSend(mDeviceListeners);
+
+ pthread_mutex_unlock(&mDeviceListenersMutex);
+
+ LOG4CPLUS_INFO(mLogger, "Starting callbacks processing. Number of callbacks: " << callbacksToProcess.size());
+
+ std::vector<SDeviceListenerCallback>::const_iterator callbackIterator;
+
+ for(callbackIterator = callbacksToProcess.begin(); callbackIterator != callbacksToProcess.end(); ++callbackIterator)
+ {
+ LOG4CPLUS_INFO(mLogger, "Processing callback of type: " << (*callbackIterator).mCallbackType);
+
+ std::vector<ITransportManagerDeviceListener*>::const_iterator deviceListenersIterator;
+ int deviceListenerIndex = 0;
+
+ for (deviceListenersIterator = deviceListenersToSend.begin(), deviceListenerIndex=0; deviceListenersIterator != deviceListenersToSend.end(); ++deviceListenersIterator, ++deviceListenerIndex)
+ {
+ LOG4CPLUS_INFO(mLogger, "Calling callback on listener #" << deviceListenerIndex);
+
+ switch((*callbackIterator).mCallbackType)
+ {
+ case CTransportManager::DeviceListenerCallbackType_DeviceListUpdated:
+ (*deviceListenersIterator)->onDeviceListUpdated((*callbackIterator).mDeviceList);
+ break;
+ case CTransportManager::DeviceListenerCallbackType_ApplicationConnected:
+ (*deviceListenersIterator)->onApplicationConnected((*callbackIterator).mDeviceInfo, (*callbackIterator).mConnectionHandle);
+ break;
+ case CTransportManager::DeviceListenerCallbackType_ApplicationDisconnected:
+ (*deviceListenersIterator)->onApplicationDisconnected((*callbackIterator).mDeviceInfo, (*callbackIterator).mConnectionHandle);
+ break;
+ default:
+ LOG4CPLUS_ERROR(mLogger, "Unknown callback type: " << (*callbackIterator).mCallbackType);
+ break;
+ }
+
+ LOG4CPLUS_INFO(mLogger, "Callback on listener #" << deviceListenerIndex <<" called");
+ }
+ }
+
+ LOG4CPLUS_INFO(mLogger, "All callbacks processed. Starting next callbacks processing iteration");
+ }
+
+ LOG4CPLUS_INFO(mLogger, "ApplicationsCallback thread terminated");
+}
+
+void* CTransportManager::applicationCallbacksThreadStartRoutine(void* Data)
+{
+ if (0 != Data)
+ {
+ static_cast<CTransportManager*>(Data)->applicationCallbacksThread();
+ }
+
+ return 0;
+}
+
+void CTransportManager::dataCallbacksThread(const tConnectionHandle ConnectionHandle)
+{
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Started data callbacks thread");
+
+ pthread_mutex_lock(&mDataListenersMutex);
+ SConnectionInfo* connectionInfo = getConnection(ConnectionHandle);
+ pthread_mutex_unlock(&mDataListenersMutex);
+
+ if(0 == connectionInfo)
+ {
+ TM_CH_LOG4CPLUS_ERROR(mLogger, ConnectionHandle, "Connection information was not found");
+ return;
+ }
+
+ while(false == connectionInfo->mTerminateFlag)
+ {
+ pthread_mutex_lock(&mDataListenersMutex);
+
+ while(connectionInfo->mDataCallbacksVector.empty() && (false == connectionInfo->mTerminateFlag))
+ {
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "No callbacks to process. Waiting");
+ pthread_cond_wait(&connectionInfo->mConditionVar, &mDataListenersMutex);
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Callbacks processing triggered");
+ }
+
+ if(connectionInfo->mTerminateFlag)
+ {
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Shutdown is on progress. Skipping callback processing.");
+ pthread_mutex_unlock(&mDataListenersMutex);
+ break;
+ }
+
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Copying callbacks and device listeners to process");
+
+ tDataCallbacksVector callbacksToProcess(connectionInfo->mDataCallbacksVector);
+ connectionInfo->mDataCallbacksVector.clear();
+
+ std::vector<ITransportManagerDataListener*> dataListenersToSend(mDataListeners);
+
+ pthread_mutex_unlock(&mDataListenersMutex);
+
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Starting callbacks processing. Number of callbacks: " << callbacksToProcess.size());
+
+ tDataCallbacksVector::const_iterator callbackIterator;
+ for(callbackIterator = callbacksToProcess.begin(); callbackIterator != callbacksToProcess.end(); ++callbackIterator)
+ {
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Processing callback of type: " << (*callbackIterator).mCallbackType);
+
+ if(ConnectionHandle != callbackIterator->mConnectionHandle)
+ {
+ TM_CH_LOG4CPLUS_ERROR(mLogger, ConnectionHandle, "Possible error. Thread connection handle ("<<ConnectionHandle<<") differs from callback connection handle ("<<callbackIterator->mConnectionHandle<<")");
+ }
+
+ std::vector<ITransportManagerDataListener*>::const_iterator dataListenersIterator;
+ int dataListenerIndex = 0;
+
+ for (dataListenersIterator = dataListenersToSend.begin(), dataListenerIndex=0; dataListenersIterator != dataListenersToSend.end(); ++dataListenersIterator, ++dataListenerIndex)
+ {
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Calling callback on listener #" << dataListenerIndex);
+
+ switch((*callbackIterator).mCallbackType)
+ {
+ case CTransportManager::DataListenerCallbackType_FrameReceived:
+ (*dataListenersIterator)->onFrameReceived(callbackIterator->mConnectionHandle, callbackIterator->mData, callbackIterator->mDataSize);
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Callback onFrameReceived on listener #" << dataListenerIndex << " was called. DataSize: " << callbackIterator->mDataSize);
+ break;
+ case CTransportManager::DataListenerCallbackType_FrameSendCompleted:
+ (*dataListenersIterator)->onFrameSendCompleted(callbackIterator->mConnectionHandle, callbackIterator->mUserData, callbackIterator->mSendStatus);
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Callback onFrameReceived on listener #" << dataListenerIndex << " was called. UserData: " << callbackIterator->mUserData<<", SendStatus: "<<callbackIterator->mSendStatus);
+ break;
+ default:
+ TM_CH_LOG4CPLUS_ERROR(mLogger, ConnectionHandle, "Unknown callback type: " << (*callbackIterator).mCallbackType);
+ break;
+ }
+
+ LOG4CPLUS_INFO(mLogger, "Callback on listener #" << dataListenerIndex <<" called"<<", ConnectionHandle: "<<ConnectionHandle);
+ }
+ }
+
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "All callbacks processed. Starting next callbacks processing iteration");
+ }
+
+ pthread_mutex_lock(&mDataListenersMutex);
+
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Terminating connection thread");
+
+ // Deleting data associated with connection handle
+ delete connectionInfo;
+ mConnections.erase(ConnectionHandle);
+ pthread_mutex_unlock(&mDataListenersMutex);
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Connection thread terminated");
+}
+
+void* CTransportManager::dataCallbacksThreadStartRoutine(void* Data)
+{
+ SDataThreadStartupParams * parameters = static_cast<SDataThreadStartupParams*>(Data);
+
+ if (0 != parameters)
+ {
+ CTransportManager *pTransportManager = parameters->mTransportManager;
+ tConnectionHandle connectionHandle(parameters->mConnectionHandle);
+
+ delete parameters;
+ parameters = 0;
+
+ pTransportManager->dataCallbacksThread(connectionHandle);
+ }
+
+ return 0;
+}
+
+void CTransportManager::startApplicationCallbacksThread()
+{
+ LOG4CPLUS_INFO(mLogger, "Starting device listeners thread");
+
+ int errorCode = pthread_create(&mApplicationCallbacksThread, 0, &applicationCallbacksThreadStartRoutine, this);
+
+ if (0 == errorCode)
+ {
+ LOG4CPLUS_INFO(mLogger, "Device listeners thread started");
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Device listeners thread cannot be started, error code " << errorCode);
+ }
+}
+
+void CTransportManager::stopApplicationCallbacksThread()
+{
+ LOG4CPLUS_TRACE(mLogger, "Stopping application-callbacks thread");
+
+ pthread_mutex_lock(&mDeviceListenersMutex);
+ pthread_cond_signal(&mDeviceListenersConditionVar);
+ pthread_mutex_unlock(&mDeviceListenersMutex);
+}
+
+void CTransportManager::startConnection(const tConnectionHandle ConnectionHandle, IDeviceAdapter & DeviceAdapter)
+{
+ TM_CH_LOG4CPLUS_TRACE(mLogger, ConnectionHandle, "Starting data-callbacks thread");
+
+ pthread_mutex_lock(&mDataListenersMutex);
+
+ if(isConnectionAvailable(ConnectionHandle))
+ {
+ TM_CH_LOG4CPLUS_ERROR(mLogger, ConnectionHandle, "Connection with this handle already available. Possible error.");
+ }
+ else
+ {
+ SConnectionInfo *connection = new SConnectionInfo(ConnectionHandle, DeviceAdapter);
+ SDataThreadStartupParams *connectionThreadParams = new SDataThreadStartupParams(this, ConnectionHandle);
+
+ int errorCode = pthread_create(&connection->mConnectionThread, 0, &dataCallbacksThreadStartRoutine, connectionThreadParams);
+
+ if (0 == errorCode)
+ {
+ mConnections[ConnectionHandle] = connection;
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Connection started.");
+ }
+ else
+ {
+ LOG4CPLUS_ERROR(mLogger, "Thread start for connection handle (" << ConnectionHandle << ") failed, error code " << errorCode);
+ delete connection;
+ delete connectionThreadParams;
+ }
+ }
+
+ pthread_mutex_unlock(&mDataListenersMutex);
+}
+
+void CTransportManager::stopConnection(const tConnectionHandle ConnectionHandle)
+{
+ TM_CH_LOG4CPLUS_TRACE(mLogger, ConnectionHandle, "Stopping data-callbacks thread");
+
+ SConnectionInfo* connectionInfo = getConnection(ConnectionHandle);
+ if(0 == connectionInfo)
+ {
+ //pthread_mutex_unlock(&mDataListenersMutex);
+ return;
+ }
+ else
+ {
+ connectionInfo->mTerminateFlag = true;
+ pthread_cond_signal(&connectionInfo->mConditionVar);
+ }
+}
+
+
+bool CTransportManager::isConnectionAvailable(const tConnectionHandle ConnectionHandle)
+{
+ TM_CH_LOG4CPLUS_TRACE(mLogger, ConnectionHandle, "Checking connection availability");
+
+ bool bConnectionExist = (mConnections.find(ConnectionHandle) != mConnections.end());
+
+ TM_CH_LOG4CPLUS_TRACE(mLogger, ConnectionHandle, "Result of checking is: " << bConnectionExist);
+
+ return bConnectionExist;
+}
+
+CTransportManager::SConnectionInfo* CTransportManager::getConnection(const tConnectionHandle ConnectionHandle)
+{
+ TM_CH_LOG4CPLUS_TRACE(mLogger, ConnectionHandle, "Checking connection availability");
+
+ if(ConnectionHandle == InvalidConnectionHandle)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, ConnectionHandle, "Trying to get connection for invalid handle.");
+ return 0;
+ }
+
+ tConnectionsMap::iterator ConnectionIterator = mConnections.find(ConnectionHandle);
+ if(ConnectionIterator == mConnections.end())
+ {
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Connection info was not found");
+ return 0;
+ }
+
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Connection info was found");
+ return ConnectionIterator->second;
+}
+
+
+void CTransportManager::addDeviceAdapter(IDeviceAdapter* DeviceAdapter)
+{
+ mDeviceAdapters.push_back(DeviceAdapter);
+ mDevicesByAdapter.insert(std::make_pair(DeviceAdapter, new tInternalDeviceList()));
+}
+
+void CTransportManager::removeDeviceAdapter(IDeviceAdapter* DeviceAdapter)
+{
+ tDevicesByAdapterMap::iterator devicesIterator = mDevicesByAdapter.find(DeviceAdapter);
+ if(devicesIterator != mDevicesByAdapter.end())
+ {
+ delete devicesIterator->second;
+ mDevicesByAdapter.erase(DeviceAdapter);
+ }
+}
+
+void CTransportManager::initializeDeviceAdapters()
+{
+ addDeviceAdapter(new CBluetoothAdapter(*this, *this));
+ addDeviceAdapter(new CTCPAdapter(*this, *this));
+ LOG4CPLUS_INFO(mLogger, "Device adapters initialized");
+}
+
+void CTransportManager::sendDeviceListUpdatedCallback()
+{
+ LOG4CPLUS_INFO(mLogger, "Preparing complete device list from all adapters");
+
+ // Preparing complete device list
+ tDeviceList devices;
+
+ tDevicesByAdapterMap::const_iterator deviceAdaptersIterator;
+
+ pthread_mutex_lock(&mDevicesByAdapterMutex);
+
+ for(deviceAdaptersIterator = mDevicesByAdapter.begin(); deviceAdaptersIterator != mDevicesByAdapter.end(); ++deviceAdaptersIterator)
+ {
+ IDeviceAdapter* pDeviceAdapter = deviceAdaptersIterator->first;
+ tInternalDeviceList *pDevices = deviceAdaptersIterator->second;
+
+ LOG4CPLUS_INFO(mLogger, "Processing adapter with type: "<<pDeviceAdapter->getDeviceType());
+
+ tInternalDeviceList::const_iterator devicesInAdapterIterator;
+ for(devicesInAdapterIterator = pDevices->begin(); devicesInAdapterIterator != pDevices->end(); ++devicesInAdapterIterator)
+ {
+ SDeviceInfo deviceInfo;
+
+ deviceInfo.mDeviceHandle = devicesInAdapterIterator->mDeviceHandle;
+ deviceInfo.mDeviceType = pDeviceAdapter->getDeviceType();
+ deviceInfo.mUniqueDeviceId = devicesInAdapterIterator->mUniqueDeviceId;
+ deviceInfo.mUserFriendlyName = devicesInAdapterIterator->mUserFriendlyName;
+
+ devices.push_back(deviceInfo);
+
+ LOG4CPLUS_INFO(mLogger, "Processed device with unique Id: "<<devicesInAdapterIterator->mUniqueDeviceId << ", friendlyName: "<<devicesInAdapterIterator->mUserFriendlyName);
+ }
+ }
+
+ LOG4CPLUS_INFO(mLogger, "Complete device list from all adapters was prepared. Preparing callback OnDeviceListUpdated for sending");
+
+ pthread_mutex_unlock(&mDevicesByAdapterMutex);
+
+ // Sending DeviceListUpdatedCallback
+ SDeviceListenerCallback cb(CTransportManager::DeviceListenerCallbackType_DeviceListUpdated, devices);
+ sendDeviceCallback(cb);
+
+ LOG4CPLUS_INFO(mLogger, "Callback OnDeviceListUpdated was prepared for sending");
+}
+
+void CTransportManager::connectDisconnectDevice(const tDeviceHandle DeviceHandle, bool Connect)
+{
+ LOG4CPLUS_INFO(mLogger, "Performing "<<(Connect?"CONNECT":"DISCONNECT")<<" for device with handle: " << DeviceHandle);
+ LOG4CPLUS_INFO(mLogger, "Searching for device adapter for handling DeviceHandle: " << DeviceHandle);
+
+ tDevicesByAdapterMap::const_iterator deviceAdaptersIterator;
+
+ pthread_mutex_lock(&mDevicesByAdapterMutex);
+
+ IDeviceAdapter* pDeviceAdapterToCall = 0;
+
+ for(deviceAdaptersIterator = mDevicesByAdapter.begin(); deviceAdaptersIterator != mDevicesByAdapter.end(); ++deviceAdaptersIterator)
+ {
+ IDeviceAdapter* pDeviceAdapter = deviceAdaptersIterator->first;
+ tInternalDeviceList *pDevices = deviceAdaptersIterator->second;
+
+ LOG4CPLUS_INFO(mLogger, "Processing adapter with type: "<<pDeviceAdapter->getDeviceType());
+
+ tInternalDeviceList::const_iterator devicesInAdapterIterator;
+ for(devicesInAdapterIterator = pDevices->begin(); devicesInAdapterIterator != pDevices->end(); ++devicesInAdapterIterator)
+ {
+ LOG4CPLUS_INFO(mLogger, "Processing device with unique Id: "<<devicesInAdapterIterator->mUniqueDeviceId << ", DeviceHandle: "<<devicesInAdapterIterator->mDeviceHandle);
+ if(devicesInAdapterIterator->mDeviceHandle == DeviceHandle)
+ {
+ LOG4CPLUS_INFO(mLogger, "DeviceHandle relates to adapter: "<<pDeviceAdapter->getDeviceType());
+ pDeviceAdapterToCall = pDeviceAdapter;
+ }
+ }
+ }
+
+ pthread_mutex_unlock(&mDevicesByAdapterMutex);
+
+ if(0 != pDeviceAdapterToCall)
+ {
+ if(Connect)
+ {
+ pDeviceAdapterToCall->connectDevice(DeviceHandle);
+ }
+ else
+ {
+ pDeviceAdapterToCall->disconnectDevice(DeviceHandle);
+ }
+ LOG4CPLUS_INFO(mLogger, (Connect?"CONNECT":"DISCONNECT")<<" operation performed on device with handle: " << DeviceHandle);
+ }
+ else
+ {
+ LOG4CPLUS_WARN(mLogger, (Connect?"CONNECT":"DISCONNECT")<<" operation was not performed. Device handle was not found on any device: " << DeviceHandle);
+ }
+}
+
+void CTransportManager::sendDataCallback(const CTransportManager::SDataListenerCallback& callback)
+{
+ TM_CH_LOG4CPLUS_INFO(mLogger, callback.mConnectionHandle, "Preparing callback of type: "<<callback.mCallbackType<<", to send");
+
+ SConnectionInfo* connectionInfo = getConnection(callback.mConnectionHandle);
+ if(0 == connectionInfo)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, callback.mConnectionHandle, "Connection information was not found");
+ }
+ else
+ {
+ connectionInfo->mDataCallbacksVector.push_back(callback);
+ pthread_cond_signal(&connectionInfo->mConditionVar);
+ }
+}
+
+void CTransportManager::sendDeviceCallback(const CTransportManager::SDeviceListenerCallback& callback)
+{
+ LOG4CPLUS_INFO(mLogger, "Sending new device callback. Type: " << callback.mCallbackType);
+ pthread_mutex_lock(&mDeviceListenersMutex);
+
+ mDeviceListenersCallbacks.push_back(callback);
+ LOG4CPLUS_INFO(mLogger, "Device callback was added to pool");
+
+ pthread_cond_signal(&mDeviceListenersConditionVar);
+
+ pthread_mutex_unlock(&mDeviceListenersMutex);
+ LOG4CPLUS_INFO(mLogger, "Triggering device callback processing");
+}
+
+CTransportManager::SFrameDataForConnection::SFrameDataForConnection(tConnectionHandle ConnectionHandle)
+: mDataSize(0)
+, mConnectionHandle(ConnectionHandle)
+, mLogger(log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("TransportManager")))
+{
+ mBufferSize = 1536;
+ mpDataBuffer = new uint8_t[mBufferSize];
+
+ TM_CH_LOG4CPLUS_INFO(mLogger, ConnectionHandle, "Initialized frame data for connection container");
+}
+
+CTransportManager::SFrameDataForConnection::~SFrameDataForConnection()
+{
+ if(0 != mpDataBuffer)
+ {
+ delete mpDataBuffer;
+ mpDataBuffer = 0;
+ }
+ TM_CH_LOG4CPLUS_INFO(mLogger, mConnectionHandle, "Frame data for connection container destroyed");
+}
+
+void CTransportManager::SFrameDataForConnection::appendFrameData(const uint8_t* Data, size_t DataSize)
+{
+ TM_CH_LOG4CPLUS_INFO(mLogger, mConnectionHandle, "Appending data to container. DataSize: " << DataSize);
+
+ // Checking that data can be added to existing buffer
+ if( (mDataSize+DataSize) <= mBufferSize)
+ {
+ TM_CH_LOG4CPLUS_INFO(mLogger, mConnectionHandle, "Data can be appended to existing buffer. Buffer size: "<<mBufferSize<<", Existing data size: "<<mDataSize<<", DataSize: " << DataSize);
+ memcpy(&mpDataBuffer[mDataSize], Data, DataSize);
+ mDataSize += DataSize;
+ }
+ else
+ {
+ TM_CH_LOG4CPLUS_INFO(mLogger, mConnectionHandle, "Data cannot be appended to existing buffer. Buffer size: "<<mBufferSize<<", Existing data size: "<<mDataSize<<", DataSize: " << DataSize);
+
+ // Currently memory for incoming data is allocated as sum of existing memory size and incoming data size.
+ // In the future depending of type and sizes of incoming data this algorithm can be changed
+ size_t newSize = mBufferSize + DataSize;
+ uint8_t *newBuffer = new uint8_t[newSize];
+
+ TM_CH_LOG4CPLUS_INFO(mLogger, mConnectionHandle, "New buffer allocated. Buffer size: "<<newSize<<", was: "<<mBufferSize);
+
+ memcpy(newBuffer, mpDataBuffer, mDataSize);
+ memcpy(&newBuffer[mDataSize], Data, DataSize);
+ delete mpDataBuffer;
+ mpDataBuffer = 0; // Paranoid mode on
+
+ mpDataBuffer = newBuffer;
+ mDataSize = mDataSize+DataSize;
+ mBufferSize = newSize;
+ }
+
+ TM_CH_LOG4CPLUS_INFO(mLogger, mConnectionHandle, "Data appended. Buffer size: "<<mBufferSize<<", Existing data size: "<<mDataSize);
+}
+
+bool CTransportManager::SFrameDataForConnection::extractFrame(uint8_t *& Data, size_t & DataSize)
+{
+ if(mDataSize < PROTOCOL_HEADER_V1_SIZE)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, mConnectionHandle, "Not enough data for version in the buffer. No changes was made. mDataSize: "<<mDataSize);
+ return false;
+ }
+
+ // Extracting version
+ uint8_t firstByte = mpDataBuffer[0];
+ uint8_t version = firstByte >> 4;
+
+ uint8_t offset = sizeof(uint32_t);
+ uint32_t frameDataSize = mpDataBuffer[offset++] << 24;
+ frameDataSize |= mpDataBuffer[offset++] << 16;
+ frameDataSize |= mpDataBuffer[offset++] << 8;
+ frameDataSize |= mpDataBuffer[offset++];
+
+ size_t requiredDataSize = 0;
+
+ if(version == PROTOCOL_VERSION_1)
+ {
+ requiredDataSize = (PROTOCOL_HEADER_V1_SIZE + frameDataSize);
+ }
+ else if(version == PROTOCOL_VERSION_2)
+ {
+ requiredDataSize = (PROTOCOL_HEADER_V2_SIZE + frameDataSize);
+ }
+ else
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, mConnectionHandle, "Unsupported version received: " << (int)version);
+ return false;
+ }
+
+ if(mDataSize < requiredDataSize)
+ {
+ TM_CH_LOG4CPLUS_WARN(mLogger, mConnectionHandle, "Frame canot be extracted. Its size: " << requiredDataSize << ", Available data size: "<<mDataSize);
+ return false;
+ }
+
+ // Extracting frame from buffer
+ Data = new uint8_t[requiredDataSize];
+ memcpy(Data, mpDataBuffer, requiredDataSize);
+ DataSize = requiredDataSize;
+
+ // Shifting buffer
+ mDataSize -= requiredDataSize;
+ memmove(mpDataBuffer, &mpDataBuffer[requiredDataSize], mDataSize);
+
+ return true;
+}
+
+
+NsSmartDeviceLink::NsTransportManager::CTransportManager::SFrameDataForConnection::SFrameDataForConnection(const SFrameDataForConnection& other)
+: mDataSize(other.mDataSize)
+, mBufferSize(other.mBufferSize)
+, mConnectionHandle(other.mConnectionHandle)
+, mLogger(log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("TransportManager")))
+{
+ mpDataBuffer = new uint8_t[other.mBufferSize];
+ memcpy(mpDataBuffer, other.mpDataBuffer, other.mBufferSize);
+
+ TM_CH_LOG4CPLUS_INFO(mLogger, mConnectionHandle, "Initialized frame data for connection container");
+}
+
+bool NsSmartDeviceLink::NsTransportManager::CTransportManager::SFrameDataForConnection::operator==( const SFrameDataForConnection& i_other ) const
+{
+ return ( (mDataSize == i_other.mDataSize)
+ && (mBufferSize == i_other.mBufferSize)
+ && (mConnectionHandle == i_other.mConnectionHandle)
+ && (0 == memcmp(mpDataBuffer, i_other.mpDataBuffer, mBufferSize))
+ );
+}
+
+CTransportManager::SConnectionInfo::SConnectionInfo(const tConnectionHandle ConnectionHandle, IDeviceAdapter & DeviceAdapter)
+: mConnectionHandle(ConnectionHandle)
+, mTerminateFlag(false)
+, mDataCallbacksVector()
+, mConnectionThread()
+, mConditionVar()
+, mpDeviceAdapter(DeviceAdapter)
+, mFrameData(ConnectionHandle)
+{
+ pthread_cond_init(&mConditionVar, NULL);
+}
+
+CTransportManager::SConnectionInfo::SConnectionInfo(const CTransportManager::SConnectionInfo& other)
+: mConnectionHandle(other.mConnectionHandle)
+, mTerminateFlag(other.mTerminateFlag)
+, mDataCallbacksVector(other.mDataCallbacksVector)
+, mConnectionThread(other.mConnectionThread)
+, mConditionVar(other.mConditionVar)
+, mpDeviceAdapter(other.mpDeviceAdapter)
+, mFrameData(other.mFrameData)
+{
+
+}
+
+bool CTransportManager::SConnectionInfo::operator==(const CTransportManager::SConnectionInfo& i_other) const
+{
+ return ( (mConnectionHandle == i_other.mConnectionHandle)
+// && (mTerminateFlag == i_other.mTerminateFlag)
+// && (mDataCallbacksVector == i_other.mDataCallbacksVector)
+// && (mConnectionThread == i_other.mConnectionThread)
+// && (mConditionVar == i_other.mConditionVar)
+// && (mpDeviceAdapter == i_other.mpDeviceAdapter)
+// && (mFrameData == i_other.mFrameData)
+ );
+}
+
+CTransportManager::SConnectionInfo::~SConnectionInfo()
+{
+ pthread_cond_destroy(&mConditionVar);
+}
diff --git a/SDL_Core/src/components/TransportManager/src/CTransportManager.hpp b/SDL_Core/src/components/TransportManager/src/CTransportManager.hpp
new file mode 100644
index 000000000..ec4062136
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/CTransportManager.hpp
@@ -0,0 +1,837 @@
+/**
+ * \file CTransportManager.hpp
+ * \brief Class CTransportManager header.
+ * 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 __TRANSPORTMANAGER_CTRANSPORTMANAGER_HPP__
+#define __TRANSPORTMANAGER_CTRANSPORTMANAGER_HPP__
+
+#include "TransportManager/ITransportManager.hpp"
+#include "IDeviceAdapterListener.hpp"
+#include "IHandleGenerator.hpp"
+#include "Logger.hpp"
+
+#include <pthread.h>
+#include <vector>
+
+namespace NsSmartDeviceLink
+{
+ namespace NsTransportManager
+ {
+ class IDeviceAdapter;
+
+ // Some constants
+
+ const uint8_t PROTOCOL_HEADER_V1_SIZE = 8;
+ const uint8_t PROTOCOL_HEADER_V2_SIZE = 12;
+
+ const uint8_t PROTOCOL_VERSION_1 = 1;
+ const uint8_t PROTOCOL_VERSION_2 = 2;
+
+ // Class definition
+
+ /**
+ * @brief Transport manager implementation.
+ *
+ * Potential future optimizations:
+ *
+ * @todo Potential future optimization: Add shutdown flag checking inside client interface function calls
+ * @todo Potential future optimization: Implement more thread-safe processing of shutdown flag
+ * @todo Potential future optimization: Move ITransportManagerDeviceListener::onApplicationConnected and
+ * ITransportManagerDeviceListener::onApplicationDisconnected callbacks calling to corresponded connection thread
+ *
+ * @todo Potential future optimization: Currently all frames processed in one thread. In the future processing of them
+ * can be moved to the thread, which sent callbacks for corresponded connection.
+ *
+ * @todo Potential future optimization: Currently it is not possible to validate incoming frame data. Some kind of data
+ * validation can be implemented and if incoming data is invalid one of the possible solutions is to close
+ * corresponded connection
+ **/
+ class CTransportManager: public ITransportManager,
+ public IDeviceAdapterListener,
+ public IHandleGenerator
+ {
+ public:
+ /**
+ * @brief Constructor.
+ **/
+ CTransportManager(void);
+
+ /**
+ * @brief Destructor.
+ **/
+ virtual ~CTransportManager(void);
+
+ /**
+ * @brief Run transport manager.
+ *
+ * Must be called from startup after all references to
+ * external components are initialized to start trasport manager.
+ **/
+ virtual void run(void);
+
+ /**
+ * @brief Start scanning for new devices.
+ *
+ * List of new devices will be supplied in onDeviceListUpdated callback.
+ **/
+ virtual void scanForNewDevices(void);
+
+ /**
+ * @brief Connect to all applications discovered on device.
+ *
+ * @param DeviceHandle Handle of device to connect to.
+ **/
+ virtual void connectDevice(const tDeviceHandle DeviceHandle);
+
+ /**
+ * @brief Disconnect from all applications connected on device.
+ *
+ * @param DeviceHandle Handle of device to disconnect from.
+ **/
+ virtual void disconnectDevice(const tDeviceHandle DeviceHandle);
+
+ /**
+ * @brief Add listener to the data-related events
+ *
+ * @param Listener Pointer to listener.
+ **/
+ virtual void addDataListener(ITransportManagerDataListener * Listener);
+
+ /**
+ * @brief Remove listener to the data-related events.
+ *
+ * @param Listener Pointer to listener.
+ **/
+ virtual void removeDataListener(ITransportManagerDataListener * Listener);
+
+ /**
+ * @brief Add listener to the device-related events.
+ *
+ * @param Listener Pointer to listener.
+ **/
+ virtual void addDeviceListener(ITransportManagerDeviceListener * Listener);
+
+ /**
+ * @brief Remove listenerto the device-related events.
+ *
+ * @param Listener Pointer to listener.
+ **/
+ virtual void removeDeviceListener(ITransportManagerDeviceListener * Listener);
+
+ /**
+ * @brief Send frame.
+ *
+ * @param ConnectionHandle Connection handle.
+ * @param Data Frame payload data.
+ * @param DataSize Size of data in bytes.
+ * @param UserData Any user data. Will be returned as is in ITransportManagerDataListener::onFrameSendCompleted
+ **/
+ virtual void sendFrame(tConnectionHandle ConnectionHandle, const uint8_t * Data, size_t DataSize, const int UserData);
+
+ /**
+ * @brief Generate new device handle.
+ *
+ * Internal method used for generation of unique device handle
+ * for device adapters.
+ *
+ * @return New device handle.
+ **/
+ virtual tDeviceHandle generateNewDeviceHandle(void);
+
+ /**
+ * @brief Generate new connection handle.
+ *
+ * Internal method used for generation of unique connection handle
+ * for device adapters.
+ *
+ * @return New connection handle.
+ **/
+ virtual tConnectionHandle generateNewConnectionHandle(void);
+
+ // Handling Device Adapters callbacks
+
+ /**
+ * @brief Available devices list updated callback.
+ *
+ * @param DeviceAdapter Calling device adapter.
+ * @param DeviceList New list of available devices.
+ **/
+ virtual void onDeviceListUpdated(IDeviceAdapter * DeviceAdapter, const tInternalDeviceList & DeviceList);
+
+ /**
+ * @brief Application connected callback.
+ *
+ * @param ConnectedDevice DeviceInfo of device with connected application.
+ * @param Connection Connection handle.
+ **/
+ virtual void onApplicationConnected(IDeviceAdapter * DeviceAdapter, const SDeviceInfo & ConnectedDevice, const tConnectionHandle ConnectionHandle);
+
+ /**
+ * @brief Application disconnected callback.
+ *
+ * @param ConnectedDevice DeviceInfo of device with connected application.
+ * @param Connection Connection handle.
+ **/
+ virtual void onApplicationDisconnected(IDeviceAdapter * DeviceAdapter, const SDeviceInfo & DisconnectedDevice, const tConnectionHandle ConnectionHandle);
+
+ /**
+ * @brief Frame received callback.
+ *
+ * @param DeviceAdapter Calling device adapter.
+ * @param ConnectionHandle Connection handle.
+ * @param Data Received frame data.
+ * @param DataSize Size of received data in bytes.
+ *
+ * @note %Data pointed by parameter Data is valid only until
+ * this callback returns control to the caller. Callback
+ * handler is responsible to copy this data to its own
+ * location if it needs the data after return.
+ **/
+ virtual void onFrameReceived(IDeviceAdapter * DeviceAdapter, tConnectionHandle ConnectionHandle, const uint8_t * Data, size_t DataSize);
+
+ /**
+ * @brief Frame send completed callback.
+ *
+ * @param DeviceAdapter Calling device adapter.
+ * @param ConnectionHandle Connection handle.
+ * @param UserData User data that was previously passed to ITransportManager::sendFrame.
+ * @param SendStatus Result status.
+ **/
+ virtual void onFrameSendCompleted(IDeviceAdapter * DeviceAdapter, tConnectionHandle ConnectionHandle, int UserData, ESendStatus SendStatus);
+
+ protected:
+
+ /**
+ * @brief Enumeration that represents type of the device listener callback
+ * that must be called
+ **/
+ enum EDeviceListenerCallbackType
+ {
+ DeviceListenerCallbackType_DeviceListUpdated = 0,
+ DeviceListenerCallbackType_ApplicationConnected = 1,
+ DeviceListenerCallbackType_ApplicationDisconnected = 2
+ };
+
+ /**
+ * @brief Enumeration that represents type of the data listener callback
+ * that must be called
+ **/
+ enum EDataListenerCallbackType
+ {
+ DataListenerCallbackType_FrameReceived = 0,
+ DataListenerCallbackType_FrameSendCompleted = 1
+ };
+
+ /**
+ * @brief Device listener callback information
+ *
+ * Used to store data for calling device listeners
+ **/
+ struct SDeviceListenerCallback
+ {
+ /**
+ * @brief Constructor for creating DeviceListUpdated callback.
+ *
+ * @param CallbackType Type of the callback
+ * @param DeviceList Device list
+ **/
+ SDeviceListenerCallback(EDeviceListenerCallbackType CallbackType, const tDeviceList & DeviceList);
+
+ /**
+ * @brief Constructor for creating ApplicationConnected and ApplicationDisconnected callbacks
+ *
+ * @param CallbackType Type of the callback
+ * @param DeviceInfo Device information
+ * @param ConnectionHandle Connection handle
+ **/
+ SDeviceListenerCallback(EDeviceListenerCallbackType CallbackType, const SDeviceInfo & DeviceInfo, const tConnectionHandle & ConnectionHandle);
+
+ /**
+ * @brief Copy constructor
+ *
+ * @param other Reference to object to be copied
+ **/
+ SDeviceListenerCallback(const SDeviceListenerCallback& other);
+
+ /**
+ * @brief Comparison operator.
+ *
+ * @param i_other Reference to the object to be compared with
+ * @return bool
+ **/
+ bool operator==( const SDeviceListenerCallback& i_other ) const;
+
+ /**
+ * @brief Destructor.
+ *
+ **/
+ ~SDeviceListenerCallback(void);
+
+ /**
+ * @brief Type of the callback that must be called
+ **/
+ EDeviceListenerCallbackType mCallbackType;
+
+ /**
+ * @brief Device list (will be sent in the DeviceListUpdated callback)
+ **/
+ tDeviceList mDeviceList;
+
+ /**
+ * @brief Device information (will be sent in the ApplicationConnected and ApplicationDisconnected callbacks)
+ **/
+ SDeviceInfo mDeviceInfo;
+
+ /**
+ * @brief Connection handle (will be sent in the ApplicationConnected and ApplicationDisconnected callbacks)
+ **/
+ tConnectionHandle mConnectionHandle;
+ };
+
+ /**
+ * @brief Data listener callback information
+ *
+ * Used to store data for calling data listeners
+ **/
+ struct SDataListenerCallback
+ {
+ /**
+ * @brief Constructor for creating FrameReceived callback.
+ *
+ * @param CallbackType Type of the callback
+ * @param ConnectionHandle Connection handle
+ * @param Data Data
+ * @param DataSize Size of the data
+ **/
+ SDataListenerCallback(NsSmartDeviceLink::NsTransportManager::CTransportManager::EDataListenerCallbackType CallbackType, NsSmartDeviceLink::NsTransportManager::tConnectionHandle ConnectionHandle, const uint8_t* Data, size_t DataSize);
+
+ /**
+ * @brief Constructor for creating FrameSendCompleted callback
+ *
+ * @param CallbackType Type of the callback
+ * @param ConnectionHandle Connection handle
+ * @param UserData User data
+ * @param SendStatus Status of operation
+ **/
+ SDataListenerCallback(EDataListenerCallbackType CallbackType, tConnectionHandle ConnectionHandle, int UserData, ESendStatus SendStatus);
+
+ /**
+ * @brief Copy constructor
+ *
+ * @param other Reference to object to be copied
+ **/
+ SDataListenerCallback(const SDataListenerCallback& other);
+
+ /**
+ * @brief Comparison operator.
+ *
+ * @param i_other Reference to the object to be compared with
+ * @return bool
+ **/
+ bool operator==( const SDataListenerCallback& i_other ) const;
+
+ /**
+ * @brief Destructor.
+ *
+ **/
+ ~SDataListenerCallback(void);
+
+ /**
+ * @brief Type of the callback that must be called
+ **/
+ EDataListenerCallbackType mCallbackType;
+
+ /**
+ * @brief Connection handle (will be sent in the ApplicationConnected and ApplicationDisconnected callbacks)
+ **/
+ tConnectionHandle mConnectionHandle;
+
+ /**
+ * @brief Data to send
+ **/
+ uint8_t * mData;
+
+ /**
+ * @brief Size of the data
+ **/
+ size_t mDataSize;
+
+ /**
+ * @brief User data
+ **/
+ int mUserData;
+
+ /**
+ * @brief Operation status
+ **/
+ ESendStatus mSendStatus;
+ };
+
+ /**
+ * @brief Struct that contains startup params for data-threads
+ **/
+ struct SDataThreadStartupParams
+ {
+ /**
+ * @brief Constructor
+ *
+ * @param TransportManager Pointer to the Transport Manager
+ * @param ConnectionHandle Connection Handle
+ **/
+ SDataThreadStartupParams(NsSmartDeviceLink::NsTransportManager::CTransportManager* TransportManager, NsSmartDeviceLink::NsTransportManager::tConnectionHandle ConnectionHandle);
+
+ /**
+ * @brief Pointer to Transport Manager
+ **/
+ CTransportManager * mTransportManager;
+
+ /**
+ * @brief Connection Handle
+ **/
+ tConnectionHandle mConnectionHandle;
+ };
+
+ /**
+ * @brief Incapsulates frame data for each connection
+ *
+ **/
+ struct SFrameDataForConnection
+ {
+ /**
+ * @brief Constructor
+ *
+ **/
+ SFrameDataForConnection(tConnectionHandle ConnectionHandle);
+
+ /**
+ * @brief Destructor
+ *
+ **/
+ ~SFrameDataForConnection();
+
+ /**
+ * @brief Copy constructor
+ *
+ * @param other Reference to object to be copied
+ **/
+ SFrameDataForConnection(const SFrameDataForConnection& other);
+
+ /**
+ * @brief Comparison operator.
+ *
+ * @param i_other Reference to the object to be compared with
+ * @return bool
+ **/
+ bool operator==( const SFrameDataForConnection& i_other ) const;
+
+ /**
+ * @brief Appends new data to the buffer
+ *
+ * @param Data Data to append
+ * @param DataSize Size of data
+ * @return void
+ **/
+ void appendFrameData(const uint8_t * Data, size_t DataSize);
+
+ /**
+ * @brief Extracts single frame and returns it
+ *
+ * @param[out] Data Pointer to the frame data
+ * @param[out] size_t Size of the returned frame.
+ *
+ * @return bool Result of extract operation
+ *
+ * @warning Memory for this buffer is allocated in the method call but must be freed
+ * when it does not needed by caller component ONLY if method returns true
+ **/
+ bool extractFrame(uint8_t *& Data, size_t & DataSize);
+
+ /**
+ * @brief Pointer to the data buffer
+ **/
+ uint8_t *mpDataBuffer;
+
+ /**
+ * @brief Size of the data in the buffer
+ **/
+ size_t mDataSize;
+
+ /**
+ * @brief Size of the data buffer
+ **/
+ size_t mBufferSize;
+
+ /**
+ * @brief Handle of the connection
+ *
+ * @note Used only for debugging purposes
+ **/
+ tConnectionHandle mConnectionHandle;
+
+ /**
+ * @brief Logger
+ **/
+ Logger mLogger;
+ };
+
+ /**
+ * @brief Vector for storing Data Callbacks.
+ **/
+ typedef std::vector<SDataListenerCallback> tDataCallbacksVector;
+
+ /**
+ * @brief Struct for storing information, related to single connection
+ **/
+ struct SConnectionInfo
+ {
+ /**
+ * @brief Constructor.
+ *
+ * @param ConnectionHandle Connection handle.
+ * @param DeviceAdapter Device adapter
+ **/
+ SConnectionInfo(const tConnectionHandle ConnectionHandle, IDeviceAdapter & DeviceAdapter);
+
+ /**
+ * @brief Copy constructor
+ *
+ * @param other Reference to object to be copied
+ **/
+ SConnectionInfo(const SConnectionInfo& other);
+
+ /**
+ * @brief Comparison operator.
+ *
+ * @param i_other Reference to the object to be compared with
+ * @return bool
+ **/
+ bool operator==( const SConnectionInfo& i_other ) const;
+
+ /**
+ * @brief Destructor
+ *
+ **/
+ virtual ~SConnectionInfo();
+
+ /**
+ * @brief Connection handle, associated with connection information
+ **/
+ const tConnectionHandle mConnectionHandle;
+
+ /**
+ * @brief Terminate flag.
+ *
+ * This flag is set to notify connection thread that connection
+ * must be closed and connection thread must be terminated.
+ **/
+ bool mTerminateFlag;
+
+ /**
+ * @brief Callbacks for sending
+ **/
+ tDataCallbacksVector mDataCallbacksVector;
+
+ /**
+ * @brief Thread handle
+ **/
+ pthread_t mConnectionThread;
+
+ /**
+ * @brief Condition variable. Used for waiting for callbacks data
+ **/
+ pthread_cond_t mConditionVar;
+
+ /**
+ * @brief Device adapter, which opened connection
+ **/
+ IDeviceAdapter& mpDeviceAdapter;
+
+ /**
+ * @brief Frame data
+ **/
+ SFrameDataForConnection mFrameData;
+ };
+
+ /**
+ * @brief Connections map
+ **/
+ typedef std::map<tConnectionHandle, SConnectionInfo*> tConnectionsMap;
+
+ /**
+ * @brief Map for storing available devices for each device adapter
+ **/
+ typedef std::map<IDeviceAdapter*, tInternalDeviceList*> tDevicesByAdapterMap;
+
+ /**
+ * @brief Start routine for Application-related callbacks.
+ *
+ * @param Data Must be pointer to CTransportManager instance.
+ *
+ * @return Thread return value.
+ **/
+ static void * applicationCallbacksThreadStartRoutine(void * Data);
+
+ /**
+ * @brief Application-related callbacks thread.
+ *
+ * From this thread all application-related callbacks are called
+ *
+ **/
+ void applicationCallbacksThread();
+
+ /**
+ * @brief Start routine for Data-related callbacks.
+ *
+ * @param Data Must be pointer to CTransportManager instance.
+ *
+ * @return Thread return value.
+ **/
+ static void * dataCallbacksThreadStartRoutine(void * Data);
+
+ /**
+ * @brief Data-related callbacks thread.
+ *
+ * From this thread all data-related callbacks related to given connection handle are called
+ *
+ * @param ConnectionHandle Connection handle
+ **/
+ void dataCallbacksThread(const tConnectionHandle ConnectionHandle);
+
+ /**
+ * @brief Starts thread for application-related callbacks
+ *
+ **/
+ void startApplicationCallbacksThread();
+
+ /**
+ * @brief Stops thread for application-related callbacks
+ *
+ * @return void
+ * @warning terminate flag must be set to true before calling this function
+ **/
+ void stopApplicationCallbacksThread();
+
+ /**
+ * @brief Starts thread for data-related callbacks for given connection handle
+ *
+ * @param ConnectionHandle Connection Handle
+ * @return bool
+ **/
+ void startConnection(const tConnectionHandle ConnectionHandle, IDeviceAdapter& DeviceAdapter);
+
+ /**
+ * @brief Stops thread for data-related callbacks for given connection handle
+ *
+ * @param ConnectionHandle Connection Handle
+ * @return void
+ * @warning terminate flag must be set to true before calling this function
+ **/
+ void stopConnection(const tConnectionHandle ConnectionHandle);
+
+ /**
+ * @brief Check thread existence for given ConnectionHandle
+ *
+ * @param ConnectionHandle Connection Handle
+ * @return bool
+ *
+ * @attention This function is not thread safe
+ **/
+ bool isConnectionAvailable(const tConnectionHandle ConnectionHandle);
+
+ /**
+ * @brief Returns connection information by Connection Handle
+ *
+ * @param ConnectionHandle Connection handle
+ * @return SConnectionInfo*
+ **/
+ SConnectionInfo* getConnection(const tConnectionHandle ConnectionHandle);
+
+ /**
+ * @brief Adds new device adapter
+ *
+ * @param DeviceAdapter Device adapter to add
+ * @return void
+ **/
+ void addDeviceAdapter(NsSmartDeviceLink::NsTransportManager::IDeviceAdapter* DeviceAdapter);
+
+ /**
+ * @brief Removes device adapter
+ *
+ * @note This function does not deletes DeviceAdapter pointer
+ *
+ * @param DeviceAdapter Device adapter to remove
+ * @return void
+ **/
+ void removeDeviceAdapter(NsSmartDeviceLink::NsTransportManager::IDeviceAdapter* DeviceAdapter);
+
+ /**
+ * @brief All device adapters initialized here
+ *
+ * @return void
+ **/
+ virtual void initializeDeviceAdapters();
+
+ /**
+ * @brief Sends callback DeviceListUpdated to subscribers
+ *
+ * @return void
+ * @attention This function is not thread safe
+ **/
+ void sendDeviceListUpdatedCallback();
+
+ /**
+ * @brief Connects and disconnects device by its handle
+ *
+ * @param DeviceHandle Handle of the device to connect or disconnect
+ * @param Connect Flag of device operation: true for connect, false for disconnect. Defaults to true.
+ * @return void
+ **/
+ void connectDisconnectDevice(const NsSmartDeviceLink::NsTransportManager::tDeviceHandle DeviceHandle, bool Connect = true);
+
+ /**
+ * @brief Sends data callback
+ *
+ * @attention This function is not thread-safe
+ * @param callback Callback to send
+ * @return void
+ **/
+ void sendDataCallback(const SDataListenerCallback& callback);
+
+ /**
+ * @brief Sends device callback
+ *
+ * @param callback Callback to send
+ * @return void
+ **/
+ void sendDeviceCallback(const SDeviceListenerCallback& callback);
+
+ /**
+ * @brief Device adapters.
+ **/
+ std::vector<IDeviceAdapter*> mDeviceAdapters;
+
+ /**
+ * @brief Logger.
+ **/
+ const log4cplus::Logger mLogger;
+
+ /**
+ * @brief Mutex restricting access to data listeners.
+ **/
+ mutable pthread_mutex_t mDataListenersMutex;
+
+ /**
+ * @brief Mutex restricting access to device listeners.
+ **/
+ mutable pthread_mutex_t mDeviceListenersMutex;
+
+ /**
+ * @brief Mutex restricting access to new device handle generation
+ **/
+ mutable pthread_mutex_t mDeviceHandleGenerationMutex;
+
+ /**
+ * @brief Mutex restricting access to new conenction handle generation
+ **/
+ mutable pthread_mutex_t mConnectionHandleGenerationMutex;
+
+ /**
+ * @brief Data listeners
+ **/
+ std::vector<ITransportManagerDataListener*> mDataListeners;
+
+ /**
+ * @brief Device listeners
+ **/
+ std::vector<ITransportManagerDeviceListener*> mDeviceListeners;
+
+ /**
+ * @brief Last used device handle
+ *
+ * Used during device handle generation
+ **/
+ tDeviceHandle mLastUsedDeviceHandle;
+
+ /**
+ * @brief Last used connection handle
+ *
+ * Used during connection handle generation
+ **/
+ tConnectionHandle mLastUsedConnectionHandle;
+
+ /**
+ * @brief ID of thread, which sends Application-related callbacks
+ **/
+ pthread_t mApplicationCallbacksThread;
+
+ /**
+ * @brief Condition variable used for device listeners callbacks synchronization
+ **/
+ pthread_cond_t mDeviceListenersConditionVar;
+
+ /**
+ * @brief Vector of the device listeners callbacks to call
+ **/
+ std::vector<SDeviceListenerCallback> mDeviceListenersCallbacks;
+
+ /**
+ * @brief Terminate flag.
+ *
+ * This flag is set to notify threads that they must be terminated.
+ **/
+ bool mTerminateFlag;
+
+ /**
+ * @brief Devices for each adapter
+ **/
+ tDevicesByAdapterMap mDevicesByAdapter;
+
+ /**
+ * @brief Mutex restricting access to devices information for each adapter
+ **/
+ mutable pthread_mutex_t mDevicesByAdapterMutex;
+
+ /**
+ * @brief Connections
+ **/
+ tConnectionsMap mConnections;
+
+ /**
+ * @brief Mutex restricting access to client interface
+ **/
+ mutable pthread_mutex_t mClientInterfaceMutex;
+ };
+ }
+}
+
+#endif
diff --git a/SDL_Core/src/components/TransportManager/src/IDeviceAdapter.cpp b/SDL_Core/src/components/TransportManager/src/IDeviceAdapter.cpp
new file mode 100644
index 000000000..3d45feecd
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/IDeviceAdapter.cpp
@@ -0,0 +1,39 @@
+/**
+ * \file IDeviceAdapter.cpp
+ * \brief Class IDeviceAdapter.
+ * 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 "IDeviceAdapter.hpp"
+
+NsSmartDeviceLink::NsTransportManager::IDeviceAdapter::~IDeviceAdapter(void)
+{
+}
diff --git a/SDL_Core/src/components/TransportManager/src/IDeviceAdapter.hpp b/SDL_Core/src/components/TransportManager/src/IDeviceAdapter.hpp
new file mode 100644
index 000000000..ec27f7c0a
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/IDeviceAdapter.hpp
@@ -0,0 +1,109 @@
+/**
+ * \file IDeviceAdapter.hpp
+ * \brief Class IDeviceAdapter header.
+ * 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 __TRANSPORTMANAGER_IDEVICEADAPTER_HPP__
+#define __TRANSPORTMANAGER_IDEVICEADAPTER_HPP__
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <vector>
+
+#include "TransportManager/ITransportManager.hpp"
+#include "SInternalDeviceInfo.hpp"
+
+namespace NsSmartDeviceLink
+{
+ namespace NsTransportManager
+ {
+ /**
+ * @brief Interface for device adapter.
+ * @interface IDeviceAdapter
+ **/
+ class IDeviceAdapter
+ {
+ public:
+ /**
+ * @brief Destructor.
+ **/
+ virtual ~IDeviceAdapter(void);
+
+ /**
+ * @brief Run device adapter.
+ *
+ * Called from transport manager to start device adapter.
+ **/
+ virtual void run(void) = 0;
+
+ /**
+ * @brief Start scanning for new devices.
+ *
+ * List of new devices will be supplied in onDeviceListUpdated callback.
+ **/
+ virtual void scanForNewDevices(void) = 0;
+
+ /**
+ * @brief Connect to all applications discovered on device.
+ *
+ * @param DeviceHandle Handle of device to connect to.
+ **/
+ virtual void connectDevice(const tDeviceHandle DeviceHandle) = 0;
+
+ /**
+ * @brief Disconnect from all applications connected on device.
+ *
+ * @param DeviceHandle Handle of device to disconnect from.
+ **/
+ virtual void disconnectDevice(const tDeviceHandle DeviceHandle) = 0;
+
+ /**
+ * @brief Get type of devices handled by this device adapter.
+ *
+ * @return Device type.
+ **/
+ virtual EDeviceType getDeviceType(void) const = 0;
+
+ /**
+ * @brief Send frame.
+ *
+ * @param ConnectionHandle Connection handle.
+ * @param Data Frame payload data.
+ * @param DataSize Size of data in bytes.
+ * @param UserData Any user data. Will be returned as is in ITransportManagerDataListener::onFrameSendCompleted
+ **/
+ virtual void sendFrame(tConnectionHandle ConnectionHandle, const uint8_t * Data, size_t DataSize, int UserData) = 0;
+ };
+ }
+}
+
+#endif
diff --git a/SDL_Core/src/components/TransportManager/src/IDeviceAdapterListener.cpp b/SDL_Core/src/components/TransportManager/src/IDeviceAdapterListener.cpp
new file mode 100644
index 000000000..d6bc0cce3
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/IDeviceAdapterListener.cpp
@@ -0,0 +1,59 @@
+/**
+ * \file IDeviceAdapterListener.cpp
+ * \brief Class IDeviceAdapterListener.
+ * 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 "IDeviceAdapterListener.hpp"
+
+NsSmartDeviceLink::NsTransportManager::IDeviceAdapterListener::~IDeviceAdapterListener(void )
+{
+}
+
+void NsSmartDeviceLink::NsTransportManager::IDeviceAdapterListener::onDeviceListUpdated(NsSmartDeviceLink::NsTransportManager::IDeviceAdapter * DeviceAdapter, const NsSmartDeviceLink::NsTransportManager::tInternalDeviceList & DeviceList)
+{
+}
+
+void NsSmartDeviceLink::NsTransportManager::IDeviceAdapterListener::onApplicationConnected(NsSmartDeviceLink::NsTransportManager::IDeviceAdapter * DeviceAdapter, const NsSmartDeviceLink::NsTransportManager::SDeviceInfo & ConnectedDevice, const NsSmartDeviceLink::NsTransportManager::tConnectionHandle ConnectionHandle)
+{
+}
+
+void NsSmartDeviceLink::NsTransportManager::IDeviceAdapterListener::onApplicationDisconnected(NsSmartDeviceLink::NsTransportManager::IDeviceAdapter * DeviceAdapter, const NsSmartDeviceLink::NsTransportManager::SDeviceInfo & DisconnectedDevice, const NsSmartDeviceLink::NsTransportManager::tConnectionHandle ConnectionHandle)
+{
+}
+
+void NsSmartDeviceLink::NsTransportManager::IDeviceAdapterListener::onFrameReceived(NsSmartDeviceLink::NsTransportManager::IDeviceAdapter * DeviceAdapter, tConnectionHandle ConnectionHandle, const uint8_t * Data, size_t DataSize)
+{
+}
+
+void NsSmartDeviceLink::NsTransportManager::IDeviceAdapterListener::onFrameSendCompleted(NsSmartDeviceLink::NsTransportManager::IDeviceAdapter * DeviceAdapter, tConnectionHandle ConnectionHandle, int FrameSequenceNumber, ESendStatus SendStatus)
+{
+}
diff --git a/SDL_Core/src/components/TransportManager/src/IDeviceAdapterListener.hpp b/SDL_Core/src/components/TransportManager/src/IDeviceAdapterListener.hpp
new file mode 100644
index 000000000..be16bc847
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/IDeviceAdapterListener.hpp
@@ -0,0 +1,126 @@
+/**
+ * \file IDeviceAdapterListener.hpp
+ * \brief Class IDeviceAdapterListener.
+ * 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 __TRANSPORTMANAGER_IDEVICEADAPTERLISTENER_HPP__
+#define __TRANSPORTMANAGER_IDEVICEADAPTERLISTENER_HPP__
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <vector>
+
+#include "TransportManager/ITransportManager.hpp"
+#include "TransportManager/ITransportManagerDataListener.hpp"
+#include "TransportManager/ITransportManagerDeviceListener.hpp"
+
+#include "SInternalDeviceInfo.hpp"
+
+namespace NsSmartDeviceLink
+{
+ namespace NsTransportManager
+ {
+ class IDeviceAdapter;
+
+ /**
+ * @brief Interface of device adapter listener.
+ *
+ * Used to notify transport manager about events in
+ * device adapters.
+ * @interface IDeviceAdapterListener
+ **/
+ class IDeviceAdapterListener
+ {
+ public:
+ /**
+ * @brief Destructor.
+ **/
+ virtual ~IDeviceAdapterListener(void);
+
+ /**
+ * @brief Available devices list updated callback.
+ *
+ * Called when device scanning initiated with scanForNewDevices
+ * is completed.
+ *
+ * @param DeviceAdapter Calling device adapter.
+ * @param DeviceList New list of available devices.
+ **/
+ virtual void onDeviceListUpdated(IDeviceAdapter * DeviceAdapter, const tInternalDeviceList & DeviceList);
+
+ /**
+ * @brief Application connected callback.
+ *
+ * @param DeviceAdapter Device adapter
+ * @param ConnectedDevice DeviceInfo of device with connected application.
+ * @param Connection Connection handle.
+ **/
+ virtual void onApplicationConnected(IDeviceAdapter * DeviceAdapter, const SDeviceInfo & ConnectedDevice, const tConnectionHandle ConnectionHandle);
+
+ /**
+ * @brief Application disconnected callback.
+ *
+ * @param DeviceAdapter Device adapter
+ * @param ConnectedDevice DeviceInfo of device with connected application.
+ * @param Connection Connection handle.
+ **/
+ virtual void onApplicationDisconnected(IDeviceAdapter * DeviceAdapter, const SDeviceInfo & DisconnectedDevice, const tConnectionHandle ConnectionHandle);
+
+ /**
+ * @brief Frame received callback.
+ *
+ * @param DeviceAdapter Calling device adapter.
+ * @param ConnectionHandle Connection handle.
+ * @param Data Received frame data.
+ * @param DataSize Size of received data in bytes.
+ *
+ * @note %Data pointed by parameter Data is valid only until
+ * this callback returns control to the caller. Callback
+ * handler is responsible to copy this data to its own
+ * location if it needs the data after return.
+ **/
+ virtual void onFrameReceived(IDeviceAdapter * DeviceAdapter, tConnectionHandle ConnectionHandle, const uint8_t * Data, size_t DataSize);
+
+ /**
+ * @brief Frame send completed callback.
+ *
+ * @param DeviceAdapter Calling device adapter.
+ * @param ConnectionHandle Connection handle.
+ * @param FrameSequenceNumber Sequence numbere of frame that was previously returned by ITransportManager::sendFrame.
+ * @param SendStatus Result status.
+ **/
+ virtual void onFrameSendCompleted(IDeviceAdapter * DeviceAdapter, tConnectionHandle ConnectionHandle, int FrameSequenceNumber, ESendStatus SendStatus);
+ };
+ }
+}
+
+#endif
diff --git a/SDL_Core/src/components/TransportManager/src/IHandleGenerator.cpp b/SDL_Core/src/components/TransportManager/src/IHandleGenerator.cpp
new file mode 100644
index 000000000..9b4dce66c
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/IHandleGenerator.cpp
@@ -0,0 +1,39 @@
+/**
+ * \file IHandleGenerator.cpp
+ * \brief Class IHandleGenerator.
+ * 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 "IHandleGenerator.hpp"
+
+NsSmartDeviceLink::NsTransportManager::IHandleGenerator::~IHandleGenerator(void)
+{
+}
diff --git a/SDL_Core/src/components/TransportManager/src/IHandleGenerator.hpp b/SDL_Core/src/components/TransportManager/src/IHandleGenerator.hpp
new file mode 100644
index 000000000..a820c6e4a
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/IHandleGenerator.hpp
@@ -0,0 +1,79 @@
+/**
+ * \file IHandleGenerator.hpp
+ * \brief Class IHandleGenerator.
+ * 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 __TRANSPORTMANAGER_IHANDLEGENERATOR_HPP__
+#define __TRANSPORTMANAGER_IHANDLEGENERATOR_HPP__
+
+#include "TransportManager/ITransportManager.hpp"
+
+namespace NsSmartDeviceLink
+{
+ namespace NsTransportManager
+ {
+ /**
+ * @brief Interface for handle generator.
+ * @interface IHandleGenerator
+ **/
+ class IHandleGenerator
+ {
+ public:
+ /**
+ * @brief Destructor.
+ **/
+ virtual ~IHandleGenerator(void);
+
+ /**
+ * @brief Generate new device handle.
+ *
+ * Internal method used for generation of unique device handle
+ * for device adapters.
+ *
+ * @return New device handle.
+ **/
+ virtual tDeviceHandle generateNewDeviceHandle(void) = 0;
+
+ /**
+ * @brief Generate new connection handle.
+ *
+ * Internal method used for generation of unique connection handle
+ * for device adapters.
+ *
+ * @return New connection handle.
+ **/
+ virtual tConnectionHandle generateNewConnectionHandle(void) = 0;
+ };
+ }
+}
+
+#endif
diff --git a/SDL_Core/src/components/TransportManager/src/ITransportManager.cpp b/SDL_Core/src/components/TransportManager/src/ITransportManager.cpp
new file mode 100644
index 000000000..5406265fc
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/ITransportManager.cpp
@@ -0,0 +1,44 @@
+/**
+ * \file ITransportManager.cpp
+ * \brief Class ITransportManager.
+ * 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 "CTransportManager.hpp"
+
+NsSmartDeviceLink::NsTransportManager::ITransportManager * NsSmartDeviceLink::NsTransportManager::ITransportManager::create(void)
+{
+ return new CTransportManager();
+}
+
+NsSmartDeviceLink::NsTransportManager::ITransportManager::~ITransportManager(void)
+{
+}
diff --git a/SDL_Core/src/components/TransportManager/src/ITransportManagerDataListener.cpp b/SDL_Core/src/components/TransportManager/src/ITransportManagerDataListener.cpp
new file mode 100644
index 000000000..3ed2a9aa9
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/ITransportManagerDataListener.cpp
@@ -0,0 +1,47 @@
+/**
+ * \file ITransportManagerDataListener.cpp
+ * \brief Class ITransportManagerDataListener.
+ * 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 "TransportManager/ITransportManagerDataListener.hpp"
+
+NsSmartDeviceLink::NsTransportManager::ITransportManagerDataListener::~ITransportManagerDataListener()
+{
+}
+
+void NsSmartDeviceLink::NsTransportManager::ITransportManagerDataListener::onFrameReceived(tConnectionHandle ConnectionHandle, const uint8_t * Data, size_t DataSize)
+{
+}
+
+void NsSmartDeviceLink::NsTransportManager::ITransportManagerDataListener::onFrameSendCompleted(tConnectionHandle ConnectionHandle, int FrameSequenceNumber, ESendStatus SendStatus)
+{
+}
diff --git a/SDL_Core/src/components/TransportManager/src/ITransportManagerDeviceListener.cpp b/SDL_Core/src/components/TransportManager/src/ITransportManagerDeviceListener.cpp
new file mode 100644
index 000000000..abdacb781
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/ITransportManagerDeviceListener.cpp
@@ -0,0 +1,52 @@
+/**
+ * \file ITransportManagerDeviceListener.cpp
+ * \brief Class ITransportManagerDeviceListener.
+ * 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 "TransportManager/ITransportManagerDeviceListener.hpp"
+
+NsSmartDeviceLink::NsTransportManager::ITransportManagerDeviceListener::~ITransportManagerDeviceListener()
+{
+
+}
+
+void NsSmartDeviceLink::NsTransportManager::ITransportManagerDeviceListener::onDeviceListUpdated(const tDeviceList & DeviceList)
+{
+}
+
+void NsSmartDeviceLink::NsTransportManager::ITransportManagerDeviceListener::onApplicationConnected(const SDeviceInfo & ConnectedDevice, const tConnectionHandle Connection)
+{
+}
+
+void NsSmartDeviceLink::NsTransportManager::ITransportManagerDeviceListener::onApplicationDisconnected(const SDeviceInfo & DisconnectedDevice, const tConnectionHandle Connection)
+{
+}
diff --git a/SDL_Core/src/components/TransportManager/src/SDeviceInfo.cpp b/SDL_Core/src/components/TransportManager/src/SDeviceInfo.cpp
new file mode 100644
index 000000000..6fda35517
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/SDeviceInfo.cpp
@@ -0,0 +1,67 @@
+/**
+ * \file SDeviceInfo.cpp
+ * \brief Class SDeviceInfo.
+ * 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 "TransportManager/SDeviceInfo.hpp"
+
+NsSmartDeviceLink::NsTransportManager::SDeviceInfo::SDeviceInfo()
+: mDeviceHandle()
+, mDeviceType()
+, mUserFriendlyName()
+, mUniqueDeviceId()
+{
+}
+
+NsSmartDeviceLink::NsTransportManager::SDeviceInfo::SDeviceInfo(tDeviceHandle DeviceHandle, EDeviceType DeviceType, std::string UserFriendlyName, std::string UniqueDeviceId)
+: mDeviceHandle(DeviceHandle)
+, mDeviceType(DeviceType)
+, mUserFriendlyName(UserFriendlyName)
+, mUniqueDeviceId(UniqueDeviceId)
+{
+}
+
+NsSmartDeviceLink::NsTransportManager::SDeviceInfo::SDeviceInfo(const SDeviceInfo& other)
+: mDeviceHandle(other.mDeviceHandle)
+, mDeviceType(other.mDeviceType)
+, mUserFriendlyName(other.mUserFriendlyName)
+, mUniqueDeviceId(other.mUniqueDeviceId)
+{
+}
+
+bool NsSmartDeviceLink::NsTransportManager::SDeviceInfo::operator==( const SDeviceInfo& i_other ) const
+{
+ return ( (mDeviceHandle == i_other.mDeviceHandle)
+ && (mDeviceType == i_other.mDeviceType)
+ && (mUserFriendlyName == i_other.mUserFriendlyName)
+ && (mUniqueDeviceId == i_other.mUniqueDeviceId));
+}
diff --git a/SDL_Core/src/components/TransportManager/src/SInternalDeviceInfo.cpp b/SDL_Core/src/components/TransportManager/src/SInternalDeviceInfo.cpp
new file mode 100644
index 000000000..4b7d8753f
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/SInternalDeviceInfo.cpp
@@ -0,0 +1,49 @@
+/**
+ * \file SInternalDeviceInfo.cpp
+ * \brief Class SInternalDeviceInfo.
+ * 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 "SInternalDeviceInfo.hpp"
+
+NsSmartDeviceLink::NsTransportManager::SInternalDeviceInfo::SInternalDeviceInfo(void):
+mDeviceHandle(NsSmartDeviceLink::NsTransportManager::InvalidDeviceHandle),
+mUserFriendlyName(),
+mUniqueDeviceId()
+{
+}
+
+NsSmartDeviceLink::NsTransportManager::SInternalDeviceInfo::SInternalDeviceInfo(NsSmartDeviceLink::NsTransportManager::tDeviceHandle DeviceHandle, const std::string & UserFriendlyName, const std::string & UniqueDeviceId):
+mDeviceHandle(DeviceHandle),
+mUserFriendlyName(UserFriendlyName),
+mUniqueDeviceId(UniqueDeviceId)
+{
+}
diff --git a/SDL_Core/src/components/TransportManager/src/SInternalDeviceInfo.hpp b/SDL_Core/src/components/TransportManager/src/SInternalDeviceInfo.hpp
new file mode 100644
index 000000000..ee95588be
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/SInternalDeviceInfo.hpp
@@ -0,0 +1,88 @@
+/**
+ * \file SInternalDeviceInfo.hpp
+ * \brief Class SInternalDeviceInfo header.
+ * 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 __TRANSPORTMANAGER_SINTERNALDEVICEINFO_HPP__
+#define __TRANSPORTMANAGER_SINTERNALDEVICEINFO_HPP__
+
+#include <vector>
+
+#include "TransportManager/SDeviceInfo.hpp"
+
+namespace NsSmartDeviceLink
+{
+ namespace NsTransportManager
+ {
+ /**
+ * @brief Internal device information.
+ **/
+ struct SInternalDeviceInfo
+ {
+ /**
+ * @brief Default constructor.
+ **/
+ SInternalDeviceInfo(void);
+
+ /**
+ * @brief Constructor.
+ *
+ * @param DeviceHandle Device handle.
+ * @param UserFriendlyName User-friendly device name.
+ * @param UniqueDeviceId Unique device identifier across all devices.
+ **/
+ SInternalDeviceInfo(tDeviceHandle DeviceHandle, const std::string & UserFriendlyName, const std::string & UniqueDeviceId);
+
+ /**
+ * @brief Device handle.
+ **/
+ tDeviceHandle mDeviceHandle;
+
+ /**
+ * @brief User-friendly device name.
+ **/
+ std::string mUserFriendlyName;
+
+ /**
+ * @brief Unique device identifier across all devices.
+ **/
+ std::string mUniqueDeviceId;
+ };
+
+ /**
+ * @brief List of internal devices.
+ **/
+ typedef std::vector<SInternalDeviceInfo> tInternalDeviceList;
+ }
+}
+
+#endif
diff --git a/SDL_Core/src/components/TransportManager/src/TransportManagerLoggerHelpers.hpp b/SDL_Core/src/components/TransportManager/src/TransportManagerLoggerHelpers.hpp
new file mode 100644
index 000000000..b9578b292
--- /dev/null
+++ b/SDL_Core/src/components/TransportManager/src/TransportManagerLoggerHelpers.hpp
@@ -0,0 +1,53 @@
+/**
+ * \file TransportManagerLoggerHelpers.hpp
+ * \brief Class TransportManagerLoggerHelpers header.
+ * 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 __TRANSPORTMANAGER_TRANSPORTMANAGERLOGGERHELPERS_HPP__
+#define __TRANSPORTMANAGER_TRANSPORTMANAGERLOGGERHELPERS_HPP__
+
+// Log helpers for logs related to Connection Handle
+#define TM_CH_LOG4CPLUS_INFO(logger, ConnectionHandle, logEvent) LOG4CPLUS_INFO(logger, "[ConnectionHandle: " << ConnectionHandle << "]: " << logEvent)
+#define TM_CH_LOG4CPLUS_INFO_STR(logger, ConnectionHandle, logEvent) LOG4CPLUS_INFO_STR(logger, "[ConnectionHandle: " << ConnectionHandle << "]: " << logEvent)
+#define TM_CH_LOG4CPLUS_TRACE_METHOD(logger, ConnectionHandle, logEvent) LOG4CPLUS_TRACE_METHOD(logger, "[ConnectionHandle: " << ConnectionHandle << "]: " << logEvent)
+#define TM_CH_LOG4CPLUS_TRACE(logger, ConnectionHandle, logEvent) LOG4CPLUS_TRACE(logger, "[ConnectionHandle: " << ConnectionHandle << "]: " << logEvent)
+#define TM_CH_LOG4CPLUS_TRACE_STR(logger, ConnectionHandle, logEvent) LOG4CPLUS_TRACE_STR(logger, "[ConnectionHandle: " << ConnectionHandle << "]: " << logEvent)
+#define TM_CH_LOG4CPLUS_DEBUG(logger, ConnectionHandle, logEvent) LOG4CPLUS_DEBUG(logger, "[ConnectionHandle: " << ConnectionHandle << "]: " << logEvent)
+#define TM_CH_LOG4CPLUS_DEBUG_STR(logger, ConnectionHandle, logEvent) LOG4CPLUS_DEBUG_STR(logger, "[ConnectionHandle: " << ConnectionHandle << "]: " << logEvent)
+#define TM_CH_LOG4CPLUS_WARN(logger, ConnectionHandle, logEvent) LOG4CPLUS_WARN(logger, "[ConnectionHandle: " << ConnectionHandle << "]: " << logEvent)
+#define TM_CH_LOG4CPLUS_WARN_STR(logger, ConnectionHandle, logEvent) LOG4CPLUS_WARN_STR(logger, "[ConnectionHandle: " << ConnectionHandle << "]: " << logEvent)
+#define TM_CH_LOG4CPLUS_ERROR(logger, ConnectionHandle, logEvent) LOG4CPLUS_ERROR(logger, "[ConnectionHandle: " << ConnectionHandle << "]: " << logEvent)
+#define TM_CH_LOG4CPLUS_ERROR_STR(logger, ConnectionHandle, logEvent) LOG4CPLUS_ERROR_STR(logger, "[ConnectionHandle: " << ConnectionHandle << "]: " << logEvent)
+#define TM_CH_LOG4CPLUS_FATAL(logger, ConnectionHandle, logEvent) LOG4CPLUS_FATAL(logger, "[ConnectionHandle: " << ConnectionHandle << "]: " << logEvent)
+#define TM_CH_LOG4CPLUS_FATAL_STR(logger, ConnectionHandle, logEvent) LOG4CPLUS_FATAL_STR(logger, "[ConnectionHandle: " << ConnectionHandle << "]: " << logEvent)
+
+#endif //__TRANSPORTMANAGER_TRANSPORTMANAGERLOGGERHELPERS_HPP__