summaryrefslogtreecommitdiff
path: root/SDL_Core/src/components/TransportManager/src/CDeviceAdapter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'SDL_Core/src/components/TransportManager/src/CDeviceAdapter.cpp')
-rw-r--r--SDL_Core/src/components/TransportManager/src/CDeviceAdapter.cpp866
1 files changed, 866 insertions, 0 deletions
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;
+}