diff --git a/src/fsfw/globalfunctions/DleParser.cpp b/src/fsfw/globalfunctions/DleParser.cpp index 211814ba..e8139fc5 100644 --- a/src/fsfw/globalfunctions/DleParser.cpp +++ b/src/fsfw/globalfunctions/DleParser.cpp @@ -4,16 +4,24 @@ #include DleParser::DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf, - BufPair decodedBuf, FoundPacketHandler handler, void* args) + BufPair decodedBuf, UserHandler handler, void* args) : decodeRingBuf(decodeRingBuf), decoder(decoder), encodedBuf(encodedBuf), decodedBuf(decodedBuf), handler(handler), - args(args) {} + 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 + } +} ReturnValue_t DleParser::passData(uint8_t* data, size_t len) { - if (data == nullptr or len == 0) { + if (data == nullptr or len == 0 or handler == nullptr) { return RETURN_FAILED; } size_t copyIntoRingBufFromHere = 0; @@ -30,8 +38,10 @@ ReturnValue_t DleParser::passData(uint8_t* data, size_t len) { } else { // Maybe print warning, should not happen decodeRingBuf.clear(); - ctx.len = idx; - handleParseError(ErrorTypes::CONSECUTIVE_STX_CHARS, ctx); + ErrorInfo info; + info.len = idx; + prepareErrorContext(ErrorTypes::CONSECUTIVE_STX_CHARS, info); + handler(ctx); copyIntoRingBufFromHere = idx; copyAmount = len - idx; } @@ -44,15 +54,20 @@ ReturnValue_t DleParser::passData(uint8_t* data, size_t len) { result = decoder.decode(data + startIdx, idx + 1 - startIdx, &readLen, decodedBuf.first, decodedBuf.second, &decodedLen); if (result == HasReturnvaluesIF::RETURN_OK) { - if (this->handler != nullptr) { - this->handler(decodedBuf.first, decodedLen, this->args); - } + ctx.setType(ContextType::PACKET_FOUND); + ctx.decodedPacket.first = decodedBuf.first; + ctx.decodedPacket.second = decodedLen; + this->handler(ctx); } else if (result == DleEncoder::STREAM_TOO_SHORT) { - ctx.res = result; - handleParseError(ErrorTypes::DECODING_BUF_TOO_SMALL, ctx); + ErrorInfo info; + info.res = result; + prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info); + handler(ctx); } else { - ctx.res = result; - handleParseError(ErrorTypes::DECODE_ERROR, ctx); + ErrorInfo info; + info.res = result; + prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info); + handler(ctx); } decodeRingBuf.clear(); if ((idx + 1) < len) { @@ -66,13 +81,17 @@ ReturnValue_t DleParser::passData(uint8_t* data, size_t len) { // to decode it result = decodeRingBuf.writeData(data, idx + 1); if (result != HasReturnvaluesIF::RETURN_OK) { - ctx.res = result; - handleParseError(ErrorTypes::RING_BUF_ERROR, ctx); + ErrorInfo info; + info.res = result; + prepareErrorContext(ErrorTypes::RING_BUF_ERROR, info); + handler(ctx); } size_t fullEncodedLen = decodeRingBuf.getAvailableReadData(); if (fullEncodedLen > encodedBuf.second) { - ctx.len = fullEncodedLen; - handleParseError(ErrorTypes::ENCODED_BUF_TOO_SMALL, ctx); + ErrorInfo info; + info.len = fullEncodedLen; + prepareErrorContext(ErrorTypes::ENCODED_BUF_TOO_SMALL, info); + handler(ctx); decodeRingBuf.clear(); } else { size_t decodedLen = 0; @@ -82,14 +101,21 @@ ReturnValue_t DleParser::passData(uint8_t* data, size_t len) { decodedBuf.second, &decodedLen); if (result == HasReturnvaluesIF::RETURN_OK) { if (this->handler != nullptr) { - this->handler(decodedBuf.first, decodedLen, this->args); + ctx.setType(ContextType::PACKET_FOUND); + ctx.decodedPacket.first = decodedBuf.first; + ctx.decodedPacket.second = decodedLen; + this->handler(ctx); } } else if (result == DleEncoder::STREAM_TOO_SHORT) { - ctx.res = result; - handleParseError(ErrorTypes::DECODING_BUF_TOO_SMALL, ctx); + ErrorInfo info; + info.res = result; + prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info); + handler(ctx); } else { - ctx.res = result; - handleParseError(ErrorTypes::DECODE_ERROR, ctx); + ErrorInfo info; + info.res = result; + prepareErrorContext(ErrorTypes::DECODE_ERROR, info); + handler(ctx); } decodeRingBuf.clear(); startFound = false; @@ -103,9 +129,11 @@ ReturnValue_t DleParser::passData(uint8_t* data, size_t len) { } } else { // End data without preceeding STX + ErrorInfo info; + info.len = idx + 1; + prepareErrorContext(ErrorTypes::CONSECUTIVE_ETX_CHARS, info); + handler(ctx); decodeRingBuf.clear(); - ctx.len = idx + 1; - handleParseError(ErrorTypes::CONSECUTIVE_ETX_CHARS, ctx); if ((idx + 1) < len) { copyIntoRingBufFromHere = idx + 1; copyAmount = len - idx - 1; @@ -120,8 +148,10 @@ ReturnValue_t DleParser::passData(uint8_t* data, size_t len) { if (copyAmount > 0) { result = decodeRingBuf.writeData(data + copyIntoRingBufFromHere, copyAmount); if (result != HasReturnvaluesIF::RETURN_OK) { - ctx.res = result; - handleParseError(ErrorTypes::RING_BUF_ERROR, ctx); + ErrorInfo info; + info.res = result; + prepareErrorContext(ErrorTypes::RING_BUF_ERROR, info); + handler(ctx); } } return RETURN_OK; @@ -138,8 +168,12 @@ void DleParser::defaultFoundPacketHandler(uint8_t* packet, size_t len, void* arg #endif } -void DleParser::handleParseError(ErrorTypes err, ErrorCtx ctx) { +void DleParser::defaultErrorHandler(ErrorTypes err, ErrorInfo ctx) { switch (err) { + case (ErrorTypes::NONE): { + errorPrinter("No error"); + break; + } case (ErrorTypes::DECODE_ERROR): { errorPrinter("Decode Error"); break; @@ -183,6 +217,12 @@ void DleParser::errorPrinter(const char* str, const char* opt) { #endif } +void DleParser::prepareErrorContext(ErrorTypes err, ErrorInfo info) { + ctx.setType(ContextType::ERROR); + ctx.error.first = err; + ctx.error.second = info; +} + void DleParser::reset() { startFound = false; decodeRingBuf.clear(); diff --git a/src/fsfw/globalfunctions/DleParser.h b/src/fsfw/globalfunctions/DleParser.h index 630de77e..32fe38cb 100644 --- a/src/fsfw/globalfunctions/DleParser.h +++ b/src/fsfw/globalfunctions/DleParser.h @@ -20,9 +20,11 @@ class DleParser : public HasReturnvaluesIF { public: using BufPair = std::pair; - using FoundPacketHandler = void (*)(uint8_t* data, size_t len, void* args); + + enum class ContextType { PACKET_FOUND, ERROR }; enum class ErrorTypes { + NONE, ENCODED_BUF_TOO_SMALL, DECODING_BUF_TOO_SMALL, DECODE_ERROR, @@ -31,11 +33,39 @@ class DleParser : public HasReturnvaluesIF { CONSECUTIVE_ETX_CHARS }; - union ErrorCtx { + union ErrorInfo { size_t len; ReturnValue_t res; }; + using ErrorPair = std::pair; + + struct Context { + public: + Context(void* args) : userArgs(args) { setType(ContextType::PACKET_FOUND); } + + void setType(ContextType type) { + if (type == ContextType::PACKET_FOUND) { + error.first = ErrorTypes::NONE; + error.second.len = 0; + } else { + decodedPacket.first = nullptr; + decodedPacket.second = 0; + } + } + + ContextType getType() const { return type; } + + BufPair decodedPacket = {}; + ErrorPair error; + void* userArgs; + + private: + ContextType type; + }; + + using UserHandler = void (*)(const Context& ctx); + /** * Base class constructor * @param decodeRingBuf Ring buffer used to store multiple packets to allow detecting DLE packets @@ -49,7 +79,7 @@ class DleParser : public HasReturnvaluesIF { * @param args Arbitrary user argument */ DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf, - BufPair decodedBuf, FoundPacketHandler handler, void* args); + BufPair decodedBuf, UserHandler handler, void* args); /** * This function allows to pass new data into the parser. It then scans for DLE packets @@ -74,23 +104,23 @@ class DleParser : public HasReturnvaluesIF { * - For buffer length errors, will be set to the detected packet length which is too large * - For decode or ring buffer errors, will be set to the result returned from the failed call */ - virtual void handleParseError(ErrorTypes err, ErrorCtx ctx); + static void defaultErrorHandler(ErrorTypes err, ErrorInfo ctx); - void errorPrinter(const char* str, const char* opt = nullptr); + static void errorPrinter(const char* str, const char* opt = nullptr); + void prepareErrorContext(ErrorTypes err, ErrorInfo ctx); /** * Resets the parser by resetting the internal states and clearing the decoding ring buffer */ void reset(); private: - ErrorCtx ctx; SimpleRingBuffer& decodeRingBuf; DleEncoder& decoder; BufPair encodedBuf; BufPair decodedBuf; - FoundPacketHandler handler = nullptr; - void* args = nullptr; + UserHandler handler = nullptr; + Context ctx; bool startFound = false; };