From ef8d727ca0eb346af951d15d84ba6f2b9564adf5 Mon Sep 17 00:00:00 2001 From: Kevin Rocard Date: Wed, 23 Apr 2014 20:34:14 +0200 Subject: [remote-processor] Add context information on failure BZ: 190038 Remote processor was not displaying information in case of network read/write error. Add some error messages to ease debug. Change-Id: I465062e8cf77f94b3d4d4d0c71338c4630aac276 Signed-off-by: Kevin Rocard Signed-off-by: Mattijs Korpershoek --- remote-processor/Message.cpp | 17 +++++++-- remote-processor/Message.h | 15 ++++++-- remote-processor/RemoteProcessorServer.cpp | 13 ++++--- remote-processor/Socket.cpp | 10 ++++++ remote-processor/Socket.h | 56 +++++++++++++++++++++++++++--- 5 files changed, 98 insertions(+), 13 deletions(-) (limited to 'remote-processor') diff --git a/remote-processor/Message.cpp b/remote-processor/Message.cpp index 8efec1f..db24d80 100644 --- a/remote-processor/Message.cpp +++ b/remote-processor/Message.cpp @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2011-2014, Intel Corporation * All rights reserved. * @@ -33,6 +33,7 @@ #include "RemoteProcessorProtocol.h" #include #include +#include CMessage::CMessage(uint8_t ucMsgId) : _ucMsgId(ucMsgId), _pucData(NULL), _uiDataSize(0), _uiIndex(0) { @@ -123,7 +124,7 @@ uint32_t CMessage::getRemainingDataSize() const } // Send/Receive -bool CMessage::serialize(CSocket* pSocket, bool bOut) +bool CMessage::serialize(CSocket* pSocket, bool bOut, string& strError) { if (bOut) { @@ -141,6 +142,7 @@ bool CMessage::serialize(CSocket* pSocket, bool bOut) if (!pSocket->write(&uiSyncWord, sizeof(uiSyncWord))) { + strError += string("Sync write failed: ") + strerror(errno); return false; } @@ -149,18 +151,21 @@ bool CMessage::serialize(CSocket* pSocket, bool bOut) if (!pSocket->write(&uiSize, sizeof(uiSize))) { + strError += string("Size write failed: ") + strerror(errno); return false; } // Msg Id if (!pSocket->write(&_ucMsgId, sizeof(_ucMsgId))) { + strError += string("Msg write failed: ") + strerror(errno); return false; } // Data if (!pSocket->write(_pucData, _uiDataSize)) { + strError = string("Data write failed: ") + strerror(errno); return false; } @@ -169,6 +174,7 @@ bool CMessage::serialize(CSocket* pSocket, bool bOut) if (!pSocket->write(&ucChecksum, sizeof(ucChecksum))) { + strError = string("Checksum write failed: ") + strerror(errno); return false; } @@ -178,12 +184,14 @@ bool CMessage::serialize(CSocket* pSocket, bool bOut) if (!pSocket->read(&uiSyncWord, sizeof(uiSyncWord))) { + strError = string("Sync read failed: ") + strerror(errno); return false; } // Check Sync word if (uiSyncWord != SYNC_WORD) { + strError = "Sync word incorrect"; return false; } @@ -192,12 +200,14 @@ bool CMessage::serialize(CSocket* pSocket, bool bOut) if (!pSocket->read(&uiSize, sizeof(uiSize))) { + strError = string("Size read failed: ") + strerror(errno); return false; } // Msg Id if (!pSocket->read(&_ucMsgId, sizeof(_ucMsgId))) { + strError = string("Msg id read failed: ") + strerror(errno); return false; } @@ -209,6 +219,7 @@ bool CMessage::serialize(CSocket* pSocket, bool bOut) // Data receive if (!pSocket->read(_pucData, _uiDataSize)) { + strError = string("Data read failed: ") + strerror(errno); return false; } @@ -217,11 +228,13 @@ bool CMessage::serialize(CSocket* pSocket, bool bOut) if (!pSocket->read(&ucChecksum, sizeof(ucChecksum))) { + strError = string("Checksum read failed: ") + strerror(errno); return false; } // Compare if (ucChecksum != computeChecksum()) { + strError = "Received checksum != computed checksum"; return false; } diff --git a/remote-processor/Message.h b/remote-processor/Message.h index 799a525..4f22977 100644 --- a/remote-processor/Message.h +++ b/remote-processor/Message.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2011-2014, Intel Corporation * All rights reserved. * @@ -43,8 +43,17 @@ public: CMessage(); virtual ~CMessage(); - // Send/Receive - bool serialize(CSocket* pSocket, bool bOut); + /** Write or read the message on pSocket. + * + * @param[in,out] pSocket is the socket on wich IO operation will be made. + * @param[in] bOut if true message should be read, + * if false it should be written. + * @param[out] strError on failure, a string explaining the error, + * on success, undefined. + * + * @return true on success, false on failure. + */ + bool serialize(CSocket* pSocket, bool bOut, std::string &strError); protected: // Msg Id diff --git a/remote-processor/RemoteProcessorServer.cpp b/remote-processor/RemoteProcessorServer.cpp index daa4894..487379e 100644 --- a/remote-processor/RemoteProcessorServer.cpp +++ b/remote-processor/RemoteProcessorServer.cpp @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2011-2014, Intel Corporation * All rights reserved. * @@ -29,6 +29,7 @@ */ #include "RemoteProcessorServer.h" #include "ListeningSocket.h" +#include #include #include #include @@ -163,10 +164,13 @@ void CRemoteProcessorServer::handleNewConnection() // Create command message CRequestMessage requestMessage; + string strError; ///// Receive command - if (!requestMessage.serialize(pClientSocket, false)) { + if (!requestMessage.serialize(pClientSocket, false, strError)) { - // Bail out + if (!pClientSocket->hasPeerDisconnected()) { + cout << "Error while receiving message: " << strError << endl; + } break; } @@ -191,9 +195,10 @@ void CRemoteProcessorServer::handleNewConnection() CAnswerMessage answerMessage(strResult, bSuccess); ///// Send answer - if (!answerMessage.serialize(pClientSocket, true)) { + if (!answerMessage.serialize(pClientSocket, true, strError)) { // Bail out + cout << "Error while sending message: " << strError << endl; break; } } diff --git a/remote-processor/Socket.cpp b/remote-processor/Socket.cpp index 07e6b60..b36d32f 100644 --- a/remote-processor/Socket.cpp +++ b/remote-processor/Socket.cpp @@ -113,6 +113,8 @@ bool CSocket::read(void* pvData, uint32_t uiSize) switch (iAccessedSize) { case 0: // recv return value is 0 when the peer has performed an orderly shutdown. + _disconnected = true; + errno = ECONNRESET; // Warn the client that the client disconnected. return false; case -1: @@ -141,6 +143,10 @@ bool CSocket::write(const void* pvData, uint32_t uiSize) int32_t iAccessedSize = ::send(_iSockFd, &pucData[uiOffset], uiSize, MSG_NOSIGNAL); if (iAccessedSize == -1) { + if (errno == ECONNRESET) { + // Peer has disconnected + _disconnected = true; + } // errno == EINTR => The send system call was interrupted, try again if (errno != EINTR) { return false; @@ -158,3 +164,7 @@ int CSocket::getFd() const { return _iSockFd; } + +bool CSocket::hasPeerDisconnected() { + return _disconnected; +} diff --git a/remote-processor/Socket.h b/remote-processor/Socket.h index 9ecc38a..e8d360f 100644 --- a/remote-processor/Socket.h +++ b/remote-processor/Socket.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2011-2014, Intel Corporation * All rights reserved. * @@ -37,6 +37,14 @@ using namespace std; struct sockaddr_in; struct in_addr; +/** Readable and writable socket. + * + * The class does not encapsulate completely it's internal file descriptor as + * it can be retrieve by the getFd method. + * + * This "feature" means that it's state consistency can not + * be enforced by the class but rather by clients. + */ class CSocket { public: @@ -50,16 +58,56 @@ public: // Communication timeout void setTimeout(uint32_t uiMilliseconds); - // Read + /* Read data + * + * On failure errno will be set appropriately (see send). + * If the client disconnects, false will be returned and + * - hasPeerDisconnected will return true + * - errno is set to ECONNRESET. + * @param[in] pvData - on success: will contain the sent data + * - on failure: undefined + * @param[in] uiSize size of the data to receive. + * + * @return true if all data could be read, false otherwise. + */ bool read(void* pvData, uint32_t uiSize); - // Write + + /* Write data + * + * On failure errno will be set (see recv) + * @param[in] pvData data to send. + * @param[in] uiSize is the size of the data to send. + * + * @return true if all data could be read, false otherwise. + */ bool write(const void* pvData, uint32_t uiSize); - // Fd + /** @return the managed file descriptor. + * + * The client can then bind/connect/accept/listen/... the socket. + */ int getFd() const; + + /** @return true if the peer has disconnected. + * + * The internal fd is returned by getFd and clients can use it for + * bind/connect/read/write/... as a result it's state can not be tracked. + * + * Thus hasPeerDisconnected returns true only if the disconnection + * was notified during a call to CSocket::write or CSocket::read. + */ + bool hasPeerDisconnected(); + protected: // Socket address init void initSockAddrIn(struct sockaddr_in* pSockAddrIn, uint32_t uiInAddr, uint16_t uiPort) const; private: int _iSockFd; + /** If the peer disconnected. + * + * This is not the state of _iSockFd (connected/disconnected) + * + * See hasPeerDisconnected for more details. + */ + bool _disconnected; }; -- cgit v1.1