22 #include "visiontransfer/datablockprotocol.h" 23 #include "visiontransfer/exceptions.h" 31 #include <arpa/inet.h> 34 #define LOG_ERROR(expr) 44 DataBlockProtocol::DataBlockProtocol(
bool server, ProtocolType protType,
int maxUdpPacketSize)
45 : isServer(server), protType(protType),
47 overwrittenTransferData{0},
48 overwrittenTransferIndex{-1},
49 overwrittenTransferBlock{-1},
50 transferHeaderData{
nullptr},
51 transferHeaderSize{0},
52 totalBytesCompleted{0}, totalTransferSize{0},
53 waitingForMissingSegments(
false),
54 totalReceiveSize(0), connectionConfirmed(
false),
55 confirmationMessagePending(
false), eofMessagePending(
false),
56 clientConnectionPending(
false), resendMessagePending(
false),
57 lastRemoteHostActivity(), lastSentHeartbeat(),
58 lastReceivedHeartbeat(std::chrono::steady_clock::now()),
59 finishedReception(
false), droppedReceptions(0),
60 completedReceptions(0), lostSegmentRate(0.0), lostSegmentBytes(0),
61 unprocessedMsgLength(0), headerReceived(
false) {
63 if(protType == PROTOCOL_TCP) {
68 minPayloadSize = maxPayloadSize;
71 resizeReceiveBuffer();
74 void DataBlockProtocol::splitRawOffset(
int rawSegmentOffset,
int& dataBlockID,
int& segmentOffset) {
75 int selector = (rawSegmentOffset >> 28) & 0xf;
76 dataBlockID = selector & 0x7;
77 segmentOffset = rawSegmentOffset & 0x0FFFffff;
80 int DataBlockProtocol::mergeRawOffset(
int dataBlockID,
int segmentOffset,
int reserved_defaults0) {
81 return ((reserved_defaults0 & 1) << 31) | ((dataBlockID & 0x07) << 28) | (segmentOffset & 0x0FFFffff);
84 void DataBlockProtocol::zeroStructures() {
85 for (
int i=0; i<MAX_DATA_BLOCKS; ++i) {
86 rawDataArr[i] =
nullptr;
87 rawDataArrStrideHackOrig[i] = 0;
88 rawDataArrStrideHackRepl[i] = 0;
90 transferOffset[i] = 0;
93 std::memset(overwrittenTransferData, 0,
sizeof(overwrittenTransferData));
94 overwrittenTransferIndex = -1;
95 overwrittenTransferBlock = -1;
96 lastTransmittedBlock = -1;
102 overwrittenTransferIndex = -1;
103 overwrittenTransferBlock = -1;
104 totalBytesCompleted = 0;
105 totalTransferSize = 0;
106 numTransferBlocks = 0;
107 missingTransferSegments.clear();
111 if (transferHeaderData ==
nullptr) {
112 throw ProtocolException(
"Tried to set data block size before initializing header!");
113 }
else if (block >= numTransferBlocks) {
114 throw ProtocolException(
"Request to set data block size - block index too high!");
116 transferSize[block] = bytes;
118 hp->netTransferSizes[block] = htonl(bytes);
122 if(!transferDone && transferOffset > 0) {
124 }
else if(headerSize + 9 > static_cast<int>(
sizeof(controlMessageBuffer))) {
128 numTransferBlocks = blocks;
130 transferDone =
false;
131 for (
int i=0; i<MAX_DATA_BLOCKS; ++i) {
132 this->transferSize[i] = 0;
137 transferHeaderData = &data[-headerBaseOffset];
140 unsigned short netHeaderSize = htons(static_cast<unsigned short>(headerSize));
141 ourHeader->netHeaderSize = netHeaderSize;
142 ourHeader->netTransferSizeDummy = htonl(-1);
144 headerSize += headerBaseOffset;
146 if(protType == PROTOCOL_UDP) {
148 transferHeaderData[headerSize++] = HEADER_MESSAGE;
149 transferHeaderData[headerSize++] = 0xFF;
150 transferHeaderData[headerSize++] = 0xFF;
151 transferHeaderData[headerSize++] = 0xFF;
152 transferHeaderData[headerSize++] = 0xFF;
155 transferHeaderSize = headerSize;
159 if(transferHeaderSize == 0 || transferHeaderData ==
nullptr) {
163 transferDone =
false;
164 rawDataArr[block] = data;
165 transferOffset[block] = 0;
166 overwrittenTransferIndex = -1;
167 overwrittenTransferBlock = -1;
168 rawValidBytes[block] = min(transferSize[block], validBytes);
169 totalBytesCompleted = 0;
173 if(validBytes >= transferSize[block]) {
174 rawValidBytes[block] = transferSize[block];
175 }
else if(validBytes < static_cast<int>(
sizeof(
int))) {
176 rawValidBytes[block] = 0;
178 rawValidBytes[block] = validBytes;
182 std::string DataBlockProtocol::statusReport() {
183 std::stringstream ss;
184 ss <<
"DataBlockProtocol, blocks=" << numTransferBlocks <<
": ";
185 for (
int i=0; i<numTransferBlocks; ++i) {
186 ss << i <<
":(len " << transferSize[i] <<
" ofs " << transferOffset[i] <<
" rawvalid " << rawValidBytes[i] <<
") ";
188 ss <<
" total done: " << totalBytesCompleted <<
"/" << totalTransferSize;
193 if(transferDone || rawValidBytes == 0) {
200 if(protType == PROTOCOL_TCP && !anyPayloadReceived() && transferHeaderData !=
nullptr) {
201 length = transferHeaderSize;
202 const unsigned char* ret = transferHeaderData;
203 transferHeaderData =
nullptr;
209 restoreTransferBuffer();
212 int block = -1, offset = -1;
213 getNextTransferSegment(block, offset, length);
218 if(protType == PROTOCOL_UDP) {
220 overwrittenTransferBlock = block;
221 overwrittenTransferIndex = offset + length;
223 std::memcpy(overwrittenTransferData, segmentHeader,
sizeof(
SegmentHeaderUDP));
224 segmentHeader->segmentOffset =
static_cast<int>(htonl(mergeRawOffset(block, offset)));
226 lastTransmittedBlock = block;
227 return &rawDataArr[block][offset];
231 overwrittenTransferBlock = block;
232 overwrittenTransferIndex = headerOffset;
234 std::memcpy(overwrittenTransferData, segmentHeader,
sizeof(
SegmentHeaderTCP));
235 segmentHeader->fragmentSize = htons(length);
236 segmentHeader->segmentOffset =
static_cast<int>(htonl(mergeRawOffset(block, offset)));
238 lastTransmittedBlock = block;
239 return &rawDataArr[block][headerOffset];
244 void DataBlockProtocol::getNextTransferSegment(
int& block,
int& offset,
int& length) {
245 if(missingTransferSegments.size() == 0) {
247 int sendBlock = 0, amount = 0;
248 for (
int i=0; i<numTransferBlocks; ++i) {
249 int avail = std::min(transferSize[i], rawValidBytes[i]);
250 avail -= transferOffset[i];
251 if (avail > amount) {
256 length = std::min(maxPayloadSize, amount);
257 if(length == 0 || (length < minPayloadSize && rawValidBytes[sendBlock] != transferSize[sendBlock])) {
263 offset = transferOffset[sendBlock];
264 transferOffset[sendBlock] += length;
265 if (protType == PROTOCOL_UDP) {
266 bool complete =
true;
267 for (
int i=0; i<numTransferBlocks; ++i) {
268 if (transferOffset[i] < transferSize[i]) {
274 eofMessagePending =
true;
279 splitRawOffset(missingTransferSegments.front().first, block, offset);
280 length = std::min(maxPayloadSize, missingTransferSegments.front().second);
281 LOG_ERROR(
"Re-transmitting: " << offset <<
" - " << (offset + length));
283 int remaining = missingTransferSegments[0].second - length;
286 missingTransferSegments.pop_front();
289 missingTransferSegments.front().first += length;
290 missingTransferSegments.front().second = remaining;
295 void DataBlockProtocol::restoreTransferBuffer() {
296 if(overwrittenTransferBlock >= 0) {
297 if(protType == PROTOCOL_UDP) {
298 std::memcpy(&rawDataArr[overwrittenTransferBlock][overwrittenTransferIndex], overwrittenTransferData,
sizeof(
SegmentHeaderUDP));
300 std::memcpy(&rawDataArr[overwrittenTransferBlock][overwrittenTransferIndex], overwrittenTransferData,
sizeof(
SegmentHeaderTCP));
303 overwrittenTransferIndex = -1;
304 overwrittenTransferBlock = -1;
308 for (
int i=0; i<numTransferBlocks; ++i) {
309 if (transferOffset[i] < transferSize[i])
return false;
311 return !eofMessagePending;
315 if(protType == PROTOCOL_TCP) {
316 return MAX_TCP_BYTES_TRANSFER;
318 return MAX_UDP_RECEPTION;
323 return &receiveBuffer[receiveOffset];
327 transferComplete =
false;
332 if(finishedReception) {
337 if(protType == PROTOCOL_UDP) {
338 processReceivedUdpMessage(length, transferComplete);
340 processReceivedTcpMessage(length, transferComplete);
343 transferComplete = finishedReception;
346 void DataBlockProtocol::processReceivedUdpMessage(
int length,
bool&
transferComplete) {
347 if(length < static_cast<int>(
sizeof(
int)) ||
348 0 + length > static_cast<int>(receiveBuffer.size())) {
353 int rawSegmentOffset = ntohl(*reinterpret_cast<int*>(
354 &receiveBuffer[0 + length -
sizeof(
int)]));
356 int dataBlockID, segmentOffset;
357 splitRawOffset(rawSegmentOffset, dataBlockID, segmentOffset);
359 if(rawSegmentOffset == static_cast<int>(0xFFFFFFFF)) {
361 processControlMessage(length);
362 }
else if(headerReceived) {
364 int realPayloadOffset = 0;
365 int payloadLength = length -
sizeof(int);
367 if(segmentOffset != blockReceiveOffsets[dataBlockID]) {
370 if(!waitingForMissingSegments &&
371 segmentOffset > blockReceiveOffsets[dataBlockID]
372 && segmentOffset + payloadLength < (
int)blockReceiveBuffers[dataBlockID].size()) {
374 LOG_ERROR(
"Missing segment: " << blockReceiveOffsets[dataBlockID] <<
" - " << segmentOffset
375 <<
" (" << missingReceiveSegments.size() <<
")");
377 MissingReceiveSegment missingSeg;
378 missingSeg.offset = mergeRawOffset(dataBlockID, blockReceiveOffsets[dataBlockID]);
379 missingSeg.length = segmentOffset - blockReceiveOffsets[dataBlockID];
380 missingSeg.isEof =
false;
381 lostSegmentBytes += missingSeg.length;
382 missingReceiveSegments.push_back(missingSeg);
385 memcpy(&blockReceiveBuffers[dataBlockID][segmentOffset], &receiveBuffer[0 + realPayloadOffset], payloadLength);
387 blockReceiveOffsets[dataBlockID] = segmentOffset + payloadLength;
393 if(segmentOffset > 0 ) {
394 if(blockReceiveOffsets[dataBlockID] > 0) {
395 LOG_ERROR(
"Resend failed!");
399 LOG_ERROR(
"Missed EOF message!");
404 memcpy(&blockReceiveBuffers[dataBlockID][segmentOffset], &receiveBuffer[0 + realPayloadOffset], payloadLength);
406 blockReceiveOffsets[dataBlockID] = segmentOffset + payloadLength;
407 if (waitingForMissingSegments) {
409 if ((missingReceiveSegments.size() == 1) && (missingReceiveSegments.front().length <= payloadLength)) {
411 blockValidSize[dataBlockID] = blockReceiveSize[dataBlockID];
413 blockValidSize[dataBlockID] = segmentOffset + payloadLength;
415 }
else if (missingReceiveSegments.size() == 0) {
416 blockValidSize[dataBlockID] = segmentOffset + payloadLength;
420 if(segmentOffset == 0 && dataBlockID == 0) {
422 lastRemoteHostActivity = std::chrono::steady_clock::now();
426 integrateMissingUdpSegments(dataBlockID, segmentOffset, payloadLength);
430 void DataBlockProtocol::integrateMissingUdpSegments(
int block,
int lastSegmentOffset,
int lastSegmentSize) {
431 if(waitingForMissingSegments) {
433 int checkBlock, checkOffset;
434 MissingReceiveSegment& firstSeg = missingReceiveSegments.front();
435 splitRawOffset(firstSeg.offset, checkBlock, checkOffset);
436 if(lastSegmentOffset != checkOffset) {
437 LOG_ERROR(
"Received invalid resend: " << lastSegmentOffset);
440 firstSeg.offset += lastSegmentSize;
441 firstSeg.length -= lastSegmentSize;
442 if(firstSeg.length == 0) {
443 missingReceiveSegments.pop_front();
446 if(missingReceiveSegments.size() == 0) {
447 waitingForMissingSegments =
false;
448 finishedReception =
true;
450 blockReceiveOffsets[block] = missingReceiveSegments.front().offset;
456 void DataBlockProtocol::processReceivedTcpMessage(
int length,
bool& transferComplete) {
458 if(!headerReceived) {
459 int totalHeaderSize = parseReceivedHeader(length, 0);
460 if(totalHeaderSize == 0) {
462 receiveOffset += length;
467 length -= totalHeaderSize;
474 int movelength = receiveOffset + length;
475 ::memmove(&receiveBuffer[0], &receiveBuffer[totalHeaderSize], movelength);
476 receiveOffset = movelength;
479 receiveOffset += length;
482 if (legacyTransfer) {
484 int remainingSize = blockReceiveSize[0] - blockValidSize[0];
485 int availableSize = std::min(receiveOffset, remainingSize);
487 std::memcpy(&blockReceiveBuffers[0][blockReceiveOffsets[0]], &receiveBuffer[0], availableSize);
488 blockReceiveOffsets[0] += availableSize;
489 blockValidSize[0] = blockReceiveOffsets[0];
491 if (receiveOffset <= remainingSize) {
496 std::memmove(&receiveBuffer[0], &receiveBuffer[remainingSize], availableSize - remainingSize);
497 receiveOffset = availableSize - remainingSize;
504 int fragsize = ntohs(header->fragmentSize);
505 int rawSegmentOffset = ntohl(header->segmentOffset);
507 splitRawOffset(rawSegmentOffset, block, offset);
514 if (offset != blockReceiveOffsets[block]) {
517 std::memcpy(&blockReceiveBuffers[block][blockReceiveOffsets[block]], &receiveBuffer[ofs+
sizeof(
SegmentHeaderTCP)], fragsize);
518 blockReceiveOffsets[block] += fragsize;
519 blockValidSize[block] = blockReceiveOffsets[block];
529 std::memmove(&receiveBuffer[0], &receiveBuffer[ofs], receiveOffset - ofs);
530 receiveOffset -= ofs;
535 bool complete =
true;
536 for (
int i=0; i<numReceptionBlocks; ++i) {
537 if (blockReceiveOffsets[i] < blockReceiveSize[i]) {
542 finishedReception = complete;
546 int DataBlockProtocol::parseReceivedHeader(
int length,
int offset) {
547 int headerExtraBytes = 6;
549 if(length < headerExtraBytes) {
553 unsigned short headerSize = ntohs(*reinterpret_cast<unsigned short*>(&receiveBuffer[offset]));
554 if (length < (headerExtraBytes + headerSize)) {
557 totalReceiveSize =
static_cast<int>(ntohl(*reinterpret_cast<unsigned int*>(&receiveBuffer[offset + 2])));
559 if (totalReceiveSize >= 0) {
560 legacyTransfer =
true;
561 headerExtraBytes = 6;
562 numReceptionBlocks = 1;
563 blockReceiveSize[0] = totalReceiveSize;
565 legacyTransfer =
false;
568 numReceptionBlocks = 0;
569 totalReceiveSize = 0;
570 for (
int i=0; i<MAX_DATA_BLOCKS; ++i) {
571 int s = ntohl(header->netTransferSizes[i]);
573 blockReceiveSize[i] = s;
574 numReceptionBlocks++;
575 totalReceiveSize += s;
583 if (numReceptionBlocks==0)
throw std::runtime_error(
"Received a transfer with zero blocks");
584 if (numReceptionBlocks > MAX_DATA_BLOCKS)
throw std::runtime_error(
"Received a transfer with too many blocks");
586 if(headerSize + headerExtraBytes > static_cast<int>(receiveBuffer.size())
587 || totalReceiveSize < 0 || headerSize + headerExtraBytes > length ) {
591 headerReceived =
true;
592 receivedHeader.assign(receiveBuffer.begin() + offset + headerExtraBytes,
593 receiveBuffer.begin() + offset + headerSize + headerExtraBytes);
594 resizeReceiveBuffer();
596 return headerSize + headerExtraBytes;
600 headerReceived =
false;
601 missingReceiveSegments.clear();
602 receivedHeader.clear();
603 waitingForMissingSegments =
false;
604 totalReceiveSize = 0;
605 finishedReception =
false;
606 lostSegmentBytes = 0;
607 for (
int i=0; i<MAX_DATA_BLOCKS; ++i) {
608 blockReceiveOffsets[i] = 0;
609 blockValidSize[i] = 0;
618 if(missingReceiveSegments.size() > 0) {
619 length = min(length, missingReceiveSegments[0].offset);
621 return &receiveBuffer[0];
625 if(receivedHeader.size() > 0) {
626 length =
static_cast<int>(receivedHeader.size());
627 return &receivedHeader[0];
633 bool DataBlockProtocol::processControlMessage(
int length) {
634 if(length < static_cast<int>(
sizeof(
int) + 1)) {
638 int payloadLength = length -
sizeof(int) - 1;
639 switch(receiveBuffer[0 + payloadLength]) {
640 case CONFIRM_MESSAGE:
642 connectionConfirmed =
true;
644 case CONNECTION_MESSAGE:
646 connectionConfirmed =
true;
647 confirmationMessagePending =
true;
648 clientConnectionPending =
true;
651 lastReceivedHeartbeat = std::chrono::steady_clock::now();
653 case HEADER_MESSAGE: {
654 if (anyPayloadReceived()) {
655 if (allBlocksDone()) {
656 LOG_ERROR(
"No EOF message received!");
658 LOG_ERROR(
"Received header too late/early!");
662 if(parseReceivedHeader(payloadLength, 0) == 0) {
669 if(anyPayloadReceived()) {
670 parseEofMessage(length);
673 case RESEND_MESSAGE: {
675 parseResendMessage(payloadLength);
678 case HEARTBEAT_MESSAGE:
680 lastReceivedHeartbeat = std::chrono::steady_clock::now();
691 if(protType == PROTOCOL_TCP) {
694 }
else if(connectionConfirmed) {
695 return !isServer || std::chrono::duration_cast<std::chrono::milliseconds>(
696 std::chrono::steady_clock::now() - lastReceivedHeartbeat).count()
697 < 2*HEARTBEAT_INTERVAL_MS;
704 if(protType == PROTOCOL_TCP) {
709 if(confirmationMessagePending) {
711 confirmationMessagePending =
false;
712 controlMessageBuffer[0] = CONFIRM_MESSAGE;
714 }
else if(!isServer && std::chrono::duration_cast<std::chrono::milliseconds>(
715 std::chrono::steady_clock::now() - lastRemoteHostActivity).count() > RECONNECT_TIMEOUT_MS) {
717 controlMessageBuffer[0] = CONNECTION_MESSAGE;
721 lastRemoteHostActivity = lastSentHeartbeat = std::chrono::steady_clock::now();
722 }
else if(transferHeaderData !=
nullptr &&
isConnected()) {
724 length = transferHeaderSize;
725 const unsigned char* ret = transferHeaderData;
726 transferHeaderData =
nullptr;
728 }
else if(eofMessagePending) {
730 eofMessagePending =
false;
731 unsigned int networkOffset = htonl(mergeRawOffset(lastTransmittedBlock, transferSize[lastTransmittedBlock]));
732 memcpy(&controlMessageBuffer[0], &networkOffset,
sizeof(
int));
733 controlMessageBuffer[
sizeof(int)] = EOF_MESSAGE;
735 }
else if(resendMessagePending) {
737 resendMessagePending =
false;
738 if(!generateResendRequest(length)) {
742 }
else if(!isServer && std::chrono::duration_cast<std::chrono::milliseconds>(
743 std::chrono::steady_clock::now() - lastSentHeartbeat).count() > HEARTBEAT_INTERVAL_MS) {
745 controlMessageBuffer[0] = HEARTBEAT_MESSAGE;
747 lastSentHeartbeat = std::chrono::steady_clock::now();
753 controlMessageBuffer[length++] = 0xff;
754 controlMessageBuffer[length++] = 0xff;
755 controlMessageBuffer[length++] = 0xff;
756 controlMessageBuffer[length++] = 0xff;
757 return controlMessageBuffer;
761 if(clientConnectionPending) {
762 clientConnectionPending =
false;
769 bool DataBlockProtocol::generateResendRequest(
int& length) {
770 length =
static_cast<int>(missingReceiveSegments.size() * (
sizeof(int) +
sizeof(
unsigned short)));
771 if(length +
sizeof(
int) + 1>
sizeof(controlMessageBuffer)) {
776 for(MissingReceiveSegment segment: missingReceiveSegments) {
777 unsigned int segOffset = htonl(static_cast<unsigned int>(segment.offset));
778 unsigned int segLen = htonl(static_cast<unsigned int>(segment.length));
780 memcpy(&controlMessageBuffer[length], &segOffset,
sizeof(segOffset));
781 length +=
sizeof(
unsigned int);
782 memcpy(&controlMessageBuffer[length], &segLen,
sizeof(segLen));
783 length +=
sizeof(
unsigned int);
786 controlMessageBuffer[length++] = RESEND_MESSAGE;
791 void DataBlockProtocol::parseResendMessage(
int length) {
792 missingTransferSegments.clear();
794 int num = length / (
sizeof(
unsigned int) +
sizeof(
unsigned short));
795 int bufferOffset = 0;
797 for(
int i=0; i<num; i++) {
798 unsigned int segOffsetNet = *
reinterpret_cast<unsigned int*
>(&receiveBuffer[bufferOffset]);
799 bufferOffset +=
sizeof(
unsigned int);
800 unsigned int segLenNet = *
reinterpret_cast<unsigned int*
>(&receiveBuffer[bufferOffset]);
801 bufferOffset +=
sizeof(
unsigned int);
803 int segmentOffsetRaw =
static_cast<int>(ntohl(segOffsetNet));
804 int segmentLength =
static_cast<int>(ntohl(segLenNet));
805 int dataBlockID, segmentOffset;
806 splitRawOffset(segmentOffsetRaw, dataBlockID, segmentOffset);
808 if(segmentOffset >= 0 && segmentLength > 0 && (segmentOffset + segmentLength) <= rawValidBytes[dataBlockID]) {
809 missingTransferSegments.push_back(std::pair<int, int>(
810 segmentOffsetRaw, segmentLength));
816 void DataBlockProtocol::parseEofMessage(
int length) {
818 completedReceptions++;
819 lostSegmentRate = (lostSegmentRate * (completedReceptions-1) + ((
double) lostSegmentBytes) / totalReceiveSize) / completedReceptions;
823 for (
int i=0; i<numReceptionBlocks; ++i) {
824 if (blockReceiveOffsets[i] < blockReceiveSize[i]) {
825 MissingReceiveSegment missingSeg;
826 missingSeg.offset = blockReceiveOffsets[i];
827 missingSeg.length = blockReceiveSize[i] - blockReceiveOffsets[i];
828 missingSeg.isEof =
true;
829 missingReceiveSegments.push_back(missingSeg);
830 lostSegmentBytes += missingSeg.length;
833 if(missingReceiveSegments.size() > 0) {
834 waitingForMissingSegments =
true;
835 resendMessagePending =
true;
838 for (
int i=0; i<static_cast<int>(missingReceiveSegments.size()); ++i) {
839 splitRawOffset(missingReceiveSegments[i].offset, mblock, moffset);
840 if (moffset < blockReceiveOffsets[mblock]) {
841 blockReceiveOffsets[mblock] = moffset;
845 finishedReception =
true;
848 LOG_ERROR(
"EOF message too short, length " << length);
852 void DataBlockProtocol::resizeReceiveBuffer() {
853 if(totalReceiveSize < 0) {
860 + MAX_OUTSTANDING_BYTES +
sizeof(int);
863 if(static_cast<int>(receiveBuffer.size()) < bufferSize) {
864 receiveBuffer.resize(bufferSize);
867 for (
int i=0; i<numReceptionBlocks; ++i) {
868 if (static_cast<int>(blockReceiveBuffers[i].size()) < blockReceiveSize[i]) {
869 blockReceiveBuffers[i].resize(blockReceiveSize[i]);
unsigned char * getNextReceiveBuffer(int maxLength)
Gets a buffer for receiving the next network message.
const unsigned char * getTransferMessage(int &length)
Gets the next network message for the current transfer.
const unsigned char * getNextControlMessage(int &length)
If a control message is pending to be transmitted, then the message data will be returned by this met...
void setTransferData(int block, unsigned char *data, int validBytes=0x7FFFFFFF)
Sets the payload data for the next transfer.
bool isConnected() const
Returns true if a remote connection is established.
void setTransferBytes(int block, long bytes)
Sets the per-block transfer size.
bool newClientConnected()
Returns true if the last network message has established a new connection from a client.
int getMaxReceptionSize() const
Returns the maximum payload size that can be received.
bool transferComplete()
Returns true if the current transfer has been completed.
void resetTransfer()
Resets all transfer related internal variables.
unsigned char * getReceivedData(int &length)
Returns the data that has been received for the current transfer.
void setTransferValidBytes(int block, int validBytes)
Updates the number of valid bytes in a partial transfer.
void setTransferHeader(unsigned char *data, int headerSize, int blocks)
Sets a user-defined header that shall be transmitted with the next transfer.
unsigned char * getReceivedHeader(int &length)
Returns the header data that has been received for the current transfer.
void processReceivedMessage(int length, bool &transferComplete)
Handles a received network message.
Exception class that is used for all protocol exceptions.
void resetReception(bool dropped)
Resets the message reception.