summaryrefslogtreecommitdiffstats
path: root/remote-processor
diff options
context:
space:
mode:
Diffstat (limited to 'remote-processor')
-rw-r--r--remote-processor/Message.cpp48
-rw-r--r--remote-processor/Message.h23
-rw-r--r--remote-processor/RemoteProcessorServer.cpp44
-rw-r--r--remote-processor/Socket.cpp44
-rw-r--r--remote-processor/Socket.h56
5 files changed, 169 insertions, 46 deletions
diff --git a/remote-processor/Message.cpp b/remote-processor/Message.cpp
index 8efec1f..8591847 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 @@ uint32_t CMessage::getRemainingDataSize() const
}
// Send/Receive
-bool CMessage::serialize(CSocket* pSocket, bool bOut)
+CMessage::Result CMessage::serialize(CSocket* pSocket, bool bOut, string& strError)
{
if (bOut) {
@@ -141,7 +142,10 @@ bool CMessage::serialize(CSocket* pSocket, bool bOut)
if (!pSocket->write(&uiSyncWord, sizeof(uiSyncWord))) {
- return false;
+ if (pSocket->hasPeerDisconnected()) {
+ return peerDisconnected;
+ }
+ return error;
}
// Size
@@ -149,19 +153,22 @@ bool CMessage::serialize(CSocket* pSocket, bool bOut)
if (!pSocket->write(&uiSize, sizeof(uiSize))) {
- return false;
+ strError += string("Size write failed: ") + strerror(errno);
+ return error;
}
// Msg Id
if (!pSocket->write(&_ucMsgId, sizeof(_ucMsgId))) {
- return false;
+ strError += string("Msg write failed: ") + strerror(errno);
+ return error;
}
// Data
if (!pSocket->write(_pucData, _uiDataSize)) {
- return false;
+ strError = string("Data write failed: ") + strerror(errno);
+ return error;
}
// Checksum
@@ -169,7 +176,8 @@ bool CMessage::serialize(CSocket* pSocket, bool bOut)
if (!pSocket->write(&ucChecksum, sizeof(ucChecksum))) {
- return false;
+ strError = string("Checksum write failed: ") + strerror(errno);
+ return error;
}
} else {
@@ -178,13 +186,18 @@ bool CMessage::serialize(CSocket* pSocket, bool bOut)
if (!pSocket->read(&uiSyncWord, sizeof(uiSyncWord))) {
- return false;
+ strError = string("Sync read failed: ") + strerror(errno);
+ if (pSocket->hasPeerDisconnected()) {
+ return peerDisconnected;
+ }
+ return error;
}
// Check Sync word
if (uiSyncWord != SYNC_WORD) {
- return false;
+ strError = "Sync word incorrect";
+ return error;
}
// Size
@@ -192,13 +205,15 @@ bool CMessage::serialize(CSocket* pSocket, bool bOut)
if (!pSocket->read(&uiSize, sizeof(uiSize))) {
- return false;
+ strError = string("Size read failed: ") + strerror(errno);
+ return error;
}
// Msg Id
if (!pSocket->read(&_ucMsgId, sizeof(_ucMsgId))) {
- return false;
+ strError = string("Msg id read failed: ") + strerror(errno);
+ return error;
}
// Data
@@ -209,7 +224,8 @@ bool CMessage::serialize(CSocket* pSocket, bool bOut)
// Data receive
if (!pSocket->read(_pucData, _uiDataSize)) {
- return false;
+ strError = string("Data read failed: ") + strerror(errno);
+ return error;
}
// Checksum
@@ -217,19 +233,21 @@ bool CMessage::serialize(CSocket* pSocket, bool bOut)
if (!pSocket->read(&ucChecksum, sizeof(ucChecksum))) {
- return false;
+ strError = string("Checksum read failed: ") + strerror(errno);
+ return error;
}
// Compare
if (ucChecksum != computeChecksum()) {
- return false;
+ strError = "Received checksum != computed checksum";
+ return error;
}
// Collect data in derived
collectReceivedData();
}
- return true;
+ return success;
}
// Checksum
diff --git a/remote-processor/Message.h b/remote-processor/Message.h
index 799a525..feafc83 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,25 @@ public:
CMessage();
virtual ~CMessage();
- // Send/Receive
- bool serialize(CSocket* pSocket, bool bOut);
+ enum Result {
+ success,
+ peerDisconnected,
+ error
+ };
+
+ /** 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 success if a correct message could be recv/send
+ * peerDisconnected if the peer disconnected before the first socket access.
+ * error if the message could not be read/write for any other reason
+ */
+ Result 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..8c66109 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,8 @@
*/
#include "RemoteProcessorServer.h"
#include "ListeningSocket.h"
+#include <iostream>
+#include <memory>
#include <assert.h>
#include <poll.h>
#include <unistd.h>
@@ -146,15 +148,15 @@ void CRemoteProcessorServer::run()
// New connection
void CRemoteProcessorServer::handleNewConnection()
{
- CSocket* pClientSocket = _pListeningSocket->accept();
+ const auto_ptr<CSocket> clientSocket(_pListeningSocket->accept());
- if (!pClientSocket) {
+ if (clientSocket.get() == NULL) {
return;
}
// Set timeout
- pClientSocket->setTimeout(5000);
+ clientSocket->setTimeout(5000);
// Process all incoming requests from the client
while (true) {
@@ -163,11 +165,20 @@ void CRemoteProcessorServer::handleNewConnection()
// Create command message
CRequestMessage requestMessage;
+ string strError;
///// Receive command
- if (!requestMessage.serialize(pClientSocket, false)) {
-
- // Bail out
- break;
+ CRequestMessage::Result res;
+ res = requestMessage.serialize(clientSocket.get(), false, strError);
+
+ switch (res) {
+ case CRequestMessage::error:
+ cout << "Error while receiving message: " << strError << endl;
+ // fall through
+ case CRequestMessage::peerDisconnected:
+ // Consider peer disconnection as normal, no log
+ return; // Bail out
+ case CRequestMessage::success:
+ break; // No error, continue
}
// Actually process the request
@@ -191,12 +202,17 @@ void CRemoteProcessorServer::handleNewConnection()
CAnswerMessage answerMessage(strResult, bSuccess);
///// Send answer
- if (!answerMessage.serialize(pClientSocket, true)) {
-
- // Bail out
- break;
+ res = answerMessage.serialize(clientSocket.get(), true, strError);
+
+ switch (res) {
+ case CRequestMessage::peerDisconnected:
+ // Peer should not disconnect while waiting for an answer
+ // Fall through to log the error and bail out
+ case CRequestMessage::error:
+ cout << "Error while receiving message: " << strError << endl;
+ return; // Bail out
+ case CRequestMessage::success:
+ break; // No error, continue
}
}
- // Remove client socket
- delete pClientSocket;
}
diff --git a/remote-processor/Socket.cpp b/remote-processor/Socket.cpp
index d79b45a..b36d32f 100644
--- a/remote-processor/Socket.cpp
+++ b/remote-processor/Socket.cpp
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (c) 2011-2014, Intel Corporation
* All rights reserved.
*
@@ -34,6 +34,7 @@
#include <assert.h>
#include <netdb.h>
#include <strings.h>
+#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
@@ -109,12 +110,24 @@ bool CSocket::read(void* pvData, uint32_t uiSize)
int32_t iAccessedSize = ::recv(_iSockFd, &pucData[uiOffset], uiSize, MSG_NOSIGNAL);
- if (!iAccessedSize || iAccessedSize == -1) {
-
+ 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:
+ // errno == EINTR => The recv system call was interrupted, try again
+ if (errno != EINTR) {
+ return false;
+ }
+ break;
+
+ default:
+ uiSize -= iAccessedSize;
+ uiOffset += iAccessedSize;
}
- uiSize -= iAccessedSize;
- uiOffset += iAccessedSize;
}
return true;
}
@@ -129,12 +142,19 @@ bool CSocket::write(const void* pvData, uint32_t uiSize)
int32_t iAccessedSize = ::send(_iSockFd, &pucData[uiOffset], uiSize, MSG_NOSIGNAL);
- if (!iAccessedSize || iAccessedSize == -1) {
-
- return false;
+ 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;
+ }
+ } else {
+ uiSize -= iAccessedSize;
+ uiOffset += iAccessedSize;
}
- uiSize -= iAccessedSize;
- uiOffset += iAccessedSize;
}
return true;
}
@@ -144,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;
};