[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 <kevinx.rocard@intel.com>
Signed-off-by: Mattijs Korpershoek <mattijsx.korpershoek@intel.com>
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 <string.h>
 #include <assert.h>
+#include <errno.h>
 
 CMessage::CMessage(uint8_t ucMsgId) : _ucMsgId(ucMsgId), _pucData(NULL), _uiDataSize(0), _uiIndex(0)
 {
@@ -123,7 +124,7 @@
 }
 
 // Send/Receive
-bool CMessage::serialize(CSocket* pSocket, bool bOut)
+bool CMessage::serialize(CSocket* pSocket, bool bOut, string& strError)
 {
     if (bOut) {
 
@@ -141,6 +142,7 @@
 
         if (!pSocket->write(&uiSyncWord, sizeof(uiSyncWord))) {
 
+            strError += string("Sync write failed: ") + strerror(errno);
             return false;
         }
 
@@ -149,18 +151,21 @@
 
         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 @@
 
         if (!pSocket->write(&ucChecksum, sizeof(ucChecksum))) {
 
+            strError = string("Checksum write failed: ") + strerror(errno);
             return false;
         }
 
@@ -178,12 +184,14 @@
 
         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 @@
 
         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 @@
         // Data receive
         if (!pSocket->read(_pucData, _uiDataSize)) {
 
+            strError = string("Data read failed: ") + strerror(errno);
             return false;
         }
 
@@ -217,11 +228,13 @@
 
         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 @@
     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 <iostream>
 #include <assert.h>
 #include <poll.h>
 #include <unistd.h>
@@ -163,10 +164,13 @@
         // 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 @@
         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 @@
         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 @@
         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 @@
 {
     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 @@
 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 @@
     // 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;
 };