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 && numTransferBlocks > 0) {
125 }
else if(headerSize + 9 > static_cast<int>(
sizeof(controlMessageBuffer))) {
127 }
else if(blocks == 0) {
131 numTransferBlocks = blocks;
133 transferDone =
false;
134 for (
int i=0; i<MAX_DATA_BLOCKS; ++i) {
135 this->transferSize[i] = 0;
140 transferHeaderData = &data[-headerBaseOffset];
143 unsigned short netHeaderSize = htons(static_cast<unsigned short>(headerSize));
144 ourHeader->netHeaderSize = netHeaderSize;
145 ourHeader->netTransferSizeDummy = htonl(-1);
147 headerSize += headerBaseOffset;
149 if(protType == PROTOCOL_UDP) {
151 transferHeaderData[headerSize++] = HEADER_MESSAGE;
152 transferHeaderData[headerSize++] = 0xFF;
153 transferHeaderData[headerSize++] = 0xFF;
154 transferHeaderData[headerSize++] = 0xFF;
155 transferHeaderData[headerSize++] = 0xFF;
158 transferHeaderSize = headerSize;
162 if(transferHeaderSize == 0 || transferHeaderData ==
nullptr) {
166 transferDone =
false;
167 rawDataArr[block] = data;
168 transferOffset[block] = 0;
169 overwrittenTransferIndex = -1;
170 overwrittenTransferBlock = -1;
171 rawValidBytes[block] = min(transferSize[block], validBytes);
172 totalBytesCompleted = 0;
176 if(validBytes >= transferSize[block]) {
177 rawValidBytes[block] = transferSize[block];
178 }
else if(validBytes < static_cast<int>(
sizeof(
int))) {
179 rawValidBytes[block] = 0;
181 rawValidBytes[block] = validBytes;
185 std::string DataBlockProtocol::statusReport() {
186 std::stringstream ss;
187 ss <<
"DataBlockProtocol, blocks=" << numTransferBlocks <<
": ";
188 for (
int i=0; i<numTransferBlocks; ++i) {
189 ss << i <<
":(len " << transferSize[i] <<
" ofs " << transferOffset[i] <<
" rawvalid " << rawValidBytes[i] <<
") ";
191 ss <<
" total done: " << totalBytesCompleted <<
"/" << totalTransferSize;
196 if(transferDone || rawValidBytes == 0) {
203 if(protType == PROTOCOL_TCP && transferHeaderData !=
nullptr) {
204 length = transferHeaderSize;
205 const unsigned char* ret = transferHeaderData;
206 transferHeaderData =
nullptr;
212 restoreTransferBuffer();
215 int block = -1, offset = -1;
216 getNextTransferSegment(block, offset, length);
221 if(protType == PROTOCOL_UDP) {
223 overwrittenTransferBlock = block;
224 overwrittenTransferIndex = offset + length;
226 std::memcpy(overwrittenTransferData, segmentHeader,
sizeof(
SegmentHeaderUDP));
227 segmentHeader->segmentOffset =
static_cast<int>(htonl(mergeRawOffset(block, offset)));
229 lastTransmittedBlock = block;
230 return &rawDataArr[block][offset];
236 unsigned char* dataPointer =
nullptr;
238 if(headerOffset < 0) {
241 static unsigned char tcpBuffer[MAX_TCP_BYTES_TRANSFER];
242 dataPointer = tcpBuffer;
244 std::memcpy(&tcpBuffer[
sizeof(segmentHeader)], &rawDataArr[block][offset], length);
248 dataPointer = &rawDataArr[block][headerOffset];
249 segmentHeader =
reinterpret_cast<SegmentHeaderTCP*
>(&rawDataArr[block][headerOffset]);
250 overwrittenTransferBlock = block;
251 overwrittenTransferIndex = headerOffset;
252 std::memcpy(overwrittenTransferData, segmentHeader,
sizeof(
SegmentHeaderTCP));
255 segmentHeader->fragmentSize = htonl(length);
256 segmentHeader->segmentOffset =
static_cast<int>(htonl(mergeRawOffset(block, offset)));
258 lastTransmittedBlock = block;
263 void DataBlockProtocol::getNextTransferSegment(
int& block,
int& offset,
int& length) {
264 if(missingTransferSegments.size() == 0) {
266 int sendBlock = 0, amount = 0;
267 for (
int i=0; i<numTransferBlocks; ++i) {
268 int avail = std::min(transferSize[i], rawValidBytes[i]);
269 avail -= transferOffset[i];
270 if (avail > amount) {
275 length = std::min(maxPayloadSize, amount);
276 if(length == 0 || (length < minPayloadSize && rawValidBytes[sendBlock] != transferSize[sendBlock])) {
282 offset = transferOffset[sendBlock];
283 transferOffset[sendBlock] += length;
284 if (protType == PROTOCOL_UDP) {
285 bool complete =
true;
286 for (
int i=0; i<numTransferBlocks; ++i) {
287 if (transferOffset[i] < transferSize[i]) {
293 eofMessagePending =
true;
298 splitRawOffset(missingTransferSegments.front().first, block, offset);
299 length = std::min(maxPayloadSize, missingTransferSegments.front().second);
300 LOG_ERROR(
"Re-transmitting: " << offset <<
" - " << (offset + length));
302 int remaining = missingTransferSegments[0].second - length;
305 missingTransferSegments.pop_front();
308 missingTransferSegments.front().first += length;
309 missingTransferSegments.front().second = remaining;
314 void DataBlockProtocol::restoreTransferBuffer() {
315 if(overwrittenTransferBlock >= 0) {
316 if(protType == PROTOCOL_UDP) {
317 std::memcpy(&rawDataArr[overwrittenTransferBlock][overwrittenTransferIndex], overwrittenTransferData,
sizeof(
SegmentHeaderUDP));
319 std::memcpy(&rawDataArr[overwrittenTransferBlock][overwrittenTransferIndex], overwrittenTransferData,
sizeof(
SegmentHeaderTCP));
322 overwrittenTransferIndex = -1;
323 overwrittenTransferBlock = -1;
327 for (
int i=0; i<numTransferBlocks; ++i) {
328 if (transferOffset[i] < transferSize[i])
return false;
330 return !eofMessagePending;
334 if(protType == PROTOCOL_TCP) {
335 return MAX_TCP_BYTES_TRANSFER;
337 return MAX_UDP_RECEPTION;
342 if(receiveOffset + maxLength > (
int)receiveBuffer.size()) {
343 receiveBuffer.resize(receiveOffset + maxLength);
345 return &receiveBuffer[receiveOffset];
349 transferComplete =
false;
354 if(finishedReception) {
359 if(protType == PROTOCOL_UDP) {
360 processReceivedUdpMessage(length, transferComplete);
362 processReceivedTcpMessage(length, transferComplete);
365 transferComplete = finishedReception;
368 void DataBlockProtocol::processReceivedUdpMessage(
int length,
bool&
transferComplete) {
369 if(length < static_cast<int>(
sizeof(
int)) ||
370 0 + length > static_cast<int>(receiveBuffer.size())) {
375 int rawSegmentOffset = ntohl(*reinterpret_cast<int*>(
376 &receiveBuffer[0 + length -
sizeof(
int)]));
378 int dataBlockID, segmentOffset;
379 splitRawOffset(rawSegmentOffset, dataBlockID, segmentOffset);
381 if(rawSegmentOffset == static_cast<int>(0xFFFFFFFF)) {
383 processControlMessage(length);
384 }
else if(headerReceived) {
386 int realPayloadOffset = 0;
387 int payloadLength = length -
sizeof(int);
389 if(segmentOffset != blockReceiveOffsets[dataBlockID]) {
392 if(!waitingForMissingSegments &&
393 segmentOffset > blockReceiveOffsets[dataBlockID]
394 && segmentOffset + payloadLength < (
int)blockReceiveBuffers[dataBlockID].size()) {
396 LOG_ERROR(
"Missing segment: " << blockReceiveOffsets[dataBlockID] <<
" - " << segmentOffset
397 <<
" (" << missingReceiveSegments.size() <<
")");
399 MissingReceiveSegment missingSeg;
400 missingSeg.offset = mergeRawOffset(dataBlockID, blockReceiveOffsets[dataBlockID]);
401 missingSeg.length = segmentOffset - blockReceiveOffsets[dataBlockID];
402 missingSeg.isEof =
false;
403 lostSegmentBytes += missingSeg.length;
404 missingReceiveSegments.push_back(missingSeg);
407 memcpy(&blockReceiveBuffers[dataBlockID][segmentOffset], &receiveBuffer[0 + realPayloadOffset], payloadLength);
409 blockReceiveOffsets[dataBlockID] = segmentOffset + payloadLength;
415 if(segmentOffset > 0 ) {
416 if(blockReceiveOffsets[dataBlockID] > 0) {
417 LOG_ERROR(
"Resend failed!");
421 LOG_ERROR(
"Missed EOF message!");
425 if ((realPayloadOffset+payloadLength) > (
int)receiveBuffer.size()) {
430 memcpy(&blockReceiveBuffers[dataBlockID][segmentOffset], &receiveBuffer[0 + realPayloadOffset], payloadLength);
432 blockReceiveOffsets[dataBlockID] = segmentOffset + payloadLength;
433 if (waitingForMissingSegments) {
435 if ((missingReceiveSegments.size() == 1) && (missingReceiveSegments.front().length <= payloadLength)) {
437 blockValidSize[dataBlockID] = blockReceiveSize[dataBlockID];
439 blockValidSize[dataBlockID] = segmentOffset + payloadLength;
441 }
else if (missingReceiveSegments.size() == 0) {
442 blockValidSize[dataBlockID] = segmentOffset + payloadLength;
446 if(segmentOffset == 0 && dataBlockID == 0) {
448 lastRemoteHostActivity = std::chrono::steady_clock::now();
452 integrateMissingUdpSegments(dataBlockID, segmentOffset, payloadLength);
456 void DataBlockProtocol::integrateMissingUdpSegments(
int block,
int lastSegmentOffset,
int lastSegmentSize) {
457 if(waitingForMissingSegments) {
459 int checkBlock, checkOffset;
460 MissingReceiveSegment& firstSeg = missingReceiveSegments.front();
461 splitRawOffset(firstSeg.offset, checkBlock, checkOffset);
462 if(lastSegmentOffset != checkOffset) {
463 LOG_ERROR(
"Received invalid resend: " << lastSegmentOffset);
466 firstSeg.offset += lastSegmentSize;
467 firstSeg.length -= lastSegmentSize;
468 if(firstSeg.length == 0) {
469 missingReceiveSegments.pop_front();
472 if(missingReceiveSegments.size() == 0) {
473 waitingForMissingSegments =
false;
474 finishedReception =
true;
476 blockReceiveOffsets[block] = missingReceiveSegments.front().offset;
482 void DataBlockProtocol::processReceivedTcpMessage(
int length,
bool& transferComplete) {
484 if(!headerReceived) {
485 int totalHeaderSize = parseReceivedHeader(length, 0);
486 if(totalHeaderSize == 0) {
488 receiveOffset += length;
493 length -= totalHeaderSize;
500 int movelength = receiveOffset + length;
501 ::memmove(&receiveBuffer[0], &receiveBuffer[totalHeaderSize], movelength);
502 receiveOffset = movelength;
505 receiveOffset += length;
508 if (legacyTransfer) {
510 int remainingSize = blockReceiveSize[0] - blockValidSize[0];
511 int availableSize = std::min(receiveOffset, remainingSize);
513 std::memcpy(&blockReceiveBuffers[0][blockReceiveOffsets[0]], &receiveBuffer[0], availableSize);
514 blockReceiveOffsets[0] += availableSize;
515 blockValidSize[0] = blockReceiveOffsets[0];
517 if (receiveOffset <= remainingSize) {
522 std::memmove(&receiveBuffer[0], &receiveBuffer[remainingSize], availableSize - remainingSize);
523 receiveOffset = availableSize - remainingSize;
530 int fragsize = ntohl(header->fragmentSize);
531 int rawSegmentOffset = ntohl(header->segmentOffset);
533 splitRawOffset(rawSegmentOffset, block, offset);
540 if (offset != blockReceiveOffsets[block]) {
543 std::memcpy(&blockReceiveBuffers[block][blockReceiveOffsets[block]], &receiveBuffer[ofs+
sizeof(
SegmentHeaderTCP)], fragsize);
544 blockReceiveOffsets[block] += fragsize;
545 blockValidSize[block] = blockReceiveOffsets[block];
555 std::memmove(&receiveBuffer[0], &receiveBuffer[ofs], receiveOffset - ofs);
556 receiveOffset -= ofs;
561 bool complete =
true;
562 for (
int i=0; i<numReceptionBlocks; ++i) {
563 if (blockReceiveOffsets[i] < blockReceiveSize[i]) {
568 finishedReception = complete;
572 int DataBlockProtocol::parseReceivedHeader(
int length,
int offset) {
573 int headerExtraBytes = 6;
575 if(length < headerExtraBytes) {
579 unsigned short headerSize = ntohs(*reinterpret_cast<unsigned short*>(&receiveBuffer[offset]));
580 if (length < (headerExtraBytes + headerSize)) {
583 totalReceiveSize =
static_cast<int>(ntohl(*reinterpret_cast<unsigned int*>(&receiveBuffer[offset + 2])));
585 if (totalReceiveSize >= 0) {
586 legacyTransfer =
true;
587 headerExtraBytes = 6;
588 numReceptionBlocks = 1;
589 blockReceiveSize[0] = totalReceiveSize;
591 legacyTransfer =
false;
594 numReceptionBlocks = 0;
595 totalReceiveSize = 0;
596 for (
int i=0; i<MAX_DATA_BLOCKS; ++i) {
597 int s = ntohl(header->netTransferSizes[i]);
599 blockReceiveSize[i] = s;
600 numReceptionBlocks++;
601 totalReceiveSize += s;
609 if (numReceptionBlocks==0)
throw std::runtime_error(
"Received a transfer with zero blocks");
610 if (numReceptionBlocks > MAX_DATA_BLOCKS)
throw std::runtime_error(
"Received a transfer with too many blocks");
612 if(headerSize + headerExtraBytes > static_cast<int>(receiveBuffer.size())
613 || totalReceiveSize < 0 || headerSize + headerExtraBytes > length ) {
617 headerReceived =
true;
618 receivedHeader.assign(receiveBuffer.begin() + offset + headerExtraBytes,
619 receiveBuffer.begin() + offset + headerSize + headerExtraBytes);
620 resizeReceiveBuffer();
622 return headerSize + headerExtraBytes;
626 numReceptionBlocks = 0;
627 headerReceived =
false;
628 missingReceiveSegments.clear();
629 receivedHeader.clear();
630 waitingForMissingSegments =
false;
631 totalReceiveSize = 0;
632 finishedReception =
false;
633 lostSegmentBytes = 0;
634 for (
int i=0; i<MAX_DATA_BLOCKS; ++i) {
635 blockReceiveOffsets[i] = 0;
636 blockValidSize[i] = 0;
645 if(missingReceiveSegments.size() > 0) {
646 length = min(length, missingReceiveSegments[0].offset);
648 return &receiveBuffer[0];
652 if(receivedHeader.size() > 0) {
653 length =
static_cast<int>(receivedHeader.size());
654 return &receivedHeader[0];
660 bool DataBlockProtocol::processControlMessage(
int length) {
661 if(length < static_cast<int>(
sizeof(
int) + 1)) {
665 int payloadLength = length -
sizeof(int) - 1;
666 switch(receiveBuffer[0 + payloadLength]) {
667 case CONFIRM_MESSAGE:
669 connectionConfirmed =
true;
671 case CONNECTION_MESSAGE:
673 connectionConfirmed =
true;
674 confirmationMessagePending =
true;
675 clientConnectionPending =
true;
678 lastReceivedHeartbeat = std::chrono::steady_clock::now();
680 case HEADER_MESSAGE: {
681 if (anyPayloadReceived()) {
682 if (allBlocksDone()) {
683 LOG_ERROR(
"No EOF message received!");
685 LOG_ERROR(
"Received header too late/early!");
689 if(parseReceivedHeader(payloadLength, 0) == 0) {
696 if(anyPayloadReceived()) {
697 parseEofMessage(length);
700 case RESEND_MESSAGE: {
702 parseResendMessage(payloadLength);
705 case HEARTBEAT_MESSAGE:
707 lastReceivedHeartbeat = std::chrono::steady_clock::now();
718 if(protType == PROTOCOL_TCP) {
721 }
else if(connectionConfirmed) {
722 return !isServer || std::chrono::duration_cast<std::chrono::milliseconds>(
723 std::chrono::steady_clock::now() - lastReceivedHeartbeat).count()
724 < 2*HEARTBEAT_INTERVAL_MS;
731 if(protType == PROTOCOL_TCP) {
736 if(confirmationMessagePending) {
738 confirmationMessagePending =
false;
739 controlMessageBuffer[0] = CONFIRM_MESSAGE;
741 }
else if(!isServer && std::chrono::duration_cast<std::chrono::milliseconds>(
742 std::chrono::steady_clock::now() - lastRemoteHostActivity).count() > RECONNECT_TIMEOUT_MS) {
744 controlMessageBuffer[0] = CONNECTION_MESSAGE;
748 lastRemoteHostActivity = lastSentHeartbeat = std::chrono::steady_clock::now();
749 }
else if(transferHeaderData !=
nullptr &&
isConnected()) {
751 length = transferHeaderSize;
752 const unsigned char* ret = transferHeaderData;
753 transferHeaderData =
nullptr;
755 }
else if(eofMessagePending) {
757 eofMessagePending =
false;
758 unsigned int networkOffset = htonl(mergeRawOffset(lastTransmittedBlock, transferSize[lastTransmittedBlock]));
759 memcpy(&controlMessageBuffer[0], &networkOffset,
sizeof(
int));
760 controlMessageBuffer[
sizeof(int)] = EOF_MESSAGE;
762 }
else if(resendMessagePending) {
764 resendMessagePending =
false;
765 if(!generateResendRequest(length)) {
769 }
else if(!isServer && std::chrono::duration_cast<std::chrono::milliseconds>(
770 std::chrono::steady_clock::now() - lastSentHeartbeat).count() > HEARTBEAT_INTERVAL_MS) {
772 controlMessageBuffer[0] = HEARTBEAT_MESSAGE;
774 lastSentHeartbeat = std::chrono::steady_clock::now();
780 controlMessageBuffer[length++] = 0xff;
781 controlMessageBuffer[length++] = 0xff;
782 controlMessageBuffer[length++] = 0xff;
783 controlMessageBuffer[length++] = 0xff;
784 return controlMessageBuffer;
788 if(clientConnectionPending) {
789 clientConnectionPending =
false;
796 bool DataBlockProtocol::generateResendRequest(
int& length) {
797 length =
static_cast<int>(missingReceiveSegments.size() * (
sizeof(int) +
sizeof(
unsigned short)));
798 if(length +
sizeof(
int) + 1>
sizeof(controlMessageBuffer)) {
803 for(MissingReceiveSegment segment: missingReceiveSegments) {
804 unsigned int segOffset = htonl(static_cast<unsigned int>(segment.offset));
805 unsigned int segLen = htonl(static_cast<unsigned int>(segment.length));
807 memcpy(&controlMessageBuffer[length], &segOffset,
sizeof(segOffset));
808 length +=
sizeof(
unsigned int);
809 memcpy(&controlMessageBuffer[length], &segLen,
sizeof(segLen));
810 length +=
sizeof(
unsigned int);
813 controlMessageBuffer[length++] = RESEND_MESSAGE;
818 void DataBlockProtocol::parseResendMessage(
int length) {
819 missingTransferSegments.clear();
821 int num = length / (
sizeof(
unsigned int) +
sizeof(
unsigned short));
822 int bufferOffset = 0;
824 for(
int i=0; i<num; i++) {
825 unsigned int segOffsetNet = *
reinterpret_cast<unsigned int*
>(&receiveBuffer[bufferOffset]);
826 bufferOffset +=
sizeof(
unsigned int);
827 unsigned int segLenNet = *
reinterpret_cast<unsigned int*
>(&receiveBuffer[bufferOffset]);
828 bufferOffset +=
sizeof(
unsigned int);
830 int segmentOffsetRaw =
static_cast<int>(ntohl(segOffsetNet));
831 int segmentLength =
static_cast<int>(ntohl(segLenNet));
832 int dataBlockID, segmentOffset;
833 splitRawOffset(segmentOffsetRaw, dataBlockID, segmentOffset);
835 if(segmentOffset >= 0 && segmentLength > 0 && (segmentOffset + segmentLength) <= rawValidBytes[dataBlockID]) {
836 missingTransferSegments.push_back(std::pair<int, int>(
837 segmentOffsetRaw, segmentLength));
843 void DataBlockProtocol::parseEofMessage(
int length) {
845 completedReceptions++;
846 lostSegmentRate = (lostSegmentRate * (completedReceptions-1) + ((
double) lostSegmentBytes) / totalReceiveSize) / completedReceptions;
850 for (
int i=0; i<numReceptionBlocks; ++i) {
851 if (blockReceiveOffsets[i] < blockReceiveSize[i]) {
852 MissingReceiveSegment missingSeg;
853 missingSeg.offset = blockReceiveOffsets[i];
854 missingSeg.length = blockReceiveSize[i] - blockReceiveOffsets[i];
855 missingSeg.isEof =
true;
856 missingReceiveSegments.push_back(missingSeg);
857 lostSegmentBytes += missingSeg.length;
860 if(missingReceiveSegments.size() > 0) {
861 waitingForMissingSegments =
true;
862 resendMessagePending =
true;
865 for (
int i=0; i<static_cast<int>(missingReceiveSegments.size()); ++i) {
866 splitRawOffset(missingReceiveSegments[i].offset, mblock, moffset);
867 if (moffset < blockReceiveOffsets[mblock]) {
868 blockReceiveOffsets[mblock] = moffset;
872 finishedReception =
true;
875 LOG_ERROR(
"EOF message too short, length " << length);
879 void DataBlockProtocol::resizeReceiveBuffer() {
880 if(totalReceiveSize < 0) {
887 + MAX_OUTSTANDING_BYTES +
sizeof(int);
890 if(static_cast<int>(receiveBuffer.size()) < bufferSize) {
891 receiveBuffer.resize(bufferSize);
894 for (
int i=0; i<numReceptionBlocks; ++i) {
895 if (static_cast<int>(blockReceiveBuffers[i].size()) < blockReceiveSize[i]) {
896 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.