From 193899b4d76ec96d30eb4e8e913a6861f41517e1 Mon Sep 17 00:00:00 2001 From: Kevin Matz Date: Fri, 27 Aug 2021 12:09:19 -0400 Subject: [PATCH] Provenance can be a POD struct --- protocols/sacn/mergeproxyuniverse.cpp | 2 +- protocols/sacn/provenance.cpp | 176 +++++--------------------- protocols/sacn/provenance.h | 98 +++++++++----- protocols/sacn/receiver.cpp | 14 +- protocols/sacn/source.cpp | 6 +- test/test_sacn.cpp | 10 +- 6 files changed, 113 insertions(+), 193 deletions(-) diff --git a/protocols/sacn/mergeproxyuniverse.cpp b/protocols/sacn/mergeproxyuniverse.cpp index 7e76e2a..4c5bf38 100644 --- a/protocols/sacn/mergeproxyuniverse.cpp +++ b/protocols/sacn/mergeproxyuniverse.cpp @@ -238,7 +238,7 @@ Universe* MergeProxyUniverse::dominant_() const { if (uni->rxRate() < (DMX::E111_DATA_LOSS_TIMEOUT / 1000.0)) continue; // stale universes cannot be dominant - if (!ret || uni->source()->priority() > ret->source()->priority()) + if (!ret || uni->source()->priority > ret->source()->priority) ret = uni; } return ret; diff --git a/protocols/sacn/provenance.cpp b/protocols/sacn/provenance.cpp index c9f56dd..d98bc6e 100644 --- a/protocols/sacn/provenance.cpp +++ b/protocols/sacn/provenance.cpp @@ -25,19 +25,18 @@ #include "provenance.h" #include "rlp/rlp.h" -namespace SACN { - +namespace sACN { /** * @brief Provenance::Provenance */ Provenance::Provenance() - : cid_(UUID::uuid()) - , description_(std::string()) - , universe_(0) - , priority_(100) - , sync_address_(0) - , options_(0) + : cid(UUID::uuid()) + , source_name(std::string()) + , priority(100) + , sync_address(0) + , sequence_number(0) + , universe(0) {} @@ -45,169 +44,58 @@ Provenance::Provenance() * @brief Construct a Universe Source from an sACN frame PDU * @param pdu */ -Provenance::Provenance(std::shared_ptr pdu) +Provenance::Provenance(ACN::PDU::Message pdu) { auto root_header = static_cast(pdu->parent()->header()); auto frame_header = static_cast(pdu->header()); - cid_ = root_header->cid; - description_ = frame_header->source_name; - universe_ = frame_header->universe; - priority_ = frame_header->priority; - sync_address_ = frame_header->sync_address; - options_ = frame_header->options; + cid = root_header->cid; + source_name = frame_header->source_name; + universe = frame_header->universe; + priority = frame_header->priority; + sync_address = frame_header->sync_address; + sequence_number = frame_header->sequence_number; + options = frame_header->options; }; /** - * @brief Provenance::CID - * @return - */ -const UUID::uuid Provenance::CID() const -{ - return cid_; -} - - -/** - * @brief Provenance::description - * @return - */ -const std::string Provenance::description() const -{ - return description_; -} - - -/** - * @brief Provenance::universe - * @return - */ -uint16_t Provenance::universe() const -{ - return universe_; -} - - -/** - * @brief Provenance::priority - * @return - */ -uint8_t Provenance::priority() const -{ - return priority_; -} - - -/** - * @brief Provenance::syncAddress - * @return - */ -uint16_t Provenance::syncAddress() const -{ - return sync_address_; -} - - -/** - * @brief Provenance::isTerminated - * @return - */ -bool Provenance::isTerminated() const -{ - return options_ & DATA::STREAM_TERMINATED; -} - - -/** - * @brief Provenance::isPreview - * @return - */ -bool Provenance::isPreview() const -{ - return options_ & DATA::PREVIEW_DATA; -} - - -/** - * @brief Provenance::isForced - * @return - */ -bool Provenance::isForced() const -{ - return options_ & DATA::FORCE_SYNCHRONIZATION; -} - - -/** - * @brief operator == + * @brief Metadata is equivalent if the CID, Priority, and Universe match. * @param a * @param b * @return */ bool operator== (const Provenance& a, const Provenance& b) { - return (std::hash{}(a) == std::hash{}(b)); + return (a.cid == b.cid && + a.priority == b.priority && + a.universe == b.universe); } /** - * @brief Provenance::setCID - * @param cid - */ -void Provenance::setCID(UUID::uuid cid) -{ - cid_ = cid; -} - - -/** - * @brief Provenance::setDescription - * @param desc - */ -void Provenance::setDescription(std::string desc) -{ - description_ = desc; -} - - -/** - * @brief Provenance::setOptions - * @param o - */ -void Provenance::setOptions(uint8_t o) -{ - options_ = o; -} - - -/** - * @brief Provenance::setUniverse - * @param n - */ -void Provenance::setUniverse(uint16_t n) -{ - if (n >= 1 && n <= 63999) universe_ = n; -} - - -/** - * @brief Provenance::setSyncAddress + * @brief For matching universe numbers, lower priorities are lesser. * @param a + * @param b + * @return */ -void Provenance::setSyncAddress(uint16_t a) +bool operator< (const Provenance& a, const Provenance& b) { - if (a >= 1 && a <= 63999) sync_address_ = a; + return (a.universe == b.universe && + a.priority < b.priority); } /** - * @brief Provenance::setPriority - * @param p + * @brief For matching universe numbers, higher priorities are greater. + * @param a + * @param b + * @return */ -void Provenance::setPriority(uint8_t p) +bool operator> (const Provenance& a, const Provenance& b) { - if (p <= 200) priority_ = p; + return (a.universe == b.universe && + a.priority > b.priority); } diff --git a/protocols/sacn/provenance.h b/protocols/sacn/provenance.h index b56d5ab..029f625 100644 --- a/protocols/sacn/provenance.h +++ b/protocols/sacn/provenance.h @@ -29,43 +29,75 @@ #include #include -namespace SACN { +namespace sACN { /** - * @brief The Provenance class + * @brief Metadata for a sACN::Universe */ -class Provenance +struct Provenance { -public: Provenance(); - Provenance(std::shared_ptr); + explicit Provenance(ACN::PDU::Message); - const UUID::uuid CID() const; - const std::string description() const; - uint16_t universe() const; - uint8_t priority() const; - uint16_t syncAddress() const; - bool isTerminated() const; - bool isPreview() const; - bool isForced() const; + /// \cite sACN 5.6 CID (Component Identifier) + /// + /// The Root Layer contains a CID. The CID shall be compliant with RFC 4122 + /// \cite uuid. + UUID::uuid cid; + + /// \cite sACN 6.2.2 E1.31 Data Packet: Source Name + /// + /// A user-assigned name provided by the source of the packet for use in + /// displaying the identity of a source to a user. + /// + /// If the source component implements ACN discovery as defined in EPI 19 + /// \cite epi19, then this name shall be the same as the UACN field specified + /// in EPI 19 \cite epi19. User-Assigned Component Names supply a single name + /// for an entire component, so this Source Name field will exist for each + /// unique CID, but may be the same across multiple universes sourced by the + /// same component. + std::string source_name; + + /// \cite sACN 6.2.3 E1.31 Data Packet: Priority + /// + /// Sources that do not support variable priority shall transmit a priority + /// of 100. Priority increases with numerical value, e.g., 200 is a higher + /// priority than 100. + uint8_t priority; + + /// \cite sACN 6.2.4 E1.31 Data Packet: Synchronization Address + /// + /// The Synchronization Address identifies a universe number to be used for + /// universe synchronization. + uint16_t sync_address; + + /// \cite sACN 6.2.5 E1.31 Data Packet: Sequence Number + /// + /// Sources shall maintain a sequence for each universe they + /// transmit. The sequence number for a universe shall be incremented by one + /// for every packet sent on that universe. There is no implied relationship + /// between the sequence number of an E1.31 Synchronization Packet and the + /// sequence number of an E1.31 Data Packet on that same universe. + uint8_t sequence_number; + + /// \cite sACN 6.2.6 E1.31 Data Packet: Options + /// + /// This bit-oriented field is used to encode optional flags that control + /// how the packet is used. + DATA::data_options options; + + /// \cite sACN 6.2.7 E1.31 Data Packet: Universe + /// + /// The Universe is a 16-bit field that defines the universe number of the + /// data carried in the packet. Universe values shall be limited to the range + /// 1 to 63999. + uint16_t universe; friend bool operator== (const Provenance& a, const Provenance& b); - - void setCID(UUID::uuid cid); - void setDescription(std::string desc); - void setOptions(uint8_t o); - void setUniverse(uint16_t n); - void setSyncAddress(uint16_t a); - void setPriority(uint8_t p); - -private: - UUID::uuid cid_; - std::string description_; - uint16_t universe_; - uint8_t priority_; - uint16_t sync_address_; - uint8_t options_; + friend bool operator< (const Provenance& a, const Provenance& b); + friend bool operator> (const Provenance& a, const Provenance& b); }; + } // SACN namespace @@ -75,18 +107,18 @@ namespace std /** * @brief The hash struct specilizaton for SACN::Provenance */ - struct hash + struct hash { /** * @brief operator () * @param src * @return */ - size_t operator()(SACN::Provenance const& src) const noexcept + size_t operator()(sACN::Provenance const& src) const noexcept { - size_t h1 = hash{}(src.description()); - size_t h2 = hash{}(src.CID()); - size_t h3 = hash{}(src.priority()); + size_t h1 = hash{}(src.source_name); + size_t h2 = hash{}(src.cid); + size_t h3 = hash{}(src.priority); size_t h = h1 ^ h2 ^ h3; // or use boost::hash_combine return h; } diff --git a/protocols/sacn/receiver.cpp b/protocols/sacn/receiver.cpp index a11de9c..d361374 100644 --- a/protocols/sacn/receiver.cpp +++ b/protocols/sacn/receiver.cpp @@ -192,9 +192,9 @@ void Receiver::extendedReceiver(ACN::PDU::Message root) void Receiver::dataFrameHandler(ACN::PDU::Message frame) { auto source = std::shared_ptr(new Provenance(frame)); - if (!universes_.count(source->universe())) + if (!universes_.count(source->universe)) return; - auto universe = universes_.at(source->universe())->sourceUniverse(*source); + auto universe = universes_.at(source->universe)->sourceUniverse(*source); /// \cite sACN /// 6.2.6 E1.31 Data Packet: Options @@ -202,7 +202,7 @@ void Receiver::dataFrameHandler(ACN::PDU::Message frame) { /// This bit, when set to 1, indicates that the data in this packet is /// intended for use in visualization or media server preview applications and /// shall not be used to generate live output. - if (source->isPreview()) + if (source->options.preview_data) return; /// \cite sACN @@ -212,8 +212,8 @@ void Receiver::dataFrameHandler(ACN::PDU::Message frame) { /// universe synchronization without waiting for a timeout to occur. /// Any property values in an E1.31 Data Packet containing this bit /// shall be ignored. - if (source->isTerminated()) { - universes_[source->universe()]->deleteSourceUniverse(*source); + if (source->options.stream_terminated) { + universes_[source->universe]->deleteSourceUniverse(*source); return; } @@ -221,8 +221,8 @@ void Receiver::dataFrameHandler(ACN::PDU::Message frame) { /// 6.2.4.1 Synchronization Address Usage in an E1.31 Data Packet /// a value of 0 in the Synchronization Address indicates that the universe /// data is not synchronized. - if (source->syncAddress() != 0) - subscribe(source->syncAddress()); + if (source->sync_address != 0) + subscribe(source->sync_address); // PDU data will be a block of DMP auto block = static_cast*>(frame->data()); diff --git a/protocols/sacn/source.cpp b/protocols/sacn/source.cpp index abed868..01076aa 100644 --- a/protocols/sacn/source.cpp +++ b/protocols/sacn/source.cpp @@ -47,9 +47,9 @@ void Source::create(const uint16_t num) universes_.emplace(num, new Universe()); auto source = std::shared_ptr(new Provenance()); - source->setCID(this->cid()); - source->setDescription(this->name()); - source->setUniverse(num); + source->cid = this->cid(); + source->source_name = this->name(); + source->universe = num; universes_[num]->setProvenance(source); } diff --git a/test/test_sacn.cpp b/test/test_sacn.cpp index 852679b..862290a 100644 --- a/test/test_sacn.cpp +++ b/test/test_sacn.cpp @@ -127,11 +127,11 @@ TEST_F(sACNdataTest, stream_in) { auto source = universe->source(); ASSERT_TRUE(source) << "stream failure"; - EXPECT_EQ(source->CID(), cid) << "UUID mismatch"; - EXPECT_EQ(source->description(), desc) << "Source Description mismatch"; - EXPECT_EQ(source->universe(), univ) << "universe number mismatch"; - EXPECT_EQ(source->priority(), priority) << "priority mismatch"; - EXPECT_EQ(source->syncAddress(), 0) << "sync address mismatch"; + EXPECT_EQ(source->cid, cid) << "UUID mismatch"; + EXPECT_EQ(source->source_name, desc) << "Source Description mismatch"; + EXPECT_EQ(source->universe, univ) << "universe number mismatch"; + EXPECT_EQ(source->priority, priority) << "priority mismatch"; + EXPECT_EQ(source->sync_address, 0) << "sync address mismatch"; EXPECT_EQ(universe->slot(512), (univ & 0xff)) << "slot 512 data mismatch"; node.unsubscribe(univ);