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;
98 numReceptionBlocks = 0;
103 overwrittenTransferIndex = -1;
104 overwrittenTransferBlock = -1;
105 totalBytesCompleted = 0;
106 totalTransferSize = 0;
107 numTransferBlocks = 0;
108 missingTransferSegments.clear();
112 if (transferHeaderData ==
nullptr) {
113 throw ProtocolException(
"Tried to set data block size before initializing header!");
114 }
else if (block >= numTransferBlocks) {
115 throw ProtocolException(
"Request to set data block size - block index too high!");
117 transferSize[block] = bytes;
119 hp->netTransferSizes[block] = htonl(bytes);
123 if(!transferDone && transferOffset > 0) {
125 }
else if(headerSize + 9 > static_cast<int>(
sizeof(controlMessageBuffer))) {
129 numTransferBlocks = blocks;
131 transferDone =
false;
132 for (
int i=0; i<MAX_DATA_BLOCKS; ++i) {
133 this->transferSize[i] = 0;
138 transferHeaderData = &data[-headerBaseOffset];
141 unsigned short netHeaderSize = htons(static_cast<unsigned short>(headerSize));
142 ourHeader->netHeaderSize = netHeaderSize;
143 ourHeader->netTransferSizeDummy = htonl(-1);
145 headerSize += headerBaseOffset;
147 if(protType == PROTOCOL_UDP) {
149 transferHeaderData[headerSize++] = HEADER_MESSAGE;
150 transferHeaderData[headerSize++] = 0xFF;
151 transferHeaderData[headerSize++] = 0xFF;
152 transferHeaderData[headerSize++] = 0xFF;
153 transferHeaderData[headerSize++] = 0xFF;
156 transferHeaderSize = headerSize;
160 if(transferHeaderSize == 0 || transferHeaderData ==
nullptr) {
164 transferDone =
false;
165 rawDataArr[block] = data;
166 transferOffset[block] = 0;
167 overwrittenTransferIndex = -1;
168 overwrittenTransferBlock = -1;
169 rawValidBytes[block] = min(transferSize[block], validBytes);
170 totalBytesCompleted = 0;
174 if(validBytes >= transferSize[block]) {
175 rawValidBytes[block] = transferSize[block];
176 }
else if(validBytes < static_cast<int>(
sizeof(
int))) {
177 rawValidBytes[block] = 0;
179 rawValidBytes[block] = validBytes;
183 std::string DataBlockProtocol::statusReport() {
184 std::stringstream ss;
185 ss <<
"DataBlockProtocol, blocks=" << numTransferBlocks <<
": ";
186 for (
int i=0; i<numTransferBlocks; ++i) {
187 ss << i <<
":(len " << transferSize[i] <<
" ofs " << transferOffset[i] <<
" rawvalid " << rawValidBytes[i] <<
") ";
189 ss <<
" total done: " << totalBytesCompleted <<
"/" << totalTransferSize;
194 if(transferDone || rawValidBytes == 0) {
201 if(protType == PROTOCOL_TCP && !anyPayloadReceived() && transferHeaderData !=
nullptr) {
202 length = transferHeaderSize;
203 const unsigned char* ret = transferHeaderData;
204 transferHeaderData =
nullptr;
210 restoreTransferBuffer();
213 int block = -1, offset = -1;
214 getNextTransferSegment(block, offset, length);
219 if(protType == PROTOCOL_UDP) {
221 overwrittenTransferBlock = block;
222 overwrittenTransferIndex = offset + length;
224 std::memcpy(overwrittenTransferData, segmentHeader,
sizeof(
SegmentHeaderUDP));
225 segmentHeader->segmentOffset =
static_cast<int>(htonl(mergeRawOffset(block, offset)));
227 lastTransmittedBlock = block;
228 return &rawDataArr[block][offset];
232 overwrittenTransferBlock = block;
233 overwrittenTransferIndex = headerOffset;
235 std::memcpy(overwrittenTransferData, segmentHeader,
sizeof(
SegmentHeaderTCP));
236 segmentHeader->fragmentSize = htons(length);
237 segmentHeader->segmentOffset =
static_cast<int>(htonl(mergeRawOffset(block, offset)));
239 lastTransmittedBlock = block;
240 return &rawDataArr[block][headerOffset];
245 void DataBlockProtocol::getNextTransferSegment(
int& block,
int& offset,
int& length) {
246 if(missingTransferSegments.size() == 0) {
248 int sendBlock = 0, amount = 0;
249 for (
int i=0; i<numTransferBlocks; ++i) {
250 int avail = std::min(transferSize[i], rawValidBytes[i]);
251 avail -= transferOffset[i];
252 if (avail > amount) {
257 length = std::min(maxPayloadSize, amount);
258 if(length == 0 || (length < minPayloadSize && rawValidBytes[sendBlock] != transferSize[sendBlock])) {
264 offset = transferOffset[sendBlock];
265 transferOffset[sendBlock] += length;
266 if (protType == PROTOCOL_UDP) {
267 bool complete =
true;
268 for (
int i=0; i<numTransferBlocks; ++i) {
269 if (transferOffset[i] < transferSize[i]) {
275 eofMessagePending =
true;
280 splitRawOffset(missingTransferSegments.front().first, block, offset);
281 length = std::min(maxPayloadSize, missingTransferSegments.front().second);
282 LOG_ERROR(
"Re-transmitting: " << offset <<
" - " << (offset + length));
284 int remaining = missingTransferSegments[0].second - length;
287 missingTransferSegments.pop_front();
290 missingTransferSegments.front().first += length;
291 missingTransferSegments.front().second = remaining;
296 void DataBlockProtocol::restoreTransferBuffer() {
297 if(overwrittenTransferBlock >= 0) {
298 if(protType == PROTOCOL_UDP) {
299 std::memcpy(&rawDataArr[overwrittenTransferBlock][overwrittenTransferIndex], overwrittenTransferData,
sizeof(
SegmentHeaderUDP));
301 std::memcpy(&rawDataArr[overwrittenTransferBlock][overwrittenTransferIndex], overwrittenTransferData,
sizeof(
SegmentHeaderTCP));
304 overwrittenTransferIndex = -1;
305 overwrittenTransferBlock = -1;
309 for (
int i=0; i<numTransferBlocks; ++i) {
310 if (transferOffset[i] < transferSize[i])
return false;
312 return !eofMessagePending;
316 if(protType == PROTOCOL_TCP) {
317 return MAX_TCP_BYTES_TRANSFER;
319 return MAX_UDP_RECEPTION;
324 return &receiveBuffer[receiveOffset];
328 transferComplete =
false;
333 if(finishedReception) {
338 if(protType == PROTOCOL_UDP) {
339 processReceivedUdpMessage(length, transferComplete);
341 processReceivedTcpMessage(length, transferComplete);
344 transferComplete = finishedReception;
347 void DataBlockProtocol::processReceivedUdpMessage(
int length,
bool&
transferComplete) {
348 if(length < static_cast<int>(
sizeof(
int)) ||
349 0 + length > static_cast<int>(receiveBuffer.size())) {
354 int rawSegmentOffset = ntohl(*reinterpret_cast<int*>(
355 &receiveBuffer[0 + length -
sizeof(
int)]));
357 int dataBlockID, segmentOffset;
358 splitRawOffset(rawSegmentOffset, dataBlockID, segmentOffset);
360 if(rawSegmentOffset == static_cast<int>(0xFFFFFFFF)) {
362 processControlMessage(length);
363 }
else if(headerReceived) {
365 int realPayloadOffset = 0;
366 int payloadLength = length -
sizeof(int);
368 if(segmentOffset != blockReceiveOffsets[dataBlockID]) {
371 if(!waitingForMissingSegments &&
372 segmentOffset > blockReceiveOffsets[dataBlockID]
373 && segmentOffset + payloadLength < (
int)blockReceiveBuffers[dataBlockID].size()) {
375 LOG_ERROR(
"Missing segment: " << blockReceiveOffsets[dataBlockID] <<
" - " << segmentOffset
376 <<
" (" << missingReceiveSegments.size() <<
")");
378 MissingReceiveSegment missingSeg;
379 missingSeg.offset = mergeRawOffset(dataBlockID, blockReceiveOffsets[dataBlockID]);
380 missingSeg.length = segmentOffset - blockReceiveOffsets[dataBlockID];
381 missingSeg.isEof =
false;
382 lostSegmentBytes += missingSeg.length;
383 missingReceiveSegments.push_back(missingSeg);
386 memcpy(&blockReceiveBuffers[dataBlockID][segmentOffset], &receiveBuffer[0 + realPayloadOffset], payloadLength);
388 blockReceiveOffsets[dataBlockID] = segmentOffset + payloadLength;
394 if(segmentOffset > 0 ) {
395 if(blockReceiveOffsets[dataBlockID] > 0) {
396 LOG_ERROR(
"Resend failed!");
400 LOG_ERROR(
"Missed EOF message!");
404 if ((realPayloadOffset+payloadLength) > (
int)receiveBuffer.size()) {
409 memcpy(&blockReceiveBuffers[dataBlockID][segmentOffset], &receiveBuffer[0 + realPayloadOffset], payloadLength);
411 blockReceiveOffsets[dataBlockID] = segmentOffset + payloadLength;
412 if (waitingForMissingSegments) {
414 if ((missingReceiveSegments.size() == 1) && (missingReceiveSegments.front().length <= payloadLength)) {
416 blockValidSize[dataBlockID] = blockReceiveSize[dataBlockID];
418 blockValidSize[dataBlockID] = segmentOffset + payloadLength;
420 }
else if (missingReceiveSegments.size() == 0) {
421 blockValidSize[dataBlockID] = segmentOffset + payloadLength;
425 if(segmentOffset == 0 && dataBlockID == 0) {
427 lastRemoteHostActivity = std::chrono::steady_clock::now();
431 integrateMissingUdpSegments(dataBlockID, segmentOffset, payloadLength);
435 void DataBlockProtocol::integrateMissingUdpSegments(
int block,
int lastSegmentOffset,
int lastSegmentSize) {
436 if(waitingForMissingSegments) {
438 int checkBlock, checkOffset;
439 MissingReceiveSegment& firstSeg = missingReceiveSegments.front();
440 splitRawOffset(firstSeg.offset, checkBlock, checkOffset);
441 if(lastSegmentOffset != checkOffset) {
442 LOG_ERROR(
"Received invalid resend: " << lastSegmentOffset);
445 firstSeg.offset += lastSegmentSize;
446 firstSeg.length -= lastSegmentSize;
447 if(firstSeg.length == 0) {
448 missingReceiveSegments.pop_front();
451 if(missingReceiveSegments.size() == 0) {
452 waitingForMissingSegments =
false;
453 finishedReception =
true;
455 blockReceiveOffsets[block] = missingReceiveSegments.front().offset;
461 void DataBlockProtocol::processReceivedTcpMessage(
int length,
bool& transferComplete) {
463 if(!headerReceived) {
464 int totalHeaderSize = parseReceivedHeader(length, 0);
465 if(totalHeaderSize == 0) {
467 receiveOffset += length;
472 length -= totalHeaderSize;
479 int movelength = receiveOffset + length;
480 ::memmove(&receiveBuffer[0], &receiveBuffer[totalHeaderSize], movelength);
481 receiveOffset = movelength;
484 receiveOffset += length;
487 if (legacyTransfer) {
489 int remainingSize = blockReceiveSize[0] - blockValidSize[0];
490 int availableSize = std::min(receiveOffset, remainingSize);
492 std::memcpy(&blockReceiveBuffers[0][blockReceiveOffsets[0]], &receiveBuffer[0], availableSize);
493 blockReceiveOffsets[0] += availableSize;
494 blockValidSize[0] = blockReceiveOffsets[0];
496 if (receiveOffset <= remainingSize) {
501 std::memmove(&receiveBuffer[0], &receiveBuffer[remainingSize], availableSize - remainingSize);
502 receiveOffset = availableSize - remainingSize;
509 int fragsize = ntohs(header->fragmentSize);
510 int rawSegmentOffset = ntohl(header->segmentOffset);
512 splitRawOffset(rawSegmentOffset, block, offset);
519 if (offset != blockReceiveOffsets[block]) {
522 std::memcpy(&blockReceiveBuffers[block][blockReceiveOffsets[block]], &receiveBuffer[ofs+
sizeof(
SegmentHeaderTCP)], fragsize);
523 blockReceiveOffsets[block] += fragsize;
524 blockValidSize[block] = blockReceiveOffsets[block];
534 std::memmove(&receiveBuffer[0], &receiveBuffer[ofs], receiveOffset - ofs);
535 receiveOffset -= ofs;
540 bool complete =
true;
541 for (
int i=0; i<numReceptionBlocks; ++i) {
542 if (blockReceiveOffsets[i] < blockReceiveSize[i]) {
547 finishedReception = complete;
551 int DataBlockProtocol::parseReceivedHeader(
int length,
int offset) {
552 int headerExtraBytes = 6;
554 if(length < headerExtraBytes) {
558 unsigned short headerSize = ntohs(*reinterpret_cast<unsigned short*>(&receiveBuffer[offset]));
559 if (length < (headerExtraBytes + headerSize)) {
562 totalReceiveSize =
static_cast<int>(ntohl(*reinterpret_cast<unsigned int*>(&receiveBuffer[offset + 2])));
564 if (totalReceiveSize >= 0) {
565 legacyTransfer =
true;
566 headerExtraBytes = 6;
567 numReceptionBlocks = 1;
568 blockReceiveSize[0] = totalReceiveSize;
570 legacyTransfer =
false;
573 numReceptionBlocks = 0;
574 totalReceiveSize = 0;
575 for (
int i=0; i<MAX_DATA_BLOCKS; ++i) {
576 int s = ntohl(header->netTransferSizes[i]);
578 blockReceiveSize[i] = s;
579 numReceptionBlocks++;
580 totalReceiveSize += s;
588 if (numReceptionBlocks==0)
throw std::runtime_error(
"Received a transfer with zero blocks");
589 if (numReceptionBlocks > MAX_DATA_BLOCKS)
throw std::runtime_error(
"Received a transfer with too many blocks");
591 if(headerSize + headerExtraBytes > static_cast<int>(receiveBuffer.size())
592 || totalReceiveSize < 0 || headerSize + headerExtraBytes > length ) {
596 headerReceived =
true;
597 receivedHeader.assign(receiveBuffer.begin() + offset + headerExtraBytes,
598 receiveBuffer.begin() + offset + headerSize + headerExtraBytes);
599 resizeReceiveBuffer();
601 return headerSize + headerExtraBytes;
605 numReceptionBlocks = 0;
606 headerReceived =
false;
607 missingReceiveSegments.clear();
608 receivedHeader.clear();
609 waitingForMissingSegments =
false;
610 totalReceiveSize = 0;
611 finishedReception =
false;
612 lostSegmentBytes = 0;
613 for (
int i=0; i<MAX_DATA_BLOCKS; ++i) {
614 blockReceiveOffsets[i] = 0;
615 blockValidSize[i] = 0;
624 if(missingReceiveSegments.size() > 0) {
625 length = min(length, missingReceiveSegments[0].offset);
627 return &receiveBuffer[0];
631 if(receivedHeader.size() > 0) {
632 length =
static_cast<int>(receivedHeader.size());
633 return &receivedHeader[0];
639 bool DataBlockProtocol::processControlMessage(
int length) {
640 if(length < static_cast<int>(
sizeof(
int) + 1)) {
644 int payloadLength = length -
sizeof(int) - 1;
645 switch(receiveBuffer[0 + payloadLength]) {
646 case CONFIRM_MESSAGE:
648 connectionConfirmed =
true;
650 case CONNECTION_MESSAGE:
652 connectionConfirmed =
true;
653 confirmationMessagePending =
true;
654 clientConnectionPending =
true;
657 lastReceivedHeartbeat = std::chrono::steady_clock::now();
659 case HEADER_MESSAGE: {
660 if (anyPayloadReceived()) {
661 if (allBlocksDone()) {
662 LOG_ERROR(
"No EOF message received!");
664 LOG_ERROR(
"Received header too late/early!");
668 if(parseReceivedHeader(payloadLength, 0) == 0) {
675 if(anyPayloadReceived()) {
676 parseEofMessage(length);
679 case RESEND_MESSAGE: {
681 parseResendMessage(payloadLength);
684 case HEARTBEAT_MESSAGE:
686 lastReceivedHeartbeat = std::chrono::steady_clock::now();
697 if(protType == PROTOCOL_TCP) {
700 }
else if(connectionConfirmed) {
701 return !isServer || std::chrono::duration_cast<std::chrono::milliseconds>(
702 std::chrono::steady_clock::now() - lastReceivedHeartbeat).count()
703 < 2*HEARTBEAT_INTERVAL_MS;
710 if(protType == PROTOCOL_TCP) {
715 if(confirmationMessagePending) {
717 confirmationMessagePending =
false;
718 controlMessageBuffer[0] = CONFIRM_MESSAGE;
720 }
else if(!isServer && std::chrono::duration_cast<std::chrono::milliseconds>(
721 std::chrono::steady_clock::now() - lastRemoteHostActivity).count() > RECONNECT_TIMEOUT_MS) {
723 controlMessageBuffer[0] = CONNECTION_MESSAGE;
727 lastRemoteHostActivity = lastSentHeartbeat = std::chrono::steady_clock::now();
728 }
else if(transferHeaderData !=
nullptr &&
isConnected()) {
730 length = transferHeaderSize;
731 const unsigned char* ret = transferHeaderData;
732 transferHeaderData =
nullptr;
734 }
else if(eofMessagePending) {
736 eofMessagePending =
false;
737 unsigned int networkOffset = htonl(mergeRawOffset(lastTransmittedBlock, transferSize[lastTransmittedBlock]));
738 memcpy(&controlMessageBuffer[0], &networkOffset,
sizeof(
int));
739 controlMessageBuffer[
sizeof(int)] = EOF_MESSAGE;
741 }
else if(resendMessagePending) {
743 resendMessagePending =
false;
744 if(!generateResendRequest(length)) {
748 }
else if(!isServer && std::chrono::duration_cast<std::chrono::milliseconds>(
749 std::chrono::steady_clock::now() - lastSentHeartbeat).count() > HEARTBEAT_INTERVAL_MS) {
751 controlMessageBuffer[0] = HEARTBEAT_MESSAGE;
753 lastSentHeartbeat = std::chrono::steady_clock::now();
759 controlMessageBuffer[length++] = 0xff;
760 controlMessageBuffer[length++] = 0xff;
761 controlMessageBuffer[length++] = 0xff;
762 controlMessageBuffer[length++] = 0xff;
763 return controlMessageBuffer;
767 if(clientConnectionPending) {
768 clientConnectionPending =
false;
775 bool DataBlockProtocol::generateResendRequest(
int& length) {
776 length =
static_cast<int>(missingReceiveSegments.size() * (
sizeof(int) +
sizeof(
unsigned short)));
777 if(length +
sizeof(
int) + 1>
sizeof(controlMessageBuffer)) {
782 for(MissingReceiveSegment segment: missingReceiveSegments) {
783 unsigned int segOffset = htonl(static_cast<unsigned int>(segment.offset));
784 unsigned int segLen = htonl(static_cast<unsigned int>(segment.length));
786 memcpy(&controlMessageBuffer[length], &segOffset,
sizeof(segOffset));
787 length +=
sizeof(
unsigned int);
788 memcpy(&controlMessageBuffer[length], &segLen,
sizeof(segLen));
789 length +=
sizeof(
unsigned int);
792 controlMessageBuffer[length++] = RESEND_MESSAGE;
797 void DataBlockProtocol::parseResendMessage(
int length) {
798 missingTransferSegments.clear();
800 int num = length / (
sizeof(
unsigned int) +
sizeof(
unsigned short));
801 int bufferOffset = 0;
803 for(
int i=0; i<num; i++) {
804 unsigned int segOffsetNet = *
reinterpret_cast<unsigned int*
>(&receiveBuffer[bufferOffset]);
805 bufferOffset +=
sizeof(
unsigned int);
806 unsigned int segLenNet = *
reinterpret_cast<unsigned int*
>(&receiveBuffer[bufferOffset]);
807 bufferOffset +=
sizeof(
unsigned int);
809 int segmentOffsetRaw =
static_cast<int>(ntohl(segOffsetNet));
810 int segmentLength =
static_cast<int>(ntohl(segLenNet));
811 int dataBlockID, segmentOffset;
812 splitRawOffset(segmentOffsetRaw, dataBlockID, segmentOffset);
814 if(segmentOffset >= 0 && segmentLength > 0 && (segmentOffset + segmentLength) <= rawValidBytes[dataBlockID]) {
815 missingTransferSegments.push_back(std::pair<int, int>(
816 segmentOffsetRaw, segmentLength));
822 void DataBlockProtocol::parseEofMessage(
int length) {
824 completedReceptions++;
825 lostSegmentRate = (lostSegmentRate * (completedReceptions-1) + ((
double) lostSegmentBytes) / totalReceiveSize) / completedReceptions;
829 for (
int i=0; i<numReceptionBlocks; ++i) {
830 if (blockReceiveOffsets[i] < blockReceiveSize[i]) {
831 MissingReceiveSegment missingSeg;
832 missingSeg.offset = blockReceiveOffsets[i];
833 missingSeg.length = blockReceiveSize[i] - blockReceiveOffsets[i];
834 missingSeg.isEof =
true;
835 missingReceiveSegments.push_back(missingSeg);
836 lostSegmentBytes += missingSeg.length;
839 if(missingReceiveSegments.size() > 0) {
840 waitingForMissingSegments =
true;
841 resendMessagePending =
true;
844 for (
int i=0; i<static_cast<int>(missingReceiveSegments.size()); ++i) {
845 splitRawOffset(missingReceiveSegments[i].offset, mblock, moffset);
846 if (moffset < blockReceiveOffsets[mblock]) {
847 blockReceiveOffsets[mblock] = moffset;
851 finishedReception =
true;
854 LOG_ERROR(
"EOF message too short, length " << length);
858 void DataBlockProtocol::resizeReceiveBuffer() {
859 if(totalReceiveSize < 0) {
866 + MAX_OUTSTANDING_BYTES +
sizeof(int);
869 if(static_cast<int>(receiveBuffer.size()) < bufferSize) {
870 receiveBuffer.resize(bufferSize);
873 for (
int i=0; i<numReceptionBlocks; ++i) {
874 if (static_cast<int>(blockReceiveBuffers[i].size()) < blockReceiveSize[i]) {
875 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.