122 lines
3.8 KiB
C++
122 lines
3.8 KiB
C++
|
|
#include "TcpBase.hpp"
|
|
|
|
#include <sys/socket.h>
|
|
#include <string.h>
|
|
|
|
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<size_t>(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<uint32_t>(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<char*>(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<const char*>(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;
|
|
}
|