From 8e7a96ac822e63e8180a9df00f3e5fbae8b3f8f8 Mon Sep 17 00:00:00 2001 From: Kevin Matz Date: Tue, 10 Aug 2021 15:35:27 -0400 Subject: [PATCH] responder counts failed message construction --- rdm/message.cpp | 39 +++++++++++++++---- rdm/message.h | 11 ++++++ rdm/responder.cpp | 95 +++++++++++++++++++++++++++-------------------- rdm/responder.h | 4 ++ 4 files changed, 101 insertions(+), 48 deletions(-) diff --git a/rdm/message.cpp b/rdm/message.cpp index ecb77ea..a99c3e1 100644 --- a/rdm/message.cpp +++ b/rdm/message.cpp @@ -30,6 +30,7 @@ namespace RDM { * @brief Message::Message */ Message::Message() + : failure_mode(0) { } @@ -47,6 +48,7 @@ Message::Message(const Message &obj) , messageCount(obj.messageCount) , subDevice(obj.subDevice) , propertyID(obj.propertyID) + , failure_mode(0) { data_.insert(data_.end(), obj.data()->begin(), obj.data()->end()); } @@ -57,6 +59,7 @@ Message::Message(const Message &obj) * @param data */ Message::Message(const std::vector &data) + : failure_mode(0) { read(data); } @@ -77,15 +80,21 @@ Message::~Message() */ void Message::read(const std::vector &data) { - if (data.size() < 3) // SC + SC_SUB + LENGTH - return; + if (data.size() < 9) // SC + SC_SUB + LENGTH + DESTINATION + { + short_message = true; + return; + } // 6.2.1 START Code // This field shall contain the defined RDM START Code (SC_RDM). Controllers // and Responders shall always send SC_RDM in this slot, and any packet // containing a value other than SC_RDM is outside the scope of this standard. if (data[0] != SC_RDM) - return; + { + incorrect_sc = true; + return; + } // 6.2.2 Sub START Code // This field shall contain the Sub-START Code within RDM that defines this @@ -95,7 +104,10 @@ void Message::read(const std::vector &data) // Controllers shall always send SC_SUB_MESSAGE in this slot, and Responders // shall ignore any packets containing other values. if (data[1] != SC_SUB_MESSAGE) - return; + { + incorrect_sub_sc = true; + return; + } // 6.2.3 Message Length // The Message Length value is defined as the number of slots in the RDM @@ -103,8 +115,11 @@ void Message::read(const std::vector &data) // an 8-bit value. // The Message Length field points to the Checksum High Slot. uint8_t length = data[2]; - if (length != data.size() - 2) - return; + if (length + 2 != data.size()) + { + length_mismatch = true; + return; + } // 6.2.4 Destination UID // The Destination UID is the UID of the target device(s). @@ -168,9 +183,19 @@ void Message::read(const std::vector &data) uint8_t pdl = data[23]; // 6.2.10.4 Parameter Data (PD) - // The Parameter Data is of variable length. The content format is PID dependent. + // The Parameter Data is of variable length. for (int i = 0; i < pdl; i++) appendData(data[24+i]); + + // 6.2.11 Checksum + // If the checksum field in the packet does not match the calculated checksum, + // then the packet shall be discarded and no response sent. + auto chksum = Message::readType(data, data.size() - 2); + if (chksum != checksum()) + { + checksum_fail = true; + return; + } } diff --git a/rdm/message.h b/rdm/message.h index 90654be..9c96d4e 100644 --- a/rdm/message.h +++ b/rdm/message.h @@ -52,6 +52,17 @@ struct Message uint8_t commandClass; PID propertyID; + union { + uint8_t failure_mode; + struct { + bool short_message : 1; + bool length_mismatch : 1; + bool checksum_fail : 1; + bool incorrect_sc : 1; + bool incorrect_sub_sc: 1; + }; + }; + const std::vector* data() const { return &data_; } uint8_t length() const { return data_.size(); } uint16_t checksum() const; diff --git a/rdm/responder.cpp b/rdm/responder.cpp index ca73d46..f8c1671 100644 --- a/rdm/responder.cpp +++ b/rdm/responder.cpp @@ -23,6 +23,8 @@ */ #include "responder.h" +#include + namespace RDM { /** @@ -34,14 +36,19 @@ Responder::Responder() deviceModelID = 1; deviceModelDescription = "Basic RDM Responder"; - // E1.20 required parameters -// DISC_UNIQUE_BRANCH -// DISC_MUTE -// DISC_UN_MUTE - - // addt'l parameters -// COMMS_STATUS -// QUEUED_MESSAGE +// /// Category – Network Management +// static const PID DISC_UNIQUE_BRANCH = 0x0001; +// static const PID DISC_MUTE = 0x0002; +// static const PID DISC_UN_MUTE = 0x0003; +// static const PID PROXIED_DEVICES = 0x0010; +// static const PID PROXIED_DEVICE_COUNT = 0x0011; +// static const PID COMMS_STATUS = 0x0015; +// /// Category - Status Collection +// static const PID QUEUED_MESSAGE = 0x0020; // See Table A-4 +// static const PID STATUS_MESSAGES = 0x0030; // See Table A-4 +// static const PID STATUS_ID_DESCRIPTION = 0x0031; +// static const PID CLEAR_STATUS_ID = 0x0032; +// static const PID SUB_DEVICE_STATUS_REPORT_THRESHOLD = 0x0033; // See Table A-4 } @@ -96,25 +103,6 @@ void Responder::send(Message *response) void Responder::receive(const std::vector &data) { auto message = new Message(data); - - // 6.2.8.1 Message Count field for Controller Generated Messages - // The Message Count shall be set to 0x00 in all controller generated requests. - if (message->messageCount != 0) - { - delete message; - return; - } - - // 6.2.11 Checksum - // If the checksum field in the packet does not match the calculated checksum, - // then the packet shall be discarded and no response sent. - auto checksum = Message::readType(data, data.size() - 2); - if (checksum != message->checksum()) - { - delete message; - return; - } - receive(message); delete message; } @@ -126,13 +114,41 @@ void Responder::receive(const std::vector &data) */ void Responder::receive(const Message *message) { - if (message->commandClass != DISCOVERY_COMMAND || - message->commandClass != GET_COMMAND || - message->commandClass != SET_COMMAND) - return; + if (message->short_message) + { + if (short_message_counter_ != std::numeric_limits::max()) + short_message_counter_++; + return; + } // RDM::UID::operator== also returns true for broadcast messages - if (message->destination != id) + if (message->destination != id || + message->incorrect_sc || + message->incorrect_sub_sc) + return; + + if (message->length_mismatch) + { + if (length_mismatch_counter_ != std::numeric_limits::max()) + length_mismatch_counter_++; + return; + } + + if (message->checksum_fail) + { + if (checksum_fail_counter_ != std::numeric_limits::max()) + checksum_fail_counter_++; + return; + } + + // all other uncaught errors + if (message->failure_mode != 0) + return; + + // responder can ignore _COMMAND_RESPONSE class messages + if (message->commandClass == DISCOVERY_COMMAND_RESPONSE || + message->commandClass == GET_COMMAND_RESPONSE || + message->commandClass == SET_COMMAND_RESPONSE) return; auto response = new Message(); @@ -153,8 +169,12 @@ void Responder::receive(const Message *message) rxSet(message, response); break; default: - break; + delete response; + return; } + + if (response) + queued_messages_.push(response); } @@ -166,7 +186,6 @@ void Responder::rxDiscovery(__attribute__((unused)) const Message *message, Message* response) { response->commandClass = DISCOVERY_COMMAND_RESPONSE; - queued_messages_.push(response); } @@ -186,14 +205,12 @@ void Responder::rxGet(const Message *message, { response->responseType = RESPONSE_TYPE_NACK_REASON; response->appendData(NR_SUB_DEVICE_OUT_OF_RANGE); - queued_messages_.push(response); return; } if (message->subDevice == 0) { get(message, response); - queued_messages_.push(response); return; } @@ -201,12 +218,10 @@ void Responder::rxGet(const Message *message, { response->responseType = RESPONSE_TYPE_NACK_REASON; response->appendData(NR_SUB_DEVICE_OUT_OF_RANGE); - queued_messages_.push(response); return; } sub_devices_.at(message->subDevice)->get(message, response); - queued_messages_.push(response); } @@ -220,7 +235,6 @@ void Responder::rxSet(const Message *message, if (message->subDevice == 0) { set(message, response); - queued_messages_.push(response); return; } @@ -234,6 +248,7 @@ void Responder::rxSet(const Message *message, queued_messages_.push(rsp); } delete response; + response = nullptr; return; } @@ -241,12 +256,10 @@ void Responder::rxSet(const Message *message, { response->responseType = RESPONSE_TYPE_NACK_REASON; response->appendData(NR_SUB_DEVICE_OUT_OF_RANGE); - queued_messages_.push(response); return; } sub_devices_.at(message->subDevice)->set(message, response); - queued_messages_.push(response); } diff --git a/rdm/responder.h b/rdm/responder.h index cfa3fcb..fb48146 100644 --- a/rdm/responder.h +++ b/rdm/responder.h @@ -53,6 +53,10 @@ protected: std::queue queued_messages_; private: + uint16_t short_message_counter_ = 0; + uint16_t length_mismatch_counter_ = 0; + uint16_t checksum_fail_counter_ = 0; + };