#include "TcpBase.hpp" #include #include TcpBase::TcpBase(LoggerService* logger) : logger_(logger) { } TcpBase::~TcpBase() { } ssize_t TcpBase::tcpRead(int fd, void* buffer, size_t maxBytes) { // read header first char header[kHeaderSize]; ssize_t bytesReceived = receiveFull(fd, &header, kHeaderSize); if(bytesReceived != kHeaderSize) { logger_->log("TcpNetworker", LogFlag::Error, "Unable to receive header."); return -1; } // parse header: 4 bytes payload length 4 bytes message type uint32_t payloadLength; uint32_t messageType; memcpy(&payloadLength, header, sizeof(payloadLength)); memcpy(&messageType, header + sizeof(payloadLength), sizeof(messageType)); size_t payloadLengthS = static_cast(payloadLength); if(maxBytes < payloadLength) { logger_->log("TcpNetworker", LogFlag::Warning, "Payload length is larger than buffer size; payload may be truncated."); payloadLengthS = maxBytes; } // read payload bytesReceived = receiveFull(fd, buffer, payloadLengthS); if(bytesReceived != payloadLengthS) { logger_->log("TcpNetworker", LogFlag::Error, "Did not receive amount of expected data."); } return bytesReceived; } ssize_t TcpBase::tcpTimedRead(int fd, void* buffer, size_t maxBytes, int timeoutPlaceholder) { return 0; } ssize_t TcpBase::tcpSend(int fd, const void* buffer, size_t numBytes) { // assemble header char header[kHeaderSize]; uint32_t payloadLength = static_cast(numBytes & 0xffffffffffffffff); uint32_t messageType = 0; // placeholder memcpy(header, &payloadLength, sizeof(payloadLength)); memcpy(header + sizeof(payloadLength), &messageType, sizeof(messageType)); // send header ssize_t bytesSent = sendFull(fd, header, kHeaderSize); if(bytesSent != kHeaderSize) { logger_->log("TcpNetworker", LogFlag::Error, "Error sending header."); } // send payload bytesSent = sendFull(fd, buffer, numBytes); if(bytesSent != numBytes) { logger_->log("TcpNetworker", LogFlag::Error, "Error sending payload."); } return bytesSent; } ssize_t TcpBase::tcpTimedSend(int fd, const void* backuffer, size_t numBytes, int timeoutPlaceholder) { return 0; } ssize_t TcpBase::receiveHeader(int fd, void* buffer, size_t maxBytes) { return 0; } ssize_t TcpBase::receivePayload(int fd, void* buffer, size_t maxBytes) { return 0; } ssize_t TcpBase::sendHeader(int fd, const void* buffer, size_t maxBytes) { return 0; } ssize_t TcpBase::sendPayload(int fd, const void* buffer, size_t maxBytes) { return 0; } ssize_t TcpBase::receiveFull(int fd, void* buffer, size_t maxBytes) { ssize_t total = 0; // attempt to receive maxBytes bytes; continue receiving until we have received maxBytes bytes while(total < maxBytes) { ssize_t bytesReceived = recv(fd, static_cast(buffer) + total, maxBytes - total, 0); if (bytesReceived <= 0) return bytesReceived; // error or connection closed total += bytesReceived; } return total; } ssize_t TcpBase::sendFull(int fd, const void* buffer, size_t numBytes) { ssize_t total = 0; // attempt to receive maxBytes bytes; continue receiving until we have received maxBytes bytes while(total < numBytes) { ssize_t bytesSent = send(fd, static_cast(buffer) + total, numBytes - total, 0); // last arg is flags, 0=default // MSG_PEEK: read without consuming the message from the queue // MSG_WAITALL: block until all of the specified size is received // MSG_DONTWAIT: non-blocking receive, returns -1 immediately if queue is empty if (bytesSent <= 0) return bytesSent; // error or connection closed total += bytesSent; } return total; }