2022-04-13 14:45:36 +02:00
|
|
|
#include "DleParser.h"
|
|
|
|
|
|
|
|
#include <fsfw/serviceinterface/ServiceInterface.h>
|
|
|
|
|
|
|
|
#include <cstdio>
|
2022-10-04 18:38:20 +02:00
|
|
|
#include <fstream>
|
|
|
|
#include <iostream>
|
2022-04-13 14:45:36 +02:00
|
|
|
|
|
|
|
DleParser::DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf,
|
|
|
|
BufPair decodedBuf, UserHandler handler, void* args)
|
|
|
|
: decodeRingBuf(decodeRingBuf),
|
|
|
|
decoder(decoder),
|
|
|
|
encodedBuf(encodedBuf),
|
|
|
|
decodedBuf(decodedBuf),
|
|
|
|
handler(handler),
|
|
|
|
ctx(args) {
|
|
|
|
if (handler == nullptr) {
|
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
|
|
sif::error << "DleParser::DleParser: Invalid user handler" << std::endl;
|
|
|
|
#else
|
|
|
|
sif::printError("DleParser::DleParser: Invalid user handler\n");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-04 18:38:20 +02:00
|
|
|
ReturnValue_t DleParser::passData(const uint8_t* data, size_t len) {
|
2022-04-13 14:45:36 +02:00
|
|
|
if (data == nullptr or len == 0 or handler == nullptr) {
|
2022-08-24 17:25:45 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-04-13 14:45:36 +02:00
|
|
|
}
|
2022-10-04 18:38:20 +02:00
|
|
|
return decodeRingBuf.writeData(data , len);
|
|
|
|
// std::string filename = std::string("/mnt/sd0/scex/transfer") + std::to_string(COUNTER++);
|
|
|
|
// std::ofstream of(filename);
|
|
|
|
// of.write(reinterpret_cast<const char*>(data), len);
|
|
|
|
// size_t copyIntoRingBufFromHere = 0;
|
|
|
|
// size_t copyAmount = len;
|
|
|
|
// size_t startIdx = 0;
|
|
|
|
// ReturnValue_t result = returnvalue::OK;
|
|
|
|
// bool startFoundInThisPacket = false;
|
|
|
|
// for (size_t idx = 0; idx < len; idx++) {
|
|
|
|
// if (data[idx] == DleEncoder::STX_CHAR) {
|
|
|
|
// if (not startFound and not startFoundInThisPacket) {
|
|
|
|
// startIdx = idx;
|
|
|
|
// copyIntoRingBufFromHere = idx;
|
|
|
|
// copyAmount = len - idx;
|
|
|
|
// } else {
|
|
|
|
// // Maybe print warning, should not happen
|
|
|
|
// decodeRingBuf.clear();
|
|
|
|
// ErrorInfo info;
|
|
|
|
// info.len = idx;
|
|
|
|
// prepareErrorContext(ErrorTypes::CONSECUTIVE_STX_CHARS, info);
|
|
|
|
// handler(ctx);
|
|
|
|
// copyIntoRingBufFromHere = idx;
|
|
|
|
// copyAmount = len - idx;
|
|
|
|
// }
|
|
|
|
// startFound = true;
|
|
|
|
// startFoundInThisPacket = true;
|
|
|
|
// } else if (data[idx] == DleEncoder::ETX_CHAR) {
|
|
|
|
// if (startFoundInThisPacket) {
|
|
|
|
// size_t readLen = 0;
|
|
|
|
// size_t decodedLen = 0;
|
|
|
|
// result = decoder.decode(data + startIdx, idx + 1 - startIdx, &readLen, decodedBuf.first,
|
|
|
|
// decodedBuf.second, &decodedLen);
|
|
|
|
// if (result == returnvalue::OK) {
|
|
|
|
// ctx.setType(ContextType::PACKET_FOUND);
|
|
|
|
// ctx.decodedPacket.first = decodedBuf.first;
|
|
|
|
// ctx.decodedPacket.second = decodedLen;
|
|
|
|
// this->handler(ctx);
|
|
|
|
// } else if (result == DleEncoder::STREAM_TOO_SHORT) {
|
|
|
|
// ErrorInfo info;
|
|
|
|
// info.res = result;
|
|
|
|
// prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
|
|
|
|
// handler(ctx);
|
|
|
|
// } else {
|
|
|
|
// ErrorInfo info;
|
|
|
|
// info.res = result;
|
|
|
|
// prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
|
|
|
|
// handler(ctx);
|
|
|
|
// }
|
|
|
|
// decodeRingBuf.clear();
|
|
|
|
// if ((idx + 1) < len) {
|
|
|
|
// copyIntoRingBufFromHere = idx + 1;
|
|
|
|
// copyAmount = len - idx - 1;
|
|
|
|
// } else {
|
|
|
|
// copyAmount = 0;
|
|
|
|
// }
|
|
|
|
// } else if (startFound) {
|
|
|
|
// // ETX found but STX was found in another mini packet. Reconstruct the full packet
|
|
|
|
// // to decode it
|
|
|
|
// result = decodeRingBuf.writeData(data, idx + 1);
|
|
|
|
// if (result != returnvalue::OK) {
|
|
|
|
// ErrorInfo info;
|
|
|
|
// info.res = result;
|
|
|
|
// prepareErrorContext(ErrorTypes::RING_BUF_ERROR, info);
|
|
|
|
// handler(ctx);
|
|
|
|
// }
|
|
|
|
// size_t fullEncodedLen = decodeRingBuf.getAvailableReadData();
|
|
|
|
// if (fullEncodedLen > encodedBuf.second) {
|
|
|
|
// ErrorInfo info;
|
|
|
|
// info.len = fullEncodedLen;
|
|
|
|
// prepareErrorContext(ErrorTypes::ENCODED_BUF_TOO_SMALL, info);
|
|
|
|
// handler(ctx);
|
|
|
|
// decodeRingBuf.clear();
|
|
|
|
// } else {
|
|
|
|
// size_t decodedLen = 0;
|
|
|
|
// size_t readLen = 0;
|
|
|
|
// decodeRingBuf.readData(encodedBuf.first, fullEncodedLen, true);
|
|
|
|
// result = decoder.decode(encodedBuf.first, fullEncodedLen, &readLen, decodedBuf.first,
|
|
|
|
// decodedBuf.second, &decodedLen);
|
|
|
|
// if (result == returnvalue::OK) {
|
|
|
|
// if (this->handler != nullptr) {
|
|
|
|
// ctx.setType(ContextType::PACKET_FOUND);
|
|
|
|
// ctx.decodedPacket.first = decodedBuf.first;
|
|
|
|
// ctx.decodedPacket.second = decodedLen;
|
|
|
|
// this->handler(ctx);
|
|
|
|
// }
|
|
|
|
// } else if (result == DleEncoder::STREAM_TOO_SHORT) {
|
|
|
|
// ErrorInfo info;
|
|
|
|
// info.res = result;
|
|
|
|
// prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
|
|
|
|
// handler(ctx);
|
|
|
|
// } else {
|
|
|
|
// ErrorInfo info;
|
|
|
|
// info.res = result;
|
|
|
|
// prepareErrorContext(ErrorTypes::DECODE_ERROR, info);
|
|
|
|
// handler(ctx);
|
|
|
|
// }
|
|
|
|
// decodeRingBuf.clear();
|
|
|
|
// startFound = false;
|
|
|
|
// startFoundInThisPacket = false;
|
|
|
|
// if ((idx + 1) < len) {
|
|
|
|
// copyIntoRingBufFromHere = idx + 1;
|
|
|
|
// copyAmount = len - idx - 1;
|
|
|
|
// } else {
|
|
|
|
// copyAmount = 0;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// } else {
|
|
|
|
// // End data without preceeding STX
|
|
|
|
// ErrorInfo info;
|
|
|
|
// info.len = idx + 1;
|
|
|
|
// prepareErrorContext(ErrorTypes::CONSECUTIVE_ETX_CHARS, info);
|
|
|
|
// handler(ctx);
|
|
|
|
// decodeRingBuf.clear();
|
|
|
|
// if ((idx + 1) < len) {
|
|
|
|
// copyIntoRingBufFromHere = idx + 1;
|
|
|
|
// copyAmount = len - idx - 1;
|
|
|
|
// } else {
|
|
|
|
// copyAmount = 0;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// startFoundInThisPacket = false;
|
|
|
|
// startFound = false;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// if (copyAmount > 0) {
|
|
|
|
// result = decodeRingBuf.writeData(data + copyIntoRingBufFromHere, copyAmount);
|
|
|
|
// if (result != returnvalue::OK) {
|
|
|
|
// ErrorInfo info;
|
|
|
|
// info.res = result;
|
|
|
|
// prepareErrorContext(ErrorTypes::RING_BUF_ERROR, info);
|
|
|
|
// handler(ctx);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ReturnValue_t DleParser::parseRingBuf(size_t& readSize) {
|
|
|
|
size_t availableData = decodeRingBuf.getAvailableReadData();
|
|
|
|
if (availableData > encodedBuf.second) {
|
|
|
|
ErrorInfo info;
|
|
|
|
info.len = decodeRingBuf.getAvailableReadData();
|
|
|
|
prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
|
|
|
|
handler(ctx);
|
|
|
|
}
|
|
|
|
ReturnValue_t result = decodeRingBuf.readData(encodedBuf.first, availableData);
|
|
|
|
if(result != returnvalue::OK) {
|
|
|
|
ErrorInfo info;
|
|
|
|
info.res = result;
|
|
|
|
prepareErrorContext(ErrorTypes::RING_BUF_ERROR, info);
|
|
|
|
}
|
|
|
|
bool stxFound = false;
|
|
|
|
size_t stxIdx = 0;
|
|
|
|
for (size_t vectorIdx = 0; vectorIdx < availableData; vectorIdx++) {
|
|
|
|
// handle STX char
|
|
|
|
if (encodedBuf.first[vectorIdx] == DleEncoder::STX_CHAR) {
|
|
|
|
if (not stxFound) {
|
|
|
|
stxFound = true;
|
|
|
|
stxIdx = vectorIdx;
|
2022-04-13 14:45:36 +02:00
|
|
|
} else {
|
2022-10-04 18:38:20 +02:00
|
|
|
// might be lost packet, so we should advance the read pointer
|
|
|
|
// without skipping the STX
|
|
|
|
readSize = vectorIdx;
|
|
|
|
return POSSIBLE_PACKET_LOSS;
|
2022-04-13 14:45:36 +02:00
|
|
|
}
|
2022-10-04 18:38:20 +02:00
|
|
|
}
|
|
|
|
// handle ETX char
|
|
|
|
if (encodedBuf.first[vectorIdx] == DleEncoder::ETX_CHAR) {
|
|
|
|
if (stxFound) {
|
|
|
|
// This is propably a packet, so we decode it.
|
2022-04-13 14:45:36 +02:00
|
|
|
size_t decodedLen = 0;
|
2022-10-04 18:38:20 +02:00
|
|
|
size_t dummy = 0;
|
|
|
|
readSize = vectorIdx;
|
|
|
|
ReturnValue_t result = decoder.decode(&encodedBuf.first[stxIdx], availableData - stxIdx,
|
|
|
|
&dummy, decodedBuf.first, decodedBuf.second, &decodedLen);
|
2022-08-24 17:25:45 +02:00
|
|
|
if (result == returnvalue::OK) {
|
2022-04-13 14:45:36 +02:00
|
|
|
ctx.setType(ContextType::PACKET_FOUND);
|
|
|
|
ctx.decodedPacket.first = decodedBuf.first;
|
|
|
|
ctx.decodedPacket.second = decodedLen;
|
|
|
|
this->handler(ctx);
|
2022-10-04 18:38:20 +02:00
|
|
|
return returnvalue::OK;
|
2022-04-13 14:45:36 +02:00
|
|
|
} else {
|
2022-10-04 18:38:20 +02:00
|
|
|
// invalid packet, skip.
|
|
|
|
readSize = ++vectorIdx;
|
|
|
|
return POSSIBLE_PACKET_LOSS;
|
2022-04-13 14:45:36 +02:00
|
|
|
}
|
|
|
|
} else {
|
2022-10-04 18:38:20 +02:00
|
|
|
// might be lost packet, so we should advance the read pointer
|
|
|
|
readSize = ++vectorIdx;
|
|
|
|
return POSSIBLE_PACKET_LOSS;
|
2022-04-13 14:45:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-08-24 17:25:45 +02:00
|
|
|
return returnvalue::OK;
|
2022-04-13 14:45:36 +02:00
|
|
|
}
|
|
|
|
|
2022-10-04 18:38:20 +02:00
|
|
|
|
2022-04-13 14:45:36 +02:00
|
|
|
void DleParser::defaultFoundPacketHandler(uint8_t* packet, size_t len, void* args) {
|
|
|
|
#if FSFW_VERBOSE_LEVEL >= 1
|
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
|
|
sif::info << "DleParserBase::handleFoundPacket: Detected DLE packet with " << len << " bytes"
|
|
|
|
<< std::endl;
|
|
|
|
#else
|
|
|
|
sif::printInfo("DleParserBase::handleFoundPacket: Detected DLE packet with %d bytes\n", len);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void DleParser::defaultErrorHandler(ErrorTypes err, ErrorInfo ctx) {
|
|
|
|
switch (err) {
|
|
|
|
case (ErrorTypes::NONE): {
|
|
|
|
errorPrinter("No error");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case (ErrorTypes::DECODE_ERROR): {
|
|
|
|
errorPrinter("Decode Error");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case (ErrorTypes::RING_BUF_ERROR): {
|
|
|
|
errorPrinter("Ring Buffer Error");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case (ErrorTypes::ENCODED_BUF_TOO_SMALL):
|
|
|
|
case (ErrorTypes::DECODING_BUF_TOO_SMALL): {
|
|
|
|
char opt[64];
|
2022-04-26 10:32:37 +02:00
|
|
|
snprintf(opt, sizeof(opt), ": Too small for packet with length %zu", ctx.len);
|
2022-04-13 14:45:36 +02:00
|
|
|
if (err == ErrorTypes::ENCODED_BUF_TOO_SMALL) {
|
|
|
|
errorPrinter("Encoded buf too small", opt);
|
|
|
|
} else {
|
|
|
|
errorPrinter("Decoding buf too small", opt);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case (ErrorTypes::CONSECUTIVE_STX_CHARS): {
|
|
|
|
errorPrinter("Consecutive STX chars detected");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case (ErrorTypes::CONSECUTIVE_ETX_CHARS): {
|
|
|
|
errorPrinter("Consecutive ETX chars detected");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DleParser::errorPrinter(const char* str, const char* opt) {
|
|
|
|
if (opt == nullptr) {
|
|
|
|
opt = "";
|
|
|
|
}
|
|
|
|
#if FSFW_VERBOSE_LEVEL >= 1
|
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
|
|
sif::info << "DleParserBase::handleParseError: " << str << opt << std::endl;
|
|
|
|
#else
|
|
|
|
sif::printInfo("DleParserBase::handleParseError: %s%s\n", str, opt);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void DleParser::prepareErrorContext(ErrorTypes err, ErrorInfo info) {
|
|
|
|
ctx.setType(ContextType::ERROR);
|
|
|
|
ctx.error.first = err;
|
|
|
|
ctx.error.second = info;
|
|
|
|
}
|
|
|
|
|
2022-10-04 18:38:20 +02:00
|
|
|
ReturnValue_t DleParser::confirmBytesRead(size_t bytesRead) {
|
|
|
|
return decodeRingBuf.deleteData(bytesRead);
|
|
|
|
}
|
|
|
|
|
2022-04-13 14:45:36 +02:00
|
|
|
void DleParser::reset() {
|
|
|
|
startFound = false;
|
|
|
|
decodeRingBuf.clear();
|
|
|
|
}
|