From 23a00bbc5ce89055c08bda9c342449fcfbade2fd Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Wed, 29 Jan 2020 18:58:52 +0000 Subject: [PATCH 001/138] First attempt at LLRP header and PDU All there apart from flags should always be 0xF0 rather than 0x70 --- include/ola/acn/ACNVectors.h | 3 + libs/acn/HeaderSet.h | 8 +- libs/acn/LLRPHeader.h | 69 ++++++++++++++++ libs/acn/LLRPInflator.cpp | 70 ++++++++++++++++ libs/acn/LLRPInflator.h | 58 ++++++++++++++ libs/acn/LLRPInflatorTest.cpp | 126 +++++++++++++++++++++++++++++ libs/acn/LLRPPDU.cpp | 117 +++++++++++++++++++++++++++ libs/acn/LLRPPDU.h | 62 ++++++++++++++ libs/acn/LLRPPDUTest.cpp | 147 ++++++++++++++++++++++++++++++++++ libs/acn/Makefile.mk | 14 ++++ 10 files changed, 673 insertions(+), 1 deletion(-) create mode 100644 libs/acn/LLRPHeader.h create mode 100644 libs/acn/LLRPInflator.cpp create mode 100644 libs/acn/LLRPInflator.h create mode 100644 libs/acn/LLRPInflatorTest.cpp create mode 100644 libs/acn/LLRPPDU.cpp create mode 100644 libs/acn/LLRPPDU.h create mode 100644 libs/acn/LLRPPDUTest.cpp diff --git a/include/ola/acn/ACNVectors.h b/include/ola/acn/ACNVectors.h index 26c94da543..028c0e264b 100644 --- a/include/ola/acn/ACNVectors.h +++ b/include/ola/acn/ACNVectors.h @@ -47,6 +47,9 @@ enum RootVector { VECTOR_ROOT_E131 = 4, /**< E1.31 (sACN) */ VECTOR_ROOT_E133 = 5, /**< E1.33 (RDNNet) */ VECTOR_ROOT_NULL = 6, /**< NULL (empty) root */ + VECTOR_ROOT_BROKER = 9, /**< E1.33 (Broker) */ + VECTOR_ROOT_LLRP = 0x0A, /**< E1.33 (LLRP) */ + VECTOR_ROOT_EPT = 0x0B, /**< E1.33 (EPT) */ }; /** diff --git a/libs/acn/HeaderSet.h b/libs/acn/HeaderSet.h index c3e9a44f98..06a56c26aa 100644 --- a/libs/acn/HeaderSet.h +++ b/libs/acn/HeaderSet.h @@ -26,6 +26,7 @@ #include "libs/acn/DMPHeader.h" #include "libs/acn/E131Header.h" #include "libs/acn/E133Header.h" +#include "libs/acn/LLRPHeader.h" #include "libs/acn/RootHeader.h" #include "libs/acn/TransportHeader.h" @@ -56,13 +57,17 @@ class HeaderSet { const DMPHeader &GetDMPHeader() const { return m_dmp_header; } void SetDMPHeader(const DMPHeader &header) { m_dmp_header = header; } + const LLRPHeader &GetLLRPHeader() const { return m_llrp_header; } + void SetLLRPHeader(const LLRPHeader &header) { m_llrp_header = header; } + bool operator==(const HeaderSet &other) const { return ( m_transport_header == other.m_transport_header && m_root_header == other.m_root_header && m_e131_header == other.m_e131_header && m_e133_header == other.m_e133_header && - m_dmp_header == other.m_dmp_header); + m_dmp_header == other.m_dmp_header && + m_llrp_header == other.m_llrp_header); } private: @@ -71,6 +76,7 @@ class HeaderSet { E131Header m_e131_header; E133Header m_e133_header; DMPHeader m_dmp_header; + LLRPHeader m_llrp_header; }; } // namespace acn } // namespace ola diff --git a/libs/acn/LLRPHeader.h b/libs/acn/LLRPHeader.h new file mode 100644 index 0000000000..1d964268fd --- /dev/null +++ b/libs/acn/LLRPHeader.h @@ -0,0 +1,69 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPHeader.h + * The E1.33 LLRP Header + * Copyright (C) 2020 Peter Newman + */ + +#ifndef LIBS_ACN_LLRPHEADER_H_ +#define LIBS_ACN_LLRPHEADER_H_ + +#include +#include + +#include + +namespace ola { +namespace acn { + +/* + * Header for the LLRP layer + */ +class LLRPHeader { + public: + LLRPHeader() + : m_transaction_number(0) { + } + + LLRPHeader(const ola::acn::CID &destination_cid, + uint32_t transaction_number) + : m_destination_cid(destination_cid), + m_transaction_number(transaction_number) { + } + ~LLRPHeader() {} + + const ola::acn::CID DestinationCid() const { return m_destination_cid; } + uint32_t TransactionNumber() const { return m_transaction_number; } + + bool operator==(const LLRPHeader &other) const { + return m_destination_cid == other.m_destination_cid && + m_transaction_number == other.m_transaction_number; + } + + PACK( + struct llrp_pdu_header_s { + uint8_t destination_cid[CID::CID_LENGTH]; + uint32_t transaction_number; + }); + typedef struct llrp_pdu_header_s llrp_pdu_header; + + private: + ola::acn::CID m_destination_cid; + uint32_t m_transaction_number; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_LLRPHEADER_H_ diff --git a/libs/acn/LLRPInflator.cpp b/libs/acn/LLRPInflator.cpp new file mode 100644 index 0000000000..e629df8d50 --- /dev/null +++ b/libs/acn/LLRPInflator.cpp @@ -0,0 +1,70 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPInflator.cpp + * The Inflator for E1.33 LLRP + * Copyright (C) 2020 Peter Newman + */ + +#include "ola/Logging.h" +#include "ola/network/NetworkUtils.h" +#include "libs/acn/LLRPInflator.h" + +namespace ola { +namespace acn { + +using ola::network::NetworkToHost; + +/* + * Decode the E1.33 LLRP headers. If data is null we're expected to use the + * last header we got. + * @param headers the HeaderSet to add to + * @param data a pointer to the data + * @param length length of the data + * @returns true if successful, false otherwise + */ +bool LLRPInflator::DecodeHeader(HeaderSet *headers, + const uint8_t *data, + unsigned int length, + unsigned int *bytes_used) { + if (data) { + // the header bit was set, decode it + if (length >= sizeof(LLRPHeader::llrp_pdu_header)) { + LLRPHeader::llrp_pdu_header raw_header; + memcpy(&raw_header, data, sizeof(LLRPHeader::llrp_pdu_header)); + LLRPHeader header( + ola::acn::CID::FromData(raw_header.destination_cid), + NetworkToHost(raw_header.transaction_number)); + m_last_header = header; + m_last_header_valid = true; + headers->SetLLRPHeader(header); + *bytes_used = sizeof(LLRPHeader::llrp_pdu_header); + return true; + } + *bytes_used = 0; + return false; + } + + // use the last header if it exists + *bytes_used = 0; + if (!m_last_header_valid) { + OLA_WARN << "Missing E1.33 LLRP Header data"; + return false; + } + headers->SetLLRPHeader(m_last_header); + return true; +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/LLRPInflator.h b/libs/acn/LLRPInflator.h new file mode 100644 index 0000000000..34a5aa023d --- /dev/null +++ b/libs/acn/LLRPInflator.h @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPInflator.h + * Interface for the LLRPInflator class. + * Copyright (C) 2020 Peter Newman + */ + +#ifndef LIBS_ACN_LLRPINFLATOR_H_ +#define LIBS_ACN_LLRPINFLATOR_H_ + +#include "ola/acn/ACNVectors.h" +#include "libs/acn/BaseInflator.h" +#include "libs/acn/LLRPHeader.h" + +namespace ola { +namespace acn { + +class LLRPInflator: public BaseInflator { + friend class LLRPInflatorTest; + + public: + LLRPInflator() + : BaseInflator(), + m_last_header_valid(false) { + } + ~LLRPInflator() {} + + uint32_t Id() const { return ola::acn::VECTOR_ROOT_LLRP; } + + protected: + bool DecodeHeader(HeaderSet *headers, + const uint8_t *data, + unsigned int len, + unsigned int *bytes_used); + + void ResetHeaderField() { + m_last_header_valid = false; + } + private: + LLRPHeader m_last_header; + bool m_last_header_valid; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_LLRPINFLATOR_H_ diff --git a/libs/acn/LLRPInflatorTest.cpp b/libs/acn/LLRPInflatorTest.cpp new file mode 100644 index 0000000000..b36c5cdc05 --- /dev/null +++ b/libs/acn/LLRPInflatorTest.cpp @@ -0,0 +1,126 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPInflatorTest.cpp + * Test fixture for the LLRPInflator class + * Copyright (C) 2020 Peter Newman + */ + +#include + +#include "ola/Logging.h" +#include "ola/network/NetworkUtils.h" +#include "libs/acn/HeaderSet.h" +#include "libs/acn/PDUTestCommon.h" +#include "libs/acn/LLRPInflator.h" +#include "libs/acn/LLRPPDU.h" +#include "ola/testing/TestUtils.h" + + +namespace ola { +namespace acn { + +using ola::network::HostToNetwork; + +class LLRPInflatorTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(LLRPInflatorTest); + CPPUNIT_TEST(testDecodeHeader); + CPPUNIT_TEST(testInflatePDU); + CPPUNIT_TEST_SUITE_END(); + + public: + void testDecodeHeader(); + void testInflatePDU(); + private: + static const uint8_t TEST_DATA[]; + static const uint8_t TEST_DATA2[]; +}; + +const uint8_t LLRPInflatorTest::TEST_DATA[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15}; +const uint8_t LLRPInflatorTest::TEST_DATA2[] = {10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, + 25}; +CPPUNIT_TEST_SUITE_REGISTRATION(LLRPInflatorTest); + + +/* + * Check that we can decode headers properly + */ +void LLRPInflatorTest::testDecodeHeader() { + LLRPHeader::llrp_pdu_header header; + memset(&header, 0, sizeof(header)); + LLRPInflator inflator; + HeaderSet header_set, header_set2; + unsigned int bytes_used; + const ola::acn::CID destination_cid = CID::FromData(TEST_DATA); + + destination_cid.Pack(header.destination_cid); + header.transaction_number = HostToNetwork(72650u); + + OLA_ASSERT(inflator.DecodeHeader(&header_set, + reinterpret_cast(&header), + sizeof(header), + &bytes_used)); + OLA_ASSERT_EQ((unsigned int) sizeof(header), bytes_used); + LLRPHeader decoded_header = header_set.GetLLRPHeader(); + OLA_ASSERT(destination_cid == decoded_header.DestinationCid()); + OLA_ASSERT_EQ((uint32_t) 72650, decoded_header.TransactionNumber()); + + // try an undersized header + OLA_ASSERT_FALSE(inflator.DecodeHeader( + &header_set, + reinterpret_cast(&header), + static_cast(sizeof(header) - 1), + &bytes_used)); + OLA_ASSERT_EQ((unsigned int) 0, bytes_used); + + // test inheriting the header from the prev call + OLA_ASSERT(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); + OLA_ASSERT_EQ((unsigned int) 0, bytes_used); + decoded_header = header_set2.GetLLRPHeader(); + OLA_ASSERT(destination_cid == decoded_header.DestinationCid()); + OLA_ASSERT_EQ((uint32_t) 72650, decoded_header.TransactionNumber()); + + inflator.ResetHeaderField(); + OLA_ASSERT_FALSE(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); + OLA_ASSERT_EQ((unsigned int) 0, bytes_used); +} + + +/* + * Check that we can inflate a LLRP PDU that contains other PDUs + */ +void LLRPInflatorTest::testInflatePDU() { + const ola::acn::CID destination_cid = CID::FromData(TEST_DATA2); + LLRPHeader header(destination_cid, 2370); + // TODO(Peter): pass a different type of msg here as well + LLRPPDU pdu(3, header, NULL); + OLA_ASSERT_EQ((unsigned int) 26, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ((unsigned int) size, bytes_used); + + LLRPInflator inflator; + HeaderSet header_set; + OLA_ASSERT(inflator.InflatePDUBlock(&header_set, data, size)); + OLA_ASSERT(header == header_set.GetLLRPHeader()); + delete[] data; +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/LLRPPDU.cpp b/libs/acn/LLRPPDU.cpp new file mode 100644 index 0000000000..5d8eba531d --- /dev/null +++ b/libs/acn/LLRPPDU.cpp @@ -0,0 +1,117 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPPDU.cpp + * The LLRPPDU + * Copyright (C) 2020 Peter Newman + */ + + +#include "ola/Logging.h" +#include "ola/base/Array.h" +#include "ola/network/NetworkUtils.h" +#include "libs/acn/LLRPPDU.h" + +namespace ola { +namespace acn { + +using ola::io::OutputStream; +using ola::network::HostToNetwork; + +/* + * Size of the header portion. + */ +unsigned int LLRPPDU::HeaderSize() const { + return sizeof(LLRPHeader::llrp_pdu_header); +} + + +/* + * Size of the data portion + */ +unsigned int LLRPPDU::DataSize() const { + return m_pdu ? m_pdu->Size() : 0; +} + + +/* + * Pack the header portion. + */ +bool LLRPPDU::PackHeader(uint8_t *data, unsigned int *length) const { + unsigned int header_size = HeaderSize(); + + if (*length < header_size) { + OLA_WARN << "LLRPPDU::PackHeader: buffer too small, got " << *length + << " required " << header_size; + *length = 0; + return false; + } + + LLRPHeader::llrp_pdu_header header; + m_header.DestinationCid().Pack(header.destination_cid); + header.transaction_number = HostToNetwork(m_header.TransactionNumber()); + *length = sizeof(LLRPHeader::llrp_pdu_header); + memcpy(data, &header, *length); + return true; +} + + +/* + * Pack the data portion. + */ +bool LLRPPDU::PackData(uint8_t *data, unsigned int *length) const { + if (m_pdu) + return m_pdu->Pack(data, length); + *length = 0; + return true; +} + + +/* + * Pack the header into a buffer. + */ +void LLRPPDU::PackHeader(OutputStream *stream) const { + LLRPHeader::llrp_pdu_header header; + m_header.DestinationCid().Pack(header.destination_cid); + header.transaction_number = HostToNetwork(m_header.TransactionNumber()); + stream->Write(reinterpret_cast(&header), + sizeof(LLRPHeader::llrp_pdu_header)); +} + + +/* + * Pack the data into a buffer + */ +void LLRPPDU::PackData(OutputStream *stream) const { + if (m_pdu) + m_pdu->Write(stream); +} + + +void LLRPPDU::PrependPDU(ola::io::IOStack *stack, uint32_t vector, + const ola::acn::CID &destination_cid, uint32_t transaction_number) { + LLRPHeader::llrp_pdu_header header; + destination_cid.Pack(header.destination_cid); + header.transaction_number = HostToNetwork(transaction_number); + stack->Write(reinterpret_cast(&header), + sizeof(LLRPHeader::llrp_pdu_header)); + + vector = HostToNetwork(vector); + stack->Write(reinterpret_cast(&vector), sizeof(vector)); + // Flags for LLRP should always be 0xF0 + PrependFlagsAndLength(stack, 0xf0); +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/LLRPPDU.h b/libs/acn/LLRPPDU.h new file mode 100644 index 0000000000..76ccdc7d65 --- /dev/null +++ b/libs/acn/LLRPPDU.h @@ -0,0 +1,62 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPPDU.h + * Interface for the LLRPPDU class + * Copyright (C) 2020 Peter Newman + */ + +#ifndef LIBS_ACN_LLRPPDU_H_ +#define LIBS_ACN_LLRPPDU_H_ + +#include +#include + +#include "libs/acn/PDU.h" +#include "libs/acn/LLRPHeader.h" + +namespace ola { +namespace acn { + +class RDMPDU; + +class LLRPPDU: public PDU { + public: + LLRPPDU(unsigned int vector, + const LLRPHeader &header, + const PDU *pdu): + PDU(vector), + m_header(header), + m_pdu(pdu) {} + ~LLRPPDU() {} + + unsigned int HeaderSize() const; + unsigned int DataSize() const; + bool PackHeader(uint8_t *data, unsigned int *length) const; + bool PackData(uint8_t *data, unsigned int *length) const; + + void PackHeader(ola::io::OutputStream *stream) const; + void PackData(ola::io::OutputStream *stream) const; + + static void PrependPDU(ola::io::IOStack *stack, uint32_t vector, + const ola::acn::CID &destination_cid, uint32_t transaction_number); + + private: + LLRPHeader m_header; + const PDU *m_pdu; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_LLRPPDU_H_ diff --git a/libs/acn/LLRPPDUTest.cpp b/libs/acn/LLRPPDUTest.cpp new file mode 100644 index 0000000000..b924d8a422 --- /dev/null +++ b/libs/acn/LLRPPDUTest.cpp @@ -0,0 +1,147 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPPDUTest.cpp + * Test fixture for the LLRPPDU class + * Copyright (C) 2020 Peter Newman + */ + +#include + +#include "ola/Logging.h" +#include "ola/io/IOQueue.h" +#include "ola/io/OutputStream.h" +#include "ola/network/NetworkUtils.h" +#include "ola/testing/TestUtils.h" +#include "libs/acn/LLRPPDU.h" +#include "libs/acn/PDUTestCommon.h" + + +namespace ola { +namespace acn { + +using ola::io::IOQueue; +using ola::io::OutputStream; +using ola::network::HostToNetwork; +using std::string; + +class LLRPPDUTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(LLRPPDUTest); + CPPUNIT_TEST(testSimpleLLRPPDU); + CPPUNIT_TEST(testSimpleLLRPPDUToOutputStream); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSimpleLLRPPDU(); + void testSimpleLLRPPDUToOutputStream(); + + void setUp() { + ola::InitLogging(ola::OLA_LOG_DEBUG, ola::OLA_LOG_STDERR); + } + + private: + static const unsigned int TEST_VECTOR; + static const uint8_t TEST_DATA[]; +}; + +const uint8_t LLRPPDUTest::TEST_DATA[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15}; + +CPPUNIT_TEST_SUITE_REGISTRATION(LLRPPDUTest); + +const unsigned int LLRPPDUTest::TEST_VECTOR = 39; + + +/* + * Test that packing a LLRPPDU without data works. + */ +void LLRPPDUTest::testSimpleLLRPPDU() { + const CID destination_cid = CID::FromData(TEST_DATA); + LLRPHeader header(destination_cid, 101); + LLRPPDU pdu(TEST_VECTOR, header, NULL); + + OLA_ASSERT_EQ(20u, pdu.HeaderSize()); + OLA_ASSERT_EQ(0u, pdu.DataSize()); + OLA_ASSERT_EQ(26u, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + + // spot check the data + OLA_ASSERT_EQ((uint8_t) 0x70, data[0]); + OLA_ASSERT_EQ((uint8_t) bytes_used, data[1]); + unsigned int actual_value; + memcpy(&actual_value, data + 2, sizeof(actual_value)); + OLA_ASSERT_EQ(HostToNetwork(TEST_VECTOR), actual_value); + + uint8_t buffer[CID::CID_LENGTH]; + destination_cid.Pack(buffer); + OLA_ASSERT_FALSE(memcmp(&data[6], buffer, CID::CID_LENGTH)); + // transaction number + OLA_ASSERT_EQ((uint8_t) 0, data[6 + CID::CID_LENGTH]); + OLA_ASSERT_EQ((uint8_t) 0, data[6 + CID::CID_LENGTH + 1]); + OLA_ASSERT_EQ((uint8_t) 0, data[6 + CID::CID_LENGTH + 2]); + OLA_ASSERT_EQ((uint8_t) 101, data[6 + CID::CID_LENGTH + 3]); + + // test undersized buffer + bytes_used = size - 1; + OLA_ASSERT_FALSE(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(0u, bytes_used); + + // test oversized buffer + bytes_used = size + 1; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + delete[] data; +} + + +/* + * Test that writing to an output stream works. + */ +void LLRPPDUTest::testSimpleLLRPPDUToOutputStream() { + const ola::acn::CID destination_cid = CID::FromData(TEST_DATA); + LLRPHeader header(destination_cid, 101); + LLRPPDU pdu(TEST_VECTOR, header, NULL); + + OLA_ASSERT_EQ(20u, pdu.HeaderSize()); + OLA_ASSERT_EQ(0u, pdu.DataSize()); + OLA_ASSERT_EQ(26u, pdu.Size()); + + IOQueue output; + OutputStream stream(&output); + pdu.Write(&stream); + OLA_ASSERT_EQ(26u, output.Size()); + + uint8_t *pdu_data = new uint8_t[output.Size()]; + unsigned int pdu_size = output.Peek(pdu_data, output.Size()); + OLA_ASSERT_EQ(output.Size(), pdu_size); + + uint8_t EXPECTED[] = { + 0xf0, 0x1a, + 0, 0, 0, 39, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 0, 0, 0, 101, // transaction number + }; + OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), pdu_data, pdu_size); + output.Pop(output.Size()); + delete[] pdu_data; +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index 57bcf5276e..42d91ea17d 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -61,6 +61,11 @@ libs_acn_libolae131core_la_SOURCES = \ libs/acn/E133StatusPDU.cpp \ libs/acn/E133StatusPDU.h \ libs/acn/HeaderSet.h \ + libs/acn/LLRPHeader.h \ + libs/acn/LLRPInflator.cpp \ + libs/acn/LLRPInflator.h \ + libs/acn/LLRPPDU.cpp \ + libs/acn/LLRPPDU.h \ libs/acn/PDU.cpp \ libs/acn/PDU.h \ libs/acn/PDUTestCommon.h \ @@ -108,6 +113,7 @@ libs_acn_e131_loadtest_LDADD = libs/acn/libolae131core.la test_programs += \ libs/acn/E131Tester \ libs/acn/E133Tester \ + libs/acn/LLRPTester \ libs/acn/TransportTester libs_acn_E131Tester_SOURCES = \ @@ -140,6 +146,14 @@ libs_acn_E133Tester_LDADD = \ libs/acn/libolae131core.la \ $(COMMON_TESTING_LIBS) +libs_acn_LLRPTester_SOURCES = \ + libs/acn/LLRPInflatorTest.cpp \ + libs/acn/LLRPPDUTest.cpp +libs_acn_LLRPTester_CPPFLAGS = $(COMMON_TESTING_FLAGS) +libs_acn_LLRPTester_LDADD = \ + libs/acn/libolae131core.la \ + $(COMMON_TESTING_LIBS) + libs_acn_TransportTester_SOURCES = \ libs/acn/TCPTransportTest.cpp \ libs/acn/UDPTransportTest.cpp From 8524079996d758de6f5f323d897b8a78f523be23 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 3 Feb 2020 01:56:25 +0000 Subject: [PATCH 002/138] Fix a Doxygen typo --- include/ola/acn/ACNVectors.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ola/acn/ACNVectors.h b/include/ola/acn/ACNVectors.h index 028c0e264b..8523ff2313 100644 --- a/include/ola/acn/ACNVectors.h +++ b/include/ola/acn/ACNVectors.h @@ -64,7 +64,7 @@ enum DMPVector { * @brief Vectors used at the E1.31 layer. */ enum E131Vector { - VECTOR_E131_DATA = 2, /**< DMP data (DATA_PACKET_VECTOR( */ + VECTOR_E131_DATA = 2, /**< DMP data (DATA_PACKET_VECTOR) */ VECTOR_E131_SYNC = 3, /**< Sync data (SYNC_PACKET_VECTOR) */ VECTOR_E131_DISCOVERY = 4, /**< Discovery data (DISCOVERY_PACKET_VECTOR) */ }; From 674ea511416bb3a8d955a1755d5251db6c53deeb Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 3 Feb 2020 14:30:00 +0000 Subject: [PATCH 003/138] Update some E1.33 Vectors --- include/ola/acn/ACNVectors.h | 11 ++++++++++- libs/acn/E133Inflator.h | 2 +- tools/e133/MessageBuilder.cpp | 4 ++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/include/ola/acn/ACNVectors.h b/include/ola/acn/ACNVectors.h index 8523ff2313..db99ff2bb8 100644 --- a/include/ola/acn/ACNVectors.h +++ b/include/ola/acn/ACNVectors.h @@ -45,7 +45,7 @@ namespace acn { enum RootVector { VECTOR_ROOT_E131_REV2 = 3, /**< Draft E1.31, used by some old gear. */ VECTOR_ROOT_E131 = 4, /**< E1.31 (sACN) */ - VECTOR_ROOT_E133 = 5, /**< E1.33 (RDNNet) */ + VECTOR_ROOT_RPT = 5, /**< E1.33 (RPT) */ VECTOR_ROOT_NULL = 6, /**< NULL (empty) root */ VECTOR_ROOT_BROKER = 9, /**< E1.33 (Broker) */ VECTOR_ROOT_LLRP = 0x0A, /**< E1.33 (LLRP) */ @@ -89,6 +89,15 @@ enum E133ControllerVector { VECTOR_CONTROLLER_DEVICE_RELEASED = 4, /**< Device released message */ VECTOR_CONTROLLER_EXPECT_MASTER = 5, /**< Expect master message */ }; + +/** + * @brief Vectors used at the E1.33 LLRP layer. + */ +enum LLRPVector { + VECTOR_LLRP_PROBE_REQUEST = 1, /**< LLRP Probe Request */ + VECTOR_LLRP_PROBE_REPLY = 1, /**< LLRP Probe Reply */ + VECTOR_LLRP_RDM_CMD = 1, /**< LLRP RDM Command */ +}; } // namespace acn } // namespace ola diff --git a/libs/acn/E133Inflator.h b/libs/acn/E133Inflator.h index ee7c968f66..d2f57daf66 100644 --- a/libs/acn/E133Inflator.h +++ b/libs/acn/E133Inflator.h @@ -38,7 +38,7 @@ class E133Inflator: public BaseInflator { } ~E133Inflator() {} - uint32_t Id() const { return ola::acn::VECTOR_ROOT_E133; } + uint32_t Id() const { return ola::acn::VECTOR_ROOT_RPT; } protected: bool DecodeHeader(HeaderSet *headers, diff --git a/tools/e133/MessageBuilder.cpp b/tools/e133/MessageBuilder.cpp index d2c6a5143a..a192b45bf0 100644 --- a/tools/e133/MessageBuilder.cpp +++ b/tools/e133/MessageBuilder.cpp @@ -109,7 +109,7 @@ void MessageBuilder::BuildTCPRootE133(IOStack *packet, uint16_t endpoint_id) { E133PDU::PrependPDU(packet, vector, m_source_name, sequence_number, endpoint_id); - RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_E133, m_cid); + RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_RPT, m_cid); PreamblePacker::AddTCPPreamble(packet); } @@ -123,7 +123,7 @@ void MessageBuilder::BuildUDPRootE133(IOStack *packet, uint16_t endpoint_id) { E133PDU::PrependPDU(packet, vector, m_source_name, sequence_number, endpoint_id); - RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_E133, m_cid); + RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_RPT, m_cid); PreamblePacker::AddUDPPreamble(packet); } } // namespace e133 From bd619c2b597cdccaf9df2dbeb2eedeadcba5c0a3 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 4 Feb 2020 00:07:24 +0000 Subject: [PATCH 004/138] Add the ability to pack UIDSets --- common/rdm/UIDTest.cpp | 15 +++++++++++++-- include/ola/rdm/UIDSet.h | 21 ++++++++++++++++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/common/rdm/UIDTest.cpp b/common/rdm/UIDTest.cpp index 9a09da67a9..e02dfd0751 100644 --- a/common/rdm/UIDTest.cpp +++ b/common/rdm/UIDTest.cpp @@ -105,13 +105,13 @@ void UIDTest::testUID() { OLA_ASSERT_TRUE(uid.Pack(buffer, buffer_size)); uint8_t expected[] = {0, 1, 0, 0, 0, 2}; - OLA_ASSERT_EQ(0, memcmp(expected, buffer, buffer_size)); + OLA_ASSERT_DATA_EQUALS(expected, sizeof(expected), buffer, buffer_size); UID unpacked_uid1(buffer); OLA_ASSERT_EQ(uid, unpacked_uid1); OLA_ASSERT_TRUE(uid3.Pack(buffer, buffer_size)); uint8_t expected2[] = {0, 2, 0, 0, 0, 0x0a}; - OLA_ASSERT_EQ(0, memcmp(expected2, buffer, buffer_size)); + OLA_ASSERT_DATA_EQUALS(expected2, sizeof(expected2), buffer, buffer_size); UID unpacked_uid2(buffer); OLA_ASSERT_EQ(uid3, unpacked_uid2); @@ -234,6 +234,17 @@ void UIDTest::testUIDSet() { difference = set3.SetDifference(set1); OLA_ASSERT_EQ(0u, difference.Size()); + + // now test the packing & unpacking + UID uid3(3, 4); + UIDSet set4(set1); + set4.AddUID(uid3); + unsigned int buffer_size = UID::UID_SIZE * 3; + uint8_t *buffer = new uint8_t[buffer_size]; + OLA_ASSERT_TRUE(set4.Pack(buffer, buffer_size)); + + uint8_t expected[] = {0, 1, 0, 0, 0, 2, 0, 2, 0, 0, 0, 10, 0, 3, 0, 0, 0, 4}; + OLA_ASSERT_DATA_EQUALS(expected, sizeof(expected), buffer, buffer_size); } diff --git a/include/ola/rdm/UIDSet.h b/include/ola/rdm/UIDSet.h index 88b43df66d..a60105b980 100644 --- a/include/ola/rdm/UIDSet.h +++ b/include/ola/rdm/UIDSet.h @@ -87,7 +87,7 @@ class UIDSet { * @return the number of UIDs in the set. */ unsigned int Size() const { - return m_uids.size(); + return static_cast(m_uids.size()); } /** @@ -207,6 +207,25 @@ class UIDSet { return out << uid_set.ToString(); } + /** + * @brief Write the binary representation of the UID to memory. + * @param buffer a pointer to memory to write the UID to + * @param length the size of the memory block, should be at least UID_SIZE. + * @returns true if length was >= UID_SIZE, false otherwise. + */ + bool Pack(uint8_t *buffer, unsigned int length) const { + if (static_cast(length) < (m_uids.size() * UID::UID_SIZE)) { + return false; + } + uint8_t *ptr = buffer; + std::set::const_iterator iter; + for (iter = m_uids.begin(); iter != m_uids.end(); ++iter) { + iter->Pack(ptr, UID::UID_SIZE); + ptr += UID::UID_SIZE; + } + return true; + } + private: std::set m_uids; From a89f3dba7d7d9251a6100c73648edae94e03b443 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 4 Feb 2020 00:08:55 +0000 Subject: [PATCH 005/138] Fix the Doxygen --- include/ola/rdm/UIDSet.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/ola/rdm/UIDSet.h b/include/ola/rdm/UIDSet.h index a60105b980..40ad0a0547 100644 --- a/include/ola/rdm/UIDSet.h +++ b/include/ola/rdm/UIDSet.h @@ -208,10 +208,11 @@ class UIDSet { } /** - * @brief Write the binary representation of the UID to memory. - * @param buffer a pointer to memory to write the UID to - * @param length the size of the memory block, should be at least UID_SIZE. - * @returns true if length was >= UID_SIZE, false otherwise. + * @brief Write the binary representation of the UID set to memory. + * @param buffer a pointer to memory to write the UID set to + * @param length the size of the memory block, should be at least UID_SIZE + * * set size. + * @returns true if length was >= UID_SIZE * set size, false otherwise. */ bool Pack(uint8_t *buffer, unsigned int length) const { if (static_cast(length) < (m_uids.size() * UID::UID_SIZE)) { From 063de3d6bf8dddba2dec06067a3c24df8c141ace Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 4 Feb 2020 00:09:27 +0000 Subject: [PATCH 006/138] Fix a Doxygen typo --- include/ola/acn/CID.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ola/acn/CID.h b/include/ola/acn/CID.h index 9114f2b468..91c403a5f4 100644 --- a/include/ola/acn/CID.h +++ b/include/ola/acn/CID.h @@ -15,7 +15,7 @@ * * CID.h * The CID class, this just wraps a CIDImpl so we don't need to include all the - * UID headers. + * UUID headers. * Copyright (C) 2007 Simon Newton */ From 0204d595c8f2753e0581d8bb88020a12dddc9ea1 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 4 Feb 2020 00:14:24 +0000 Subject: [PATCH 007/138] Add the initial LLRPProbeRequestPDU --- include/ola/acn/ACNPort.h | 5 ++ libs/acn/LLRPHeader.h | 2 + libs/acn/LLRPPDU.h | 2 - libs/acn/LLRPProbeRequestPDU.cpp | 62 ++++++++++++++++++++ libs/acn/LLRPProbeRequestPDU.h | 62 ++++++++++++++++++++ libs/acn/LLRPProbeRequestPDUTest.cpp | 85 ++++++++++++++++++++++++++++ libs/acn/Makefile.mk | 5 +- 7 files changed, 220 insertions(+), 3 deletions(-) create mode 100644 libs/acn/LLRPProbeRequestPDU.cpp create mode 100644 libs/acn/LLRPProbeRequestPDU.h create mode 100644 libs/acn/LLRPProbeRequestPDUTest.cpp diff --git a/include/ola/acn/ACNPort.h b/include/ola/acn/ACNPort.h index bef7619c38..97f98a1ab2 100644 --- a/include/ola/acn/ACNPort.h +++ b/include/ola/acn/ACNPort.h @@ -61,6 +61,11 @@ const uint16_t ACN_PORT = 5568; */ const uint16_t E133_PORT = 5569; +/** + * @brief The port used for E1.33 LLRP communication. + */ +const uint16_t LLRP_PORT = 5569; + /** * @} */ diff --git a/libs/acn/LLRPHeader.h b/libs/acn/LLRPHeader.h index 1d964268fd..40a5098c42 100644 --- a/libs/acn/LLRPHeader.h +++ b/libs/acn/LLRPHeader.h @@ -29,6 +29,8 @@ namespace ola { namespace acn { +// TODO(Peter): I think technically this probably shouldn't be a header and +// instead is just data at this level! /* * Header for the LLRP layer */ diff --git a/libs/acn/LLRPPDU.h b/libs/acn/LLRPPDU.h index 76ccdc7d65..67ccf7af58 100644 --- a/libs/acn/LLRPPDU.h +++ b/libs/acn/LLRPPDU.h @@ -30,8 +30,6 @@ namespace ola { namespace acn { -class RDMPDU; - class LLRPPDU: public PDU { public: LLRPPDU(unsigned int vector, diff --git a/libs/acn/LLRPProbeRequestPDU.cpp b/libs/acn/LLRPProbeRequestPDU.cpp new file mode 100644 index 0000000000..6fe5378081 --- /dev/null +++ b/libs/acn/LLRPProbeRequestPDU.cpp @@ -0,0 +1,62 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPProbeRequestPDU.cpp + * The LLRPProbeRequestPDU + * Copyright (C) 2020 Peter Newman + */ + +#include "libs/acn/LLRPProbeRequestPDU.h" + +#include +#include +#include + +namespace ola { +namespace acn { + +using ola::io::OutputStream; +using ola::network::HostToNetwork; +using ola::rdm::UID; +using std::vector; + +void LLRPProbeRequestPDU::PrependPDU(ola::io::IOStack *stack, + const UID &lower_uid, + const UID &upper_uid, + bool client_tcp_connection_inactive, + bool brokers_only, + const ola::rdm::UIDSet &known_uids) { + llrp_probe_request_pdu_data data; + lower_uid.Pack(data.lower_uid, sizeof(data.lower_uid)); + upper_uid.Pack(data.upper_uid, sizeof(data.upper_uid)); + uint16_t filter = 0; + if (client_tcp_connection_inactive) { + filter |= FILTER_CLIENT_TCP_CONNECTION_INACTIVE; + } + if (brokers_only) { + filter |= FILTER_BROKERS_ONLY; + } + data.filter = HostToNetwork(filter); + known_uids.Pack(data.known_uids, sizeof(data.known_uids)); + stack->Write(reinterpret_cast(&data), + static_cast(sizeof(llrp_probe_request_pdu_data) - + sizeof(data.known_uids) + + (known_uids.Size() * UID::LENGTH))); + uint8_t vector = HostToNetwork(VECTOR_PROBE_REQUEST_DATA); + stack->Write(reinterpret_cast(&vector), sizeof(vector)); + PrependFlagsAndLength(stack); +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/LLRPProbeRequestPDU.h b/libs/acn/LLRPProbeRequestPDU.h new file mode 100644 index 0000000000..34e5ac79e0 --- /dev/null +++ b/libs/acn/LLRPProbeRequestPDU.h @@ -0,0 +1,62 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPProbeRequestPDU.h + * The LLRPProbeRequestPDU class + * Copyright (C) 2020 Peter Newman + */ + +#ifndef LIBS_ACN_LLRPPROBEREQUESTPDU_H_ +#define LIBS_ACN_LLRPPROBEREQUESTPDU_H_ + +#include +#include +#include + +#include "libs/acn/PDU.h" + +namespace ola { +namespace acn { + +class LLRPProbeRequestPDU : private PDU { + public: + static void PrependPDU(ola::io::IOStack *stack, + const ola::rdm::UID &lower_uid, + const ola::rdm::UID &upper_uid, + bool client_tcp_connection_inactive, + bool brokers_only, + const ola::rdm::UIDSet &known_uids); + + static const uint8_t VECTOR_PROBE_REQUEST_DATA = 0x01; + + static const unsigned int LLRP_KNOWN_UID_SIZE = 200; + + // bit masks for filter + static const uint16_t FILTER_CLIENT_TCP_CONNECTION_INACTIVE = 0x0001; + static const uint16_t FILTER_BROKERS_ONLY = 0x0002; + + private: + PACK( + struct llrp_probe_request_pdu_data_s { + uint8_t lower_uid[ola::rdm::UID::LENGTH]; + uint8_t upper_uid[ola::rdm::UID::LENGTH]; + uint16_t filter; + uint8_t known_uids[ola::rdm::UID::LENGTH * LLRP_KNOWN_UID_SIZE]; + }); + typedef struct llrp_probe_request_pdu_data_s llrp_probe_request_pdu_data; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_LLRPProbeRequestPDU_H_ diff --git a/libs/acn/LLRPProbeRequestPDUTest.cpp b/libs/acn/LLRPProbeRequestPDUTest.cpp new file mode 100644 index 0000000000..ca6596991c --- /dev/null +++ b/libs/acn/LLRPProbeRequestPDUTest.cpp @@ -0,0 +1,85 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPProbeRequestPDUTest.cpp + * Test fixture for the LLRPProbeRequestPDU class + * Copyright (C) 2020 Peter Newman + */ + +#include +#include +#include + +#include "ola/Logging.h" +#include "ola/io/IOStack.h" +#include "ola/network/NetworkUtils.h" +#include "ola/rdm/UID.h" +#include "ola/rdm/UIDSet.h" +#include "ola/testing/TestUtils.h" +#include "libs/acn/PDUTestCommon.h" +#include "libs/acn/LLRPProbeRequestPDU.h" + +namespace ola { +namespace acn { + +using ola::io::IOStack; +using ola::rdm::UID; +using ola::rdm::UIDSet; + +class LLRPProbeRequestPDUTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(LLRPProbeRequestPDUTest); + CPPUNIT_TEST(testPrepend); + CPPUNIT_TEST_SUITE_END(); + + public: + void testPrepend(); + + private: + static const unsigned int TEST_VECTOR; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(LLRPProbeRequestPDUTest); + +void LLRPProbeRequestPDUTest::testPrepend() { + IOStack stack; + UIDSet known_uids; + known_uids.AddUID(UID(0x1234, 0x00000001)); + known_uids.AddUID(UID(0x5678, 0x00000002)); + known_uids.AddUID(UID(0x4321, 0x12345678)); + LLRPProbeRequestPDU::PrependPDU(&stack, + UID(0x0000, 0x00000000), + UID(0xffff, 0xffffffff), + false, + false, + known_uids); + + unsigned int length = stack.Size(); + uint8_t *buffer = new uint8_t[length]; + OLA_ASSERT(stack.Read(buffer, length)); + + const uint8_t expected_data[] = { + 0xf0, 0x23, 1, + 0, 0, 0, 0, 0, 0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, + 0x12, 0x34, 0, 0, 0, 1, + 0x43, 0x21, 0x12, 0x34, 0x56, 0x78, + 0x56, 0x78, 0, 0, 0, 2, + }; + OLA_ASSERT_DATA_EQUALS(expected_data, sizeof(expected_data), buffer, length); + delete[] buffer; +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index 42d91ea17d..3402e80be6 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -64,6 +64,8 @@ libs_acn_libolae131core_la_SOURCES = \ libs/acn/LLRPHeader.h \ libs/acn/LLRPInflator.cpp \ libs/acn/LLRPInflator.h \ + libs/acn/LLRPProbeRequestPDU.cpp \ + libs/acn/LLRPProbeRequestPDU.h \ libs/acn/LLRPPDU.cpp \ libs/acn/LLRPPDU.h \ libs/acn/PDU.cpp \ @@ -148,7 +150,8 @@ libs_acn_E133Tester_LDADD = \ libs_acn_LLRPTester_SOURCES = \ libs/acn/LLRPInflatorTest.cpp \ - libs/acn/LLRPPDUTest.cpp + libs/acn/LLRPPDUTest.cpp \ + libs/acn/LLRPProbeRequestPDUTest.cpp libs_acn_LLRPTester_CPPFLAGS = $(COMMON_TESTING_FLAGS) libs_acn_LLRPTester_LDADD = \ libs/acn/libolae131core.la \ From f1cc481d6d900de8db5a64334fe7419b41bfffa4 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 4 Feb 2020 13:39:23 +0000 Subject: [PATCH 008/138] Tidy some Doxygen --- include/ola/acn/ACNVectors.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/ola/acn/ACNVectors.h b/include/ola/acn/ACNVectors.h index db99ff2bb8..fc08d266ff 100644 --- a/include/ola/acn/ACNVectors.h +++ b/include/ola/acn/ACNVectors.h @@ -98,10 +98,11 @@ enum LLRPVector { VECTOR_LLRP_PROBE_REPLY = 1, /**< LLRP Probe Reply */ VECTOR_LLRP_RDM_CMD = 1, /**< LLRP RDM Command */ }; -} // namespace acn -} // namespace ola /** * @} */ +} // namespace acn +} // namespace ola + #endif // INCLUDE_OLA_ACN_ACNVECTORS_H_ From 27c1cb51d84857b4e4da352e11f8af703ad4857e Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 4 Feb 2020 14:03:25 +0000 Subject: [PATCH 009/138] Add the ability to easily write a CID to an ostream --- include/ola/acn/CID.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/ola/acn/CID.h b/include/ola/acn/CID.h index 91c403a5f4..3b98d127d7 100644 --- a/include/ola/acn/CID.h +++ b/include/ola/acn/CID.h @@ -89,6 +89,15 @@ class CID { */ std::string ToString() const; + /** + * @brief A helper function to write a CID to an ostream. + * @param out the ostream + * @param cid the CID to write. + */ + friend std::ostream& operator<< (std::ostream &out, const CID &cid) { + return out << cid.ToString(); + } + /** * @brief Write the CID to an OutputBufferInterface */ From e9dd3742f9310c0a72bccacfc45cfb9bacf115aa Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 4 Feb 2020 15:35:15 +0000 Subject: [PATCH 010/138] Add LLRP Probe Request PDU, fix the length flags bug --- include/ola/acn/ACNFlags.h | 70 ++++++++++++++++++++++++++++ include/ola/acn/Makefile.mk | 1 + libs/acn/BaseInflator.cpp | 4 +- libs/acn/BaseInflator.h | 7 ++- libs/acn/BaseInflatorTest.cpp | 18 +++---- libs/acn/LLRPInflatorTest.cpp | 2 +- libs/acn/LLRPPDU.cpp | 3 +- libs/acn/LLRPPDU.h | 8 ++-- libs/acn/LLRPPDUTest.cpp | 25 +++++----- libs/acn/LLRPProbeRequestPDU.cpp | 2 +- libs/acn/LLRPProbeRequestPDUTest.cpp | 2 +- libs/acn/PDU.cpp | 32 ++++++++++--- libs/acn/PDU.h | 37 +++++++++++---- 13 files changed, 161 insertions(+), 50 deletions(-) create mode 100644 include/ola/acn/ACNFlags.h diff --git a/include/ola/acn/ACNFlags.h b/include/ola/acn/ACNFlags.h new file mode 100644 index 0000000000..a055a429b0 --- /dev/null +++ b/include/ola/acn/ACNFlags.h @@ -0,0 +1,70 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ACNFlags.h + * Flags used in ACN PDUs + * Copyright (C) 2020 Peter Newman + */ + +#ifndef INCLUDE_OLA_ACN_ACNFLAGS_H_ +#define INCLUDE_OLA_ACN_ACNFLAGS_H_ + +/** + * @addtogroup acn + * @{ + * @file ACNFlags.h + * @brief ACN flag values. + * @} + */ + +#include + +namespace ola { +namespace acn { + +/** + * @addtogroup acn + * @{ + */ + +// masks for the flag fields +/** + * @brief This indicates a 20 bit length field (default is 12 bits) + */ +static const uint8_t LFLAG_MASK = 0x80; + +/** + * @brief This indicates a vector is present + */ +static const uint8_t VFLAG_MASK = 0x40; + +/** + * @brief This indicates a header field is present + */ +static const uint8_t HFLAG_MASK = 0x20; + +/** + * @brief This indicates a data field is present + */ +static const uint8_t DFLAG_MASK = 0x10; + +/** + * @} + */ + +} // namespace acn +} // namespace ola + +#endif // INCLUDE_OLA_ACN_ACNFLAGS_H_ diff --git a/include/ola/acn/Makefile.mk b/include/ola/acn/Makefile.mk index 56bc647eb5..afd628d812 100644 --- a/include/ola/acn/Makefile.mk +++ b/include/ola/acn/Makefile.mk @@ -3,6 +3,7 @@ olaacninclude_HEADERS = if INSTALL_ACN olaacninclude_HEADERS += \ + include/ola/acn/ACNFlags.h \ include/ola/acn/ACNPort.h \ include/ola/acn/ACNVectors.h \ include/ola/acn/CID.h diff --git a/libs/acn/BaseInflator.cpp b/libs/acn/BaseInflator.cpp index e3917967ad..a41dca370c 100644 --- a/libs/acn/BaseInflator.cpp +++ b/libs/acn/BaseInflator.cpp @@ -163,7 +163,7 @@ bool BaseInflator::DecodeLength(const uint8_t *data, bool BaseInflator::DecodeVector(uint8_t flags, const uint8_t *data, unsigned int length, uint32_t *vector, unsigned int *bytes_used) { - if (flags & PDU::VFLAG_MASK) { + if (flags & ola::acn::VFLAG_MASK) { if ((unsigned int) m_vector_size > length) { *vector = 0; *bytes_used = 0; @@ -223,7 +223,7 @@ bool BaseInflator::InflatePDU(HeaderSet *headers, return false; } - if (flags & PDU::HFLAG_MASK) { + if (flags & ola::acn::HFLAG_MASK) { result = DecodeHeader(headers, data + data_offset, pdu_len - data_offset, &header_bytes_used); diff --git a/libs/acn/BaseInflator.h b/libs/acn/BaseInflator.h index 384351bc28..07b7c6b88b 100644 --- a/libs/acn/BaseInflator.h +++ b/libs/acn/BaseInflator.h @@ -87,8 +87,11 @@ class BaseInflator : public InflatorInterface { unsigned int len); // masks for the flag fields - // This indicates a 20 bit length field (default is 12 bits) - static const uint8_t LFLAG_MASK = 0x80; + /** + * @brief This indicates a 20 bit length field (default is 12 bits) + * @deprecated Use ola::acn::LFLAG_MASK instead (4 Feb 2020). + */ + static const uint8_t LFLAG_MASK = ola::acn::LFLAG_MASK; // This masks the first 4 bits of the length field static const uint8_t LENGTH_MASK = 0x0F; diff --git a/libs/acn/BaseInflatorTest.cpp b/libs/acn/BaseInflatorTest.cpp index 17e86121b8..a4e0a0dd81 100644 --- a/libs/acn/BaseInflatorTest.cpp +++ b/libs/acn/BaseInflatorTest.cpp @@ -204,7 +204,7 @@ void BaseInflatorTest::testDecodeVector() { uint8_t data[] = {1, 2, 3, 4, 5, 6}; // the test data unsigned int vector = 1; unsigned int bytes_used = 0; - uint8_t flags = PDU::VFLAG_MASK; + uint8_t flags = VFLAG_MASK; OLA_ASSERT_FALSE(inflator.DecodeVector(flags, data, 0, &vector, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, vector); @@ -235,7 +235,7 @@ void BaseInflatorTest::testDecodeVector() { } // now try with a vector size of 2 - flags = PDU::VFLAG_MASK; + flags = VFLAG_MASK; TestInflator inflator2(0, PDU::TWO_BYTES); for (unsigned int i = 0; i < 2; i++) { OLA_ASSERT_FALSE( @@ -270,7 +270,7 @@ void BaseInflatorTest::testDecodeVector() { } // now try with a vector size of 4 - flags = PDU::VFLAG_MASK; + flags = VFLAG_MASK; TestInflator inflator4(0, PDU::FOUR_BYTES); for (unsigned int i = 0; i < 4; i++) { OLA_ASSERT_FALSE( @@ -297,7 +297,7 @@ void BaseInflatorTest::testDecodeVector() { void BaseInflatorTest::testInflatePDU() { TestInflator inflator; // test with a vector size of 2 HeaderSet header_set; - uint8_t flags = PDU::VFLAG_MASK; + uint8_t flags = VFLAG_MASK; unsigned int data_size = static_cast(PDU::TWO_BYTES + sizeof(PDU_DATA)); uint8_t *data = new uint8_t[data_size]; @@ -324,7 +324,7 @@ void BaseInflatorTest::testInflatePDUBlock() { length_size + PDU::TWO_BYTES + sizeof(PDU_DATA)); uint8_t *data = new uint8_t[data_size]; // setup the vector - data[0] = PDU::VFLAG_MASK; + data[0] = VFLAG_MASK; data[1] = static_cast(data_size); data[2] = 0x01; data[3] = 0x21; @@ -337,14 +337,14 @@ void BaseInflatorTest::testInflatePDUBlock() { // inflate a multi-pdu block data = new uint8_t[2 * data_size]; - data[0] = PDU::VFLAG_MASK; + data[0] = VFLAG_MASK; data[1] = static_cast(data_size); data[2] = 0x01; data[3] = 0x21; memcpy(data + length_size + PDU::TWO_BYTES, PDU_DATA, sizeof(PDU_DATA)); - data[data_size] = PDU::VFLAG_MASK; + data[data_size] = VFLAG_MASK; data[data_size + 1] = static_cast(data_size); data[data_size + 2] = 0x01; data[data_size + 3] = 0x21; @@ -362,11 +362,11 @@ void BaseInflatorTest::testInflatePDUBlock() { unsigned int pdu_size = data_size + length_size + PDU::TWO_BYTES; data = new uint8_t[pdu_size]; - data[0] = PDU::VFLAG_MASK; + data[0] = VFLAG_MASK; data[1] = static_cast(pdu_size); data[2] = 0x01; data[3] = 0x21; - data[4] = PDU::VFLAG_MASK; + data[4] = VFLAG_MASK; data[5] = static_cast(data_size); data[6] = 0x01; data[7] = 0x21; diff --git a/libs/acn/LLRPInflatorTest.cpp b/libs/acn/LLRPInflatorTest.cpp index b36c5cdc05..16bcd96431 100644 --- a/libs/acn/LLRPInflatorTest.cpp +++ b/libs/acn/LLRPInflatorTest.cpp @@ -108,7 +108,7 @@ void LLRPInflatorTest::testInflatePDU() { LLRPHeader header(destination_cid, 2370); // TODO(Peter): pass a different type of msg here as well LLRPPDU pdu(3, header, NULL); - OLA_ASSERT_EQ((unsigned int) 26, pdu.Size()); + OLA_ASSERT_EQ((unsigned int) 27, pdu.Size()); unsigned int size = pdu.Size(); uint8_t *data = new uint8_t[size]; diff --git a/libs/acn/LLRPPDU.cpp b/libs/acn/LLRPPDU.cpp index 5d8eba531d..a1654338e9 100644 --- a/libs/acn/LLRPPDU.cpp +++ b/libs/acn/LLRPPDU.cpp @@ -110,8 +110,7 @@ void LLRPPDU::PrependPDU(ola::io::IOStack *stack, uint32_t vector, vector = HostToNetwork(vector); stack->Write(reinterpret_cast(&vector), sizeof(vector)); - // Flags for LLRP should always be 0xF0 - PrependFlagsAndLength(stack, 0xf0); + PrependFlagsAndLength(stack, VFLAG_MASK | HFLAG_MASK | DFLAG_MASK, true); } } // namespace acn } // namespace ola diff --git a/libs/acn/LLRPPDU.h b/libs/acn/LLRPPDU.h index 67ccf7af58..669f5b5c06 100644 --- a/libs/acn/LLRPPDU.h +++ b/libs/acn/LLRPPDU.h @@ -35,7 +35,7 @@ class LLRPPDU: public PDU { LLRPPDU(unsigned int vector, const LLRPHeader &header, const PDU *pdu): - PDU(vector), + PDU(vector, FOUR_BYTES, true), m_header(header), m_pdu(pdu) {} ~LLRPPDU() {} @@ -48,8 +48,10 @@ class LLRPPDU: public PDU { void PackHeader(ola::io::OutputStream *stream) const; void PackData(ola::io::OutputStream *stream) const; - static void PrependPDU(ola::io::IOStack *stack, uint32_t vector, - const ola::acn::CID &destination_cid, uint32_t transaction_number); + static void PrependPDU(ola::io::IOStack *stack, + uint32_t vector, + const ola::acn::CID &destination_cid, + uint32_t transaction_number); private: LLRPHeader m_header; diff --git a/libs/acn/LLRPPDUTest.cpp b/libs/acn/LLRPPDUTest.cpp index b924d8a422..13273f60ed 100644 --- a/libs/acn/LLRPPDUTest.cpp +++ b/libs/acn/LLRPPDUTest.cpp @@ -74,7 +74,7 @@ void LLRPPDUTest::testSimpleLLRPPDU() { OLA_ASSERT_EQ(20u, pdu.HeaderSize()); OLA_ASSERT_EQ(0u, pdu.DataSize()); - OLA_ASSERT_EQ(26u, pdu.Size()); + OLA_ASSERT_EQ(27u, pdu.Size()); unsigned int size = pdu.Size(); uint8_t *data = new uint8_t[size]; @@ -83,20 +83,21 @@ void LLRPPDUTest::testSimpleLLRPPDU() { OLA_ASSERT_EQ(size, bytes_used); // spot check the data - OLA_ASSERT_EQ((uint8_t) 0x70, data[0]); - OLA_ASSERT_EQ((uint8_t) bytes_used, data[1]); + OLA_ASSERT_EQ((uint8_t) 0xf0, data[0]); + // bytes_used is technically data[1] and data[2] if > 255 + OLA_ASSERT_EQ((uint8_t) bytes_used, data[2]); unsigned int actual_value; - memcpy(&actual_value, data + 2, sizeof(actual_value)); + memcpy(&actual_value, data + 3, sizeof(actual_value)); OLA_ASSERT_EQ(HostToNetwork(TEST_VECTOR), actual_value); uint8_t buffer[CID::CID_LENGTH]; destination_cid.Pack(buffer); - OLA_ASSERT_FALSE(memcmp(&data[6], buffer, CID::CID_LENGTH)); + OLA_ASSERT_DATA_EQUALS(&data[7], CID::CID_LENGTH, buffer, sizeof(buffer)); // transaction number - OLA_ASSERT_EQ((uint8_t) 0, data[6 + CID::CID_LENGTH]); - OLA_ASSERT_EQ((uint8_t) 0, data[6 + CID::CID_LENGTH + 1]); - OLA_ASSERT_EQ((uint8_t) 0, data[6 + CID::CID_LENGTH + 2]); - OLA_ASSERT_EQ((uint8_t) 101, data[6 + CID::CID_LENGTH + 3]); + OLA_ASSERT_EQ((uint8_t) 0, data[7 + CID::CID_LENGTH]); + OLA_ASSERT_EQ((uint8_t) 0, data[7 + CID::CID_LENGTH + 1]); + OLA_ASSERT_EQ((uint8_t) 0, data[7 + CID::CID_LENGTH + 2]); + OLA_ASSERT_EQ((uint8_t) 101, data[7 + CID::CID_LENGTH + 3]); // test undersized buffer bytes_used = size - 1; @@ -121,19 +122,19 @@ void LLRPPDUTest::testSimpleLLRPPDUToOutputStream() { OLA_ASSERT_EQ(20u, pdu.HeaderSize()); OLA_ASSERT_EQ(0u, pdu.DataSize()); - OLA_ASSERT_EQ(26u, pdu.Size()); + OLA_ASSERT_EQ(27u, pdu.Size()); IOQueue output; OutputStream stream(&output); pdu.Write(&stream); - OLA_ASSERT_EQ(26u, output.Size()); + OLA_ASSERT_EQ(27u, output.Size()); uint8_t *pdu_data = new uint8_t[output.Size()]; unsigned int pdu_size = output.Peek(pdu_data, output.Size()); OLA_ASSERT_EQ(output.Size(), pdu_size); uint8_t EXPECTED[] = { - 0xf0, 0x1a, + 0xf0, 0x00, 0x1b, 0, 0, 0, 39, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, diff --git a/libs/acn/LLRPProbeRequestPDU.cpp b/libs/acn/LLRPProbeRequestPDU.cpp index 6fe5378081..ba1623ed3a 100644 --- a/libs/acn/LLRPProbeRequestPDU.cpp +++ b/libs/acn/LLRPProbeRequestPDU.cpp @@ -56,7 +56,7 @@ void LLRPProbeRequestPDU::PrependPDU(ola::io::IOStack *stack, (known_uids.Size() * UID::LENGTH))); uint8_t vector = HostToNetwork(VECTOR_PROBE_REQUEST_DATA); stack->Write(reinterpret_cast(&vector), sizeof(vector)); - PrependFlagsAndLength(stack); + PrependFlagsAndLength(stack, VFLAG_MASK | HFLAG_MASK | DFLAG_MASK, true); } } // namespace acn } // namespace ola diff --git a/libs/acn/LLRPProbeRequestPDUTest.cpp b/libs/acn/LLRPProbeRequestPDUTest.cpp index ca6596991c..6666002b6a 100644 --- a/libs/acn/LLRPProbeRequestPDUTest.cpp +++ b/libs/acn/LLRPProbeRequestPDUTest.cpp @@ -70,7 +70,7 @@ void LLRPProbeRequestPDUTest::testPrepend() { OLA_ASSERT(stack.Read(buffer, length)); const uint8_t expected_data[] = { - 0xf0, 0x23, 1, + 0xf0, 0x00, 0x24, 1, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, diff --git a/libs/acn/PDU.cpp b/libs/acn/PDU.cpp index c9166db6cb..0f256eca13 100644 --- a/libs/acn/PDU.cpp +++ b/libs/acn/PDU.cpp @@ -35,8 +35,9 @@ using ola::network::HostToNetwork; unsigned int PDU::Size() const { unsigned int length = m_vector_size + HeaderSize() + DataSize(); - if (length > TWOB_LENGTH_LIMIT - 2) + if ((length > TWOB_LENGTH_LIMIT - 2) || m_force_length_flag) { length += 1; + } length += 2; return length; } @@ -59,7 +60,7 @@ bool PDU::Pack(uint8_t *buffer, unsigned int *length) const { return false; } - if (size <= TWOB_LENGTH_LIMIT) { + if (size <= TWOB_LENGTH_LIMIT && !m_force_length_flag) { buffer[0] = (uint8_t) ((size & 0x0f00) >> 8); buffer[1] = (uint8_t) (size & 0xff); } else { @@ -69,6 +70,11 @@ bool PDU::Pack(uint8_t *buffer, unsigned int *length) const { offset += 1; } + if (m_force_length_flag) { + // TODO(Peter): Should this happen regardless of the force when we're + // writing 20 bits of length? + buffer[0] |= LFLAG_MASK; + } buffer[0] |= VFLAG_MASK; buffer[0] |= HFLAG_MASK; buffer[0] |= DFLAG_MASK; @@ -117,13 +123,18 @@ bool PDU::Pack(uint8_t *buffer, unsigned int *length) const { void PDU::Write(OutputStream *stream) const { unsigned int size = Size(); - if (size <= TWOB_LENGTH_LIMIT) { + if (size <= TWOB_LENGTH_LIMIT && !m_force_length_flag) { uint16_t flags_and_length = static_cast(size); flags_and_length |= (VFLAG_MASK | HFLAG_MASK | DFLAG_MASK) << 8u; *stream << HostToNetwork(flags_and_length); } else { uint8_t vhl_flags = static_cast((size & 0x0f0000) >> 16); vhl_flags |= VFLAG_MASK | HFLAG_MASK | DFLAG_MASK; + if (m_force_length_flag) { + // TODO(Peter): Should this happen regardless of the force as we're + // writing 20 bits of length? + vhl_flags |= LFLAG_MASK; + } *stream << vhl_flags; *stream << (uint8_t) ((size & 0xff00) >> 8); *stream << (uint8_t) (size & 0xff); @@ -150,8 +161,9 @@ void PDU::Write(OutputStream *stream) const { * Prepend the flags and length to an OutputBufferInterface. */ void PDU::PrependFlagsAndLength(ola::io::OutputBufferInterface *output, - uint8_t flags) { - PrependFlagsAndLength(output, output->Size(), flags); + uint8_t flags, + bool force_length_flag) { + PrependFlagsAndLength(output, output->Size(), flags, force_length_flag); } @@ -160,8 +172,9 @@ void PDU::PrependFlagsAndLength(ola::io::OutputBufferInterface *output, */ void PDU::PrependFlagsAndLength(ola::io::OutputBufferInterface *output, unsigned int size, - uint8_t flags) { - if (size + 2 <= TWOB_LENGTH_LIMIT) { + uint8_t flags, + bool force_length_flag) { + if (size + 2 <= TWOB_LENGTH_LIMIT && !force_length_flag) { size += 2; uint16_t flags_and_length = static_cast(size); flags_and_length |= static_cast(flags << 8u); @@ -173,6 +186,11 @@ void PDU::PrependFlagsAndLength(ola::io::OutputBufferInterface *output, uint8_t flags_and_length[3]; flags_and_length[0] = static_cast((size & 0x0f0000) >> 16); flags_and_length[0] |= flags; + if (force_length_flag) { + // TODO(Peter): Should this happen regardless of the force as we're + // writing 20 bits of length? + flags_and_length[0] |= LFLAG_MASK; + } flags_and_length[1] = static_cast((size & 0xff00) >> 8); flags_and_length[2] = static_cast(size & 0xff); output->Write(flags_and_length, sizeof(flags_and_length)); diff --git a/libs/acn/PDU.h b/libs/acn/PDU.h index 64c1e82adb..2be285dead 100644 --- a/libs/acn/PDU.h +++ b/libs/acn/PDU.h @@ -22,6 +22,7 @@ #define LIBS_ACN_PDU_H_ #include +#include #include #include #include @@ -41,9 +42,12 @@ class PDU { FOUR_BYTES = 4, } vector_size; - explicit PDU(unsigned int vector, vector_size size = FOUR_BYTES): + explicit PDU(unsigned int vector, + vector_size size = FOUR_BYTES, + bool force_length_flag = false): m_vector(vector), - m_vector_size(size) {} + m_vector_size(size), + m_force_length_flag(force_length_flag) {} virtual ~PDU() {} // Returns the size of this PDU @@ -72,23 +76,36 @@ class PDU { static void PrependFlagsAndLength( ola::io::OutputBufferInterface *output, - uint8_t flags = VFLAG_MASK | HFLAG_MASK | DFLAG_MASK); + uint8_t flags = VFLAG_MASK | HFLAG_MASK | DFLAG_MASK, + bool force_length_flag = false); static void PrependFlagsAndLength( ola::io::OutputBufferInterface *output, unsigned int length, - uint8_t flags); + uint8_t flags, + bool force_length_flag = false); + + /** + * @brief This indicates a vector is present. + * @deprecated Use ola::acn::VFLAG_MASK instead (4 Feb 2020). + */ + static const uint8_t VFLAG_MASK = ola::acn::VFLAG_MASK; + /** + * @brief This indicates a header field is present. + * @deprecated Use ola::acn::HFLAG_MASK instead (4 Feb 2020). + */ + static const uint8_t HFLAG_MASK = ola::acn::HFLAG_MASK; + /** + * @brief This indicates a data field is present. + * @deprecated Use ola::acn::DFLAG_MASK instead (4 Feb 2020). + */ + static const uint8_t DFLAG_MASK = ola::acn::DFLAG_MASK; - // This indicates a vector is present - static const uint8_t VFLAG_MASK = 0x40; - // This indicates a header field is present - static const uint8_t HFLAG_MASK = 0x20; - // This indicates a data field is present - static const uint8_t DFLAG_MASK = 0x10; private: unsigned int m_vector; unsigned int m_vector_size; + bool m_force_length_flag; // The max PDU length that can be represented with the 2 byte format for // the length field. From 2d0ed43d1d351c696a8c5122c6c469d79bd2ee9f Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 4 Feb 2020 16:46:09 +0000 Subject: [PATCH 011/138] Fix the lint issues --- libs/acn/LLRPPDU.cpp | 6 ++++-- libs/acn/LLRPPDUTest.cpp | 1 - libs/acn/LLRPProbeRequestPDU.h | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libs/acn/LLRPPDU.cpp b/libs/acn/LLRPPDU.cpp index a1654338e9..4fb3b3644f 100644 --- a/libs/acn/LLRPPDU.cpp +++ b/libs/acn/LLRPPDU.cpp @@ -100,8 +100,10 @@ void LLRPPDU::PackData(OutputStream *stream) const { } -void LLRPPDU::PrependPDU(ola::io::IOStack *stack, uint32_t vector, - const ola::acn::CID &destination_cid, uint32_t transaction_number) { +void LLRPPDU::PrependPDU(ola::io::IOStack *stack, + uint32_t vector, + const ola::acn::CID &destination_cid, + uint32_t transaction_number) { LLRPHeader::llrp_pdu_header header; destination_cid.Pack(header.destination_cid); header.transaction_number = HostToNetwork(transaction_number); diff --git a/libs/acn/LLRPPDUTest.cpp b/libs/acn/LLRPPDUTest.cpp index 13273f60ed..01c30db22a 100644 --- a/libs/acn/LLRPPDUTest.cpp +++ b/libs/acn/LLRPPDUTest.cpp @@ -35,7 +35,6 @@ namespace acn { using ola::io::IOQueue; using ola::io::OutputStream; using ola::network::HostToNetwork; -using std::string; class LLRPPDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(LLRPPDUTest); diff --git a/libs/acn/LLRPProbeRequestPDU.h b/libs/acn/LLRPProbeRequestPDU.h index 34e5ac79e0..b39b768cf9 100644 --- a/libs/acn/LLRPProbeRequestPDU.h +++ b/libs/acn/LLRPProbeRequestPDU.h @@ -59,4 +59,4 @@ class LLRPProbeRequestPDU : private PDU { }; } // namespace acn } // namespace ola -#endif // LIBS_ACN_LLRPProbeRequestPDU_H_ +#endif // LIBS_ACN_LLRPPROBEREQUESTPDU_H_ From 38d893db6b6bb1a8c0256fc7fc9320cd7ff65965 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 6 Feb 2020 00:30:59 +0000 Subject: [PATCH 012/138] Add the LLRPProbeReplyPDU --- libs/acn/LLRPProbeReplyPDU.cpp | 50 ++++++++++++++++++ libs/acn/LLRPProbeReplyPDU.h | 59 ++++++++++++++++++++++ libs/acn/LLRPProbeReplyPDUTest.cpp | 81 ++++++++++++++++++++++++++++++ libs/acn/Makefile.mk | 3 ++ 4 files changed, 193 insertions(+) create mode 100644 libs/acn/LLRPProbeReplyPDU.cpp create mode 100644 libs/acn/LLRPProbeReplyPDU.h create mode 100644 libs/acn/LLRPProbeReplyPDUTest.cpp diff --git a/libs/acn/LLRPProbeReplyPDU.cpp b/libs/acn/LLRPProbeReplyPDU.cpp new file mode 100644 index 0000000000..830766fd85 --- /dev/null +++ b/libs/acn/LLRPProbeReplyPDU.cpp @@ -0,0 +1,50 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPProbeReplyPDU.cpp + * The LLRPProbeReplyPDU + * Copyright (C) 2020 Peter Newman + */ + +#include "libs/acn/LLRPProbeReplyPDU.h" + +#include +#include +#include + +namespace ola { +namespace acn { + +using ola::io::OutputStream; +using ola::network::HostToNetwork; +using ola::network::MACAddress; +using ola::rdm::UID; + +void LLRPProbeReplyPDU::PrependPDU(ola::io::IOStack *stack, + const UID &target_uid, + const MACAddress &hardware_address, + const LLRPComponentType type) { + llrp_probe_reply_pdu_data data; + target_uid.Pack(data.target_uid, sizeof(data.target_uid)); + hardware_address.Pack(data.hardware_address, sizeof(data.hardware_address)); + data.type = HostToNetwork(static_cast(type)); + stack->Write(reinterpret_cast(&data), + static_cast(sizeof(llrp_probe_reply_pdu_data))); + uint8_t vector = HostToNetwork(VECTOR_PROBE_REPLY_DATA); + stack->Write(reinterpret_cast(&vector), sizeof(vector)); + PrependFlagsAndLength(stack, VFLAG_MASK | HFLAG_MASK | DFLAG_MASK, true); +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/LLRPProbeReplyPDU.h b/libs/acn/LLRPProbeReplyPDU.h new file mode 100644 index 0000000000..08bbc55835 --- /dev/null +++ b/libs/acn/LLRPProbeReplyPDU.h @@ -0,0 +1,59 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPProbeReplyPDU.h + * The LLRPProbeReplyPDU class + * Copyright (C) 2020 Peter Newman + */ + +#ifndef LIBS_ACN_LLRPPROBEREPLYPDU_H_ +#define LIBS_ACN_LLRPPROBEREPLYPDU_H_ + +#include +#include +#include + +#include "libs/acn/PDU.h" + +namespace ola { +namespace acn { + +class LLRPProbeReplyPDU : private PDU { + public: + typedef enum { + LLRP_COMPONENT_TYPE_RPT_DEVICE = 0, /**< Device */ + LLRP_COMPONENT_TYPE_RPT_CONTROLLER = 1, /**< Controller */ + LLRP_COMPONENT_TYPE_BROKER = 2, /**< Broker */ + LLRP_COMPONENT_TYPE_NON_RDMNET = 0xff, /**< Non-RDMnet */ + } LLRPComponentType; + + static void PrependPDU(ola::io::IOStack *stack, + const ola::rdm::UID &target_uid, + const ola::network::MACAddress &hardware_address, + const LLRPComponentType type); + + static const uint8_t VECTOR_PROBE_REPLY_DATA = 0x01; + + PACK( + struct llrp_probe_reply_pdu_data_s { + uint8_t target_uid[ola::rdm::UID::LENGTH]; + uint8_t hardware_address[ola::network::MACAddress::LENGTH]; + uint8_t type; + }); + typedef struct llrp_probe_reply_pdu_data_s llrp_probe_reply_pdu_data; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_LLRPPROBEREPLYPDU_H_ diff --git a/libs/acn/LLRPProbeReplyPDUTest.cpp b/libs/acn/LLRPProbeReplyPDUTest.cpp new file mode 100644 index 0000000000..2ae354c47d --- /dev/null +++ b/libs/acn/LLRPProbeReplyPDUTest.cpp @@ -0,0 +1,81 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPProbeReplyPDUTest.cpp + * Test fixture for the LLRPProbeReplyPDU class + * Copyright (C) 2020 Peter Newman + */ + +#include +#include +#include + +#include "ola/Logging.h" +#include "ola/io/IOStack.h" +#include "ola/network/NetworkUtils.h" +#include "ola/rdm/UID.h" +#include "ola/rdm/UIDSet.h" +#include "ola/testing/TestUtils.h" +#include "libs/acn/PDUTestCommon.h" +#include "libs/acn/LLRPProbeReplyPDU.h" + +namespace ola { +namespace acn { + +using ola::acn::LLRPProbeReplyPDU; +using ola::io::IOStack; +using ola::network::MACAddress; +using ola::rdm::UID; + +class LLRPProbeReplyPDUTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(LLRPProbeReplyPDUTest); + CPPUNIT_TEST(testPrepend); + CPPUNIT_TEST_SUITE_END(); + + public: + void testPrepend(); + + private: + static const unsigned int TEST_VECTOR; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(LLRPProbeReplyPDUTest); + +void LLRPProbeReplyPDUTest::testPrepend() { + IOStack stack; + UID target_uid = UID(0x4321, 0x12345678); + MACAddress hardware_address; + MACAddress::FromString("01:23:45:67:89:ab", &hardware_address); + LLRPProbeReplyPDU::PrependPDU( + &stack, + target_uid, + hardware_address, + LLRPProbeReplyPDU::LLRP_COMPONENT_TYPE_NON_RDMNET); + + unsigned int length = stack.Size(); + uint8_t *buffer = new uint8_t[length]; + OLA_ASSERT(stack.Read(buffer, length)); + + const uint8_t expected_data[] = { + 0xf0, 0x00, 0x11, 1, + 0x43, 0x21, 0x12, 0x34, 0x56, 0x78, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, + 0xff + }; + OLA_ASSERT_DATA_EQUALS(expected_data, sizeof(expected_data), buffer, length); + delete[] buffer; +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index 3402e80be6..b203c5b258 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -64,6 +64,8 @@ libs_acn_libolae131core_la_SOURCES = \ libs/acn/LLRPHeader.h \ libs/acn/LLRPInflator.cpp \ libs/acn/LLRPInflator.h \ + libs/acn/LLRPProbeReplyPDU.cpp \ + libs/acn/LLRPProbeReplyPDU.h \ libs/acn/LLRPProbeRequestPDU.cpp \ libs/acn/LLRPProbeRequestPDU.h \ libs/acn/LLRPPDU.cpp \ @@ -151,6 +153,7 @@ libs_acn_E133Tester_LDADD = \ libs_acn_LLRPTester_SOURCES = \ libs/acn/LLRPInflatorTest.cpp \ libs/acn/LLRPPDUTest.cpp \ + libs/acn/LLRPProbeReplyPDUTest.cpp \ libs/acn/LLRPProbeRequestPDUTest.cpp libs_acn_LLRPTester_CPPFLAGS = $(COMMON_TESTING_FLAGS) libs_acn_LLRPTester_LDADD = \ From 956c0fb0eaedb81a303d22cbcbe60239eebe0c1a Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 6 Feb 2020 01:21:41 +0000 Subject: [PATCH 013/138] Fix the LLRP vector values --- include/ola/acn/ACNVectors.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/ola/acn/ACNVectors.h b/include/ola/acn/ACNVectors.h index fc08d266ff..72c050ea91 100644 --- a/include/ola/acn/ACNVectors.h +++ b/include/ola/acn/ACNVectors.h @@ -95,8 +95,8 @@ enum E133ControllerVector { */ enum LLRPVector { VECTOR_LLRP_PROBE_REQUEST = 1, /**< LLRP Probe Request */ - VECTOR_LLRP_PROBE_REPLY = 1, /**< LLRP Probe Reply */ - VECTOR_LLRP_RDM_CMD = 1, /**< LLRP RDM Command */ + VECTOR_LLRP_PROBE_REPLY = 2, /**< LLRP Probe Reply */ + VECTOR_LLRP_RDM_CMD = 3, /**< LLRP RDM Command */ }; /** From d72c6aaf162bf2c1c7c409589f70c392353dcdb8 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 6 Feb 2020 14:58:13 +0000 Subject: [PATCH 014/138] Add the ability to force the length flag on a Root PDU --- libs/acn/RootPDU.cpp | 4 ++-- libs/acn/RootPDU.h | 6 +++--- libs/acn/RootSender.cpp | 4 ++-- libs/acn/RootSender.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/acn/RootPDU.cpp b/libs/acn/RootPDU.cpp index 227406124f..cec65ed7bb 100644 --- a/libs/acn/RootPDU.cpp +++ b/libs/acn/RootPDU.cpp @@ -86,12 +86,12 @@ void RootPDU::SetBlock(const PDUBlock *block) { /* * Prepend a Root Layer flags, length, vector & header */ -void RootPDU::PrependPDU(IOStack *stack, uint32_t vector, const CID &cid) { +void RootPDU::PrependPDU(IOStack *stack, uint32_t vector, const CID &cid, bool force_length_flag) { cid.Write(stack); vector = HostToNetwork(vector); stack->Write(reinterpret_cast(&vector), sizeof(vector)); - PrependFlagsAndLength(stack); + PrependFlagsAndLength(stack, VFLAG_MASK | HFLAG_MASK | DFLAG_MASK, force_length_flag); } } // namespace acn } // namespace ola diff --git a/libs/acn/RootPDU.h b/libs/acn/RootPDU.h index cc10ff8bcc..6d66ebc178 100644 --- a/libs/acn/RootPDU.h +++ b/libs/acn/RootPDU.h @@ -33,8 +33,8 @@ namespace acn { class RootPDU: public PDU { public: - explicit RootPDU(unsigned int vector): - PDU(vector), + explicit RootPDU(unsigned int vector, bool force_length_flag = false): + PDU(vector, FOUR_BYTES, force_length_flag), m_block(NULL), m_block_size(0) {} RootPDU(unsigned int vector, @@ -60,7 +60,7 @@ class RootPDU: public PDU { void SetBlock(const PDUBlock *block); static void PrependPDU(ola::io::IOStack *stack, uint32_t vector, - const ola::acn::CID &cid); + const ola::acn::CID &cid, bool force_length_flag = false); private: ola::acn::CID m_cid; diff --git a/libs/acn/RootSender.cpp b/libs/acn/RootSender.cpp index 009bb30f7e..767c8844c1 100644 --- a/libs/acn/RootSender.cpp +++ b/libs/acn/RootSender.cpp @@ -31,8 +31,8 @@ using ola::acn::CID; * Create a new RootSender * @param cid The CID to send in the Root PDU. */ -RootSender::RootSender(const CID &cid) - : m_root_pdu(0) { +RootSender::RootSender(const CID &cid, bool force_length_flag) + : m_root_pdu(0, force_length_flag) { m_root_pdu.Cid(cid); } diff --git a/libs/acn/RootSender.h b/libs/acn/RootSender.h index 31926ef8f0..a09bbf6199 100644 --- a/libs/acn/RootSender.h +++ b/libs/acn/RootSender.h @@ -32,7 +32,7 @@ namespace acn { class RootSender { public: - explicit RootSender(const ola::acn::CID &cid); + explicit RootSender(const ola::acn::CID &cid, bool force_length_flag = false); ~RootSender() {} // Convenience method to encapsulate & send a single PDU From d972695ecd437044be622982e490b63ca42c66b9 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 6 Feb 2020 14:59:22 +0000 Subject: [PATCH 015/138] Allow an LLRPProbeReplyPDU to be sent --- libs/acn/LLRPProbeReplyPDU.cpp | 20 ++++++ libs/acn/LLRPProbeReplyPDU.h | 28 +++++++- libs/acn/LLRPProbeReplyPDUTest.cpp | 100 +++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 1 deletion(-) diff --git a/libs/acn/LLRPProbeReplyPDU.cpp b/libs/acn/LLRPProbeReplyPDU.cpp index 830766fd85..a7822e7dc9 100644 --- a/libs/acn/LLRPProbeReplyPDU.cpp +++ b/libs/acn/LLRPProbeReplyPDU.cpp @@ -32,6 +32,26 @@ using ola::network::HostToNetwork; using ola::network::MACAddress; using ola::rdm::UID; +bool LLRPProbeReplyPDU::PackData(uint8_t *data, unsigned int *length) const { + llrp_probe_reply_pdu_data pdu_data; + m_target_uid.Pack(pdu_data.target_uid, sizeof(pdu_data.target_uid)); + m_hardware_address.Pack(pdu_data.hardware_address, sizeof(pdu_data.hardware_address)); + pdu_data.type = HostToNetwork(static_cast(m_type)); + + *length = sizeof(llrp_probe_reply_pdu_data); + memcpy(data, &pdu_data, *length); + return true; +} + +void LLRPProbeReplyPDU::PackData(ola::io::OutputStream *stream) const { + llrp_probe_reply_pdu_data data; + m_target_uid.Pack(data.target_uid, sizeof(data.target_uid)); + m_hardware_address.Pack(data.hardware_address, sizeof(data.hardware_address)); + data.type = HostToNetwork(static_cast(m_type)); + stream->Write(reinterpret_cast(&data), + static_cast(sizeof(llrp_probe_reply_pdu_data))); +} + void LLRPProbeReplyPDU::PrependPDU(ola::io::IOStack *stack, const UID &target_uid, const MACAddress &hardware_address, diff --git a/libs/acn/LLRPProbeReplyPDU.h b/libs/acn/LLRPProbeReplyPDU.h index 08bbc55835..96b0644151 100644 --- a/libs/acn/LLRPProbeReplyPDU.h +++ b/libs/acn/LLRPProbeReplyPDU.h @@ -30,7 +30,7 @@ namespace ola { namespace acn { -class LLRPProbeReplyPDU : private PDU { +class LLRPProbeReplyPDU : public PDU { public: typedef enum { LLRP_COMPONENT_TYPE_RPT_DEVICE = 0, /**< Device */ @@ -39,6 +39,27 @@ class LLRPProbeReplyPDU : private PDU { LLRP_COMPONENT_TYPE_NON_RDMNET = 0xff, /**< Non-RDMnet */ } LLRPComponentType; + explicit LLRPProbeReplyPDU(unsigned int vector, + const ola::rdm::UID &target_uid, + const ola::network::MACAddress &hardware_address, + const LLRPComponentType type): + PDU(vector, ONE_BYTE, true), + m_target_uid(target_uid), + m_hardware_address(hardware_address), + m_type(type) {} + + unsigned int HeaderSize() const { return 0; } + bool PackHeader(OLA_UNUSED uint8_t *data, + unsigned int *length) const { + *length = 0; + return true; + } + void PackHeader(OLA_UNUSED ola::io::OutputStream *stream) const {} + + unsigned int DataSize() const { return sizeof(llrp_probe_reply_pdu_data); } + bool PackData(uint8_t *data, unsigned int *length) const; + void PackData(ola::io::OutputStream *stream) const; + static void PrependPDU(ola::io::IOStack *stack, const ola::rdm::UID &target_uid, const ola::network::MACAddress &hardware_address, @@ -53,6 +74,11 @@ class LLRPProbeReplyPDU : private PDU { uint8_t type; }); typedef struct llrp_probe_reply_pdu_data_s llrp_probe_reply_pdu_data; + + private: + const ola::rdm::UID m_target_uid; + const ola::network::MACAddress m_hardware_address; + const LLRPComponentType m_type; }; } // namespace acn } // namespace ola diff --git a/libs/acn/LLRPProbeReplyPDUTest.cpp b/libs/acn/LLRPProbeReplyPDUTest.cpp index 2ae354c47d..ae25918683 100644 --- a/libs/acn/LLRPProbeReplyPDUTest.cpp +++ b/libs/acn/LLRPProbeReplyPDUTest.cpp @@ -23,7 +23,9 @@ #include #include "ola/Logging.h" +#include "ola/io/IOQueue.h" #include "ola/io/IOStack.h" +#include "ola/io/OutputStream.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" @@ -35,16 +37,23 @@ namespace ola { namespace acn { using ola::acn::LLRPProbeReplyPDU; +using ola::io::IOQueue; using ola::io::IOStack; +using ola::io::OutputStream; +using ola::network::HostToNetwork; using ola::network::MACAddress; using ola::rdm::UID; class LLRPProbeReplyPDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(LLRPProbeReplyPDUTest); + CPPUNIT_TEST(testSimpleLLRPProbeReplyPDU); + CPPUNIT_TEST(testSimpleLLRPProbeReplyPDUToOutputStream); CPPUNIT_TEST(testPrepend); CPPUNIT_TEST_SUITE_END(); public: + void testSimpleLLRPProbeReplyPDU(); + void testSimpleLLRPProbeReplyPDUToOutputStream(); void testPrepend(); private: @@ -53,6 +62,97 @@ class LLRPProbeReplyPDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE_REGISTRATION(LLRPProbeReplyPDUTest); +const unsigned int LLRPProbeReplyPDUTest::TEST_VECTOR = 39; + + +/* + * Test that packing a LLRPProbeReplyPDU works. + */ +void LLRPProbeReplyPDUTest::testSimpleLLRPProbeReplyPDU() { + UID target_uid = UID(0x4321, 0x12345678); + MACAddress hardware_address; + MACAddress::FromString("01:23:45:67:89:ab", &hardware_address); + LLRPProbeReplyPDU pdu( + TEST_VECTOR, + target_uid, + hardware_address, + LLRPProbeReplyPDU::LLRP_COMPONENT_TYPE_NON_RDMNET); + + OLA_ASSERT_EQ(0u, pdu.HeaderSize()); + OLA_ASSERT_EQ(13u, pdu.DataSize()); + OLA_ASSERT_EQ(17u, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + + // spot check the data + OLA_ASSERT_EQ((uint8_t) 0xf0, data[0]); + // bytes_used is technically data[1] and data[2] if > 255 + OLA_ASSERT_EQ((uint8_t) bytes_used, data[2]); + OLA_ASSERT_EQ(HostToNetwork((uint8_t) TEST_VECTOR), data[3]); + + uint8_t buffer[UID::LENGTH]; + target_uid.Pack(buffer, sizeof(buffer)); + OLA_ASSERT_DATA_EQUALS(&data[4], UID::LENGTH, buffer, sizeof(buffer)); + uint8_t buffer2[MACAddress::LENGTH]; + hardware_address.Pack(buffer2, sizeof(buffer2)); + OLA_ASSERT_DATA_EQUALS(&data[10], MACAddress::LENGTH, buffer2, sizeof(buffer2)); + + // test undersized buffer + bytes_used = size - 1; + OLA_ASSERT_FALSE(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(0u, bytes_used); + + // test oversized buffer + bytes_used = size + 1; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + delete[] data; +} + + +/* + * Test that writing to an output stream works. + */ +void LLRPProbeReplyPDUTest::testSimpleLLRPProbeReplyPDUToOutputStream() { + UID target_uid = UID(0x4321, 0x12345678); + MACAddress hardware_address; + MACAddress::FromString("01:23:45:67:89:ab", &hardware_address); + LLRPProbeReplyPDU pdu( + TEST_VECTOR, + target_uid, + hardware_address, + LLRPProbeReplyPDU::LLRP_COMPONENT_TYPE_NON_RDMNET); + + OLA_ASSERT_EQ(0u, pdu.HeaderSize()); + OLA_ASSERT_EQ(13u, pdu.DataSize()); + OLA_ASSERT_EQ(17u, pdu.Size()); + + IOQueue output; + OutputStream stream(&output); + pdu.Write(&stream); + OLA_ASSERT_EQ(17u, output.Size()); + + uint8_t *pdu_data = new uint8_t[output.Size()]; + unsigned int pdu_size = output.Peek(pdu_data, output.Size()); + OLA_ASSERT_EQ(output.Size(), pdu_size); + + uint8_t EXPECTED[] = { + 0xf0, 0x00, 0x11, + 39, + 0x43, 0x21, 0x12, 0x34, 0x56, 0x78, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, + 0xff + }; + OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), pdu_data, pdu_size); + output.Pop(output.Size()); + delete[] pdu_data; +} + + void LLRPProbeReplyPDUTest::testPrepend() { IOStack stack; UID target_uid = UID(0x4321, 0x12345678); From 3eb8518d9f08e27a7eeb22659f89e5700a93bf24 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 6 Feb 2020 14:59:51 +0000 Subject: [PATCH 016/138] Tidying and TODO --- libs/acn/LLRPProbeRequestPDU.cpp | 2 +- libs/acn/LLRPProbeRequestPDU.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/acn/LLRPProbeRequestPDU.cpp b/libs/acn/LLRPProbeRequestPDU.cpp index ba1623ed3a..6db4af3bab 100644 --- a/libs/acn/LLRPProbeRequestPDU.cpp +++ b/libs/acn/LLRPProbeRequestPDU.cpp @@ -30,7 +30,6 @@ namespace acn { using ola::io::OutputStream; using ola::network::HostToNetwork; using ola::rdm::UID; -using std::vector; void LLRPProbeRequestPDU::PrependPDU(ola::io::IOStack *stack, const UID &lower_uid, @@ -49,6 +48,7 @@ void LLRPProbeRequestPDU::PrependPDU(ola::io::IOStack *stack, filter |= FILTER_BROKERS_ONLY; } data.filter = HostToNetwork(filter); + // TODO(Peter): We need to check we've got <= 200 UIDs here known_uids.Pack(data.known_uids, sizeof(data.known_uids)); stack->Write(reinterpret_cast(&data), static_cast(sizeof(llrp_probe_request_pdu_data) - diff --git a/libs/acn/LLRPProbeRequestPDU.h b/libs/acn/LLRPProbeRequestPDU.h index b39b768cf9..17a3145c69 100644 --- a/libs/acn/LLRPProbeRequestPDU.h +++ b/libs/acn/LLRPProbeRequestPDU.h @@ -47,7 +47,6 @@ class LLRPProbeRequestPDU : private PDU { static const uint16_t FILTER_CLIENT_TCP_CONNECTION_INACTIVE = 0x0001; static const uint16_t FILTER_BROKERS_ONLY = 0x0002; - private: PACK( struct llrp_probe_request_pdu_data_s { uint8_t lower_uid[ola::rdm::UID::LENGTH]; From f3b751195ab17d9796dfc4cc3eaa89a8db200699 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 6 Feb 2020 15:00:48 +0000 Subject: [PATCH 017/138] Initial handling of LLRPProbeRequest PDUs --- libs/acn/LLRPProbeRequestInflator.cpp | 119 ++++++++++++++++++++++++++ libs/acn/LLRPProbeRequestInflator.h | 71 +++++++++++++++ libs/acn/Makefile.mk | 2 + 3 files changed, 192 insertions(+) create mode 100644 libs/acn/LLRPProbeRequestInflator.cpp create mode 100644 libs/acn/LLRPProbeRequestInflator.h diff --git a/libs/acn/LLRPProbeRequestInflator.cpp b/libs/acn/LLRPProbeRequestInflator.cpp new file mode 100644 index 0000000000..cbc2fff04d --- /dev/null +++ b/libs/acn/LLRPProbeRequestInflator.cpp @@ -0,0 +1,119 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPProbeRequestInflator.cpp + * The Inflator for the LLRP Probe Request PDUs + * Copyright (C) 2020 Peter Newman + */ + +#include +#include +#include "ola/Logging.h" +#include "include/ola/rdm/UID.h" +#include "include/ola/rdm/UIDSet.h" +#include "include/ola/strings/Format.h" +#include "libs/acn/LLRPProbeRequestInflator.h" +#include "libs/acn/LLRPProbeRequestPDU.h" + +namespace ola { +namespace acn { + +using ola::acn::LLRPProbeRequestPDU; +using ola::rdm::UID; +using ola::rdm::UIDSet; + +/** + * Create a new LLRP Probe Request inflator + */ +LLRPProbeRequestInflator::LLRPProbeRequestInflator() + : BaseInflator(PDU::ONE_BYTE) { +} + +/** + * Set a RDMHandler to run when receiving a RDM message. + * @param handler the callback to invoke when there is rdm data for this + * universe. + */ +void LLRPProbeRequestInflator::SetLLRPProbeRequestHandler( + LLRPProbeRequestHandler *handler) { + m_llrp_probe_request_handler.reset(handler); +} + + +/* + * Decode the LLRP Probe Request 'header', which is 0 bytes in length. + * @param headers the HeaderSet to add to + * @param data a pointer to the data + * @param length length of the data + * @returns true if successful, false otherwise + */ +bool LLRPProbeRequestInflator::DecodeHeader(HeaderSet *, + const uint8_t*, + unsigned int, + unsigned int *bytes_used) { + *bytes_used = 0; + return true; +} + + +/* + * Handle a LLRP Probe Request PDU for E1.33. + */ +bool LLRPProbeRequestInflator::HandlePDUData(uint32_t vector, + const HeaderSet &headers, + const uint8_t *data, + unsigned int pdu_len) { + if (vector != LLRPProbeRequestPDU::VECTOR_PROBE_REQUEST_DATA) { + OLA_INFO << "Not a probe request, vector was " << vector; + return true; + } + + ola::strings::FormatData(&std::cout, data, pdu_len); + + LLRPProbeRequestPDU::llrp_probe_request_pdu_data pdu_data; + if (pdu_len > sizeof(pdu_data)) { + OLA_WARN << "Got too much data, received " << pdu_len << " only expecting " + << sizeof(pdu_data); + return false; + } + + unsigned int known_uids_size = static_cast( + pdu_len - (sizeof(pdu_data) - + sizeof(pdu_data.known_uids))); + if (known_uids_size % UID::UID_SIZE != 0) { + OLA_WARN << "Got a partial known UID, received " << known_uids_size << " bytes"; + return false; + } + + memcpy(reinterpret_cast(&pdu_data), data, sizeof(pdu_data)); + + OLA_DEBUG << "Probe from " << UID(pdu_data.lower_uid) << " to " << UID(pdu_data.upper_uid); + +// string rdm_message(reinterpret_cast(&data[0]), pdu_len); + + if (m_llrp_probe_request_handler.get()) { + m_llrp_probe_request_handler->Run(&headers, + UID(pdu_data.lower_uid), + UID(pdu_data.upper_uid) +//, +// UIDSet() +); + } else { + OLA_WARN << "No LLRP Probe Request handler defined!"; + } + return true; +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/LLRPProbeRequestInflator.h b/libs/acn/LLRPProbeRequestInflator.h new file mode 100644 index 0000000000..1d63b84e9f --- /dev/null +++ b/libs/acn/LLRPProbeRequestInflator.h @@ -0,0 +1,71 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPProbeRequestInflator.h + * Copyright (C) 2020 Peter Newman + */ + +#ifndef LIBS_ACN_LLRPPROBEREQUESTINFLATOR_H_ +#define LIBS_ACN_LLRPPROBEREQUESTINFLATOR_H_ + +#include "ola/Callback.h" +#include "ola/acn/ACNVectors.h" +#include "ola/rdm/UID.h" +#include "ola/rdm/UIDSet.h" +#include "libs/acn/BaseInflator.h" +#include "libs/acn/HeaderSet.h" + +namespace ola { +namespace acn { + +class LLRPProbeRequestInflator: public BaseInflator { + friend class LLRPProbeRequestInflatorTest; + + public: + // These are pointers so the callers don't have to pull in all the headers. + typedef ola::Callback3 LLRPProbeRequestHandler; + + LLRPProbeRequestInflator(); + ~LLRPProbeRequestInflator() {} + + uint32_t Id() const { return ola::acn::VECTOR_LLRP_PROBE_REQUEST; } + + void SetLLRPProbeRequestHandler(LLRPProbeRequestHandler *handler); + + protected: + bool DecodeHeader(HeaderSet *headers, + const uint8_t *data, + unsigned int len, + unsigned int *bytes_used); + + void ResetHeaderField() {} // namespace noop + + virtual bool HandlePDUData(uint32_t vector, + const HeaderSet &headers, + const uint8_t *data, + unsigned int pdu_len); + + private: + std::auto_ptr m_llrp_probe_request_handler; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_LLRPPROBEREQUESTINFLATOR_H_ diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index b203c5b258..7c81ef9031 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -66,6 +66,8 @@ libs_acn_libolae131core_la_SOURCES = \ libs/acn/LLRPInflator.h \ libs/acn/LLRPProbeReplyPDU.cpp \ libs/acn/LLRPProbeReplyPDU.h \ + libs/acn/LLRPProbeRequestInflator.cpp \ + libs/acn/LLRPProbeRequestInflator.h \ libs/acn/LLRPProbeRequestPDU.cpp \ libs/acn/LLRPProbeRequestPDU.h \ libs/acn/LLRPPDU.cpp \ From e445c32b48e203a380d9558e3763a99fd74768d6 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 6 Feb 2020 15:01:27 +0000 Subject: [PATCH 018/138] Initial LLRP discoverable device --- .gitignore | 2 + tools/e133/Makefile.mk | 6 +- tools/e133/llrp-receive-test.cpp | 236 +++++++++++++++++++++++++++++++ 3 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 tools/e133/llrp-receive-test.cpp diff --git a/.gitignore b/.gitignore index b41ca378ac..6103d55d61 100644 --- a/.gitignore +++ b/.gitignore @@ -212,6 +212,8 @@ tools/e133/e133_monitor tools/e133/e133_monitor.exe tools/e133/e133_receiver tools/e133/e133_receiver.exe +tools/e133/llrp_receive_test +tools/e133/llrp_receive_test.exe tools/e133/slp_locate tools/e133/slp_locate.exe tools/e133/slp_register diff --git a/tools/e133/Makefile.mk b/tools/e133/Makefile.mk index 6b77f499d3..132da06b7b 100644 --- a/tools/e133/Makefile.mk +++ b/tools/e133/Makefile.mk @@ -70,7 +70,8 @@ noinst_PROGRAMS += \ tools/e133/basic_device \ tools/e133/e133_controller \ tools/e133/e133_monitor \ - tools/e133/e133_receiver + tools/e133/e133_receiver \ + tools/e133/llrp_receive_test tools_e133_e133_receiver_SOURCES = tools/e133/e133-receiver.cpp tools_e133_e133_receiver_LDADD = common/libolacommon.la \ @@ -104,3 +105,6 @@ tools_e133_basic_device_SOURCES = tools/e133/basic-device.cpp tools_e133_basic_device_LDADD = common/libolacommon.la \ libs/acn/libolaacn.la \ tools/e133/libolae133common.la + +tools_e133_llrp_receive_test_SOURCES = tools/e133/llrp-receive-test.cpp +tools_e133_llrp_receive_test_LDADD = libs/acn/libolae131core.la diff --git a/tools/e133/llrp-receive-test.cpp b/tools/e133/llrp-receive-test.cpp new file mode 100644 index 0000000000..e6530e6530 --- /dev/null +++ b/tools/e133/llrp-receive-test.cpp @@ -0,0 +1,236 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * e131_transmit_test.cpp + * The sends custom E1.31 packets in order to test the implementation of a + * remote node. + * Copyright (C) 2010 Simon Newton + * + * The remote node needs to be listening for Universe 1. + */ + +#include +#include +#include +#include +#include "libs/acn/HeaderSet.h" +#include "libs/acn/LLRPHeader.h" +#include "libs/acn/LLRPInflator.h" +#include "libs/acn/LLRPPDU.h" +#include "libs/acn/LLRPProbeReplyPDU.h" +#include "libs/acn/LLRPProbeRequestInflator.h" +#include "libs/acn/PreamblePacker.h" +#include "libs/acn/RootHeader.h" +#include "libs/acn/RootInflator.h" +#include "libs/acn/RootSender.h" +#include "libs/acn/Transport.h" +#include "libs/acn/UDPTransport.h" +#include "ola/Callback.h" +#include "ola/acn/ACNPort.h" +#include "ola/acn/CID.h" +#include "ola/io/SelectServer.h" +#include "ola/network/InterfacePicker.h" +#include "ola/network/IPV4Address.h" +#include "ola/network/MACAddress.h" +#include "ola/network/SocketAddress.h" +#include "ola/network/Socket.h" +#include "ola/rdm/UID.h" +#include "ola/DmxBuffer.h" +#include "ola/Logging.h" + +using std::string; +using std::vector; +using std::auto_ptr; + +using ola::acn::CID; +using ola::acn::IncomingUDPTransport; +using ola::acn::LLRPHeader; +using ola::acn::LLRPProbeReplyPDU; +using ola::acn::OutgoingUDPTransport; +using ola::acn::OutgoingUDPTransportImpl; +using ola::network::IPV4Address; +using ola::network::IPV4SocketAddress; +using ola::network::MACAddress; +using ola::rdm::UID; + +/* + * Display the help message + */ +void DisplayHelp(const char *binary_name) { + std::cout << "Usage: " << binary_name << " [--interactive]\n" + "\n" + "Run the E1.31 Transmit test. This test can run in one of two modes:\n" + " * interactive mode. This sends data to the multicast addresses\n" + " and a human gets to verify it.\n" + " * local mode (default). This starts a local E131Node and sends it data,\n" + " verifying against the expected output.\n" + "\n" + " -h, --help Display this help message and exit.\n" + " -i, --interactive Run in interactive mode.\n" + << std::endl; +} + + +ola::network::Interface m_interface; +const std::string m_preferred_ip; +ola::network::UDPSocket m_socket; +uint8_t *m_recv_buffer; + +ola::acn::PreamblePacker m_packer; +ola::acn::CID cid = CID::Generate(); +ola::acn::RootSender m_root_sender(cid, true); + +//void CheckData() { +// std::cout << "Awaiting data..." << std::endl; +// if (!m_recv_buffer) +// m_recv_buffer = new uint8_t[512]; +// +// ssize_t size = 512; +// ola::network::IPV4SocketAddress source; + +// if (!m_socket.RecvFrom(m_recv_buffer, &size, &source)) +// return; + +// std::cout << "Got " << size << " bytes" << std::endl; + +// ola::FormatData(&std::cout, m_recv_buffer, size); + +// ola::acn::HeaderSet header_set; +// if (root_inflator.InflatePDUBlock(&header_set, &m_recv_buffer[16], size - 16)) { +// std::cout << "Inflated" << std::endl; +// } else { +// std::cout << "Failed to inflate" << std::endl; +// } +//} + +void HandleLLRPProbeRequest( + const ola::acn::HeaderSet *headers, + const ola::rdm::UID &lower_uid, + const ola::rdm::UID &upper_uid) { + OLA_DEBUG << "Handling probe from " << lower_uid << " to " << upper_uid; + + const ola::acn::RootHeader root_header = headers->GetRootHeader(); + const ola::acn::LLRPHeader llrp_header = headers->GetLLRPHeader(); + + OLA_DEBUG << "Source CID: " << root_header.GetCid(); + OLA_DEBUG << "TN: " << llrp_header.TransactionNumber(); + + ola::acn::LLRPHeader reply_llrp_header = LLRPHeader(root_header.GetCid(), llrp_header.TransactionNumber()); + + IPV4Address *target_address = IPV4Address::FromString("239.255.250.134"); + + OutgoingUDPTransportImpl transport_impl = OutgoingUDPTransportImpl(&m_socket, &m_packer); + OutgoingUDPTransport transport(&transport_impl, + *target_address, + ola::acn::LLRP_PORT); + + UID target_uid = UID(0x4321, 0x12345678); + MACAddress hardware_address; + MACAddress::FromString("01:23:45:67:89:ab", &hardware_address); + + LLRPProbeReplyPDU probe_reply( + LLRPProbeReplyPDU::VECTOR_PROBE_REPLY_DATA, + target_uid, + hardware_address, + LLRPProbeReplyPDU::LLRP_COMPONENT_TYPE_NON_RDMNET); + + ola::acn::LLRPPDU pdu(ola::acn::VECTOR_LLRP_PROBE_REPLY, reply_llrp_header, &probe_reply); + m_root_sender.SendPDU(ola::acn::VECTOR_ROOT_LLRP, pdu, &transport); + OLA_DEBUG << "Sent PDU"; +} + +int main(int argc, char* argv[]) { + ola::InitLogging(ola::OLA_LOG_DEBUG, ola::OLA_LOG_STDERR); + + static struct option long_options[] = { + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + + int option_index = 0; + + while (1) { + int c = getopt_long(argc, argv, "ih", long_options, &option_index); + + if (c == -1) + break; + + switch (c) { + case 0: + break; + case 'h': + DisplayHelp(argv[0]); + return 0; + case '?': + break; + default: + break; + } + } + + ola::io::SelectServer ss; + + if (!m_socket.Init()) { + return false; + } + std::cout << "Init!" << std::endl; + + std::cout << "Using CID " << cid << std::endl; + + if (!m_socket.Bind(IPV4SocketAddress(IPV4Address::WildCard(), + ola::acn::LLRP_PORT))) { + return false; + } + std::cout << "Bind!" << std::endl; + + IPV4Address *addr = IPV4Address::FromString("239.255.250.133"); + + auto_ptr picker( + ola::network::InterfacePicker::NewPicker()); + if (!picker->ChooseInterface(&m_interface, m_preferred_ip)) { + OLA_INFO << "Failed to find an interface"; + return false; + } + + std::cout << "IF " << m_interface << std::endl; + + if (!m_socket.JoinMulticast(m_interface.ip_address, *addr)) { + OLA_WARN << "Failed to join multicast group " << addr; + } + + ola::acn::RootInflator root_inflator; + ola::acn::LLRPInflator llrp_inflator; + ola::acn::LLRPProbeRequestInflator llrp_probe_request_inflator; + llrp_probe_request_inflator.SetLLRPProbeRequestHandler( + ola::NewCallback(&HandleLLRPProbeRequest)); + + // setup all the inflators + root_inflator.AddInflator(&llrp_inflator); + llrp_inflator.AddInflator(&llrp_probe_request_inflator); + + IncomingUDPTransport m_incoming_udp_transport(&m_socket, &root_inflator); + m_socket.SetOnData(ola::NewCallback(&m_incoming_udp_transport, + &IncomingUDPTransport::Receive)); +// m_socket.SetOnData(ola::NewCallback(&CheckData)); + ss.AddReadDescriptor(&m_socket); + + std::cout << "Pre run!" << std::endl; + + ss.Run(); + + std::cout << "Run!" << std::endl; + + return 0; +} From f74347603903a10421c2c6a9224e63586dad44cc Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 9 Feb 2020 16:32:52 +0000 Subject: [PATCH 019/138] Use the correct MAC address in the responses --- tools/e133/llrp-receive-test.cpp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/tools/e133/llrp-receive-test.cpp b/tools/e133/llrp-receive-test.cpp index e6530e6530..e5817592dc 100644 --- a/tools/e133/llrp-receive-test.cpp +++ b/tools/e133/llrp-receive-test.cpp @@ -22,6 +22,7 @@ */ #include +#include #include #include #include @@ -41,6 +42,7 @@ #include "ola/acn/ACNPort.h" #include "ola/acn/CID.h" #include "ola/io/SelectServer.h" +#include "ola/network/Interface.h" #include "ola/network/InterfacePicker.h" #include "ola/network/IPV4Address.h" #include "ola/network/MACAddress.h" @@ -60,6 +62,7 @@ using ola::acn::LLRPHeader; using ola::acn::LLRPProbeReplyPDU; using ola::acn::OutgoingUDPTransport; using ola::acn::OutgoingUDPTransportImpl; +using ola::network::Interface; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::network::MACAddress; @@ -82,7 +85,8 @@ void DisplayHelp(const char *binary_name) { << std::endl; } - +auto_ptr picker( + ola::network::InterfacePicker::NewPicker()); ola::network::Interface m_interface; const std::string m_preferred_ip; ola::network::UDPSocket m_socket; @@ -92,6 +96,20 @@ ola::acn::PreamblePacker m_packer; ola::acn::CID cid = CID::Generate(); ola::acn::RootSender m_root_sender(cid, true); +bool CompareInterfaceMACs(Interface a, Interface b) { + return a.hw_address < b.hw_address; +} + +Interface FindLowestMAC() { + // TODO(Peter): Get some clarification on whether we only care about active + // interfaces, or any installed ones? + // TODO(Peter): Work out what to do here if running on localhost only? Return + // 00:00:00:00:00:00 + std::vector interfaces = picker->GetInterfaces(false); + std::vector::iterator result = std::min_element(interfaces.begin(), interfaces.end(), CompareInterfaceMACs); + return *result; +} + //void CheckData() { // std::cout << "Awaiting data..." << std::endl; // if (!m_recv_buffer) @@ -137,13 +155,11 @@ void HandleLLRPProbeRequest( ola::acn::LLRP_PORT); UID target_uid = UID(0x4321, 0x12345678); - MACAddress hardware_address; - MACAddress::FromString("01:23:45:67:89:ab", &hardware_address); LLRPProbeReplyPDU probe_reply( LLRPProbeReplyPDU::VECTOR_PROBE_REPLY_DATA, target_uid, - hardware_address, + FindLowestMAC().hw_address, LLRPProbeReplyPDU::LLRP_COMPONENT_TYPE_NON_RDMNET); ola::acn::LLRPPDU pdu(ola::acn::VECTOR_LLRP_PROBE_REPLY, reply_llrp_header, &probe_reply); @@ -197,8 +213,6 @@ int main(int argc, char* argv[]) { IPV4Address *addr = IPV4Address::FromString("239.255.250.133"); - auto_ptr picker( - ola::network::InterfacePicker::NewPicker()); if (!picker->ChooseInterface(&m_interface, m_preferred_ip)) { OLA_INFO << "Failed to find an interface"; return false; From 7e5f9352df85a41a5ae7b641e1957f3721cb2cca Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 9 Feb 2020 18:00:49 +0000 Subject: [PATCH 020/138] Fix a typo --- libs/acn/e131_transmit_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/acn/e131_transmit_test.cpp b/libs/acn/e131_transmit_test.cpp index 342d5c21c5..7ff99a268e 100644 --- a/libs/acn/e131_transmit_test.cpp +++ b/libs/acn/e131_transmit_test.cpp @@ -14,7 +14,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * e131_transmit_test.cpp - * The sends custom E1.31 packets in order to test the implementation of a + * This sends custom E1.31 packets in order to test the implementation of a * remote node. * Copyright (C) 2010 Simon Newton * From 4983aa97960762339935cd95b6e4824f972d7146 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 9 Feb 2020 18:37:35 +0000 Subject: [PATCH 021/138] Switch to our flags module and set the UID from the command line --- tools/e133/llrp-receive-test.cpp | 69 +++++++++----------------------- 1 file changed, 18 insertions(+), 51 deletions(-) diff --git a/tools/e133/llrp-receive-test.cpp b/tools/e133/llrp-receive-test.cpp index e5817592dc..ef7d6a9a5b 100644 --- a/tools/e133/llrp-receive-test.cpp +++ b/tools/e133/llrp-receive-test.cpp @@ -13,12 +13,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * e131_transmit_test.cpp - * The sends custom E1.31 packets in order to test the implementation of a - * remote node. - * Copyright (C) 2010 Simon Newton - * - * The remote node needs to be listening for Universe 1. + * llrp-receive-test.cpp + * Run a very simple E1.33 LLRP Responder. + * Copyright (C) 2020 Peter Newman */ #include @@ -41,6 +38,9 @@ #include "ola/Callback.h" #include "ola/acn/ACNPort.h" #include "ola/acn/CID.h" +#include "ola/base/Flags.h" +#include "ola/base/Init.h" +#include "ola/base/SysExits.h" #include "ola/io/SelectServer.h" #include "ola/network/Interface.h" #include "ola/network/InterfacePicker.h" @@ -68,22 +68,7 @@ using ola::network::IPV4SocketAddress; using ola::network::MACAddress; using ola::rdm::UID; -/* - * Display the help message - */ -void DisplayHelp(const char *binary_name) { - std::cout << "Usage: " << binary_name << " [--interactive]\n" - "\n" - "Run the E1.31 Transmit test. This test can run in one of two modes:\n" - " * interactive mode. This sends data to the multicast addresses\n" - " and a human gets to verify it.\n" - " * local mode (default). This starts a local E131Node and sends it data,\n" - " verifying against the expected output.\n" - "\n" - " -h, --help Display this help message and exit.\n" - " -i, --interactive Run in interactive mode.\n" - << std::endl; -} +DEFINE_string(uid, "7a70:00000001", "The UID of the responder."); auto_ptr picker( ola::network::InterfacePicker::NewPicker()); @@ -91,6 +76,7 @@ ola::network::Interface m_interface; const std::string m_preferred_ip; ola::network::UDPSocket m_socket; uint8_t *m_recv_buffer; +std::auto_ptr target_uid; ola::acn::PreamblePacker m_packer; ola::acn::CID cid = CID::Generate(); @@ -154,11 +140,9 @@ void HandleLLRPProbeRequest( *target_address, ola::acn::LLRP_PORT); - UID target_uid = UID(0x4321, 0x12345678); - LLRPProbeReplyPDU probe_reply( LLRPProbeReplyPDU::VECTOR_PROBE_REPLY_DATA, - target_uid, + *target_uid, FindLowestMAC().hw_address, LLRPProbeReplyPDU::LLRP_COMPONENT_TYPE_NON_RDMNET); @@ -168,32 +152,15 @@ void HandleLLRPProbeRequest( } int main(int argc, char* argv[]) { - ola::InitLogging(ola::OLA_LOG_DEBUG, ola::OLA_LOG_STDERR); - - static struct option long_options[] = { - {"help", no_argument, 0, 'h'}, - {0, 0, 0, 0} - }; - - int option_index = 0; - - while (1) { - int c = getopt_long(argc, argv, "ih", long_options, &option_index); - - if (c == -1) - break; - - switch (c) { - case 0: - break; - case 'h': - DisplayHelp(argv[0]); - return 0; - case '?': - break; - default: - break; - } + ola::AppInit(&argc, argv, "[options]", "Run a very simple E1.33 LLRP Responder."); + + target_uid.reset(UID::FromString(FLAGS_uid)); + if (!target_uid.get()) { + OLA_WARN << "Invalid UID: " << FLAGS_uid; + ola::DisplayUsage(); + exit(ola::EXIT_USAGE); + } else { + OLA_INFO << "Started LLRP Responder with UID " << *target_uid; } ola::io::SelectServer ss; From dc06b8ae5f60c361947d2bea250103d64081dc0e Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 9 Feb 2020 23:01:12 +0000 Subject: [PATCH 022/138] Add the ability to make a UID set from binary data --- common/rdm/UIDTest.cpp | 43 ++++++++++++++++++++++++++++++++++++++++ include/ola/rdm/UIDSet.h | 15 ++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/common/rdm/UIDTest.cpp b/common/rdm/UIDTest.cpp index e02dfd0751..685df3adf5 100644 --- a/common/rdm/UIDTest.cpp +++ b/common/rdm/UIDTest.cpp @@ -245,6 +245,49 @@ void UIDTest::testUIDSet() { uint8_t expected[] = {0, 1, 0, 0, 0, 2, 0, 2, 0, 0, 0, 10, 0, 3, 0, 0, 0, 4}; OLA_ASSERT_DATA_EQUALS(expected, sizeof(expected), buffer, buffer_size); + + // Creating UIDSets from binary data + uint8_t empty[] = {}; + unsigned int data_size = sizeof(empty); + UIDSet set5(empty, &data_size); + UIDSet empty_set = UIDSet(); + OLA_ASSERT_EQ(set5, empty_set); + + uint8_t raw_short[] = {0, 1}; + data_size = sizeof(raw_short); + UIDSet set6(raw_short, &data_size); + OLA_ASSERT_EQ(set6, empty_set); + + UIDSet set7; + set7.AddUID(UID(1, 2)); + uint8_t raw_one[] = {0, 1, 0, 0, 0, 2}; + data_size = sizeof(raw_one); + UIDSet set8(raw_one, &data_size); + OLA_ASSERT_EQ(6u, data_size); + OLA_ASSERT_EQ(set7, set8); + + uint8_t raw_one_extra[] = {0, 1, 0, 0, 0, 2, 3, 4}; + data_size = sizeof(raw_one_extra); + UIDSet set9(raw_one_extra, &data_size); + OLA_ASSERT_EQ(6u, data_size); + OLA_ASSERT_EQ(set7, set9); + + set7.AddUID(UID(2, 10)); + set7.AddUID(UID(3, 4)); + + uint8_t raw_three[] = + {0, 1, 0, 0, 0, 2, 0, 2, 0, 0, 0, 10, 0, 3, 0, 0, 0, 4}; + data_size = sizeof(raw_three); + UIDSet set10(raw_three, &data_size); + OLA_ASSERT_EQ(18u, data_size); + OLA_ASSERT_EQ(set7, set10); + + uint8_t raw_three_extra[] = + {0, 1, 0, 0, 0, 2, 0, 2, 0, 0, 0, 10, 0, 3, 0, 0, 0, 4, 5, 6}; + data_size = sizeof(raw_three_extra); + UIDSet set11(raw_three_extra, &data_size); + OLA_ASSERT_EQ(18u, data_size); + OLA_ASSERT_EQ(set7, set11); } diff --git a/include/ola/rdm/UIDSet.h b/include/ola/rdm/UIDSet.h index 40ad0a0547..308cb2a68f 100644 --- a/include/ola/rdm/UIDSet.h +++ b/include/ola/rdm/UIDSet.h @@ -65,6 +65,21 @@ class UIDSet { m_uids(other.m_uids) { } + /** + * @brief Construct a new UIDSet from binary data. + * @param data a pointer to the memory containing the UIDSet data. The data + * should be most significant byte first. + * @param length is the length of the data you wish to retrieve + */ + explicit UIDSet(const uint8_t *data, unsigned int *length) { + unsigned int used_length = 0; + while ((*length - used_length) >= UID::LENGTH) { + m_uids.insert(UID(data + used_length)); + used_length += UID::LENGTH; + } + *length = used_length; + } + /** * @brief Assignment operator */ From f2343ce127c43a395ffb5dec1457bc3165b02b6a Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 9 Feb 2020 23:08:23 +0000 Subject: [PATCH 023/138] Pass all the LLRPProbeRequest info across in the callback and act on more of it --- libs/acn/LLRPProbeRequestInflator.cpp | 12 ++++++------ libs/acn/LLRPProbeRequestInflator.h | 20 +++++++++++++++----- tools/e133/llrp-receive-test.cpp | 24 +++++++++++++++++++++--- 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/libs/acn/LLRPProbeRequestInflator.cpp b/libs/acn/LLRPProbeRequestInflator.cpp index cbc2fff04d..adf7d63fdd 100644 --- a/libs/acn/LLRPProbeRequestInflator.cpp +++ b/libs/acn/LLRPProbeRequestInflator.cpp @@ -101,15 +101,15 @@ bool LLRPProbeRequestInflator::HandlePDUData(uint32_t vector, OLA_DEBUG << "Probe from " << UID(pdu_data.lower_uid) << " to " << UID(pdu_data.upper_uid); -// string rdm_message(reinterpret_cast(&data[0]), pdu_len); + LLRPProbeRequest request(UID(pdu_data.lower_uid), UID(pdu_data.upper_uid)); + request.client_tcp_connection_inactive = (pdu_data.filter & LLRPProbeRequestPDU::FILTER_CLIENT_TCP_CONNECTION_INACTIVE); + request.brokers_only = (pdu_data.filter & LLRPProbeRequestPDU::FILTER_BROKERS_ONLY); + unsigned int known_uids_used_size = known_uids_size; + request.known_uids = UIDSet(pdu_data.known_uids, &known_uids_used_size); if (m_llrp_probe_request_handler.get()) { m_llrp_probe_request_handler->Run(&headers, - UID(pdu_data.lower_uid), - UID(pdu_data.upper_uid) -//, -// UIDSet() -); + request); } else { OLA_WARN << "No LLRP Probe Request handler defined!"; } diff --git a/libs/acn/LLRPProbeRequestInflator.h b/libs/acn/LLRPProbeRequestInflator.h index 1d63b84e9f..7cb4b49302 100644 --- a/libs/acn/LLRPProbeRequestInflator.h +++ b/libs/acn/LLRPProbeRequestInflator.h @@ -34,13 +34,23 @@ class LLRPProbeRequestInflator: public BaseInflator { friend class LLRPProbeRequestInflatorTest; public: + struct LLRPProbeRequest { + LLRPProbeRequest(const ola::rdm::UID &_lower, const ola::rdm::UID &_upper) + : lower(_lower), + upper(_upper) { + } + ola::rdm::UID lower; + ola::rdm::UID upper; + bool client_tcp_connection_inactive; + bool brokers_only; + ola::rdm::UIDSet known_uids; + }; + + // These are pointers so the callers don't have to pull in all the headers. - typedef ola::Callback3 LLRPProbeRequestHandler; LLRPProbeRequestInflator(); diff --git a/tools/e133/llrp-receive-test.cpp b/tools/e133/llrp-receive-test.cpp index ef7d6a9a5b..33446730d9 100644 --- a/tools/e133/llrp-receive-test.cpp +++ b/tools/e133/llrp-receive-test.cpp @@ -60,6 +60,7 @@ using ola::acn::CID; using ola::acn::IncomingUDPTransport; using ola::acn::LLRPHeader; using ola::acn::LLRPProbeReplyPDU; +using ola::acn::LLRPProbeRequestInflator; using ola::acn::OutgoingUDPTransport; using ola::acn::OutgoingUDPTransportImpl; using ola::network::Interface; @@ -121,9 +122,23 @@ Interface FindLowestMAC() { void HandleLLRPProbeRequest( const ola::acn::HeaderSet *headers, - const ola::rdm::UID &lower_uid, - const ola::rdm::UID &upper_uid) { - OLA_DEBUG << "Handling probe from " << lower_uid << " to " << upper_uid; + const LLRPProbeRequestInflator::LLRPProbeRequest &request) { + OLA_DEBUG << "Potentially handling probe from " << request.lower << " to " + << request.upper; + + if ((*target_uid < request.lower) || (*target_uid > request.upper)) { + OLA_INFO << "Ignoring probe request as we are not in the target UID range"; + return; + } + + OLA_DEBUG << "Known UIDs are: " << request.known_uids; + + if (request.known_uids.Contains(*target_uid)) { + OLA_INFO << "Ignoring probe request as we are already in the known UID list"; + return; + } + + // TODO(Peter): Check the filter bits! const ola::acn::RootHeader root_header = headers->GetRootHeader(); const ola::acn::LLRPHeader llrp_header = headers->GetLLRPHeader(); @@ -147,6 +162,9 @@ void HandleLLRPProbeRequest( LLRPProbeReplyPDU::LLRP_COMPONENT_TYPE_NON_RDMNET); ola::acn::LLRPPDU pdu(ola::acn::VECTOR_LLRP_PROBE_REPLY, reply_llrp_header, &probe_reply); + + // TODO(Peter): Delay sending by 0 to LLRP_MAX_BACKOFF! + m_root_sender.SendPDU(ola::acn::VECTOR_ROOT_LLRP, pdu, &transport); OLA_DEBUG << "Sent PDU"; } From 95837932508cb6d2fb08cd784cf3528120f251a3 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 10 Feb 2020 21:18:07 +0000 Subject: [PATCH 024/138] Fix a typo --- tools/e133/E133Device.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/e133/E133Device.cpp b/tools/e133/E133Device.cpp index c9350d61f6..ca2a4a69f9 100644 --- a/tools/e133/E133Device.cpp +++ b/tools/e133/E133Device.cpp @@ -205,8 +205,7 @@ void E133Device::EndpointRequest( const string &raw_request) { IPV4SocketAddress target = transport_header->Source(); uint16_t endpoint_id = e133_header->Endpoint(); - OLA_INFO << "Got request for to endpoint " << endpoint_id - << " from " << target; + OLA_INFO << "Got request for endpoint " << endpoint_id << " from " << target; E133EndpointInterface *endpoint = NULL; if (endpoint_id) From 1955638b07cb996447b8ba3c7274ce79514d244e Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 11 Feb 2020 00:08:26 +0000 Subject: [PATCH 025/138] Allow the RDMInflator to be used with both native E1.33 and LLRP RDM messages --- libs/acn/RDMInflator.cpp | 25 +++++++++++++++++++------ libs/acn/RDMInflator.h | 12 ++++++++++-- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/libs/acn/RDMInflator.cpp b/libs/acn/RDMInflator.cpp index a18f634e01..a4e32166e1 100644 --- a/libs/acn/RDMInflator.cpp +++ b/libs/acn/RDMInflator.cpp @@ -32,13 +32,14 @@ using std::string; /** * Create a new RDM inflator */ -RDMInflator::RDMInflator() - : BaseInflator(PDU::ONE_BYTE) { +RDMInflator::RDMInflator(unsigned int vector) + : BaseInflator(PDU::ONE_BYTE), + m_vector(vector) { } /** - * Set a RDMHandler to run when receiving a RDM message. - * @param handler the callback to invoke when there is rdm data for this + * Set an RDMMessageHandler to run when receiving a RDM message. + * @param handler the callback to invoke when there is RDM data for this * universe. */ void RDMInflator::SetRDMHandler(RDMMessageHandler *handler) { @@ -46,6 +47,16 @@ void RDMInflator::SetRDMHandler(RDMMessageHandler *handler) { } +/** + * Set a GenericRDMHandler to run when receiving a RDM message. + * @param handler the callback to invoke when there is RDM data for this + * universe. + */ +void RDMInflator::SetGenericRDMHandler(GenericRDMMessageHandler *handler) { + m_generic_rdm_handler.reset(handler); +} + + /* * Decode the RDM 'header', which is 0 bytes in length. * @param headers the HeaderSet to add to @@ -76,11 +87,13 @@ bool RDMInflator::HandlePDUData(uint32_t vector, string rdm_message(reinterpret_cast(&data[0]), pdu_len); - E133Header e133_header = headers.GetE133Header(); - if (m_rdm_handler.get()) { + E133Header e133_header = headers.GetE133Header(); + m_rdm_handler->Run(&headers.GetTransportHeader(), &e133_header, rdm_message); + } else if (m_generic_rdm_handler.get()) { + m_generic_rdm_handler->Run(&headers, rdm_message); } else { OLA_WARN << "No RDM handler defined!"; } diff --git a/libs/acn/RDMInflator.h b/libs/acn/RDMInflator.h index 36ccf48930..4c37cf6c0c 100644 --- a/libs/acn/RDMInflator.h +++ b/libs/acn/RDMInflator.h @@ -41,12 +41,18 @@ class RDMInflator: public BaseInflator { const std::string& // rdm data > RDMMessageHandler; - RDMInflator(); + typedef ola::Callback2 GenericRDMMessageHandler; + + RDMInflator(unsigned int vector = ola::acn::VECTOR_FRAMING_RDMNET); ~RDMInflator() {} - uint32_t Id() const { return ola::acn::VECTOR_FRAMING_RDMNET; } + uint32_t Id() const { return m_vector; } void SetRDMHandler(RDMMessageHandler *handler); + void SetGenericRDMHandler(GenericRDMMessageHandler *handler); static const unsigned int VECTOR_RDMNET_DATA = 0xcc; @@ -65,6 +71,8 @@ class RDMInflator: public BaseInflator { private: std::auto_ptr m_rdm_handler; + std::auto_ptr m_generic_rdm_handler; + unsigned int m_vector; }; } // namespace acn } // namespace ola From 32ecc529a99a243c79afc85e5174bf6e8507ca3b Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 11 Feb 2020 00:53:01 +0000 Subject: [PATCH 026/138] Add the ability to pack an RDMPDU --- libs/acn/RDMPDU.cpp | 15 ++++++ libs/acn/RDMPDU.h | 24 +++++++++- libs/acn/RDMPDUTest.cpp | 103 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 1 deletion(-) diff --git a/libs/acn/RDMPDU.cpp b/libs/acn/RDMPDU.cpp index 7b7b61f6c8..cab7d20a5c 100644 --- a/libs/acn/RDMPDU.cpp +++ b/libs/acn/RDMPDU.cpp @@ -29,6 +29,21 @@ namespace acn { using ola::io::OutputStream; using ola::network::HostToNetwork; +unsigned int RDMPDU::DataSize() const { + return static_cast(m_command.size()); +} + +bool RDMPDU::PackData(uint8_t *data, unsigned int *length) const { + *length = static_cast(m_command.size()); + memcpy(data, reinterpret_cast(m_command.data()), *length); + return true; +} + +void RDMPDU::PackData(ola::io::OutputStream *stream) const { + stream->Write(reinterpret_cast(m_command.data()), + static_cast(m_command.size())); +} + void RDMPDU::PrependPDU(ola::io::IOStack *stack) { uint8_t vector = HostToNetwork(ola::rdm::START_CODE); stack->Write(reinterpret_cast(&vector), sizeof(vector)); diff --git a/libs/acn/RDMPDU.h b/libs/acn/RDMPDU.h index 8d36e0ced7..c51d9a140f 100644 --- a/libs/acn/RDMPDU.h +++ b/libs/acn/RDMPDU.h @@ -21,16 +21,38 @@ #ifndef LIBS_ACN_RDMPDU_H_ #define LIBS_ACN_RDMPDU_H_ +#include +#include #include +#include #include "libs/acn/PDU.h" namespace ola { namespace acn { -class RDMPDU : private PDU { +class RDMPDU : public PDU { public: + explicit RDMPDU(const ola::io::ByteString &command): + PDU(ola::rdm::START_CODE, ONE_BYTE, true), + m_command(command) {} + + unsigned int HeaderSize() const { return 0; } + bool PackHeader(OLA_UNUSED uint8_t *data, + unsigned int *length) const { + *length = 0; + return true; + } + void PackHeader(OLA_UNUSED ola::io::OutputStream *stream) const {} + + unsigned int DataSize() const; + bool PackData(uint8_t *data, unsigned int *length) const; + void PackData(ola::io::OutputStream *stream) const; + static void PrependPDU(ola::io::IOStack *stack); + + private: + const ola::io::ByteString m_command; }; } // namespace acn } // namespace ola diff --git a/libs/acn/RDMPDUTest.cpp b/libs/acn/RDMPDUTest.cpp index 4c6ce89df2..ff6489d0fb 100644 --- a/libs/acn/RDMPDUTest.cpp +++ b/libs/acn/RDMPDUTest.cpp @@ -23,6 +23,8 @@ #include #include "ola/Logging.h" +#include "ola/io/ByteString.h" +#include "ola/io/IOQueue.h" #include "ola/io/IOStack.h" #include "ola/network/NetworkUtils.h" #include "ola/testing/TestUtils.h" @@ -32,24 +34,125 @@ namespace ola { namespace acn { +using ola::io::ByteString; +using ola::io::IOQueue; using ola::io::IOStack; +using ola::io::OutputStream; +using ola::network::HostToNetwork; class RDMPDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RDMPDUTest); + CPPUNIT_TEST(testSimpleRDMPDU); + CPPUNIT_TEST(testSimpleRDMPDUToOutputStream); CPPUNIT_TEST(testPrepend); CPPUNIT_TEST_SUITE_END(); public: + void testSimpleRDMPDU(); + void testSimpleRDMPDUToOutputStream(); void testPrepend(); private: static const unsigned int TEST_VECTOR; + static const uint8_t EXPECTED_GET_RESPONSE_BUFFER[]; }; CPPUNIT_TEST_SUITE_REGISTRATION(RDMPDUTest); const unsigned int RDMPDUTest::TEST_VECTOR = 0xcc; +const uint8_t RDMPDUTest::EXPECTED_GET_RESPONSE_BUFFER[] = { + 1, 28, // sub code & length + 0, 3, 0, 0, 0, 4, // dst uid + 0, 1, 0, 0, 0, 2, // src uid + 0, 0, 0, 0, 10, // transaction, port id, msg count & sub device + 0x21, 1, 40, 4, // command, param id, param data length + 0x5a, 0x5a, 0x5a, 0x5a, // param data + 0x02, 0xb3 // checksum +}; + +/* + * Test that packing an RDMPDU works. + */ +void RDMPDUTest::testSimpleRDMPDU() { + ByteString empty; + RDMPDU empty_pdu(empty); + + OLA_ASSERT_EQ(0u, empty_pdu.HeaderSize()); + OLA_ASSERT_EQ(0u, empty_pdu.DataSize()); + OLA_ASSERT_EQ(4u, empty_pdu.Size()); + + ByteString response(EXPECTED_GET_RESPONSE_BUFFER, + sizeof(EXPECTED_GET_RESPONSE_BUFFER)); + RDMPDU pdu(response); + + OLA_ASSERT_EQ(0u, pdu.HeaderSize()); + OLA_ASSERT_EQ(29u, pdu.DataSize()); + OLA_ASSERT_EQ(33u, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + + // spot check the data + OLA_ASSERT_EQ((uint8_t) 0xf0, data[0]); + // bytes_used is technically data[1] and data[2] if > 255 + OLA_ASSERT_EQ((uint8_t) bytes_used, data[2]); + OLA_ASSERT_EQ(HostToNetwork((uint8_t) TEST_VECTOR), data[3]); + + // test undersized buffer + bytes_used = size - 1; + OLA_ASSERT_FALSE(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(0u, bytes_used); + + // test oversized buffer + bytes_used = size + 1; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + delete[] data; +} + + +/* + * Test that writing to an output stream works. + */ +void RDMPDUTest::testSimpleRDMPDUToOutputStream() { + ByteString response(EXPECTED_GET_RESPONSE_BUFFER, + sizeof(EXPECTED_GET_RESPONSE_BUFFER)); + RDMPDU pdu(response); + + OLA_ASSERT_EQ(0u, pdu.HeaderSize()); + OLA_ASSERT_EQ(29u, pdu.DataSize()); + OLA_ASSERT_EQ(33u, pdu.Size()); + + IOQueue output; + OutputStream stream(&output); + pdu.Write(&stream); + OLA_ASSERT_EQ(33u, output.Size()); + + uint8_t *pdu_data = new uint8_t[output.Size()]; + unsigned int pdu_size = output.Peek(pdu_data, output.Size()); + OLA_ASSERT_EQ(output.Size(), pdu_size); + + uint8_t EXPECTED[] = { + 0xf0, 0x00, 0x21, + 0xcc, + 1, 28, // sub code & length + 0, 3, 0, 0, 0, 4, // dst uid + 0, 1, 0, 0, 0, 2, // src uid + 0, 0, 0, 0, 10, // transaction, port id, msg count & sub device + 0x21, 1, 40, 4, // command, param id, param data length + 0x5a, 0x5a, 0x5a, 0x5a, // param data + 0x02, 0xb3 // checksum + }; + OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), pdu_data, pdu_size); + output.Pop(output.Size()); + delete[] pdu_data; +} + + void RDMPDUTest::testPrepend() { IOStack stack; RDMPDU::PrependPDU(&stack); From 04697246fce5dc48d4489eac8e43c90fe5920353 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 11 Feb 2020 00:59:34 +0000 Subject: [PATCH 027/138] Initial version of an LLRP RDM responder --- tools/e133/llrp-receive-test.cpp | 129 ++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 44 deletions(-) diff --git a/tools/e133/llrp-receive-test.cpp b/tools/e133/llrp-receive-test.cpp index 33446730d9..bb9a8921d4 100644 --- a/tools/e133/llrp-receive-test.cpp +++ b/tools/e133/llrp-receive-test.cpp @@ -23,6 +23,26 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "libs/acn/HeaderSet.h" #include "libs/acn/LLRPHeader.h" #include "libs/acn/LLRPInflator.h" @@ -30,27 +50,13 @@ #include "libs/acn/LLRPProbeReplyPDU.h" #include "libs/acn/LLRPProbeRequestInflator.h" #include "libs/acn/PreamblePacker.h" +#include "libs/acn/RDMInflator.h" +#include "libs/acn/RDMPDU.h" #include "libs/acn/RootHeader.h" #include "libs/acn/RootInflator.h" #include "libs/acn/RootSender.h" #include "libs/acn/Transport.h" #include "libs/acn/UDPTransport.h" -#include "ola/Callback.h" -#include "ola/acn/ACNPort.h" -#include "ola/acn/CID.h" -#include "ola/base/Flags.h" -#include "ola/base/Init.h" -#include "ola/base/SysExits.h" -#include "ola/io/SelectServer.h" -#include "ola/network/Interface.h" -#include "ola/network/InterfacePicker.h" -#include "ola/network/IPV4Address.h" -#include "ola/network/MACAddress.h" -#include "ola/network/SocketAddress.h" -#include "ola/network/Socket.h" -#include "ola/rdm/UID.h" -#include "ola/DmxBuffer.h" -#include "ola/Logging.h" using std::string; using std::vector; @@ -78,6 +84,7 @@ const std::string m_preferred_ip; ola::network::UDPSocket m_socket; uint8_t *m_recv_buffer; std::auto_ptr target_uid; +std::auto_ptr dummy_responder; ola::acn::PreamblePacker m_packer; ola::acn::CID cid = CID::Generate(); @@ -97,29 +104,6 @@ Interface FindLowestMAC() { return *result; } -//void CheckData() { -// std::cout << "Awaiting data..." << std::endl; -// if (!m_recv_buffer) -// m_recv_buffer = new uint8_t[512]; -// -// ssize_t size = 512; -// ola::network::IPV4SocketAddress source; - -// if (!m_socket.RecvFrom(m_recv_buffer, &size, &source)) -// return; - -// std::cout << "Got " << size << " bytes" << std::endl; - -// ola::FormatData(&std::cout, m_recv_buffer, size); - -// ola::acn::HeaderSet header_set; -// if (root_inflator.InflatePDUBlock(&header_set, &m_recv_buffer[16], size - 16)) { -// std::cout << "Inflated" << std::endl; -// } else { -// std::cout << "Failed to inflate" << std::endl; -// } -//} - void HandleLLRPProbeRequest( const ola::acn::HeaderSet *headers, const LLRPProbeRequestInflator::LLRPProbeRequest &request) { @@ -169,6 +153,62 @@ void HandleLLRPProbeRequest( OLA_DEBUG << "Sent PDU"; } +void RDMRequestComplete( + ola::acn::HeaderSet headers, + ola::rdm::RDMReply *reply) { + OLA_INFO << "Got RDM reply to send"; + OLA_DEBUG << reply->ToString(); + + const ola::acn::RootHeader root_header = headers.GetRootHeader(); + const ola::acn::LLRPHeader llrp_header = headers.GetLLRPHeader(); + + OLA_DEBUG << "Source CID: " << root_header.GetCid(); + OLA_DEBUG << "TN: " << llrp_header.TransactionNumber(); + + ola::acn::LLRPHeader reply_llrp_header = LLRPHeader(root_header.GetCid(), llrp_header.TransactionNumber()); + + IPV4Address *target_address = IPV4Address::FromString("239.255.250.134"); + + OutgoingUDPTransportImpl transport_impl = OutgoingUDPTransportImpl(&m_socket, &m_packer); + OutgoingUDPTransport transport(&transport_impl, + *target_address, + ola::acn::LLRP_PORT); + + ola::io::ByteString raw_reply; + ola::rdm::RDMCommandSerializer::Pack(*reply->Response(), &raw_reply); + + ola::acn::RDMPDU rdm_reply(raw_reply); + + ola::acn::LLRPPDU pdu(ola::acn::VECTOR_LLRP_RDM_CMD, reply_llrp_header, &rdm_reply); + + m_root_sender.SendPDU(ola::acn::VECTOR_ROOT_LLRP, pdu, &transport); + OLA_DEBUG << "Sent RDM PDU"; +} + +void HandleRDM( + const ola::acn::HeaderSet *headers, + const string &raw_request) { + IPV4SocketAddress target = headers->GetTransportHeader().Source(); + OLA_INFO << "Got RDM request from " << target; + + // attempt to unpack as a request + ola::rdm::RDMRequest *request = ola::rdm::RDMRequest::InflateFromData( + reinterpret_cast(raw_request.data()), + raw_request.size()); + + if (!request) { + OLA_WARN << "Failed to unpack LLRP RDM message, ignoring request."; + return; + } else { + OLA_DEBUG << "Got RDM request " << request->ToString(); + } + + dummy_responder->SendRDMRequest( + request, + ola::NewSingleCallback(&RDMRequestComplete, + *headers)); +} + int main(int argc, char* argv[]) { ola::AppInit(&argc, argv, "[options]", "Run a very simple E1.33 LLRP Responder."); @@ -181,6 +221,8 @@ int main(int argc, char* argv[]) { OLA_INFO << "Started LLRP Responder with UID " << *target_uid; } + dummy_responder.reset(new ola::rdm::DummyResponder(*target_uid)); + ola::io::SelectServer ss; if (!m_socket.Init()) { @@ -214,22 +256,21 @@ int main(int argc, char* argv[]) { ola::acn::LLRPProbeRequestInflator llrp_probe_request_inflator; llrp_probe_request_inflator.SetLLRPProbeRequestHandler( ola::NewCallback(&HandleLLRPProbeRequest)); + ola::acn::RDMInflator llrp_rdm_inflator(ola::acn::VECTOR_LLRP_RDM_CMD); + llrp_rdm_inflator.SetGenericRDMHandler( + ola::NewCallback(&HandleRDM)); // setup all the inflators root_inflator.AddInflator(&llrp_inflator); llrp_inflator.AddInflator(&llrp_probe_request_inflator); + llrp_inflator.AddInflator(&llrp_rdm_inflator); IncomingUDPTransport m_incoming_udp_transport(&m_socket, &root_inflator); m_socket.SetOnData(ola::NewCallback(&m_incoming_udp_transport, &IncomingUDPTransport::Receive)); -// m_socket.SetOnData(ola::NewCallback(&CheckData)); ss.AddReadDescriptor(&m_socket); - std::cout << "Pre run!" << std::endl; - ss.Run(); - std::cout << "Run!" << std::endl; - return 0; } From a150d7e263d3e55c3403af9325e37b6ef04644ad Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 11 Feb 2020 16:57:48 +0000 Subject: [PATCH 028/138] Add the LLRP Broadcast CID --- include/ola/acn/CID.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/ola/acn/CID.h b/include/ola/acn/CID.h index 3b98d127d7..295b0786c2 100644 --- a/include/ola/acn/CID.h +++ b/include/ola/acn/CID.h @@ -141,6 +141,10 @@ class CID { */ static CID FromString(const std::string &cid); + static CID LLRPBroadcastCID() { + return FromString("FBAD822C-BD0C-4D4C-BDC8-7EABEBC85AFF"); + } + private: class CIDImpl *m_impl; From b0662a0eaf3fb3c10d9be0945f6fa731793be414 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 11 Feb 2020 17:01:48 +0000 Subject: [PATCH 029/138] Fix some lint issues and follow more of the standard --- tools/e133/llrp-receive-test.cpp | 74 +++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/tools/e133/llrp-receive-test.cpp b/tools/e133/llrp-receive-test.cpp index bb9a8921d4..f669551df2 100644 --- a/tools/e133/llrp-receive-test.cpp +++ b/tools/e133/llrp-receive-test.cpp @@ -18,11 +18,6 @@ * Copyright (C) 2020 Peter Newman */ -#include -#include -#include -#include -#include #include #include #include @@ -39,10 +34,17 @@ #include #include #include +#include #include #include #include #include + +#include +#include +#include +#include + #include "libs/acn/HeaderSet.h" #include "libs/acn/LLRPHeader.h" #include "libs/acn/LLRPInflator.h" @@ -69,6 +71,7 @@ using ola::acn::LLRPProbeReplyPDU; using ola::acn::LLRPProbeRequestInflator; using ola::acn::OutgoingUDPTransport; using ola::acn::OutgoingUDPTransportImpl; +using ola::acn::RootHeader; using ola::network::Interface; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; @@ -87,9 +90,14 @@ std::auto_ptr target_uid; std::auto_ptr dummy_responder; ola::acn::PreamblePacker m_packer; -ola::acn::CID cid = CID::Generate(); +CID cid = CID::Generate(); ola::acn::RootSender m_root_sender(cid, true); +bool CheckCIDAddressedToUs(const CID destination_cid) { + return (destination_cid == CID::LLRPBroadcastCID() || + destination_cid == cid); +} + bool CompareInterfaceMACs(Interface a, Interface b) { return a.hw_address < b.hw_address; } @@ -99,8 +107,10 @@ Interface FindLowestMAC() { // interfaces, or any installed ones? // TODO(Peter): Work out what to do here if running on localhost only? Return // 00:00:00:00:00:00 - std::vector interfaces = picker->GetInterfaces(false); - std::vector::iterator result = std::min_element(interfaces.begin(), interfaces.end(), CompareInterfaceMACs); + vector interfaces = picker->GetInterfaces(false); + vector::iterator result = std::min_element(interfaces.begin(), + interfaces.end(), + CompareInterfaceMACs); return *result; } @@ -110,6 +120,12 @@ void HandleLLRPProbeRequest( OLA_DEBUG << "Potentially handling probe from " << request.lower << " to " << request.upper; + const LLRPHeader llrp_header = headers->GetLLRPHeader(); + if (!CheckCIDAddressedToUs(llrp_header.DestinationCid())) { + OLA_INFO << "Ignoring probe request as it's not addressed to us or the LLRP broadcast CID"; + return; + } + if ((*target_uid < request.lower) || (*target_uid > request.upper)) { OLA_INFO << "Ignoring probe request as we are not in the target UID range"; return; @@ -118,19 +134,20 @@ void HandleLLRPProbeRequest( OLA_DEBUG << "Known UIDs are: " << request.known_uids; if (request.known_uids.Contains(*target_uid)) { - OLA_INFO << "Ignoring probe request as we are already in the known UID list"; + OLA_INFO << "Ignoring probe request as we are already in the known UID " + << "list"; return; } // TODO(Peter): Check the filter bits! - const ola::acn::RootHeader root_header = headers->GetRootHeader(); - const ola::acn::LLRPHeader llrp_header = headers->GetLLRPHeader(); + const RootHeader root_header = headers->GetRootHeader(); OLA_DEBUG << "Source CID: " << root_header.GetCid(); OLA_DEBUG << "TN: " << llrp_header.TransactionNumber(); - ola::acn::LLRPHeader reply_llrp_header = LLRPHeader(root_header.GetCid(), llrp_header.TransactionNumber()); + LLRPHeader reply_llrp_header = LLRPHeader(root_header.GetCid(), + llrp_header.TransactionNumber()); IPV4Address *target_address = IPV4Address::FromString("239.255.250.134"); @@ -159,13 +176,20 @@ void RDMRequestComplete( OLA_INFO << "Got RDM reply to send"; OLA_DEBUG << reply->ToString(); - const ola::acn::RootHeader root_header = headers.GetRootHeader(); - const ola::acn::LLRPHeader llrp_header = headers.GetLLRPHeader(); +// TODO(Peter): Do the below +//LLRP Targets shall not return RDM responses with response types of ACK_TIMER or +//ACK_OVERFLOW. LLRP Targets shall respond with a NACK with reason code +//NR_ACTION_NOT_SUPPORTED to any RDM request that cannot be answered without starting +//an ACK_TIMER or ACK_OVERFLOW sequence. + + const RootHeader root_header = headers.GetRootHeader(); + const LLRPHeader llrp_header = headers.GetLLRPHeader(); OLA_DEBUG << "Source CID: " << root_header.GetCid(); OLA_DEBUG << "TN: " << llrp_header.TransactionNumber(); - ola::acn::LLRPHeader reply_llrp_header = LLRPHeader(root_header.GetCid(), llrp_header.TransactionNumber()); + LLRPHeader reply_llrp_header = LLRPHeader(root_header.GetCid(), + llrp_header.TransactionNumber()); IPV4Address *target_address = IPV4Address::FromString("239.255.250.134"); @@ -191,6 +215,11 @@ void HandleRDM( IPV4SocketAddress target = headers->GetTransportHeader().Source(); OLA_INFO << "Got RDM request from " << target; + if (!CheckCIDAddressedToUs(headers->GetLLRPHeader().DestinationCid())) { + OLA_INFO << "Ignoring probe request as it's not addressed to us or the LLRP broadcast CID"; + return; + } + // attempt to unpack as a request ola::rdm::RDMRequest *request = ola::rdm::RDMRequest::InflateFromData( reinterpret_cast(raw_request.data()), @@ -203,6 +232,20 @@ void HandleRDM( OLA_DEBUG << "Got RDM request " << request->ToString(); } + if (!request->DestinationUID().DirectedToUID(*target_uid)) { + OLA_WARN << "Destination UID " << request->DestinationUID() << " was not " + << "directed to us"; + return; + } + + if (!((request->SubDevice() == ola::rdm::ROOT_RDM_DEVICE) || + (request->SubDevice() == ola::rdm::ALL_RDM_SUBDEVICES))) { + OLA_WARN << "Subdevice " << request->SubDevice() << " was not the root or " + << "broadcast subdevice"; + // TODO(Peter): NACK with NR_SUB_DEVICE_OUT_OF_RANGE + return; + } + dummy_responder->SendRDMRequest( request, ola::NewSingleCallback(&RDMRequestComplete, @@ -249,6 +292,7 @@ int main(int argc, char* argv[]) { if (!m_socket.JoinMulticast(m_interface.ip_address, *addr)) { OLA_WARN << "Failed to join multicast group " << addr; + return false; } ola::acn::RootInflator root_inflator; From 280d3f6d02d4803997a67dd977a458c2f0c2615b Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 17 Feb 2020 02:52:32 +0000 Subject: [PATCH 030/138] Ensure we work on the same host as the manager --- tools/e133/llrp-receive-test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/e133/llrp-receive-test.cpp b/tools/e133/llrp-receive-test.cpp index f669551df2..8edbf4f3a3 100644 --- a/tools/e133/llrp-receive-test.cpp +++ b/tools/e133/llrp-receive-test.cpp @@ -290,7 +290,7 @@ int main(int argc, char* argv[]) { std::cout << "IF " << m_interface << std::endl; - if (!m_socket.JoinMulticast(m_interface.ip_address, *addr)) { + if (!m_socket.JoinMulticast(m_interface.ip_address, *addr, true)) { OLA_WARN << "Failed to join multicast group " << addr; return false; } From 324b4ec341d20d121c57e61afc6d272a6951d0c1 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 17 Feb 2020 16:20:57 +0000 Subject: [PATCH 031/138] Add a helper method to convert an RDMResponse to a NACKing RDMResponse --- common/rdm/RDMCommand.cpp | 16 ++++++++++++++++ common/rdm/RDMCommandTest.cpp | 27 +++++++++++++++++++++++++++ include/ola/rdm/RDMCommand.h | 8 ++++++++ 3 files changed, 51 insertions(+) diff --git a/common/rdm/RDMCommand.cpp b/common/rdm/RDMCommand.cpp index 3dd0987836..c8f0d145b8 100644 --- a/common/rdm/RDMCommand.cpp +++ b/common/rdm/RDMCommand.cpp @@ -592,6 +592,22 @@ RDMResponse *NackWithReason(const RDMRequest *request, outstanding_messages); } +RDMResponse *NackWithReason(const RDMResponse *response, + rdm_nack_reason reason_enum) { + uint16_t reason = ola::network::HostToNetwork( + static_cast(reason_enum)); + return new RDMResponse(response->SourceUID(), + response->DestinationUID(), + response->TransactionNumber(), + RDM_NACK_REASON, + response->MessageCount(), + response->SubDevice(), + response->CommandClass(), + response->ParamId(), + reinterpret_cast(&reason), + sizeof(reason)); +} + RDMResponse *GetResponseFromData(const RDMRequest *request, const uint8_t *data, unsigned int length, diff --git a/common/rdm/RDMCommandTest.cpp b/common/rdm/RDMCommandTest.cpp index 77d160f6ca..91b16efe47 100644 --- a/common/rdm/RDMCommandTest.cpp +++ b/common/rdm/RDMCommandTest.cpp @@ -670,6 +670,33 @@ void RDMCommandTest::testNackWithReason() { OLA_ASSERT_EQ(2u, response->ParamDataSize()); OLA_ASSERT_EQ((uint16_t) ola::rdm::NR_WRITE_PROTECT, NackReasonFromResponse(response.get())); + + RDMResponse get_command_response(source, + destination, + 0, // transaction # + ola::rdm::RDM_ACK, // response type + 5, // message count + 10, // sub device + RDMCommand::GET_COMMAND_RESPONSE, + 296, // param id + NULL, // data + 0); // data length + + response.reset(NackWithReason(&get_command_response, + ola::rdm::NR_DATA_OUT_OF_RANGE)); + OLA_ASSERT_NOT_NULL(response.get()); + // Comparing response to response, so no flipping of UIDs + OLA_ASSERT_EQ(source, response->SourceUID()); + OLA_ASSERT_EQ(destination, response->DestinationUID()); + OLA_ASSERT_EQ((uint8_t) 0, response->TransactionNumber()); + OLA_ASSERT_EQ((uint8_t) ola::rdm::RDM_NACK_REASON, response->ResponseType()); + OLA_ASSERT_EQ((uint8_t) 5, response->MessageCount()); + OLA_ASSERT_EQ((uint16_t) 10, response->SubDevice()); + OLA_ASSERT_EQ(RDMCommand::GET_COMMAND_RESPONSE, response->CommandClass()); + OLA_ASSERT_EQ((uint16_t) 296, response->ParamId()); + OLA_ASSERT_EQ(2u, response->ParamDataSize()); + OLA_ASSERT_EQ((uint16_t) ola::rdm::NR_DATA_OUT_OF_RANGE, + NackReasonFromResponse(response.get())); } diff --git a/include/ola/rdm/RDMCommand.h b/include/ola/rdm/RDMCommand.h index 56d02dabd0..50948860bf 100644 --- a/include/ola/rdm/RDMCommand.h +++ b/include/ola/rdm/RDMCommand.h @@ -649,6 +649,14 @@ typedef BaseRDMResponse RDMSetResponse; RDMResponse *NackWithReason(const RDMRequest *request, rdm_nack_reason reason, uint8_t outstanding_messages = 0); + +/** + * @brief Make a NACK response with a reason code based on an existing + * RDMResponse + */ +RDMResponse *NackWithReason(const RDMResponse *response, + rdm_nack_reason reason); + /** * @brief Generate an ACK Response with some data */ From ccba9fab044c5acb92aae5f766e6719b0e6babb6 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 17 Feb 2020 17:06:19 +0000 Subject: [PATCH 032/138] Don't send back ACK_OVERFLOW or ACK_TIMER responses --- tools/e133/llrp-receive-test.cpp | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/tools/e133/llrp-receive-test.cpp b/tools/e133/llrp-receive-test.cpp index 8edbf4f3a3..c3e8041064 100644 --- a/tools/e133/llrp-receive-test.cpp +++ b/tools/e133/llrp-receive-test.cpp @@ -32,10 +32,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -76,6 +78,7 @@ using ola::network::Interface; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::network::MACAddress; +using ola::rdm::RDMResponse; using ola::rdm::UID; DEFINE_string(uid, "7a70:00000001", "The UID of the responder."); @@ -176,11 +179,20 @@ void RDMRequestComplete( OLA_INFO << "Got RDM reply to send"; OLA_DEBUG << reply->ToString(); -// TODO(Peter): Do the below -//LLRP Targets shall not return RDM responses with response types of ACK_TIMER or -//ACK_OVERFLOW. LLRP Targets shall respond with a NACK with reason code -//NR_ACTION_NOT_SUPPORTED to any RDM request that cannot be answered without starting -//an ACK_TIMER or ACK_OVERFLOW sequence. + const RDMResponse *response = reply->Response(); + uint8_t response_type = response->ResponseType(); + + if (response_type == ola::rdm::RDM_ACK_TIMER || + response_type == ola::rdm::ACK_OVERFLOW) { + // Technically we shouldn't have even actioned the request but we can't + // really do that in OLA, as we don't know what it might return until we've + // done it + OLA_DEBUG << "Got a disallowed ACK, mangling to NR_ACTION_NOT_SUPPORTED"; + response = NackWithReason(response, ola::rdm::NR_ACTION_NOT_SUPPORTED); + } else { + OLA_DEBUG << "Got an acceptable response type: " + << (unsigned int)response_type; + } const RootHeader root_header = headers.GetRootHeader(); const LLRPHeader llrp_header = headers.GetLLRPHeader(); @@ -199,7 +211,7 @@ void RDMRequestComplete( ola::acn::LLRP_PORT); ola::io::ByteString raw_reply; - ola::rdm::RDMCommandSerializer::Pack(*reply->Response(), &raw_reply); + ola::rdm::RDMCommandSerializer::Pack(*response, &raw_reply); ola::acn::RDMPDU rdm_reply(raw_reply); @@ -216,7 +228,7 @@ void HandleRDM( OLA_INFO << "Got RDM request from " << target; if (!CheckCIDAddressedToUs(headers->GetLLRPHeader().DestinationCid())) { - OLA_INFO << "Ignoring probe request as it's not addressed to us or the LLRP broadcast CID"; + OLA_INFO << "Ignoring RDM request as it's not addressed to us or the LLRP broadcast CID"; return; } @@ -283,13 +295,17 @@ int main(int argc, char* argv[]) { IPV4Address *addr = IPV4Address::FromString("239.255.250.133"); - if (!picker->ChooseInterface(&m_interface, m_preferred_ip)) { + ola::network::InterfacePicker::Options options; + options.include_loopback = false; + if (!picker->ChooseInterface(&m_interface, m_preferred_ip, options)) { OLA_INFO << "Failed to find an interface"; return false; } std::cout << "IF " << m_interface << std::endl; + // If we enable multicast loopback, we can test two bits of software on the + // same machine, but we get, and must ignore, all our own requests too if (!m_socket.JoinMulticast(m_interface.ip_address, *addr, true)) { OLA_WARN << "Failed to join multicast group " << addr; return false; From 52e8913b99436fa8e5773f98fa5841c0667356ef Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 17 Feb 2020 17:26:39 +0000 Subject: [PATCH 033/138] NACK if an invalid subdevice is targetted --- tools/e133/llrp-receive-test.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/tools/e133/llrp-receive-test.cpp b/tools/e133/llrp-receive-test.cpp index c3e8041064..efed057d2f 100644 --- a/tools/e133/llrp-receive-test.cpp +++ b/tools/e133/llrp-receive-test.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -78,6 +79,7 @@ using ola::network::Interface; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::network::MACAddress; +using ola::rdm::RDMReply; using ola::rdm::RDMResponse; using ola::rdm::UID; @@ -253,15 +255,19 @@ void HandleRDM( if (!((request->SubDevice() == ola::rdm::ROOT_RDM_DEVICE) || (request->SubDevice() == ola::rdm::ALL_RDM_SUBDEVICES))) { OLA_WARN << "Subdevice " << request->SubDevice() << " was not the root or " - << "broadcast subdevice"; - // TODO(Peter): NACK with NR_SUB_DEVICE_OUT_OF_RANGE - return; + << "broadcast subdevice, NACKing"; + // Immediately send a NACK + RDMReply reply( + ola::rdm::RDM_COMPLETED_OK, + NackWithReason(request, ola::rdm::NR_SUB_DEVICE_OUT_OF_RANGE)); + RDMRequestComplete(*headers, &reply); + } else { + // Dispatch the message to the responder + dummy_responder->SendRDMRequest( + request, + ola::NewSingleCallback(&RDMRequestComplete, + *headers)); } - - dummy_responder->SendRDMRequest( - request, - ola::NewSingleCallback(&RDMRequestComplete, - *headers)); } int main(int argc, char* argv[]) { From bc2099bac694c2291f7dcb92cfb7025e4680218d Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 18 Feb 2020 02:12:23 +0000 Subject: [PATCH 034/138] Rename the target code to a more standardised name --- .gitignore | 4 ++-- tools/e133/Makefile.mk | 6 +++--- tools/e133/{llrp-receive-test.cpp => llrp-target.cpp} | 0 3 files changed, 5 insertions(+), 5 deletions(-) rename tools/e133/{llrp-receive-test.cpp => llrp-target.cpp} (100%) diff --git a/.gitignore b/.gitignore index 6103d55d61..c1299e8062 100644 --- a/.gitignore +++ b/.gitignore @@ -212,8 +212,8 @@ tools/e133/e133_monitor tools/e133/e133_monitor.exe tools/e133/e133_receiver tools/e133/e133_receiver.exe -tools/e133/llrp_receive_test -tools/e133/llrp_receive_test.exe +tools/e133/llrp_target +tools/e133/llrp_target.exe tools/e133/slp_locate tools/e133/slp_locate.exe tools/e133/slp_register diff --git a/tools/e133/Makefile.mk b/tools/e133/Makefile.mk index 132da06b7b..f354d0858a 100644 --- a/tools/e133/Makefile.mk +++ b/tools/e133/Makefile.mk @@ -71,7 +71,7 @@ noinst_PROGRAMS += \ tools/e133/e133_controller \ tools/e133/e133_monitor \ tools/e133/e133_receiver \ - tools/e133/llrp_receive_test + tools/e133/llrp_target tools_e133_e133_receiver_SOURCES = tools/e133/e133-receiver.cpp tools_e133_e133_receiver_LDADD = common/libolacommon.la \ @@ -106,5 +106,5 @@ tools_e133_basic_device_LDADD = common/libolacommon.la \ libs/acn/libolaacn.la \ tools/e133/libolae133common.la -tools_e133_llrp_receive_test_SOURCES = tools/e133/llrp-receive-test.cpp -tools_e133_llrp_receive_test_LDADD = libs/acn/libolae131core.la +tools_e133_llrp_target_SOURCES = tools/e133/llrp-target.cpp +tools_e133_llrp_target_LDADD = libs/acn/libolae131core.la diff --git a/tools/e133/llrp-receive-test.cpp b/tools/e133/llrp-target.cpp similarity index 100% rename from tools/e133/llrp-receive-test.cpp rename to tools/e133/llrp-target.cpp From ed113e142f91b7b0c642fc49b96aaa2ac337e987 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 18 Feb 2020 02:43:01 +0000 Subject: [PATCH 035/138] Update some missed docs --- tools/e133/llrp-target.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/e133/llrp-target.cpp b/tools/e133/llrp-target.cpp index efed057d2f..8d466e5a56 100644 --- a/tools/e133/llrp-target.cpp +++ b/tools/e133/llrp-target.cpp @@ -13,8 +13,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * llrp-receive-test.cpp - * Run a very simple E1.33 LLRP Responder. + * llrp-target.cpp + * Run a very simple E1.33 LLRP Target. * Copyright (C) 2020 Peter Newman */ @@ -83,7 +83,7 @@ using ola::rdm::RDMReply; using ola::rdm::RDMResponse; using ola::rdm::UID; -DEFINE_string(uid, "7a70:00000001", "The UID of the responder."); +DEFINE_string(uid, "7a70:00000001", "The UID of the target."); auto_ptr picker( ola::network::InterfacePicker::NewPicker()); @@ -271,7 +271,7 @@ void HandleRDM( } int main(int argc, char* argv[]) { - ola::AppInit(&argc, argv, "[options]", "Run a very simple E1.33 LLRP Responder."); + ola::AppInit(&argc, argv, "[options]", "Run a very simple E1.33 LLRP Target."); target_uid.reset(UID::FromString(FLAGS_uid)); if (!target_uid.get()) { From 8db5131776b31ada6cf78a0bd6c78a280840432b Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 18 Feb 2020 05:41:54 +0000 Subject: [PATCH 036/138] Add the ability to inflate an LLRP Probe Reply and build a Probe Request --- libs/acn/LLRPProbeReplyInflator.cpp | 107 +++++++++++++++++++++++++ libs/acn/LLRPProbeReplyInflator.h | 79 +++++++++++++++++++ libs/acn/LLRPProbeRequestPDU.cpp | 50 ++++++++++++ libs/acn/LLRPProbeRequestPDU.h | 34 +++++++- libs/acn/LLRPProbeRequestPDUTest.cpp | 112 +++++++++++++++++++++++++++ libs/acn/Makefile.mk | 2 + 6 files changed, 383 insertions(+), 1 deletion(-) create mode 100644 libs/acn/LLRPProbeReplyInflator.cpp create mode 100644 libs/acn/LLRPProbeReplyInflator.h diff --git a/libs/acn/LLRPProbeReplyInflator.cpp b/libs/acn/LLRPProbeReplyInflator.cpp new file mode 100644 index 0000000000..153433c166 --- /dev/null +++ b/libs/acn/LLRPProbeReplyInflator.cpp @@ -0,0 +1,107 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPProbeReplyInflator.cpp + * The Inflator for the LLRP Probe Reply PDUs + * Copyright (C) 2020 Peter Newman + */ + +#include +#include +#include "ola/Logging.h" +#include "include/ola/rdm/UID.h" +#include "include/ola/rdm/UIDSet.h" +#include "include/ola/strings/Format.h" +#include "libs/acn/LLRPProbeReplyInflator.h" +#include "libs/acn/LLRPProbeReplyPDU.h" + +namespace ola { +namespace acn { + +using ola::acn::LLRPProbeReplyPDU; +using ola::rdm::UID; +using ola::rdm::UIDSet; + +/** + * Create a new LLRP Probe Reply inflator + */ +LLRPProbeReplyInflator::LLRPProbeReplyInflator() + : BaseInflator(PDU::ONE_BYTE) { +} + +/** + * Set an LLRPProbeReplyHandler to run when receiving an LLRP Probe Reply + * message. + * @param handler the callback to invoke when there is and LLRP Probe Reply. + */ +void LLRPProbeReplyInflator::SetLLRPProbeReplyHandler( + LLRPProbeReplyHandler *handler) { + m_llrp_probe_reply_handler.reset(handler); +} + + +/* + * Decode the LLRP Probe Reply 'header', which is 0 bytes in length. + * @param headers the HeaderSet to add to + * @param data a pointer to the data + * @param length length of the data + * @returns true if successful, false otherwise + */ +bool LLRPProbeReplyInflator::DecodeHeader(HeaderSet *, + const uint8_t*, + unsigned int, + unsigned int *bytes_used) { + *bytes_used = 0; + return true; +} + + +/* + * Handle a LLRP Probe Reply PDU for E1.33. + */ +bool LLRPProbeReplyInflator::HandlePDUData(uint32_t vector, + const HeaderSet &headers, + const uint8_t *data, + unsigned int pdu_len) { + if (vector != LLRPProbeReplyPDU::VECTOR_PROBE_REPLY_DATA) { + OLA_INFO << "Not a probe reply, vector was " << vector; + return true; + } + + ola::strings::FormatData(&std::cout, data, pdu_len); + + LLRPProbeReplyPDU::llrp_probe_reply_pdu_data pdu_data; + if (pdu_len > sizeof(pdu_data)) { + OLA_WARN << "Got too much data, received " << pdu_len << " only expecting " + << sizeof(pdu_data); + return false; + } + + memcpy(reinterpret_cast(&pdu_data), data, sizeof(pdu_data)); + + OLA_DEBUG << "Probe from " << UID(pdu_data.target_uid); + + LLRPProbeReply reply(UID(pdu_data.target_uid)); + + if (m_llrp_probe_reply_handler.get()) { + m_llrp_probe_reply_handler->Run(&headers, + reply); + } else { + OLA_WARN << "No LLRP Probe Reply handler defined!"; + } + return true; +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/LLRPProbeReplyInflator.h b/libs/acn/LLRPProbeReplyInflator.h new file mode 100644 index 0000000000..3aab45f7b1 --- /dev/null +++ b/libs/acn/LLRPProbeReplyInflator.h @@ -0,0 +1,79 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * LLRPProbeReplyInflator.h + * Copyright (C) 2020 Peter Newman + */ + +#ifndef LIBS_ACN_LLRPPROBEREPLYINFLATOR_H_ +#define LIBS_ACN_LLRPPROBEREPLYINFLATOR_H_ + +#include "ola/Callback.h" +#include "ola/acn/ACNVectors.h" +#include "ola/rdm/UID.h" +#include "ola/rdm/UIDSet.h" +#include "libs/acn/BaseInflator.h" +#include "libs/acn/HeaderSet.h" +#include "libs/acn/LLRPProbeReplyPDU.h" + +namespace ola { +namespace acn { + +class LLRPProbeReplyInflator: public BaseInflator { + friend class LLRPProbeReplyInflatorTest; + + public: + struct LLRPProbeReply { + LLRPProbeReply(const ola::rdm::UID &_uid) + : uid(_uid) { + } + ola::rdm::UID uid; + ola::network::MACAddress hardware_address; + ola::acn::LLRPProbeReplyPDU::LLRPComponentType component_type; + }; + + + // These are pointers so the callers don't have to pull in all the headers. + typedef ola::Callback2 LLRPProbeReplyHandler; + + LLRPProbeReplyInflator(); + ~LLRPProbeReplyInflator() {} + + uint32_t Id() const { return ola::acn::VECTOR_LLRP_PROBE_REPLY; } + + void SetLLRPProbeReplyHandler(LLRPProbeReplyHandler *handler); + + protected: + bool DecodeHeader(HeaderSet *headers, + const uint8_t *data, + unsigned int len, + unsigned int *bytes_used); + + void ResetHeaderField() {} // namespace noop + + virtual bool HandlePDUData(uint32_t vector, + const HeaderSet &headers, + const uint8_t *data, + unsigned int pdu_len); + + private: + std::auto_ptr m_llrp_probe_reply_handler; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_LLRPPROBEREPLYINFLATOR_H_ diff --git a/libs/acn/LLRPProbeRequestPDU.cpp b/libs/acn/LLRPProbeRequestPDU.cpp index 6db4af3bab..ee8a021ec7 100644 --- a/libs/acn/LLRPProbeRequestPDU.cpp +++ b/libs/acn/LLRPProbeRequestPDU.cpp @@ -31,6 +31,56 @@ using ola::io::OutputStream; using ola::network::HostToNetwork; using ola::rdm::UID; +unsigned int LLRPProbeRequestPDU::DataSize() const { + llrp_probe_request_pdu_data data; + return static_cast(sizeof(llrp_probe_request_pdu_data) - + sizeof(data.known_uids) + + (m_known_uids.Size() * UID::LENGTH)); + +} + +bool LLRPProbeRequestPDU::PackData(uint8_t *data, unsigned int *length) const { + llrp_probe_request_pdu_data pdu_data; + m_lower_uid.Pack(pdu_data.lower_uid, sizeof(pdu_data.lower_uid)); + m_upper_uid.Pack(pdu_data.upper_uid, sizeof(pdu_data.upper_uid)); + uint16_t filter = 0; + if (m_client_tcp_connection_inactive) { + filter |= FILTER_CLIENT_TCP_CONNECTION_INACTIVE; + } + if (m_brokers_only) { + filter |= FILTER_BROKERS_ONLY; + } + pdu_data.filter = HostToNetwork(filter); + // TODO(Peter): We need to check we've got <= 200 UIDs here + m_known_uids.Pack(pdu_data.known_uids, sizeof(pdu_data.known_uids)); + *length = static_cast(sizeof(llrp_probe_request_pdu_data) - + sizeof(pdu_data.known_uids) + + (m_known_uids.Size() * UID::LENGTH)); + + memcpy(data, &pdu_data, *length); + return true; +} + +void LLRPProbeRequestPDU::PackData(ola::io::OutputStream *stream) const { + llrp_probe_request_pdu_data data; + m_lower_uid.Pack(data.lower_uid, sizeof(data.lower_uid)); + m_upper_uid.Pack(data.upper_uid, sizeof(data.upper_uid)); + uint16_t filter = 0; + if (m_client_tcp_connection_inactive) { + filter |= FILTER_CLIENT_TCP_CONNECTION_INACTIVE; + } + if (m_brokers_only) { + filter |= FILTER_BROKERS_ONLY; + } + data.filter = HostToNetwork(filter); + // TODO(Peter): We need to check we've got <= 200 UIDs here + m_known_uids.Pack(data.known_uids, sizeof(data.known_uids)); + stream->Write(reinterpret_cast(&data), + static_cast(sizeof(llrp_probe_request_pdu_data) - + sizeof(data.known_uids) + + (m_known_uids.Size() * UID::LENGTH))); +} + void LLRPProbeRequestPDU::PrependPDU(ola::io::IOStack *stack, const UID &lower_uid, const UID &upper_uid, diff --git a/libs/acn/LLRPProbeRequestPDU.h b/libs/acn/LLRPProbeRequestPDU.h index 17a3145c69..56095c709c 100644 --- a/libs/acn/LLRPProbeRequestPDU.h +++ b/libs/acn/LLRPProbeRequestPDU.h @@ -30,8 +30,33 @@ namespace ola { namespace acn { -class LLRPProbeRequestPDU : private PDU { +class LLRPProbeRequestPDU : public PDU { public: + explicit LLRPProbeRequestPDU(unsigned int vector, + const ola::rdm::UID &lower_uid, + const ola::rdm::UID &upper_uid, + bool client_tcp_connection_inactive, + bool brokers_only, + const ola::rdm::UIDSet &known_uids): + PDU(vector, ONE_BYTE, true), + m_lower_uid(lower_uid), + m_upper_uid(upper_uid), + m_client_tcp_connection_inactive(client_tcp_connection_inactive), + m_brokers_only(brokers_only), + m_known_uids(known_uids) {} + + unsigned int HeaderSize() const { return 0; } + bool PackHeader(OLA_UNUSED uint8_t *data, + unsigned int *length) const { + *length = 0; + return true; + } + void PackHeader(OLA_UNUSED ola::io::OutputStream *stream) const {} + + unsigned int DataSize() const; + bool PackData(uint8_t *data, unsigned int *length) const; + void PackData(ola::io::OutputStream *stream) const; + static void PrependPDU(ola::io::IOStack *stack, const ola::rdm::UID &lower_uid, const ola::rdm::UID &upper_uid, @@ -55,6 +80,13 @@ class LLRPProbeRequestPDU : private PDU { uint8_t known_uids[ola::rdm::UID::LENGTH * LLRP_KNOWN_UID_SIZE]; }); typedef struct llrp_probe_request_pdu_data_s llrp_probe_request_pdu_data; + + private: + const ola::rdm::UID m_lower_uid; + const ola::rdm::UID m_upper_uid; + bool m_client_tcp_connection_inactive; + bool m_brokers_only; + const ola::rdm::UIDSet m_known_uids; }; } // namespace acn } // namespace ola diff --git a/libs/acn/LLRPProbeRequestPDUTest.cpp b/libs/acn/LLRPProbeRequestPDUTest.cpp index 6666002b6a..88f39d587c 100644 --- a/libs/acn/LLRPProbeRequestPDUTest.cpp +++ b/libs/acn/LLRPProbeRequestPDUTest.cpp @@ -23,7 +23,9 @@ #include #include "ola/Logging.h" +#include "ola/io/IOQueue.h" #include "ola/io/IOStack.h" +#include "ola/io/OutputStream.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" @@ -34,16 +36,24 @@ namespace ola { namespace acn { +using ola::acn::LLRPProbeRequestPDU; +using ola::io::IOQueue; using ola::io::IOStack; +using ola::io::OutputStream; +using ola::network::HostToNetwork; using ola::rdm::UID; using ola::rdm::UIDSet; class LLRPProbeRequestPDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(LLRPProbeRequestPDUTest); + CPPUNIT_TEST(testSimpleLLRPProbeRequestPDU); + CPPUNIT_TEST(testSimpleLLRPProbeRequestPDUToOutputStream); CPPUNIT_TEST(testPrepend); CPPUNIT_TEST_SUITE_END(); public: + void testSimpleLLRPProbeRequestPDU(); + void testSimpleLLRPProbeRequestPDUToOutputStream(); void testPrepend(); private: @@ -52,6 +62,108 @@ class LLRPProbeRequestPDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE_REGISTRATION(LLRPProbeRequestPDUTest); +const unsigned int LLRPProbeRequestPDUTest::TEST_VECTOR = 39; + + +/* + * Test that packing a LLRPProbeRequestPDU works. + */ +void LLRPProbeRequestPDUTest::testSimpleLLRPProbeRequestPDU() { + UID lower_uid = UID(0x4321, 0x12345678); + UID upper_uid = UID(0x5678, 0x00abcdef); + UIDSet known_uids; + known_uids.AddUID(UID(0x1234, 0x00000001)); + known_uids.AddUID(UID(0x5678, 0x00000002)); + known_uids.AddUID(UID(0x4321, 0x56789abc)); + LLRPProbeRequestPDU pdu( + TEST_VECTOR, + lower_uid, + upper_uid, + false, + false, + known_uids); + + OLA_ASSERT_EQ(0u, pdu.HeaderSize()); + OLA_ASSERT_EQ(32u, pdu.DataSize()); + OLA_ASSERT_EQ(36u, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + + // spot check the data + OLA_ASSERT_EQ((uint8_t) 0xf0, data[0]); + // bytes_used is technically data[1] and data[2] if > 255 + OLA_ASSERT_EQ((uint8_t) bytes_used, data[2]); + OLA_ASSERT_EQ(HostToNetwork((uint8_t) TEST_VECTOR), data[3]); + + uint8_t buffer[UID::LENGTH]; + lower_uid.Pack(buffer, sizeof(buffer)); + OLA_ASSERT_DATA_EQUALS(&data[4], UID::LENGTH, buffer, sizeof(buffer)); + upper_uid.Pack(buffer, sizeof(buffer)); + OLA_ASSERT_DATA_EQUALS(&data[10], UID::LENGTH, buffer, sizeof(buffer)); + + // test undersized buffer + bytes_used = size - 1; + OLA_ASSERT_FALSE(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(0u, bytes_used); + + // test oversized buffer + bytes_used = size + 1; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + delete[] data; +} + +/* + * Test that writing to an output stream works. + */ +void LLRPProbeRequestPDUTest::testSimpleLLRPProbeRequestPDUToOutputStream() { + UID lower_uid = UID(0x4321, 0x12345678); + UID upper_uid = UID(0x5678, 0x00abcdef); + UIDSet known_uids; + known_uids.AddUID(UID(0x1234, 0x00000001)); + known_uids.AddUID(UID(0x5678, 0x00000002)); + known_uids.AddUID(UID(0x4321, 0x56789abc)); + LLRPProbeRequestPDU pdu( + TEST_VECTOR, + lower_uid, + upper_uid, + false, + false, + known_uids); + + OLA_ASSERT_EQ(0u, pdu.HeaderSize()); + OLA_ASSERT_EQ(32u, pdu.DataSize()); + OLA_ASSERT_EQ(36u, pdu.Size()); + + IOQueue output; + OutputStream stream(&output); + pdu.Write(&stream); + OLA_ASSERT_EQ(36u, output.Size()); + + uint8_t *pdu_data = new uint8_t[output.Size()]; + unsigned int pdu_size = output.Peek(pdu_data, output.Size()); + OLA_ASSERT_EQ(output.Size(), pdu_size); + + uint8_t EXPECTED[] = { + 0xf0, 0x00, 0x24, + 39, + 0x43, 0x21, 0x12, 0x34, 0x56, 0x78, + 0x56, 0x78, 0x00, 0xab, 0xcd, 0xef, + 0x00, 0x00, + 0x12, 0x34, 0, 0, 0, 1, + 0x43, 0x21, 0x56, 0x78, 0x9a, 0xbc, + 0x56, 0x78, 0, 0, 0, 2 + }; + OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), pdu_data, pdu_size); + output.Pop(output.Size()); + delete[] pdu_data; +} + + void LLRPProbeRequestPDUTest::testPrepend() { IOStack stack; UIDSet known_uids; diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index 7c81ef9031..a036a3f55a 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -64,6 +64,8 @@ libs_acn_libolae131core_la_SOURCES = \ libs/acn/LLRPHeader.h \ libs/acn/LLRPInflator.cpp \ libs/acn/LLRPInflator.h \ + libs/acn/LLRPProbeReplyInflator.cpp \ + libs/acn/LLRPProbeReplyInflator.h \ libs/acn/LLRPProbeReplyPDU.cpp \ libs/acn/LLRPProbeReplyPDU.h \ libs/acn/LLRPProbeRequestInflator.cpp \ From bd0a09c536cdfccd4dec8e9b5fc1736690e630b3 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Wed, 19 Feb 2020 13:02:48 +0000 Subject: [PATCH 037/138] Minor tweak to some logging --- tools/e133/llrp-target.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/e133/llrp-target.cpp b/tools/e133/llrp-target.cpp index 8d466e5a56..b7159ec8c5 100644 --- a/tools/e133/llrp-target.cpp +++ b/tools/e133/llrp-target.cpp @@ -279,7 +279,7 @@ int main(int argc, char* argv[]) { ola::DisplayUsage(); exit(ola::EXIT_USAGE); } else { - OLA_INFO << "Started LLRP Responder with UID " << *target_uid; + OLA_INFO << "Started LLRP Target with UID " << *target_uid; } dummy_responder.reset(new ola::rdm::DummyResponder(*target_uid)); From fc8333076395abf6e22f1f5ba0f5769ada4cef25 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Wed, 19 Feb 2020 13:09:12 +0000 Subject: [PATCH 038/138] Initial basic attempt at an LLRP manager --- .gitignore | 2 + tools/e133/Makefile.mk | 10 +- tools/e133/llrp-manager.cpp | 433 ++++++++++++++++++++++++++++++++++++ 3 files changed, 444 insertions(+), 1 deletion(-) create mode 100644 tools/e133/llrp-manager.cpp diff --git a/.gitignore b/.gitignore index c1299e8062..447f772cf6 100644 --- a/.gitignore +++ b/.gitignore @@ -212,6 +212,8 @@ tools/e133/e133_monitor tools/e133/e133_monitor.exe tools/e133/e133_receiver tools/e133/e133_receiver.exe +tools/e133/llrp_manager +tools/e133/llrp_manager.exe tools/e133/llrp_target tools/e133/llrp_target.exe tools/e133/slp_locate diff --git a/tools/e133/Makefile.mk b/tools/e133/Makefile.mk index f354d0858a..76f23cdf21 100644 --- a/tools/e133/Makefile.mk +++ b/tools/e133/Makefile.mk @@ -71,6 +71,7 @@ noinst_PROGRAMS += \ tools/e133/e133_controller \ tools/e133/e133_monitor \ tools/e133/e133_receiver \ + tools/e133/llrp_manager \ tools/e133/llrp_target tools_e133_e133_receiver_SOURCES = tools/e133/e133-receiver.cpp @@ -106,5 +107,12 @@ tools_e133_basic_device_LDADD = common/libolacommon.la \ libs/acn/libolaacn.la \ tools/e133/libolae133common.la +tools_e133_llrp_manager_SOURCES = tools/e133/llrp-manager.cpp +tools_e133_llrp_manager_LDADD = common/libolacommon.la \ + libs/acn/libolaacn.la \ + tools/e133/libolae133common.la + tools_e133_llrp_target_SOURCES = tools/e133/llrp-target.cpp -tools_e133_llrp_target_LDADD = libs/acn/libolae131core.la +tools_e133_llrp_target_LDADD = common/libolacommon.la \ + libs/acn/libolaacn.la \ + tools/e133/libolae133common.la diff --git a/tools/e133/llrp-manager.cpp b/tools/e133/llrp-manager.cpp new file mode 100644 index 0000000000..35021e3e33 --- /dev/null +++ b/tools/e133/llrp-manager.cpp @@ -0,0 +1,433 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * llrp-manager.cpp + * Run a very simple E1.33 LLRP Manager. + * Copyright (C) 2020 Peter Newman + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "libs/acn/HeaderSet.h" +#include "libs/acn/LLRPHeader.h" +#include "libs/acn/LLRPInflator.h" +#include "libs/acn/LLRPPDU.h" +#include "libs/acn/LLRPProbeReplyInflator.h" +#include "libs/acn/LLRPProbeReplyPDU.h" +#include "libs/acn/LLRPProbeRequestPDU.h" +#include "libs/acn/PreamblePacker.h" +#include "libs/acn/RDMInflator.h" +#include "libs/acn/RDMPDU.h" +#include "libs/acn/RootHeader.h" +#include "libs/acn/RootInflator.h" +#include "libs/acn/RootSender.h" +#include "libs/acn/Transport.h" +#include "libs/acn/UDPTransport.h" + +using std::string; +using std::vector; +using std::auto_ptr; + +using ola::acn::CID; +using ola::acn::IncomingUDPTransport; +using ola::acn::LLRPHeader; +using ola::acn::LLRPProbeReplyInflator; +using ola::acn::LLRPProbeReplyPDU; +using ola::acn::LLRPProbeRequestPDU; +using ola::acn::OutgoingUDPTransport; +using ola::acn::OutgoingUDPTransportImpl; +using ola::acn::RootHeader; +using ola::network::Interface; +using ola::network::IPV4Address; +using ola::network::IPV4SocketAddress; +using ola::network::MACAddress; +using ola::network::NetworkToHost; +using ola::rdm::PidStoreHelper; +using ola::rdm::RDMGetRequest; +using ola::rdm::RDMReply; +using ola::rdm::RDMRequest; +using ola::rdm::RDMResponse; +using ola::rdm::UID; +using ola::rdm::UIDSet; + +DEFINE_string(manager_uid, "7a70:00000002", "The UID of the manager."); + +auto_ptr picker( + ola::network::InterfacePicker::NewPicker()); +ola::network::Interface m_interface; +const std::string m_preferred_ip; +ola::network::UDPSocket m_socket; +uint8_t *m_recv_buffer; +std::auto_ptr manager_uid; +std::auto_ptr m_pid_helper; +ola::SequenceNumber m_llrp_transaction_number_sequence; +ola::SequenceNumber m_rdm_transaction_number_sequence; + +std::string pid_name; +vector rdm_inputs; + +ola::acn::PreamblePacker m_packer; +CID cid = CID::Generate(); +ola::acn::RootSender m_root_sender(cid, true); + +bool CheckCIDAddressedToUs(const CID destination_cid) { + return (destination_cid == CID::LLRPBroadcastCID() || + destination_cid == cid); +} + +void SendLLRPProbeRequest() { + LLRPHeader llrp_header = LLRPHeader(CID::LLRPBroadcastCID(), + m_llrp_transaction_number_sequence.Next()); + + IPV4Address *target_address = IPV4Address::FromString("239.255.250.133"); + + OutgoingUDPTransportImpl transport_impl = OutgoingUDPTransportImpl(&m_socket, &m_packer); + OutgoingUDPTransport transport(&transport_impl, + *target_address, + ola::acn::LLRP_PORT); + + LLRPProbeRequestPDU probe_request( + LLRPProbeRequestPDU::VECTOR_PROBE_REQUEST_DATA, + *UID::FromString("0000:00000000"), + *UID::FromString("ffff:ffffffff"), + false, + false, + UIDSet()); + + ola::acn::LLRPPDU pdu(ola::acn::VECTOR_LLRP_PROBE_REQUEST, llrp_header, &probe_request); + + m_root_sender.SendPDU(ola::acn::VECTOR_ROOT_LLRP, pdu, &transport); + OLA_DEBUG << "Sent PDU"; +} + +void HandleLLRPProbeReply( + const ola::acn::HeaderSet *headers, + const LLRPProbeReplyInflator::LLRPProbeReply &reply) { + OLA_DEBUG << "Potentially handling probe reply from " << reply.uid; + + const LLRPHeader llrp_header = headers->GetLLRPHeader(); + if (!CheckCIDAddressedToUs(llrp_header.DestinationCid())) { + OLA_INFO << "Ignoring probe request as it's not addressed to us or the LLRP broadcast CID"; + return; + } + + const RootHeader root_header = headers->GetRootHeader(); + + OLA_DEBUG << "Source CID: " << root_header.GetCid(); + OLA_DEBUG << "TN: " << llrp_header.TransactionNumber(); + + LLRPHeader rdm_llrp_header = LLRPHeader(root_header.GetCid(), + m_llrp_transaction_number_sequence.Next()); + + IPV4Address *target_address = IPV4Address::FromString("239.255.250.133"); + + OutgoingUDPTransportImpl transport_impl = OutgoingUDPTransportImpl(&m_socket, &m_packer); + OutgoingUDPTransport transport(&transport_impl, + *target_address, + ola::acn::LLRP_PORT); + + // TODO(Peter): Enable set + bool is_set = false; + + // get the pid descriptor + const ola::rdm::PidDescriptor *pid_descriptor = m_pid_helper->GetDescriptor( + pid_name, + reply.uid.ManufacturerId()); + + uint16_t pid_value; + if (!pid_descriptor && + (ola::PrefixedHexStringToInt(pid_name, &pid_value) || + ola::StringToInt(pid_name, &pid_value))) { + pid_descriptor = m_pid_helper->GetDescriptor( + pid_value, + reply.uid.ManufacturerId()); + } + + if (!pid_descriptor) { + std::cout << "Unknown PID: " << pid_name << std::endl; + std::cout << "Use --list-pids to list the available PIDs." << std::endl; + return; + } + + const ola::messaging::Descriptor *descriptor = NULL; + if (is_set) + descriptor = pid_descriptor->SetRequest(); + else + descriptor = pid_descriptor->GetRequest(); + + if (!descriptor) { + std::cout << (is_set ? "SET" : "GET") << " command not supported for " + << pid_name << std::endl; + return; + } + + // attempt to build the message + auto_ptr message(m_pid_helper->BuildMessage( + descriptor, + rdm_inputs)); + + if (!message.get()) { + std::cout << m_pid_helper->SchemaAsString(descriptor); + return; + } + + unsigned int param_data_length; + const uint8_t *param_data = m_pid_helper->SerializeMessage( + message.get(), + ¶m_data_length); + + RDMRequest *request = new RDMGetRequest( + *manager_uid, + reply.uid, + m_rdm_transaction_number_sequence.Next(), // transaction # + 1, // port id + 0, // sub device + pid_descriptor->Value(), // param id + param_data, // data + param_data_length); // data length + + ola::io::ByteString raw_reply; + ola::rdm::RDMCommandSerializer::Pack(*request, &raw_reply); + + ola::acn::RDMPDU rdm_reply(raw_reply); + + ola::acn::LLRPPDU pdu(ola::acn::VECTOR_LLRP_RDM_CMD, rdm_llrp_header, &rdm_reply); + + m_root_sender.SendPDU(ola::acn::VECTOR_ROOT_LLRP, pdu, &transport); + OLA_DEBUG << "Sent PDU"; +} + +/** + * Handle an ACK response + */ +void HandleAckResponse(uint16_t manufacturer_id, + bool is_set, + uint16_t pid, + const uint8_t *data, + unsigned int length) { + const ola::rdm::PidDescriptor *pid_descriptor = m_pid_helper->GetDescriptor( + pid, + manufacturer_id); + + if (!pid_descriptor) { + OLA_WARN << "Unknown PID: " << pid << "."; + return; + } + + const ola::messaging::Descriptor *descriptor = NULL; + if (is_set) { + descriptor = pid_descriptor->SetResponse(); + } else { + descriptor = pid_descriptor->GetResponse(); + } + + if (!descriptor) { + OLA_WARN << "Unknown response message: " << (is_set ? "SET" : "GET") << + " " << pid_descriptor->Name(); + return; + } + + auto_ptr message( + m_pid_helper->DeserializeMessage(descriptor, data, length)); + + if (!message.get()) { + OLA_WARN << "Unable to inflate RDM response"; + return; + } + + std::cout << m_pid_helper->PrettyPrintMessage(manufacturer_id, + is_set, + pid, + message.get()); +} + +void HandleRDM( + const ola::acn::HeaderSet *headers, + const string &raw_response) { + IPV4SocketAddress target = headers->GetTransportHeader().Source(); + OLA_INFO << "Got RDM response from " << target; + + if (!CheckCIDAddressedToUs(headers->GetLLRPHeader().DestinationCid())) { + OLA_INFO << "Ignoring RDM response as it's not addressed to us or the LLRP broadcast CID"; + return; + } + + ola::rdm::RDMStatusCode status_code; + // attempt to unpack as a request + ola::rdm::RDMResponse *response = ola::rdm::RDMResponse::InflateFromData( + reinterpret_cast(raw_response.data()), + raw_response.size(), + &status_code); + + OLA_DEBUG << "Got status code " << ola::rdm::StatusCodeToString(status_code); + + if (!response) { + OLA_WARN << "Failed to unpack LLRP RDM message, ignoring request."; + return; + } else { + OLA_DEBUG << "Got RDM response " << response->ToString(); + } + + if (!response->DestinationUID().DirectedToUID(*manager_uid)) { + OLA_WARN << "Destination UID " << response->DestinationUID() << " was not " + << "directed to us"; + return; + } + + OLA_INFO << "Got RDM response from " << response->SourceUID(); + if (response->ResponseType() == ola::rdm::RDM_ACK) { + HandleAckResponse(response->SourceUID().ManufacturerId(), + (response->CommandClass() == + ola::rdm::RDMCommand::SET_COMMAND_RESPONSE), + response->ParamId(), + response->ParamData(), + response->ParamDataSize()); + } else if (response->ResponseType() == ola::rdm::RDM_NACK_REASON) { + uint16_t nack_reason; + if (response->ParamDataSize() != sizeof(nack_reason)) { + OLA_WARN << "Invalid NACK reason size of " << response->ParamDataSize(); + } else { + memcpy(reinterpret_cast(&nack_reason), response->ParamData(), + sizeof(nack_reason)); + nack_reason = NetworkToHost(nack_reason); + std::cout << "Request NACKed: " << + ola::rdm::NackReasonToString(nack_reason) << std::endl; + } + } else { + OLA_WARN << "Unknown RDM response type " + << ola::strings::ToHex(response->ResponseType()); + } +} + +int main(int argc, char* argv[]) { + ola::AppInit(&argc, argv, "[options]", "Run a very simple E1.33 LLRP Manager."); + + if (argc >= 2) { + pid_name = argv[1]; + + // split out rdm message params from the pid name (ignore program name) + rdm_inputs.resize(argc - 2); + for(int i = 0; i < argc - 2; i++) { + rdm_inputs[i] = argv[i+2]; + } + OLA_DEBUG << "Parsed RDM"; + } else { + OLA_INFO << "No RDM to parse"; + } + + m_pid_helper.reset(new PidStoreHelper("")); + m_pid_helper->Init(); + + manager_uid.reset(UID::FromString(FLAGS_manager_uid)); + if (!manager_uid.get()) { + OLA_WARN << "Invalid UID: " << FLAGS_manager_uid; + ola::DisplayUsage(); + exit(ola::EXIT_USAGE); + } else { + OLA_INFO << "Started LLRP Manager with UID " << *manager_uid; + } + + ola::io::SelectServer ss; + + if (!m_socket.Init()) { + return false; + } + std::cout << "Init!" << std::endl; + + std::cout << "Using CID " << cid << std::endl; + + IPV4Address *addr = IPV4Address::FromString("239.255.250.134"); + + if (!m_socket.Bind(IPV4SocketAddress(*addr, + ola::acn::LLRP_PORT))) { + return false; + } + std::cout << "Bind!" << std::endl; + + ola::network::InterfacePicker::Options options; + options.include_loopback = false; + if (!picker->ChooseInterface(&m_interface, m_preferred_ip, options)) { + OLA_INFO << "Failed to find an interface"; + return false; + } + + std::cout << "IF " << m_interface << std::endl; + + // If we enable multicast loopback, we can test two bits of software on the + // same machine, but we get, and must ignore, all our own requests too + if (!m_socket.JoinMulticast(m_interface.ip_address, *addr, true)) { + OLA_WARN << "Failed to join multicast group " << addr; + return false; + } + + ola::acn::RootInflator root_inflator; + ola::acn::LLRPInflator llrp_inflator; + ola::acn::LLRPProbeReplyInflator llrp_probe_reply_inflator; + llrp_probe_reply_inflator.SetLLRPProbeReplyHandler( + ola::NewCallback(&HandleLLRPProbeReply)); + ola::acn::RDMInflator llrp_rdm_inflator(ola::acn::VECTOR_LLRP_RDM_CMD); + llrp_rdm_inflator.SetGenericRDMHandler( + ola::NewCallback(&HandleRDM)); + + // setup all the inflators + root_inflator.AddInflator(&llrp_inflator); + llrp_inflator.AddInflator(&llrp_probe_reply_inflator); + llrp_inflator.AddInflator(&llrp_rdm_inflator); + + IncomingUDPTransport m_incoming_udp_transport(&m_socket, &root_inflator); + m_socket.SetOnData(ola::NewCallback(&m_incoming_udp_transport, + &IncomingUDPTransport::Receive)); + ss.AddReadDescriptor(&m_socket); + + // TODO(Peter): Add the ability to filter on UID or UID+CID to avoid the probing + + // TODO(Peter): Send this three times + // TODO(Peter): Deal with known UID list etc and proper discovery + SendLLRPProbeRequest(); + ss.Run(); + + return 0; +} From ac119e8248aeecd9198448bcd49dff4e3669f49f Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 25 Feb 2020 13:48:28 +0000 Subject: [PATCH 039/138] Support sending set commands --- tools/e133/llrp-manager.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/tools/e133/llrp-manager.cpp b/tools/e133/llrp-manager.cpp index 35021e3e33..4857919287 100644 --- a/tools/e133/llrp-manager.cpp +++ b/tools/e133/llrp-manager.cpp @@ -90,10 +90,12 @@ using ola::rdm::RDMGetRequest; using ola::rdm::RDMReply; using ola::rdm::RDMRequest; using ola::rdm::RDMResponse; +using ola::rdm::RDMSetRequest; using ola::rdm::UID; using ola::rdm::UIDSet; DEFINE_string(manager_uid, "7a70:00000002", "The UID of the manager."); +DEFINE_default_bool(set, false, "Send a set rather than a get."); auto_ptr picker( ola::network::InterfacePicker::NewPicker()); @@ -169,8 +171,7 @@ void HandleLLRPProbeReply( *target_address, ola::acn::LLRP_PORT); - // TODO(Peter): Enable set - bool is_set = false; + bool is_set = FLAGS_set; // get the pid descriptor const ola::rdm::PidDescriptor *pid_descriptor = m_pid_helper->GetDescriptor( @@ -193,10 +194,11 @@ void HandleLLRPProbeReply( } const ola::messaging::Descriptor *descriptor = NULL; - if (is_set) + if (is_set) { descriptor = pid_descriptor->SetRequest(); - else + } else { descriptor = pid_descriptor->GetRequest(); + } if (!descriptor) { std::cout << (is_set ? "SET" : "GET") << " command not supported for " @@ -219,7 +221,19 @@ void HandleLLRPProbeReply( message.get(), ¶m_data_length); - RDMRequest *request = new RDMGetRequest( + RDMRequest *request; + if (is_set) { + request = new RDMSetRequest( + *manager_uid, + reply.uid, + m_rdm_transaction_number_sequence.Next(), // transaction # + 1, // port id + 0, // sub device + pid_descriptor->Value(), // param id + param_data, // data + param_data_length); // data length + } else { + request = new RDMGetRequest( *manager_uid, reply.uid, m_rdm_transaction_number_sequence.Next(), // transaction # @@ -228,6 +242,7 @@ void HandleLLRPProbeReply( pid_descriptor->Value(), // param id param_data, // data param_data_length); // data length + } ola::io::ByteString raw_reply; ola::rdm::RDMCommandSerializer::Pack(*request, &raw_reply); From 9845e378fd0569c95206368f04af528bc269b412 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 25 Feb 2020 17:36:17 +0000 Subject: [PATCH 040/138] Update some RDM comments --- tools/rdm/TestDefinitions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/rdm/TestDefinitions.py b/tools/rdm/TestDefinitions.py index e88147380e..8071311099 100644 --- a/tools/rdm/TestDefinitions.py +++ b/tools/rdm/TestDefinitions.py @@ -911,7 +911,7 @@ class GetSubDeviceSupportedParameters(ResponderTestFixture): REQUIRES = ['sub_device_addresses'] PROVIDES = ['sub_device_supported_parameters'] - # E1.37, 2.1 Sub devices are required to support these. + # E1.37-1, 2.1 Sub devices are required to support these. MANDATORY_PIDS = ['SUPPORTED_PARAMETERS', 'DEVICE_INFO', 'SOFTWARE_VERSION_LABEL', @@ -4539,7 +4539,7 @@ class AllSubDevicesGetPresetPlayback(TestMixins.AllSubDevicesGetMixin, PID = 'PRESET_PLAYBACK' -# E1.37 PIDS +# E1.37-1 PIDS # ============================================================================= # IDENTIFY_MODE From e6b8f998585114223dd37241928b64c391c83641 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 25 Feb 2020 17:47:12 +0000 Subject: [PATCH 041/138] Update PIDs from rdm-app repo --- data/rdm/draft_pids.proto | 853 +-------------- data/rdm/manufacturer_names.proto | 1604 +++++++++++++++++++++++++++-- data/rdm/manufacturer_pids.proto | 244 +++-- data/rdm/pids.proto | 1263 ++++++++++++++++++++++- 4 files changed, 2912 insertions(+), 1052 deletions(-) diff --git a/data/rdm/draft_pids.proto b/data/rdm/draft_pids.proto index 69a87d8e2a..4d8425795f 100644 --- a/data/rdm/draft_pids.proto +++ b/data/rdm/draft_pids.proto @@ -1,852 +1 @@ -pid { - name: "BACKGROUND_QUEUED_STATUS_POLICY" - value: 32720 - get_request { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - } - get_response { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - field { - type: UINT8 - name: "current_policy_setting" - } - field { - type: UINT8 - name: "num_policy_settings" - } - } - get_sub_device_range: ROOT_DEVICE - set_request { - field { - type: UINT16 - name: "endpoint_id" - label { - value: 65535 - label: "All Endpoints" - } - range { - min: 0 - max: 65535 - } - } - field { - type: UINT8 - name: "policy" - } - } - set_response { - } - set_sub_device_range: ROOT_DEVICE -} -pid { - name: "BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION" - value: 32721 - get_request { - field { - type: UINT8 - name: "policy_setting" - } - } - get_response { - field { - type: UINT8 - name: "policy_setting" - } - field { - type: STRING - name: "description" - max_size: 32 - } - } - get_sub_device_range: ROOT_DEVICE -} -pid { - name: "BACKGROUND_STATUS_TYPE" - value: 32722 - get_request { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - } - get_response { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - field { - type: UINT8 - name: "status_type" - } - } - get_sub_device_range: ROOT_DEVICE - set_request { - field { - type: UINT16 - name: "endpoint_id" - label { - value: 65535 - label: "All Endpoints" - } - range { - min: 0 - max: 65535 - } - } - field { - type: UINT8 - name: "status_type" - } - } - set_response { - } - set_sub_device_range: ROOT_DEVICE -} -pid { - name: "QUEUED_STATUS_ENDPOINT_COLLECTION" - value: 32723 - set_request { - field { - type: UINT16 - name: "endpoint_id" - label { - value: 65535 - label: "All Endpoints" - } - range { - min: 0 - max: 65534 - } - } - field { - type: UINT8 - name: "status_type" - } - } - set_response { - } - set_sub_device_range: ROOT_DEVICE -} -pid { - name: "QUEUED_STATUS_UID_COLLECTION" - value: 32724 - set_request { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - field { - type: UID - name: "target_uid" - } - field { - type: UINT8 - name: "status_type" - } - } - set_response { - } - set_sub_device_range: ROOT_DEVICE -} -pid { - name: "ENDPOINT_LIST" - value: 32736 - get_request { - } - get_response { - field { - type: UINT32 - name: "list_change_number" - } - field { - type: GROUP - name: "endpoints" - field { - type: UINT16 - name: "endpoint_id" - } - } - } - get_sub_device_range: ROOT_DEVICE -} -pid { - name: "ENDPOINT_TO_UNIVERSE" - value: 32737 - get_request { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - } - get_response { - field { - type: UINT16 - name: "endpoint_id" - } - field { - type: UINT16 - name: "universe" - label { - value: 65535 - label: "Composite" - } - range { - min: 1 - max: 65535 - } - } - field { - type: BOOL - name: "physical" - } - } - get_sub_device_range: ROOT_DEVICE - set_request { - field { - type: UINT16 - name: "endpoint_id" - label { - value: 65535 - label: "All Endpoints" - } - range { - min: 0 - max: 65535 - } - } - field { - type: UINT16 - name: "universe" - label { - value: 65535 - label: "Composite" - } - range { - min: 1 - max: 63999 - } - } - } - set_response { - } - set_sub_device_range: ROOT_DEVICE -} -pid { - name: "RDM_TRAFFIC_ENABLE" - value: 32738 - get_request { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - } - get_response { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - field { - type: BOOL - name: "rdm_enabled" - } - } - get_sub_device_range: ROOT_DEVICE - set_request { - field { - type: UINT16 - name: "endpoint_id" - label { - value: 65535 - label: "All Endpoints" - } - range { - min: 0 - max: 65535 - } - } - field { - type: BOOL - name: "rdm_enabled" - } - } - set_response { - } - set_sub_device_range: ROOT_DEVICE -} -pid { - name: "ENDPOINT_MODE" - value: 32739 - get_request { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - } - get_response { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - field { - type: UINT8 - name: "endpoint_function" - label { - value: 0 - label: "Disabled" - } - label { - value: 1 - label: "Input" - } - label { - value: 2 - label: "Output" - } - } - } - get_sub_device_range: ROOT_DEVICE - set_request { - field { - type: UINT16 - name: "endpoint_id" - label { - value: 65535 - label: "All Endpoints" - } - range { - min: 0 - max: 65535 - } - } - field { - type: UINT8 - name: "endpoint_function" - label { - value: 0 - label: "Disabled" - } - label { - value: 1 - label: "Input" - } - label { - value: 2 - label: "Output" - } - } - } - set_response { - } - set_sub_device_range: ROOT_DEVICE -} -pid { - name: "ENDPOINT_LABEL" - value: 32740 - get_request { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - } - get_response { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - field { - type: STRING - name: "endpoint_label" - max_size: 32 - } - } - get_sub_device_range: ROOT_DEVICE - set_request { - field { - type: UINT16 - name: "endpoint_id" - label { - value: 65535 - label: "All Endpoints" - } - range { - min: 0 - max: 65535 - } - } - field { - type: STRING - name: "endpoint_label" - max_size: 32 - } - } - set_response { - } - set_sub_device_range: ROOT_DEVICE -} -pid { - name: "DISCOVERY_STATE" - value: 32741 - get_request { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - } - get_response { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - field { - type: UINT16 - name: "device_count" - label { - value: 65535 - label: "Not Supported" - } - range { - min: 0 - max: 65534 - } - } - field { - type: UINT8 - name: "discovery_state" - label { - value: 0 - label: "Not Run" - } - label { - value: 1 - label: "Completed" - } - label { - value: 2 - label: "Incremental" - } - label { - value: 3 - label: "Full" - } - } - } - get_sub_device_range: ROOT_DEVICE - set_request { - field { - type: UINT16 - name: "endpoint_id" - label { - value: 65535 - label: "All Endpoints" - } - range { - min: 0 - max: 65535 - } - } - field { - type: UINT8 - name: "discovery_state" - label { - value: 0 - label: "Not Run" - } - label { - value: 1 - label: "Completed" - } - label { - value: 2 - label: "Incremental" - } - label { - value: 3 - label: "Full" - } - } - } - set_response { - } - set_sub_device_range: ROOT_DEVICE -} -pid { - name: "ENDPOINT_TIMING" - value: 32742 - get_request { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - } - get_response { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - field { - type: UINT8 - name: "current_setting" - } - field { - type: UINT8 - name: "number_of_settings" - } - } - get_sub_device_range: ROOT_DEVICE - set_request { - field { - type: UINT16 - name: "endpoint_id" - label { - value: 65535 - label: "All Endpoints" - } - range { - min: 0 - max: 65535 - } - } - field { - type: UINT8 - name: "timing_setting" - } - } - set_response { - } - set_sub_device_range: ROOT_DEVICE -} -pid { - name: "ENDPOINT_TIMING_DESCRIPTION" - value: 32743 - get_request { - field { - type: UINT8 - name: "timing_setting" - } - } - get_response { - field { - type: UINT8 - name: "timing_setting" - } - field { - type: STRING - name: "description" - max_size: 32 - } - } - get_sub_device_range: ROOT_DEVICE -} -pid { - name: "BINDING_CONTROL_FIELDS" - value: 32744 - get_request { - field { - type: UID - name: "uid" - } - } - get_response { - field { - type: UID - name: "uid" - } - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - field { - type: UINT16 - name: "control_bits" - } - field { - type: UID - name: "binding_uid" - } - } - get_sub_device_range: ROOT_DEVICE -} -pid { - name: "ENDPOINT_IDENTIFY" - value: 32745 - get_request { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - } - get_response { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - field { - type: BOOL - name: "identify_state" - } - } - get_sub_device_range: ROOT_DEVICE - set_request { - field { - type: UINT16 - name: "endpoint_id" - label { - value: 65535 - label: "All Endpoints" - } - range { - min: 0 - max: 65535 - } - } - field { - type: BOOL - name: "identify_state" - } - } - set_response { - } - set_sub_device_range: ROOT_DEVICE -} -pid { - name: "BACKGROUND_DISCOVERY" - value: 32746 - get_request { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - } - get_response { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - field { - type: BOOL - name: "background_discovery" - } - } - get_sub_device_range: ROOT_DEVICE - set_request { - field { - type: UINT16 - name: "endpoint_id" - label { - value: 65535 - label: "All Endpoints" - } - range { - min: 0 - max: 65535 - } - } - field { - type: BOOL - name: "background_discovery" - } - } - set_response { - } - set_sub_device_range: ROOT_DEVICE -} -pid { - name: "ENDPOINT_DEVICE_LIST_CHANGE" - value: 32747 - get_request { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - } - get_response { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - field { - type: UINT32 - name: "list_change_number" - } - } - get_sub_device_range: ROOT_DEVICE -} -pid { - name: "ENDPOINT_DEVICES" - value: 32748 - get_request { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - } - get_response { - field { - type: UINT16 - name: "endpoint_id" - range { - min: 0 - max: 65534 - } - } - field { - type: UINT32 - name: "list_change_number" - } - field { - type: GROUP - name: "uids" - field { - type: UID - name: "uid" - } - } - } - get_sub_device_range: ROOT_DEVICE -} -pid { - name: "TCP_COMMS_STATUS" - value: 32749 - get_request { - } - get_response { - field { - type: IPV4 - name: "controller_ip" - label { - value: 0 - label: "No Connection" - } - } - field { - type: UINT16 - name: "unhealthy_events" - } - field { - type: UINT16 - name: "connection_events" - } - } - get_sub_device_range: ROOT_DEVICE - set_request { - } - set_response { - } - set_sub_device_range: ROOT_DEVICE -} -pid { - name: "ENDPOINT_LIST_CHANGE" - value: 32750 - get_request { - } - get_response { - field { - type: UINT32 - name: "list_change_number" - } - } - get_sub_device_range: ROOT_DEVICE -} -version: 1438559429 +version: 1582652719 diff --git a/data/rdm/manufacturer_names.proto b/data/rdm/manufacturer_names.proto index 25d58cca15..d04d83dfc2 100644 --- a/data/rdm/manufacturer_names.proto +++ b/data/rdm/manufacturer_names.proto @@ -1,7 +1,19 @@ +manufacturer { + manufacturer_id: 2279 + manufacturer_name: "3A Guangzhou Electronics Co., Ltd" +} manufacturer { manufacturer_id: 1966 manufacturer_name: "A-LITE B.V." } +manufacturer { + manufacturer_id: 262 + manufacturer_name: "A.L.A. Equipment Company Ltd." +} +manufacturer { + manufacturer_id: 109 + manufacturer_name: "AA Tasarim Ltd." +} manufacturer { manufacturer_id: 2223 manufacturer_name: "AAdyn Technology" @@ -22,6 +34,10 @@ manufacturer { manufacturer_id: 16707 manufacturer_name: "AC Lasers" } +manufacturer { + manufacturer_id: 111 + manufacturer_name: "AC Power Distribution/ACT Lighting Inc." +} manufacturer { manufacturer_id: 5388 manufacturer_name: "ACASS SYSTEMS LLC" @@ -52,7 +68,11 @@ manufacturer { } manufacturer { manufacturer_id: 16709 - manufacturer_name: "ADE ELETTRONICA srl " + manufacturer_name: "ADE ELETTRONICA srl" +} +manufacturer { + manufacturer_id: 6400 + manufacturer_name: "ADJ Products LLC" } manufacturer { manufacturer_id: 2202 @@ -66,6 +86,14 @@ manufacturer { manufacturer_id: 20055 manufacturer_name: "AIM Northwest" } +manufacturer { + manufacturer_id: 106 + manufacturer_name: "AIMTECH Electronik Tasarim Ltd. Sti." +} +manufacturer { + manufacturer_id: 1800 + manufacturer_name: "AK-LIGHT" +} manufacturer { manufacturer_id: 8358 manufacturer_name: "ALADIN Architekturlicht GmbH" @@ -82,6 +110,10 @@ manufacturer { manufacturer_id: 7104 manufacturer_name: "ALS Stanislaw Binkiewicz" } +manufacturer { + manufacturer_id: 1576 + manufacturer_name: "APEX PRO LIGHT CO.,LTD" +} manufacturer { manufacturer_id: 272 manufacturer_name: "APF S.r.l." @@ -90,6 +122,18 @@ manufacturer { manufacturer_id: 2165 manufacturer_name: "ARC Solid-State Lighting Corp." } +manufacturer { + manufacturer_id: 176 + manufacturer_name: "ARENA LUCI s.r.l." +} +manufacturer { + manufacturer_id: 4612 + manufacturer_name: "ARES s.r.l. - Socio Unico" +} +manufacturer { + manufacturer_id: 1973 + manufacturer_name: "ARM Automation, Inc" +} manufacturer { manufacturer_id: 16754 manufacturer_name: "ARNOLD LICHTTECHNIK" @@ -98,6 +142,14 @@ manufacturer { manufacturer_id: 8377 manufacturer_name: "ARRI -- Arnold & Richter Cine Technik GmbH & Co. Betriebs KG" } +manufacturer { + manufacturer_id: 20594 + manufacturer_name: "ARRI Rental Deutschland GmbH" +} +manufacturer { + manufacturer_id: 16710 + manufacturer_name: "AUS FX" +} manufacturer { manufacturer_id: 21553 manufacturer_name: "AUTOLUX Handels- und ProduktionsgmbH" @@ -122,10 +174,18 @@ manufacturer { manufacturer_id: 8365 manufacturer_name: "AZ e-lite Pte Ltd" } +manufacturer { + manufacturer_id: 1624 + manufacturer_name: "AZCOLOR LITE CO., LIMITED" +} manufacturer { manufacturer_id: 5860 manufacturer_name: "Aboutshow Color Light Co., LTD" } +manufacturer { + manufacturer_id: 2 + manufacturer_name: "Abstract AVR Ltd." +} manufacturer { manufacturer_id: 714 manufacturer_name: "Acclaim Lighting" @@ -182,6 +242,10 @@ manufacturer { manufacturer_id: 16689 manufacturer_name: "Altman Stage Lighting" } +manufacturer { + manufacturer_id: 188 + manufacturer_name: "Ambion GmbH (Ambrain)" +} manufacturer { manufacturer_id: 1308 manufacturer_name: "Ambitsel, Inc." @@ -206,6 +270,10 @@ manufacturer { manufacturer_id: 31392 manufacturer_name: "Anaren Inc." } +manufacturer { + manufacturer_id: 120 + manufacturer_name: "Andy Lighting Technology Group Ltd." +} manufacturer { manufacturer_id: 16713 manufacturer_name: "Anidea Engineering, Inc." @@ -234,6 +302,14 @@ manufacturer { manufacturer_id: 2483 manufacturer_name: "Aquatique Show Int." } +manufacturer { + manufacturer_id: 28652 + manufacturer_name: "Arc Lighting Co. Ltd." +} +manufacturer { + manufacturer_id: 470 + manufacturer_name: "Argent Data Systems, Inc." +} manufacturer { manufacturer_id: 2497 manufacturer_name: "Argetron Elektrik Elektronik Organizasyon Gida San. ve Dis Tic. Ltd. Sti." @@ -242,6 +318,14 @@ manufacturer { manufacturer_id: 16724 manufacturer_name: "Arnold Tang Productions" } +manufacturer { + manufacturer_id: 640 + manufacturer_name: "Arrigo Lighting" +} +manufacturer { + manufacturer_id: 418 + manufacturer_name: "Art Lighting Production, s.r.o." +} manufacturer { manufacturer_id: 515 manufacturer_name: "Artemide S.p.A" @@ -254,10 +338,18 @@ manufacturer { manufacturer_id: 16716 manufacturer_name: "Artistic Licence Engineering Ltd." } +manufacturer { + manufacturer_id: 366 + manufacturer_name: "Artled Technology Corp." +} manufacturer { manufacturer_id: 16755 manufacturer_name: "Astera LED Technology GmbH" } +manufacturer { + manufacturer_id: 2050 + manufacturer_name: "AstralPool" +} manufacturer { manufacturer_id: 16723 manufacturer_name: "Audio Scene" @@ -298,6 +390,14 @@ manufacturer { manufacturer_id: 8482 manufacturer_name: "BEGLEC NV" } +manufacturer { + manufacturer_id: 446 + manufacturer_name: "BEN-RI Electronica S.A." +} +manufacturer { + manufacturer_id: 1986 + manufacturer_name: "BOOQlight BV" +} manufacturer { manufacturer_id: 16975 manufacturer_name: "BOTEX" @@ -306,6 +406,10 @@ manufacturer { manufacturer_id: 276 manufacturer_name: "BSL Lighting" } +manufacturer { + manufacturer_id: 2156 + manufacturer_name: "Bafa Elektronik ve Isik Tasarimlari Sanayii Ticaret LTD Sti." +} manufacturer { manufacturer_id: 29541 manufacturer_name: "Ballantyne Strong Inc." @@ -322,14 +426,30 @@ manufacturer { manufacturer_id: 2445 manufacturer_name: "Batmink Ltd." } +manufacturer { + manufacturer_id: 1898 + manufacturer_name: "BeamZ (Tronios B.V.)" +} manufacturer { manufacturer_id: 1666 - manufacturer_name: "Beijing Ming Rui Lighting Technology Co., Ltd. " + manufacturer_name: "Beijing Ming Rui Lighting Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 437 + manufacturer_name: "Beijing Soft Rock Technology Development Co., Ltd." +} +manufacturer { + manufacturer_id: 2313 + manufacturer_name: "Beijing Starlight Electronics Co., Ltd." } manufacturer { manufacturer_id: 1102 manufacturer_name: "Ben Peoples Industries, LLC" } +manufacturer { + manufacturer_id: 26985 + manufacturer_name: "Better Way Lighting" +} manufacturer { manufacturer_id: 675 manufacturer_name: "Big Bang Lightning" @@ -350,6 +470,10 @@ manufacturer { manufacturer_id: 15100 manufacturer_name: "Black Tank Engineering" } +manufacturer { + manufacturer_id: 513 + manufacturer_name: "Blinkinlabs, LLC" +} manufacturer { manufacturer_id: 260 manufacturer_name: "Blizzard Lighting, LLC" @@ -366,10 +490,22 @@ manufacturer { manufacturer_id: 2180 manufacturer_name: "Bright Group" } +manufacturer { + manufacturer_id: 2106 + manufacturer_name: "Bright Ideas Custom Electronics Inc." +} +manufacturer { + manufacturer_id: 2195 + manufacturer_name: "Brighten LED Lighting Limited" +} manufacturer { manufacturer_id: 1487 manufacturer_name: "Brighten Technology Development Co., Ltd." } +manufacturer { + manufacturer_id: 716 + manufacturer_name: "Brightix" +} manufacturer { manufacturer_id: 2429 manufacturer_name: "Brink Electronics" @@ -378,10 +514,18 @@ manufacturer { manufacturer_id: 2484 manufacturer_name: "Brompton Technology Ltd." } +manufacturer { + manufacturer_id: 183 + manufacturer_name: "Bron Elektronik AG" +} manufacturer { manufacturer_id: 8481 manufacturer_name: "Brother,Brother & Sons Aps" } +manufacturer { + manufacturer_id: 1761 + manufacturer_name: "Burck IT GmbH & Co. KG" +} manufacturer { manufacturer_id: 2220 manufacturer_name: "Bushveld Labs" @@ -390,10 +534,18 @@ manufacturer { manufacturer_id: 16965 manufacturer_name: "Bytecraft Entertainment Pty Ltd" } +manufacturer { + manufacturer_id: 8712 + manufacturer_name: "C.I.M.E.S. (Conception Installation Maintenance En Eclairage & Sonorisation)" +} manufacturer { manufacturer_id: 17225 manufacturer_name: "C.I.Tronics Lighting Designers Ltda" } +manufacturer { + manufacturer_id: 1710 + manufacturer_name: "CANARA LIGHTING INDUSTRIES PVT LTD" +} manufacturer { manufacturer_id: 458 manufacturer_name: "CASCADE s.a.s." @@ -414,6 +566,14 @@ manufacturer { manufacturer_id: 25444 manufacturer_name: "CDS advanced technology bv" } +manufacturer { + manufacturer_id: 6648 + manufacturer_name: "CEZOS Spolka z ograniczona odpowiedzialnoscia, sp.k." +} +manufacturer { + manufacturer_id: 119 + manufacturer_name: "CHAMP Licht" +} manufacturer { manufacturer_id: 8612 manufacturer_name: "CHAUVET Lighting" @@ -470,10 +630,18 @@ manufacturer { manufacturer_id: 8617 manufacturer_name: "CaptSystemes" } +manufacturer { + manufacturer_id: 18433 + manufacturer_name: "Capture Visualisation AB" +} manufacturer { manufacturer_id: 812 manufacturer_name: "Carallon Ltd." } +manufacturer { + manufacturer_id: 32490 + manufacturer_name: "Cartwright Engineering" +} manufacturer { manufacturer_id: 2330 manufacturer_name: "Celex LED Technology Ltd." @@ -486,6 +654,10 @@ manufacturer { manufacturer_id: 26646 manufacturer_name: "ChamberPlus Co., Ltd" } +manufacturer { + manufacturer_id: 13621 + manufacturer_name: "ChangshaA Spark Technology Electronics Ltd." +} manufacturer { manufacturer_id: 21360 manufacturer_name: "Chroma-Q" @@ -494,6 +666,10 @@ manufacturer { manufacturer_id: 8629 manufacturer_name: "ChromaCove LLC" } +manufacturer { + manufacturer_id: 13622 + manufacturer_name: "Cindy Professional Lighting Co., Ltd." +} manufacturer { manufacturer_id: 6669 manufacturer_name: "Cineo Lighting" @@ -522,6 +698,10 @@ manufacturer { manufacturer_id: 2153 manufacturer_name: "Club Cannon LLC" } +manufacturer { + manufacturer_id: 1984 + manufacturer_name: "Code Mercenaries GmbH" +} manufacturer { manufacturer_id: 17229 manufacturer_name: "Coemar Spa" @@ -566,10 +746,18 @@ manufacturer { manufacturer_id: 1851 manufacturer_name: "Corsair Technology Ltd." } +manufacturer { + manufacturer_id: 19802 + manufacturer_name: "Covert Science GmbH" +} manufacturer { manufacturer_id: 161 manufacturer_name: "Creative Lighting And Sound Systems Pty Ltd." } +manufacturer { + manufacturer_id: 2353 + manufacturer_name: "Cristal Controles" +} manufacturer { manufacturer_id: 2504 manufacturer_name: "Crystal Fountains Inc." @@ -578,6 +766,18 @@ manufacturer { manufacturer_id: 8609 manufacturer_name: "Culture Crew bvba" } +manufacturer { + manufacturer_id: 2117 + manufacturer_name: "Cush Light LLC" +} +manufacturer { + manufacturer_id: 420 + manufacturer_name: "Custom Effects LED Solutions Inc." +} +manufacturer { + manufacturer_id: 144 + manufacturer_name: "Cyclops Lighting" +} manufacturer { manufacturer_id: 1491 manufacturer_name: "D-LED Illumination Technologies Ltd." @@ -598,6 +798,10 @@ manufacturer { manufacturer_id: 1808 manufacturer_name: "D.T.S. Illuminazione srl" } +manufacturer { + manufacturer_id: 197 + manufacturer_name: "DAGE Stage Lighting Master Co., Ltd." +} manufacturer { manufacturer_id: 17486 manufacturer_name: "DALCNET SRL" @@ -630,6 +834,10 @@ manufacturer { manufacturer_id: 20781 manufacturer_name: "DJPOWER ELECTRONIC STAGE LIGHTING FIXTURE FACTORY (GUANGZHOU)" } +manufacturer { + manufacturer_id: 434 + manufacturer_name: "DJSI Schinstad ANS (Northern Light)" +} manufacturer { manufacturer_id: 13105 manufacturer_name: "DMG Lumiere" @@ -646,14 +854,30 @@ manufacturer { manufacturer_id: 17488 manufacturer_name: "DMXPROFI.EU GmbH i.G." } +manufacturer { + manufacturer_id: 415 + manufacturer_name: "DaisaLed Ltd." +} +manufacturer { + manufacturer_id: 29696 + manufacturer_name: "Danalux" +} manufacturer { manufacturer_id: 25700 manufacturer_name: "Dangeross Design" } +manufacturer { + manufacturer_id: 472 + manufacturer_name: "Daniel Large Lighting" +} manufacturer { manufacturer_id: 2328 manufacturer_name: "David O Smith Design" } +manufacturer { + manufacturer_id: 165 + manufacturer_name: "Delta Electronics, Inc." +} manufacturer { manufacturer_id: 17185 manufacturer_name: "Design Partners of Canada" @@ -670,6 +894,14 @@ manufacturer { manufacturer_id: 17477 manufacturer_name: "Dezelectric Kft." } +manufacturer { + manufacturer_id: 773 + manufacturer_name: "DiCon Fiberoptics, Inc." +} +manufacturer { + manufacturer_id: 182 + manufacturer_name: "DiGidot Technologies BV" +} manufacturer { manufacturer_id: 17513 manufacturer_name: "Diamante Lighting Srl" @@ -690,6 +922,10 @@ manufacturer { manufacturer_id: 30600 manufacturer_name: "DigitaLicht AG" } +manufacturer { + manufacturer_id: 187 + manufacturer_name: "Digital Lighting Engineering & Design, LLC" +} manufacturer { manufacturer_id: 2447 manufacturer_name: "Digital Sputnik Lighting" @@ -698,6 +934,18 @@ manufacturer { manufacturer_id: 31515 manufacturer_name: "DimLight Ltd." } +manufacturer { + manufacturer_id: 428 + manufacturer_name: "DongGuan Phcistar Optoelectronics Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 2306 + manufacturer_name: "DongGuan Betterway Lighting Co.,Ltd" +} +manufacturer { + manufacturer_id: 419 + manufacturer_name: "Dongguan Yongya Technology Co., Ltd" +} manufacturer { manufacturer_id: 17478 manufacturer_name: "Doug Fleenor Design, Inc." @@ -734,6 +982,10 @@ manufacturer { manufacturer_id: 17731 manufacturer_name: "EC Elettronica Srl" } +manufacturer { + manufacturer_id: 2245 + manufacturer_name: "EHRGEIZ Lichttechnik GmbH" +} manufacturer { manufacturer_id: 25964 manufacturer_name: "ELC lighting" @@ -754,6 +1006,10 @@ manufacturer { manufacturer_id: 17742 manufacturer_name: "ENTTEC Pty Ltd" } +manufacturer { + manufacturer_id: 521 + manufacturer_name: "ER Productions" +} manufacturer { manufacturer_id: 17747 manufacturer_name: "ERAL srl" @@ -782,17 +1038,25 @@ manufacturer { manufacturer_id: 17733 manufacturer_name: "EastSun Technology Co. Ltd." } +manufacturer { + manufacturer_id: 2056 + manufacturer_name: "Eaton - Zero 88" +} manufacturer { manufacturer_id: 2446 - manufacturer_name: "Ecosense Lighting Company Limited " + manufacturer_name: "Ecosense Lighting Company Limited" +} +manufacturer { + manufacturer_id: 2361 + manufacturer_name: "Edelmann Electronics" } manufacturer { manufacturer_id: 1193 manufacturer_name: "Edward J. Keefe Jr." } manufacturer { - manufacturer_id: 2245 - manufacturer_name: "Ehrgeiz" + manufacturer_id: 159 + manufacturer_name: "Efore SpA" } manufacturer { manufacturer_id: 2399 @@ -800,7 +1064,11 @@ manufacturer { } manufacturer { manufacturer_id: 8870 - manufacturer_name: "Elation Lighting" + manufacturer_name: "Elation Lighting Inc." +} +manufacturer { + manufacturer_id: 411 + manufacturer_name: "ElectroTAS Soluciones Profesionales" } manufacturer { manufacturer_id: 5806 @@ -822,6 +1090,10 @@ manufacturer { manufacturer_id: 17772 manufacturer_name: "Element Labs Inc." } +manufacturer { + manufacturer_id: 2342 + manufacturer_name: "Elumeros Lighting Limited" +} manufacturer { manufacturer_id: 18518 manufacturer_name: "Enfis Ltd" @@ -854,6 +1126,14 @@ manufacturer { manufacturer_id: 1766 manufacturer_name: "Equipson S.A." } +manufacturer { + manufacturer_id: 122 + manufacturer_name: "Equivalent" +} +manufacturer { + manufacturer_id: 25939 + manufacturer_name: "EtherShow" +} manufacturer { manufacturer_id: 8889 manufacturer_name: "Etherlight" @@ -874,6 +1154,14 @@ manufacturer { manufacturer_id: 1344 manufacturer_name: "EverBrighten Co., Ltd." } +manufacturer { + manufacturer_id: 28653 + manufacturer_name: "Explorentis" +} +manufacturer { + manufacturer_id: 1875 + manufacturer_name: "F&V Europe B.V." +} manufacturer { manufacturer_id: 1930 manufacturer_name: "FATEC sarl" @@ -886,6 +1174,10 @@ manufacturer { manufacturer_id: 1060 manufacturer_name: "FLUX ECLAIRAGE" } +manufacturer { + manufacturer_id: 2193 + manufacturer_name: "Feiner Lichttechnik GMBH" +} manufacturer { manufacturer_id: 16706 manufacturer_name: "Filmgear, Inc." @@ -910,13 +1202,21 @@ manufacturer { manufacturer_id: 2191 manufacturer_name: "First Design System Inc." } +manufacturer { + manufacturer_id: 13620 + manufacturer_name: "Five4, LLC" +} +manufacturer { + manufacturer_id: 108 + manufacturer_name: "Flash-Butrym Sp.J." +} manufacturer { manufacturer_id: 17996 manufacturer_name: "Flashlight/Ampco Holding" } manufacturer { manufacturer_id: 25091 - manufacturer_name: "Flektor " + manufacturer_name: "Flektor" } manufacturer { manufacturer_id: 18006 @@ -926,6 +1226,10 @@ manufacturer { manufacturer_id: 14472 manufacturer_name: "Fly Dragon Lighting Equipment Co.,ltd" } +manufacturer { + manufacturer_id: 2010 + manufacturer_name: "Flytech s.r.l." +} manufacturer { manufacturer_id: 9015 manufacturer_name: "Focon Showtechnic" @@ -938,6 +1242,18 @@ manufacturer { manufacturer_id: 259 manufacturer_name: "Fontana Technologies" } +manufacturer { + manufacturer_id: 2250 + manufacturer_name: "Foshan City Xuandao Optoelectronics Equipment Co., Ltd" +} +manufacturer { + manufacturer_id: 2329 + manufacturer_name: "Foshan Leiyuan Photoelectric Co., LTD" +} +manufacturer { + manufacturer_id: 192 + manufacturer_name: "Foshan Yinhe Lanjing Lighting & Electrical Co., Ltd." +} manufacturer { manufacturer_id: 2466 manufacturer_name: "Fountain People" @@ -946,6 +1262,14 @@ manufacturer { manufacturer_id: 26227 manufacturer_name: "Freescale Semiconductor U.K. Ltd." } +manufacturer { + manufacturer_id: 20483 + manufacturer_name: "Futlight Optoelectronics Co.,Ltd." +} +manufacturer { + manufacturer_id: 18247 + manufacturer_name: "G&G LED Lighting" +} manufacturer { manufacturer_id: 18252 manufacturer_name: "G-LEC Europe GmbH" @@ -954,10 +1278,18 @@ manufacturer { manufacturer_id: 1 manufacturer_name: "GEE" } +manufacturer { + manufacturer_id: 466 + manufacturer_name: "GIP Innovation Tools GmbH" +} manufacturer { manufacturer_id: 26476 manufacturer_name: "GLP German Light Products GmbH" } +manufacturer { + manufacturer_id: 1708 + manufacturer_name: "GOLVER PROJECTS S.L." +} manufacturer { manufacturer_id: 18245 manufacturer_name: "GPE srl" @@ -966,10 +1298,30 @@ manufacturer { manufacturer_id: 2316 manufacturer_name: "GRE Alpha" } +manufacturer { + manufacturer_id: 655 + manufacturer_name: "GRE Alpha Electronics Ltd." +} +manufacturer { + manufacturer_id: 191 + manufacturer_name: "GTR Industries" +} +manufacturer { + manufacturer_id: 1515 + manufacturer_name: "GUANGZHOU BO WEI TE LIGHTING CO.LTD" +} +manufacturer { + manufacturer_id: 1647 + manufacturer_name: "GUANGZHOU CY LIGHTING EQUIPMENT CO.,LTD" +} manufacturer { manufacturer_id: 1721 manufacturer_name: "GUANGZHOU DASEN LIGHTING CORPORATION LIMITED" } +manufacturer { + manufacturer_id: 1678 + manufacturer_name: "GUANGZHOU TEANMA STAGE LIGHTING FACTORY" +} manufacturer { manufacturer_id: 6280 manufacturer_name: "GUANZHOU KAVON STAGE EQUIPMENT CO., LTD." @@ -1022,9 +1374,13 @@ manufacturer { manufacturer_id: 18259 manufacturer_name: "Golden Sea Disco Light Manufacturer" } +manufacturer { + manufacturer_id: 2230 + manufacturer_name: "Graf Lichttechnik UG" +} manufacturer { manufacturer_id: 1167 - manufacturer_name: "Grand Canyon LED Lighting System (Suzhou) Co., Ltd. " + manufacturer_name: "Grand Canyon LED Lighting System (Suzhou) Co., Ltd." } manufacturer { manufacturer_id: 5264 @@ -1038,129 +1394,425 @@ manufacturer { manufacturer_id: 712 manufacturer_name: "Growflux LLC" } +manufacturer { + manufacturer_id: 2288 + manufacturer_name: "Guang Dong LMJ Lighting Co., Ltd" +} +manufacturer { + manufacturer_id: 2215 + manufacturer_name: "GuangZhou Deliya Opto-electronic Tech Co., Ltd" +} +manufacturer { + manufacturer_id: 479 + manufacturer_name: "GuangZhou Dream Lighting Equipment Co., Ltd." +} +manufacturer { + manufacturer_id: 163 + manufacturer_name: "GuangZhou Huanshi Lighting Equipment Co., Limited" +} manufacturer { manufacturer_id: 2176 manufacturer_name: "GuangZhou LiDang Technology Inc." } manufacturer { manufacturer_id: 5536 - manufacturer_name: "GuangZhou MCSWE Technologies, INC " + manufacturer_name: "GuangZhou MCSWE Technologies, INC" +} +manufacturer { + manufacturer_id: 1416 + manufacturer_name: "GuangZhou XiangMing Light Limited" } manufacturer { manufacturer_id: 270 manufacturer_name: "Guangzhou ATON Lighting Technology Co.,Ltd" } manufacturer { - manufacturer_id: 2124 - manufacturer_name: "Guangzhou Ba Lin Electronic Technology Co., Ltd." + manufacturer_id: 2321 + manufacturer_name: "Guangzhou Aceda Professional Lighting Co., Ltd." } manufacturer { - manufacturer_id: 1519 - manufacturer_name: "Guangzhou Chai Yi Light Co., Ltd." + manufacturer_id: 2341 + manufacturer_name: "Guangzhou Aiweidy Lighting Acoustics Equipment Co.,Ltd." } manufacturer { - manufacturer_id: 17491 - manufacturer_name: "Guangzhou Desheng Lighting Industrial Co., Ltd." + manufacturer_id: 142 + manufacturer_name: "Guangzhou Ao Mei Di Stage Lighting Equipment Co.,Ltd." } manufacturer { - manufacturer_id: 767 - manufacturer_name: "Guangzhou Eway Stage Equipment Technology Co., Ltd." + manufacturer_id: 2163 + manufacturer_name: "Guangzhou BKLite Stage Lighting Equipment Co.,LTD" } manufacturer { - manufacturer_id: 2385 - manufacturer_name: "Guangzhou GTD Lighting Technology Co., Ltd " + manufacturer_id: 2124 + manufacturer_name: "Guangzhou Ba Lin Electronic Technology Co., Ltd." } manufacturer { - manufacturer_id: 1240 - manufacturer_name: "Guangzhou Hong Yuan Electronic Technology Co., LTD." + manufacturer_id: 185 + manufacturer_name: "Guangzhou Baiyun District Sanjie Eletronic Stage Lighting Audio Equipment Factory" } manufacturer { - manufacturer_id: 1208 - manufacturer_name: "Guangzhou Hongcai Stage Equipment Co., Ltd." + manufacturer_id: 478 + manufacturer_name: "Guangzhou Baiyun Xinxiang Lighting Equipment Factory (XPRO LIGHT)" } manufacturer { - manufacturer_id: 456 - manufacturer_name: "Guangzhou JINLIN Stage Lighting Equipment Co., Ltd. " + manufacturer_id: 2408 + manufacturer_name: "Guangzhou Beyond Lighting Co., Limited." } manufacturer { - manufacturer_id: 783 - manufacturer_name: "Guangzhou Litewise Lighting Equipments Co., Ltd. dba \"EK Lights\"" + manufacturer_id: 131 + manufacturer_name: "Guangzhou Bright Moon Technology Co., Ltd." } manufacturer { - manufacturer_id: 1088 - manufacturer_name: "Guangzhou VAS Lighting Co., Ltd." + manufacturer_id: 2235 + manufacturer_name: "Guangzhou CHEN Electronic Technology Co., Ltd." } manufacturer { - manufacturer_id: 14474 - manufacturer_name: "Guangzhou Yajiang (Yagang - Silver Star) Photoelectric Equipment Ltd." + manufacturer_id: 1519 + manufacturer_name: "Guangzhou Chai Yi Light Co., Ltd." } manufacturer { - manufacturer_id: 9249 - manufacturer_name: "HB-Laserkomponenten GmbH" + manufacturer_id: 2348 + manufacturer_name: "Guangzhou Chaoran Computer Co., Ltd." } manufacturer { - manufacturer_id: 18508 - manufacturer_name: "HBE Lighting Systems" + manufacturer_id: 2325 + manufacturer_name: "Guangzhou Chuangfeng Photoelectric Equipment Co., Ltd." } manufacturer { - manufacturer_id: 2061 - manufacturer_name: "HBJ Elektronik" + manufacturer_id: 20544 + manufacturer_name: "Guangzhou Color Imagination LED Lighting Ltd." } manufacturer { - manufacturer_id: 2362 - manufacturer_name: "HDT impex s.r.o." + manufacturer_id: 196 + manufacturer_name: "Guangzhou Dahe Electronic Technology Co. Ltd." } manufacturer { - manufacturer_id: 26732 - manufacturer_name: "HERA LED" + manufacturer_id: 474 + manufacturer_name: "Guangzhou Daisy Electronic Technology Co., Ltd." } manufacturer { - manufacturer_id: 32097 - manufacturer_name: "HMB|TEC GmbH" + manufacturer_id: 17491 + manufacturer_name: "Guangzhou Desheng Lighting Industrial Co., Ltd." } manufacturer { - manufacturer_id: 4626 - manufacturer_name: "HPL Light Company" + manufacturer_id: 2323 + manufacturer_name: "Guangzhou ECK Light Equipment Company Limited" } manufacturer { - manufacturer_id: 5220 - manufacturer_name: "HUMAL Elektroonika OU" + manufacturer_id: 2419 + manufacturer_name: "Guangzhou Eagle Wei Photoelectric Technology Co., Ltd." } manufacturer { - manufacturer_id: 9328 - manufacturer_name: "Hale Microsystems LLC" + manufacturer_id: 767 + manufacturer_name: "Guangzhou Eway Stage Equipment Technology Co., Ltd." } manufacturer { - manufacturer_id: 170 - manufacturer_name: "Hangzhou Easun Technology Co., Ltd." + manufacturer_id: 158 + manufacturer_name: "Guangzhou Flying Butterfly Stage Lighting Equipment Co., Ltd." } manufacturer { - manufacturer_id: 2339 - manufacturer_name: "Hangzhou Roleds Lighting System Co., Ltd." + manufacturer_id: 1955 + manufacturer_name: "Guangzhou GBR PROLIGHT GROUP CO.,LTD (GBR PROLIGHT)" } manufacturer { - manufacturer_id: 264 - manufacturer_name: "Haya Lighting Equipment Limited" + manufacturer_id: 2385 + manufacturer_name: "Guangzhou GTD Lighting Technology Co., Ltd" } manufacturer { - manufacturer_id: 25626 - manufacturer_name: "Heliospectra AB" + manufacturer_id: 2210 + manufacturer_name: "Guangzhou Gesida Light Equipment Co., Ltd." } manufacturer { - manufacturer_id: 9266 - manufacturer_name: "Helvar Ltd" + manufacturer_id: 2047 + manufacturer_name: "Guangzhou HOMEI LIGHT Manufacturer" } manufacturer { - manufacturer_id: 19538 - manufacturer_name: "High End Systems Inc." + manufacturer_id: 154 + manufacturer_name: "Guangzhou Haoyang Electronic Co., Ltd." } manufacturer { - manufacturer_id: 2186 - manufacturer_name: "Highendled Electronics Company Limited" + manufacturer_id: 2158 + manufacturer_name: "Guangzhou Hi-LTTE Electronics Technology Co.,Ltd" } manufacturer { - manufacturer_id: 721 - manufacturer_name: "Hoffmeister Leuchten GmbH" + manufacturer_id: 1240 + manufacturer_name: "Guangzhou Hong Yuan Electronic Technology Co., LTD." +} +manufacturer { + manufacturer_id: 1208 + manufacturer_name: "Guangzhou Hongcai Stage Equipment Co., Ltd." +} +manufacturer { + manufacturer_id: 2363 + manufacturer_name: "Guangzhou Hongmingwei Stage Lighting Co., Ltd." +} +manufacturer { + manufacturer_id: 282 + manufacturer_name: "Guangzhou Hotion Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 2233 + manufacturer_name: "Guangzhou Hua Rong Electronic Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 2423 + manufacturer_name: "Guangzhou HuaYong Intelligent Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 2357 + manufacturer_name: "Guangzhou Huadu District Richa Lighting Equipment Factory" +} +manufacturer { + manufacturer_id: 113 + manufacturer_name: "Guangzhou Huaxinyuan Electronics Co., Ltd." +} +manufacturer { + manufacturer_id: 28416 + manufacturer_name: "Guangzhou Huaying Stage Lighting Equipment Co. Ltd." +} +manufacturer { + manufacturer_id: 456 + manufacturer_name: "Guangzhou JINLIN Stage Lighting Equipment Co., Ltd." +} +manufacturer { + manufacturer_id: 155 + manufacturer_name: "Guangzhou Jiawei Electronic Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 2275 + manufacturer_name: "Guangzhou JinZhiHui Electronic Technology Co.,Ltd." +} +manufacturer { + manufacturer_id: 6152 + manufacturer_name: "Guangzhou Jinye Electronic Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 2367 + manufacturer_name: "Guangzhou Julong Platform Lighting Equipment Factory" +} +manufacturer { + manufacturer_id: 198 + manufacturer_name: "Guangzhou Lantian Electronic Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 138 + manufacturer_name: "Guangzhou Lees Electronics Co., Ltd." +} +manufacturer { + manufacturer_id: 2347 + manufacturer_name: "Guangzhou Lightful Stage Lighting&Sound Equipment Co,.Ltd." +} +manufacturer { + manufacturer_id: 2373 + manufacturer_name: "Guangzhou Lin Xiang Stage Lighting Equipment CO.,LTD" +} +manufacturer { + manufacturer_id: 2189 + manufacturer_name: "Guangzhou Ling Yang lighting Science and Technology Co.,Ltd" +} +manufacturer { + manufacturer_id: 783 + manufacturer_name: "Guangzhou Litewise Lighting Equipments Co., Ltd. dba \"EK Lights\"" +} +manufacturer { + manufacturer_id: 2138 + manufacturer_name: "Guangzhou Ming Jing Stage Light Equipment Co., Ltd." +} +manufacturer { + manufacturer_id: 141 + manufacturer_name: "Guangzhou Minghao Electronic Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 2343 + manufacturer_name: "Guangzhou Mingying Electronic Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 2125 + manufacturer_name: "Guangzhou NECO Stage Lighting Factory" +} +manufacturer { + manufacturer_id: 133 + manufacturer_name: "Guangzhou Nanshi Light Equipment Co., Ltd." +} +manufacturer { + manufacturer_id: 177 + manufacturer_name: "Guangzhou Omarte Lighting Co., Ltd." +} +manufacturer { + manufacturer_id: 785 + manufacturer_name: "Guangzhou PUGUANG Electronic Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 2262 + manufacturer_name: "Guangzhou Precision Vision Intelligent Equipment Co, Ltd" +} +manufacturer { + manufacturer_id: 2287 + manufacturer_name: "Guangzhou RuiYang lighting technology co. LTD." +} +manufacturer { + manufacturer_id: 2252 + manufacturer_name: "Guangzhou Santu Stage Lighting Equipment Co.Ltd" +} +manufacturer { + manufacturer_id: 2351 + manufacturer_name: "Guangzhou Shinelight Stage Equipment Factory" +} +manufacturer { + manufacturer_id: 145 + manufacturer_name: "Guangzhou Shuozhi Optoelectronic Technology Co., Ltd. (Konelite)" +} +manufacturer { + manufacturer_id: 2243 + manufacturer_name: "Guangzhou Spark Stage Equipment Co. Ltd" +} +manufacturer { + manufacturer_id: 2386 + manufacturer_name: "Guangzhou Sunway Entertainment Equipment Co., Ltd." +} +manufacturer { + manufacturer_id: 1088 + manufacturer_name: "Guangzhou VAS Lighting Co., Ltd." +} +manufacturer { + manufacturer_id: 2360 + manufacturer_name: "Guangzhou Vanray Lighting Equipment CO.,Ltd." +} +manufacturer { + manufacturer_id: 1861 + manufacturer_name: "Guangzhou Wingo Stage Light Co., Ltd" +} +manufacturer { + manufacturer_id: 2413 + manufacturer_name: "Guangzhou Xin Yilong Stage Lighting Equipment Co., Limited" +} +manufacturer { + manufacturer_id: 2500 + manufacturer_name: "Guangzhou XinHuang Industrial Co., Ltd." +} +manufacturer { + manufacturer_id: 786 + manufacturer_name: "Guangzhou Xingkong Studio Lighting Co., Ltd." +} +manufacturer { + manufacturer_id: 6586 + manufacturer_name: "Guangzhou Xinzhijie Photoelectric Co., Ltd." +} +manufacturer { + manufacturer_id: 136 + manufacturer_name: "Guangzhou YaFeng Optoelectronic Equipment Co., Ltd." +} +manufacturer { + manufacturer_id: 14474 + manufacturer_name: "Guangzhou Yajiang (Yagang - Silver Star) Photoelectric Equipment Ltd." +} +manufacturer { + manufacturer_id: 399 + manufacturer_name: "Guangzhou YiCheng Light Industry Ltd." +} +manufacturer { + manufacturer_id: 1542 + manufacturer_name: "Guangzhou YiGuang Stage Lighting Co., Ltd." +} +manufacturer { + manufacturer_id: 2516 + manufacturer_name: "Guangzhou Yilaiming Photoelectric Technology Co., Ltd" +} +manufacturer { + manufacturer_id: 32488 + manufacturer_name: "Guangzhou Yingfeng Lighting Equipment Co., Ltd." +} +manufacturer { + manufacturer_id: 114 + manufacturer_name: "Guangzhou Zenith Aurora Lighting Co., Ltd." +} +manufacturer { + manufacturer_id: 2337 + manufacturer_name: "Guangzhou mengyi stage lighting equipment co., LTD." +} +manufacturer { + manufacturer_id: 1549 + manufacturer_name: "HANIL TNC CO.,LTD" +} +manufacturer { + manufacturer_id: 9249 + manufacturer_name: "HB-Laserkomponenten GmbH" +} +manufacturer { + manufacturer_id: 18508 + manufacturer_name: "HBE Lighting Systems" +} +manufacturer { + manufacturer_id: 2061 + manufacturer_name: "HBJ Elektronik" +} +manufacturer { + manufacturer_id: 2362 + manufacturer_name: "HDT impex s.r.o." +} +manufacturer { + manufacturer_id: 26732 + manufacturer_name: "HERA LED" +} +manufacturer { + manufacturer_id: 32097 + manufacturer_name: "HMB|TEC GmbH" +} +manufacturer { + manufacturer_id: 4626 + manufacturer_name: "HPL Light Company" +} +manufacturer { + manufacturer_id: 5220 + manufacturer_name: "HUMAL Elektroonika OU" +} +manufacturer { + manufacturer_id: 1620 + manufacturer_name: "HUNAN XIANG CAIXU FILM AND TELEVISION CULTURE CO.LTD" +} +manufacturer { + manufacturer_id: 9328 + manufacturer_name: "Hale Microsystems LLC" +} +manufacturer { + manufacturer_id: 170 + manufacturer_name: "Hangzhou Easun Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 2339 + manufacturer_name: "Hangzhou Roleds Lighting System Co., Ltd." +} +manufacturer { + manufacturer_id: 264 + manufacturer_name: "Haya Lighting Equipment Limited" +} +manufacturer { + manufacturer_id: 25626 + manufacturer_name: "Heliospectra AB" +} +manufacturer { + manufacturer_id: 9266 + manufacturer_name: "Helvar Ltd" +} +manufacturer { + manufacturer_id: 422 + manufacturer_name: "Hengmei Lighting Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 19538 + manufacturer_name: "High End Systems Inc." +} +manufacturer { + manufacturer_id: 2186 + manufacturer_name: "Highendled Electronics Company Limited" +} +manufacturer { + manufacturer_id: 365 + manufacturer_name: "Hive Lighting" +} +manufacturer { + manufacturer_id: 721 + manufacturer_name: "Hoffmeister Leuchten GmbH" } manufacturer { manufacturer_id: 18511 @@ -1170,6 +1822,10 @@ manufacturer { manufacturer_id: 4858 manufacturer_name: "Hollywood Rentals LLC" } +manufacturer { + manufacturer_id: 2048 + manufacturer_name: "Hongyeah Light" +} manufacturer { manufacturer_id: 18499 manufacturer_name: "Horizon Control Inc." @@ -1178,10 +1834,30 @@ manufacturer { manufacturer_id: 18501 manufacturer_name: "Howard Eaton Lighting Ltd." } +manufacturer { + manufacturer_id: 20481 + manufacturer_name: "Hua Yuan Ke Tai" +} manufacturer { manufacturer_id: 26725 manufacturer_name: "Hubbell Entertainment, Inc." } +manufacturer { + manufacturer_id: 124 + manufacturer_name: "Huizhou Desay Intelligent Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 2359 + manufacturer_name: "Huizhou Zhonghan Electronic Technology Co., Ltd" +} +manufacturer { + manufacturer_id: 431 + manufacturer_name: "Hunan Minghe Opto Tech Co., Ltd." +} +manufacturer { + manufacturer_id: 2160 + manufacturer_name: "Hunan YESTECH Optoelectronic Co., Ltd" +} manufacturer { manufacturer_id: 9258 manufacturer_name: "Hungaroflash" @@ -1190,10 +1866,6 @@ manufacturer { manufacturer_id: 18500 manufacturer_name: "HxDx" } -manufacturer { - manufacturer_id: 459 - manufacturer_name: "I-Light USA, Inc." -} manufacturer { manufacturer_id: 18764 manufacturer_name: "I-Lum" @@ -1210,10 +1882,22 @@ manufacturer { manufacturer_id: 1669 manufacturer_name: "IBL/ESD-Datentechnik GmbH" } +manufacturer { + manufacturer_id: 480 + manufacturer_name: "IBN Labs Ltd." +} manufacturer { manufacturer_id: 18759 manufacturer_name: "IGuzzini illuminazione spa" } +manufacturer { + manufacturer_id: 459 + manufacturer_name: "ILT Italy SRL" +} +manufacturer { + manufacturer_id: 1880 + manufacturer_name: "IMPOLUX GmbH" +} manufacturer { manufacturer_id: 929 manufacturer_name: "INAREX INC." @@ -1240,7 +1924,7 @@ manufacturer { } manufacturer { manufacturer_id: 776 - manufacturer_name: "ImageCue LLC " + manufacturer_name: "ImageCue LLC" } manufacturer { manufacturer_id: 603 @@ -1248,7 +1932,7 @@ manufacturer { } manufacturer { manufacturer_id: 1527 - manufacturer_name: "Immersive Design Studios Inc. " + manufacturer_name: "Immersive Design Studios Inc." } manufacturer { manufacturer_id: 21314 @@ -1278,10 +1962,18 @@ manufacturer { manufacturer_id: 20951 manufacturer_name: "Innovative Dimmers LLC" } +manufacturer { + manufacturer_id: 28651 + manufacturer_name: "Insight Lighting" +} manufacturer { manufacturer_id: 18757 manufacturer_name: "Insta Elektro GmbH" } +manufacturer { + manufacturer_id: 112 + manufacturer_name: "Instalighting GmbH" +} manufacturer { manufacturer_id: 18771 manufacturer_name: "Integrated System Technologies Ltd." @@ -1290,6 +1982,10 @@ manufacturer { manufacturer_id: 18772 manufacturer_name: "Integrated Theatre, Inc." } +manufacturer { + manufacturer_id: 134 + manufacturer_name: "Intella System Co., Ltd." +} manufacturer { manufacturer_id: 5280 manufacturer_name: "Intense Lighting, LLC" @@ -1306,6 +2002,10 @@ manufacturer { manufacturer_id: 1206 manufacturer_name: "IntiLED" } +manufacturer { + manufacturer_id: 436 + manufacturer_name: "Inventeq B.V." +} manufacturer { manufacturer_id: 263 manufacturer_name: "Inventronics (Hangzhou), Inc." @@ -1314,10 +2014,18 @@ manufacturer { manufacturer_id: 18770 manufacturer_name: "Invisible Rival Incorporated" } +manufacturer { + manufacturer_id: 2379 + manufacturer_name: "Invisua Lighting BV" +} manufacturer { manufacturer_id: 26996 manufacturer_name: "Ittermann electronic GmbH" } +manufacturer { + manufacturer_id: 168 + manufacturer_name: "Iwasaki Electric Co., Ltd." +} manufacturer { manufacturer_id: 19009 manufacturer_name: "JANUS srl" @@ -1326,6 +2034,10 @@ manufacturer { manufacturer_id: 20809 manufacturer_name: "JAP Optoelectronic Ltd." } +manufacturer { + manufacturer_id: 1571 + manufacturer_name: "JAS LIGHTING & SOUND CO., LTD." +} manufacturer { manufacturer_id: 19010 manufacturer_name: "JB-lighting GmbH" @@ -1342,6 +2054,10 @@ manufacturer { manufacturer_id: 19027 manufacturer_name: "JSC 'MFG'" } +manufacturer { + manufacturer_id: 467 + manufacturer_name: "JSC Aksera" +} manufacturer { manufacturer_id: 26724 manufacturer_name: "James Embedded Systems Engineering (JESE Ltd)" @@ -1358,25 +2074,45 @@ manufacturer { manufacturer_id: 19041 manufacturer_name: "Jands Pty Ltd." } +manufacturer { + manufacturer_id: 143 + manufacturer_name: "Jiangmen Coolfish Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 193 + manufacturer_name: "Jingchuang Water Technology" +} manufacturer { manufacturer_id: 682 - manufacturer_name: "Jinnax Opto Technology Co., Ltd. " + manufacturer_name: "Jinnax Opto Technology Co., Ltd." } manufacturer { manufacturer_id: 19020 manufacturer_name: "Johnsson Lighting Technologies AB" } +manufacturer { + manufacturer_id: 148 + manufacturer_name: "Joinmax Display Technology Co., Ltd." +} manufacturer { manufacturer_id: 18993 manufacturer_name: "Joshua 1 Systems Inc." } +manufacturer { + manufacturer_id: 283 + manufacturer_name: "Jumptronic GmbH" +} manufacturer { manufacturer_id: 2129 manufacturer_name: "Junction Inc. Ltd" } manufacturer { manufacturer_id: 2136 - manufacturer_name: "Juno Lighting Group " + manufacturer_name: "Juno Lighting Group" +} +manufacturer { + manufacturer_id: 1414 + manufacturer_name: "K 5600, Inc." } manufacturer { manufacturer_id: 2421 @@ -1390,10 +2126,18 @@ manufacturer { manufacturer_id: 19276 manufacturer_name: "KLH Electronics PLC" } +manufacturer { + manufacturer_id: 2182 + manufacturer_name: "KLIK Systems" +} manufacturer { manufacturer_id: 19277 manufacturer_name: "KMX Inc." } +manufacturer { + manufacturer_id: 1506 + manufacturer_name: "KORRO PLUS" +} manufacturer { manufacturer_id: 27492 manufacturer_name: "Key Delfin" @@ -1438,10 +2182,18 @@ manufacturer { manufacturer_id: 19778 manufacturer_name: "LAN Systems--Midibox project" } +manufacturer { + manufacturer_id: 179 + manufacturer_name: "LANTERN" +} manufacturer { manufacturer_id: 9762 manufacturer_name: "LDDE Vertriebs Gmbh" } +manufacturer { + manufacturer_id: 2118 + manufacturer_name: "LDR - Luci della Ribalta Srl" +} manufacturer { manufacturer_id: 9761 manufacturer_name: "LEADER LIGHT s.r.o." @@ -1454,6 +2206,10 @@ manufacturer { manufacturer_id: 30900 manufacturer_name: "LED Flex Limited" } +manufacturer { + manufacturer_id: 476 + manufacturer_name: "LED Linear GmbH" +} manufacturer { manufacturer_id: 19556 manufacturer_name: "LED Team" @@ -1470,6 +2226,10 @@ manufacturer { manufacturer_id: 1887 manufacturer_name: "LEDEngin Inc." } +manufacturer { + manufacturer_id: 132 + manufacturer_name: "LEDIXIS (Exalux brand)" +} manufacturer { manufacturer_id: 19542 manufacturer_name: "LEDValley Technologies Sdn Bhd" @@ -1494,6 +2254,18 @@ manufacturer { manufacturer_id: 19561 manufacturer_name: "LIGHTOLIER" } +manufacturer { + manufacturer_id: 1746 + manufacturer_name: "LIGHTSTAR (BEIJING) ELECTRONIC CORPORATION" +} +manufacturer { + manufacturer_id: 471 + manufacturer_name: "LIMEDIA" +} +manufacturer { + manufacturer_id: 130 + manufacturer_name: "LKE Lasershowtechnik GmbH" +} manufacturer { manufacturer_id: 2462 manufacturer_name: "LLC Lighting Technologies production" @@ -1510,18 +2282,34 @@ manufacturer { manufacturer_id: 9766 manufacturer_name: "LLT Lichttechnik GmbH&CO.KG" } +manufacturer { + manufacturer_id: 135 + manufacturer_name: "LMBD" +} +manufacturer { + manufacturer_id: 1660 + manufacturer_name: "LOTRONIC SA" +} +manufacturer { + manufacturer_id: 140 + manufacturer_name: "LRX Lighting (Dwight Crane Ltd.)" +} manufacturer { manufacturer_id: 19571 manufacturer_name: "LSC Lighting Systems (Aust) Pty. Ltd." } manufacturer { manufacturer_id: 25088 - manufacturer_name: "LUCITAG Ltd. " + manufacturer_name: "LUCITAG Ltd." } manufacturer { manufacturer_id: 19532 manufacturer_name: "LUMINEX Lighting Control Equipment bvba" } +manufacturer { + manufacturer_id: 19524 + manufacturer_name: "LVDIAN PHOTOELECTRIC SCIENCE TECHNOLOGY LIMITED" +} manufacturer { manufacturer_id: 1109 manufacturer_name: "Lamp & Pencil" @@ -1546,14 +2334,26 @@ manufacturer { manufacturer_id: 19521 manufacturer_name: "LaserAnimation Sollinger GmbH" } +manufacturer { + manufacturer_id: 1596 + manufacturer_name: "LaserNet" +} manufacturer { manufacturer_id: 9776 manufacturer_name: "Laservision Pty Ltd" } +manufacturer { + manufacturer_id: 2026 + manufacturer_name: "Le Maitre Ltd" +} manufacturer { manufacturer_id: 775 manufacturer_name: "Ledium Kft." } +manufacturer { + manufacturer_id: 194 + manufacturer_name: "Ledogen" +} manufacturer { manufacturer_id: 19557 manufacturer_name: "Legargeant and Associates" @@ -1566,6 +2366,10 @@ manufacturer { manufacturer_id: 9763 manufacturer_name: "Leonh Hardware Enterprise Inc." } +manufacturer { + manufacturer_id: 30976 + manufacturer_name: "Leprecon / CAE, Inc." +} manufacturer { manufacturer_id: 17763 manufacturer_name: "Les Eclairages Lou Inc." @@ -1574,6 +2378,10 @@ manufacturer { manufacturer_id: 19780 manufacturer_name: "Les Generateurs de brouillard MDG Fog Generators Ltd." } +manufacturer { + manufacturer_id: 284 + manufacturer_name: "Letong Electronic (Guangzhou) Co., Ltd." +} manufacturer { manufacturer_id: 19525 manufacturer_name: "Leviton Manufacturing Co., Inc." @@ -1582,6 +2390,10 @@ manufacturer { manufacturer_id: 19544 manufacturer_name: "Lex Products Corp." } +manufacturer { + manufacturer_id: 121 + manufacturer_name: "Leyard Opto Electronics Co., Ltd." +} manufacturer { manufacturer_id: 19539 manufacturer_name: "Licht-, Steuer- und Schaltanlagenbau GmbH (LSS GmbH)" @@ -1594,6 +2406,10 @@ manufacturer { manufacturer_id: 14295 manufacturer_name: "Lichttechnik & Sonderbau" } +manufacturer { + manufacturer_id: 416 + manufacturer_name: "Light With LED" +} manufacturer { manufacturer_id: 1696 manufacturer_name: "Light.Audio.Design" @@ -1618,10 +2434,18 @@ manufacturer { manufacturer_id: 19543 manufacturer_name: "LightWild LC" } +manufacturer { + manufacturer_id: 433 + manufacturer_name: "Lightcare A/S" +} manufacturer { manufacturer_id: 923 manufacturer_name: "Lightforce Lasertechnik" } +manufacturer { + manufacturer_id: 512 + manufacturer_name: "Lighting Infusion LLC" +} manufacturer { manufacturer_id: 25094 manufacturer_name: "Lighting Innovation Company, LLC" @@ -1638,6 +2462,10 @@ manufacturer { manufacturer_id: 11488 manufacturer_name: "Lighting Services Inc." } +manufacturer { + manufacturer_id: 473 + manufacturer_name: "Lightronics Inc." +} manufacturer { manufacturer_id: 9764 manufacturer_name: "Lisys Fenyrendszer Zrt." @@ -1646,10 +2474,22 @@ manufacturer { manufacturer_id: 5882 manufacturer_name: "Lite Puter Enterprise Co., Ltd." } +manufacturer { + manufacturer_id: 186 + manufacturer_name: "LiteGear Inc." +} manufacturer { manufacturer_id: 9781 manufacturer_name: "LjusDesign AB" } +manufacturer { + manufacturer_id: 2309 + manufacturer_name: "Locimation Pty Ltd" +} +manufacturer { + manufacturer_id: 475 + manufacturer_name: "Logen Ltd." +} manufacturer { manufacturer_id: 9783 manufacturer_name: "Loxone Electronics GmbH" @@ -1678,6 +2518,14 @@ manufacturer { manufacturer_id: 28650 manufacturer_name: "Lumina Visual Productions" } +manufacturer { + manufacturer_id: 147 + manufacturer_name: "Luminous Show Technology Ltd." +} +manufacturer { + manufacturer_id: 1028 + manufacturer_name: "Luminxa" +} manufacturer { manufacturer_id: 13853 manufacturer_name: "Lumishore Ltd. UK" @@ -1694,6 +2542,10 @@ manufacturer { manufacturer_id: 269 manufacturer_name: "Lumos / DMLite" } +manufacturer { + manufacturer_id: 180 + manufacturer_name: "Lumos Design" +} manufacturer { manufacturer_id: 748 manufacturer_name: "Lutron Electronics" @@ -1702,6 +2554,10 @@ manufacturer { manufacturer_id: 826 manufacturer_name: "Lux Lumen" } +manufacturer { + manufacturer_id: 156 + manufacturer_name: "LuxBalance Lighting" +} manufacturer { manufacturer_id: 2433 manufacturer_name: "Luxam, Ltd." @@ -1714,6 +2570,10 @@ manufacturer { manufacturer_id: 19777 manufacturer_name: "MA Lighting Technology GmbH" } +manufacturer { + manufacturer_id: 26221 + manufacturer_name: "MAD-Effects" +} manufacturer { manufacturer_id: 18008 manufacturer_name: "MAGIC FX B.V." @@ -1726,6 +2586,10 @@ manufacturer { manufacturer_id: 19809 manufacturer_name: "MARTINI S.p.A." } +manufacturer { + manufacturer_id: 1605 + manufacturer_name: "MATSUMURA ELECTRIC MFG. CO. , LTD." +} manufacturer { manufacturer_id: 28002 manufacturer_name: "MBN GmbH" @@ -1750,6 +2614,14 @@ manufacturer { manufacturer_id: 1999 manufacturer_name: "MH-Sound" } +manufacturer { + manufacturer_id: 421 + manufacturer_name: "MJ Lighting Co., Ltd." +} +manufacturer { + manufacturer_id: 2142 + manufacturer_name: "MMS Distribution Ltd" +} manufacturer { manufacturer_id: 10465 manufacturer_name: "MTC maintronic GmbH" @@ -1762,14 +2634,30 @@ manufacturer { manufacturer_id: 1938 manufacturer_name: "MY-Semi Inc." } +manufacturer { + manufacturer_id: 11049 + manufacturer_name: "MaNima Technologies BV" +} manufacturer { manufacturer_id: 13192 manufacturer_name: "Macostar International Ltd." } +manufacturer { + manufacturer_id: 2001 + manufacturer_name: "Made By Mouse LTD" +} +manufacturer { + manufacturer_id: 27497 + manufacturer_name: "Magical Fountain SA de CV (Magic Fountain)" +} manufacturer { manufacturer_id: 1205 manufacturer_name: "Major" } +manufacturer { + manufacturer_id: 1365 + manufacturer_name: "Maresch Electronics" +} manufacturer { manufacturer_id: 19792 manufacturer_name: "Martin Professional A/S" @@ -1782,22 +2670,58 @@ manufacturer { manufacturer_id: 2420 manufacturer_name: "Marumo Electric Co., Ltd." } +manufacturer { + manufacturer_id: 2284 + manufacturer_name: "Marvin Nadrowski" +} manufacturer { manufacturer_id: 7887 manufacturer_name: "Masiero s.r.l." } +manufacturer { + manufacturer_id: 286 + manufacturer_name: "Master LED" +} manufacturer { manufacturer_id: 2269 manufacturer_name: "Matthew Tong" } +manufacturer { + manufacturer_id: 2526 + manufacturer_name: "Matthias Bauch Software" +} manufacturer { manufacturer_id: 676 manufacturer_name: "McNicoll Entertainment Systems" } +manufacturer { + manufacturer_id: 2143 + manufacturer_name: "Media Visions, Inc." +} manufacturer { manufacturer_id: 23980 manufacturer_name: "Mediatec Group" } +manufacturer { + manufacturer_id: 25410 + manufacturer_name: "Mega Systems Inc." +} +manufacturer { + manufacturer_id: 22098 + manufacturer_name: "Megapixel Visual Reality" +} +manufacturer { + manufacturer_id: 115 + manufacturer_name: "Meijay Technologies Co., Ltd." +} +manufacturer { + manufacturer_id: 2234 + manufacturer_name: "Meteor Lighting" +} +manufacturer { + manufacturer_id: 2236 + manufacturer_name: "Michael Parkin" +} manufacturer { manufacturer_id: 9908 manufacturer_name: "Milford Instruments Ltd." @@ -1830,14 +2754,30 @@ manufacturer { manufacturer_id: 2508 manufacturer_name: "Motomuto Aps" } +manufacturer { + manufacturer_id: 4611 + manufacturer_name: "Movecat GmbH" +} manufacturer { manufacturer_id: 19831 - manufacturer_name: "Muller Elektronik" + manufacturer_name: "Mueller Elektronik" } manufacturer { manufacturer_id: 5584 manufacturer_name: "Music & Lights S.r.l." } +manufacturer { + manufacturer_id: 1715 + manufacturer_name: "NANOLUMENS, INC." +} +manufacturer { + manufacturer_id: 2132 + manufacturer_name: "NEC Display Solutions, Ltd." +} +manufacturer { + manufacturer_id: 1835 + manufacturer_name: "NEWSUBSTANCE Ltd." +} manufacturer { manufacturer_id: 20042 manufacturer_name: "NJD Electronics" @@ -1856,7 +2796,7 @@ manufacturer { } manufacturer { manufacturer_id: 2063 - manufacturer_name: "Navo Corp." + manufacturer_name: "NavoLabs" } manufacturer { manufacturer_id: 2123 @@ -1870,6 +2810,10 @@ manufacturer { manufacturer_id: 4826 manufacturer_name: "Newlab S.r.l." } +manufacturer { + manufacturer_id: 20560 + manufacturer_name: "Newton Engineering and Design Group LLC" +} manufacturer { manufacturer_id: 13107 manufacturer_name: "NightStarry Electronics Co., LTD." @@ -1882,6 +2826,10 @@ manufacturer { manufacturer_id: 10020 manufacturer_name: "Nila Inc." } +manufacturer { + manufacturer_id: 149 + manufacturer_name: "Ningbo Jeg Lighting Tech Co., Ltd." +} manufacturer { manufacturer_id: 10036 manufacturer_name: "Nixer Ltd." @@ -1890,17 +2838,25 @@ manufacturer { manufacturer_id: 5966 manufacturer_name: "Nordgas SNe-lightingsystem" } +manufacturer { + manufacturer_id: 13623 + manufacturer_name: "Novacorp Inc." +} manufacturer { manufacturer_id: 25089 manufacturer_name: "NuDelta Digital, LLC" } +manufacturer { + manufacturer_id: 117 + manufacturer_name: "ODELI" +} manufacturer { manufacturer_id: 1630 manufacturer_name: "OFilms" } manufacturer { manufacturer_id: 674 - manufacturer_name: "OJSC Kadoshkinsky electrotechnical " + manufacturer_name: "OJSC Kadoshkinsky electrotechnical" } manufacturer { manufacturer_id: 17969 @@ -1927,13 +2883,17 @@ manufacturer { manufacturer_name: "Oase GmbH" } manufacturer { - manufacturer_id: 20291 - manufacturer_name: "Obsidian Controls Ltd." + manufacturer_id: 409 + manufacturer_name: "Ocean LED Marine Ltd." } manufacturer { manufacturer_id: 21315 manufacturer_name: "Ocean Thin Films Inc." } +manufacturer { + manufacturer_id: 20291 + manufacturer_name: "Offstage Controls (formerly Obsidian Control)" +} manufacturer { manufacturer_id: 31344 manufacturer_name: "Open Lighting" @@ -1942,14 +2902,42 @@ manufacturer { manufacturer_id: 749 manufacturer_name: "OpenLX SP Ltd." } +manufacturer { + manufacturer_id: 2083 + manufacturer_name: "Opito Labs GmbH" +} +manufacturer { + manufacturer_id: 2221 + manufacturer_name: "Optical Productions LLC" +} +manufacturer { + manufacturer_id: 139 + manufacturer_name: "Opto Tech Corporation" +} +manufacturer { + manufacturer_id: 2291 + manufacturer_name: "Outdoor Lasers Ltd." +} manufacturer { manufacturer_id: 20341 manufacturer_name: "Outsight Pty Ltd." } +manufacturer { + manufacturer_id: 20561 + manufacturer_name: "PDQ Manufacturing, Inc" +} manufacturer { manufacturer_id: 7089 manufacturer_name: "PH Lightning AB" } +manufacturer { + manufacturer_id: 1828 + manufacturer_name: "PHC Lighting & BMS Sp. z o.o." +} +manufacturer { + manufacturer_id: 2005 + manufacturer_name: "PHIDA Stage Equipment Co., Ltd" +} manufacturer { manufacturer_id: 2266 manufacturer_name: "PLC Intelligent Technology (Shanghai) Co., Ltd." @@ -1962,13 +2950,17 @@ manufacturer { manufacturer_id: 10281 manufacturer_name: "PR-Electronic" } +manufacturer { + manufacturer_id: 4609 + manufacturer_name: "PRICOM Design" +} manufacturer { manufacturer_id: 1375 manufacturer_name: "PRO-SOLUTIONS" } manufacturer { manufacturer_id: 684 - manufacturer_name: "PSL Electronik Sanayi ve Ticaret A.S. " + manufacturer_name: "PSL Electronik Sanayi ve Ticaret A.S." } manufacturer { manufacturer_id: 20568 @@ -1978,13 +2970,17 @@ manufacturer { manufacturer_id: 8319 manufacturer_name: "Padura Elektronik GmbH" } +manufacturer { + manufacturer_id: 6587 + manufacturer_name: "Panalux Ltd." +} manufacturer { manufacturer_id: 1871 manufacturer_name: "Panasonic Corporation" } manufacturer { manufacturer_id: 28912 - manufacturer_name: "Pangolin Laser Systems, Inc. " + manufacturer_name: "Pangolin Laser Systems, Inc." } manufacturer { manufacturer_id: 20547 @@ -2020,7 +3016,7 @@ manufacturer { } manufacturer { manufacturer_id: 10279 - manufacturer_name: "Peternet Electronics BVBA " + manufacturer_name: "Peternet Electronics BVBA" } manufacturer { manufacturer_id: 20582 @@ -2046,10 +3042,18 @@ manufacturer { manufacturer_id: 20563 manufacturer_name: "Philips Selecon" } +manufacturer { + manufacturer_id: 477 + manufacturer_name: "Photonia srl" +} manufacturer { manufacturer_id: 2218 manufacturer_name: "PiXL Factory" } +manufacturer { + manufacturer_id: 129 + manufacturer_name: "Pino Solutions" +} manufacturer { manufacturer_id: 10273 manufacturer_name: "Pioneer Corporation" @@ -2058,6 +3062,10 @@ manufacturer { manufacturer_id: 28792 manufacturer_name: "PixelRange Inc." } +manufacturer { + manufacturer_id: 1804 + manufacturer_name: "Pixout SIA" +} manufacturer { manufacturer_id: 10294 manufacturer_name: "Planungsbuero" @@ -2070,6 +3078,10 @@ manufacturer { manufacturer_id: 460 manufacturer_name: "Portman Custom Lights" } +manufacturer { + manufacturer_id: 2166 + manufacturer_name: "Power Gems LTD" +} manufacturer { manufacturer_id: 28786 manufacturer_name: "Pr-Lighting Ltd." @@ -2106,6 +3118,14 @@ manufacturer { manufacturer_id: 20813 manufacturer_name: "QMAXZ lighting" } +manufacturer { + manufacturer_id: 2219 + manufacturer_name: "Qdot Lighting Limited" +} +manufacturer { + manufacturer_id: 16397 + manufacturer_name: "Quasar Science LLC" +} manufacturer { manufacturer_id: 20819 manufacturer_name: "QuickSilver Controls, Inc." @@ -2114,6 +3134,14 @@ manufacturer { manufacturer_id: 20844 manufacturer_name: "Quicklights" } +manufacturer { + manufacturer_id: 118 + manufacturer_name: "R. S. Schwarze Elektrotechnik Moderne Industrieelektronik GmbH" +} +manufacturer { + manufacturer_id: 1366 + manufacturer_name: "RAYSYS" +} manufacturer { manufacturer_id: 1616 manufacturer_name: "RDC, Inc. d.b.a. LynTec" @@ -2123,67 +3151,67 @@ manufacturer { manufacturer_name: "RE-Engineering" } manufacturer { - manufacturer_id: 32759 + manufacturer_id: 32752 manufacturer_name: "RESERVED FOR PROTOTYPING/EXPERIMENTAL USE ONLY" } manufacturer { - manufacturer_id: 32767 + manufacturer_id: 32760 manufacturer_name: "RESERVED FOR PROTOTYPING/EXPERIMENTAL USE ONLY" } manufacturer { - manufacturer_id: 32763 + manufacturer_id: 32756 manufacturer_name: "RESERVED FOR PROTOTYPING/EXPERIMENTAL USE ONLY" } manufacturer { - manufacturer_id: 32755 + manufacturer_id: 32764 manufacturer_name: "RESERVED FOR PROTOTYPING/EXPERIMENTAL USE ONLY" } manufacturer { - manufacturer_id: 32761 + manufacturer_id: 32754 manufacturer_name: "RESERVED FOR PROTOTYPING/EXPERIMENTAL USE ONLY" } manufacturer { - manufacturer_id: 32753 + manufacturer_id: 32762 manufacturer_name: "RESERVED FOR PROTOTYPING/EXPERIMENTAL USE ONLY" } manufacturer { - manufacturer_id: 32765 + manufacturer_id: 32758 manufacturer_name: "RESERVED FOR PROTOTYPING/EXPERIMENTAL USE ONLY" } manufacturer { - manufacturer_id: 32757 + manufacturer_id: 32766 manufacturer_name: "RESERVED FOR PROTOTYPING/EXPERIMENTAL USE ONLY" } manufacturer { - manufacturer_id: 32760 + manufacturer_id: 32753 manufacturer_name: "RESERVED FOR PROTOTYPING/EXPERIMENTAL USE ONLY" } manufacturer { - manufacturer_id: 32752 + manufacturer_id: 32761 manufacturer_name: "RESERVED FOR PROTOTYPING/EXPERIMENTAL USE ONLY" } manufacturer { - manufacturer_id: 32764 + manufacturer_id: 32757 manufacturer_name: "RESERVED FOR PROTOTYPING/EXPERIMENTAL USE ONLY" } manufacturer { - manufacturer_id: 32756 + manufacturer_id: 32765 manufacturer_name: "RESERVED FOR PROTOTYPING/EXPERIMENTAL USE ONLY" } manufacturer { - manufacturer_id: 32762 + manufacturer_id: 32755 manufacturer_name: "RESERVED FOR PROTOTYPING/EXPERIMENTAL USE ONLY" } manufacturer { - manufacturer_id: 32754 + manufacturer_id: 32763 manufacturer_name: "RESERVED FOR PROTOTYPING/EXPERIMENTAL USE ONLY" } manufacturer { - manufacturer_id: 32766 + manufacturer_id: 32759 manufacturer_name: "RESERVED FOR PROTOTYPING/EXPERIMENTAL USE ONLY" } manufacturer { - manufacturer_id: 32758 + manufacturer_id: 32767 manufacturer_name: "RESERVED FOR PROTOTYPING/EXPERIMENTAL USE ONLY" } manufacturer { @@ -2202,6 +3230,14 @@ manufacturer { manufacturer_id: 10535 manufacturer_name: "ROAL Electronics SpA" } +manufacturer { + manufacturer_id: 2024 + manufacturer_name: "ROCKETSIGN Technology HK Ltd" +} +manufacturer { + manufacturer_id: 1699 + manufacturer_name: "RODLIGHT ALBRECHT SILBERBERGER" +} manufacturer { manufacturer_id: 2438 manufacturer_name: "ROE Visual Co. Ltd." @@ -2226,6 +3262,10 @@ manufacturer { manufacturer_id: 462 manufacturer_name: "Railiks Enterprises" } +manufacturer { + manufacturer_id: 20593 + manufacturer_name: "Raindrop-Media" +} manufacturer { manufacturer_id: 2431 manufacturer_name: "RaumZeitLabor e.V." @@ -2254,9 +3294,13 @@ manufacturer { manufacturer_id: 21060 manufacturer_name: "Revolution Display" } +manufacturer { + manufacturer_id: 435 + manufacturer_name: "Ricardo Dias" +} manufacturer { manufacturer_id: 169 - manufacturer_name: "Richter Lighting Technologies GmbH " + manufacturer_name: "Richter Lighting Technologies GmbH" } manufacturer { manufacturer_id: 683 @@ -2286,6 +3330,22 @@ manufacturer { manufacturer_id: 843 manufacturer_name: "Rosstech Signals Inc." } +manufacturer { + manufacturer_id: 6153 + manufacturer_name: "Rotolight" +} +manufacturer { + manufacturer_id: 4641 + manufacturer_name: "SAGITTER - Proel" +} +manufacturer { + manufacturer_id: 164 + manufacturer_name: "SAKMA Electronica Industrial S.A.U." +} +manufacturer { + manufacturer_id: 107 + manufacturer_name: "SALZBRENNER media GmbH" +} manufacturer { manufacturer_id: 16465 manufacturer_name: "SAN JACK ANALOG HOUSE CO., LTD." @@ -2294,9 +3354,13 @@ manufacturer { manufacturer_id: 21322 manufacturer_name: "SAS Productions" } +manufacturer { + manufacturer_id: 28784 + manufacturer_name: "SBT GmbH" +} manufacturer { manufacturer_id: 455 - manufacturer_name: "SCHIEDERWERK GmbH " + manufacturer_name: "SCHIEDERWERK GmbH" } manufacturer { manufacturer_id: 5216 @@ -2314,6 +3378,10 @@ manufacturer { manufacturer_id: 21319 manufacturer_name: "SGM Technology For Lighting SPA" } +manufacturer { + manufacturer_id: 1686 + manufacturer_name: "SHENZHEN HOION LIGHTING CO.,LTD" +} manufacturer { manufacturer_id: 5418 manufacturer_name: "SHOWTACLE Ltd." @@ -2334,10 +3402,18 @@ manufacturer { manufacturer_id: 21323 manufacturer_name: "SK-Software" } +manufacturer { + manufacturer_id: 4642 + manufacturer_name: "SM International" +} manufacturer { manufacturer_id: 21324 manufacturer_name: "SOUNDLIGHT" } +manufacturer { + manufacturer_id: 367 + manufacturer_name: "SQD Lighting Co. Ltd" +} manufacturer { manufacturer_id: 463 manufacturer_name: "SRM Technik GmbH" @@ -2360,7 +3436,7 @@ manufacturer { } manufacturer { manufacturer_id: 2259 - manufacturer_name: "SVI Public Company Limited " + manufacturer_name: "SVI Public Company Limited" } manufacturer { manufacturer_id: 21367 @@ -2394,6 +3470,14 @@ manufacturer { manufacturer_id: 21331 manufacturer_name: "Sean Sill" } +manufacturer { + manufacturer_id: 522 + manufacturer_name: "Seebacher GmbH" +} +manufacturer { + manufacturer_id: 4608 + manufacturer_name: "Seekway Technology Limited" +} manufacturer { manufacturer_id: 28003 manufacturer_name: "Sein & Schein GmbH" @@ -2410,10 +3494,18 @@ manufacturer { manufacturer_id: 2260 manufacturer_name: "Sensa-Lite Ltd." } +manufacturer { + manufacturer_id: 166 + manufacturer_name: "Sensation Lighting Technology Co., Ltd." +} manufacturer { manufacturer_id: 5902 manufacturer_name: "Serva Transport Systems GmbH" } +manufacturer { + manufacturer_id: 427 + manufacturer_name: "Shanghai Euchips Industrial Co., Ltd." +} manufacturer { manufacturer_id: 771 manufacturer_name: "Shanghai Moons' Automation Control Co., Ltd" @@ -2422,14 +3514,46 @@ manufacturer { manufacturer_id: 464 manufacturer_name: "Shanghai Semping Electronics Co., Ltd." } +manufacturer { + manufacturer_id: 20482 + manufacturer_name: "Shanghai Shylon Optoelectronic Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 2369 + manufacturer_name: "Shenzen Zhuoyang Intelligent Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 128 + manufacturer_name: "Shenzhen AOTO Electronics Co., Ltd." +} manufacturer { manufacturer_id: 25092 manufacturer_name: "Shenzhen Absen Optoelectronic Co., Ltd" } +manufacturer { + manufacturer_id: 22101 + manufacturer_name: "Shenzhen CAS VU Technologies Co., Ltd." +} +manufacturer { + manufacturer_id: 2273 + manufacturer_name: "Shenzhen CLT Electronics Co.,LTD" +} +manufacturer { + manufacturer_id: 778 + manufacturer_name: "Shenzhen Colordreamer Technology Co., Ltd." +} manufacturer { manufacturer_id: 2368 manufacturer_name: "Shenzhen CreateLED Electronics Co., Ltd" } +manufacturer { + manufacturer_id: 160 + manufacturer_name: "Shenzhen Dicolor Optoelectronics Co., Ltd." +} +manufacturer { + manufacturer_id: 2187 + manufacturer_name: "Shenzhen Doit Vision Co., Ltd" +} manufacturer { manufacturer_id: 15240 manufacturer_name: "Shenzhen Eastar Electronic Co., Ltd." @@ -2438,26 +3562,66 @@ manufacturer { manufacturer_id: 2058 manufacturer_name: "Shenzhen FantaLED Electronics Co., Ltd" } +manufacturer { + manufacturer_id: 2209 + manufacturer_name: "Shenzhen Gloshine Technology Co., Ltd" +} manufacturer { manufacturer_id: 2307 manufacturer_name: "Shenzhen INFiLED Electronics, Ltd." } +manufacturer { + manufacturer_id: 27631 + manufacturer_name: "Shenzhen Ifountain Technology Ltd." +} manufacturer { manufacturer_id: 32232 manufacturer_name: "Shenzhen LAMP Technology Co., Ltd." } +manufacturer { + manufacturer_id: 2111 + manufacturer_name: "Shenzhen LeiFei Lighting Technologies Co.,Ltd." +} manufacturer { manufacturer_id: 1451 - manufacturer_name: "Shenzhen Lesan Lighting Co., Ltd. " + manufacturer_name: "Shenzhen Lesan Lighting Co., Ltd." +} +manufacturer { + manufacturer_id: 469 + manufacturer_name: "Shenzhen Liantronics Co., Ltd" +} +manufacturer { + manufacturer_id: 2467 + manufacturer_name: "Shenzhen Lightlink Display Technology Co., Ltd" } manufacturer { manufacturer_id: 2444 - manufacturer_name: "Shenzhen Longrich Energy Sources Technology Co., Ltd. " + manufacturer_name: "Shenzhen Longrich Energy Sources Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 184 + manufacturer_name: "Shenzhen Singba Light Technology Co., Ltd." } manufacturer { manufacturer_id: 20840 manufacturer_name: "Shenzhen Sunricher Technology Co.,Ltd." } +manufacturer { + manufacturer_id: 2320 + manufacturer_name: "Shenzhen Tecnon EXCO-Vision Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 425 + manufacturer_name: "Shenzhen Uniview LED Ltd. Co." +} +manufacturer { + manufacturer_id: 520 + manufacturer_name: "Shenzhen Yuming Vision Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 20592 + manufacturer_name: "Show Light Oy" +} manufacturer { manufacturer_id: 21352 manufacturer_name: "ShowCAD Control Systems Ltd." @@ -2470,6 +3634,18 @@ manufacturer { manufacturer_id: 10676 manufacturer_name: "Showtec (Highlite International B.V.)" } +manufacturer { + manufacturer_id: 2365 + manufacturer_name: "Sichuan Hushan Electric Co. Ltd" +} +manufacturer { + manufacturer_id: 2318 + manufacturer_name: "Sichuan esRadio Technology Co., Ltd" +} +manufacturer { + manufacturer_id: 4371 + manufacturer_name: "SiliconCore Technology, Inc." +} manufacturer { manufacturer_id: 21416 manufacturer_name: "Simon Tech" @@ -2502,6 +3678,10 @@ manufacturer { manufacturer_id: 21347 manufacturer_name: "SpaceCannon vH" } +manufacturer { + manufacturer_id: 2286 + manufacturer_name: "Spacelights" +} manufacturer { manufacturer_id: 10680 manufacturer_name: "Spotlight s.r.l." @@ -2510,6 +3690,10 @@ manufacturer { manufacturer_id: 257 manufacturer_name: "St. Anne Engineering GmbH" } +manufacturer { + manufacturer_id: 2190 + manufacturer_name: "Stage One International Co., Ltd." +} manufacturer { manufacturer_id: 4852 manufacturer_name: "Stage Services Ltd." @@ -2530,6 +3714,14 @@ manufacturer { manufacturer_id: 21332 manufacturer_name: "Stagetronics Ltda" } +manufacturer { + manufacturer_id: 2561 + manufacturer_name: "Star-Reach Corporation" +} +manufacturer { + manufacturer_id: 2315 + manufacturer_name: "StarLighting" +} manufacturer { manufacturer_id: 21316 manufacturer_name: "Stardraw.com Ltd." @@ -2562,6 +3754,10 @@ manufacturer { manufacturer_id: 29548 manufacturer_name: "Strand Lighting Ltd." } +manufacturer { + manufacturer_id: 25957 + manufacturer_name: "Stratus Systems LLC" +} manufacturer { manufacturer_id: 911 manufacturer_name: "Strich Labs" @@ -2582,6 +3778,10 @@ manufacturer { manufacturer_id: 10657 manufacturer_name: "Sturdy Corporation" } +manufacturer { + manufacturer_id: 181 + manufacturer_name: "Suga koubou Co., Ltd." +} manufacturer { manufacturer_id: 10679 manufacturer_name: "Sundrax, LLC" @@ -2590,10 +3790,26 @@ manufacturer { manufacturer_id: 26180 manufacturer_name: "Sunlab Technologies S.L." } +manufacturer { + manufacturer_id: 2542 + manufacturer_name: "Suzhou Pinzong Electronic Technology, CO.,Ltd" +} +manufacturer { + manufacturer_id: 770 + manufacturer_name: "Swefog Technology Group AB" +} +manufacturer { + manufacturer_id: 401 + manufacturer_name: "Sycra Technologies" +} manufacturer { manufacturer_id: 1276 manufacturer_name: "Syncrolite LLC" } +manufacturer { + manufacturer_id: 167 + manufacturer_name: "Syncronorm GmbH" +} manufacturer { manufacturer_id: 21318 manufacturer_name: "Synthe FX, LLC" @@ -2604,7 +3820,7 @@ manufacturer { } manufacturer { manufacturer_id: 1969 - manufacturer_name: "TBF-PyroTec GmbH " + manufacturer_name: "TBF-PyroTec GmbH" } manufacturer { manufacturer_id: 1335 @@ -2618,10 +3834,18 @@ manufacturer { manufacturer_id: 2045 manufacturer_name: "THELIGHT Luminary for Cine and TV S.L." } +manufacturer { + manufacturer_id: 199 + manufacturer_name: "THOR" +} manufacturer { manufacturer_id: 6906 manufacturer_name: "TMB" } +manufacturer { + manufacturer_id: 90 + manufacturer_name: "TPD Lighting" +} manufacturer { manufacturer_id: 737 manufacturer_name: "Tait Towers Manufacturing Inc." @@ -2638,18 +3862,30 @@ manufacturer { manufacturer_id: 1239 manufacturer_name: "Targetti Sankey Spa" } +manufacturer { + manufacturer_id: 2192 + manufacturer_name: "Taurus Light Co.,Limited" +} manufacturer { manufacturer_id: 2426 manufacturer_name: "Teamboyce Limited" } manufacturer { manufacturer_id: 21569 - manufacturer_name: "TecArt Lighting " + manufacturer_name: "TecArt Lighting" +} +manufacturer { + manufacturer_id: 2222 + manufacturer_name: "Technical Audio Group Pty Ltd" } manufacturer { manufacturer_id: 21572 manufacturer_name: "Technographic Displays Ltd." } +manufacturer { + manufacturer_id: 32489 + manufacturer_name: "Technology Kitchen" +} manufacturer { manufacturer_id: 13106 manufacturer_name: "Teclumen s.r.l." @@ -2658,6 +3894,10 @@ manufacturer { manufacturer_id: 21580 manufacturer_name: "Tempest Lighting Inc." } +manufacturer { + manufacturer_id: 190 + manufacturer_name: "The Light Luminary for Cine and TV S.L. (VELVET LIGHT)" +} manufacturer { manufacturer_id: 29009 manufacturer_name: "The Light Source, Inc." @@ -2678,6 +3918,10 @@ manufacturer { manufacturer_id: 713 manufacturer_name: "Theatrixx Technologies" } +manufacturer { + manufacturer_id: 116 + manufacturer_name: "Thomann GmbH" +} manufacturer { manufacturer_id: 10789 manufacturer_name: "Thorn Lighting Limited" @@ -2698,18 +3942,38 @@ manufacturer { manufacturer_id: 26608 manufacturer_name: "Toshiba Lighting & Technology Corporation" } +manufacturer { + manufacturer_id: 2333 + manufacturer_name: "TouchPlate Technologies Inc." +} manufacturer { manufacturer_id: 5852 - manufacturer_name: "Traxon Technologies Ltd. " + manufacturer_name: "Traxon Technologies Ltd." } manufacturer { manufacturer_id: 1461 - manufacturer_name: "Turkowski GmbH " + manufacturer_name: "Turkowski GmbH" +} +manufacturer { + manufacturer_id: 410 + manufacturer_name: "TwoGain Electronics" } manufacturer { manufacturer_id: 21840 manufacturer_name: "UP-LUX Eletronica Ltda." } +manufacturer { + manufacturer_id: 2345 + manufacturer_name: "UPlight stage equipment(GZ) CO., Ltd." +} +manufacturer { + manufacturer_id: 1619 + manufacturer_name: "USAI, LLC" +} +manufacturer { + manufacturer_id: 2552 + manufacturer_name: "UberDisplays" +} manufacturer { manufacturer_id: 19533 manufacturer_name: "Ultratec Special Effects" @@ -2726,14 +3990,30 @@ manufacturer { manufacturer_id: 2393 manufacturer_name: "Urbs Lighting, LLC" } +manufacturer { + manufacturer_id: 2152 + manufacturer_name: "Ushio America, Inc." +} +manufacturer { + manufacturer_id: 4610 + manufacturer_name: "Ushio Lighting, Inc." +} manufacturer { manufacturer_id: 265 manufacturer_name: "V-Productions" } +manufacturer { + manufacturer_id: 18432 + manufacturer_name: "VOD VISUAL.CO. (UK) Ltd." +} manufacturer { manufacturer_id: 4941 manufacturer_name: "VT-Control" } +manufacturer { + manufacturer_id: 6682 + manufacturer_name: "ValDim Waterfountains Ltd." +} manufacturer { manufacturer_id: 22092 manufacturer_name: "Vari-Lite, Inc." @@ -2750,6 +4030,10 @@ manufacturer { manufacturer_id: 280 manufacturer_name: "Vello Light Co., Ltd." } +manufacturer { + manufacturer_id: 2336 + manufacturer_name: "Vexica Technology Limited" +} manufacturer { manufacturer_id: 22097 manufacturer_name: "Vision Quest Lighting Inc." @@ -2770,6 +4054,10 @@ manufacturer { manufacturer_id: 174 manufacturer_name: "Vitrulux Ltd" } +manufacturer { + manufacturer_id: 137 + manufacturer_name: "Vulcan Lighting" +} manufacturer { manufacturer_id: 22340 manufacturer_name: "W-DEV" @@ -2790,10 +4078,18 @@ manufacturer { manufacturer_id: 30564 manufacturer_name: "WET" } +manufacturer { + manufacturer_id: 110 + manufacturer_name: "WHITEvoid GmbH" +} manufacturer { manufacturer_id: 2515 manufacturer_name: "WLPS Wodielite Production Services" } +manufacturer { + manufacturer_id: 22343 + manufacturer_name: "Wenger / JR Clancy" +} manufacturer { manufacturer_id: 22342 manufacturer_name: "Wildfire, Inc." @@ -2810,6 +4106,10 @@ manufacturer { manufacturer_id: 22355 manufacturer_name: "Wireless Solution Sweden AB" } +manufacturer { + manufacturer_id: 400 + manufacturer_name: "Wizlogics Co., Ltd." +} manufacturer { manufacturer_id: 22361 manufacturer_name: "Wybron, Inc." @@ -2830,14 +4130,34 @@ manufacturer { manufacturer_id: 11306 manufacturer_name: "XTBA" } +manufacturer { + manufacturer_id: 2147 + manufacturer_name: "XTEC Industries Pte Ltd" +} manufacturer { manufacturer_id: 2324 manufacturer_name: "Xenio" } +manufacturer { + manufacturer_id: 195 + manufacturer_name: "Xicato" +} manufacturer { manufacturer_id: 22605 manufacturer_name: "Xtraordinary Musical Accolade Systems" } +manufacturer { + manufacturer_id: 285 + manufacturer_name: "Yangzhou Zhituo Lighting Vision Technology Co., Ltd." +} +manufacturer { + manufacturer_id: 465 + manufacturer_name: "Yarilo Pro" +} +manufacturer { + manufacturer_id: 2441 + manufacturer_name: "YeGrin Liteworks" +} manufacturer { manufacturer_id: 14341 manufacturer_name: "Yifeng Lighting Co., Ltd." @@ -2846,26 +4166,46 @@ manufacturer { manufacturer_id: 5968 manufacturer_name: "Yuesheng International Limited" } +manufacturer { + manufacturer_id: 417 + manufacturer_name: "Yuesheng Stage Light Limited" +} +manufacturer { + manufacturer_id: 1711 + manufacturer_name: "ZHEJIANG JINGRI TECHNOLOGY CO.,LTD" +} manufacturer { manufacturer_id: 5292 manufacturer_name: "Zaklad Elektroniczny AGAT s.c." } manufacturer { - manufacturer_id: 2056 - manufacturer_name: "Zero 88" + manufacturer_id: 8201 + manufacturer_name: "Zboxes Intelligent Technology (Shanghai) Co., Ltd." } manufacturer { manufacturer_id: 172 manufacturer_name: "ZhouChuang Industrial Co. Limited" } +manufacturer { + manufacturer_id: 4370 + manufacturer_name: "Zhuhai Bincolor Electronic Technology Co., Ltd." +} manufacturer { manufacturer_id: 25093 manufacturer_name: "Zhuhai Ltech Technology Co., Ltd." } +manufacturer { + manufacturer_id: 2302 + manufacturer_name: "Zhuhai Shengchang Electronics Co., Ltd." +} manufacturer { manufacturer_id: 23123 manufacturer_name: "Zingerli Show Engineering" } +manufacturer { + manufacturer_id: 424 + manufacturer_name: "ZongDa Photoelectricity Science and Technology Co., Ltd." +} manufacturer { manufacturer_id: 27757 manufacturer_name: "Zumtobel Lighting GmbH" @@ -2878,6 +4218,10 @@ manufacturer { manufacturer_id: 2322 manufacturer_name: "ags - Wissenschaftliche Arbeitsgemeinschaft fur Studio- und Senderfragen" } +manufacturer { + manufacturer_id: 123 + manufacturer_name: "alurays lighting technology GmbH" +} manufacturer { manufacturer_id: 5776 manufacturer_name: "awaptec GmbH" @@ -2894,6 +4238,10 @@ manufacturer { manufacturer_id: 2556 manufacturer_name: "deskontrol electronics" } +manufacturer { + manufacturer_id: 146 + manufacturer_name: "digiLED (UK) Ltd." +} manufacturer { manufacturer_id: 25708 manufacturer_name: "dilitronics GmbH" @@ -2926,6 +4274,10 @@ manufacturer { manufacturer_id: 2205 manufacturer_name: "gobo.ws" } +manufacturer { + manufacturer_id: 20480 + manufacturer_name: "http://www.orangepi-dmx.org" +} manufacturer { manufacturer_id: 982 manufacturer_name: "i-Lumen" @@ -2942,10 +4294,18 @@ manufacturer { manufacturer_id: 26956 manufacturer_name: "iLight Technologies Inc" } +manufacturer { + manufacturer_id: 2487 + manufacturer_name: "inCon-trol water systems" +} manufacturer { manufacturer_id: 18753 manufacturer_name: "inoage GmbH" } +manufacturer { + manufacturer_id: 2352 + manufacturer_name: "jiaozuo shengguang film &equipment Co. Ltd" +} manufacturer { manufacturer_id: 2394 manufacturer_name: "kLabs Research UK" @@ -2970,10 +4330,30 @@ manufacturer { manufacturer_id: 19796 manufacturer_name: "medien technik cords" } +manufacturer { + manufacturer_id: 2057 + manufacturer_name: "mumoco GmbH" +} +manufacturer { + manufacturer_id: 32491 + manufacturer_name: "mylaserpage" +} +manufacturer { + manufacturer_id: 2304 + manufacturer_name: "nox multimedia GmbH" +} +manufacturer { + manufacturer_id: 189 + manufacturer_name: "numeo GmbH" +} manufacturer { manufacturer_id: 5658 manufacturer_name: "techKnow Design Ltd." } +manufacturer { + manufacturer_id: 178 + manufacturer_name: "unonovesette srl" +} manufacturer { manufacturer_id: 5382 manufacturer_name: "v2 Lighting Group, Inc." @@ -2982,8 +4362,12 @@ manufacturer { manufacturer_id: 22637 manufacturer_name: "www.doityourselfchristmas.com hobbyists" } +manufacturer { + manufacturer_id: 468 + manufacturer_name: "x-labs" +} manufacturer { manufacturer_id: 15664 manufacturer_name: "zactrack Lighting Technologies Gmbh" } -version: 1505079062 +version: 1582652364 diff --git a/data/rdm/manufacturer_pids.proto b/data/rdm/manufacturer_pids.proto index f59398dba4..7d0343aa7b 100644 --- a/data/rdm/manufacturer_pids.proto +++ b/data/rdm/manufacturer_pids.proto @@ -2496,18 +2496,78 @@ manufacturer { manufacturer_id: 17742 manufacturer_name: "ENTTEC Pty Ltd" pid { - name: "AUTO_MODE" - value: 34559 + name: "PWM_OUTPUT_FREQUENCY" + value: 32770 + get_request { + } + get_response { + field { + type: UINT16 + name: "frequency" + } + } + get_sub_device_range: ROOT_OR_SUBDEVICE + set_request { + field { + type: UINT16 + name: "frequency" + range { + min: 500 + max: 2000 + } + } + } + set_response { + } + set_sub_device_range: ROOT_OR_ALL_SUBDEVICE + } + pid { + name: "FAN_ON_PERCENTAGE" + value: 32771 get_request { } get_response { field { type: UINT8 - name: "program" + name: "percentage" + label { + value: 0 + label: "Auto" + } + } + } + get_sub_device_range: ROOT_DEVICE + set_request { + field { + type: UINT8 + name: "percentage" + label { + value: 0 + label: "Auto" + } range { min: 0 - max: 9 + max: 0 + } + range { + min: 50 + max: 100 } + } + } + set_response { + } + set_sub_device_range: ROOT_DEVICE + } + pid { + name: "AUTO_MODE" + value: 34559 + get_request { + } + get_response { + field { + type: UINT8 + name: "program" label { value: 0 label: "Disabled" @@ -2524,14 +2584,14 @@ manufacturer { value: 8 label: "1 colour chase, 3 chans FW>=1.2" } - } - field { - type: UINT8 - name: "speed" range { min: 0 max: 9 } + } + field { + type: UINT8 + name: "speed" label { value: 0 label: "Fastest" @@ -2540,14 +2600,14 @@ manufacturer { value: 9 label: "Slowest" } - } - field { - type: UINT8 - name: "delay" range { min: 0 max: 9 } + } + field { + type: UINT8 + name: "delay" label { value: 0 label: "Shortest" @@ -2556,17 +2616,17 @@ manufacturer { value: 9 label: "Longest" } + range { + min: 0 + max: 9 + } } } - get_sub_device_range: ROOT_OR_SUBDEVICE + get_sub_device_range: ROOT_DEVICE set_request { field { type: UINT8 name: "program" - range { - min: 0 - max: 9 - } label { value: 0 label: "Disabled" @@ -2583,14 +2643,14 @@ manufacturer { value: 8 label: "1 colour chase, 3 chans FW>=1.2" } - } - field { - type: UINT8 - name: "speed" range { min: 0 max: 9 } + } + field { + type: UINT8 + name: "speed" label { value: 0 label: "Fastest" @@ -2599,85 +2659,25 @@ manufacturer { value: 9 label: "Slowest" } - } - field { - type: UINT8 - name: "delay" range { min: 0 max: 9 } - label { - value: 0 - label: "Shortest" - } - label { - value: 9 - label: "Longest" - } } - } - set_response { - } - set_sub_device_range: ROOT_OR_ALL_SUBDEVICE - } - pid { - name: "PWM_OUTPUT_FREQUENCY" - value: 32770 - get_request { - } - get_response { - field { - type: UINT16 - name: "frequency" - } - } - get_sub_device_range: ROOT_OR_SUBDEVICE - set_request { - field { - type: UINT16 - name: "frequency" - range { - min: 500 - max: 2000 - } - } - } - set_response { - } - set_sub_device_range: ROOT_OR_ALL_SUBDEVICE - } - pid { - name: "FAN_ON_PERCENTAGE" - value: 32771 - get_request { - } - get_response { field { type: UINT8 - name: "percentage" + name: "delay" label { value: 0 - label: "Auto" + label: "Shortest" } - } - } - get_sub_device_range: ROOT_DEVICE - set_request { - field { - type: UINT8 - name: "percentage" label { - value: 0 - label: "Auto" + value: 9 + label: "Longest" } range { min: 0 - max: 0 - } - range { - min: 50 - max: 100 + max: 9 } } } @@ -3339,14 +3339,14 @@ manufacturer { get_response { field { type: UINT16 - name: "enabled" + name: "fixture_id" } } get_sub_device_range: ROOT_DEVICE set_request { field { type: UINT16 - name: "enabled" + name: "fixture_id" } } set_response { @@ -6919,6 +6919,72 @@ manufacturer { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } + pid { + name: "PT_FEEDBACK" + value: 40960 + get_request { + } + get_response { + field { + type: BOOL + name: "Pan Tilt Feedback" + } + } + get_sub_device_range: ROOT_OR_SUBDEVICE + set_request { + field { + type: BOOL + name: "Pan Tilt Feedback" + } + } + set_response { + } + set_sub_device_range: ROOT_OR_ALL_SUBDEVICE + } + pid { + name: "OUTPUT_UNIFORMITY" + value: 40969 + get_request { + } + get_response { + field { + type: BOOL + name: "Output Uniformity" + } + } + get_sub_device_range: ROOT_OR_SUBDEVICE + set_request { + field { + type: BOOL + name: "Output Uniformity" + } + } + set_response { + } + set_sub_device_range: ROOT_OR_ALL_SUBDEVICE + } + pid { + name: "DL_COMPATIBLE_MODE" + value: 40973 + get_request { + } + get_response { + field { + type: BOOL + name: "DL Compatible Mode" + } + } + get_sub_device_range: ROOT_OR_SUBDEVICE + set_request { + field { + type: BOOL + name: "DL Compatible Mode" + } + } + set_response { + } + set_sub_device_range: ROOT_OR_ALL_SUBDEVICE + } pid { name: "TOUCHSCREEN_LOCK" value: 40975 @@ -9290,4 +9356,4 @@ manufacturer { set_sub_device_range: ROOT_DEVICE } } -version: 1528709287 +version: 1582652719 diff --git a/data/rdm/pids.proto b/data/rdm/pids.proto index 47b3c77dce..a74cf3df7b 100644 --- a/data/rdm/pids.proto +++ b/data/rdm/pids.proto @@ -4010,6 +4010,1267 @@ pid { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } +pid { + name: "COMPONENT_SCOPE" + value: 2048 + get_request { + field { + type: UINT16 + name: "scope_slot" + range { + min: 1 + max: 65535 + } + } + } + get_response { + field { + type: UINT16 + name: "scope_slot" + range { + min: 1 + max: 65535 + } + } + field { + type: STRING + name: "scope_string" + max_size: 63 + } + field { + type: UINT8 + name: "static_config_type" + label { + value: 0 + label: "No static config" + } + label { + value: 1 + label: "Static config IPv4" + } + label { + value: 1 + label: "Static config IPv6" + } + range { + min: 0 + max: 2 + } + } + field { + type: IPV4 + name: "static_broker_ipv4_address" + label { + value: 0 + label: "No static broker IPv4 address" + } + } + field { + type: IPV6 + name: "static_broker_ipv6_address" + label { + value: 0 + label: "No static broker IPv6 address" + } + } + field { + type: UINT16 + name: "static_broker_port" + label { + value: 0 + label: "No static broker port" + } + } + } + get_sub_device_range: ROOT_DEVICE + set_request { + field { + type: UINT16 + name: "scope_slot" + range { + min: 1 + max: 65535 + } + } + field { + type: STRING + name: "scope_string" + max_size: 63 + } + field { + type: UINT8 + name: "static_config_type" + label { + value: 0 + label: "No static config" + } + label { + value: 1 + label: "Static config IPv4" + } + label { + value: 1 + label: "Static config IPv6" + } + range { + min: 0 + max: 2 + } + } + field { + type: IPV4 + name: "static_broker_ipv4_address" + label { + value: 0 + label: "No static broker IPv4 address" + } + } + field { + type: IPV6 + name: "static_broker_ipv6_address" + label { + value: 0 + label: "No static broker IPv6 address" + } + } + field { + type: UINT16 + name: "static_broker_port" + label { + value: 0 + label: "No static broker port" + } + } + } + set_response { + } + set_sub_device_range: ROOT_DEVICE +} +pid { + name: "SEARCH_DOMAIN" + value: 2049 + get_request { + } + get_response { + field { + type: STRING + name: "search_domain" + min_size: 0 + max_size: 231 + } + } + get_sub_device_range: ROOT_DEVICE + set_request { + field { + type: STRING + name: "search_domain" + min_size: 0 + max_size: 231 + } + } + set_response { + } + set_sub_device_range: ROOT_DEVICE +} +pid { + name: "TCP_COMMS_STATUS" + value: 2050 + get_request { + } + get_response { + field { + type: GROUP + name: "comms_statuses" + field { + type: STRING + name: "scope_string" + max_size: 63 + } + field { + type: IPV4 + name: "broker_ipv4_address" + label { + value: 0 + label: "No IPv4 Connection" + } + } + field { + type: IPV6 + name: "broker_ipv6_address" + label { + value: 0 + label: "No IPv6 Connection" + } + } + field { + type: UINT16 + name: "broker_port" + } + field { + type: UINT16 + name: "unhealthy_tcp_events" + } + } + } + get_sub_device_range: ROOT_DEVICE + set_request { + field { + type: STRING + name: "scope_string" + max_size: 63 + } + } + set_response { + } + set_sub_device_range: ROOT_DEVICE +} +pid { + name: "BROKER_STATUS" + value: 2051 + get_request { + } + get_response { + field { + type: BOOL + name: "set_allowed" + } + field { + type: UINT8 + name: "broker_state" + label { + value: 0 + label: "Disabled" + } + label { + value: 1 + label: "Active" + } + label { + value: 2 + label: "Standby" + } + range { + min: 0 + max: 2 + } + } + } + get_sub_device_range: ROOT_DEVICE + set_request { + field { + type: UINT8 + name: "broker_state" + label { + value: 0 + label: "Disabled" + } + label { + value: 1 + label: "Active" + } + range { + min: 0 + max: 1 + } + } + } + set_response { + } + set_sub_device_range: ROOT_DEVICE +} +pid { + name: "ENDPOINT_LIST" + value: 2304 + get_request { + } + get_response { + field { + type: UINT32 + name: "list_change_number" + } + field { + type: GROUP + name: "endpoints" + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + field { + type: UINT8 + name: "endpoint_type" + label { + value: 0 + label: "Virtual Endpoint" + } + label { + value: 1 + label: "Physical Endpoint" + } + range { + min: 0 + max: 1 + } + } + } + } + get_sub_device_range: ROOT_DEVICE +} +pid { + name: "ENDPOINT_LIST_CHANGE" + value: 2305 + get_request { + } + get_response { + field { + type: UINT32 + name: "list_change_number" + } + } + get_sub_device_range: ROOT_DEVICE +} +pid { + name: "IDENTIFY_ENDPOINT" + value: 2306 + get_request { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + } + get_response { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + field { + type: BOOL + name: "identify_state" + } + } + get_sub_device_range: ROOT_DEVICE + set_request { + field { + type: UINT16 + name: "endpoint_id" + label { + value: 65535 + label: "All Endpoints" + } + range { + min: 1 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + field { + type: BOOL + name: "identify_state" + } + } + set_response { + field { + type: UINT16 + name: "endpoint_id" + label { + value: 65535 + label: "All Endpoints" + } + range { + min: 1 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + } + set_sub_device_range: ROOT_DEVICE +} +pid { + name: "ENDPOINT_TO_UNIVERSE" + value: 2307 + get_request { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + } + get_response { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + field { + type: UINT16 + name: "universe" + label { + value: 0 + label: "Unpatched" + } + label { + value: 65535 + label: "Composite" + } + range { + min: 0 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + } + get_sub_device_range: ROOT_DEVICE + set_request { + field { + type: UINT16 + name: "endpoint_id" + label { + value: 65535 + label: "All Endpoints" + } + range { + min: 1 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + field { + type: UINT16 + name: "universe" + label { + value: 0 + label: "Unpatch" + } + range { + min: 0 + max: 63999 + } + } + } + set_response { + field { + type: UINT16 + name: "endpoint_id" + label { + value: 65535 + label: "All Endpoints" + } + range { + min: 1 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + } + set_sub_device_range: ROOT_DEVICE +} +pid { + name: "ENDPOINT_MODE" + value: 2308 + get_request { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + } + get_response { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + field { + type: UINT8 + name: "endpoint_mode" + label { + value: 0 + label: "Disabled" + } + label { + value: 1 + label: "Input" + } + label { + value: 2 + label: "Output" + } + } + } + get_sub_device_range: ROOT_DEVICE + set_request { + field { + type: UINT16 + name: "endpoint_id" + label { + value: 65535 + label: "All Endpoints" + } + range { + min: 1 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + field { + type: UINT8 + name: "endpoint_mode" + label { + value: 0 + label: "Disable" + } + label { + value: 1 + label: "Input" + } + label { + value: 2 + label: "Output" + } + } + } + set_response { + field { + type: UINT16 + name: "endpoint_id" + label { + value: 65535 + label: "All Endpoints" + } + range { + min: 1 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + } + set_sub_device_range: ROOT_DEVICE +} +pid { + name: "ENDPOINT_LABEL" + value: 2309 + get_request { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + } + get_response { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + field { + type: STRING + name: "endpoint_label" + max_size: 32 + } + } + get_sub_device_range: ROOT_DEVICE + set_request { + field { + type: UINT16 + name: "endpoint_id" + label { + value: 65535 + label: "All Endpoints" + } + range { + min: 1 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + field { + type: STRING + name: "endpoint_label" + max_size: 32 + } + } + set_response { + field { + type: UINT16 + name: "endpoint_id" + label { + value: 65535 + label: "All Endpoints" + } + range { + min: 1 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + } + set_sub_device_range: ROOT_DEVICE +} +pid { + name: "RDM_TRAFFIC_ENABLE" + value: 2310 + get_request { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + } + get_response { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + field { + type: BOOL + name: "rdm_enabled" + } + } + get_sub_device_range: ROOT_DEVICE + set_request { + field { + type: UINT16 + name: "endpoint_id" + label { + value: 65535 + label: "All Endpoints" + } + range { + min: 1 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + field { + type: BOOL + name: "rdm_enabled" + } + } + set_response { + field { + type: UINT16 + name: "endpoint_id" + label { + value: 65535 + label: "All Endpoints" + } + range { + min: 1 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + } + set_sub_device_range: ROOT_DEVICE +} +pid { + name: "DISCOVERY_STATE" + value: 2311 + get_request { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + } + get_response { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + field { + type: UINT16 + name: "device_count" + label { + value: 0 + label: "Incomplete" + } + label { + value: 65535 + label: "Unknown" + } + range { + min: 0 + max: 65535 + } + } + field { + type: UINT8 + name: "discovery_state" + label { + value: 0 + label: "Incomplete" + } + label { + value: 1 + label: "Incremental" + } + label { + value: 2 + label: "Full" + } + label { + value: 4 + label: "Completed" + } + range { + min: 0 + max: 2 + } + range { + min: 4 + max: 4 + } + range { + min: 128 + max: 223 + } + } + } + get_sub_device_range: ROOT_DEVICE + set_request { + field { + type: UINT16 + name: "endpoint_id" + label { + value: 65535 + label: "All Endpoints" + } + range { + min: 1 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + field { + type: UINT8 + name: "discovery_state" + label { + value: 1 + label: "Incremental" + } + label { + value: 2 + label: "Full" + } + label { + value: 4 + label: "Stop" + } + range { + min: 1 + max: 2 + } + range { + min: 4 + max: 4 + } + range { + min: 128 + max: 223 + } + } + } + set_response { + field { + type: UINT16 + name: "endpoint_id" + label { + value: 65535 + label: "All Endpoints" + } + range { + min: 1 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + } + set_sub_device_range: ROOT_DEVICE +} +pid { + name: "BACKGROUND_DISCOVERY" + value: 2312 + get_request { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + } + get_response { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + field { + type: BOOL + name: "background_discovery" + } + } + get_sub_device_range: ROOT_DEVICE + set_request { + field { + type: UINT16 + name: "endpoint_id" + label { + value: 65535 + label: "All Endpoints" + } + range { + min: 1 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + field { + type: BOOL + name: "background_discovery" + } + } + set_response { + field { + type: UINT16 + name: "endpoint_id" + label { + value: 65535 + label: "All Endpoints" + } + range { + min: 1 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + } + set_sub_device_range: ROOT_DEVICE +} +pid { + name: "ENDPOINT_TIMING" + value: 2313 + get_request { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + } + get_response { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + field { + type: UINT8 + name: "current_setting" + range { + min: 1 + max: 255 + } + } + field { + type: UINT8 + name: "number_of_settings" + } + } + get_sub_device_range: ROOT_DEVICE + set_request { + field { + type: UINT16 + name: "endpoint_id" + label { + value: 65535 + label: "All Endpoints" + } + range { + min: 1 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + field { + type: UINT8 + name: "timing_setting" + range { + min: 1 + max: 255 + } + } + } + set_response { + field { + type: UINT16 + name: "endpoint_id" + label { + value: 65535 + label: "All Endpoints" + } + range { + min: 1 + max: 63999 + } + range { + min: 65535 + max: 65535 + } + } + } + set_sub_device_range: ROOT_DEVICE +} +pid { + name: "ENDPOINT_TIMING_DESCRIPTION" + value: 2314 + get_request { + field { + type: UINT8 + name: "timing_setting" + range { + min: 1 + max: 255 + } + } + } + get_response { + field { + type: UINT8 + name: "timing_setting" + range { + min: 1 + max: 255 + } + } + field { + type: STRING + name: "description" + max_size: 32 + } + } + get_sub_device_range: ROOT_DEVICE +} +pid { + name: "ENDPOINT_RESPONDERS" + value: 2315 + get_request { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + } + get_response { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + field { + type: UINT32 + name: "list_change_number" + } + field { + type: GROUP + name: "uids" + field { + type: UID + name: "uid" + } + } + } + get_sub_device_range: ROOT_DEVICE +} +pid { + name: "ENDPOINT_RESPONDER_LIST_CHANGE" + value: 2316 + get_request { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + } + get_response { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + field { + type: UINT32 + name: "list_change_number" + } + } + get_sub_device_range: ROOT_DEVICE +} +pid { + name: "BINDING_CONTROL_FIELDS" + value: 2317 + get_request { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + field { + type: UID + name: "uid" + } + } + get_response { + field { + type: UINT16 + name: "endpoint_id" + range { + min: 1 + max: 63999 + } + } + field { + type: UID + name: "uid" + } + field { + type: UINT16 + name: "control_bits" + } + field { + type: UID + name: "binding_uid" + label { + value: 0 + label: "No Information Present" + } + } + } + get_sub_device_range: ROOT_DEVICE +} +pid { + name: "BACKGROUND_QUEUED_STATUS_POLICY" + value: 2318 + get_request { + } + get_response { + field { + type: UINT8 + name: "current_policy_setting" + label { + value: 0 + label: "None" + } + label { + value: 1 + label: "Advisory" + } + label { + value: 2 + label: "Warning" + } + label { + value: 3 + label: "Error" + } + range { + min: 0 + max: 255 + } + } + field { + type: UINT8 + name: "num_policy_settings" + } + } + get_sub_device_range: ROOT_OR_SUBDEVICE + set_request { + field { + type: UINT8 + name: "policy" + label { + value: 0 + label: "None" + } + label { + value: 1 + label: "Advisory" + } + label { + value: 2 + label: "Warning" + } + label { + value: 3 + label: "Error" + } + range { + min: 0 + max: 255 + } + } + } + set_response { + } + set_sub_device_range: ROOT_OR_ALL_SUBDEVICE +} +pid { + name: "BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION" + value: 2319 + get_request { + field { + type: UINT8 + name: "policy_setting" + label { + value: 0 + label: "None" + } + label { + value: 1 + label: "Advisory" + } + label { + value: 2 + label: "Warning" + } + label { + value: 3 + label: "Error" + } + range { + min: 0 + max: 255 + } + } + } + get_response { + field { + type: UINT8 + name: "policy_setting" + } + field { + type: STRING + name: "description" + max_size: 32 + } + } + get_sub_device_range: ROOT_OR_SUBDEVICE +} pid { name: "IDENTIFY_DEVICE" value: 4096 @@ -4548,4 +5809,4 @@ pid { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } -version: 1521301591 +version: 1582652719 From 2aeaac8f33f3e75eb55e02a2aaa862c899474519 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Wed, 26 Feb 2020 08:43:43 +0000 Subject: [PATCH 042/138] Add initial negative E1.33/E1.37-7 tests. Need to add categories still --- tools/rdm/TestDefinitions.py | 770 +++++++++++++++++++++++++++++++++++ 1 file changed, 770 insertions(+) diff --git a/tools/rdm/TestDefinitions.py b/tools/rdm/TestDefinitions.py index 8071311099..149f75d0e9 100644 --- a/tools/rdm/TestDefinitions.py +++ b/tools/rdm/TestDefinitions.py @@ -7851,6 +7851,776 @@ class SetInterfaceHardwareAddressType1WithData( PID = 'INTERFACE_HARDWARE_ADDRESS_TYPE1' +# E1.33/E1.37-7 PIDS +# ============================================================================= + +class AllSubDevicesGetSearchDomain(TestMixins.AllSubDevicesGetMixin, + OptionalParameterTestFixture): + """Send a get SEARCH_DOMAIN to ALL_SUB_DEVICES.""" + PID = 'SEARCH_DOMAIN' + + +# class GetSearchDomain(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'SEARCH_DOMAIN' +# TODO(peter): Test get + + +class GetSearchDomainWithData(TestMixins.GetWithDataMixin, + OptionalParameterTestFixture): + """GET SEARCH_DOMAIN with data.""" + PID = 'SEARCH_DOMAIN' + + +# class SetSearchDomain(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'SEARCH_DOMAIN' +# TODO(peter): Test set + + +class SetSearchDomainWithNoData(TestMixins.SetWithNoDataMixin, + OptionalParameterTestFixture): + """Set SEARCH_DOMAIN command with no data.""" + PID = 'SEARCH_DOMAIN' + + +class SetSearchDomainWithExtraData(TestMixins.SetWithDataMixin, + OptionalParameterTestFixture): + """Send a SET SEARCH_DOMAIN command with extra data.""" + PID = 'SEARCH_DOMAIN' + + +class AllSubDevicesGetBrokerStatus(TestMixins.AllSubDevicesGetMixin, + OptionalParameterTestFixture): + """Send a get BROKER_STATUS to ALL_SUB_DEVICES.""" + PID = 'BROKER_STATUS' + + +# class GetBrokerStatus(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'BROKER_STATUS' +# TODO(peter): Test get + + +class GetBrokerStatusWithData(TestMixins.GetWithDataMixin, + OptionalParameterTestFixture): + """GET BROKER_STATUS with data.""" + PID = 'BROKER_STATUS' + + +# class SetBrokerStatus(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'BROKER_STATUS' +# TODO(peter): Test set + + +class SetBrokerStatusWithNoData(TestMixins.SetWithNoDataMixin, + OptionalParameterTestFixture): + """Set BROKER_STATUS command with no data.""" + PID = 'BROKER_STATUS' + + +class SetBrokerStatusWithExtraData(TestMixins.SetWithDataMixin, + OptionalParameterTestFixture): + """Send a SET BROKER_STATUS command with extra data.""" + PID = 'BROKER_STATUS' + + +class AllSubDevicesGetEndpointMode(TestMixins.AllSubDevicesGetMixin, + OptionalParameterTestFixture): + """Send a get ENDPOINT_MODE to ALL_SUB_DEVICES.""" + PID = 'ENDPOINT_MODE' + DATA = [0x0001] + + +# class GetEndpointMode(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'ENDPOINT_MODE' +# TODO(peter): Test get + + +class GetZeroEndpointMode(TestMixins.GetZeroUInt16Mixin, + OptionalParameterTestFixture): + """GET ENDPOINT_MODE for endpoint id 0.""" + PID = 'ENDPOINT_MODE' + + +class GetEndpointModeWithNoData(TestMixins.GetWithNoDataMixin, + OptionalParameterTestFixture): + """GET ENDPOINT_MODE with no argument given.""" + PID = 'ENDPOINT_MODE' + + +class GetEndpointModeWithExtraData(TestMixins.GetWithDataMixin, + OptionalParameterTestFixture): + """GET ENDPOINT_MODE with more than 2 bytes of data.""" + PID = 'ENDPOINT_MODE' + + +# class SetEndpointMode(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'ENDPOINT_MODE' +# TODO(peter): Test set + + +# class SetZeroEndpointMode(TestMixins.SetZero, +# OptionalParameterTestFixture): +# """SET ENDPOINT_MODE for endpoint id 0.""" +# PID = 'ENDPOINT_MODE' +# TODO(peter): Test set zero + + +class SetEndpointModeWithNoData(TestMixins.SetWithNoDataMixin, + OptionalParameterTestFixture): + """Set ENDPOINT_MODE command with no data.""" + PID = 'ENDPOINT_MODE' + + +class SetEndpointModeWithExtraData(TestMixins.SetWithDataMixin, + OptionalParameterTestFixture): + """Send a SET ENDPOINT_MODE command with extra data.""" + PID = 'ENDPOINT_MODE' + DATA = 'foobar' + + +class AllSubDevicesGetEndpointLabel(TestMixins.AllSubDevicesGetMixin, + OptionalParameterTestFixture): + """Send a get ENDPOINT_LABEL to ALL_SUB_DEVICES.""" + PID = 'ENDPOINT_LABEL' + DATA = [0x0001] + + +# class GetEndpointLabel(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'ENDPOINT_LABEL' +# TODO(peter): Test get + + +class GetZeroEndpointLabel(TestMixins.GetZeroUInt16Mixin, + OptionalParameterTestFixture): + """GET ENDPOINT_LABEL for endpoint id 0.""" + PID = 'ENDPOINT_LABEL' + + +class GetEndpointLabelWithNoData(TestMixins.GetWithNoDataMixin, + OptionalParameterTestFixture): + """GET ENDPOINT_LABEL with no argument given.""" + PID = 'ENDPOINT_LABEL' + + +class GetEndpointLabelWithExtraData(TestMixins.GetWithDataMixin, + OptionalParameterTestFixture): + """GET ENDPOINT_LABEL with more than 2 bytes of data.""" + PID = 'ENDPOINT_LABEL' + + +# class SetEndpointLabel(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'ENDPOINT_LABEL' +# TODO(peter): Test set + + +# class SetZeroEndpointLabel(TestMixins.SetZero, +# OptionalParameterTestFixture): +# """SET ENDPOINT_LABEL for endpoint id 0.""" +# PID = 'ENDPOINT_LABEL' +# TODO(peter): Test set zero + + +class SetEndpointLabelWithNoData(TestMixins.SetWithNoDataMixin, + OptionalParameterTestFixture): + """Set ENDPOINT_LABEL command with no data.""" + PID = 'ENDPOINT_LABEL' + + +class SetEndpointLabelWithExtraData(TestMixins.SetWithDataMixin, + OptionalParameterTestFixture): + """Send a SET ENDPOINT_LABEL command with extra data.""" + PID = 'ENDPOINT_LABEL' + + +class AllSubDevicesGetEndpointTiming(TestMixins.AllSubDevicesGetMixin, + OptionalParameterTestFixture): + """Send a get ENDPOINT_TIMING to ALL_SUB_DEVICES.""" + PID = 'ENDPOINT_TIMING' + DATA = [0x0001] + + +# class GetEndpointTiming(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'ENDPOINT_TIMING' +# TODO(peter): Test get + + +class GetZeroEndpointTiming(TestMixins.GetZeroUInt16Mixin, + OptionalParameterTestFixture): + """GET ENDPOINT_TIMING for endpoint id 0.""" + PID = 'ENDPOINT_TIMING' + + +class GetEndpointTimingWithNoData(TestMixins.GetWithNoDataMixin, + OptionalParameterTestFixture): + """GET ENDPOINT_TIMING with no argument given.""" + PID = 'ENDPOINT_TIMING' + + +class GetEndpointTimingWithExtraData(TestMixins.GetWithDataMixin, + OptionalParameterTestFixture): + """GET ENDPOINT_TIMING with more than 2 bytes of data.""" + PID = 'ENDPOINT_TIMING' + + +# class SetEndpointTiming(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'ENDPOINT_TIMING' +# TODO(peter): Test set + + +# class SetZeroEndpointTiming(TestMixins.SetZero, +# OptionalParameterTestFixture): +# """SET ENDPOINT_TIMING for endpoint id 0.""" +# PID = 'ENDPOINT_TIMING' +# TODO(peter): Test set zero + + +class SetEndpointTimingWithNoData(TestMixins.SetWithNoDataMixin, + OptionalParameterTestFixture): + """Set ENDPOINT_TIMING command with no data.""" + PID = 'ENDPOINT_TIMING' + + +class SetEndpointTimingWithExtraData(TestMixins.SetWithDataMixin, + OptionalParameterTestFixture): + """Send a SET ENDPOINT_TIMING command with extra data.""" + PID = 'ENDPOINT_TIMING' + DATA = 'foobar' + + +class AllSubDevicesGetEndpointTimingDescription( + TestMixins.AllSubDevicesGetMixin, + OptionalParameterTestFixture): + """Send a get ENDPOINT_TIMING_DESCRIPTION to ALL_SUB_DEVICES.""" + PID = 'ENDPOINT_TIMING_DESCRIPTION' + DATA = [0x01] + + +# class GetEndpointTimingDescription(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'ENDPOINT_TIMING_DESCRIPTION' +# TODO(peter): Test get + + +class GetZeroEndpointTimingDescription(TestMixins.GetZeroUInt8Mixin, + OptionalParameterTestFixture): + """GET ENDPOINT_TIMING_DESCRIPTION for timing setting 0.""" + PID = 'ENDPOINT_TIMING_DESCRIPTION' + + +class GetEndpointTimingDescriptionWithNoData(TestMixins.GetWithNoDataMixin, + OptionalParameterTestFixture): + """GET ENDPOINT_TIMING_DESCRIPTION with no argument given.""" + PID = 'ENDPOINT_TIMING_DESCRIPTION' + + +class GetEndpointTimingDescriptionWithExtraData(TestMixins.GetWithDataMixin, + OptionalParameterTestFixture): + """GET ENDPOINT_TIMING_DESCRIPTION with more than 1 byte of data.""" + PID = 'ENDPOINT_TIMING_DESCRIPTION' + + +class SetEndpointTimingDescription(TestMixins.UnsupportedSetMixin, + OptionalParameterTestFixture): + """Attempt to SET ENDPOINT_TIMING_DESCRIPTION.""" + PID = 'ENDPOINT_TIMING_DESCRIPTION' + + +class SetEndpointTimingDescriptionWithData( + TestMixins.UnsupportedSetWithDataMixin, + OptionalParameterTestFixture): + """Attempt to SET ENDPOINT_TIMING_DESCRIPTION with data.""" + PID = 'ENDPOINT_TIMING_DESCRIPTION' + + +class AllSubDevicesGetEndpointResponders(TestMixins.AllSubDevicesGetMixin, + OptionalParameterTestFixture): + """Send a get ENDPOINT_RESPONDERS to ALL_SUB_DEVICES.""" + PID = 'ENDPOINT_RESPONDERS' + DATA = [0x0001] + + +# class GetEndpointResponders(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'ENDPOINT_RESPONDERS' +# TODO(peter): Test get + + +class GetZeroEndpointResponders(TestMixins.GetZeroUInt16Mixin, + OptionalParameterTestFixture): + """GET ENDPOINT_RESPONDERS for endpoint id 0.""" + PID = 'ENDPOINT_RESPONDERS' + + +class GetEndpointRespondersWithNoData(TestMixins.GetWithNoDataMixin, + OptionalParameterTestFixture): + """GET ENDPOINT_RESPONDERS with no argument given.""" + PID = 'ENDPOINT_RESPONDERS' + + +class GetEndpointRespondersWithExtraData(TestMixins.GetWithDataMixin, + OptionalParameterTestFixture): + """GET ENDPOINT_RESPONDERS with more than 2 bytes of data.""" + PID = 'ENDPOINT_RESPONDERS' + + +class SetEndpointResponders(TestMixins.UnsupportedSetMixin, + OptionalParameterTestFixture): + """Attempt to SET ENDPOINT_RESPONDERS.""" + PID = 'ENDPOINT_RESPONDERS' + + +class SetEndpointRespondersWithData(TestMixins.UnsupportedSetWithDataMixin, + OptionalParameterTestFixture): + """Attempt to SET ENDPOINT_RESPONDERS with data.""" + PID = 'ENDPOINT_RESPONDERS' + + +class AllSubDevicesGetEndpointResponderListChange( + TestMixins.AllSubDevicesGetMixin, + OptionalParameterTestFixture): + """Send a get ENDPOINT_RESPONDER_LIST_CHANGE to ALL_SUB_DEVICES.""" + PID = 'ENDPOINT_RESPONDER_LIST_CHANGE' + DATA = [0x0001] + + +# class GetEndpointResponderListChange(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'ENDPOINT_RESPONDER_LIST_CHANGE' +# TODO(peter): Test get + + +class GetZeroEndpointResponderListChange(TestMixins.GetZeroUInt16Mixin, + OptionalParameterTestFixture): + """GET ENDPOINT_RESPONDER_LIST_CHANGE for endpoint id 0.""" + PID = 'ENDPOINT_RESPONDER_LIST_CHANGE' + + +class GetEndpointResponderListChangeWithNoData(TestMixins.GetWithNoDataMixin, + OptionalParameterTestFixture): + """GET ENDPOINT_RESPONDER_LIST_CHANGE with no argument given.""" + PID = 'ENDPOINT_RESPONDER_LIST_CHANGE' + + +class GetEndpointResponderListChangeWithExtraData(TestMixins.GetWithDataMixin, + OptionalParameterTestFixture): + """GET ENDPOINT_RESPONDER_LIST_CHANGE with more than 2 bytes of data.""" + PID = 'ENDPOINT_RESPONDER_LIST_CHANGE' + + +class SetEndpointResponderListChange(TestMixins.UnsupportedSetMixin, + OptionalParameterTestFixture): + """Attempt to SET ENDPOINT_RESPONDER_LIST_CHANGE.""" + PID = 'ENDPOINT_RESPONDER_LIST_CHANGE' + + +class SetEndpointResponderListChangeWithData( + TestMixins.UnsupportedSetWithDataMixin, + OptionalParameterTestFixture): + """Attempt to SET ENDPOINT_RESPONDER_LIST_CHANGE with data.""" + PID = 'ENDPOINT_RESPONDER_LIST_CHANGE' + + +class AllSubDevicesGetEndpointList(TestMixins.AllSubDevicesGetMixin, + OptionalParameterTestFixture): + """Send a get ENDPOINT_LIST to ALL_SUB_DEVICES.""" + PID = 'ENDPOINT_LIST' + + +# class GetEndpointList(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'ENDPOINT_LIST' +# TODO(peter): Test get + + +class GetEndpointListWithData(TestMixins.GetWithDataMixin, + OptionalParameterTestFixture): + """GET ENDPOINT_LIST with data.""" + PID = 'ENDPOINT_LIST' + + +class SetEndpointList(TestMixins.UnsupportedSetMixin, + OptionalParameterTestFixture): + """Attempt to SET ENDPOINT_LIST.""" + PID = 'ENDPOINT_LIST' + + +class SetEndpointListWithData(TestMixins.UnsupportedSetWithDataMixin, + OptionalParameterTestFixture): + """Attempt to SET ENDPOINT_LIST with data.""" + PID = 'ENDPOINT_LIST' + + +class AllSubDevicesGetEndpointListChange(TestMixins.AllSubDevicesGetMixin, + OptionalParameterTestFixture): + """Send a get ENDPOINT_LIST_CHANGE to ALL_SUB_DEVICES.""" + PID = 'ENDPOINT_LIST_CHANGE' + + +# class GetEndpointListChange(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'ENDPOINT_LIST_CHANGE' +# TODO(peter): Test get + + +class GetEndpointListChangeWithData(TestMixins.GetWithDataMixin, + OptionalParameterTestFixture): + """GET ENDPOINT_LIST_CHANGE with data.""" + PID = 'ENDPOINT_LIST_CHANGE' + + +class SetEndpointListChange(TestMixins.UnsupportedSetMixin, + OptionalParameterTestFixture): + """Attempt to SET ENDPOINT_LIST_CHANGE.""" + PID = 'ENDPOINT_LIST_CHANGE' + + +class SetEndpointListChangeWithData(TestMixins.UnsupportedSetWithDataMixin, + OptionalParameterTestFixture): + """Attempt to SET ENDPOINT_LIST_CHANGE with data.""" + PID = 'ENDPOINT_LIST_CHANGE' + + +class AllSubDevicesGetEndpointToUniverse(TestMixins.AllSubDevicesGetMixin, + OptionalParameterTestFixture): + """Send a get ENDPOINT_TO_UNIVERSE to ALL_SUB_DEVICES.""" + PID = 'ENDPOINT_TO_UNIVERSE' + DATA = [0x0001] + + +# class GetEndpointToUniverse(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'ENDPOINT_TO_UNIVERSE' +# TODO(peter): Test get + + +class GetZeroEndpointToUniverse(TestMixins.GetZeroUInt16Mixin, + OptionalParameterTestFixture): + """GET ENDPOINT_TO_UNIVERSE for endpoint id 0.""" + PID = 'ENDPOINT_TO_UNIVERSE' + + +class GetEndpointToUniverseWithNoData(TestMixins.GetWithNoDataMixin, + OptionalParameterTestFixture): + """GET ENDPOINT_TO_UNIVERSE with no argument given.""" + PID = 'ENDPOINT_TO_UNIVERSE' + + +class GetEndpointToUniverseWithExtraData(TestMixins.GetWithDataMixin, + OptionalParameterTestFixture): + """GET ENDPOINT_TO_UNIVERSE with more than 2 bytes of data.""" + PID = 'ENDPOINT_TO_UNIVERSE' + + +# class SetEndpointToUniverse(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'ENDPOINT_TO_UNIVERSE' +# TODO(peter): Test set + + +# class SetZeroEndpointToUniverse(TestMixins.SetZero, +# OptionalParameterTestFixture): +# """SET ENDPOINT_TO_UNIVERSE for endpoint id 0.""" +# PID = 'ENDPOINT_TO_UNIVERSE' +# TODO(peter): Test set zero + + +class SetEndpointToUniverseWithNoData(TestMixins.SetWithNoDataMixin, + OptionalParameterTestFixture): + """Set ENDPOINT_TO_UNIVERSE command with no data.""" + PID = 'ENDPOINT_TO_UNIVERSE' + + +class SetEndpointToUniverseWithExtraData(TestMixins.SetWithDataMixin, + OptionalParameterTestFixture): + """Send a SET ENDPOINT_TO_UNIVERSE command with extra data.""" + PID = 'ENDPOINT_TO_UNIVERSE' + DATA = 'foobar' + + +class AllSubDevicesGetRdmTrafficEnable(TestMixins.AllSubDevicesGetMixin, + OptionalParameterTestFixture): + """Send a get RDM_TRAFFIC_ENABLE to ALL_SUB_DEVICES.""" + PID = 'RDM_TRAFFIC_ENABLE' + DATA = [0x0001] + + +# class GetRdmTrafficEnable(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'RDM_TRAFFIC_ENABLE' +# TODO(peter): Test get + + +class GetZeroRdmTrafficEnable(TestMixins.GetZeroUInt16Mixin, + OptionalParameterTestFixture): + """GET RDM_TRAFFIC_ENABLE for endpoint id 0.""" + PID = 'RDM_TRAFFIC_ENABLE' + + +class GetRdmTrafficEnableWithNoData(TestMixins.GetWithNoDataMixin, + OptionalParameterTestFixture): + """GET RDM_TRAFFIC_ENABLE with no argument given.""" + PID = 'RDM_TRAFFIC_ENABLE' + + +class GetRdmTrafficEnableWithExtraData(TestMixins.GetWithDataMixin, + OptionalParameterTestFixture): + """GET RDM_TRAFFIC_ENABLE with more than 2 bytes of data.""" + PID = 'RDM_TRAFFIC_ENABLE' + + +# class SetRdmTrafficEnable(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'RDM_TRAFFIC_ENABLE' +# TODO(peter): Test set + + +# class SetZeroRdmTrafficEnable(TestMixins.SetZero, +# OptionalParameterTestFixture): +# """SET RDM_TRAFFIC_ENABLE for endpoint id 0.""" +# PID = 'RDM_TRAFFIC_ENABLE' +# TODO(peter): Test set zero + + +class SetRdmTrafficEnableWithNoData(TestMixins.SetWithNoDataMixin, + OptionalParameterTestFixture): + """Set RDM_TRAFFIC_ENABLE command with no data.""" + PID = 'RDM_TRAFFIC_ENABLE' + + +class SetRdmTrafficEnableWithExtraData(TestMixins.SetWithDataMixin, + OptionalParameterTestFixture): + """Send a SET RDM_TRAFFIC_ENABLE command with extra data.""" + PID = 'RDM_TRAFFIC_ENABLE' + DATA = 'foobar' + + +class AllSubDevicesGetDiscoveryState(TestMixins.AllSubDevicesGetMixin, + OptionalParameterTestFixture): + """Send a get DISCOVERY_STATE to ALL_SUB_DEVICES.""" + PID = 'DISCOVERY_STATE' + DATA = [0x0001] + + +# class GetDiscoveryState(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'DISCOVERY_STATE' +# TODO(peter): Test get + + +class GetZeroDiscoveryState(TestMixins.GetZeroUInt16Mixin, + OptionalParameterTestFixture): + """GET DISCOVERY_STATE for endpoint id 0.""" + PID = 'DISCOVERY_STATE' + + +class GetDiscoveryStateWithNoData(TestMixins.GetWithNoDataMixin, + OptionalParameterTestFixture): + """GET DISCOVERY_STATE with no argument given.""" + PID = 'DISCOVERY_STATE' + + +class GetDiscoveryStateWithExtraData(TestMixins.GetWithDataMixin, + OptionalParameterTestFixture): + """GET DISCOVERY_STATE with more than 2 bytes of data.""" + PID = 'DISCOVERY_STATE' + + +# class SetDiscoveryState(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'DISCOVERY_STATE' +# TODO(peter): Test set + + +# class SetZeroDiscoveryState(TestMixins.SetZero, +# OptionalParameterTestFixture): +# """SET DISCOVERY_STATE for endpoint id 0.""" +# PID = 'DISCOVERY_STATE' +# TODO(peter): Test set zero + + +class SetDiscoveryStateWithNoData(TestMixins.SetWithNoDataMixin, + OptionalParameterTestFixture): + """Set DISCOVERY_STATE command with no data.""" + PID = 'DISCOVERY_STATE' + + +class SetDiscoveryStateWithExtraData(TestMixins.SetWithDataMixin, + OptionalParameterTestFixture): + """Send a SET DISCOVERY_STATE command with extra data.""" + PID = 'DISCOVERY_STATE' + DATA = 'foobar' + + +class AllSubDevicesGetBackgroundDiscovery(TestMixins.AllSubDevicesGetMixin, + OptionalParameterTestFixture): + """Send a get BACKGROUND_DISCOVERY to ALL_SUB_DEVICES.""" + PID = 'BACKGROUND_DISCOVERY' + DATA = [0x0001] + + +# class GetBackgroundDiscovery(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'BACKGROUND_DISCOVERY' +# TODO(peter): Test get + + +class GetZeroBackgroundDiscovery(TestMixins.GetZeroUInt16Mixin, + OptionalParameterTestFixture): + """GET BACKGROUND_DISCOVERY for endpoint id 0.""" + PID = 'BACKGROUND_DISCOVERY' + + +class GetBackgroundDiscoveryWithNoData(TestMixins.GetWithNoDataMixin, + OptionalParameterTestFixture): + """GET BACKGROUND_DISCOVERY with no argument given.""" + PID = 'BACKGROUND_DISCOVERY' + + +class GetBackgroundDiscoveryWithExtraData(TestMixins.GetWithDataMixin, + OptionalParameterTestFixture): + """GET BACKGROUND_DISCOVERY with more than 2 bytes of data.""" + PID = 'BACKGROUND_DISCOVERY' + + +# class SetBackgroundDiscovery(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'BACKGROUND_DISCOVERY' +# TODO(peter): Test set + + +# class SetZeroBackgroundDiscovery(TestMixins.SetZero, +# OptionalParameterTestFixture): +# """SET BACKGROUND_DISCOVERY for endpoint id 0.""" +# PID = 'BACKGROUND_DISCOVERY' +# TODO(peter): Test set zero + + +class SetBackgroundDiscoveryWithNoData(TestMixins.SetWithNoDataMixin, + OptionalParameterTestFixture): + """Set BACKGROUND_DISCOVERY command with no data.""" + PID = 'BACKGROUND_DISCOVERY' + + +class SetBackgroundDiscoveryWithExtraData(TestMixins.SetWithDataMixin, + OptionalParameterTestFixture): + """Send a SET BACKGROUND_DISCOVERY command with extra data.""" + PID = 'BACKGROUND_DISCOVERY' + DATA = 'foobar' + + +class AllSubDevicesGetBackgroundQueuedStatusPolicy( + TestMixins.AllSubDevicesGetMixin, + OptionalParameterTestFixture): + """Send a get BACKGROUND_QUEUED_STATUS_POLICY to ALL_SUB_DEVICES.""" + PID = 'BACKGROUND_QUEUED_STATUS_POLICY' + + +# class GetBackgroundQueuedStatusPolicy(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'BACKGROUND_QUEUED_STATUS_POLICY' +# TODO(peter): Test get + + +class GetBackgroundQueuedStatusPolicyWithData(TestMixins.GetWithDataMixin, + OptionalParameterTestFixture): + """GET BACKGROUND_QUEUED_STATUS_POLICY with data.""" + PID = 'BACKGROUND_QUEUED_STATUS_POLICY' + + +# class SetBackgroundQueuedStatusPolicy(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'BACKGROUND_QUEUED_STATUS_POLICY' +# TODO(peter): Test set + + +class SetBackgroundQueuedStatusPolicyWithNoData(TestMixins.SetWithNoDataMixin, + OptionalParameterTestFixture): + """Set BACKGROUND_QUEUED_STATUS_POLICY command with no data.""" + PID = 'BACKGROUND_QUEUED_STATUS_POLICY' + + +class SetBackgroundQueuedStatusPolicyWithExtraData(TestMixins.SetWithDataMixin, + OptionalParameterTestFixture): + """Send a SET BACKGROUND_QUEUED_STATUS_POLICY command with extra data.""" + PID = 'BACKGROUND_QUEUED_STATUS_POLICY' + + +class AllSubDevicesGetBackgroundQueuedStatusPolicyDescription( + TestMixins.AllSubDevicesGetMixin, + OptionalParameterTestFixture): + """Send a get BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION to ALL_SUB_DEVICES.""" + PID = 'BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION' + DATA = [0x00] + + +# class GetBackgroundQueuedStatusPolicyDescription(TestMixins., +# OptionalParameterTestFixture): +# CATEGORY = TestCategory. +# PID = 'BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION' +# TODO(peter): Test get + + +class GetBackgroundQueuedStatusPolicyDescriptionWithNoData( + TestMixins.GetWithNoDataMixin, + OptionalParameterTestFixture): + """GET BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION with no argument given.""" + PID = 'BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION' + + +class GetBackgroundQueuedStatusPolicyDescriptionWithExtraData( + TestMixins.GetWithDataMixin, + OptionalParameterTestFixture): + """GET BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION with more than 1 byte of data.""" + PID = 'BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION' + + +class SetBackgroundQueuedStatusPolicyDescription(TestMixins.UnsupportedSetMixin, + OptionalParameterTestFixture): + """Attempt to SET BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION.""" + PID = 'BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION' + + +class SetBackgroundQueuedStatusPolicyDescriptionWithData( + TestMixins.UnsupportedSetWithDataMixin, + OptionalParameterTestFixture): + """Attempt to SET BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION with data.""" + PID = 'BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION' + + # Cross check the control fields with various other properties # ----------------------------------------------------------------------------- class SubDeviceControlField(TestFixture): From 68703616d688d41d0f0a6d43e048aa5b806051c7 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Wed, 26 Feb 2020 11:48:27 +0000 Subject: [PATCH 043/138] Add the ability to override the expected NACK for GetZeroMixin --- tools/rdm/TestMixins.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/rdm/TestMixins.py b/tools/rdm/TestMixins.py index 3145c95bc1..58c0dc13c8 100644 --- a/tools/rdm/TestMixins.py +++ b/tools/rdm/TestMixins.py @@ -1021,16 +1021,27 @@ def ResetState(self): class GetZeroMixin(ResponderTestFixture): - """Send a get to index 0, expect NR_DATA_OUT_OF_RANGE""" + """Send a get to index 0, normally expect NR_DATA_OUT_OF_RANGE + + If OVERRIDE_NACKS is non-empty, this overrides NR_DATA_OUT_OF_RANGE and adds + a custom NackGetResult to the list of allowed results for each entry. + """ CATEGORY = TestCategory.ERROR_CONDITIONS DATA = None + OVERRIDE_NACKS = [] def Test(self): if self.DATA is None: self.SetBroken('No DATA given for %s' % self.__class__.__name__) return - self.AddIfGetSupported(self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) + results = [] + if self.OVERRIDE_NACKS: + for nack in self.OVERRIDE_NACKS: + results.append(self.NackGetResult(nack)) + else: + results.append(self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) + self.AddIfGetSupported(results) self.SendRawGet(ROOT_DEVICE, self.pid, self.DATA) From f67491fa6b7a6403788f1bec94e8c03c4d40637d Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Wed, 26 Feb 2020 11:48:54 +0000 Subject: [PATCH 044/138] Correct the expected NACK for some endpoint number checks --- tools/rdm/TestDefinitions.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/rdm/TestDefinitions.py b/tools/rdm/TestDefinitions.py index 149f75d0e9..db6ddce576 100644 --- a/tools/rdm/TestDefinitions.py +++ b/tools/rdm/TestDefinitions.py @@ -7948,6 +7948,7 @@ class GetZeroEndpointMode(TestMixins.GetZeroUInt16Mixin, OptionalParameterTestFixture): """GET ENDPOINT_MODE for endpoint id 0.""" PID = 'ENDPOINT_MODE' + OVERRIDE_NACKS = [RDMNack.NR_ENDPOINT_NUMBER_INVALID] class GetEndpointModeWithNoData(TestMixins.GetWithNoDataMixin, @@ -8007,6 +8008,7 @@ class GetZeroEndpointLabel(TestMixins.GetZeroUInt16Mixin, OptionalParameterTestFixture): """GET ENDPOINT_LABEL for endpoint id 0.""" PID = 'ENDPOINT_LABEL' + OVERRIDE_NACKS = [RDMNack.NR_ENDPOINT_NUMBER_INVALID] class GetEndpointLabelWithNoData(TestMixins.GetWithNoDataMixin, @@ -8065,6 +8067,7 @@ class GetZeroEndpointTiming(TestMixins.GetZeroUInt16Mixin, OptionalParameterTestFixture): """GET ENDPOINT_TIMING for endpoint id 0.""" PID = 'ENDPOINT_TIMING' + OVERRIDE_NACKS = [RDMNack.NR_ENDPOINT_NUMBER_INVALID] class GetEndpointTimingWithNoData(TestMixins.GetWithNoDataMixin, @@ -8170,6 +8173,7 @@ class GetZeroEndpointResponders(TestMixins.GetZeroUInt16Mixin, OptionalParameterTestFixture): """GET ENDPOINT_RESPONDERS for endpoint id 0.""" PID = 'ENDPOINT_RESPONDERS' + OVERRIDE_NACKS = [RDMNack.NR_ENDPOINT_NUMBER_INVALID] class GetEndpointRespondersWithNoData(TestMixins.GetWithNoDataMixin, @@ -8215,6 +8219,7 @@ class GetZeroEndpointResponderListChange(TestMixins.GetZeroUInt16Mixin, OptionalParameterTestFixture): """GET ENDPOINT_RESPONDER_LIST_CHANGE for endpoint id 0.""" PID = 'ENDPOINT_RESPONDER_LIST_CHANGE' + OVERRIDE_NACKS = [RDMNack.NR_ENDPOINT_NUMBER_INVALID] class GetEndpointResponderListChangeWithNoData(TestMixins.GetWithNoDataMixin, @@ -8322,6 +8327,7 @@ class GetZeroEndpointToUniverse(TestMixins.GetZeroUInt16Mixin, OptionalParameterTestFixture): """GET ENDPOINT_TO_UNIVERSE for endpoint id 0.""" PID = 'ENDPOINT_TO_UNIVERSE' + OVERRIDE_NACKS = [RDMNack.NR_ENDPOINT_NUMBER_INVALID] class GetEndpointToUniverseWithNoData(TestMixins.GetWithNoDataMixin, @@ -8381,6 +8387,7 @@ class GetZeroRdmTrafficEnable(TestMixins.GetZeroUInt16Mixin, OptionalParameterTestFixture): """GET RDM_TRAFFIC_ENABLE for endpoint id 0.""" PID = 'RDM_TRAFFIC_ENABLE' + OVERRIDE_NACKS = [RDMNack.NR_ENDPOINT_NUMBER_INVALID] class GetRdmTrafficEnableWithNoData(TestMixins.GetWithNoDataMixin, @@ -8440,6 +8447,7 @@ class GetZeroDiscoveryState(TestMixins.GetZeroUInt16Mixin, OptionalParameterTestFixture): """GET DISCOVERY_STATE for endpoint id 0.""" PID = 'DISCOVERY_STATE' + OVERRIDE_NACKS = [RDMNack.NR_ENDPOINT_NUMBER_INVALID] class GetDiscoveryStateWithNoData(TestMixins.GetWithNoDataMixin, @@ -8499,6 +8507,7 @@ class GetZeroBackgroundDiscovery(TestMixins.GetZeroUInt16Mixin, OptionalParameterTestFixture): """GET BACKGROUND_DISCOVERY for endpoint id 0.""" PID = 'BACKGROUND_DISCOVERY' + OVERRIDE_NACKS = [RDMNack.NR_ENDPOINT_NUMBER_INVALID] class GetBackgroundDiscoveryWithNoData(TestMixins.GetWithNoDataMixin, From e59b0289a7eead8fc440556b628829725693bc63 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Wed, 26 Feb 2020 18:04:40 +0000 Subject: [PATCH 045/138] Support loopback and selecting an interface --- tools/e133/llrp-manager.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/e133/llrp-manager.cpp b/tools/e133/llrp-manager.cpp index 4857919287..aa9f742277 100644 --- a/tools/e133/llrp-manager.cpp +++ b/tools/e133/llrp-manager.cpp @@ -96,11 +96,14 @@ using ola::rdm::UIDSet; DEFINE_string(manager_uid, "7a70:00000002", "The UID of the manager."); DEFINE_default_bool(set, false, "Send a set rather than a get."); +DEFINE_default_bool(allow_loopback, false, "Include the loopback interface."); +DEFINE_s_string(interface, i, "", + "The interface name (e.g. eth0) or IP address of the network " + "interface to use for LLRP messages."); auto_ptr picker( ola::network::InterfacePicker::NewPicker()); ola::network::Interface m_interface; -const std::string m_preferred_ip; ola::network::UDPSocket m_socket; uint8_t *m_recv_buffer; std::auto_ptr manager_uid; @@ -402,8 +405,9 @@ int main(int argc, char* argv[]) { } std::cout << "Bind!" << std::endl; + const std::string m_preferred_ip = FLAGS_interface; ola::network::InterfacePicker::Options options; - options.include_loopback = false; + options.include_loopback = FLAGS_allow_loopback; if (!picker->ChooseInterface(&m_interface, m_preferred_ip, options)) { OLA_INFO << "Failed to find an interface"; return false; From fd26efa54d1476fb45a01363ab45dc0bf7ae51ce Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 4 Mar 2023 07:37:00 +0000 Subject: [PATCH 046/138] Add some detail on how DMX-TRI error codes are done from its developer --- plugins/usbpro/DmxTriWidget.cpp | 3 +++ plugins/usbpro/DmxTriWidget.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/plugins/usbpro/DmxTriWidget.cpp b/plugins/usbpro/DmxTriWidget.cpp index e6fdefc6a3..d8b98461df 100644 --- a/plugins/usbpro/DmxTriWidget.cpp +++ b/plugins/usbpro/DmxTriWidget.cpp @@ -950,6 +950,9 @@ bool DmxTriWidgetImpl::TriToOlaReturnCode( /** * Convert a DMX-TRI return code to Nack reason code if appropriate + * + * On the widget, the RDM NACK code is currently bitwise or-ed with 0x20 to + * generate the error code */ bool DmxTriWidgetImpl::ReturnCodeToNackReason( uint8_t return_code, diff --git a/plugins/usbpro/DmxTriWidget.h b/plugins/usbpro/DmxTriWidget.h index 6ec0addb9d..1b9f28a346 100644 --- a/plugins/usbpro/DmxTriWidget.h +++ b/plugins/usbpro/DmxTriWidget.h @@ -201,6 +201,8 @@ class DmxTriWidgetImpl: public BaseUsbProWidget, EC_INVALID_IPV6_ADDRESS = 0x32, // this is a guess EC_INVALID_PORT = 0x33 // this is a guess } dmx_tri_error_codes; + // The RDM NACK code is currently bitwise or-ed with 0x20 to generate the + // error code // TODO(Peter): try and test the guessed values static const unsigned int DATA_OFFSET = 2; // first two bytes are CI & RC From 9d60884097e6ae5cedd05126a82f2fe382ae6c6e Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 4 Mar 2023 08:16:44 +0000 Subject: [PATCH 047/138] Improve some size calculations, only output SetWithNoData when actually required and improve how and when we set the DATA variable --- tools/rdm/list_rdm_tests.py | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/tools/rdm/list_rdm_tests.py b/tools/rdm/list_rdm_tests.py index 5ea5cdb590..1e4e386438 100755 --- a/tools/rdm/list_rdm_tests.py +++ b/tools/rdm/list_rdm_tests.py @@ -153,10 +153,14 @@ def GetWithExtraData(names, pid, pid_test_base_name, get_size): dummy_data = GenerateDummyData(get_size) if dummy_data is None: print((" #DATA = 'foo' # TODO(%s): Specify extra data if this isn't " - "enough") % (getpass.getuser())) + "enough. Ensure the first %d bytes are sane/valid.") % (getpass.getuser(), get_size)) elif dummy_data != 'foo': - # Doesn't match default - print(" DATA = '%s'" % (dummy_data)) + # Doesn't match default, explicitly set value + print((" DATA = '%s' # TODO(%s): Specify extra data if this isn't " + "enough. Ensure the first %d bytes are sane/valid.") % (dummy_data, getpass.getuser(), get_size)) + else: + print((" #DATA = '%s' # TODO(%s): Specify extra data if this isn't " + "enough. Ensure the first %d bytes are sane/valid.") % (dummy_data, getpass.getuser(), get_size)) print('') print('') @@ -272,10 +276,14 @@ def SetWithExtraData(names, pid, pid_test_base_name, set_size): dummy_data = GenerateDummyData(set_size) if dummy_data is None: print((" #DATA = 'foo' # TODO(%s): Specify extra data if this isn't " - "enough") % (getpass.getuser())) + "enough. Ensure the first %d bytes are sane/valid.") % (getpass.getuser(), set_size)) elif dummy_data != 'foo': - # Doesn't match default - print(" DATA = '%s'" % (dummy_data)) + # Doesn't match default, explicitly set value + print((" DATA = '%s' # TODO(%s): Specify extra data if this isn't " + "enough. Ensure the first %d bytes are sane/valid.") % (dummy_data, getpass.getuser(), set_size)) + else: + print((" #DATA = '%s' # TODO(%s): Specify extra data if this isn't " + "enough. Ensure the first %d bytes are sane/valid.") % (dummy_data, getpass.getuser(), set_size)) print('') print('') @@ -342,8 +350,11 @@ def main(): get_size = 0 if ((pid.RequestSupported(PidStore.RDM_GET)) and (pid.GetRequest(PidStore.RDM_GET).HasAtoms())): - get_size = pid.GetRequest(PidStore.RDM_GET).GetAtoms()[0].size - # print('# Get requires %d bytes' % (get_size)) + for atom in pid.GetRequest(PidStore.RDM_GET).GetAtoms(): + get_size += atom.size + #TODO(Peter): Should we just print this total all the time? + if get_size != pid.GetRequest(PidStore.RDM_GET).GetAtoms()[0].size: + print('# Get requires %d bytes' % (get_size)) AllSubDevicesGet(names, pid, pid_test_base_name, get_size) @@ -381,7 +392,8 @@ def main(): first_atom.ValidateRawValueInRange(1))): SetZero(names, pid, pid_test_base_name, first_atom) - SetWithNoData(names, pid, pid_test_base_name) + if set_size > 0: + SetWithNoData(names, pid, pid_test_base_name) SetWithExtraData(names, pid, pid_test_base_name, set_size) else: From c2126d1d1d686671db65c58bad9acd7b90243514 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 7 Mar 2023 14:44:52 +0000 Subject: [PATCH 048/138] First attempt at the E1.33 Broker PDU --- libs/acn/BrokerPDU.cpp | 68 ++++++++++++++++++++ libs/acn/BrokerPDU.h | 62 ++++++++++++++++++ libs/acn/BrokerPDUTest.cpp | 127 +++++++++++++++++++++++++++++++++++++ libs/acn/Makefile.mk | 3 + 4 files changed, 260 insertions(+) create mode 100644 libs/acn/BrokerPDU.cpp create mode 100644 libs/acn/BrokerPDU.h create mode 100644 libs/acn/BrokerPDUTest.cpp diff --git a/libs/acn/BrokerPDU.cpp b/libs/acn/BrokerPDU.cpp new file mode 100644 index 0000000000..8dcf9a844e --- /dev/null +++ b/libs/acn/BrokerPDU.cpp @@ -0,0 +1,68 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerPDU.cpp + * The BrokerPDU + * Copyright (C) 2023 Peter Newman + */ + + +#include "ola/Logging.h" +#include "ola/base/Array.h" +#include "ola/network/NetworkUtils.h" +#include "libs/acn/BrokerPDU.h" + +namespace ola { +namespace acn { + +using ola::io::OutputStream; +using ola::network::HostToNetwork; + +/* + * Size of the data portion + */ +unsigned int BrokerPDU::DataSize() const { + return m_pdu ? m_pdu->Size() : 0; +} + + +/* + * Pack the data portion. + */ +bool BrokerPDU::PackData(uint8_t *data, unsigned int *length) const { + if (m_pdu) + return m_pdu->Pack(data, length); + *length = 0; + return true; +} + + +/* + * Pack the data into a buffer + */ +void BrokerPDU::PackData(OutputStream *stream) const { + if (m_pdu) + m_pdu->Write(stream); +} + + +void BrokerPDU::PrependPDU(ola::io::IOStack *stack, + uint32_t vector) { + vector = HostToNetwork(vector); + stack->Write(reinterpret_cast(&vector), sizeof(vector)); + PrependFlagsAndLength(stack, VFLAG_MASK | HFLAG_MASK | DFLAG_MASK, true); +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/BrokerPDU.h b/libs/acn/BrokerPDU.h new file mode 100644 index 0000000000..788f409b5a --- /dev/null +++ b/libs/acn/BrokerPDU.h @@ -0,0 +1,62 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerPDU.h + * Interface for the BrokerPDU class + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_BROKERPDU_H_ +#define LIBS_ACN_BROKERPDU_H_ + +#include +#include + +#include "libs/acn/PDU.h" +#include "libs/acn/BrokerHeader.h" + +namespace ola { +namespace acn { + +class BrokerPDU: public PDU { + public: + BrokerPDU(unsigned int vector, + const PDU *pdu): + PDU(vector, FOUR_BYTES, true), + m_pdu(pdu) {} + ~BrokerPDU() {} + + unsigned int HeaderSize() const { return 0; } + bool PackHeader(OLA_UNUSED uint8_t *data, + unsigned int *length) const { + *length = 0; + return true; + } + void PackHeader(OLA_UNUSED ola::io::OutputStream *stream) const {} + + unsigned int DataSize() const; + bool PackData(uint8_t *data, unsigned int *length) const; + + void PackData(ola::io::OutputStream *stream) const; + + static void PrependPDU(ola::io::IOStack *stack, + uint32_t vector); + + private: + const PDU *m_pdu; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_BROKERPDU_H_ diff --git a/libs/acn/BrokerPDUTest.cpp b/libs/acn/BrokerPDUTest.cpp new file mode 100644 index 0000000000..e4c2c6ef60 --- /dev/null +++ b/libs/acn/BrokerPDUTest.cpp @@ -0,0 +1,127 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerPDUTest.cpp + * Test fixture for the BrokerPDU class + * Copyright (C) 2023 Peter Newman + */ + +#include + +#include "ola/Logging.h" +#include "ola/io/IOQueue.h" +#include "ola/io/OutputStream.h" +#include "ola/network/NetworkUtils.h" +#include "ola/testing/TestUtils.h" +#include "libs/acn/BrokerPDU.h" +#include "libs/acn/PDUTestCommon.h" + + +namespace ola { +namespace acn { + +using ola::io::IOQueue; +using ola::io::OutputStream; +using ola::network::HostToNetwork; + +class BrokerPDUTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(BrokerPDUTest); + CPPUNIT_TEST(testSimpleBrokerPDU); + CPPUNIT_TEST(testSimpleBrokerPDUToOutputStream); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSimpleBrokerPDU(); + void testSimpleBrokerPDUToOutputStream(); + + void setUp() { + ola::InitLogging(ola::OLA_LOG_DEBUG, ola::OLA_LOG_STDERR); + } + + private: + static const unsigned int TEST_VECTOR; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(BrokerPDUTest); + +const unsigned int BrokerPDUTest::TEST_VECTOR = 39; + + +/* + * Test that packing a BrokerPDU without data works. + */ +void BrokerPDUTest::testSimpleBrokerPDU() { + BrokerPDU pdu(TEST_VECTOR, NULL); + + OLA_ASSERT_EQ(0u, pdu.HeaderSize()); + OLA_ASSERT_EQ(0u, pdu.DataSize()); + OLA_ASSERT_EQ(7u, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + + // spot check the data + OLA_ASSERT_EQ((uint8_t) 0xf0, data[0]); + // bytes_used is technically data[1] and data[2] if > 255 + OLA_ASSERT_EQ((uint8_t) bytes_used, data[2]); + unsigned int actual_value; + memcpy(&actual_value, data + 3, sizeof(actual_value)); + OLA_ASSERT_EQ(HostToNetwork(TEST_VECTOR), actual_value); + + // test undersized buffer + bytes_used = size - 1; + OLA_ASSERT_FALSE(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(0u, bytes_used); + + // test oversized buffer + bytes_used = size + 1; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + delete[] data; +} + + +/* + * Test that writing to an output stream works. + */ +void BrokerPDUTest::testSimpleBrokerPDUToOutputStream() { + BrokerPDU pdu(TEST_VECTOR, NULL); + + OLA_ASSERT_EQ(0u, pdu.HeaderSize()); + OLA_ASSERT_EQ(0u, pdu.DataSize()); + OLA_ASSERT_EQ(7u, pdu.Size()); + + IOQueue output; + OutputStream stream(&output); + pdu.Write(&stream); + OLA_ASSERT_EQ(7u, output.Size()); + + uint8_t *pdu_data = new uint8_t[output.Size()]; + unsigned int pdu_size = output.Peek(pdu_data, output.Size()); + OLA_ASSERT_EQ(output.Size(), pdu_size); + + uint8_t EXPECTED[] = { + 0xf0, 0x00, 0x07, + 0, 0, 0, 39 + }; + OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), pdu_data, pdu_size); + output.Pop(output.Size()); + delete[] pdu_data; +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index a036a3f55a..82466ec2a3 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -31,6 +31,8 @@ noinst_LTLIBRARIES += libs/acn/libolae131core.la libs_acn_libolae131core_la_SOURCES = \ libs/acn/BaseInflator.cpp \ libs/acn/BaseInflator.h \ + libs/acn/BrokerPDU.cpp \ + libs/acn/BrokerPDU.h \ libs/acn/DMPAddress.cpp \ libs/acn/DMPAddress.h \ libs/acn/DMPE131Inflator.cpp \ @@ -146,6 +148,7 @@ libs_acn_E131Tester_LDADD = \ $(COMMON_TESTING_LIBS) libs_acn_E133Tester_SOURCES = \ + libs/acn/BrokerPDUTest.cpp \ libs/acn/E133InflatorTest.cpp \ libs/acn/E133PDUTest.cpp \ libs/acn/RDMPDUTest.cpp From 2a43710c8e595911c2981ce08bf0dc47d5888f27 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 7 Mar 2023 16:23:26 +0000 Subject: [PATCH 049/138] First attempt at BrokerClientEntryPDU --- libs/acn/BrokerClientEntryHeader.h | 63 ++++++++++++ libs/acn/BrokerClientEntryPDU.cpp | 114 +++++++++++++++++++++ libs/acn/BrokerClientEntryPDU.h | 61 +++++++++++ libs/acn/BrokerClientEntryPDUTest.cpp | 141 ++++++++++++++++++++++++++ libs/acn/BrokerPDU.h | 1 - libs/acn/Makefile.mk | 4 + 6 files changed, 383 insertions(+), 1 deletion(-) create mode 100644 libs/acn/BrokerClientEntryHeader.h create mode 100644 libs/acn/BrokerClientEntryPDU.cpp create mode 100644 libs/acn/BrokerClientEntryPDU.h create mode 100644 libs/acn/BrokerClientEntryPDUTest.cpp diff --git a/libs/acn/BrokerClientEntryHeader.h b/libs/acn/BrokerClientEntryHeader.h new file mode 100644 index 0000000000..d2277d9671 --- /dev/null +++ b/libs/acn/BrokerClientEntryHeader.h @@ -0,0 +1,63 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerClientEntryHeader.h + * The E1.33 Broker Client Entry Header + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_BROKERCLIENTENTRYHEADER_H_ +#define LIBS_ACN_BROKERCLIENTENTRYHEADER_H_ + +#include +#include + +#include + +namespace ola { +namespace acn { + +// TODO(Peter): I think technically this probably shouldn't be a header and +// instead is just data at this level! +/* + * Header for the Broker Client Entry level + */ +class BrokerClientEntryHeader { + public: + BrokerClientEntryHeader() {} + + BrokerClientEntryHeader(const ola::acn::CID &client_cid) + : m_client_cid(client_cid) { + } + ~BrokerClientEntryHeader() {} + + const ola::acn::CID ClientCid() const { return m_client_cid; } + + bool operator==(const BrokerClientEntryHeader &other) const { + return m_client_cid == other.m_client_cid; + } + + PACK( + struct broker_client_entry_pdu_header_s { + uint8_t client_cid[CID::CID_LENGTH]; + }); + typedef struct broker_client_entry_pdu_header_s broker_client_entry_pdu_header; + + private: + ola::acn::CID m_client_cid; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_BROKERCLIENTENTRYHEADER_H_ diff --git a/libs/acn/BrokerClientEntryPDU.cpp b/libs/acn/BrokerClientEntryPDU.cpp new file mode 100644 index 0000000000..521604e742 --- /dev/null +++ b/libs/acn/BrokerClientEntryPDU.cpp @@ -0,0 +1,114 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerClientEntryPDU.cpp + * The BrokerClientEntryPDU + * Copyright (C) 2023 Peter Newman + */ + + +#include "ola/Logging.h" +#include "ola/base/Array.h" +#include "ola/network/NetworkUtils.h" +#include "libs/acn/BrokerClientEntryPDU.h" + +namespace ola { +namespace acn { + +using ola::io::OutputStream; +using ola::network::HostToNetwork; + +/* + * Size of the header portion. + */ +unsigned int BrokerClientEntryPDU::HeaderSize() const { + return sizeof(BrokerClientEntryHeader::broker_client_entry_pdu_header); +} + + +/* + * Size of the data portion + */ +unsigned int BrokerClientEntryPDU::DataSize() const { + return m_pdu ? m_pdu->Size() : 0; +} + + +/* + * Pack the header portion. + */ +bool BrokerClientEntryPDU::PackHeader(uint8_t *data, unsigned int *length) const { + unsigned int header_size = HeaderSize(); + + if (*length < header_size) { + OLA_WARN << "BrokerClientEntryPDU::PackHeader: buffer too small, got " << *length + << " required " << header_size; + *length = 0; + return false; + } + + BrokerClientEntryHeader::broker_client_entry_pdu_header header; + m_header.ClientCid().Pack(header.client_cid); + *length = sizeof(BrokerClientEntryHeader::broker_client_entry_pdu_header); + memcpy(data, &header, *length); + return true; +} + + +/* + * Pack the data portion. + */ +bool BrokerClientEntryPDU::PackData(uint8_t *data, unsigned int *length) const { + if (m_pdu) + return m_pdu->Pack(data, length); + *length = 0; + return true; +} + + +/* + * Pack the header into a buffer. + */ +void BrokerClientEntryPDU::PackHeader(OutputStream *stream) const { + BrokerClientEntryHeader::broker_client_entry_pdu_header header; + m_header.ClientCid().Pack(header.client_cid); + stream->Write(reinterpret_cast(&header), + sizeof(BrokerClientEntryHeader::broker_client_entry_pdu_header)); +} + + +/* + * Pack the data into a buffer + */ +void BrokerClientEntryPDU::PackData(OutputStream *stream) const { + if (m_pdu) + m_pdu->Write(stream); +} + + +void BrokerClientEntryPDU::PrependPDU(ola::io::IOStack *stack, + uint32_t vector, + const ola::acn::CID &client_cid) { + BrokerClientEntryHeader::broker_client_entry_pdu_header header; + client_cid.Pack(header.client_cid); + stack->Write(reinterpret_cast(&header), + sizeof(BrokerClientEntryHeader::broker_client_entry_pdu_header)); + + vector = HostToNetwork(vector); + stack->Write(reinterpret_cast(&vector), sizeof(vector)); + PrependFlagsAndLength(stack, VFLAG_MASK | HFLAG_MASK | DFLAG_MASK, true); +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/BrokerClientEntryPDU.h b/libs/acn/BrokerClientEntryPDU.h new file mode 100644 index 0000000000..cd6c83b4eb --- /dev/null +++ b/libs/acn/BrokerClientEntryPDU.h @@ -0,0 +1,61 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerClientEntryPDU.h + * Interface for the BrokerClientEntryPDU class + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_BROKERCLIENTENTRYPDU_H_ +#define LIBS_ACN_BROKERCLIENTENTRYPDU_H_ + +#include +#include + +#include "libs/acn/PDU.h" +#include "libs/acn/BrokerClientEntryHeader.h" + +namespace ola { +namespace acn { + +class BrokerClientEntryPDU: public PDU { + public: + BrokerClientEntryPDU(unsigned int vector, + const BrokerClientEntryHeader &header, + const PDU *pdu): + PDU(vector, FOUR_BYTES, true), + m_header(header), + m_pdu(pdu) {} + ~BrokerClientEntryPDU() {} + + unsigned int HeaderSize() const; + unsigned int DataSize() const; + bool PackHeader(uint8_t *data, unsigned int *length) const; + bool PackData(uint8_t *data, unsigned int *length) const; + + void PackHeader(ola::io::OutputStream *stream) const; + void PackData(ola::io::OutputStream *stream) const; + + static void PrependPDU(ola::io::IOStack *stack, + uint32_t vector, + const ola::acn::CID &client_cid); + + private: + BrokerClientEntryHeader m_header; + const PDU *m_pdu; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_BROKERCLIENTENTRYPDU_H_ diff --git a/libs/acn/BrokerClientEntryPDUTest.cpp b/libs/acn/BrokerClientEntryPDUTest.cpp new file mode 100644 index 0000000000..bdeedc3175 --- /dev/null +++ b/libs/acn/BrokerClientEntryPDUTest.cpp @@ -0,0 +1,141 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerClientEntryPDUTest.cpp + * Test fixture for the BrokerClientEntryPDU class + * Copyright (C) 2023 Peter Newman + */ + +#include + +#include "ola/Logging.h" +#include "ola/io/IOQueue.h" +#include "ola/io/OutputStream.h" +#include "ola/network/NetworkUtils.h" +#include "ola/testing/TestUtils.h" +#include "libs/acn/BrokerClientEntryPDU.h" +#include "libs/acn/PDUTestCommon.h" + + +namespace ola { +namespace acn { + +using ola::io::IOQueue; +using ola::io::OutputStream; +using ola::network::HostToNetwork; + +class BrokerClientEntryPDUTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(BrokerClientEntryPDUTest); + CPPUNIT_TEST(testSimpleBrokerClientEntryPDU); + CPPUNIT_TEST(testSimpleBrokerClientEntryPDUToOutputStream); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSimpleBrokerClientEntryPDU(); + void testSimpleBrokerClientEntryPDUToOutputStream(); + + void setUp() { + ola::InitLogging(ola::OLA_LOG_DEBUG, ola::OLA_LOG_STDERR); + } + + private: + static const unsigned int TEST_VECTOR; + static const uint8_t TEST_DATA[]; +}; + +const uint8_t BrokerClientEntryPDUTest::TEST_DATA[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15}; + +CPPUNIT_TEST_SUITE_REGISTRATION(BrokerClientEntryPDUTest); + +const unsigned int BrokerClientEntryPDUTest::TEST_VECTOR = 39; + + +/* + * Test that packing a BrokerClientEntryPDU without data works. + */ +void BrokerClientEntryPDUTest::testSimpleBrokerClientEntryPDU() { + const CID client_cid = CID::FromData(TEST_DATA); + BrokerClientEntryHeader header(client_cid); + BrokerClientEntryPDU pdu(TEST_VECTOR, header, NULL); + + OLA_ASSERT_EQ(16u, pdu.HeaderSize()); + OLA_ASSERT_EQ(0u, pdu.DataSize()); + OLA_ASSERT_EQ(23u, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + + // spot check the data + OLA_ASSERT_EQ((uint8_t) 0xf0, data[0]); + // bytes_used is technically data[1] and data[2] if > 255 + OLA_ASSERT_EQ((uint8_t) bytes_used, data[2]); + unsigned int actual_value; + memcpy(&actual_value, data + 3, sizeof(actual_value)); + OLA_ASSERT_EQ(HostToNetwork(TEST_VECTOR), actual_value); + + uint8_t buffer[CID::CID_LENGTH]; + client_cid.Pack(buffer); + OLA_ASSERT_DATA_EQUALS(&data[7], CID::CID_LENGTH, buffer, sizeof(buffer)); + + // test undersized buffer + bytes_used = size - 1; + OLA_ASSERT_FALSE(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(0u, bytes_used); + + // test oversized buffer + bytes_used = size + 1; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + delete[] data; +} + + +/* + * Test that writing to an output stream works. + */ +void BrokerClientEntryPDUTest::testSimpleBrokerClientEntryPDUToOutputStream() { + const ola::acn::CID client_cid = CID::FromData(TEST_DATA); + BrokerClientEntryHeader header(client_cid); + BrokerClientEntryPDU pdu(TEST_VECTOR, header, NULL); + + OLA_ASSERT_EQ(16u, pdu.HeaderSize()); + OLA_ASSERT_EQ(0u, pdu.DataSize()); + OLA_ASSERT_EQ(23u, pdu.Size()); + + IOQueue output; + OutputStream stream(&output); + pdu.Write(&stream); + OLA_ASSERT_EQ(23u, output.Size()); + + uint8_t *pdu_data = new uint8_t[output.Size()]; + unsigned int pdu_size = output.Peek(pdu_data, output.Size()); + OLA_ASSERT_EQ(output.Size(), pdu_size); + + uint8_t EXPECTED[] = { + 0xf0, 0x00, 0x17, + 0, 0, 0, 39, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15 + }; + OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), pdu_data, pdu_size); + output.Pop(output.Size()); + delete[] pdu_data; +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/BrokerPDU.h b/libs/acn/BrokerPDU.h index 788f409b5a..9c6b50322b 100644 --- a/libs/acn/BrokerPDU.h +++ b/libs/acn/BrokerPDU.h @@ -25,7 +25,6 @@ #include #include "libs/acn/PDU.h" -#include "libs/acn/BrokerHeader.h" namespace ola { namespace acn { diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index 82466ec2a3..965052a1d8 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -31,6 +31,9 @@ noinst_LTLIBRARIES += libs/acn/libolae131core.la libs_acn_libolae131core_la_SOURCES = \ libs/acn/BaseInflator.cpp \ libs/acn/BaseInflator.h \ + libs/acn/BrokerClientEntryHeader.h \ + libs/acn/BrokerClientEntryPDU.cpp \ + libs/acn/BrokerClientEntryPDU.h \ libs/acn/BrokerPDU.cpp \ libs/acn/BrokerPDU.h \ libs/acn/DMPAddress.cpp \ @@ -148,6 +151,7 @@ libs_acn_E131Tester_LDADD = \ $(COMMON_TESTING_LIBS) libs_acn_E133Tester_SOURCES = \ + libs/acn/BrokerClientEntryPDUTest.cpp \ libs/acn/BrokerPDUTest.cpp \ libs/acn/E133InflatorTest.cpp \ libs/acn/E133PDUTest.cpp \ From 19eca6fd3ad371c010ca32005b78d12082b34e18 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 7 Mar 2023 23:52:15 +0000 Subject: [PATCH 050/138] First go at BrokerConnectPDU, could do with more tests --- include/ola/acn/ACNVectors.h | 21 ++++ include/ola/rdm/RDMEnums.h | 3 + libs/acn/BrokerConnectPDU.cpp | 123 ++++++++++++++++++ libs/acn/BrokerConnectPDU.h | 84 +++++++++++++ libs/acn/BrokerConnectPDUTest.cpp | 199 ++++++++++++++++++++++++++++++ libs/acn/Makefile.mk | 3 + 6 files changed, 433 insertions(+) create mode 100644 libs/acn/BrokerConnectPDU.cpp create mode 100644 libs/acn/BrokerConnectPDU.h create mode 100644 libs/acn/BrokerConnectPDUTest.cpp diff --git a/include/ola/acn/ACNVectors.h b/include/ola/acn/ACNVectors.h index 72c050ea91..fe75a05a5c 100644 --- a/include/ola/acn/ACNVectors.h +++ b/include/ola/acn/ACNVectors.h @@ -99,6 +99,27 @@ enum LLRPVector { VECTOR_LLRP_RDM_CMD = 3, /**< LLRP RDM Command */ }; +/** + * @brief Vectors used at the E1.33 Broker layer. + */ +enum BrokerVector { + VECTOR_BROKER_CONNECT = 0x0001, /**< Broker Client Connect */ + VECTOR_BROKER_CONNECT_REPLY = 0x0002, /**< Broker Connect Reply */ + VECTOR_BROKER_CLIENT_ENTRY_UPDATE = 0x0003, /**< Broker Client Entry Update */ + VECTOR_BROKER_REDIRECT_V4 = 0x0004, /**< Broker Client Redirect IPv4 */ + VECTOR_BROKER_REDIRECT_V6 = 0x0005, /**< Broker Client Redirect IPv6 */ + VECTOR_BROKER_FETCH_CLIENT_LIST = 0x0006, /**< Broker Fetch Client List */ + VECTOR_BROKER_CONNECTED_CLIENT_LIST = 0x0007, /**< Broker Connected Client List */ + VECTOR_BROKER_CLIENT_ADD = 0x0008, /**< Broker Client Incremental Addition */ + VECTOR_BROKER_CLIENT_REMOVE = 0x0009, /**< Broker Client Incremental Deletion */ + VECTOR_BROKER_CLIENT_ENTRY_CHANGE = 0x000A, /**< Broker Client Entry Change */ + VECTOR_BROKER_REQUEST_DYNAMIC_UIDS = 0x000B, /**< Broker Request Dynamic UID Assignment */ + VECTOR_BROKER_ASSIGNED_DYNAMIC_UIDS = 0x000C, /**< Broker Dynamic UID Assignment List */ + VECTOR_BROKER_FETCH_DYNAMIC_UID_LIST = 0x000D, /**< Broker Fetch Dynamic UID Assignment List */ + VECTOR_BROKER_DISCONNECT = 0x000E, /**< Broker Client Disconnect */ + VECTOR_BROKER_NULL = 0x000F, /**< Broker Client Null */ +}; + /** * @} */ diff --git a/include/ola/rdm/RDMEnums.h b/include/ola/rdm/RDMEnums.h index c57e8f7e97..72bc8aabe0 100644 --- a/include/ola/rdm/RDMEnums.h +++ b/include/ola/rdm/RDMEnums.h @@ -718,6 +718,9 @@ static const uint8_t MAX_RDM_HOSTNAME_LENGTH = 63; static const uint8_t MAX_RDM_DOMAIN_NAME_LENGTH = 231; static const uint8_t DNS_NAME_SERVER_MAX_INDEX = 2; + +// Excluding the mandatory NULL terminator +static const uint8_t MAX_RDM_SCOPE_STRING_LENGTH = 62; } // namespace rdm } // namespace ola #endif // INCLUDE_OLA_RDM_RDMENUMS_H_ diff --git a/libs/acn/BrokerConnectPDU.cpp b/libs/acn/BrokerConnectPDU.cpp new file mode 100644 index 0000000000..753efc0ba0 --- /dev/null +++ b/libs/acn/BrokerConnectPDU.cpp @@ -0,0 +1,123 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerConnectPDU.cpp + * The BrokerConnectPDU + * Copyright (C) 2023 Peter Newman + */ + +#include + +#include "libs/acn/BrokerConnectPDU.h" + +#include +#include + +namespace ola { +namespace acn { + +using ola::io::OutputStream; +using ola::network::HostToNetwork; +using std::min; +using std::string; + +unsigned int BrokerConnectPDU::DataSize() const { + //broker_connect_pdu_data data; + return static_cast(sizeof(broker_connect_pdu_data)); +} + +bool BrokerConnectPDU::PackData(uint8_t *data, unsigned int *length) const { + broker_connect_pdu_data pdu_data; + + size_t client_scope_str_len = min(m_client_scope.size(), sizeof(pdu_data.client_scope)); + strncpy(pdu_data.client_scope, m_client_scope.c_str(), client_scope_str_len); + memset(pdu_data.client_scope + client_scope_str_len, 0, + (sizeof(pdu_data.client_scope) - client_scope_str_len)); + + pdu_data.e133_version = m_e133_version; + + size_t search_domain_str_len = min(m_search_domain.size(), sizeof(pdu_data.search_domain)); + strncpy(pdu_data.search_domain, m_search_domain.c_str(), search_domain_str_len); + memset(pdu_data.search_domain + search_domain_str_len, 0, + (sizeof(pdu_data.search_domain) - search_domain_str_len)); + + uint8_t connection = 0; + if (m_incremental_updates) { + connection |= CONNECTION_INCREMENTAL_UPDATES; + } + pdu_data.connection = HostToNetwork(connection); + *length = static_cast(sizeof(broker_connect_pdu_data)); + + memcpy(data, &pdu_data, *length); + return true; +} + +void BrokerConnectPDU::PackData(ola::io::OutputStream *stream) const { + broker_connect_pdu_data pdu_data; + + size_t client_scope_str_len = min(m_client_scope.size(), sizeof(pdu_data.client_scope)); + strncpy(pdu_data.client_scope, m_client_scope.c_str(), client_scope_str_len); + memset(pdu_data.client_scope + client_scope_str_len, 0, + (sizeof(pdu_data.client_scope) - client_scope_str_len)); + + pdu_data.e133_version = m_e133_version; + + size_t search_domain_str_len = min(m_search_domain.size(), sizeof(pdu_data.search_domain)); + strncpy(pdu_data.search_domain, m_search_domain.c_str(), search_domain_str_len); + memset(pdu_data.search_domain + search_domain_str_len, 0, + (sizeof(pdu_data.search_domain) - search_domain_str_len)); + + uint8_t connection = 0; + if (m_incremental_updates) { + connection |= CONNECTION_INCREMENTAL_UPDATES; + } + pdu_data.connection = HostToNetwork(connection); + + stream->Write(reinterpret_cast(&pdu_data), + static_cast(sizeof(broker_connect_pdu_data))); +} + +void BrokerConnectPDU::PrependPDU(ola::io::IOStack *stack, + const string &client_scope, + uint16_t e133_version, + const string &search_domain, + bool incremental_updates) { + broker_connect_pdu_data pdu_data; + + size_t client_scope_str_len = min(client_scope.size(), sizeof(pdu_data.client_scope)); + strncpy(pdu_data.client_scope, client_scope.c_str(), client_scope_str_len); + memset(pdu_data.client_scope + client_scope_str_len, 0, + (sizeof(pdu_data.client_scope) - client_scope_str_len)); + + pdu_data.e133_version = e133_version; + + size_t search_domain_str_len = min(search_domain.size(), sizeof(pdu_data.search_domain)); + strncpy(pdu_data.search_domain, search_domain.c_str(), search_domain_str_len); + memset(pdu_data.search_domain + search_domain_str_len, 0, + (sizeof(pdu_data.search_domain) - search_domain_str_len)); + + uint8_t connection = 0; + if (incremental_updates) { + connection |= CONNECTION_INCREMENTAL_UPDATES; + } + pdu_data.connection = HostToNetwork(connection); + stack->Write(reinterpret_cast(&pdu_data), + static_cast(sizeof(broker_connect_pdu_data))); + uint16_t vector = HostToNetwork(static_cast(VECTOR_BROKER_CONNECT)); + stack->Write(reinterpret_cast(&vector), sizeof(vector)); + PrependFlagsAndLength(stack, VFLAG_MASK | HFLAG_MASK | DFLAG_MASK, true); +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/BrokerConnectPDU.h b/libs/acn/BrokerConnectPDU.h new file mode 100644 index 0000000000..8850ed00c8 --- /dev/null +++ b/libs/acn/BrokerConnectPDU.h @@ -0,0 +1,84 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerConnectPDU.h + * The BrokerConnectPDU class + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_BROKERCONNECTPDU_H_ +#define LIBS_ACN_BROKERCONNECTPDU_H_ + +#include +#include + +#include "libs/acn/PDU.h" + +namespace ola { +namespace acn { + +class BrokerConnectPDU : public PDU { + public: + explicit BrokerConnectPDU(unsigned int vector, + const std::string &client_scope, + uint16_t e133_version, + const std::string &search_domain, + bool incremental_updates): + PDU(vector, TWO_BYTES, true), + m_client_scope(client_scope), + m_e133_version(e133_version), + m_search_domain(search_domain), + m_incremental_updates(incremental_updates) {} + + unsigned int HeaderSize() const { return 0; } + bool PackHeader(OLA_UNUSED uint8_t *data, + unsigned int *length) const { + *length = 0; + return true; + } + void PackHeader(OLA_UNUSED ola::io::OutputStream *stream) const {} + + unsigned int DataSize() const; + bool PackData(uint8_t *data, unsigned int *length) const; + void PackData(ola::io::OutputStream *stream) const; + + static void PrependPDU(ola::io::IOStack *stack, + const std::string &client_scope, + uint16_t e133_version, + const std::string &search_domain, + bool incremental_updates); + + // bit masks for connection + static const uint8_t CONNECTION_INCREMENTAL_UPDATES = 0x01; + + PACK( + struct broker_connect_pdu_data_s { + // Plus one to allow for the mandatory null + char client_scope[ola::rdm::MAX_RDM_SCOPE_STRING_LENGTH + 1]; + uint16_t e133_version; + char search_domain[ola::rdm::MAX_RDM_DOMAIN_NAME_LENGTH]; + uint8_t connection; + }); + typedef struct broker_connect_pdu_data_s broker_connect_pdu_data; + + private: + const std::string m_client_scope; + uint16_t m_e133_version; + const std::string m_search_domain; + uint8_t m_incremental_updates; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_BROKERCONNECTPDU_H_ diff --git a/libs/acn/BrokerConnectPDUTest.cpp b/libs/acn/BrokerConnectPDUTest.cpp new file mode 100644 index 0000000000..d3add5d2c4 --- /dev/null +++ b/libs/acn/BrokerConnectPDUTest.cpp @@ -0,0 +1,199 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerConnectPDUTest.cpp + * Test fixture for the BrokerConnectPDU class + * Copyright (C) 2023 Peter Newman + */ + +#include +#include +#include + +#include "ola/Logging.h" +#include "ola/io/IOQueue.h" +#include "ola/io/IOStack.h" +#include "ola/io/OutputStream.h" +#include "ola/network/NetworkUtils.h" +#include "ola/testing/TestUtils.h" +#include "libs/acn/PDUTestCommon.h" +#include "libs/acn/BrokerConnectPDU.h" + +namespace ola { +namespace acn { + +using ola::acn::BrokerConnectPDU; +using ola::io::IOQueue; +using ola::io::IOStack; +using ola::io::OutputStream; +using ola::network::HostToNetwork; + +class BrokerConnectPDUTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(BrokerConnectPDUTest); + CPPUNIT_TEST(testSimpleBrokerConnectPDU); + CPPUNIT_TEST(testSimpleBrokerConnectPDUToOutputStream); + CPPUNIT_TEST(testPrepend); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSimpleBrokerConnectPDU(); + void testSimpleBrokerConnectPDUToOutputStream(); + void testPrepend(); + + private: + static const uint16_t TEST_VECTOR; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(BrokerConnectPDUTest); + +const uint16_t BrokerConnectPDUTest::TEST_VECTOR = 39; + + +/* + * Test that packing a BrokerConnectPDU works. + */ +void BrokerConnectPDUTest::testSimpleBrokerConnectPDU() { + BrokerConnectPDU pdu( + TEST_VECTOR, + "default", + 1, + "local.", + true); + + OLA_ASSERT_EQ(0u, pdu.HeaderSize()); + OLA_ASSERT_EQ(297u, pdu.DataSize()); + OLA_ASSERT_EQ(302u, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + + // spot check the data + OLA_ASSERT_EQ((uint8_t) 0xf0, data[0]); + // bytes_used is technically data[1] and data[2] if > 255 + OLA_ASSERT_EQ((uint8_t) bytes_used, data[2]); + uint16_t actual_value; + memcpy(&actual_value, data + 3, sizeof(actual_value)); + OLA_ASSERT_EQ(HostToNetwork(TEST_VECTOR), actual_value); + + // TODO(Peter): Better spot check the data! + + // test undersized buffer + bytes_used = size - 1; + OLA_ASSERT_FALSE(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(0u, bytes_used); + + // test oversized buffer + bytes_used = size + 1; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + delete[] data; +} + +/* + * Test that writing to an output stream works. + */ +void BrokerConnectPDUTest::testSimpleBrokerConnectPDUToOutputStream() { + BrokerConnectPDU pdu( + TEST_VECTOR, + "default", + 1, + "local.", + true); + + OLA_ASSERT_EQ(0u, pdu.HeaderSize()); + OLA_ASSERT_EQ(297u, pdu.DataSize()); + OLA_ASSERT_EQ(302u, pdu.Size()); + + IOQueue output; + OutputStream stream(&output); + pdu.Write(&stream); + OLA_ASSERT_EQ(302u, output.Size()); + + uint8_t *pdu_data = new uint8_t[output.Size()]; + unsigned int pdu_size = output.Peek(pdu_data, output.Size()); + OLA_ASSERT_EQ(output.Size(), pdu_size); + + uint8_t EXPECTED[] = { + 0xf0, 0x01, 0x2e, + 0, 39, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, // default + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x01, 0, + 0x6c, 0x6f, 0x63, 0x61, 0x6C, 0x2e, // local. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1 + }; + OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), pdu_data, pdu_size); + output.Pop(output.Size()); + delete[] pdu_data; +} + + +void BrokerConnectPDUTest::testPrepend() { + IOStack stack; + BrokerConnectPDU::PrependPDU(&stack, + "default", + 1, + "local.", + true); + + unsigned int length = stack.Size(); + uint8_t *buffer = new uint8_t[length]; + OLA_ASSERT(stack.Read(buffer, length)); + + const uint8_t expected_data[] = { + 0xf0, 0x01, 0x2e, + 0, 1, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, // default + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x01, 0, + 0x6c, 0x6f, 0x63, 0x61, 0x6C, 0x2e, // local. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1 + }; + OLA_ASSERT_DATA_EQUALS(expected_data, sizeof(expected_data), buffer, length); + delete[] buffer; +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index 965052a1d8..ad9909be42 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -34,6 +34,8 @@ libs_acn_libolae131core_la_SOURCES = \ libs/acn/BrokerClientEntryHeader.h \ libs/acn/BrokerClientEntryPDU.cpp \ libs/acn/BrokerClientEntryPDU.h \ + libs/acn/BrokerConnectPDU.cpp \ + libs/acn/BrokerConnectPDU.h \ libs/acn/BrokerPDU.cpp \ libs/acn/BrokerPDU.h \ libs/acn/DMPAddress.cpp \ @@ -152,6 +154,7 @@ libs_acn_E131Tester_LDADD = \ libs_acn_E133Tester_SOURCES = \ libs/acn/BrokerClientEntryPDUTest.cpp \ + libs/acn/BrokerConnectPDUTest.cpp \ libs/acn/BrokerPDUTest.cpp \ libs/acn/E133InflatorTest.cpp \ libs/acn/E133PDUTest.cpp \ From d01494b9c3ff3bdec37b072a9029cdb36126cc61 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Wed, 8 Mar 2023 13:29:57 +0000 Subject: [PATCH 051/138] Fix a typo in the DeviceManager stuff --- include/ola/e133/DeviceManager.h | 4 ++-- tools/e133/DeviceManager.cpp | 4 ++-- tools/e133/DeviceManagerImpl.cpp | 4 ++-- tools/e133/DeviceManagerImpl.h | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/ola/e133/DeviceManager.h b/include/ola/e133/DeviceManager.h index 9fada52606..023e8d9f1b 100644 --- a/include/ola/e133/DeviceManager.h +++ b/include/ola/e133/DeviceManager.h @@ -53,7 +53,7 @@ class DeviceManager { * @returns true if the data should be acknowledged, false otherwise. */ typedef ola::Callback3 RDMMesssageCallback; + const string&> RDMMessageCallback; // Run when we acquire designated controller status for a device. typedef ola::Callback1 AcquireDeviceCallback; @@ -66,7 +66,7 @@ class DeviceManager { ~DeviceManager(); // Ownership of the callbacks is transferred. - void SetRDMMessageCallback(RDMMesssageCallback *callback); + void SetRDMMessageCallback(RDMMessageCallback *callback); void SetAcquireDeviceCallback(AcquireDeviceCallback *callback); void SetReleaseDeviceCallback(ReleaseDeviceCallback *callback); diff --git a/tools/e133/DeviceManager.cpp b/tools/e133/DeviceManager.cpp index b91879eddd..3fe1f38874 100644 --- a/tools/e133/DeviceManager.cpp +++ b/tools/e133/DeviceManager.cpp @@ -54,9 +54,9 @@ DeviceManager::~DeviceManager() {} /** * Set the callback to be run when RDMNet data is received from a device. - * @param callback the RDMMesssageCallback to run when data is received. + * @param callback the RDMMessageCallback to run when data is received. */ -void DeviceManager::SetRDMMessageCallback(RDMMesssageCallback *callback) { +void DeviceManager::SetRDMMessageCallback(RDMMessageCallback *callback) { m_impl->SetRDMMessageCallback(callback); } diff --git a/tools/e133/DeviceManagerImpl.cpp b/tools/e133/DeviceManagerImpl.cpp index 86ace1d99c..2e16aa4a94 100644 --- a/tools/e133/DeviceManagerImpl.cpp +++ b/tools/e133/DeviceManagerImpl.cpp @@ -132,9 +132,9 @@ DeviceManagerImpl::~DeviceManagerImpl() { /** * Set the callback to be run when RDMNet data is received from a device. - * @param callback the RDMMesssageCallback to run when data is received. + * @param callback the RDMMessageCallback to run when data is received. */ -void DeviceManagerImpl::SetRDMMessageCallback(RDMMesssageCallback *callback) { +void DeviceManagerImpl::SetRDMMessageCallback(RDMMessageCallback *callback) { m_rdm_callback.reset(callback); } diff --git a/tools/e133/DeviceManagerImpl.h b/tools/e133/DeviceManagerImpl.h index 90bee905ef..5f0c7ad1c4 100644 --- a/tools/e133/DeviceManagerImpl.h +++ b/tools/e133/DeviceManagerImpl.h @@ -70,7 +70,7 @@ class DeviceManagerImpl { * @returns true if the data should be acknowledged, false otherwise. */ typedef ola::Callback3 RDMMesssageCallback; + const string&> RDMMessageCallback; // Run when we acquire designated controller status for a device. typedef ola::Callback1 AcquireDeviceCallback; @@ -83,7 +83,7 @@ class DeviceManagerImpl { ~DeviceManagerImpl(); // Ownership of the callbacks is transferred. - void SetRDMMessageCallback(RDMMesssageCallback *callback); + void SetRDMMessageCallback(RDMMessageCallback *callback); void SetAcquireDeviceCallback(AcquireDeviceCallback *callback); void SetReleaseDeviceCallback(ReleaseDeviceCallback *callback); @@ -98,7 +98,7 @@ class DeviceManagerImpl { DeviceMap; DeviceMap m_device_map; - auto_ptr m_rdm_callback; + auto_ptr m_rdm_callback; auto_ptr m_acquire_device_cb_; auto_ptr m_release_device_cb_; From f49c1f83420634a41309898a7cf327795ec3ed10 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Wed, 8 Mar 2023 16:55:30 +0000 Subject: [PATCH 052/138] Add the BrokerNullPDU and tests --- libs/acn/BrokerNullPDU.cpp | 40 +++++++++ libs/acn/BrokerNullPDU.h | 56 +++++++++++++ libs/acn/BrokerNullPDUTest.cpp | 145 +++++++++++++++++++++++++++++++++ libs/acn/Makefile.mk | 3 + 4 files changed, 244 insertions(+) create mode 100644 libs/acn/BrokerNullPDU.cpp create mode 100644 libs/acn/BrokerNullPDU.h create mode 100644 libs/acn/BrokerNullPDUTest.cpp diff --git a/libs/acn/BrokerNullPDU.cpp b/libs/acn/BrokerNullPDU.cpp new file mode 100644 index 0000000000..5f50bb9a8f --- /dev/null +++ b/libs/acn/BrokerNullPDU.cpp @@ -0,0 +1,40 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerNullPDU.cpp + * The BrokerNullPDU + * Copyright (C) 2023 Peter Newman + */ + +#include "libs/acn/BrokerNullPDU.h" + +#include +#include + +namespace ola { +namespace acn { + +using ola::io::OutputStream; +using ola::network::HostToNetwork; +using std::min; +using std::string; + +void BrokerNullPDU::PrependPDU(ola::io::IOStack *stack) { + uint16_t vector = HostToNetwork(static_cast(VECTOR_BROKER_NULL)); + stack->Write(reinterpret_cast(&vector), sizeof(vector)); + PrependFlagsAndLength(stack, VFLAG_MASK | HFLAG_MASK | DFLAG_MASK, true); +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/BrokerNullPDU.h b/libs/acn/BrokerNullPDU.h new file mode 100644 index 0000000000..88450f7ad0 --- /dev/null +++ b/libs/acn/BrokerNullPDU.h @@ -0,0 +1,56 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerNullPDU.h + * The BrokerNullPDU class + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_BROKERNULLPDU_H_ +#define LIBS_ACN_BROKERNULLPDU_H_ + +#include + +#include "libs/acn/PDU.h" + +namespace ola { +namespace acn { + +class BrokerNullPDU : public PDU { + public: + explicit BrokerNullPDU(unsigned int vector): + PDU(vector, TWO_BYTES, true) {} + + unsigned int HeaderSize() const { return 0; } + bool PackHeader(OLA_UNUSED uint8_t *data, + unsigned int *length) const { + *length = 0; + return true; + } + void PackHeader(OLA_UNUSED ola::io::OutputStream *stream) const {} + + unsigned int DataSize() const { return 0; } + bool PackData(OLA_UNUSED uint8_t *data, + unsigned int *length) const { + *length = 0; + return true; + } + void PackData(OLA_UNUSED ola::io::OutputStream *stream) const {}; + + static void PrependPDU(ola::io::IOStack *stack); +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_BROKERNULLPDU_H_ diff --git a/libs/acn/BrokerNullPDUTest.cpp b/libs/acn/BrokerNullPDUTest.cpp new file mode 100644 index 0000000000..46fa712b50 --- /dev/null +++ b/libs/acn/BrokerNullPDUTest.cpp @@ -0,0 +1,145 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerNullPDUTest.cpp + * Test fixture for the BrokerNullPDU class + * Copyright (C) 2023 Peter Newman + */ + +#include +#include +#include + +#include "ola/Logging.h" +#include "ola/io/IOQueue.h" +#include "ola/io/IOStack.h" +#include "ola/io/OutputStream.h" +#include "ola/network/NetworkUtils.h" +#include "ola/testing/TestUtils.h" +#include "libs/acn/PDUTestCommon.h" +#include "libs/acn/BrokerNullPDU.h" + +namespace ola { +namespace acn { + +using ola::acn::BrokerNullPDU; +using ola::io::IOQueue; +using ola::io::IOStack; +using ola::io::OutputStream; +using ola::network::HostToNetwork; + +class BrokerNullPDUTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(BrokerNullPDUTest); + CPPUNIT_TEST(testSimpleBrokerNullPDU); + CPPUNIT_TEST(testSimpleBrokerNullPDUToOutputStream); + CPPUNIT_TEST(testPrepend); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSimpleBrokerNullPDU(); + void testSimpleBrokerNullPDUToOutputStream(); + void testPrepend(); + + private: + static const uint16_t TEST_VECTOR; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(BrokerNullPDUTest); + +const uint16_t BrokerNullPDUTest::TEST_VECTOR = 39; + + +/* + * Test that packing a BrokerNullPDU works. + */ +void BrokerNullPDUTest::testSimpleBrokerNullPDU() { + BrokerNullPDU pdu(TEST_VECTOR); + + OLA_ASSERT_EQ(0u, pdu.HeaderSize()); + OLA_ASSERT_EQ(0u, pdu.DataSize()); + OLA_ASSERT_EQ(5u, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + + // spot check the data + OLA_ASSERT_EQ((uint8_t) 0xf0, data[0]); + // bytes_used is technically data[1] and data[2] if > 255 + OLA_ASSERT_EQ((uint8_t) bytes_used, data[2]); + uint16_t actual_value; + memcpy(&actual_value, data + 3, sizeof(actual_value)); + OLA_ASSERT_EQ(HostToNetwork(TEST_VECTOR), actual_value); + + // test undersized buffer + bytes_used = size - 1; + OLA_ASSERT_FALSE(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(0u, bytes_used); + + // test oversized buffer + bytes_used = size + 1; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + delete[] data; +} + +/* + * Test that writing to an output stream works. + */ +void BrokerNullPDUTest::testSimpleBrokerNullPDUToOutputStream() { + BrokerNullPDU pdu(TEST_VECTOR); + + OLA_ASSERT_EQ(0u, pdu.HeaderSize()); + OLA_ASSERT_EQ(0u, pdu.DataSize()); + OLA_ASSERT_EQ(5u, pdu.Size()); + + IOQueue output; + OutputStream stream(&output); + pdu.Write(&stream); + OLA_ASSERT_EQ(5u, output.Size()); + + uint8_t *pdu_data = new uint8_t[output.Size()]; + unsigned int pdu_size = output.Peek(pdu_data, output.Size()); + OLA_ASSERT_EQ(output.Size(), pdu_size); + + uint8_t EXPECTED[] = { + 0xf0, 0x00, 0x05, + 0, 39 + }; + OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), pdu_data, pdu_size); + output.Pop(output.Size()); + delete[] pdu_data; +} + + +void BrokerNullPDUTest::testPrepend() { + IOStack stack; + BrokerNullPDU::PrependPDU(&stack); + + unsigned int length = stack.Size(); + uint8_t *buffer = new uint8_t[length]; + OLA_ASSERT(stack.Read(buffer, length)); + + const uint8_t expected_data[] = { + 0xf0, 0x00, 0x05, + 0, 0x0f + }; + OLA_ASSERT_DATA_EQUALS(expected_data, sizeof(expected_data), buffer, length); + delete[] buffer; +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index ad9909be42..4d89196233 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -36,6 +36,8 @@ libs_acn_libolae131core_la_SOURCES = \ libs/acn/BrokerClientEntryPDU.h \ libs/acn/BrokerConnectPDU.cpp \ libs/acn/BrokerConnectPDU.h \ + libs/acn/BrokerNullPDU.cpp \ + libs/acn/BrokerNullPDU.h \ libs/acn/BrokerPDU.cpp \ libs/acn/BrokerPDU.h \ libs/acn/DMPAddress.cpp \ @@ -155,6 +157,7 @@ libs_acn_E131Tester_LDADD = \ libs_acn_E133Tester_SOURCES = \ libs/acn/BrokerClientEntryPDUTest.cpp \ libs/acn/BrokerConnectPDUTest.cpp \ + libs/acn/BrokerNullPDUTest.cpp \ libs/acn/BrokerPDUTest.cpp \ libs/acn/E133InflatorTest.cpp \ libs/acn/E133PDUTest.cpp \ From 5b36363f858bb303ddde228328912b70d607dd87 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 9 Mar 2023 15:52:54 +0000 Subject: [PATCH 053/138] Correct the byte order for the E1.33 version field --- libs/acn/BrokerConnectPDU.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/acn/BrokerConnectPDU.cpp b/libs/acn/BrokerConnectPDU.cpp index 753efc0ba0..8bf3114ace 100644 --- a/libs/acn/BrokerConnectPDU.cpp +++ b/libs/acn/BrokerConnectPDU.cpp @@ -46,7 +46,7 @@ bool BrokerConnectPDU::PackData(uint8_t *data, unsigned int *length) const { memset(pdu_data.client_scope + client_scope_str_len, 0, (sizeof(pdu_data.client_scope) - client_scope_str_len)); - pdu_data.e133_version = m_e133_version; + pdu_data.e133_version = HostToNetwork(m_e133_version); size_t search_domain_str_len = min(m_search_domain.size(), sizeof(pdu_data.search_domain)); strncpy(pdu_data.search_domain, m_search_domain.c_str(), search_domain_str_len); @@ -72,7 +72,7 @@ void BrokerConnectPDU::PackData(ola::io::OutputStream *stream) const { memset(pdu_data.client_scope + client_scope_str_len, 0, (sizeof(pdu_data.client_scope) - client_scope_str_len)); - pdu_data.e133_version = m_e133_version; + pdu_data.e133_version = HostToNetwork(m_e133_version); size_t search_domain_str_len = min(m_search_domain.size(), sizeof(pdu_data.search_domain)); strncpy(pdu_data.search_domain, m_search_domain.c_str(), search_domain_str_len); @@ -101,7 +101,7 @@ void BrokerConnectPDU::PrependPDU(ola::io::IOStack *stack, memset(pdu_data.client_scope + client_scope_str_len, 0, (sizeof(pdu_data.client_scope) - client_scope_str_len)); - pdu_data.e133_version = e133_version; + pdu_data.e133_version = HostToNetwork(e133_version); size_t search_domain_str_len = min(search_domain.size(), sizeof(pdu_data.search_domain)); strncpy(pdu_data.search_domain, search_domain.c_str(), search_domain_str_len); From eb609f384ee363070180f0954801c85b353c4047 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 9 Mar 2023 15:53:29 +0000 Subject: [PATCH 054/138] Correct the size of the BrokerPDU's vector --- libs/acn/BrokerPDU.cpp | 2 +- libs/acn/BrokerPDU.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/acn/BrokerPDU.cpp b/libs/acn/BrokerPDU.cpp index 8dcf9a844e..50364833ce 100644 --- a/libs/acn/BrokerPDU.cpp +++ b/libs/acn/BrokerPDU.cpp @@ -59,7 +59,7 @@ void BrokerPDU::PackData(OutputStream *stream) const { void BrokerPDU::PrependPDU(ola::io::IOStack *stack, - uint32_t vector) { + uint16_t vector) { vector = HostToNetwork(vector); stack->Write(reinterpret_cast(&vector), sizeof(vector)); PrependFlagsAndLength(stack, VFLAG_MASK | HFLAG_MASK | DFLAG_MASK, true); diff --git a/libs/acn/BrokerPDU.h b/libs/acn/BrokerPDU.h index 9c6b50322b..f77bfe6452 100644 --- a/libs/acn/BrokerPDU.h +++ b/libs/acn/BrokerPDU.h @@ -51,7 +51,7 @@ class BrokerPDU: public PDU { void PackData(ola::io::OutputStream *stream) const; static void PrependPDU(ola::io::IOStack *stack, - uint32_t vector); + uint16_t vector); private: const PDU *m_pdu; From e99ec916eb0d6e739f08c29e8f169959091302d6 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 9 Mar 2023 15:59:55 +0000 Subject: [PATCH 055/138] Correct a broker endian check for the E1.33 version in our tests --- libs/acn/BrokerConnectPDUTest.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/acn/BrokerConnectPDUTest.cpp b/libs/acn/BrokerConnectPDUTest.cpp index d3add5d2c4..e9d1052e34 100644 --- a/libs/acn/BrokerConnectPDUTest.cpp +++ b/libs/acn/BrokerConnectPDUTest.cpp @@ -135,8 +135,8 @@ void BrokerConnectPDUTest::testSimpleBrokerConnectPDUToOutputStream() { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0x01, 0, - 0x6c, 0x6f, 0x63, 0x61, 0x6C, 0x2e, // local. + 0, 0x01, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2e, // local. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -176,8 +176,8 @@ void BrokerConnectPDUTest::testPrepend() { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0x01, 0, - 0x6c, 0x6f, 0x63, 0x61, 0x6C, 0x2e, // local. + 0, 0x01, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2e, // local. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, From d40a36a4daa1835cd9a4a3057fc6b18b2e8ed773 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 9 Mar 2023 17:50:46 +0000 Subject: [PATCH 056/138] Add a testPrepend test for the BrokerClientEntryPDU base class --- libs/acn/BrokerClientEntryPDUTest.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/libs/acn/BrokerClientEntryPDUTest.cpp b/libs/acn/BrokerClientEntryPDUTest.cpp index bdeedc3175..e907d03a33 100644 --- a/libs/acn/BrokerClientEntryPDUTest.cpp +++ b/libs/acn/BrokerClientEntryPDUTest.cpp @@ -22,6 +22,7 @@ #include "ola/Logging.h" #include "ola/io/IOQueue.h" +#include "ola/io/IOStack.h" #include "ola/io/OutputStream.h" #include "ola/network/NetworkUtils.h" #include "ola/testing/TestUtils.h" @@ -33,6 +34,7 @@ namespace ola { namespace acn { using ola::io::IOQueue; +using ola::io::IOStack; using ola::io::OutputStream; using ola::network::HostToNetwork; @@ -40,11 +42,13 @@ class BrokerClientEntryPDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(BrokerClientEntryPDUTest); CPPUNIT_TEST(testSimpleBrokerClientEntryPDU); CPPUNIT_TEST(testSimpleBrokerClientEntryPDUToOutputStream); + CPPUNIT_TEST(testPrepend); CPPUNIT_TEST_SUITE_END(); public: void testSimpleBrokerClientEntryPDU(); void testSimpleBrokerClientEntryPDUToOutputStream(); + void testPrepend(); void setUp() { ola::InitLogging(ola::OLA_LOG_DEBUG, ola::OLA_LOG_STDERR); @@ -137,5 +141,27 @@ void BrokerClientEntryPDUTest::testSimpleBrokerClientEntryPDUToOutputStream() { output.Pop(output.Size()); delete[] pdu_data; } + + +void BrokerClientEntryPDUTest::testPrepend() { + const ola::acn::CID client_cid = CID::FromData(TEST_DATA); + IOStack stack; + BrokerClientEntryPDU::PrependPDU(&stack, + TEST_VECTOR, + client_cid); + + unsigned int length = stack.Size(); + uint8_t *buffer = new uint8_t[length]; + OLA_ASSERT(stack.Read(buffer, length)); + + const uint8_t expected_data[] = { + 0xf0, 0x00, 0x17, + 0, 0, 0, 39, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15 + }; + OLA_ASSERT_DATA_EQUALS(expected_data, sizeof(expected_data), buffer, length); + delete[] buffer; +} } // namespace acn } // namespace ola From ad9ac0d49f03b6af87947bfc0ab6ab386102ed91 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Fri, 10 Mar 2023 18:42:43 +0000 Subject: [PATCH 057/138] Allow the timeout interval of the HealthCheckedConnection to be customised --- common/network/HealthCheckedConnection.cpp | 17 +++- .../network/HealthCheckedConnectionTest.cpp | 81 ++++++++++++++++++- include/ola/network/HealthCheckedConnection.h | 13 ++- 3 files changed, 100 insertions(+), 11 deletions(-) diff --git a/common/network/HealthCheckedConnection.cpp b/common/network/HealthCheckedConnection.cpp index 6f5cc741de..b39008a608 100644 --- a/common/network/HealthCheckedConnection.cpp +++ b/common/network/HealthCheckedConnection.cpp @@ -26,14 +26,25 @@ namespace network { HealthCheckedConnection::HealthCheckedConnection( ola::thread::SchedulerInterface *scheduler, + const ola::TimeInterval heartbeat_interval, const ola::TimeInterval timeout_interval) : m_scheduler(scheduler), - m_heartbeat_interval(timeout_interval), + m_heartbeat_interval(heartbeat_interval), + m_timeout_interval(timeout_interval), m_send_timeout_id(ola::thread::INVALID_TIMEOUT), m_receive_timeout_id(ola::thread::INVALID_TIMEOUT) { } +HealthCheckedConnection::HealthCheckedConnection( + ola::thread::SchedulerInterface *scheduler, + const ola::TimeInterval heartbeat_interval) + : HealthCheckedConnection(scheduler, + heartbeat_interval, + ola::TimeInterval(static_cast( + 2.5 * heartbeat_interval.AsInt()))) { +} + HealthCheckedConnection::~HealthCheckedConnection() { if (m_send_timeout_id != ola::thread::INVALID_TIMEOUT) m_scheduler->RemoveTimeout(m_send_timeout_id); @@ -101,10 +112,8 @@ bool HealthCheckedConnection::SendNextHeartbeat() { void HealthCheckedConnection::UpdateReceiveTimer() { - TimeInterval timeout_interval(static_cast( - 2.5 * m_heartbeat_interval.AsInt())); m_receive_timeout_id = m_scheduler->RegisterSingleTimeout( - timeout_interval, + m_timeout_interval, NewSingleCallback( this, &HealthCheckedConnection::InternalHeartbeatTimeout)); } diff --git a/common/network/HealthCheckedConnectionTest.cpp b/common/network/HealthCheckedConnectionTest.cpp index 4a6a09d9de..6f07f9e1d7 100644 --- a/common/network/HealthCheckedConnectionTest.cpp +++ b/common/network/HealthCheckedConnectionTest.cpp @@ -56,10 +56,26 @@ class MockHealthCheckedConnection: public HealthCheckedConnection { MockHealthCheckedConnection(ola::io::ConnectedDescriptor *descriptor, SelectServer *scheduler, + const ola::TimeInterval heartbeat_interval, const ola::TimeInterval timeout_interval, const Options &options, MockClock *clock) - : HealthCheckedConnection(scheduler, timeout_interval), + : HealthCheckedConnection(scheduler, heartbeat_interval, timeout_interval), + m_descriptor(descriptor), + m_ss(scheduler), + m_options(options), + m_next_heartbeat(0), + m_expected_heartbeat(0), + m_channel_ok(true), + m_clock(clock) { + } + + MockHealthCheckedConnection(ola::io::ConnectedDescriptor *descriptor, + SelectServer *scheduler, + const ola::TimeInterval heartbeat_interval, + const Options &options, + MockClock *clock) + : HealthCheckedConnection(scheduler, heartbeat_interval), m_descriptor(descriptor), m_ss(scheduler), m_options(options), @@ -70,8 +86,10 @@ class MockHealthCheckedConnection: public HealthCheckedConnection { } void SendHeartbeat() { + OLA_DEBUG << "Maybe send heartbeat"; if (m_options.send_every == 0 || m_next_heartbeat % m_options.send_every == 0) { + OLA_DEBUG << "Sending heartbeat"; m_descriptor->Send(&m_next_heartbeat, sizeof(m_next_heartbeat)); } m_clock->AdvanceTime(0, 180000); @@ -115,13 +133,18 @@ class HealthCheckedConnectionTest: public CppUnit::TestFixture { HealthCheckedConnectionTest() : CppUnit::TestFixture(), m_ss(NULL, &m_clock), - heartbeat_interval(0, 200000) { + heartbeat_interval(0, 200000), + // Allow a little bit of wiggle room so we don't hit timing issues + // when running the tests + timeout_interval(0, 650000) { } CPPUNIT_TEST_SUITE(HealthCheckedConnectionTest); CPPUNIT_TEST(testSimpleChannel); CPPUNIT_TEST(testChannelWithPacketLoss); CPPUNIT_TEST(testChannelWithHeavyPacketLoss); + CPPUNIT_TEST(testChannelWithHeavyPacketLossLongerTimeout); + CPPUNIT_TEST(testChannelWithVeryHeavyPacketLossLongerTimeout); CPPUNIT_TEST(testPauseAndResume); CPPUNIT_TEST_SUITE_END(); @@ -131,6 +154,8 @@ class HealthCheckedConnectionTest: public CppUnit::TestFixture { void testSimpleChannel(); void testChannelWithPacketLoss(); void testChannelWithHeavyPacketLoss(); + void testChannelWithHeavyPacketLossLongerTimeout(); + void testChannelWithVeryHeavyPacketLossLongerTimeout(); void testPauseAndResume(); void PauseReading(MockHealthCheckedConnection *connection) { @@ -148,6 +173,7 @@ class HealthCheckedConnectionTest: public CppUnit::TestFixture { SelectServer m_ss; LoopbackDescriptor socket; TimeInterval heartbeat_interval; + TimeInterval timeout_interval; MockHealthCheckedConnection::Options options; }; @@ -206,7 +232,7 @@ void HealthCheckedConnectionTest::testChannelWithPacketLoss() { /** - * Check the channel works when every 2nd heartbeat is lost + * Check the channel fails when 2 of every 3 heartbeats are lost */ void HealthCheckedConnectionTest::testChannelWithHeavyPacketLoss() { options.send_every = 3; @@ -228,6 +254,55 @@ void HealthCheckedConnectionTest::testChannelWithHeavyPacketLoss() { } +/** + * Check the channel works when 2 of every 3 heartbeats are lost but the + * timeout interval is 3 * heartbeat_interval rather than the default + */ +void HealthCheckedConnectionTest::testChannelWithHeavyPacketLossLongerTimeout() { + options.send_every = 3; + MockHealthCheckedConnection connection(&socket, + &m_ss, + heartbeat_interval, + timeout_interval, + options, + &m_clock); + + socket.SetOnData( + NewCallback(&connection, &MockHealthCheckedConnection::ReadData)); + connection.Setup(); + m_ss.AddReadDescriptor(&socket); + connection.Setup(); + + m_ss.Run(); + OLA_ASSERT_TRUE(connection.ChannelOk()); +} + + +/** + * Check the channel fails when 3 of every 4 heartbeats are lost even though + * the timeout interval is 3 * heartbeat_interval + */ +void HealthCheckedConnectionTest::testChannelWithVeryHeavyPacketLossLongerTimeout() { + options.send_every = 4; + options.abort_on_failure = false; + MockHealthCheckedConnection connection(&socket, + &m_ss, + heartbeat_interval, + timeout_interval, + options, + &m_clock); + + socket.SetOnData( + NewCallback(&connection, &MockHealthCheckedConnection::ReadData)); + connection.Setup(); + m_ss.AddReadDescriptor(&socket); + connection.Setup(); + + m_ss.Run(); + OLA_ASSERT_FALSE(connection.ChannelOk()); +} + + /** * Check pausing doesn't mark the channel as bad. */ diff --git a/include/ola/network/HealthCheckedConnection.h b/include/ola/network/HealthCheckedConnection.h index a4311f51eb..dc6a64b06d 100644 --- a/include/ola/network/HealthCheckedConnection.h +++ b/include/ola/network/HealthCheckedConnection.h @@ -18,16 +18,17 @@ * * This class adds health checking to a connection, which ensures that the * connection is able to transfer data in a timely manner. The implementation - * is pretty simple: we define a heart beat interval I, which *must* be the + * is pretty simple: we define a heartbeat interval I, which *must* be the * same at both ends of the connection. Every I seconds, both ends send a - * heart beat message and if either end doesn't receive a heart beat in - * 2.5 * I, the connection is deemed dead, and the connection is closed. + * heartbeat message and if either end doesn't receive a heartbeat within the + * timeout interval (which defaults to 2.5 * I if not specified), the + * connection is deemed dead, and the connection is closed. * * This class provides the basic health check mechanism, the sub class is left * to define the format of the heartbeat message. * * To use this health checked channel, subclass HealthCheckedConnection, and - * provide the SendHeartbeat() and HeartbeatTimeout methods. + * provide the SendHeartbeat() and HeartbeatTimeout() methods. * * There are some additional features: * - Some receivers may want to stop reading from a connection under some @@ -57,7 +58,10 @@ namespace network { class HealthCheckedConnection { public: HealthCheckedConnection(ola::thread::SchedulerInterface *scheduler, + const ola::TimeInterval heartbeat_interval, const ola::TimeInterval timeout_interval); + HealthCheckedConnection(ola::thread::SchedulerInterface *scheduler, + const ola::TimeInterval heartbeat_interval); virtual ~HealthCheckedConnection(); /** @@ -106,6 +110,7 @@ class HealthCheckedConnection { private: ola::thread::SchedulerInterface *m_scheduler; ola::TimeInterval m_heartbeat_interval; + ola::TimeInterval m_timeout_interval; ola::thread::timeout_id m_send_timeout_id; ola::thread::timeout_id m_receive_timeout_id; From 9fab74913e2d43936a4ce5aa1bb2415a79667f03 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 3 Jul 2023 17:55:57 +0100 Subject: [PATCH 058/138] Add some more new simple E1.33 inflators Tests still required for these! --- libs/acn/BrokerClientAddInflator.h | 55 ++++++++++++++++++++++ libs/acn/BrokerClientEntryChangeInflator.h | 55 ++++++++++++++++++++++ libs/acn/BrokerClientRemoveInflator.h | 55 ++++++++++++++++++++++ libs/acn/BrokerInflator.h | 55 ++++++++++++++++++++++ libs/acn/BrokerNullInflator.h | 55 ++++++++++++++++++++++ libs/acn/Makefile.mk | 5 ++ 6 files changed, 280 insertions(+) create mode 100644 libs/acn/BrokerClientAddInflator.h create mode 100644 libs/acn/BrokerClientEntryChangeInflator.h create mode 100644 libs/acn/BrokerClientRemoveInflator.h create mode 100644 libs/acn/BrokerInflator.h create mode 100644 libs/acn/BrokerNullInflator.h diff --git a/libs/acn/BrokerClientAddInflator.h b/libs/acn/BrokerClientAddInflator.h new file mode 100644 index 0000000000..14af53fe16 --- /dev/null +++ b/libs/acn/BrokerClientAddInflator.h @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerClientAddInflator.h + * Interface for the BrokerClientAddInflator class. + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_BROKERCLIENTADDINFLATOR_H_ +#define LIBS_ACN_BROKERCLIENTADDINFLATOR_H_ + +#include "ola/acn/ACNVectors.h" +#include "libs/acn/BaseInflator.h" + +namespace ola { +namespace acn { + +class BrokerClientAddInflator: public BaseInflator { + friend class BrokerClientAddInflatorTest; + + public: + BrokerClientAddInflator() + : BaseInflator() { + } + ~BrokerClientAddInflator() {} + + uint32_t Id() const { return ola::acn::VECTOR_BROKER_CLIENT_ADD; } + + protected: + // The 'header' is 0 bytes in length. + bool DecodeHeader(HeaderSet*, + const uint8_t*, + unsigned int, + unsigned int *bytes_used) { + *bytes_used = 0; + return true; + } + + void ResetHeaderField() {} // namespace noop +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_BROKERCLIENTADDINFLATOR_H_ diff --git a/libs/acn/BrokerClientEntryChangeInflator.h b/libs/acn/BrokerClientEntryChangeInflator.h new file mode 100644 index 0000000000..9827a60618 --- /dev/null +++ b/libs/acn/BrokerClientEntryChangeInflator.h @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerClientEntryChangeInflator.h + * Interface for the BrokerClientEntryChangeInflator class. + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_BROKERCLIENTENTRYCHANGEINFLATOR_H_ +#define LIBS_ACN_BROKERCLIENTENTRYCHANGEINFLATOR_H_ + +#include "ola/acn/ACNVectors.h" +#include "libs/acn/BaseInflator.h" + +namespace ola { +namespace acn { + +class BrokerClientEntryChangeInflator: public BaseInflator { + friend class BrokerClientEntryChangeInflatorTest; + + public: + BrokerClientEntryChangeInflator() + : BaseInflator() { + } + ~BrokerClientEntryChangeInflator() {} + + uint32_t Id() const { return ola::acn::VECTOR_BROKER_CLIENT_ENTRY_CHANGE; } + + protected: + // The 'header' is 0 bytes in length. + bool DecodeHeader(HeaderSet*, + const uint8_t*, + unsigned int, + unsigned int *bytes_used) { + *bytes_used = 0; + return true; + } + + void ResetHeaderField() {} // namespace noop +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_BROKERCLIENTENTRYCHANGEINFLATOR_H_ diff --git a/libs/acn/BrokerClientRemoveInflator.h b/libs/acn/BrokerClientRemoveInflator.h new file mode 100644 index 0000000000..4117139350 --- /dev/null +++ b/libs/acn/BrokerClientRemoveInflator.h @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerClientRemoveInflator.h + * Interface for the BrokerClientRemoveInflator class. + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_BROKERCLIENTREMOVEINFLATOR_H_ +#define LIBS_ACN_BROKERCLIENTREMOVEINFLATOR_H_ + +#include "ola/acn/ACNVectors.h" +#include "libs/acn/BaseInflator.h" + +namespace ola { +namespace acn { + +class BrokerClientRemoveInflator: public BaseInflator { + friend class BrokerClientRemoveInflatorTest; + + public: + BrokerClientRemoveInflator() + : BaseInflator() { + } + ~BrokerClientRemoveInflator() {} + + uint32_t Id() const { return ola::acn::VECTOR_BROKER_CLIENT_REMOVE; } + + protected: + // The 'header' is 0 bytes in length. + bool DecodeHeader(HeaderSet*, + const uint8_t*, + unsigned int, + unsigned int *bytes_used) { + *bytes_used = 0; + return true; + } + + void ResetHeaderField() {} // namespace noop +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_BROKERCLIENTREMOVEINFLATOR_H_ diff --git a/libs/acn/BrokerInflator.h b/libs/acn/BrokerInflator.h new file mode 100644 index 0000000000..58da325542 --- /dev/null +++ b/libs/acn/BrokerInflator.h @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerInflator.h + * Interface for the BrokerInflator class. + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_BROKERINFLATOR_H_ +#define LIBS_ACN_BROKERINFLATOR_H_ + +#include "ola/acn/ACNVectors.h" +#include "libs/acn/BaseInflator.h" + +namespace ola { +namespace acn { + +class BrokerInflator: public BaseInflator { + friend class BrokerInflatorTest; + + public: + BrokerInflator() + : BaseInflator(PDU::TWO_BYTES) { + } + ~BrokerInflator() {} + + uint32_t Id() const { return ola::acn::VECTOR_ROOT_BROKER; } + + protected: + // The 'header' is 0 bytes in length. + bool DecodeHeader(HeaderSet*, + const uint8_t*, + unsigned int, + unsigned int *bytes_used) { + *bytes_used = 0; + return true; + } + + void ResetHeaderField() {} // namespace noop +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_BROKERINFLATOR_H_ diff --git a/libs/acn/BrokerNullInflator.h b/libs/acn/BrokerNullInflator.h new file mode 100644 index 0000000000..28a641c722 --- /dev/null +++ b/libs/acn/BrokerNullInflator.h @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerNullInflator.h + * Interface for the BrokerNullInflator class. + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_BROKERNULLINFLATOR_H_ +#define LIBS_ACN_BROKERNULLINFLATOR_H_ + +#include "ola/acn/ACNVectors.h" +#include "libs/acn/BaseInflator.h" + +namespace ola { +namespace acn { + +class BrokerNullInflator: public BaseInflator { + friend class BrokerNullInflatorTest; + + public: + BrokerNullInflator() + : BaseInflator() { + } + ~BrokerNullInflator() {} + + uint32_t Id() const { return ola::acn::VECTOR_BROKER_NULL; } + + protected: + // The 'header' is 0 bytes in length. + bool DecodeHeader(HeaderSet*, + const uint8_t*, + unsigned int, + unsigned int *bytes_used) { + *bytes_used = 0; + return true; + } + + void ResetHeaderField() {} // namespace noop +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_BROKERNULLINFLATOR_H_ diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index 4d89196233..7c02570ed9 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -31,11 +31,16 @@ noinst_LTLIBRARIES += libs/acn/libolae131core.la libs_acn_libolae131core_la_SOURCES = \ libs/acn/BaseInflator.cpp \ libs/acn/BaseInflator.h \ + libs/acn/BrokerClientAddInflator.h \ + libs/acn/BrokerClientEntryChangeInflator.h \ libs/acn/BrokerClientEntryHeader.h \ libs/acn/BrokerClientEntryPDU.cpp \ libs/acn/BrokerClientEntryPDU.h \ + libs/acn/BrokerClientRemoveInflator.h \ libs/acn/BrokerConnectPDU.cpp \ libs/acn/BrokerConnectPDU.h \ + libs/acn/BrokerInflator.h \ + libs/acn/BrokerNullInflator.h \ libs/acn/BrokerNullPDU.cpp \ libs/acn/BrokerNullPDU.h \ libs/acn/BrokerPDU.cpp \ From 6d4d923a37dd575f2991862fb215d0a11b040c6f Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 3 Jul 2023 18:01:06 +0100 Subject: [PATCH 059/138] More E1.33 vectors --- include/ola/acn/ACNVectors.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/ola/acn/ACNVectors.h b/include/ola/acn/ACNVectors.h index fe75a05a5c..3a1d1cb741 100644 --- a/include/ola/acn/ACNVectors.h +++ b/include/ola/acn/ACNVectors.h @@ -120,6 +120,17 @@ enum BrokerVector { VECTOR_BROKER_NULL = 0x000F, /**< Broker Client Null */ }; +// Table A-21, Client Protocol Codes +// These aren't fully named as vectors in the standard, but are used as such so +// we put them in here +/** + * @brief Vectors used at the E1.33 Broker Client Entry layer. + */ +enum ClientProtocolCode { + CLIENT_PROTOCOL_RPT = 0x00000005, /**< Broker RPT Client Entry */ + CLIENT_PROTOCOL_EPT = 0x0000000b, /**< Broker EPT Client Entry */ +}; + /** * @} */ From 81b8e38432d2720210156f0755b0a1979d929ddd Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 3 Jul 2023 18:04:15 +0100 Subject: [PATCH 060/138] Fix a minor typo --- libs/acn/LLRPProbeReplyInflator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/acn/LLRPProbeReplyInflator.cpp b/libs/acn/LLRPProbeReplyInflator.cpp index 153433c166..6da01971cf 100644 --- a/libs/acn/LLRPProbeReplyInflator.cpp +++ b/libs/acn/LLRPProbeReplyInflator.cpp @@ -44,7 +44,7 @@ LLRPProbeReplyInflator::LLRPProbeReplyInflator() /** * Set an LLRPProbeReplyHandler to run when receiving an LLRP Probe Reply * message. - * @param handler the callback to invoke when there is and LLRP Probe Reply. + * @param handler the callback to invoke when there is an LLRP Probe Reply. */ void LLRPProbeReplyInflator::SetLLRPProbeReplyHandler( LLRPProbeReplyHandler *handler) { From b23bc6bcd54dcf152e9a4b269401712318c032ee Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 3 Jul 2023 18:07:06 +0100 Subject: [PATCH 061/138] A few more E1.33 enums --- include/ola/e133/E133Enums.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/ola/e133/E133Enums.h b/include/ola/e133/E133Enums.h index f4c2b4ac06..f8e81767f8 100644 --- a/include/ola/e133/E133Enums.h +++ b/include/ola/e133/E133Enums.h @@ -53,10 +53,21 @@ enum E133StatusCode { SC_E133_BROADCAST_COMPLETE = 0x0009, }; +// Table A-22 E1.33 RPT Client Type Codes +enum E133RPTClientTypeCode { + RPT_CLIENT_TYPE_DEVICE = 0x00, + RPT_CLIENT_TYPE_CONTROLLER = 0x01, +}; + // The max size of an E1.33 Status string. enum { MAX_E133_STATUS_STRING_SIZE = 64 }; + +// The E1.33 version.. +enum { + E133_VERSION = 1 +}; } // namespace e133 } // namespace ola #endif // INCLUDE_OLA_E133_E133ENUMS_H_ From bdb40db292dda2f280db66c738c120d6a7fa5c45 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 3 Jul 2023 18:17:55 +0100 Subject: [PATCH 062/138] Add the ability to build BrokerNullTCP packets --- include/ola/e133/MessageBuilder.h | 4 ++++ tools/e133/MessageBuilder.cpp | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/include/ola/e133/MessageBuilder.h b/include/ola/e133/MessageBuilder.h index 272a56339a..ebff6ffe58 100644 --- a/include/ola/e133/MessageBuilder.h +++ b/include/ola/e133/MessageBuilder.h @@ -48,6 +48,10 @@ class MessageBuilder { void BuildNullTCPPacket(IOStack *packet); + void BuildBrokerFetchClientListTCPPacket(IOStack *packet); + + void BuildBrokerNullTCPPacket(IOStack *packet); + void BuildTCPE133StatusPDU(IOStack *packet, uint32_t sequence_number, uint16_t endpoint_id, ola::e133::E133StatusCode status_code, diff --git a/tools/e133/MessageBuilder.cpp b/tools/e133/MessageBuilder.cpp index a192b45bf0..eed3b85961 100644 --- a/tools/e133/MessageBuilder.cpp +++ b/tools/e133/MessageBuilder.cpp @@ -25,6 +25,7 @@ #include "ola/e133/MessageBuilder.h" #include "ola/io/IOStack.h" +#include "libs/acn/BrokerPDU.h" #include "libs/acn/E133PDU.h" #include "libs/acn/RDMPDU.h" #include "libs/acn/RootPDU.h" @@ -36,6 +37,7 @@ namespace e133 { using ola::acn::CID; using ola::io::IOStack; +using ola::acn::BrokerPDU; using ola::acn::E133PDU; using ola::acn::PreamblePacker; using ola::acn::RootPDU; @@ -67,6 +69,16 @@ void MessageBuilder::BuildNullTCPPacket(IOStack *packet) { } +/** + * Build a Broker NULL TCP packet. These packets can be used for broker heartbeats. + */ +void MessageBuilder::BuildBrokerNullTCPPacket(IOStack *packet) { + BrokerPDU::PrependPDU(packet, ola::acn::VECTOR_BROKER_NULL); + RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_BROKER, m_cid, true); + PreamblePacker::AddTCPPreamble(packet); +} + + /** * Build a TCP E1.33 Status PDU response. This should really only be used with * SC_E133_ACK. From 847734f7527568c8ad380d60f327e96243f8e10b Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 3 Jul 2023 18:19:10 +0100 Subject: [PATCH 063/138] Correctly commit only a partial change for now --- include/ola/e133/MessageBuilder.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/ola/e133/MessageBuilder.h b/include/ola/e133/MessageBuilder.h index ebff6ffe58..a94d52200c 100644 --- a/include/ola/e133/MessageBuilder.h +++ b/include/ola/e133/MessageBuilder.h @@ -48,8 +48,6 @@ class MessageBuilder { void BuildNullTCPPacket(IOStack *packet); - void BuildBrokerFetchClientListTCPPacket(IOStack *packet); - void BuildBrokerNullTCPPacket(IOStack *packet); void BuildTCPE133StatusPDU(IOStack *packet, From 4d7049caf766586177248d1fbba0b31b7185633d Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 3 Jul 2023 18:29:12 +0100 Subject: [PATCH 064/138] Update E133HealthCheckedConnection to work with the new standardised heartbeat behaviour and timing --- tools/e133/E133HealthCheckedConnection.cpp | 8 +++++--- tools/e133/E133HealthCheckedConnection.h | 17 ++++++++++++----- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/tools/e133/E133HealthCheckedConnection.cpp b/tools/e133/E133HealthCheckedConnection.cpp index f03e7e5dc7..c6dd17f663 100644 --- a/tools/e133/E133HealthCheckedConnection.cpp +++ b/tools/e133/E133HealthCheckedConnection.cpp @@ -39,8 +39,9 @@ E133HealthCheckedConnection::E133HealthCheckedConnection( ola::io::NonBlockingSender *message_queue, ola::SingleUseCallback0 *on_timeout, ola::thread::SchedulingExecutorInterface *scheduler, - const ola::TimeInterval heartbeat_interval) - : HealthCheckedConnection(scheduler, heartbeat_interval), + const ola::TimeInterval heartbeat_interval, + const ola::TimeInterval timeout_interval) + : HealthCheckedConnection(scheduler, heartbeat_interval, timeout_interval), m_message_builder(message_builder), m_message_queue(message_queue), m_on_timeout(on_timeout), @@ -52,8 +53,9 @@ E133HealthCheckedConnection::E133HealthCheckedConnection( * Send a E1.33 heartbeat */ void E133HealthCheckedConnection::SendHeartbeat() { + OLA_DEBUG << "Sending heartbeat"; IOStack packet(m_message_builder->pool()); - m_message_builder->BuildNullTCPPacket(&packet); + m_message_builder->BuildBrokerNullTCPPacket(&packet); m_message_queue->SendMessage(&packet); } diff --git a/tools/e133/E133HealthCheckedConnection.h b/tools/e133/E133HealthCheckedConnection.h index 5e7b61453a..3e6712cb30 100644 --- a/tools/e133/E133HealthCheckedConnection.h +++ b/tools/e133/E133HealthCheckedConnection.h @@ -21,9 +21,12 @@ * same health checking logic (and agree on heartbeat intervals) for this to * work correctly. * - * Even though this is called a E1.33 Health Checked Connection, it doesn't - * actually rely on E1.33 at all. You can use it with any ACN based protocol - * since it just sends PDUs with a ROOT_VECTOR_NULL as heartbeat messages. + * This is a E1.33 Health Checked Connection as it sends E1.33 Broker NULL PDUs + * using VECTOR_BROKER_NULL, but it also accepts any ACN root layer PDUs as a + * positive indication the connection is healthy. + * + * You could use it with any ACN based protocol by subclassing it and sending + * heartbeat messages of ROOT_VECTOR_NULL via SendHeartbeat instead. */ #ifndef TOOLS_E133_E133HEALTHCHECKEDCONNECTION_H_ @@ -52,7 +55,9 @@ class E133HealthCheckedConnection ola::SingleUseCallback0 *on_timeout, ola::thread::SchedulingExecutorInterface *scheduler, const ola::TimeInterval heartbeat_interval = - ola::TimeInterval(E133_TCP_HEARTBEAT_INTERVAL, 0)); + ola::TimeInterval(E133_TCP_HEARTBEAT_INTERVAL, 0), + const ola::TimeInterval timeout_interval = + ola::TimeInterval(E133_HEARTBEAT_TIMEOUT, 0)); void SendHeartbeat(); void HeartbeatTimeout(); @@ -64,6 +69,8 @@ class E133HealthCheckedConnection ola::thread::SchedulingExecutorInterface *m_executor; // The default interval in seconds for sending heartbeat messages. - static const unsigned int E133_TCP_HEARTBEAT_INTERVAL = 5; + static const unsigned int E133_TCP_HEARTBEAT_INTERVAL = 15; + // The default interval in seconds before timing out. + static const unsigned int E133_HEARTBEAT_TIMEOUT = 45; }; #endif // TOOLS_E133_E133HEALTHCHECKEDCONNECTION_H_ From a5775352a3d1ff32a042c3d50bdac8257eec6f5d Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 3 Jul 2023 23:10:20 +0100 Subject: [PATCH 065/138] Fix a lint issue --- common/network/HealthCheckedConnectionTest.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/network/HealthCheckedConnectionTest.cpp b/common/network/HealthCheckedConnectionTest.cpp index 6f07f9e1d7..3664d7825e 100644 --- a/common/network/HealthCheckedConnectionTest.cpp +++ b/common/network/HealthCheckedConnectionTest.cpp @@ -60,7 +60,9 @@ class MockHealthCheckedConnection: public HealthCheckedConnection { const ola::TimeInterval timeout_interval, const Options &options, MockClock *clock) - : HealthCheckedConnection(scheduler, heartbeat_interval, timeout_interval), + : HealthCheckedConnection(scheduler, + heartbeat_interval, + timeout_interval), m_descriptor(descriptor), m_ss(scheduler), m_options(options), From 7686be6a02789205cfcab07d88ffddf2941b350b Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 3 Jul 2023 23:20:11 +0100 Subject: [PATCH 066/138] Temporarily remove the the PIDs with IPV6 type in them until we support it properly --- data/rdm/pids.proto | 188 -------------------------------------------- 1 file changed, 188 deletions(-) diff --git a/data/rdm/pids.proto b/data/rdm/pids.proto index 0ca443ce29..cebb8ef20e 100644 --- a/data/rdm/pids.proto +++ b/data/rdm/pids.proto @@ -4010,142 +4010,6 @@ pid { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } -pid { - name: "COMPONENT_SCOPE" - value: 2048 - get_request { - field { - type: UINT16 - name: "scope_slot" - range { - min: 1 - max: 65535 - } - } - } - get_response { - field { - type: UINT16 - name: "scope_slot" - range { - min: 1 - max: 65535 - } - } - field { - type: STRING - name: "scope_string" - max_size: 63 - } - field { - type: UINT8 - name: "static_config_type" - label { - value: 0 - label: "No static config" - } - label { - value: 1 - label: "Static config IPv4" - } - label { - value: 1 - label: "Static config IPv6" - } - range { - min: 0 - max: 2 - } - } - field { - type: IPV4 - name: "static_broker_ipv4_address" - label { - value: 0 - label: "No static broker IPv4 address" - } - } - field { - type: IPV6 - name: "static_broker_ipv6_address" - label { - value: 0 - label: "No static broker IPv6 address" - } - } - field { - type: UINT16 - name: "static_broker_port" - label { - value: 0 - label: "No static broker port" - } - } - } - get_sub_device_range: ROOT_DEVICE - set_request { - field { - type: UINT16 - name: "scope_slot" - range { - min: 1 - max: 65535 - } - } - field { - type: STRING - name: "scope_string" - max_size: 63 - } - field { - type: UINT8 - name: "static_config_type" - label { - value: 0 - label: "No static config" - } - label { - value: 1 - label: "Static config IPv4" - } - label { - value: 1 - label: "Static config IPv6" - } - range { - min: 0 - max: 2 - } - } - field { - type: IPV4 - name: "static_broker_ipv4_address" - label { - value: 0 - label: "No static broker IPv4 address" - } - } - field { - type: IPV6 - name: "static_broker_ipv6_address" - label { - value: 0 - label: "No static broker IPv6 address" - } - } - field { - type: UINT16 - name: "static_broker_port" - label { - value: 0 - label: "No static broker port" - } - } - } - set_response { - } - set_sub_device_range: ROOT_DEVICE -} pid { name: "SEARCH_DOMAIN" value: 2049 @@ -4172,58 +4036,6 @@ pid { } set_sub_device_range: ROOT_DEVICE } -pid { - name: "TCP_COMMS_STATUS" - value: 2050 - get_request { - } - get_response { - field { - type: GROUP - name: "comms_statuses" - field { - type: STRING - name: "scope_string" - max_size: 63 - } - field { - type: IPV4 - name: "broker_ipv4_address" - label { - value: 0 - label: "No IPv4 Connection" - } - } - field { - type: IPV6 - name: "broker_ipv6_address" - label { - value: 0 - label: "No IPv6 Connection" - } - } - field { - type: UINT16 - name: "broker_port" - } - field { - type: UINT16 - name: "unhealthy_tcp_events" - } - } - } - get_sub_device_range: ROOT_DEVICE - set_request { - field { - type: STRING - name: "scope_string" - max_size: 63 - } - } - set_response { - } - set_sub_device_range: ROOT_DEVICE -} pid { name: "BROKER_STATUS" value: 2051 From 1a027aced39d813eb8c0531ff3040ad3d23ab364 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 8 Jul 2023 21:43:54 +0100 Subject: [PATCH 067/138] Add some more enums --- include/ola/acn/ACNVectors.h | 51 +++++++++++++++++++++++++++++++++++- include/ola/e133/E133Enums.h | 33 +++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/include/ola/acn/ACNVectors.h b/include/ola/acn/ACNVectors.h index 3a1d1cb741..8734583e81 100644 --- a/include/ola/acn/ACNVectors.h +++ b/include/ola/acn/ACNVectors.h @@ -120,6 +120,55 @@ enum BrokerVector { VECTOR_BROKER_NULL = 0x000F, /**< Broker Client Null */ }; +// Table A-8, RPT PDU Vector +/** + * @brief Vectors used at the E1.33 RPT layer. + */ +enum RPTVector { + VECTOR_RPT_REQUEST = 1, /**< RPT Request */ + VECTOR_RPT_STATUS = 2, /**< RPT Status */ + VECTOR_RPT_NOTIFICATION = 3, /**< RPT Notification */ +}; + +// Table A-9, RPT Request PDU Vector +/** + * @brief Vectors used at the E1.33 RPT Request layer. + */ +enum RPTRequestVector { + VECTOR_REQUEST_RDM_CMD = 1, /**< RPT Request RDM Command */ +}; + +// Table A-10, RPT Status PDU Vector +/** + * @brief Vectors used at the E1.33 RPT Status layer. + */ +enum RPTStatusVector { + VECTOR_RPT_STATUS_UNKNOWN_RPT_UID = 0x0001, /**< RPT Status Unknown RPT UID */ + VECTOR_RPT_STATUS_RDM_TIMEOUT = 0x0002, /**< RPT Status RDM Timeout */ + VECTOR_RPT_STATUS_RDM_INVALID_RESPONSE = 0x0003, /**< RPT Status RDM Invalid Response */ + VECTOR_RPT_STATUS_UNKNOWN_RDM_UID = 0x0004, /**< RPT Status Unknown RDM UID */ + VECTOR_RPT_STATUS_UNKNOWN_ENDPOINT = 0x0005, /**< RPT Status Unknown Endpoint */ + VECTOR_RPT_STATUS_BROADCAST_COMPLETE = 0x0006, /**< RPT Status Broadcast Complete */ + VECTOR_RPT_STATUS_UNKNOWN_VECTOR = 0x0007, /**< RPT Status Unknown Vector */ + VECTOR_RPT_STATUS_INVALID_MESSAGE = 0x0008, /**< RPT Status Invalid Message */ + VECTOR_RPT_STATUS_INVALID_COMMAND_CLASS = 0x0009, /**< RPT Status Invalid Command Class */ +}; + +// Table A-11, RPT Notification PDU Vector +/** + * @brief Vectors used at the E1.33 RPT Notification layer. + */ +enum RPTNotificationVector { + VECTOR_NOTIFICATION_RDM_CMD = 1, /**< RPT Notification RDM Command */ +}; + +/** + * @brief Vectors used at the E1.33 RDM Command layer. + */ +enum RDMCommandVector { + VECTOR_RDM_CMD_RDM_DATA = 0xCC, /**< E1.33 RDM Command */ +}; + // Table A-21, Client Protocol Codes // These aren't fully named as vectors in the standard, but are used as such so // we put them in here @@ -128,7 +177,7 @@ enum BrokerVector { */ enum ClientProtocolCode { CLIENT_PROTOCOL_RPT = 0x00000005, /**< Broker RPT Client Entry */ - CLIENT_PROTOCOL_EPT = 0x0000000b, /**< Broker EPT Client Entry */ + CLIENT_PROTOCOL_EPT = 0x0000000B, /**< Broker EPT Client Entry */ }; /** diff --git a/include/ola/e133/E133Enums.h b/include/ola/e133/E133Enums.h index f8e81767f8..888ececf35 100644 --- a/include/ola/e133/E133Enums.h +++ b/include/ola/e133/E133Enums.h @@ -39,6 +39,7 @@ enum EndpointMode { ENDPOINT_MODE_OUTPUT = 2, }; +// TODO(Peter): Check that this no longer exists // Table A-9 E1.33 Status Codes enum E133StatusCode { SC_E133_ACK = 0x0000, @@ -53,12 +54,44 @@ enum E133StatusCode { SC_E133_BROADCAST_COMPLETE = 0x0009, }; +// Table A-19 E1.33 Connection Status Codes for Broker Connect +enum E133ConnectStatusCode { + CONNECT_OK = 0x0000, + CONNECT_SCOPE_MISMATCH = 0x0001, + CONNECT_CAPACITY_EXCEEDED = 0x0002, + CONNECT_DUPLICATE_UID = 0x0003, + CONNECT_INVALID_CLIENT_ENTRY = 0x0004, + CONNECT_INVALID_UID = 0x0005, +}; + +// Table A-20 E1.33 Status Codes for Dynamic UID Mapping +enum E133DynamicUIDStatusCode { + DYNAMIC_UID_STATUS_OK = 0x0000, + DYNAMIC_UID_STATUS_INVALID_REQUEST = 0x0001, + DYNAMIC_UID_STATUS_UID_NOT_FOUND = 0x0002, + DYNAMIC_UID_STATUS_DUPLICATE_RID = 0x0003, + DYNAMIC_UID_STATUS_CAPACITY_EXHAUSTED = 0x0004, +}; + // Table A-22 E1.33 RPT Client Type Codes enum E133RPTClientTypeCode { RPT_CLIENT_TYPE_DEVICE = 0x00, RPT_CLIENT_TYPE_CONTROLLER = 0x01, }; +// Table A-24 E1.33 Client Disconnect Reason Codes +enum E133DisconnectStatusCode { + DISCONNECT_SHUTDOWN = 0x0000, + DISCONNECT_CAPACITY_EXHAUSTED = 0x0001, + DISCONNECT_HARDWARE_FAULT = 0x0002, + DISCONNECT_SOFTWARE_FAULT = 0x0003, + DISCONNECT_SOFTWARE_RESET = 0x0004, + DISCONNECT_INCORRECT_SCOPE = 0x0005, + DISCONNECT_RPT_RECONFIGURE = 0x0006, + DISCONNECT_LLRP_RECONFIGURE = 0x0007, + DISCONNECT_USER_RECONFIGURE = 0x0008, +}; + // The max size of an E1.33 Status string. enum { MAX_E133_STATUS_STRING_SIZE = 64 From d1eb7b8ff4f3f8fce4149844d03cbb53a5a42ac7 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 8 Jul 2023 23:07:14 +0100 Subject: [PATCH 068/138] Update the RDM Inflator to the standardised E1.33 --- libs/acn/RDMInflator.cpp | 4 ++-- libs/acn/RDMInflator.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/acn/RDMInflator.cpp b/libs/acn/RDMInflator.cpp index a4e32166e1..9dba40ba45 100644 --- a/libs/acn/RDMInflator.cpp +++ b/libs/acn/RDMInflator.cpp @@ -74,13 +74,13 @@ bool RDMInflator::DecodeHeader(HeaderSet *, /* - * Handle a DMP PDU for E1.33. + * Handle an RDM PDU for E1.33. */ bool RDMInflator::HandlePDUData(uint32_t vector, const HeaderSet &headers, const uint8_t *data, unsigned int pdu_len) { - if (vector != VECTOR_RDMNET_DATA) { + if (vector != VECTOR_RDM_CMD_RDM_DATA) { OLA_INFO << "Not a RDM message, vector was " << vector; return true; } diff --git a/libs/acn/RDMInflator.h b/libs/acn/RDMInflator.h index 4c37cf6c0c..27b43fb7bb 100644 --- a/libs/acn/RDMInflator.h +++ b/libs/acn/RDMInflator.h @@ -46,6 +46,8 @@ class RDMInflator: public BaseInflator { const std::string& // rdm data > GenericRDMMessageHandler; + // TODO(Peter): Set a better default vector for RDM use (possibly the RPT + // one) RDMInflator(unsigned int vector = ola::acn::VECTOR_FRAMING_RDMNET); ~RDMInflator() {} @@ -54,8 +56,6 @@ class RDMInflator: public BaseInflator { void SetRDMHandler(RDMMessageHandler *handler); void SetGenericRDMHandler(GenericRDMMessageHandler *handler); - static const unsigned int VECTOR_RDMNET_DATA = 0xcc; - protected: bool DecodeHeader(HeaderSet *headers, const uint8_t *data, From 669e2e5fd5c15252223a6a22e5e1840d8d40be6d Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 8 Jul 2023 23:11:55 +0100 Subject: [PATCH 069/138] Add support inflator for a lot of E1.33 RPT PDUs --- libs/acn/HeaderSet.h | 8 ++- libs/acn/Makefile.mk | 5 ++ libs/acn/RPTHeader.h | 94 ++++++++++++++++++++++++++++++ libs/acn/RPTInflator.cpp | 73 +++++++++++++++++++++++ libs/acn/RPTInflator.h | 58 ++++++++++++++++++ libs/acn/RPTNotificationInflator.h | 55 +++++++++++++++++ libs/acn/RPTRequestInflator.h | 55 +++++++++++++++++ 7 files changed, 347 insertions(+), 1 deletion(-) create mode 100644 libs/acn/RPTHeader.h create mode 100644 libs/acn/RPTInflator.cpp create mode 100644 libs/acn/RPTInflator.h create mode 100644 libs/acn/RPTNotificationInflator.h create mode 100644 libs/acn/RPTRequestInflator.h diff --git a/libs/acn/HeaderSet.h b/libs/acn/HeaderSet.h index 06a56c26aa..ae4925e1b4 100644 --- a/libs/acn/HeaderSet.h +++ b/libs/acn/HeaderSet.h @@ -28,6 +28,7 @@ #include "libs/acn/E133Header.h" #include "libs/acn/LLRPHeader.h" #include "libs/acn/RootHeader.h" +#include "libs/acn/RPTHeader.h" #include "libs/acn/TransportHeader.h" namespace ola { @@ -60,6 +61,9 @@ class HeaderSet { const LLRPHeader &GetLLRPHeader() const { return m_llrp_header; } void SetLLRPHeader(const LLRPHeader &header) { m_llrp_header = header; } + const RPTHeader &GetRPTHeader() const { return m_rpt_header; } + void SetRPTHeader(const RPTHeader &header) { m_rpt_header = header; } + bool operator==(const HeaderSet &other) const { return ( m_transport_header == other.m_transport_header && @@ -67,7 +71,8 @@ class HeaderSet { m_e131_header == other.m_e131_header && m_e133_header == other.m_e133_header && m_dmp_header == other.m_dmp_header && - m_llrp_header == other.m_llrp_header); + m_llrp_header == other.m_llrp_header && + m_rpt_header == other.m_rpt_header); } private: @@ -77,6 +82,7 @@ class HeaderSet { E133Header m_e133_header; DMPHeader m_dmp_header; LLRPHeader m_llrp_header; + RPTHeader m_rpt_header; }; } // namespace acn } // namespace ola diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index 7c02570ed9..45c84e1619 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -104,6 +104,11 @@ libs_acn_libolae131core_la_SOURCES = \ libs/acn/RootPDU.h \ libs/acn/RootSender.cpp \ libs/acn/RootSender.h \ + libs/acn/RPTHeader.h \ + libs/acn/RPTInflator.cpp \ + libs/acn/RPTInflator.h \ + libs/acn/RPTNotificationInflator.h \ + libs/acn/RPTRequestInflator.h \ libs/acn/TCPTransport.cpp \ libs/acn/TCPTransport.h \ libs/acn/Transport.h \ diff --git a/libs/acn/RPTHeader.h b/libs/acn/RPTHeader.h new file mode 100644 index 0000000000..80bb34cb5f --- /dev/null +++ b/libs/acn/RPTHeader.h @@ -0,0 +1,94 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * RPTHeader.h + * The E1.33 RPT Header + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_RPTHEADER_H_ +#define LIBS_ACN_RPTHEADER_H_ + +#include +#include + +#include +#include + +namespace ola { +namespace acn { + +/* + * Header for the E133 RPT layer + */ +class RPTHeader { + public: + RPTHeader() + : m_source_uid(0, 0), + m_source_endpoint(0), + m_destination_uid(0, 0), + m_destination_endpoint(0), + m_sequence(0) { + } + + RPTHeader(ola::rdm::UID source_uid, + uint16_t source_endpoint, + ola::rdm::UID destination_uid, + uint16_t destination_endpoint, + uint32_t sequence) + : m_source_uid(source_uid), + m_source_endpoint(source_endpoint), + m_destination_uid(destination_uid), + m_destination_endpoint(destination_endpoint), + m_sequence(sequence) { + } + ~RPTHeader() {} + + ola::rdm::UID SourceUID() const { return m_source_uid; } + uint16_t SourceEndpoint() const { return m_source_endpoint; } + ola::rdm::UID DestinationUID() const { return m_destination_uid; } + uint16_t DestinationEndpoint() const { return m_destination_endpoint; } + // TODO(Peter): Should the sequence number really be part of the header? + uint32_t Sequence() const { return m_sequence; } + + bool operator==(const RPTHeader &other) const { + return m_source_uid == other.m_source_uid && + m_source_endpoint == other.m_source_endpoint && + m_destination_uid == other.m_destination_uid && + m_destination_endpoint == other.m_destination_endpoint && + m_sequence == other.m_sequence; + } + + PACK( + struct rpt_pdu_header_s { + uint8_t source_uid[ola::rdm::UID::LENGTH]; + uint16_t source_endpoint; + uint8_t destination_uid[ola::rdm::UID::LENGTH]; + uint16_t destination_endpoint; + uint32_t sequence; + uint8_t reserved; + }); + typedef struct rpt_pdu_header_s rpt_pdu_header; + + private: + ola::rdm::UID m_source_uid; + uint16_t m_source_endpoint; + ola::rdm::UID m_destination_uid; + uint16_t m_destination_endpoint; + uint32_t m_sequence; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_RPTHEADER_H_ diff --git a/libs/acn/RPTInflator.cpp b/libs/acn/RPTInflator.cpp new file mode 100644 index 0000000000..5d9cde6f50 --- /dev/null +++ b/libs/acn/RPTInflator.cpp @@ -0,0 +1,73 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * RPTInflator.cpp + * The Inflator for E1.33 RPT + * Copyright (C) 2023 Peter Newman + */ + +#include "ola/Logging.h" +#include "ola/network/NetworkUtils.h" +#include "libs/acn/RPTInflator.h" + +namespace ola { +namespace acn { + +using ola::network::NetworkToHost; + +/* + * Decode the E1.33 RPT headers. If data is null we're expected to use the + * last header we got. + * @param headers the HeaderSet to add to + * @param data a pointer to the data + * @param length length of the data + * @returns true if successful, false otherwise + */ +bool RPTInflator::DecodeHeader(HeaderSet *headers, + const uint8_t *data, + unsigned int length, + unsigned int *bytes_used) { + if (data) { + // the header bit was set, decode it + if (length >= sizeof(RPTHeader::rpt_pdu_header)) { + RPTHeader::rpt_pdu_header raw_header; + memcpy(&raw_header, data, sizeof(RPTHeader::rpt_pdu_header)); + RPTHeader header( + ola::rdm::UID(raw_header.source_uid), + NetworkToHost(raw_header.source_endpoint), + ola::rdm::UID(raw_header.destination_uid), + NetworkToHost(raw_header.destination_endpoint), + NetworkToHost(raw_header.sequence)); + m_last_header = header; + m_last_header_valid = true; + headers->SetRPTHeader(header); + *bytes_used = sizeof(RPTHeader::rpt_pdu_header); + return true; + } + *bytes_used = 0; + return false; + } + + // use the last header if it exists + *bytes_used = 0; + if (!m_last_header_valid) { + OLA_WARN << "Missing E1.33 RPT Header data"; + return false; + } + headers->SetRPTHeader(m_last_header); + return true; +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/RPTInflator.h b/libs/acn/RPTInflator.h new file mode 100644 index 0000000000..1fd4eedaaf --- /dev/null +++ b/libs/acn/RPTInflator.h @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * RPTInflator.h + * Interface for the RPTInflator class. + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_RPTINFLATOR_H_ +#define LIBS_ACN_RPTINFLATOR_H_ + +#include "ola/acn/ACNVectors.h" +#include "libs/acn/BaseInflator.h" +#include "libs/acn/RPTHeader.h" + +namespace ola { +namespace acn { + +class RPTInflator: public BaseInflator { + friend class RPTInflatorTest; + + public: + RPTInflator() + : BaseInflator(), + m_last_header_valid(false) { + } + ~RPTInflator() {} + + uint32_t Id() const { return ola::acn::VECTOR_ROOT_RPT; } + + protected: + bool DecodeHeader(HeaderSet *headers, + const uint8_t *data, + unsigned int len, + unsigned int *bytes_used); + + void ResetHeaderField() { + m_last_header_valid = false; + } + private: + RPTHeader m_last_header; + bool m_last_header_valid; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_RPTINFLATOR_H_ diff --git a/libs/acn/RPTNotificationInflator.h b/libs/acn/RPTNotificationInflator.h new file mode 100644 index 0000000000..532fb45a54 --- /dev/null +++ b/libs/acn/RPTNotificationInflator.h @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * RPTNotificationInflator.h + * Interface for the RPTNotificationInflator class. + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_RPTNOTIFICATIONINFLATOR_H_ +#define LIBS_ACN_RPTNOTIFICATIONINFLATOR_H_ + +#include "ola/acn/ACNVectors.h" +#include "libs/acn/BaseInflator.h" + +namespace ola { +namespace acn { + +class RPTNotificationInflator: public BaseInflator { + friend class RPTNotificationInflatorTest; + + public: + RPTNotificationInflator() + : BaseInflator() { + } + ~RPTNotificationInflator() {} + + uint32_t Id() const { return ola::acn::VECTOR_RPT_NOTIFICATION; } + + protected: + // The 'header' is 0 bytes in length. + bool DecodeHeader(HeaderSet*, + const uint8_t*, + unsigned int, + unsigned int *bytes_used) { + *bytes_used = 0; + return true; + } + + void ResetHeaderField() {} // namespace noop +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_RPTNOTIFICATIONINFLATOR_H_ diff --git a/libs/acn/RPTRequestInflator.h b/libs/acn/RPTRequestInflator.h new file mode 100644 index 0000000000..ec2cf38de3 --- /dev/null +++ b/libs/acn/RPTRequestInflator.h @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * RPTRequestInflator.h + * Interface for the RPTRequestInflator class. + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_RPTREQUESTINFLATOR_H_ +#define LIBS_ACN_RPTREQUESTINFLATOR_H_ + +#include "ola/acn/ACNVectors.h" +#include "libs/acn/BaseInflator.h" + +namespace ola { +namespace acn { + +class RPTRequestInflator: public BaseInflator { + friend class RPTRequestInflatorTest; + + public: + RPTRequestInflator() + : BaseInflator() { + } + ~RPTRequestInflator() {} + + uint32_t Id() const { return ola::acn::VECTOR_RPT_REQUEST; } + + protected: + // The 'header' is 0 bytes in length. + bool DecodeHeader(HeaderSet*, + const uint8_t*, + unsigned int, + unsigned int *bytes_used) { + *bytes_used = 0; + return true; + } + + void ResetHeaderField() {} // namespace noop +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_RPTREQUESTINFLATOR_H_ From ec58616c7d5631f479c7c82e1e821c4f4145bd02 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 8 Jul 2023 23:38:51 +0100 Subject: [PATCH 070/138] Add tests for the LLRP and RPT headers in the HeaderSet --- libs/acn/HeaderSetTest.cpp | 76 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/libs/acn/HeaderSetTest.cpp b/libs/acn/HeaderSetTest.cpp index 18fa7141f5..26623b0c1f 100644 --- a/libs/acn/HeaderSetTest.cpp +++ b/libs/acn/HeaderSetTest.cpp @@ -25,6 +25,7 @@ #include "ola/acn/CID.h" #include "ola/network/SocketAddress.h" #include "ola/network/NetworkUtils.h" +#include "ola/rdm/UID.h" #include "libs/acn/HeaderSet.h" #include "ola/testing/TestUtils.h" @@ -36,11 +37,14 @@ using ola::acn::E131Rev2Header; using ola::acn::E133Header; using ola::acn::FOUR_BYTES; using ola::acn::HeaderSet; +using ola::acn::LLRPHeader; using ola::acn::NON_RANGE; using ola::acn::ONE_BYTES; using ola::acn::RANGE_EQUAL; using ola::acn::RootHeader; +using ola::acn::RPTHeader; using ola::acn::TransportHeader; +using ola::rdm::UID; class HeaderSetTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(HeaderSetTest); @@ -49,6 +53,8 @@ class HeaderSetTest: public CppUnit::TestFixture { CPPUNIT_TEST(testE131Header); CPPUNIT_TEST(testE133Header); CPPUNIT_TEST(testDMPHeader); + CPPUNIT_TEST(testLLRPHeader); + CPPUNIT_TEST(testRPTHeader); CPPUNIT_TEST(testHeaderSet); CPPUNIT_TEST_SUITE_END(); @@ -58,6 +64,8 @@ class HeaderSetTest: public CppUnit::TestFixture { void testE131Header(); void testE133Header(); void testDMPHeader(); + void testLLRPHeader(); + void testRPTHeader(); void testHeaderSet(); }; @@ -213,6 +221,59 @@ void HeaderSetTest::testDMPHeader() { } +/* + * test the E1.33 LLRP Header + */ +void HeaderSetTest::testLLRPHeader() { + CID cid = CID::Generate(); + + LLRPHeader header(cid, 9840); + OLA_ASSERT(cid == header.DestinationCid()); + OLA_ASSERT_EQ((uint32_t) 9840, header.TransactionNumber()); + + // test copy and assign + LLRPHeader header2 = header; + OLA_ASSERT(header.DestinationCid() == header2.DestinationCid()); + OLA_ASSERT_EQ(header.TransactionNumber(), header2.TransactionNumber()); + + LLRPHeader header3(header); + OLA_ASSERT(header.DestinationCid() == header3.DestinationCid()); + OLA_ASSERT_EQ(header.TransactionNumber(), header3.TransactionNumber()); + OLA_ASSERT(header == header3); +} + + +/* + * test the RPT Header + */ +void HeaderSetTest::testRPTHeader() { + UID src(1, 2); + UID dest(4, 10); + RPTHeader header(src, 3, dest, 5, 9840); + OLA_ASSERT(src == header.SourceUID()); + OLA_ASSERT_EQ((uint16_t) 3, header.SourceEndpoint()); + OLA_ASSERT(dest == header.DestinationUID()); + OLA_ASSERT_EQ((uint16_t) 5, header.DestinationEndpoint()); + OLA_ASSERT_EQ((uint32_t) 9840, header.Sequence()); + + // test copy and assign + RPTHeader header2 = header; + OLA_ASSERT(header.SourceUID() == header2.SourceUID()); + OLA_ASSERT_EQ(header.SourceEndpoint(), header2.SourceEndpoint()); + OLA_ASSERT(header.DestinationUID() == header2.DestinationUID()); + OLA_ASSERT_EQ(header.DestinationEndpoint(), header2.DestinationEndpoint()); + OLA_ASSERT_EQ(header.Sequence(), header2.Sequence()); + + RPTHeader header3(header); + OLA_ASSERT(header.SourceUID() == header3.SourceUID()); + OLA_ASSERT_EQ(header.SourceEndpoint(), header3.SourceEndpoint()); + OLA_ASSERT(header.DestinationUID() == header3.DestinationUID()); + OLA_ASSERT_EQ(header.DestinationEndpoint(), header3.DestinationEndpoint()); + OLA_ASSERT_EQ(header.Sequence(), header3.Sequence()); + OLA_ASSERT(header == header3); +} + + /* * Check that the header set works */ @@ -222,6 +283,9 @@ void HeaderSetTest::testHeaderSet() { E131Header e131_header("e131", 1, 2, 6001); E133Header e133_header("foo", 1, 2050); DMPHeader dmp_header(false, false, NON_RANGE, ONE_BYTES); + CID destination_cid = CID::Generate(); + LLRPHeader llrp_header(destination_cid, 9840); + RPTHeader rpt_header(UID(1, 2), 3, UID(4, 10), 5, 9840); // test the root header component CID cid = CID::Generate(); @@ -241,12 +305,22 @@ void HeaderSetTest::testHeaderSet() { headers.SetDMPHeader(dmp_header); OLA_ASSERT(dmp_header == headers.GetDMPHeader()); + // test the LLRP headers component + headers.SetLLRPHeader(llrp_header); + OLA_ASSERT(llrp_header == headers.GetLLRPHeader()); + + // test the RPT headers component + headers.SetRPTHeader(rpt_header); + OLA_ASSERT(rpt_header == headers.GetRPTHeader()); + // test assign HeaderSet headers2 = headers; OLA_ASSERT(root_header == headers2.GetRootHeader()); OLA_ASSERT(e131_header == headers2.GetE131Header()); OLA_ASSERT(e133_header == headers2.GetE133Header()); OLA_ASSERT(dmp_header == headers2.GetDMPHeader()); + OLA_ASSERT(llrp_header == headers2.GetLLRPHeader()); + OLA_ASSERT(rpt_header == headers2.GetRPTHeader()); OLA_ASSERT(headers2 == headers); // test copy @@ -255,5 +329,7 @@ void HeaderSetTest::testHeaderSet() { OLA_ASSERT(e131_header == headers3.GetE131Header()); OLA_ASSERT(e133_header == headers3.GetE133Header()); OLA_ASSERT(dmp_header == headers3.GetDMPHeader()); + OLA_ASSERT(llrp_header == headers3.GetLLRPHeader()); + OLA_ASSERT(rpt_header == headers3.GetRPTHeader()); OLA_ASSERT(headers3 == headers); } From 7c44c8b9dd58cb99885082f1a15e5e751310b5aa Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Wed, 27 Dec 2023 00:14:27 +0000 Subject: [PATCH 071/138] Add some ConnectStatusCode helpers --- include/ola/e133/E133StatusHelper.h | 5 ++++ tools/e133/E133StatusHelper.cpp | 46 +++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/include/ola/e133/E133StatusHelper.h b/include/ola/e133/E133StatusHelper.h index cd9680b029..7ca19412df 100644 --- a/include/ola/e133/E133StatusHelper.h +++ b/include/ola/e133/E133StatusHelper.h @@ -30,9 +30,14 @@ namespace e133 { using std::string; using ola::e133::E133StatusCode; +using ola::e133::E133ConnectStatusCode; bool IntToStatusCode(uint16_t input, E133StatusCode *status_code); string StatusCodeToString(E133StatusCode status_code); + +bool IntToConnectStatusCode(uint16_t input, + E133ConnectStatusCode *connect_status_code); +string ConnectStatusCodeToString(E133ConnectStatusCode connect_status_code); } // namespace e133 } // namespace ola #endif // INCLUDE_OLA_E133_E133STATUSHELPER_H_ diff --git a/tools/e133/E133StatusHelper.cpp b/tools/e133/E133StatusHelper.cpp index a87376425a..a1ec71627c 100644 --- a/tools/e133/E133StatusHelper.cpp +++ b/tools/e133/E133StatusHelper.cpp @@ -96,5 +96,51 @@ string StatusCodeToString(E133StatusCode status_code) { } return "Unknown E1.33 Status Code"; } + + +bool IntToConnectStatusCode(uint16_t input, + E133ConnectStatusCode *connect_status_code) { + switch (input) { + case ola::e133::CONNECT_OK: + *connect_status_code = ola::e133::CONNECT_OK; + return true; + case ola::e133::CONNECT_SCOPE_MISMATCH: + *connect_status_code = ola::e133::CONNECT_SCOPE_MISMATCH; + return true; + case ola::e133::CONNECT_CAPACITY_EXCEEDED: + *connect_status_code = ola::e133::CONNECT_CAPACITY_EXCEEDED; + return true; + case ola::e133::CONNECT_DUPLICATE_UID: + *connect_status_code = ola::e133::CONNECT_DUPLICATE_UID; + return true; + case ola::e133::CONNECT_INVALID_CLIENT_ENTRY: + *connect_status_code = ola::e133::CONNECT_INVALID_CLIENT_ENTRY; + return true; + case ola::e133::CONNECT_INVALID_UID: + *connect_status_code = ola::e133::CONNECT_INVALID_UID; + return true; + default: + return false; + } +} + + +string ConnectStatusCodeToString(E133ConnectStatusCode connect_status_code) { + switch (connect_status_code) { + case ola::e133::CONNECT_OK: + return "Ok"; + case ola::e133::CONNECT_SCOPE_MISMATCH: + return "Scope mismatch"; + case ola::e133::CONNECT_CAPACITY_EXCEEDED: + return "Capacity exceeded"; + case ola::e133::CONNECT_DUPLICATE_UID: + return "Duplicate UID"; + case ola::e133::CONNECT_INVALID_CLIENT_ENTRY: + return "Invalid client entry"; + case ola::e133::CONNECT_INVALID_UID: + return "Invalid UID"; + } + return "Unknown E1.33 Connect Status Code"; +} } // namespace e133 } // namespace ola From eb97fb49c6059622a6da6f152b28ac44d5925832 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 2 Jan 2024 23:12:52 +0000 Subject: [PATCH 072/138] Add some E1.33 helpers --- include/ola/e133/E133Helper.h | 36 +++++++++++++++++ include/ola/e133/Makefile.mk | 1 + tools/e133/E133Helper.cpp | 73 +++++++++++++++++++++++++++++++++++ tools/e133/Makefile.mk | 1 + 4 files changed, 111 insertions(+) create mode 100644 include/ola/e133/E133Helper.h create mode 100644 tools/e133/E133Helper.cpp diff --git a/include/ola/e133/E133Helper.h b/include/ola/e133/E133Helper.h new file mode 100644 index 0000000000..325f3aa920 --- /dev/null +++ b/include/ola/e133/E133Helper.h @@ -0,0 +1,36 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * E133Helper.h + * Various misc E1.33 functions. + * Copyright (C) 2024 Peter Newman + */ + +#ifndef INCLUDE_OLA_E133_E133HELPER_H_ +#define INCLUDE_OLA_E133_E133HELPER_H_ + +#include +#include +#include + +namespace ola { +namespace e133 { + +bool IntToRPTClientType(uint8_t input, + ola::e133::E133RPTClientTypeCode *client_type); +std::string RPTClientTypeToString(uint8_t type); +} // namespace e133 +} // namespace ola +#endif // INCLUDE_OLA_E133_E133HELPER_H_ diff --git a/include/ola/e133/Makefile.mk b/include/ola/e133/Makefile.mk index d9f7c11c2f..d8f72c9728 100644 --- a/include/ola/e133/Makefile.mk +++ b/include/ola/e133/Makefile.mk @@ -4,6 +4,7 @@ if INSTALL_E133 olae133include_HEADERS = \ include/ola/e133/DeviceManager.h \ include/ola/e133/E133Enums.h \ + include/ola/e133/E133Helper.h \ include/ola/e133/E133Receiver.h \ include/ola/e133/E133StatusHelper.h \ include/ola/e133/E133URLParser.h \ diff --git a/tools/e133/E133Helper.cpp b/tools/e133/E133Helper.cpp new file mode 100644 index 0000000000..1905a16bce --- /dev/null +++ b/tools/e133/E133Helper.cpp @@ -0,0 +1,73 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * E133Helper.cpp + * Various misc E1.33 functions. + * Copyright (C) 2024 Peter Newman + * + * At some point we may want to localize this file. + */ + +#include +#include +#include +#include "ola/e133/E133Enums.h" +#include "ola/e133/E133Helper.h" +#include "ola/StringUtils.h" + +namespace ola { +namespace e133 { + +using std::ostringstream; +using std::string; +using std::vector; + + +/** + * Verify that the int is a valid E1.33 RPT Client Type. + */ +bool IntToRPTClientType(uint8_t input, + ola::e133::E133RPTClientTypeCode *client_type) { + switch (input) { + case ola::e133::RPT_CLIENT_TYPE_DEVICE: + *client_type = ola::e133::RPT_CLIENT_TYPE_DEVICE; + return true; + case ola::e133::RPT_CLIENT_TYPE_CONTROLLER: + *client_type = ola::e133::RPT_CLIENT_TYPE_CONTROLLER; + return true; + default: + return false; + } +} + + +/** + * Convert a uint8_t representing an RPT client type to a human-readable string. + * @param type the RPT client type value + */ +string RPTClientTypeToString(uint8_t type) { + switch (type) { + case RPT_CLIENT_TYPE_DEVICE: + return "Device"; + case RPT_CLIENT_TYPE_CONTROLLER: + return "Controller"; + default: + ostringstream str; + str << "Unknown, was " << static_cast(type); + return str.str(); + } +} +} // namespace e133 +} // namespace ola diff --git a/tools/e133/Makefile.mk b/tools/e133/Makefile.mk index 76f23cdf21..c81e3cf682 100644 --- a/tools/e133/Makefile.mk +++ b/tools/e133/Makefile.mk @@ -24,6 +24,7 @@ endif tools_e133_libolae133common_la_SOURCES = \ tools/e133/E133HealthCheckedConnection.cpp \ tools/e133/E133HealthCheckedConnection.h \ + tools/e133/E133Helper.cpp \ tools/e133/E133Receiver.cpp \ tools/e133/E133StatusHelper.cpp \ tools/e133/MessageBuilder.cpp From 40ff84c7a504bcec7eb472d15fab4b2cbdb713f3 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 24 Feb 2024 21:54:18 +0000 Subject: [PATCH 073/138] Update the RDM PDU to the released standard version --- libs/acn/RDMPDU.cpp | 2 +- libs/acn/RDMPDUTest.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/acn/RDMPDU.cpp b/libs/acn/RDMPDU.cpp index cab7d20a5c..5c47cbb1e0 100644 --- a/libs/acn/RDMPDU.cpp +++ b/libs/acn/RDMPDU.cpp @@ -47,7 +47,7 @@ void RDMPDU::PackData(ola::io::OutputStream *stream) const { void RDMPDU::PrependPDU(ola::io::IOStack *stack) { uint8_t vector = HostToNetwork(ola::rdm::START_CODE); stack->Write(reinterpret_cast(&vector), sizeof(vector)); - PrependFlagsAndLength(stack); + PrependFlagsAndLength(stack, VFLAG_MASK | HFLAG_MASK | DFLAG_MASK, true); } } // namespace acn } // namespace ola diff --git a/libs/acn/RDMPDUTest.cpp b/libs/acn/RDMPDUTest.cpp index ff6489d0fb..f11160f6ba 100644 --- a/libs/acn/RDMPDUTest.cpp +++ b/libs/acn/RDMPDUTest.cpp @@ -161,7 +161,7 @@ void RDMPDUTest::testPrepend() { uint8_t *buffer = new uint8_t[length]; OLA_ASSERT(stack.Read(buffer, length)); - const uint8_t expected_data[] = {0x70, 3, TEST_VECTOR}; + const uint8_t expected_data[] = {0xf0, 0, 4, TEST_VECTOR}; OLA_ASSERT_DATA_EQUALS(expected_data, sizeof(expected_data), buffer, length); delete[] buffer; } From b3942cf1c8dac01026497ef80b920048b7efd21c Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 24 Feb 2024 23:12:08 +0000 Subject: [PATCH 074/138] Add the RPT and RPT Request PDU classes --- libs/acn/Makefile.mk | 9 +- libs/acn/RPTHeader.h | 2 + libs/acn/RPTInflatorTest.cpp | 129 ++++++++++++++++++++++++++++ libs/acn/RPTPDU.cpp | 132 ++++++++++++++++++++++++++++ libs/acn/RPTPDU.h | 65 ++++++++++++++ libs/acn/RPTPDUTest.cpp | 152 +++++++++++++++++++++++++++++++++ libs/acn/RPTRequestPDU.cpp | 39 +++++++++ libs/acn/RPTRequestPDU.h | 56 ++++++++++++ libs/acn/RPTRequestPDUTest.cpp | 145 +++++++++++++++++++++++++++++++ 9 files changed, 728 insertions(+), 1 deletion(-) create mode 100644 libs/acn/RPTInflatorTest.cpp create mode 100644 libs/acn/RPTPDU.cpp create mode 100644 libs/acn/RPTPDU.h create mode 100644 libs/acn/RPTPDUTest.cpp create mode 100644 libs/acn/RPTRequestPDU.cpp create mode 100644 libs/acn/RPTRequestPDU.h create mode 100644 libs/acn/RPTRequestPDUTest.cpp diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index 45c84e1619..d66b402a72 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -108,7 +108,11 @@ libs_acn_libolae131core_la_SOURCES = \ libs/acn/RPTInflator.cpp \ libs/acn/RPTInflator.h \ libs/acn/RPTNotificationInflator.h \ + libs/acn/RPTPDU.cpp \ + libs/acn/RPTPDU.h \ libs/acn/RPTRequestInflator.h \ + libs/acn/RPTRequestPDU.cpp \ + libs/acn/RPTRequestPDU.h \ libs/acn/TCPTransport.cpp \ libs/acn/TCPTransport.h \ libs/acn/Transport.h \ @@ -171,7 +175,10 @@ libs_acn_E133Tester_SOURCES = \ libs/acn/BrokerPDUTest.cpp \ libs/acn/E133InflatorTest.cpp \ libs/acn/E133PDUTest.cpp \ - libs/acn/RDMPDUTest.cpp + libs/acn/RDMPDUTest.cpp \ + libs/acn/RPTInflatorTest.cpp \ + libs/acn/RPTPDUTest.cpp \ + libs/acn/RPTRequestPDUTest.cpp libs_acn_E133Tester_CPPFLAGS = $(COMMON_TESTING_FLAGS) libs_acn_E133Tester_LDADD = \ libs/acn/libolae131core.la \ diff --git a/libs/acn/RPTHeader.h b/libs/acn/RPTHeader.h index 80bb34cb5f..00a26bc349 100644 --- a/libs/acn/RPTHeader.h +++ b/libs/acn/RPTHeader.h @@ -60,6 +60,7 @@ class RPTHeader { uint16_t SourceEndpoint() const { return m_source_endpoint; } ola::rdm::UID DestinationUID() const { return m_destination_uid; } uint16_t DestinationEndpoint() const { return m_destination_endpoint; } + // TODO(Peter): Should this be SequenceNumber? // TODO(Peter): Should the sequence number really be part of the header? uint32_t Sequence() const { return m_sequence; } @@ -73,6 +74,7 @@ class RPTHeader { PACK( struct rpt_pdu_header_s { + rpt_pdu_header_s() : reserved(0) {} uint8_t source_uid[ola::rdm::UID::LENGTH]; uint16_t source_endpoint; uint8_t destination_uid[ola::rdm::UID::LENGTH]; diff --git a/libs/acn/RPTInflatorTest.cpp b/libs/acn/RPTInflatorTest.cpp new file mode 100644 index 0000000000..931c78b062 --- /dev/null +++ b/libs/acn/RPTInflatorTest.cpp @@ -0,0 +1,129 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * RPTInflatorTest.cpp + * Test fixture for the RPTInflator class + * Copyright (C) 2024 Peter Newman + */ + +#include + +#include "ola/Logging.h" +#include "ola/network/NetworkUtils.h" +#include "ola/rdm/UID.h" +#include "libs/acn/HeaderSet.h" +#include "libs/acn/PDUTestCommon.h" +#include "libs/acn/RPTInflator.h" +#include "libs/acn/RPTPDU.h" +#include "ola/testing/TestUtils.h" + + +namespace ola { +namespace acn { + +using ola::network::HostToNetwork; +using ola::rdm::UID; + +class RPTInflatorTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(RPTInflatorTest); + CPPUNIT_TEST(testDecodeHeader); + CPPUNIT_TEST(testInflatePDU); + CPPUNIT_TEST_SUITE_END(); + + public: + void testDecodeHeader(); + void testInflatePDU(); + private: + static const uint8_t TEST_DATA[]; + static const uint8_t TEST_DATA2[]; +}; + +const uint8_t RPTInflatorTest::TEST_DATA[] = {0, 1, 2, 3, 4, 5}; +const uint8_t RPTInflatorTest::TEST_DATA2[] = {10, 11, 12, 13, 14, 15}; +CPPUNIT_TEST_SUITE_REGISTRATION(RPTInflatorTest); + + +/* + * Check that we can decode headers properly + */ +void RPTInflatorTest::testDecodeHeader() { + RPTHeader::rpt_pdu_header header; + memset(&header, 0, sizeof(header)); + RPTInflator inflator; + HeaderSet header_set, header_set2; + unsigned int bytes_used; + const ola::rdm::UID source_uid = UID(TEST_DATA); + const ola::rdm::UID destination_uid = UID(TEST_DATA2); + + source_uid.Pack(header.source_uid, sizeof(header.source_uid)); + header.source_endpoint = HostToNetwork((uint16_t) 1234u); + destination_uid.Pack(header.destination_uid, sizeof(header.destination_uid)); + header.destination_endpoint = HostToNetwork((uint16_t) 5678u); + header.sequence = HostToNetwork(72650u); + + OLA_ASSERT(inflator.DecodeHeader(&header_set, + reinterpret_cast(&header), + sizeof(header), + &bytes_used)); + OLA_ASSERT_EQ((unsigned int) sizeof(header), bytes_used); + RPTHeader decoded_header = header_set.GetRPTHeader(); + + // try an undersized header + OLA_ASSERT_FALSE(inflator.DecodeHeader( + &header_set, + reinterpret_cast(&header), + static_cast(sizeof(header) - 1), + &bytes_used)); + OLA_ASSERT_EQ((unsigned int) 0, bytes_used); + + // test inheriting the header from the prev call + OLA_ASSERT(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); + OLA_ASSERT_EQ((unsigned int) 0, bytes_used); + decoded_header = header_set2.GetRPTHeader(); + OLA_ASSERT(source_uid == decoded_header.SourceUID()); + OLA_ASSERT_EQ((uint16_t) 1234, decoded_header.SourceEndpoint()); + OLA_ASSERT(destination_uid == decoded_header.DestinationUID()); + OLA_ASSERT_EQ((uint16_t) 5678, decoded_header.DestinationEndpoint()); + OLA_ASSERT_EQ((uint32_t) 72650, decoded_header.Sequence()); + + inflator.ResetHeaderField(); + OLA_ASSERT_FALSE(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); + OLA_ASSERT_EQ((unsigned int) 0, bytes_used); +} + + +/* + * Check that we can inflate a RPT PDU that contains other PDUs + */ +void RPTInflatorTest::testInflatePDU() { + RPTHeader header(UID(1, 2), 42, UID(10, 20), 99, 2370); + // TODO(Peter): pass a different type of msg here as well + RPTPDU pdu(3, header, NULL); + OLA_ASSERT_EQ((unsigned int) 28, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ((unsigned int) size, bytes_used); + + RPTInflator inflator; + HeaderSet header_set; + OLA_ASSERT(inflator.InflatePDUBlock(&header_set, data, size)); + OLA_ASSERT(header == header_set.GetRPTHeader()); + delete[] data; +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/RPTPDU.cpp b/libs/acn/RPTPDU.cpp new file mode 100644 index 0000000000..f7eaf0b422 --- /dev/null +++ b/libs/acn/RPTPDU.cpp @@ -0,0 +1,132 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * RPTPDU.cpp + * The E1.33 RPT PDU + * Copyright (C) 2024 Peter Newman + */ + + +#include "ola/Logging.h" +#include "ola/base/Array.h" +#include "ola/network/NetworkUtils.h" +#include "libs/acn/RPTPDU.h" + +namespace ola { +namespace acn { + +using ola::io::OutputStream; +using ola::network::HostToNetwork; + +/* + * Size of the header portion. + */ +unsigned int RPTPDU::HeaderSize() const { + return sizeof(RPTHeader::rpt_pdu_header); +} + + +/* + * Size of the data portion + */ +unsigned int RPTPDU::DataSize() const { + return m_pdu ? m_pdu->Size() : 0; +} + + +/* + * Pack the header portion. + */ +bool RPTPDU::PackHeader(uint8_t *data, unsigned int *length) const { + unsigned int header_size = HeaderSize(); + + if (*length < header_size) { + OLA_WARN << "RPTPDU::PackHeader: buffer too small, got " << *length + << " required " << header_size; + *length = 0; + return false; + } + + RPTHeader::rpt_pdu_header header; + m_header.SourceUID().Pack(header.source_uid, sizeof(header.source_uid)); + header.source_endpoint = HostToNetwork(m_header.SourceEndpoint()); + m_header.DestinationUID().Pack(header.destination_uid, + sizeof(header.destination_uid)); + header.destination_endpoint = HostToNetwork(m_header.DestinationEndpoint()); + header.sequence = HostToNetwork(m_header.Sequence()); + *length = sizeof(RPTHeader::rpt_pdu_header); + memcpy(data, &header, *length); + return true; +} + + +/* + * Pack the data portion. + */ +bool RPTPDU::PackData(uint8_t *data, unsigned int *length) const { + if (m_pdu) + return m_pdu->Pack(data, length); + *length = 0; + return true; +} + + +/* + * Pack the header into a buffer. + */ +void RPTPDU::PackHeader(OutputStream *stream) const { + RPTHeader::rpt_pdu_header header; + m_header.SourceUID().Pack(header.source_uid, sizeof(header.source_uid)); + header.source_endpoint = HostToNetwork(m_header.SourceEndpoint()); + m_header.DestinationUID().Pack(header.destination_uid, + sizeof(header.destination_uid)); + header.destination_endpoint = HostToNetwork(m_header.DestinationEndpoint()); + header.sequence = HostToNetwork(m_header.Sequence()); + stream->Write(reinterpret_cast(&header), + sizeof(RPTHeader::rpt_pdu_header)); +} + + +/* + * Pack the data into a buffer + */ +void RPTPDU::PackData(OutputStream *stream) const { + if (m_pdu) + m_pdu->Write(stream); +} + + +void RPTPDU::PrependPDU(ola::io::IOStack *stack, + uint32_t vector, + const ola::rdm::UID &source_uid, + uint16_t source_endpoint, + const ola::rdm::UID &destination_uid, + uint16_t destination_endpoint, + uint32_t sequence_number) { + RPTHeader::rpt_pdu_header header; + source_uid.Pack(header.source_uid, sizeof(header.source_uid)); + header.source_endpoint = HostToNetwork(source_endpoint); + destination_uid.Pack(header.destination_uid, sizeof(header.destination_uid)); + header.destination_endpoint = HostToNetwork(destination_endpoint); + header.sequence = HostToNetwork(sequence_number); + stack->Write(reinterpret_cast(&header), + sizeof(RPTHeader::rpt_pdu_header)); + + vector = HostToNetwork(vector); + stack->Write(reinterpret_cast(&vector), sizeof(vector)); + PrependFlagsAndLength(stack, VFLAG_MASK | HFLAG_MASK | DFLAG_MASK, true); +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/RPTPDU.h b/libs/acn/RPTPDU.h new file mode 100644 index 0000000000..eb04809915 --- /dev/null +++ b/libs/acn/RPTPDU.h @@ -0,0 +1,65 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * RPTPDU.h + * Interface for the E1.33 RPTPDU class + * Copyright (C) 2024 Peter Newman + */ + +#ifndef LIBS_ACN_RPTPDU_H_ +#define LIBS_ACN_RPTPDU_H_ + +#include +#include + +#include "libs/acn/PDU.h" +#include "libs/acn/RPTHeader.h" + +namespace ola { +namespace acn { + +class RPTPDU: public PDU { + public: + RPTPDU(unsigned int vector, + const RPTHeader &header, + const PDU *pdu): + PDU(vector, FOUR_BYTES, true), + m_header(header), + m_pdu(pdu) {} + ~RPTPDU() {} + + unsigned int HeaderSize() const; + unsigned int DataSize() const; + bool PackHeader(uint8_t *data, unsigned int *length) const; + bool PackData(uint8_t *data, unsigned int *length) const; + + void PackHeader(ola::io::OutputStream *stream) const; + void PackData(ola::io::OutputStream *stream) const; + + static void PrependPDU(ola::io::IOStack *stack, + uint32_t vector, + const ola::rdm::UID &source_uid, + uint16_t source_endpoint, + const ola::rdm::UID &destination_uid, + uint16_t destination_endpoint, + uint32_t sequence_number); + + private: + RPTHeader m_header; + const PDU *m_pdu; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_RPTPDU_H_ diff --git a/libs/acn/RPTPDUTest.cpp b/libs/acn/RPTPDUTest.cpp new file mode 100644 index 0000000000..075b2b52e3 --- /dev/null +++ b/libs/acn/RPTPDUTest.cpp @@ -0,0 +1,152 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * RPTPDUTest.cpp + * Test fixture for the E1.33 RPTPDU class + * Copyright (C) 2024 Peter Newman + */ + +#include + +#include "ola/Logging.h" +#include "ola/io/IOQueue.h" +#include "ola/io/OutputStream.h" +#include "ola/network/NetworkUtils.h" +#include "ola/rdm/UID.h" +#include "ola/testing/TestUtils.h" +#include "libs/acn/RPTPDU.h" +#include "libs/acn/PDUTestCommon.h" + + +namespace ola { +namespace acn { + +using ola::io::IOQueue; +using ola::io::OutputStream; +using ola::network::HostToNetwork; +using ola::rdm::UID; + +class RPTPDUTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(RPTPDUTest); + CPPUNIT_TEST(testSimpleRPTPDU); + CPPUNIT_TEST(testSimpleRPTPDUToOutputStream); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSimpleRPTPDU(); + void testSimpleRPTPDUToOutputStream(); + + void setUp() { + ola::InitLogging(ola::OLA_LOG_DEBUG, ola::OLA_LOG_STDERR); + } + + private: + static const unsigned int TEST_VECTOR; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(RPTPDUTest); + +const unsigned int RPTPDUTest::TEST_VECTOR = 39; + + +/* + * Test that packing a RPTPDU without data works. + */ +void RPTPDUTest::testSimpleRPTPDU() { + UID source_uid(1, 2); + UID destination_uid(10, 20); + RPTHeader header(source_uid, 42, destination_uid, 99, 2370); + RPTPDU pdu(TEST_VECTOR, header, NULL); + + OLA_ASSERT_EQ(21u, pdu.HeaderSize()); + OLA_ASSERT_EQ(0u, pdu.DataSize()); + OLA_ASSERT_EQ(28u, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + + // spot check the data + OLA_ASSERT_EQ((uint8_t) 0xf0, data[0]); + // bytes_used is technically data[1] and data[2] if > 255 + OLA_ASSERT_EQ((uint8_t) bytes_used, data[2]); + unsigned int actual_value; + memcpy(&actual_value, data + 3, sizeof(actual_value)); + OLA_ASSERT_EQ(HostToNetwork(TEST_VECTOR), actual_value); + + uint8_t buffer[UID::LENGTH]; + source_uid.Pack(buffer, sizeof(buffer)); + OLA_ASSERT_DATA_EQUALS(&data[7], UID::LENGTH, buffer, sizeof(buffer)); + destination_uid.Pack(buffer, sizeof(buffer)); + OLA_ASSERT_DATA_EQUALS(&data[15], UID::LENGTH, buffer, sizeof(buffer)); + // sequence number + OLA_ASSERT_EQ((uint8_t) 0, data[23]); + OLA_ASSERT_EQ((uint8_t) 0, data[23 + 1]); + OLA_ASSERT_EQ((unsigned int) 9, (unsigned int) data[23 + 2]); + OLA_ASSERT_EQ((unsigned int) 66, (unsigned int) data[23 + 3]); + + // test undersized buffer + bytes_used = size - 1; + OLA_ASSERT_FALSE(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(0u, bytes_used); + + // test oversized buffer + bytes_used = size + 1; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + delete[] data; +} + + +/* + * Test that writing to an output stream works. + */ +void RPTPDUTest::testSimpleRPTPDUToOutputStream() { + RPTHeader header(UID(0x0102, 0x03040506), 3456, + UID(0x4050, 0x60708090), 7890, + 2370); + RPTPDU pdu(TEST_VECTOR, header, NULL); + + OLA_ASSERT_EQ(21u, pdu.HeaderSize()); + OLA_ASSERT_EQ(0u, pdu.DataSize()); + OLA_ASSERT_EQ(28u, pdu.Size()); + + IOQueue output; + OutputStream stream(&output); + pdu.Write(&stream); + OLA_ASSERT_EQ(28u, output.Size()); + + uint8_t *pdu_data = new uint8_t[output.Size()]; + unsigned int pdu_size = output.Peek(pdu_data, output.Size()); + OLA_ASSERT_EQ(output.Size(), pdu_size); + + uint8_t EXPECTED[] = { + 0xf0, 0x00, 0x1c, + 0, 0, 0, 39, + 1, 2, 3, 4, 5, 6, // source UID + 13, 128, // source endpoint + 64, 80, 96, 112, 128, 144, // dest UID + 30, 210, // dest endpoint + 0, 0, 9, 66, // sequence number + 0 // reserved + }; + OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), pdu_data, pdu_size); + output.Pop(output.Size()); + delete[] pdu_data; +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/RPTRequestPDU.cpp b/libs/acn/RPTRequestPDU.cpp new file mode 100644 index 0000000000..577e382b11 --- /dev/null +++ b/libs/acn/RPTRequestPDU.cpp @@ -0,0 +1,39 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * RPTRequestPDU.cpp + * The RPTRequestPDU + * Copyright (C) 2024 Peter Newman + */ + +#include "libs/acn/RPTRequestPDU.h" + +#include +#include + +namespace ola { +namespace acn { + +using ola::io::OutputStream; +using ola::network::HostToNetwork; + +void RPTRequestPDU::PrependPDU(ola::io::IOStack *stack) { + uint32_t vector = HostToNetwork( + static_cast(VECTOR_REQUEST_RDM_CMD)); + stack->Write(reinterpret_cast(&vector), sizeof(vector)); + PrependFlagsAndLength(stack, VFLAG_MASK | HFLAG_MASK | DFLAG_MASK, true); +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/RPTRequestPDU.h b/libs/acn/RPTRequestPDU.h new file mode 100644 index 0000000000..97a490cd44 --- /dev/null +++ b/libs/acn/RPTRequestPDU.h @@ -0,0 +1,56 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * RPTRequestPDU.h + * The RPTRequestPDU class + * Copyright (C) 2024 Peter Newman + */ + +#ifndef LIBS_ACN_RPTREQUESTPDU_H_ +#define LIBS_ACN_RPTREQUESTPDU_H_ + +#include + +#include "libs/acn/PDU.h" + +namespace ola { +namespace acn { + +class RPTRequestPDU : public PDU { + public: + explicit RPTRequestPDU(unsigned int vector): + PDU(vector, FOUR_BYTES, true) {} + + unsigned int HeaderSize() const { return 0; } + bool PackHeader(OLA_UNUSED uint8_t *data, + unsigned int *length) const { + *length = 0; + return true; + } + void PackHeader(OLA_UNUSED ola::io::OutputStream *stream) const {} + + unsigned int DataSize() const { return 0; } + bool PackData(OLA_UNUSED uint8_t *data, + unsigned int *length) const { + *length = 0; + return true; + } + void PackData(OLA_UNUSED ola::io::OutputStream *stream) const {} + + static void PrependPDU(ola::io::IOStack *stack); +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_RPTREQUESTPDU_H_ diff --git a/libs/acn/RPTRequestPDUTest.cpp b/libs/acn/RPTRequestPDUTest.cpp new file mode 100644 index 0000000000..d04b88712b --- /dev/null +++ b/libs/acn/RPTRequestPDUTest.cpp @@ -0,0 +1,145 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * RPTRequestPDUTest.cpp + * Test fixture for the RPTRequestPDU class + * Copyright (C) 2024 Peter Newman + */ + +#include +#include +#include + +#include "ola/Logging.h" +#include "ola/io/IOQueue.h" +#include "ola/io/IOStack.h" +#include "ola/io/OutputStream.h" +#include "ola/network/NetworkUtils.h" +#include "ola/testing/TestUtils.h" +#include "libs/acn/PDUTestCommon.h" +#include "libs/acn/RPTRequestPDU.h" + +namespace ola { +namespace acn { + +using ola::acn::RPTRequestPDU; +using ola::io::IOQueue; +using ola::io::IOStack; +using ola::io::OutputStream; +using ola::network::HostToNetwork; + +class RPTRequestPDUTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(RPTRequestPDUTest); + CPPUNIT_TEST(testSimpleRPTRequestPDU); + CPPUNIT_TEST(testSimpleRPTRequestPDUToOutputStream); + CPPUNIT_TEST(testPrepend); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSimpleRPTRequestPDU(); + void testSimpleRPTRequestPDUToOutputStream(); + void testPrepend(); + + private: + static const uint32_t TEST_VECTOR; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(RPTRequestPDUTest); + +const uint32_t RPTRequestPDUTest::TEST_VECTOR = 39; + + +/* + * Test that packing a RPTRequestPDU works. + */ +void RPTRequestPDUTest::testSimpleRPTRequestPDU() { + RPTRequestPDU pdu(TEST_VECTOR); + + OLA_ASSERT_EQ(0u, pdu.HeaderSize()); + OLA_ASSERT_EQ(0u, pdu.DataSize()); + OLA_ASSERT_EQ(7u, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + + // spot check the data + OLA_ASSERT_EQ((uint8_t) 0xf0, data[0]); + // bytes_used is technically part of data[0-2] if > 255 + OLA_ASSERT_EQ((uint8_t) bytes_used, data[2]); + uint32_t actual_value; + memcpy(&actual_value, data + 3, sizeof(actual_value)); + OLA_ASSERT_EQ(HostToNetwork(TEST_VECTOR), actual_value); + + // test undersized buffer + bytes_used = size - 1; + OLA_ASSERT_FALSE(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(0u, bytes_used); + + // test oversized buffer + bytes_used = size + 1; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + delete[] data; +} + +/* + * Test that writing to an output stream works. + */ +void RPTRequestPDUTest::testSimpleRPTRequestPDUToOutputStream() { + RPTRequestPDU pdu(TEST_VECTOR); + + OLA_ASSERT_EQ(0u, pdu.HeaderSize()); + OLA_ASSERT_EQ(0u, pdu.DataSize()); + OLA_ASSERT_EQ(7u, pdu.Size()); + + IOQueue output; + OutputStream stream(&output); + pdu.Write(&stream); + OLA_ASSERT_EQ(7u, output.Size()); + + uint8_t *pdu_data = new uint8_t[output.Size()]; + unsigned int pdu_size = output.Peek(pdu_data, output.Size()); + OLA_ASSERT_EQ(output.Size(), pdu_size); + + uint8_t EXPECTED[] = { + 0xf0, 0x00, 0x07, + 0, 0, 0, 39 + }; + OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), pdu_data, pdu_size); + output.Pop(output.Size()); + delete[] pdu_data; +} + + +void RPTRequestPDUTest::testPrepend() { + IOStack stack; + RPTRequestPDU::PrependPDU(&stack); + + unsigned int length = stack.Size(); + uint8_t *buffer = new uint8_t[length]; + OLA_ASSERT(stack.Read(buffer, length)); + + const uint8_t expected_data[] = { + 0xf0, 0x00, 0x07, + 0, 0, 0, 0x01 + }; + OLA_ASSERT_DATA_EQUALS(expected_data, sizeof(expected_data), buffer, length); + delete[] buffer; +} +} // namespace acn +} // namespace ola From 218c4c7cd836cd345d1619c8a2f6b1ea5055b788 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 24 Feb 2024 23:14:06 +0000 Subject: [PATCH 075/138] Tidy the whitespace on RPTPDU.h --- libs/acn/RPTPDU.h | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/libs/acn/RPTPDU.h b/libs/acn/RPTPDU.h index eb04809915..c359855402 100644 --- a/libs/acn/RPTPDU.h +++ b/libs/acn/RPTPDU.h @@ -32,33 +32,33 @@ namespace acn { class RPTPDU: public PDU { public: - RPTPDU(unsigned int vector, - const RPTHeader &header, - const PDU *pdu): - PDU(vector, FOUR_BYTES, true), - m_header(header), - m_pdu(pdu) {} - ~RPTPDU() {} + RPTPDU(unsigned int vector, + const RPTHeader &header, + const PDU *pdu): + PDU(vector, FOUR_BYTES, true), + m_header(header), + m_pdu(pdu) {} + ~RPTPDU() {} - unsigned int HeaderSize() const; - unsigned int DataSize() const; - bool PackHeader(uint8_t *data, unsigned int *length) const; - bool PackData(uint8_t *data, unsigned int *length) const; + unsigned int HeaderSize() const; + unsigned int DataSize() const; + bool PackHeader(uint8_t *data, unsigned int *length) const; + bool PackData(uint8_t *data, unsigned int *length) const; - void PackHeader(ola::io::OutputStream *stream) const; - void PackData(ola::io::OutputStream *stream) const; + void PackHeader(ola::io::OutputStream *stream) const; + void PackData(ola::io::OutputStream *stream) const; - static void PrependPDU(ola::io::IOStack *stack, - uint32_t vector, - const ola::rdm::UID &source_uid, - uint16_t source_endpoint, - const ola::rdm::UID &destination_uid, - uint16_t destination_endpoint, - uint32_t sequence_number); + static void PrependPDU(ola::io::IOStack *stack, + uint32_t vector, + const ola::rdm::UID &source_uid, + uint16_t source_endpoint, + const ola::rdm::UID &destination_uid, + uint16_t destination_endpoint, + uint32_t sequence_number); private: - RPTHeader m_header; - const PDU *m_pdu; + RPTHeader m_header; + const PDU *m_pdu; }; } // namespace acn } // namespace ola From ec6ba371d6546273c4f7d49b23e4e68354101b4d Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Wed, 28 Feb 2024 17:45:02 +0000 Subject: [PATCH 076/138] Remove some unnecessary usings from BrokerNullPDU --- libs/acn/BrokerNullPDU.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libs/acn/BrokerNullPDU.cpp b/libs/acn/BrokerNullPDU.cpp index 5f50bb9a8f..6a4b08741b 100644 --- a/libs/acn/BrokerNullPDU.cpp +++ b/libs/acn/BrokerNullPDU.cpp @@ -26,10 +26,7 @@ namespace ola { namespace acn { -using ola::io::OutputStream; using ola::network::HostToNetwork; -using std::min; -using std::string; void BrokerNullPDU::PrependPDU(ola::io::IOStack *stack) { uint16_t vector = HostToNetwork(static_cast(VECTOR_BROKER_NULL)); From e00322deed9baf2f4e9a015c1790fbf58f0a4cde Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Wed, 28 Feb 2024 17:48:51 +0000 Subject: [PATCH 077/138] Add the BrokerFetchClientListPDU class --- libs/acn/BrokerFetchClientListPDU.cpp | 38 ++++++ libs/acn/BrokerFetchClientListPDU.h | 56 ++++++++ libs/acn/BrokerFetchClientListPDUTest.cpp | 148 ++++++++++++++++++++++ libs/acn/Makefile.mk | 3 + 4 files changed, 245 insertions(+) create mode 100644 libs/acn/BrokerFetchClientListPDU.cpp create mode 100644 libs/acn/BrokerFetchClientListPDU.h create mode 100644 libs/acn/BrokerFetchClientListPDUTest.cpp diff --git a/libs/acn/BrokerFetchClientListPDU.cpp b/libs/acn/BrokerFetchClientListPDU.cpp new file mode 100644 index 0000000000..99e7f866e3 --- /dev/null +++ b/libs/acn/BrokerFetchClientListPDU.cpp @@ -0,0 +1,38 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerFetchClientListPDU.cpp + * The BrokerFetchClientListPDU + * Copyright (C) 2023 Peter Newman + */ + +#include "libs/acn/BrokerFetchClientListPDU.h" + +#include +#include + +namespace ola { +namespace acn { + +using ola::network::HostToNetwork; + +void BrokerFetchClientListPDU::PrependPDU(ola::io::IOStack *stack) { + uint16_t vector = HostToNetwork(static_cast( + VECTOR_BROKER_FETCH_CLIENT_LIST)); + stack->Write(reinterpret_cast(&vector), sizeof(vector)); + PrependFlagsAndLength(stack, VFLAG_MASK | HFLAG_MASK | DFLAG_MASK, true); +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/BrokerFetchClientListPDU.h b/libs/acn/BrokerFetchClientListPDU.h new file mode 100644 index 0000000000..df4a40e4f0 --- /dev/null +++ b/libs/acn/BrokerFetchClientListPDU.h @@ -0,0 +1,56 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerFetchClientListPDU.h + * The BrokerFetchClientListPDU class + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_BROKERFETCHCLIENTLISTPDU_H_ +#define LIBS_ACN_BROKERFETCHCLIENTLISTPDU_H_ + +#include + +#include "libs/acn/PDU.h" + +namespace ola { +namespace acn { + +class BrokerFetchClientListPDU : public PDU { + public: + explicit BrokerFetchClientListPDU(unsigned int vector): + PDU(vector, TWO_BYTES, true) {} + + unsigned int HeaderSize() const { return 0; } + bool PackHeader(OLA_UNUSED uint8_t *data, + unsigned int *length) const { + *length = 0; + return true; + } + void PackHeader(OLA_UNUSED ola::io::OutputStream *stream) const {} + + unsigned int DataSize() const { return 0; } + bool PackData(OLA_UNUSED uint8_t *data, + unsigned int *length) const { + *length = 0; + return true; + } + void PackData(OLA_UNUSED ola::io::OutputStream *stream) const {} + + static void PrependPDU(ola::io::IOStack *stack); +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_BROKERFETCHCLIENTLISTPDU_H_ diff --git a/libs/acn/BrokerFetchClientListPDUTest.cpp b/libs/acn/BrokerFetchClientListPDUTest.cpp new file mode 100644 index 0000000000..00a5ad09cf --- /dev/null +++ b/libs/acn/BrokerFetchClientListPDUTest.cpp @@ -0,0 +1,148 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerFetchClientListPDUTest.cpp + * Test fixture for the BrokerFetchClientListPDU class + * Copyright (C) 2023 Peter Newman + */ + +#include + +#include "ola/Logging.h" +#include "ola/io/IOQueue.h" +#include "ola/io/IOStack.h" +#include "ola/io/OutputStream.h" +#include "ola/network/NetworkUtils.h" +#include "ola/testing/TestUtils.h" +#include "libs/acn/PDUTestCommon.h" +#include "libs/acn/BrokerFetchClientListPDU.h" + +namespace ola { +namespace acn { + +using ola::acn::BrokerFetchClientListPDU; +using ola::io::IOQueue; +using ola::io::IOStack; +using ola::io::OutputStream; +using ola::network::HostToNetwork; + +class BrokerFetchClientListPDUTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(BrokerFetchClientListPDUTest); + CPPUNIT_TEST(testSimpleBrokerFetchClientListPDU); + CPPUNIT_TEST(testSimpleBrokerFetchClientListPDUToOutputStream); + CPPUNIT_TEST(testPrepend); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSimpleBrokerFetchClientListPDU(); + void testSimpleBrokerFetchClientListPDUToOutputStream(); + void testPrepend(); + + void setUp() { + ola::InitLogging(ola::OLA_LOG_DEBUG, ola::OLA_LOG_STDERR); + } + + private: + static const uint16_t TEST_VECTOR; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(BrokerFetchClientListPDUTest); + +const uint16_t BrokerFetchClientListPDUTest::TEST_VECTOR = 39; + + +/* + * Test that packing a BrokerFetchClientListPDU works. + */ +void BrokerFetchClientListPDUTest::testSimpleBrokerFetchClientListPDU() { + BrokerFetchClientListPDU pdu(TEST_VECTOR); + + OLA_ASSERT_EQ(0u, pdu.HeaderSize()); + OLA_ASSERT_EQ(0u, pdu.DataSize()); + OLA_ASSERT_EQ(5u, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + + // spot check the data + OLA_ASSERT_EQ((uint8_t) 0xf0, data[0]); + // bytes_used is technically data[1] and data[2] if > 255 + OLA_ASSERT_EQ((uint8_t) bytes_used, data[2]); + uint16_t actual_value; + memcpy(&actual_value, data + 3, sizeof(actual_value)); + OLA_ASSERT_EQ(HostToNetwork(TEST_VECTOR), actual_value); + + // test undersized buffer + bytes_used = size - 1; + OLA_ASSERT_FALSE(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(0u, bytes_used); + + // test oversized buffer + bytes_used = size + 1; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + delete[] data; +} + +/* + * Test that writing to an output stream works. + */ +void BrokerFetchClientListPDUTest:: + testSimpleBrokerFetchClientListPDUToOutputStream() { + BrokerFetchClientListPDU pdu(TEST_VECTOR); + + OLA_ASSERT_EQ(0u, pdu.HeaderSize()); + OLA_ASSERT_EQ(0u, pdu.DataSize()); + OLA_ASSERT_EQ(5u, pdu.Size()); + + IOQueue output; + OutputStream stream(&output); + pdu.Write(&stream); + OLA_ASSERT_EQ(5u, output.Size()); + + uint8_t *pdu_data = new uint8_t[output.Size()]; + unsigned int pdu_size = output.Peek(pdu_data, output.Size()); + OLA_ASSERT_EQ(output.Size(), pdu_size); + + uint8_t EXPECTED[] = { + 0xf0, 0x00, 0x05, + 0, 39 + }; + OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), pdu_data, pdu_size); + output.Pop(output.Size()); + delete[] pdu_data; +} + + +void BrokerFetchClientListPDUTest::testPrepend() { + IOStack stack; + BrokerFetchClientListPDU::PrependPDU(&stack); + + unsigned int length = stack.Size(); + uint8_t *buffer = new uint8_t[length]; + OLA_ASSERT(stack.Read(buffer, length)); + + const uint8_t expected_data[] = { + 0xf0, 0x00, 0x05, + 0, 0x06 + }; + OLA_ASSERT_DATA_EQUALS(expected_data, sizeof(expected_data), buffer, length); + delete[] buffer; +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index d66b402a72..37c8d999f8 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -39,6 +39,8 @@ libs_acn_libolae131core_la_SOURCES = \ libs/acn/BrokerClientRemoveInflator.h \ libs/acn/BrokerConnectPDU.cpp \ libs/acn/BrokerConnectPDU.h \ + libs/acn/BrokerFetchClientListPDU.cpp \ + libs/acn/BrokerFetchClientListPDU.h \ libs/acn/BrokerInflator.h \ libs/acn/BrokerNullInflator.h \ libs/acn/BrokerNullPDU.cpp \ @@ -171,6 +173,7 @@ libs_acn_E131Tester_LDADD = \ libs_acn_E133Tester_SOURCES = \ libs/acn/BrokerClientEntryPDUTest.cpp \ libs/acn/BrokerConnectPDUTest.cpp \ + libs/acn/BrokerFetchClientListPDUTest.cpp \ libs/acn/BrokerNullPDUTest.cpp \ libs/acn/BrokerPDUTest.cpp \ libs/acn/E133InflatorTest.cpp \ From 16455b1db66c9d157aade362a7142b0c0558bcfc Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Wed, 28 Feb 2024 17:50:53 +0000 Subject: [PATCH 078/138] Add message builders for RDMCommand and BrokerFetchClientList packets --- include/ola/e133/MessageBuilder.h | 9 ++++++++ tools/e133/MessageBuilder.cpp | 34 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/include/ola/e133/MessageBuilder.h b/include/ola/e133/MessageBuilder.h index a94d52200c..ace419b40f 100644 --- a/include/ola/e133/MessageBuilder.h +++ b/include/ola/e133/MessageBuilder.h @@ -27,6 +27,7 @@ #include #include #include +#include #include namespace ola { @@ -46,8 +47,16 @@ class MessageBuilder { void PrependRDMHeader(IOStack *packet); + void BuildTCPRDMCommandPDU(IOStack *packet, + ola::rdm::RDMRequest *request, + uint16_t source_endpoint_id, + uint16_t destination_endpoint_id, + uint32_t sequence_number); + void BuildNullTCPPacket(IOStack *packet); + void BuildBrokerFetchClientListTCPPacket(IOStack *packet); + void BuildBrokerNullTCPPacket(IOStack *packet); void BuildTCPE133StatusPDU(IOStack *packet, diff --git a/tools/e133/MessageBuilder.cpp b/tools/e133/MessageBuilder.cpp index eed3b85961..41d352539b 100644 --- a/tools/e133/MessageBuilder.cpp +++ b/tools/e133/MessageBuilder.cpp @@ -24,11 +24,14 @@ #include "ola/acn/CID.h" #include "ola/e133/MessageBuilder.h" #include "ola/io/IOStack.h" +#include "ola/rdm/RDMCommandSerializer.h" #include "libs/acn/BrokerPDU.h" #include "libs/acn/E133PDU.h" #include "libs/acn/RDMPDU.h" #include "libs/acn/RootPDU.h" +#include "libs/acn/RPTPDU.h" +#include "libs/acn/RPTRequestPDU.h" #include "libs/acn/E133StatusPDU.h" #include "libs/acn/PreamblePacker.h" @@ -41,6 +44,7 @@ using ola::acn::BrokerPDU; using ola::acn::E133PDU; using ola::acn::PreamblePacker; using ola::acn::RootPDU; +using ola::acn::RPTPDU; MessageBuilder::MessageBuilder(const CID &cid, const string &source_name) @@ -60,6 +64,26 @@ void MessageBuilder::PrependRDMHeader(IOStack *packet) { } +/** + * Build a TCP E1.33 RDM Command PDU response. + */ +void MessageBuilder::BuildTCPRDMCommandPDU(IOStack *packet, + ola::rdm::RDMRequest *request, + uint16_t source_endpoint_id, + uint16_t destination_endpoint_id, + uint32_t sequence_number) { + ola::rdm::RDMCommandSerializer::Write(*request, packet); + ola::acn::RDMPDU::PrependPDU(packet); + ola::acn::RPTRequestPDU::PrependPDU(packet); + RPTPDU::PrependPDU(packet, ola::acn::VECTOR_RPT_REQUEST, + request->SourceUID(), source_endpoint_id, + request->DestinationUID(), destination_endpoint_id, + sequence_number); + RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_RPT, m_cid, true); + PreamblePacker::AddTCPPreamble(packet); +} + + /** * Build a NULL TCP packet. These packets can be used for heartbeats. */ @@ -69,6 +93,16 @@ void MessageBuilder::BuildNullTCPPacket(IOStack *packet) { } +/** + * Build a Broker Fetch Client List TCP packet. + */ +void MessageBuilder::BuildBrokerFetchClientListTCPPacket(IOStack *packet) { + BrokerPDU::PrependPDU(packet, ola::acn::VECTOR_BROKER_FETCH_CLIENT_LIST); + RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_BROKER, m_cid, true); + PreamblePacker::AddTCPPreamble(packet); +} + + /** * Build a Broker NULL TCP packet. These packets can be used for broker heartbeats. */ From b176ba12607490fc8724cee7e337520dba05566b Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 3 Mar 2024 19:20:15 +0000 Subject: [PATCH 079/138] Update the TCP header for ACN to match the released standards --- libs/acn/PreamblePacker.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/acn/PreamblePacker.cpp b/libs/acn/PreamblePacker.cpp index 1803b38e69..520b064f3c 100644 --- a/libs/acn/PreamblePacker.cpp +++ b/libs/acn/PreamblePacker.cpp @@ -47,8 +47,7 @@ const uint8_t PreamblePacker::ACN_HEADER[] = { const unsigned int PreamblePacker::ACN_HEADER_SIZE = sizeof(ACN_HEADER); const uint8_t PreamblePacker::TCP_ACN_HEADER[] = { - 0x00, 0x14, // preamble size - 0x00, 0x00, // post amble size + // No pre or post amble size for TCP 0x41, 0x53, 0x43, 0x2d, 0x45, 0x31, 0x2e, 0x31, 0x37, 0x00, 0x00, 0x00 From 356decf0f7c27ba791592f35051600855652d9fc Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 10 Mar 2024 21:10:25 +0000 Subject: [PATCH 080/138] Handle some conversion errors --- include/ola/network/AdvancedTCPConnector.h | 2 +- include/ola/network/TCPConnector.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/ola/network/AdvancedTCPConnector.h b/include/ola/network/AdvancedTCPConnector.h index fdc57c7b04..2810329486 100644 --- a/include/ola/network/AdvancedTCPConnector.h +++ b/include/ola/network/AdvancedTCPConnector.h @@ -84,7 +84,7 @@ class AdvancedTCPConnector { /** * @brief Return the number of connections tracked by this connector. */ - unsigned int EndpointCount() const { return m_connections.size(); } + unsigned int EndpointCount() const { return static_cast(m_connections.size()); } /** * @brief The state of a connection. diff --git a/include/ola/network/TCPConnector.h b/include/ola/network/TCPConnector.h index 4b74c71f9a..b7d8a92b9a 100644 --- a/include/ola/network/TCPConnector.h +++ b/include/ola/network/TCPConnector.h @@ -98,7 +98,7 @@ class TCPConnector { /** * @brief Return the number of pending connections */ - unsigned int ConnectionsPending() const { return m_connections.size(); } + unsigned int ConnectionsPending() const { return static_cast(m_connections.size()); } /** * @brief Called when the TCP socket connects. From e96154c1aa0be0fe2fda143ac88d8b7ada3e9d58 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 10 Mar 2024 21:24:38 +0000 Subject: [PATCH 081/138] Migrate the E1.33 code into a separate lib in libs/acn --- libs/acn/E133HealthCheckedConnection.cpp | 71 +++++++ libs/acn/E133HealthCheckedConnection.h | 76 ++++++++ libs/acn/E133Helper.cpp | 73 ++++++++ libs/acn/E133StatusHelper.cpp | 146 +++++++++++++++ libs/acn/Makefile.mk | 90 ++++++--- libs/acn/MessageBuilder.cpp | 176 ++++++++++++++++++ tools/e133/DesignatedControllerConnection.cpp | 2 +- tools/e133/DesignatedControllerConnection.h | 2 +- tools/e133/DeviceManagerImpl.cpp | 2 +- tools/e133/E133Device.cpp | 2 +- tools/e133/Makefile.mk | 20 +- tools/e133/basic-controller.cpp | 2 +- tools/e133/basic-device.cpp | 2 +- 13 files changed, 626 insertions(+), 38 deletions(-) create mode 100644 libs/acn/E133HealthCheckedConnection.cpp create mode 100644 libs/acn/E133HealthCheckedConnection.h create mode 100644 libs/acn/E133Helper.cpp create mode 100644 libs/acn/E133StatusHelper.cpp create mode 100644 libs/acn/MessageBuilder.cpp diff --git a/libs/acn/E133HealthCheckedConnection.cpp b/libs/acn/E133HealthCheckedConnection.cpp new file mode 100644 index 0000000000..798728e3d1 --- /dev/null +++ b/libs/acn/E133HealthCheckedConnection.cpp @@ -0,0 +1,71 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * E133HealthCheckedConnection.cpp + * Copyright (C) 2012 Simon Newton + */ + +#include +#include +#include + +#include "libs/acn/E133HealthCheckedConnection.h" +#include "libs/acn/RootSender.h" + +using ola::io::IOStack; + +/** + * Create a new E1.33 Health Checked Connection. + * @param message_builder the MessageBuilder to use to create packets. + * @param message_queue the NonBlockingSender to use to send packets. + * @param on_timeout the callback to run when the heartbeats don't arrive + * @param scheduler A SchedulerInterface used to control the timers + * @param heartbeat_interval the TimeInterval between heartbeats + */ +E133HealthCheckedConnection::E133HealthCheckedConnection( + ola::e133::MessageBuilder *message_builder, + ola::io::NonBlockingSender *message_queue, + ola::SingleUseCallback0 *on_timeout, + ola::thread::SchedulingExecutorInterface *scheduler, + const ola::TimeInterval heartbeat_interval, + const ola::TimeInterval timeout_interval) + : HealthCheckedConnection(scheduler, heartbeat_interval, timeout_interval), + m_message_builder(message_builder), + m_message_queue(message_queue), + m_on_timeout(on_timeout), + m_executor(scheduler) { +} + + +/** + * Send a E1.33 heartbeat + */ +void E133HealthCheckedConnection::SendHeartbeat() { + OLA_DEBUG << "Sending heartbeat"; + IOStack packet(m_message_builder->pool()); + m_message_builder->BuildBrokerNullTCPPacket(&packet); + m_message_queue->SendMessage(&packet); +} + + +/** + * Called if the connection is declared dead + */ +void E133HealthCheckedConnection::HeartbeatTimeout() { + OLA_INFO << "TCP connection heartbeat timeout"; + if (m_on_timeout.get()) { + m_executor->Execute(m_on_timeout.release()); + } +} diff --git a/libs/acn/E133HealthCheckedConnection.h b/libs/acn/E133HealthCheckedConnection.h new file mode 100644 index 0000000000..3e6712cb30 --- /dev/null +++ b/libs/acn/E133HealthCheckedConnection.h @@ -0,0 +1,76 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * E133HealthCheckedConnection.h + * Copyright (C) 2012 Simon Newton + * + * This class detects unhealthy TCP connections. A TCP connection is defined as + * healthy if it can pass data in both directions. Both ends must implement the + * same health checking logic (and agree on heartbeat intervals) for this to + * work correctly. + * + * This is a E1.33 Health Checked Connection as it sends E1.33 Broker NULL PDUs + * using VECTOR_BROKER_NULL, but it also accepts any ACN root layer PDUs as a + * positive indication the connection is healthy. + * + * You could use it with any ACN based protocol by subclassing it and sending + * heartbeat messages of ROOT_VECTOR_NULL via SendHeartbeat instead. + */ + +#ifndef TOOLS_E133_E133HEALTHCHECKEDCONNECTION_H_ +#define TOOLS_E133_E133HEALTHCHECKEDCONNECTION_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include + + +/** + * An E1.33 health checked connection. + */ +class E133HealthCheckedConnection + : public ola::network::HealthCheckedConnection { + public: + E133HealthCheckedConnection( + ola::e133::MessageBuilder *message_builder, + ola::io::NonBlockingSender *message_queue, + ola::SingleUseCallback0 *on_timeout, + ola::thread::SchedulingExecutorInterface *scheduler, + const ola::TimeInterval heartbeat_interval = + ola::TimeInterval(E133_TCP_HEARTBEAT_INTERVAL, 0), + const ola::TimeInterval timeout_interval = + ola::TimeInterval(E133_HEARTBEAT_TIMEOUT, 0)); + + void SendHeartbeat(); + void HeartbeatTimeout(); + + private: + ola::e133::MessageBuilder *m_message_builder; + ola::io::NonBlockingSender *m_message_queue; + std::auto_ptr > m_on_timeout; + ola::thread::SchedulingExecutorInterface *m_executor; + + // The default interval in seconds for sending heartbeat messages. + static const unsigned int E133_TCP_HEARTBEAT_INTERVAL = 15; + // The default interval in seconds before timing out. + static const unsigned int E133_HEARTBEAT_TIMEOUT = 45; +}; +#endif // TOOLS_E133_E133HEALTHCHECKEDCONNECTION_H_ diff --git a/libs/acn/E133Helper.cpp b/libs/acn/E133Helper.cpp new file mode 100644 index 0000000000..1905a16bce --- /dev/null +++ b/libs/acn/E133Helper.cpp @@ -0,0 +1,73 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * E133Helper.cpp + * Various misc E1.33 functions. + * Copyright (C) 2024 Peter Newman + * + * At some point we may want to localize this file. + */ + +#include +#include +#include +#include "ola/e133/E133Enums.h" +#include "ola/e133/E133Helper.h" +#include "ola/StringUtils.h" + +namespace ola { +namespace e133 { + +using std::ostringstream; +using std::string; +using std::vector; + + +/** + * Verify that the int is a valid E1.33 RPT Client Type. + */ +bool IntToRPTClientType(uint8_t input, + ola::e133::E133RPTClientTypeCode *client_type) { + switch (input) { + case ola::e133::RPT_CLIENT_TYPE_DEVICE: + *client_type = ola::e133::RPT_CLIENT_TYPE_DEVICE; + return true; + case ola::e133::RPT_CLIENT_TYPE_CONTROLLER: + *client_type = ola::e133::RPT_CLIENT_TYPE_CONTROLLER; + return true; + default: + return false; + } +} + + +/** + * Convert a uint8_t representing an RPT client type to a human-readable string. + * @param type the RPT client type value + */ +string RPTClientTypeToString(uint8_t type) { + switch (type) { + case RPT_CLIENT_TYPE_DEVICE: + return "Device"; + case RPT_CLIENT_TYPE_CONTROLLER: + return "Controller"; + default: + ostringstream str; + str << "Unknown, was " << static_cast(type); + return str.str(); + } +} +} // namespace e133 +} // namespace ola diff --git a/libs/acn/E133StatusHelper.cpp b/libs/acn/E133StatusHelper.cpp new file mode 100644 index 0000000000..a1ec71627c --- /dev/null +++ b/libs/acn/E133StatusHelper.cpp @@ -0,0 +1,146 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * E133StatusHelper.cpp + * Functions for dealing with E1.33 Status Codes. + * Copyright (C) 2013 Simon Newton + */ + +#include +#include +#include "ola/e133/E133StatusHelper.h" + +namespace ola { +namespace e133 { + +using std::string; + +/** + * Verify that the int is a valid E1.33 Status Code. + */ +bool IntToStatusCode(uint16_t input, E133StatusCode *status_code) { + switch (input) { + case ola::e133::SC_E133_ACK: + *status_code = ola::e133::SC_E133_ACK; + return true; + case ola::e133::SC_E133_RDM_TIMEOUT: + *status_code = ola::e133::SC_E133_RDM_TIMEOUT; + return true; + case ola::e133::SC_E133_RDM_INVALID_RESPONSE: + *status_code = ola::e133::SC_E133_RDM_INVALID_RESPONSE; + return true; + case ola::e133::SC_E133_BUFFER_FULL: + *status_code = ola::e133::SC_E133_BUFFER_FULL; + return true; + case ola::e133::SC_E133_UNKNOWN_UID: + *status_code = ola::e133::SC_E133_UNKNOWN_UID; + return true; + case ola::e133::SC_E133_NONEXISTENT_ENDPOINT: + *status_code = ola::e133::SC_E133_NONEXISTENT_ENDPOINT; + return true; + case ola::e133::SC_E133_WRONG_ENDPOINT: + *status_code = ola::e133::SC_E133_WRONG_ENDPOINT; + return true; + case ola::e133::SC_E133_ACK_OVERFLOW_CACHE_EXPIRED: + *status_code = ola::e133::SC_E133_ACK_OVERFLOW_CACHE_EXPIRED; + return true; + case ola::e133::SC_E133_ACK_OVERFLOW_IN_PROGRESS: + *status_code = ola::e133::SC_E133_ACK_OVERFLOW_IN_PROGRESS; + return true; + case ola::e133::SC_E133_BROADCAST_COMPLETE: + *status_code = ola::e133::SC_E133_BROADCAST_COMPLETE; + return true; + default: + return false; + } +} + + +/** + * Return a text string describing this status code. + */ +string StatusCodeToString(E133StatusCode status_code) { + switch (status_code) { + case ola::e133::SC_E133_ACK: + return "Acknowledged"; + case ola::e133::SC_E133_RDM_TIMEOUT: + return "Response Timeout"; + case ola::e133::SC_E133_RDM_INVALID_RESPONSE: + return "Invalid Response"; + case ola::e133::SC_E133_BUFFER_FULL: + return "Buffer Full"; + case ola::e133::SC_E133_UNKNOWN_UID: + return "Unknown UID"; + case ola::e133::SC_E133_NONEXISTENT_ENDPOINT: + return "Endpoint doesn't exist"; + case ola::e133::SC_E133_WRONG_ENDPOINT: + return "Wrong endpoint"; + case ola::e133::SC_E133_ACK_OVERFLOW_CACHE_EXPIRED: + return "Ack overflow cache expired"; + case ola::e133::SC_E133_ACK_OVERFLOW_IN_PROGRESS: + return "Ack overflow in progress"; + case ola::e133::SC_E133_BROADCAST_COMPLETE: + return "Request was broadcast"; + } + return "Unknown E1.33 Status Code"; +} + + +bool IntToConnectStatusCode(uint16_t input, + E133ConnectStatusCode *connect_status_code) { + switch (input) { + case ola::e133::CONNECT_OK: + *connect_status_code = ola::e133::CONNECT_OK; + return true; + case ola::e133::CONNECT_SCOPE_MISMATCH: + *connect_status_code = ola::e133::CONNECT_SCOPE_MISMATCH; + return true; + case ola::e133::CONNECT_CAPACITY_EXCEEDED: + *connect_status_code = ola::e133::CONNECT_CAPACITY_EXCEEDED; + return true; + case ola::e133::CONNECT_DUPLICATE_UID: + *connect_status_code = ola::e133::CONNECT_DUPLICATE_UID; + return true; + case ola::e133::CONNECT_INVALID_CLIENT_ENTRY: + *connect_status_code = ola::e133::CONNECT_INVALID_CLIENT_ENTRY; + return true; + case ola::e133::CONNECT_INVALID_UID: + *connect_status_code = ola::e133::CONNECT_INVALID_UID; + return true; + default: + return false; + } +} + + +string ConnectStatusCodeToString(E133ConnectStatusCode connect_status_code) { + switch (connect_status_code) { + case ola::e133::CONNECT_OK: + return "Ok"; + case ola::e133::CONNECT_SCOPE_MISMATCH: + return "Scope mismatch"; + case ola::e133::CONNECT_CAPACITY_EXCEEDED: + return "Capacity exceeded"; + case ola::e133::CONNECT_DUPLICATE_UID: + return "Duplicate UID"; + case ola::e133::CONNECT_INVALID_CLIENT_ENTRY: + return "Invalid client entry"; + case ola::e133::CONNECT_INVALID_UID: + return "Invalid UID"; + } + return "Unknown E1.33 Connect Status Code"; +} +} // namespace e133 +} // namespace ola diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index 37c8d999f8..720805da50 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -1,4 +1,5 @@ COMMON_E131_CXXFLAGS = $(COMMON_CXXFLAGS) -Wconversion +COMMON_E133_CXXFLAGS = $(COMMON_CXXFLAGS) -Wconversion # pkg-config ################################################## @@ -15,6 +16,12 @@ else noinst_LTLIBRARIES += libs/acn/libolaacn.la endif +if INSTALL_E133 + lib_LTLIBRARIES += libs/acn/libolae133core.la +else + noinst_LTLIBRARIES += libs/acn/libolae133core.la +endif + # libolaacn.la libs_acn_libolaacn_la_SOURCES = \ libs/acn/CID.cpp \ @@ -31,22 +38,6 @@ noinst_LTLIBRARIES += libs/acn/libolae131core.la libs_acn_libolae131core_la_SOURCES = \ libs/acn/BaseInflator.cpp \ libs/acn/BaseInflator.h \ - libs/acn/BrokerClientAddInflator.h \ - libs/acn/BrokerClientEntryChangeInflator.h \ - libs/acn/BrokerClientEntryHeader.h \ - libs/acn/BrokerClientEntryPDU.cpp \ - libs/acn/BrokerClientEntryPDU.h \ - libs/acn/BrokerClientRemoveInflator.h \ - libs/acn/BrokerConnectPDU.cpp \ - libs/acn/BrokerConnectPDU.h \ - libs/acn/BrokerFetchClientListPDU.cpp \ - libs/acn/BrokerFetchClientListPDU.h \ - libs/acn/BrokerInflator.h \ - libs/acn/BrokerNullInflator.h \ - libs/acn/BrokerNullPDU.cpp \ - libs/acn/BrokerNullPDU.h \ - libs/acn/BrokerPDU.cpp \ - libs/acn/BrokerPDU.h \ libs/acn/DMPAddress.cpp \ libs/acn/DMPAddress.h \ libs/acn/DMPE131Inflator.cpp \ @@ -67,15 +58,6 @@ libs_acn_libolae131core_la_SOURCES = \ libs/acn/E131PDU.h \ libs/acn/E131Sender.cpp \ libs/acn/E131Sender.h \ - libs/acn/E133Header.h \ - libs/acn/E133Inflator.cpp \ - libs/acn/E133Inflator.h \ - libs/acn/E133PDU.cpp \ - libs/acn/E133PDU.h \ - libs/acn/E133StatusInflator.cpp \ - libs/acn/E133StatusInflator.h \ - libs/acn/E133StatusPDU.cpp \ - libs/acn/E133StatusPDU.h \ libs/acn/HeaderSet.h \ libs/acn/LLRPHeader.h \ libs/acn/LLRPInflator.cpp \ @@ -128,6 +110,61 @@ libs_acn_libolae131core_la_LIBADD = $(uuid_LIBS) \ common/libolacommon.la \ libs/acn/libolaacn.la +# libolae133core.la +# This needs to be after libolaacn.la and libolae131core.la since it depends on +# them. Otherwise it breaks the freeBSD build +libs_acn_libolae133core_la_SOURCES = \ + libs/acn/BrokerClientAddInflator.h \ + libs/acn/BrokerClientEntryChangeInflator.h \ + libs/acn/BrokerClientEntryHeader.h \ + libs/acn/BrokerClientEntryPDU.cpp \ + libs/acn/BrokerClientEntryPDU.h \ + libs/acn/BrokerClientEntryRPTPDU.cpp \ + libs/acn/BrokerClientEntryRPTPDU.h \ + libs/acn/BrokerClientEntryRPTInflator.cpp \ + libs/acn/BrokerClientEntryRPTInflator.h \ + libs/acn/BrokerClientEntryUpdateInflator.h \ + libs/acn/BrokerClientRemoveInflator.h \ + libs/acn/BrokerConnectedClientListInflator.cpp \ + libs/acn/BrokerConnectedClientListInflator.h \ + libs/acn/BrokerConnectPDU.cpp \ + libs/acn/BrokerConnectPDU.h \ + libs/acn/BrokerConnectReplyInflator.cpp \ + libs/acn/BrokerConnectReplyInflator.h \ + libs/acn/BrokerFetchClientListPDU.cpp \ + libs/acn/BrokerFetchClientListPDU.h \ + libs/acn/BrokerHeader.h \ + libs/acn/BrokerInflator.h \ + libs/acn/BrokerManager.cpp \ + libs/acn/BrokerManagerImpl.cpp \ + libs/acn/BrokerManagerImpl.h \ + libs/acn/BrokerNullInflator.h \ + libs/acn/BrokerNullPDU.cpp \ + libs/acn/BrokerNullPDU.h \ + libs/acn/BrokerPDU.cpp \ + libs/acn/BrokerPDU.h \ + libs/acn/E133Header.h \ + libs/acn/E133HealthCheckedConnection.cpp \ + libs/acn/E133HealthCheckedConnection.h \ + libs/acn/E133Helper.cpp \ + libs/acn/E133Inflator.cpp \ + libs/acn/E133Inflator.h \ + libs/acn/E133PDU.cpp \ + libs/acn/E133PDU.h \ + libs/acn/E133StatusHelper.cpp \ + libs/acn/E133StatusInflator.cpp \ + libs/acn/E133StatusInflator.h \ + libs/acn/E133StatusPDU.cpp \ + libs/acn/E133StatusPDU.h \ + libs/acn/MessageBuilder.cpp + +libs_acn_libolae133core_la_CXXFLAGS = \ + $(COMMON_E133_CXXFLAGS) $(uuid_CFLAGS) +libs_acn_libolae133core_la_LIBADD = $(uuid_LIBS) \ + common/libolacommon.la \ + libs/acn/libolaacn.la \ + libs/acn/libolae131core.la + # PROGRAMS ################################################## noinst_PROGRAMS += libs/acn/e131_transmit_test \ @@ -170,10 +207,13 @@ libs_acn_E131Tester_LDADD = \ libs/acn/libolae131core.la \ $(COMMON_TESTING_LIBS) +# libs/acn/BrokerInflatorTest.cpp libs_acn_E133Tester_SOURCES = \ libs/acn/BrokerClientEntryPDUTest.cpp \ + libs/acn/BrokerClientEntryRPTPDUTest.cpp \ libs/acn/BrokerConnectPDUTest.cpp \ libs/acn/BrokerFetchClientListPDUTest.cpp \ + libs/acn/BrokerNullInflatorTest.cpp \ libs/acn/BrokerNullPDUTest.cpp \ libs/acn/BrokerPDUTest.cpp \ libs/acn/E133InflatorTest.cpp \ diff --git a/libs/acn/MessageBuilder.cpp b/libs/acn/MessageBuilder.cpp new file mode 100644 index 0000000000..41d352539b --- /dev/null +++ b/libs/acn/MessageBuilder.cpp @@ -0,0 +1,176 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * MessageBuilder.cpp + * Copyright (C) 2013 Simon Newton + * + * A class to simplify some of the E1.33 packet building operations. + */ + +#include +#include "ola/acn/ACNVectors.h" +#include "ola/acn/CID.h" +#include "ola/e133/MessageBuilder.h" +#include "ola/io/IOStack.h" +#include "ola/rdm/RDMCommandSerializer.h" + +#include "libs/acn/BrokerPDU.h" +#include "libs/acn/E133PDU.h" +#include "libs/acn/RDMPDU.h" +#include "libs/acn/RootPDU.h" +#include "libs/acn/RPTPDU.h" +#include "libs/acn/RPTRequestPDU.h" +#include "libs/acn/E133StatusPDU.h" +#include "libs/acn/PreamblePacker.h" + +namespace ola { +namespace e133 { + +using ola::acn::CID; +using ola::io::IOStack; +using ola::acn::BrokerPDU; +using ola::acn::E133PDU; +using ola::acn::PreamblePacker; +using ola::acn::RootPDU; +using ola::acn::RPTPDU; + + +MessageBuilder::MessageBuilder(const CID &cid, const string &source_name) + : m_cid(cid), + m_source_name(source_name), + // The Max sized RDM packet is 256 bytes, E1.33 adds 118 bytes of + // headers. + m_memory_pool(400) { +} + + +/** + * Append a RDM PDU Header onto this packet + */ +void MessageBuilder::PrependRDMHeader(IOStack *packet) { + ola::acn::RDMPDU::PrependPDU(packet); +} + + +/** + * Build a TCP E1.33 RDM Command PDU response. + */ +void MessageBuilder::BuildTCPRDMCommandPDU(IOStack *packet, + ola::rdm::RDMRequest *request, + uint16_t source_endpoint_id, + uint16_t destination_endpoint_id, + uint32_t sequence_number) { + ola::rdm::RDMCommandSerializer::Write(*request, packet); + ola::acn::RDMPDU::PrependPDU(packet); + ola::acn::RPTRequestPDU::PrependPDU(packet); + RPTPDU::PrependPDU(packet, ola::acn::VECTOR_RPT_REQUEST, + request->SourceUID(), source_endpoint_id, + request->DestinationUID(), destination_endpoint_id, + sequence_number); + RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_RPT, m_cid, true); + PreamblePacker::AddTCPPreamble(packet); +} + + +/** + * Build a NULL TCP packet. These packets can be used for heartbeats. + */ +void MessageBuilder::BuildNullTCPPacket(IOStack *packet) { + RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_NULL, m_cid); + PreamblePacker::AddTCPPreamble(packet); +} + + +/** + * Build a Broker Fetch Client List TCP packet. + */ +void MessageBuilder::BuildBrokerFetchClientListTCPPacket(IOStack *packet) { + BrokerPDU::PrependPDU(packet, ola::acn::VECTOR_BROKER_FETCH_CLIENT_LIST); + RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_BROKER, m_cid, true); + PreamblePacker::AddTCPPreamble(packet); +} + + +/** + * Build a Broker NULL TCP packet. These packets can be used for broker heartbeats. + */ +void MessageBuilder::BuildBrokerNullTCPPacket(IOStack *packet) { + BrokerPDU::PrependPDU(packet, ola::acn::VECTOR_BROKER_NULL); + RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_BROKER, m_cid, true); + PreamblePacker::AddTCPPreamble(packet); +} + + +/** + * Build a TCP E1.33 Status PDU response. This should really only be used with + * SC_E133_ACK. + */ +void MessageBuilder::BuildTCPE133StatusPDU(ola::io::IOStack *packet, + uint32_t sequence_number, + uint16_t endpoint_id, + E133StatusCode status_code, + const string &description) { + ola::acn::E133StatusPDU::PrependPDU( + packet, status_code, description); + BuildTCPRootE133( + packet, ola::acn::VECTOR_FRAMING_STATUS, + sequence_number, endpoint_id); +} + + +/** + * Build an E1.33 Status PDU response + */ +void MessageBuilder::BuildUDPE133StatusPDU(ola::io::IOStack *packet, + uint32_t sequence_number, + uint16_t endpoint_id, + E133StatusCode status_code, + const string &description) { + ola::acn::E133StatusPDU::PrependPDU( + packet, status_code, description); + BuildUDPRootE133( + packet, ola::acn::VECTOR_FRAMING_STATUS, + sequence_number, endpoint_id); +} + + +/** + * Append an E133PDU, a RootPDU and the TCP preamble to a packet. + */ +void MessageBuilder::BuildTCPRootE133(IOStack *packet, + uint32_t vector, + uint32_t sequence_number, + uint16_t endpoint_id) { + E133PDU::PrependPDU(packet, vector, m_source_name, sequence_number, + endpoint_id); + RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_RPT, m_cid); + PreamblePacker::AddTCPPreamble(packet); +} + + +/** + * Append an E133PDU, a RootPDU and the UDP preamble to a packet. + */ +void MessageBuilder::BuildUDPRootE133(IOStack *packet, + uint32_t vector, + uint32_t sequence_number, + uint16_t endpoint_id) { + E133PDU::PrependPDU(packet, vector, m_source_name, sequence_number, + endpoint_id); + RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_RPT, m_cid); + PreamblePacker::AddUDPPreamble(packet); +} +} // namespace e133 +} // namespace ola diff --git a/tools/e133/DesignatedControllerConnection.cpp b/tools/e133/DesignatedControllerConnection.cpp index 5daae899fa..0683712e91 100644 --- a/tools/e133/DesignatedControllerConnection.cpp +++ b/tools/e133/DesignatedControllerConnection.cpp @@ -33,10 +33,10 @@ #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMCommandSerializer.h" #include "libs/acn/E133Header.h" +#include "libs/acn/E133HealthCheckedConnection.h" #include "libs/acn/E133StatusInflator.h" #include "libs/acn/RDMPDU.h" #include "tools/e133/DesignatedControllerConnection.h" -#include "tools/e133/E133HealthCheckedConnection.h" #include "tools/e133/TCPConnectionStats.h" using ola::NewCallback; diff --git a/tools/e133/DesignatedControllerConnection.h b/tools/e133/DesignatedControllerConnection.h index 7993b70e12..25820594bc 100644 --- a/tools/e133/DesignatedControllerConnection.h +++ b/tools/e133/DesignatedControllerConnection.h @@ -33,11 +33,11 @@ #include "ola/network/TCPSocket.h" #include "ola/network/TCPSocketFactory.h" #include "ola/util/SequenceNumber.h" +#include "libs/acn/E133HealthCheckedConnection.h" #include "libs/acn/E133Inflator.h" #include "libs/acn/E133StatusInflator.h" #include "libs/acn/RootInflator.h" #include "libs/acn/TCPTransport.h" -#include "tools/e133/E133HealthCheckedConnection.h" #include "tools/e133/TCPConnectionStats.h" using std::string; diff --git a/tools/e133/DeviceManagerImpl.cpp b/tools/e133/DeviceManagerImpl.cpp index 2e16aa4a94..f063ae441a 100644 --- a/tools/e133/DeviceManagerImpl.cpp +++ b/tools/e133/DeviceManagerImpl.cpp @@ -36,13 +36,13 @@ #include #include +#include "libs/acn/E133HealthCheckedConnection.h" #include "libs/acn/E133Inflator.h" #include "libs/acn/E133StatusPDU.h" #include "libs/acn/TCPTransport.h" #include "tools/e133/DeviceManagerImpl.h" #include "tools/e133/E133Endpoint.h" -#include "tools/e133/E133HealthCheckedConnection.h" namespace ola { namespace e133 { diff --git a/tools/e133/E133Device.cpp b/tools/e133/E133Device.cpp index ca2a4a69f9..4411d035cd 100644 --- a/tools/e133/E133Device.cpp +++ b/tools/e133/E133Device.cpp @@ -42,7 +42,7 @@ #include "tools/e133/E133Device.h" #include "tools/e133/E133Endpoint.h" -#include "tools/e133/E133HealthCheckedConnection.h" +#include "libs/acn/E133HealthCheckedConnection.h" #include "tools/e133/EndpointManager.h" #include "tools/e133/TCPConnectionStats.h" diff --git a/tools/e133/Makefile.mk b/tools/e133/Makefile.mk index c81e3cf682..76377e1add 100644 --- a/tools/e133/Makefile.mk +++ b/tools/e133/Makefile.mk @@ -22,13 +22,10 @@ endif # libolae133common # Code required by both the controller and device. tools_e133_libolae133common_la_SOURCES = \ - tools/e133/E133HealthCheckedConnection.cpp \ - tools/e133/E133HealthCheckedConnection.h \ - tools/e133/E133Helper.cpp \ - tools/e133/E133Receiver.cpp \ - tools/e133/E133StatusHelper.cpp \ - tools/e133/MessageBuilder.cpp -tools_e133_libolae133common_la_LIBADD = libs/acn/libolae131core.la + tools/e133/E133Receiver.cpp +tools_e133_libolae133common_la_LIBADD = \ + libs/acn/libolae131core.la \ + libs/acn/libolae133core.la # libolae133controller # Controller side. @@ -39,6 +36,7 @@ tools_e133_libolae133controller_la_SOURCES = \ tools_e133_libolae133controller_la_LIBADD = \ common/libolacommon.la \ libs/acn/libolae131core.la \ + libs/acn/libolae133core.la \ tools/e133/libolae133common.la # libolae133device @@ -61,6 +59,7 @@ tools_e133_libolae133device_la_SOURCES = \ tools_e133_libolae133device_la_LIBADD = \ common/libolacommon.la \ libs/acn/libolae131core.la \ + libs/acn/libolae133core.la \ tools/e133/libolae133common.la @@ -78,6 +77,7 @@ noinst_PROGRAMS += \ tools_e133_e133_receiver_SOURCES = tools/e133/e133-receiver.cpp tools_e133_e133_receiver_LDADD = common/libolacommon.la \ libs/acn/libolaacn.la \ + libs/acn/libolae133core.la \ plugins/usbpro/libolausbprowidget.la \ tools/e133/libolae133device.la @@ -88,6 +88,7 @@ endif tools_e133_e133_monitor_SOURCES = tools/e133/e133-monitor.cpp tools_e133_e133_monitor_LDADD = common/libolacommon.la \ libs/acn/libolaacn.la \ + libs/acn/libolae133core.la \ tools/e133/libolae133common.la \ tools/e133/libolae133controller.la @@ -95,25 +96,30 @@ tools_e133_e133_controller_SOURCES = tools/e133/e133-controller.cpp # required for PID_DATA_FILE tools_e133_e133_controller_LDADD = common/libolacommon.la \ libs/acn/libolae131core.la \ + libs/acn/libolae133core.la \ tools/e133/libolae133common.la \ tools/e133/libolae133controller.la tools_e133_basic_controller_SOURCES = tools/e133/basic-controller.cpp tools_e133_basic_controller_LDADD = common/libolacommon.la \ libs/acn/libolaacn.la \ + libs/acn/libolae133core.la \ tools/e133/libolae133common.la tools_e133_basic_device_SOURCES = tools/e133/basic-device.cpp tools_e133_basic_device_LDADD = common/libolacommon.la \ libs/acn/libolaacn.la \ + libs/acn/libolae133core.la \ tools/e133/libolae133common.la tools_e133_llrp_manager_SOURCES = tools/e133/llrp-manager.cpp tools_e133_llrp_manager_LDADD = common/libolacommon.la \ libs/acn/libolaacn.la \ + libs/acn/libolae133core.la \ tools/e133/libolae133common.la tools_e133_llrp_target_SOURCES = tools/e133/llrp-target.cpp tools_e133_llrp_target_LDADD = common/libolacommon.la \ libs/acn/libolaacn.la \ + libs/acn/libolae133core.la \ tools/e133/libolae133common.la diff --git a/tools/e133/basic-controller.cpp b/tools/e133/basic-controller.cpp index 4df2ddcfb3..02bfd3825e 100644 --- a/tools/e133/basic-controller.cpp +++ b/tools/e133/basic-controller.cpp @@ -42,9 +42,9 @@ #include #include +#include "libs/acn/E133HealthCheckedConnection.h" #include "libs/acn/RootInflator.h" #include "libs/acn/TCPTransport.h" -#include "tools/e133/E133HealthCheckedConnection.h" DEFINE_string(listen_ip, "", "The IP Address to listen on"); DEFINE_uint16(listen_port, 5569, "The port to listen on"); diff --git a/tools/e133/basic-device.cpp b/tools/e133/basic-device.cpp index bdc87afc22..3d30c99a9a 100644 --- a/tools/e133/basic-device.cpp +++ b/tools/e133/basic-device.cpp @@ -39,9 +39,9 @@ #include #include +#include "libs/acn/E133HealthCheckedConnection.h" #include "libs/acn/RootInflator.h" #include "libs/acn/TCPTransport.h" -#include "tools/e133/E133HealthCheckedConnection.h" DEFINE_string(controller_ip, "", "The IP Address of the Controller"); DEFINE_uint16(controller_port, 5569, "The port on the controller"); From 596121269e8d9d66608177385e8455fcacc9c323 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 10 Mar 2024 21:28:24 +0000 Subject: [PATCH 082/138] Fix a header guard after moving a file --- libs/acn/E133HealthCheckedConnection.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/acn/E133HealthCheckedConnection.h b/libs/acn/E133HealthCheckedConnection.h index 3e6712cb30..1008edfcaf 100644 --- a/libs/acn/E133HealthCheckedConnection.h +++ b/libs/acn/E133HealthCheckedConnection.h @@ -29,8 +29,8 @@ * heartbeat messages of ROOT_VECTOR_NULL via SendHeartbeat instead. */ -#ifndef TOOLS_E133_E133HEALTHCHECKEDCONNECTION_H_ -#define TOOLS_E133_E133HEALTHCHECKEDCONNECTION_H_ +#ifndef LIBS_ACN_E133HEALTHCHECKEDCONNECTION_H_ +#define LIBS_ACN_E133HEALTHCHECKEDCONNECTION_H_ #include #include @@ -73,4 +73,4 @@ class E133HealthCheckedConnection // The default interval in seconds before timing out. static const unsigned int E133_HEARTBEAT_TIMEOUT = 45; }; -#endif // TOOLS_E133_E133HEALTHCHECKEDCONNECTION_H_ +#endif // LIBS_ACN_E133HEALTHCHECKEDCONNECTION_H_ From e41fd88093392bccf2c6a0b648efc93a1f84f35e Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 10 Mar 2024 22:45:19 +0000 Subject: [PATCH 083/138] Fix the tests after making a new library --- libs/acn/Makefile.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index 720805da50..1ca876e548 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -225,6 +225,7 @@ libs_acn_E133Tester_SOURCES = \ libs_acn_E133Tester_CPPFLAGS = $(COMMON_TESTING_FLAGS) libs_acn_E133Tester_LDADD = \ libs/acn/libolae131core.la \ + libs/acn/libolae133core.la \ $(COMMON_TESTING_LIBS) libs_acn_LLRPTester_SOURCES = \ From 35e4ed193da7691d5b40255a733ee05232a57d6c Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 16 Mar 2024 12:34:43 +0000 Subject: [PATCH 084/138] Be more consistent with the representation of enums to match the standard --- include/ola/acn/ACNVectors.h | 94 ++++++++++++++++++++++++------------ 1 file changed, 64 insertions(+), 30 deletions(-) diff --git a/include/ola/acn/ACNVectors.h b/include/ola/acn/ACNVectors.h index 8734583e81..b058beb810 100644 --- a/include/ola/acn/ACNVectors.h +++ b/include/ola/acn/ACNVectors.h @@ -43,13 +43,14 @@ namespace acn { * @brief ACN vectors used at the root layer. */ enum RootVector { - VECTOR_ROOT_E131_REV2 = 3, /**< Draft E1.31, used by some old gear. */ - VECTOR_ROOT_E131 = 4, /**< E1.31 (sACN) */ - VECTOR_ROOT_RPT = 5, /**< E1.33 (RPT) */ - VECTOR_ROOT_NULL = 6, /**< NULL (empty) root */ - VECTOR_ROOT_BROKER = 9, /**< E1.33 (Broker) */ - VECTOR_ROOT_LLRP = 0x0A, /**< E1.33 (LLRP) */ - VECTOR_ROOT_EPT = 0x0B, /**< E1.33 (EPT) */ + /** @brief Draft E1.31, used by some old gear. */ + VECTOR_ROOT_E131_REV2 = 0x00000003, + VECTOR_ROOT_E131 = 0x00000004, /**< E1.31 (sACN) */ + VECTOR_ROOT_RPT = 0x00000005, /**< E1.33 (RPT) */ + VECTOR_ROOT_NULL = 0x00000006, /**< NULL (empty) root */ + VECTOR_ROOT_BROKER = 0x00000009, /**< E1.33 (Broker) */ + VECTOR_ROOT_LLRP = 0x0000000A, /**< E1.33 (LLRP) */ + VECTOR_ROOT_EPT = 0x0000000B, /**< E1.33 (EPT) */ }; /** @@ -94,9 +95,9 @@ enum E133ControllerVector { * @brief Vectors used at the E1.33 LLRP layer. */ enum LLRPVector { - VECTOR_LLRP_PROBE_REQUEST = 1, /**< LLRP Probe Request */ - VECTOR_LLRP_PROBE_REPLY = 2, /**< LLRP Probe Reply */ - VECTOR_LLRP_RDM_CMD = 3, /**< LLRP RDM Command */ + VECTOR_LLRP_PROBE_REQUEST = 0x00000001, /**< LLRP Probe Request */ + VECTOR_LLRP_PROBE_REPLY = 0x00000002, /**< LLRP Probe Reply */ + VECTOR_LLRP_RDM_CMD = 0x00000003, /**< LLRP RDM Command */ }; /** @@ -105,17 +106,35 @@ enum LLRPVector { enum BrokerVector { VECTOR_BROKER_CONNECT = 0x0001, /**< Broker Client Connect */ VECTOR_BROKER_CONNECT_REPLY = 0x0002, /**< Broker Connect Reply */ - VECTOR_BROKER_CLIENT_ENTRY_UPDATE = 0x0003, /**< Broker Client Entry Update */ + + /** @brief Broker Client Entry Update */ + VECTOR_BROKER_CLIENT_ENTRY_UPDATE = 0x0003, + VECTOR_BROKER_REDIRECT_V4 = 0x0004, /**< Broker Client Redirect IPv4 */ VECTOR_BROKER_REDIRECT_V6 = 0x0005, /**< Broker Client Redirect IPv6 */ VECTOR_BROKER_FETCH_CLIENT_LIST = 0x0006, /**< Broker Fetch Client List */ - VECTOR_BROKER_CONNECTED_CLIENT_LIST = 0x0007, /**< Broker Connected Client List */ - VECTOR_BROKER_CLIENT_ADD = 0x0008, /**< Broker Client Incremental Addition */ - VECTOR_BROKER_CLIENT_REMOVE = 0x0009, /**< Broker Client Incremental Deletion */ - VECTOR_BROKER_CLIENT_ENTRY_CHANGE = 0x000A, /**< Broker Client Entry Change */ - VECTOR_BROKER_REQUEST_DYNAMIC_UIDS = 0x000B, /**< Broker Request Dynamic UID Assignment */ - VECTOR_BROKER_ASSIGNED_DYNAMIC_UIDS = 0x000C, /**< Broker Dynamic UID Assignment List */ - VECTOR_BROKER_FETCH_DYNAMIC_UID_LIST = 0x000D, /**< Broker Fetch Dynamic UID Assignment List */ + + /** @brief Broker Connected Client List */ + VECTOR_BROKER_CONNECTED_CLIENT_LIST = 0x0007, + + /** @brief Broker Client Incremental Addition */ + VECTOR_BROKER_CLIENT_ADD = 0x0008, + + /** @brief Broker Client Incremental Deletion */ + VECTOR_BROKER_CLIENT_REMOVE = 0x0009, + + /** @brief Broker Client Entry Change */ + VECTOR_BROKER_CLIENT_ENTRY_CHANGE = 0x000A, + + /** @brief Broker Request Dynamic UID Assignment */ + VECTOR_BROKER_REQUEST_DYNAMIC_UIDS = 0x000B, + + /** @brief Broker Dynamic UID Assignment List */ + VECTOR_BROKER_ASSIGNED_DYNAMIC_UIDS = 0x000C, + + /** @brief Broker Fetch Dynamic UID Assignment List */ + VECTOR_BROKER_FETCH_DYNAMIC_UID_LIST = 0x000D, + VECTOR_BROKER_DISCONNECT = 0x000E, /**< Broker Client Disconnect */ VECTOR_BROKER_NULL = 0x000F, /**< Broker Client Null */ }; @@ -125,9 +144,9 @@ enum BrokerVector { * @brief Vectors used at the E1.33 RPT layer. */ enum RPTVector { - VECTOR_RPT_REQUEST = 1, /**< RPT Request */ - VECTOR_RPT_STATUS = 2, /**< RPT Status */ - VECTOR_RPT_NOTIFICATION = 3, /**< RPT Notification */ + VECTOR_RPT_REQUEST = 0x00000001, /**< RPT Request */ + VECTOR_RPT_STATUS = 0x00000002, /**< RPT Status */ + VECTOR_RPT_NOTIFICATION = 0x00000003, /**< RPT Notification */ }; // Table A-9, RPT Request PDU Vector @@ -135,7 +154,7 @@ enum RPTVector { * @brief Vectors used at the E1.33 RPT Request layer. */ enum RPTRequestVector { - VECTOR_REQUEST_RDM_CMD = 1, /**< RPT Request RDM Command */ + VECTOR_REQUEST_RDM_CMD = 0x01, /**< RPT Request RDM Command */ }; // Table A-10, RPT Status PDU Vector @@ -143,15 +162,30 @@ enum RPTRequestVector { * @brief Vectors used at the E1.33 RPT Status layer. */ enum RPTStatusVector { - VECTOR_RPT_STATUS_UNKNOWN_RPT_UID = 0x0001, /**< RPT Status Unknown RPT UID */ + /** @brief RPT Status Unknown RPT UID */ + VECTOR_RPT_STATUS_UNKNOWN_RPT_UID = 0x0001, + VECTOR_RPT_STATUS_RDM_TIMEOUT = 0x0002, /**< RPT Status RDM Timeout */ - VECTOR_RPT_STATUS_RDM_INVALID_RESPONSE = 0x0003, /**< RPT Status RDM Invalid Response */ - VECTOR_RPT_STATUS_UNKNOWN_RDM_UID = 0x0004, /**< RPT Status Unknown RDM UID */ - VECTOR_RPT_STATUS_UNKNOWN_ENDPOINT = 0x0005, /**< RPT Status Unknown Endpoint */ - VECTOR_RPT_STATUS_BROADCAST_COMPLETE = 0x0006, /**< RPT Status Broadcast Complete */ + + /** @brief RPT Status RDM Invalid Response */ + VECTOR_RPT_STATUS_RDM_INVALID_RESPONSE = 0x0003, + + /** @brief RPT Status Unknown RDM UID */ + VECTOR_RPT_STATUS_UNKNOWN_RDM_UID = 0x0004, + + /** @brief RPT Status Unknown Endpoint */ + VECTOR_RPT_STATUS_UNKNOWN_ENDPOINT = 0x0005, + + /** @brief RPT Status Broadcast Complete */ + VECTOR_RPT_STATUS_BROADCAST_COMPLETE = 0x0006, + VECTOR_RPT_STATUS_UNKNOWN_VECTOR = 0x0007, /**< RPT Status Unknown Vector */ - VECTOR_RPT_STATUS_INVALID_MESSAGE = 0x0008, /**< RPT Status Invalid Message */ - VECTOR_RPT_STATUS_INVALID_COMMAND_CLASS = 0x0009, /**< RPT Status Invalid Command Class */ + + /** @brief RPT Status Invalid Message */ + VECTOR_RPT_STATUS_INVALID_MESSAGE = 0x0008, + + /** @brief RPT Status Invalid Command Class */ + VECTOR_RPT_STATUS_INVALID_COMMAND_CLASS = 0x0009, }; // Table A-11, RPT Notification PDU Vector @@ -159,7 +193,7 @@ enum RPTStatusVector { * @brief Vectors used at the E1.33 RPT Notification layer. */ enum RPTNotificationVector { - VECTOR_NOTIFICATION_RDM_CMD = 1, /**< RPT Notification RDM Command */ + VECTOR_NOTIFICATION_RDM_CMD = 0x01, /**< RPT Notification RDM Command */ }; /** From 7026e60b16e9cc7608c3451816a1fa6944a6f316 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 16 Mar 2024 16:42:46 +0000 Subject: [PATCH 085/138] Remove redundant duplicate copies of some libraries since they've moved --- tools/e133/E133HealthCheckedConnection.cpp | 71 --------- tools/e133/E133HealthCheckedConnection.h | 76 --------- tools/e133/E133Helper.cpp | 73 --------- tools/e133/E133StatusHelper.cpp | 146 ----------------- tools/e133/MessageBuilder.cpp | 176 --------------------- 5 files changed, 542 deletions(-) delete mode 100644 tools/e133/E133HealthCheckedConnection.cpp delete mode 100644 tools/e133/E133HealthCheckedConnection.h delete mode 100644 tools/e133/E133Helper.cpp delete mode 100644 tools/e133/E133StatusHelper.cpp delete mode 100644 tools/e133/MessageBuilder.cpp diff --git a/tools/e133/E133HealthCheckedConnection.cpp b/tools/e133/E133HealthCheckedConnection.cpp deleted file mode 100644 index c6dd17f663..0000000000 --- a/tools/e133/E133HealthCheckedConnection.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * E133HealthCheckedConnection.cpp - * Copyright (C) 2012 Simon Newton - */ - -#include -#include -#include - -#include "libs/acn/RootSender.h" -#include "tools/e133/E133HealthCheckedConnection.h" - -using ola::io::IOStack; - -/** - * Create a new E1.33 Health Checked Connection. - * @param message_builder the MessageBuilder to use to create packets. - * @param message_queue the NonBlockingSender to use to send packets. - * @param on_timeout the callback to run when the heartbeats don't arrive - * @param scheduler A SchedulerInterface used to control the timers - * @param heartbeat_interval the TimeInterval between heartbeats - */ -E133HealthCheckedConnection::E133HealthCheckedConnection( - ola::e133::MessageBuilder *message_builder, - ola::io::NonBlockingSender *message_queue, - ola::SingleUseCallback0 *on_timeout, - ola::thread::SchedulingExecutorInterface *scheduler, - const ola::TimeInterval heartbeat_interval, - const ola::TimeInterval timeout_interval) - : HealthCheckedConnection(scheduler, heartbeat_interval, timeout_interval), - m_message_builder(message_builder), - m_message_queue(message_queue), - m_on_timeout(on_timeout), - m_executor(scheduler) { -} - - -/** - * Send a E1.33 heartbeat - */ -void E133HealthCheckedConnection::SendHeartbeat() { - OLA_DEBUG << "Sending heartbeat"; - IOStack packet(m_message_builder->pool()); - m_message_builder->BuildBrokerNullTCPPacket(&packet); - m_message_queue->SendMessage(&packet); -} - - -/** - * Called if the connection is declared dead - */ -void E133HealthCheckedConnection::HeartbeatTimeout() { - OLA_INFO << "TCP connection heartbeat timeout"; - if (m_on_timeout.get()) { - m_executor->Execute(m_on_timeout.release()); - } -} diff --git a/tools/e133/E133HealthCheckedConnection.h b/tools/e133/E133HealthCheckedConnection.h deleted file mode 100644 index 3e6712cb30..0000000000 --- a/tools/e133/E133HealthCheckedConnection.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * E133HealthCheckedConnection.h - * Copyright (C) 2012 Simon Newton - * - * This class detects unhealthy TCP connections. A TCP connection is defined as - * healthy if it can pass data in both directions. Both ends must implement the - * same health checking logic (and agree on heartbeat intervals) for this to - * work correctly. - * - * This is a E1.33 Health Checked Connection as it sends E1.33 Broker NULL PDUs - * using VECTOR_BROKER_NULL, but it also accepts any ACN root layer PDUs as a - * positive indication the connection is healthy. - * - * You could use it with any ACN based protocol by subclassing it and sending - * heartbeat messages of ROOT_VECTOR_NULL via SendHeartbeat instead. - */ - -#ifndef TOOLS_E133_E133HEALTHCHECKEDCONNECTION_H_ -#define TOOLS_E133_E133HEALTHCHECKEDCONNECTION_H_ - -#include -#include -#include -#include -#include -#include -#include - -#include - - -/** - * An E1.33 health checked connection. - */ -class E133HealthCheckedConnection - : public ola::network::HealthCheckedConnection { - public: - E133HealthCheckedConnection( - ola::e133::MessageBuilder *message_builder, - ola::io::NonBlockingSender *message_queue, - ola::SingleUseCallback0 *on_timeout, - ola::thread::SchedulingExecutorInterface *scheduler, - const ola::TimeInterval heartbeat_interval = - ola::TimeInterval(E133_TCP_HEARTBEAT_INTERVAL, 0), - const ola::TimeInterval timeout_interval = - ola::TimeInterval(E133_HEARTBEAT_TIMEOUT, 0)); - - void SendHeartbeat(); - void HeartbeatTimeout(); - - private: - ola::e133::MessageBuilder *m_message_builder; - ola::io::NonBlockingSender *m_message_queue; - std::auto_ptr > m_on_timeout; - ola::thread::SchedulingExecutorInterface *m_executor; - - // The default interval in seconds for sending heartbeat messages. - static const unsigned int E133_TCP_HEARTBEAT_INTERVAL = 15; - // The default interval in seconds before timing out. - static const unsigned int E133_HEARTBEAT_TIMEOUT = 45; -}; -#endif // TOOLS_E133_E133HEALTHCHECKEDCONNECTION_H_ diff --git a/tools/e133/E133Helper.cpp b/tools/e133/E133Helper.cpp deleted file mode 100644 index 1905a16bce..0000000000 --- a/tools/e133/E133Helper.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * E133Helper.cpp - * Various misc E1.33 functions. - * Copyright (C) 2024 Peter Newman - * - * At some point we may want to localize this file. - */ - -#include -#include -#include -#include "ola/e133/E133Enums.h" -#include "ola/e133/E133Helper.h" -#include "ola/StringUtils.h" - -namespace ola { -namespace e133 { - -using std::ostringstream; -using std::string; -using std::vector; - - -/** - * Verify that the int is a valid E1.33 RPT Client Type. - */ -bool IntToRPTClientType(uint8_t input, - ola::e133::E133RPTClientTypeCode *client_type) { - switch (input) { - case ola::e133::RPT_CLIENT_TYPE_DEVICE: - *client_type = ola::e133::RPT_CLIENT_TYPE_DEVICE; - return true; - case ola::e133::RPT_CLIENT_TYPE_CONTROLLER: - *client_type = ola::e133::RPT_CLIENT_TYPE_CONTROLLER; - return true; - default: - return false; - } -} - - -/** - * Convert a uint8_t representing an RPT client type to a human-readable string. - * @param type the RPT client type value - */ -string RPTClientTypeToString(uint8_t type) { - switch (type) { - case RPT_CLIENT_TYPE_DEVICE: - return "Device"; - case RPT_CLIENT_TYPE_CONTROLLER: - return "Controller"; - default: - ostringstream str; - str << "Unknown, was " << static_cast(type); - return str.str(); - } -} -} // namespace e133 -} // namespace ola diff --git a/tools/e133/E133StatusHelper.cpp b/tools/e133/E133StatusHelper.cpp deleted file mode 100644 index a1ec71627c..0000000000 --- a/tools/e133/E133StatusHelper.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * E133StatusHelper.cpp - * Functions for dealing with E1.33 Status Codes. - * Copyright (C) 2013 Simon Newton - */ - -#include -#include -#include "ola/e133/E133StatusHelper.h" - -namespace ola { -namespace e133 { - -using std::string; - -/** - * Verify that the int is a valid E1.33 Status Code. - */ -bool IntToStatusCode(uint16_t input, E133StatusCode *status_code) { - switch (input) { - case ola::e133::SC_E133_ACK: - *status_code = ola::e133::SC_E133_ACK; - return true; - case ola::e133::SC_E133_RDM_TIMEOUT: - *status_code = ola::e133::SC_E133_RDM_TIMEOUT; - return true; - case ola::e133::SC_E133_RDM_INVALID_RESPONSE: - *status_code = ola::e133::SC_E133_RDM_INVALID_RESPONSE; - return true; - case ola::e133::SC_E133_BUFFER_FULL: - *status_code = ola::e133::SC_E133_BUFFER_FULL; - return true; - case ola::e133::SC_E133_UNKNOWN_UID: - *status_code = ola::e133::SC_E133_UNKNOWN_UID; - return true; - case ola::e133::SC_E133_NONEXISTENT_ENDPOINT: - *status_code = ola::e133::SC_E133_NONEXISTENT_ENDPOINT; - return true; - case ola::e133::SC_E133_WRONG_ENDPOINT: - *status_code = ola::e133::SC_E133_WRONG_ENDPOINT; - return true; - case ola::e133::SC_E133_ACK_OVERFLOW_CACHE_EXPIRED: - *status_code = ola::e133::SC_E133_ACK_OVERFLOW_CACHE_EXPIRED; - return true; - case ola::e133::SC_E133_ACK_OVERFLOW_IN_PROGRESS: - *status_code = ola::e133::SC_E133_ACK_OVERFLOW_IN_PROGRESS; - return true; - case ola::e133::SC_E133_BROADCAST_COMPLETE: - *status_code = ola::e133::SC_E133_BROADCAST_COMPLETE; - return true; - default: - return false; - } -} - - -/** - * Return a text string describing this status code. - */ -string StatusCodeToString(E133StatusCode status_code) { - switch (status_code) { - case ola::e133::SC_E133_ACK: - return "Acknowledged"; - case ola::e133::SC_E133_RDM_TIMEOUT: - return "Response Timeout"; - case ola::e133::SC_E133_RDM_INVALID_RESPONSE: - return "Invalid Response"; - case ola::e133::SC_E133_BUFFER_FULL: - return "Buffer Full"; - case ola::e133::SC_E133_UNKNOWN_UID: - return "Unknown UID"; - case ola::e133::SC_E133_NONEXISTENT_ENDPOINT: - return "Endpoint doesn't exist"; - case ola::e133::SC_E133_WRONG_ENDPOINT: - return "Wrong endpoint"; - case ola::e133::SC_E133_ACK_OVERFLOW_CACHE_EXPIRED: - return "Ack overflow cache expired"; - case ola::e133::SC_E133_ACK_OVERFLOW_IN_PROGRESS: - return "Ack overflow in progress"; - case ola::e133::SC_E133_BROADCAST_COMPLETE: - return "Request was broadcast"; - } - return "Unknown E1.33 Status Code"; -} - - -bool IntToConnectStatusCode(uint16_t input, - E133ConnectStatusCode *connect_status_code) { - switch (input) { - case ola::e133::CONNECT_OK: - *connect_status_code = ola::e133::CONNECT_OK; - return true; - case ola::e133::CONNECT_SCOPE_MISMATCH: - *connect_status_code = ola::e133::CONNECT_SCOPE_MISMATCH; - return true; - case ola::e133::CONNECT_CAPACITY_EXCEEDED: - *connect_status_code = ola::e133::CONNECT_CAPACITY_EXCEEDED; - return true; - case ola::e133::CONNECT_DUPLICATE_UID: - *connect_status_code = ola::e133::CONNECT_DUPLICATE_UID; - return true; - case ola::e133::CONNECT_INVALID_CLIENT_ENTRY: - *connect_status_code = ola::e133::CONNECT_INVALID_CLIENT_ENTRY; - return true; - case ola::e133::CONNECT_INVALID_UID: - *connect_status_code = ola::e133::CONNECT_INVALID_UID; - return true; - default: - return false; - } -} - - -string ConnectStatusCodeToString(E133ConnectStatusCode connect_status_code) { - switch (connect_status_code) { - case ola::e133::CONNECT_OK: - return "Ok"; - case ola::e133::CONNECT_SCOPE_MISMATCH: - return "Scope mismatch"; - case ola::e133::CONNECT_CAPACITY_EXCEEDED: - return "Capacity exceeded"; - case ola::e133::CONNECT_DUPLICATE_UID: - return "Duplicate UID"; - case ola::e133::CONNECT_INVALID_CLIENT_ENTRY: - return "Invalid client entry"; - case ola::e133::CONNECT_INVALID_UID: - return "Invalid UID"; - } - return "Unknown E1.33 Connect Status Code"; -} -} // namespace e133 -} // namespace ola diff --git a/tools/e133/MessageBuilder.cpp b/tools/e133/MessageBuilder.cpp deleted file mode 100644 index 41d352539b..0000000000 --- a/tools/e133/MessageBuilder.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * MessageBuilder.cpp - * Copyright (C) 2013 Simon Newton - * - * A class to simplify some of the E1.33 packet building operations. - */ - -#include -#include "ola/acn/ACNVectors.h" -#include "ola/acn/CID.h" -#include "ola/e133/MessageBuilder.h" -#include "ola/io/IOStack.h" -#include "ola/rdm/RDMCommandSerializer.h" - -#include "libs/acn/BrokerPDU.h" -#include "libs/acn/E133PDU.h" -#include "libs/acn/RDMPDU.h" -#include "libs/acn/RootPDU.h" -#include "libs/acn/RPTPDU.h" -#include "libs/acn/RPTRequestPDU.h" -#include "libs/acn/E133StatusPDU.h" -#include "libs/acn/PreamblePacker.h" - -namespace ola { -namespace e133 { - -using ola::acn::CID; -using ola::io::IOStack; -using ola::acn::BrokerPDU; -using ola::acn::E133PDU; -using ola::acn::PreamblePacker; -using ola::acn::RootPDU; -using ola::acn::RPTPDU; - - -MessageBuilder::MessageBuilder(const CID &cid, const string &source_name) - : m_cid(cid), - m_source_name(source_name), - // The Max sized RDM packet is 256 bytes, E1.33 adds 118 bytes of - // headers. - m_memory_pool(400) { -} - - -/** - * Append a RDM PDU Header onto this packet - */ -void MessageBuilder::PrependRDMHeader(IOStack *packet) { - ola::acn::RDMPDU::PrependPDU(packet); -} - - -/** - * Build a TCP E1.33 RDM Command PDU response. - */ -void MessageBuilder::BuildTCPRDMCommandPDU(IOStack *packet, - ola::rdm::RDMRequest *request, - uint16_t source_endpoint_id, - uint16_t destination_endpoint_id, - uint32_t sequence_number) { - ola::rdm::RDMCommandSerializer::Write(*request, packet); - ola::acn::RDMPDU::PrependPDU(packet); - ola::acn::RPTRequestPDU::PrependPDU(packet); - RPTPDU::PrependPDU(packet, ola::acn::VECTOR_RPT_REQUEST, - request->SourceUID(), source_endpoint_id, - request->DestinationUID(), destination_endpoint_id, - sequence_number); - RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_RPT, m_cid, true); - PreamblePacker::AddTCPPreamble(packet); -} - - -/** - * Build a NULL TCP packet. These packets can be used for heartbeats. - */ -void MessageBuilder::BuildNullTCPPacket(IOStack *packet) { - RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_NULL, m_cid); - PreamblePacker::AddTCPPreamble(packet); -} - - -/** - * Build a Broker Fetch Client List TCP packet. - */ -void MessageBuilder::BuildBrokerFetchClientListTCPPacket(IOStack *packet) { - BrokerPDU::PrependPDU(packet, ola::acn::VECTOR_BROKER_FETCH_CLIENT_LIST); - RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_BROKER, m_cid, true); - PreamblePacker::AddTCPPreamble(packet); -} - - -/** - * Build a Broker NULL TCP packet. These packets can be used for broker heartbeats. - */ -void MessageBuilder::BuildBrokerNullTCPPacket(IOStack *packet) { - BrokerPDU::PrependPDU(packet, ola::acn::VECTOR_BROKER_NULL); - RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_BROKER, m_cid, true); - PreamblePacker::AddTCPPreamble(packet); -} - - -/** - * Build a TCP E1.33 Status PDU response. This should really only be used with - * SC_E133_ACK. - */ -void MessageBuilder::BuildTCPE133StatusPDU(ola::io::IOStack *packet, - uint32_t sequence_number, - uint16_t endpoint_id, - E133StatusCode status_code, - const string &description) { - ola::acn::E133StatusPDU::PrependPDU( - packet, status_code, description); - BuildTCPRootE133( - packet, ola::acn::VECTOR_FRAMING_STATUS, - sequence_number, endpoint_id); -} - - -/** - * Build an E1.33 Status PDU response - */ -void MessageBuilder::BuildUDPE133StatusPDU(ola::io::IOStack *packet, - uint32_t sequence_number, - uint16_t endpoint_id, - E133StatusCode status_code, - const string &description) { - ola::acn::E133StatusPDU::PrependPDU( - packet, status_code, description); - BuildUDPRootE133( - packet, ola::acn::VECTOR_FRAMING_STATUS, - sequence_number, endpoint_id); -} - - -/** - * Append an E133PDU, a RootPDU and the TCP preamble to a packet. - */ -void MessageBuilder::BuildTCPRootE133(IOStack *packet, - uint32_t vector, - uint32_t sequence_number, - uint16_t endpoint_id) { - E133PDU::PrependPDU(packet, vector, m_source_name, sequence_number, - endpoint_id); - RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_RPT, m_cid); - PreamblePacker::AddTCPPreamble(packet); -} - - -/** - * Append an E133PDU, a RootPDU and the UDP preamble to a packet. - */ -void MessageBuilder::BuildUDPRootE133(IOStack *packet, - uint32_t vector, - uint32_t sequence_number, - uint16_t endpoint_id) { - E133PDU::PrependPDU(packet, vector, m_source_name, sequence_number, - endpoint_id); - RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_RPT, m_cid); - PreamblePacker::AddUDPPreamble(packet); -} -} // namespace e133 -} // namespace ola From 33ea03fd6956a631b342dbe0ace8d17584f21e66 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 16 Mar 2024 17:11:48 +0000 Subject: [PATCH 086/138] Update the TCP header for ACN to match the released standards in TCPTransport --- libs/acn/TCPTransport.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/acn/TCPTransport.cpp b/libs/acn/TCPTransport.cpp index 5890f0c0ff..4060df25fa 100644 --- a/libs/acn/TCPTransport.cpp +++ b/libs/acn/TCPTransport.cpp @@ -31,8 +31,7 @@ namespace ola { namespace acn { const uint8_t ACN_HEADER[] = { - 0x00, 0x14, // preamble size - 0x00, 0x00, // post amble size + // No pre or post amble size for TCP 0x41, 0x53, 0x43, 0x2d, 0x45, 0x31, 0x2e, 0x31, 0x37, 0x00, 0x00, 0x00 From 0ea80e1e96361bfccb3e7fa34da58486b2d5eec2 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 16 Mar 2024 19:48:52 +0000 Subject: [PATCH 087/138] Work towards a new E1.33 plugin --- common/protocol/Ola.proto | 1 + configure.ac | 1 + olad/DynamicPluginLoader.cpp | 8 ++++++++ plugins/Makefile.mk | 1 + 4 files changed, 11 insertions(+) diff --git a/common/protocol/Ola.proto b/common/protocol/Ola.proto index 02896effa4..a1190add51 100644 --- a/common/protocol/Ola.proto +++ b/common/protocol/Ola.proto @@ -68,6 +68,7 @@ enum PluginIds { OLA_PLUGIN_GPIO = 22; OLA_PLUGIN_SPIDMX = 23; OLA_PLUGIN_NANOLEAF = 24; + OLA_PLUGIN_E133 = 25; /* * To obtain a new plugin ID, open a ticket at diff --git a/configure.ac b/configure.ac index 3e9e809afe..c54571a452 100644 --- a/configure.ac +++ b/configure.ac @@ -894,6 +894,7 @@ PLUGIN_SUPPORT(artnet, USE_ARTNET) PLUGIN_SUPPORT(dmx4linux, USE_DMX4LINUX, [$have_dmx4linux]) PLUGIN_SUPPORT(dummy, USE_DUMMY) PLUGIN_SUPPORT(e131, USE_E131) +PLUGIN_SUPPORT(e133, USE_E133) PLUGIN_SUPPORT(espnet, USE_ESPNET) PLUGIN_SUPPORT(ftdidmx, USE_FTDI, [$have_libftdi]) PLUGIN_SUPPORT(gpio, USE_GPIO) diff --git a/olad/DynamicPluginLoader.cpp b/olad/DynamicPluginLoader.cpp index d5b11e60ec..233df1eb69 100644 --- a/olad/DynamicPluginLoader.cpp +++ b/olad/DynamicPluginLoader.cpp @@ -39,6 +39,10 @@ #include "plugins/e131/E131Plugin.h" #endif // USE_E131 +#ifdef USE_E133 +#include "plugins/e133/E133Plugin.h" +#endif // USE_E133 + #ifdef USE_ESPNET #include "plugins/espnet/EspNetPlugin.h" #endif // USE_ESPNET @@ -159,6 +163,10 @@ void DynamicPluginLoader::PopulatePlugins() { m_plugins.push_back(new ola::plugin::e131::E131Plugin(m_plugin_adaptor)); #endif // USE_E131 +#ifdef USE_E133 + m_plugins.push_back(new ola::plugin::e133::E133Plugin(m_plugin_adaptor)); +#endif // USE_E133 + #ifdef USE_ESPNET m_plugins.push_back(new ola::plugin::espnet::EspNetPlugin(m_plugin_adaptor)); #endif // USE_ESPNET diff --git a/plugins/Makefile.mk b/plugins/Makefile.mk index b298128a1e..67e3e56ff9 100644 --- a/plugins/Makefile.mk +++ b/plugins/Makefile.mk @@ -23,6 +23,7 @@ if !USING_WIN32 include plugins/usbpro/Makefile.mk include plugins/dmx4linux/Makefile.mk include plugins/e131/Makefile.mk +include plugins/e133/Makefile.mk include plugins/uartdmx/Makefile.mk endif From 1a036f9766407d4997af114200ddd0d3f00f4983 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 16 Mar 2024 20:08:43 +0000 Subject: [PATCH 088/138] Some of the basics of the E1.33 plugin --- plugins/e133/E133Plugin.cpp | 185 ++++++++++++++++++++++++++++++++++++ plugins/e133/E133Plugin.h | 67 +++++++++++++ plugins/e133/Makefile.mk | 35 +++++++ plugins/e133/README.md | 26 +++++ 4 files changed, 313 insertions(+) create mode 100644 plugins/e133/E133Plugin.cpp create mode 100644 plugins/e133/E133Plugin.h create mode 100644 plugins/e133/Makefile.mk create mode 100644 plugins/e133/README.md diff --git a/plugins/e133/E133Plugin.cpp b/plugins/e133/E133Plugin.cpp new file mode 100644 index 0000000000..02018a957f --- /dev/null +++ b/plugins/e133/E133Plugin.cpp @@ -0,0 +1,185 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * E133Plugin.cpp + * The E1.33 plugin for ola + * Copyright (C) 2024 Peter Newman + */ + +#include +#include + +#include "ola/Logging.h" +#include "ola/network/NetworkUtils.h" +#include "ola/network/SocketAddress.h" +#include "ola/StringUtils.h" +#include "ola/acn/CID.h" +#include "olad/PluginAdaptor.h" +#include "olad/Preferences.h" +#include "plugins/e133/E133Device.h" +#include "plugins/e133/E133Plugin.h" +#include "plugins/e133/E133PluginDescription.h" + +namespace ola { +namespace plugin { +namespace e133 { + +using ola::acn::CID; +using ola::network::IPV4SocketAddress; +using std::string; + +const char E133Plugin::CID_KEY[] = "cid"; +const unsigned int E133Plugin::DEFAULT_DSCP_VALUE = 0; +const char E133Plugin::DSCP_KEY[] = "dscp"; +const char E133Plugin::INPUT_PORT_COUNT_KEY[] = "input_ports"; +const char E133Plugin::IP_KEY[] = "ip"; +const char E133Plugin::OUTPUT_PORT_COUNT_KEY[] = "output_ports"; +const char E133Plugin::PLUGIN_NAME[] = "E1.33 (RDMNet)"; +const char E133Plugin::PLUGIN_PREFIX[] = "e133"; +const char E133Plugin::PREPEND_HOSTNAME_KEY[] = "prepend_hostname"; +const char E133Plugin::TARGET_SOCKET_KEY[] = "target_socket"; +const unsigned int E133Plugin::DEFAULT_PORT_COUNT = 5; + + +/* + * Start the plugin + */ +bool E133Plugin::StartHook() { + CID cid = CID::FromString(m_preferences->GetValue(CID_KEY)); + string ip_addr = m_preferences->GetValue(IP_KEY); + + E133Device::E133DeviceOptions options; + if (m_preferences->GetValueAsBool(PREPEND_HOSTNAME_KEY)) { + std::ostringstream str; + str << ola::network::Hostname() << "-" << m_plugin_adaptor->InstanceName(); +// options.source_name = str.str(); + } else { +// options.source_name = m_plugin_adaptor->InstanceName(); + } + + unsigned int dscp; + if (!StringToInt(m_preferences->GetValue(DSCP_KEY), &dscp)) { + OLA_WARN << "Can't convert dscp value " << + m_preferences->GetValue(DSCP_KEY) << " to int"; +// options.dscp = 0; + } else { + // shift 2 bits left +// options.dscp = dscp << 2; + } + + if (!StringToInt(m_preferences->GetValue(INPUT_PORT_COUNT_KEY), + &options.input_ports)) { + OLA_WARN << "Invalid value for input_ports"; + } + + if (!StringToInt(m_preferences->GetValue(OUTPUT_PORT_COUNT_KEY), + &options.output_ports)) { + OLA_WARN << "Invalid value for output_ports"; + } + + IPV4SocketAddress socket_address; + if (!IPV4SocketAddress::FromString(m_preferences->GetValue(TARGET_SOCKET_KEY), &socket_address)) { + OLA_WARN << "Invalid value for " << TARGET_SOCKET_KEY; + } + + m_device = new E133Device(this, cid, ip_addr, socket_address, m_plugin_adaptor, options); + + if (!m_device->Start()) { + delete m_device; + return false; + } + + m_plugin_adaptor->RegisterDevice(m_device); + return true; +} + + +/* + * Stop the plugin + * @return true on success, false on failure + */ +bool E133Plugin::StopHook() { + if (m_device) { + m_plugin_adaptor->UnregisterDevice(m_device); + bool ret = m_device->Stop(); + delete m_device; + return ret; + } + return true; +} + + +/* + * Return the description for this plugin + */ +string E133Plugin::Description() const { + return plugin_description; +} + + +/* + * Load the plugin prefs and default to sensible values + * + */ +bool E133Plugin::SetDefaultPreferences() { + if (!m_preferences) + return false; + + bool save = false; + + CID cid = CID::FromString(m_preferences->GetValue(CID_KEY)); + if (cid.IsNil()) { + cid = CID::Generate(); + m_preferences->SetValue(CID_KEY, cid.ToString()); + save = true; + } + + save |= m_preferences->SetDefaultValue( + DSCP_KEY, + UIntValidator(0, 63), + DEFAULT_DSCP_VALUE); + + save |= m_preferences->SetDefaultValue( + INPUT_PORT_COUNT_KEY, + UIntValidator(0, 512), + DEFAULT_PORT_COUNT); + + save |= m_preferences->SetDefaultValue( + OUTPUT_PORT_COUNT_KEY, + UIntValidator(0, 512), + DEFAULT_PORT_COUNT); + + save |= m_preferences->SetDefaultValue(IP_KEY, StringValidator(true), ""); + + save |= m_preferences->SetDefaultValue( + PREPEND_HOSTNAME_KEY, + BoolValidator(), + true); + + IPV4SocketAddress socket_address; + if (!IPV4SocketAddress::FromString(m_preferences->GetValue(TARGET_SOCKET_KEY), &socket_address)) { + m_preferences->SetValue(TARGET_SOCKET_KEY, ""); + save = true; + } + + if (save) { + m_preferences->Save(); + } + + return true; +} +} // namespace e133 +} // namespace plugin +} // namespace ola diff --git a/plugins/e133/E133Plugin.h b/plugins/e133/E133Plugin.h new file mode 100644 index 0000000000..68059f302d --- /dev/null +++ b/plugins/e133/E133Plugin.h @@ -0,0 +1,67 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * E133Plugin.h + * Interface for the E1.33 plugin class + * Copyright (C) 2024 Peter Newman + */ + +#ifndef PLUGINS_E133_E133PLUGIN_H_ +#define PLUGINS_E133_E133PLUGIN_H_ + +#include +#include "olad/Plugin.h" +#include "ola/plugin_id.h" + +namespace ola { +namespace plugin { +namespace e133 { + +class E133Device; + +class E133Plugin: public ola::Plugin { + public: + explicit E133Plugin(ola::PluginAdaptor *plugin_adaptor): + ola::Plugin(plugin_adaptor), + m_device(NULL) {} + ~E133Plugin() {} + + std::string Name() const { return PLUGIN_NAME; } + ola_plugin_id Id() const { return OLA_PLUGIN_E133; } + std::string Description() const; + std::string PluginPrefix() const { return PLUGIN_PREFIX; } + + private: + bool StartHook(); + bool StopHook(); + bool SetDefaultPreferences(); + + E133Device *m_device; + static const char CID_KEY[]; + static const unsigned int DEFAULT_DSCP_VALUE; + static const unsigned int DEFAULT_PORT_COUNT; + static const char DSCP_KEY[]; + static const char INPUT_PORT_COUNT_KEY[]; + static const char IP_KEY[]; + static const char OUTPUT_PORT_COUNT_KEY[]; + static const char PLUGIN_NAME[]; + static const char PLUGIN_PREFIX[]; + static const char PREPEND_HOSTNAME_KEY[]; + static const char TARGET_SOCKET_KEY[]; +}; +} // namespace e133 +} // namespace plugin +} // namespace ola +#endif // PLUGINS_E133_E133PLUGIN_H_ diff --git a/plugins/e133/Makefile.mk b/plugins/e133/Makefile.mk new file mode 100644 index 0000000000..d64378a62c --- /dev/null +++ b/plugins/e133/Makefile.mk @@ -0,0 +1,35 @@ +# LIBRARIES +################################################## + +if USE_E133 +lib_LTLIBRARIES += plugins/e133/libolae133.la + +# Plugin description is generated from README.md +built_sources += plugins/e133/E133PluginDescription.h +nodist_plugins_e133_libolae133_la_SOURCES = \ + plugins/e133/E133PluginDescription.h +plugins/e133/E133PluginDescription.h: plugins/e133/README.md plugins/e133/Makefile.mk plugins/convert_README_to_header.sh + sh $(top_srcdir)/plugins/convert_README_to_header.sh $(top_srcdir)/plugins/e133 $(top_builddir)/plugins/e133/E133PluginDescription.h + +plugins_e133_libolae133_la_SOURCES = \ + plugins/e133/E133Device.cpp \ + plugins/e133/E133Device.h \ + plugins/e133/E133Plugin.cpp \ + plugins/e133/E133Plugin.h \ + plugins/e133/E133Port.cpp \ + plugins/e133/E133Port.h \ + plugins/e133/E133PortImpl.cpp \ + plugins/e133/E133PortImpl.h +plugins_e133_libolae133_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) $(uuid_CFLAGS) + +# plugins/e133/messages/libolae133conf.la +plugins_e133_libolae133_la_LIBADD = \ + $(uuid_LIBS) \ + common/libolacommon.la \ + olad/plugin_api/libolaserverplugininterface.la \ + libs/acn/libolaacn.la \ + libs/acn/libolae131core.la \ + libs/acn/libolae133core.la +endif + +EXTRA_DIST += plugins/e133/README.md diff --git a/plugins/e133/README.md b/plugins/e133/README.md new file mode 100644 index 0000000000..56ca954d07 --- /dev/null +++ b/plugins/e133/README.md @@ -0,0 +1,26 @@ +E1.33 (RDMNet) Plugin +===================================== + +This plugin creates a single device with a configurable number of input and +output ports. + +Each port can be assigned to a different E1.33 Universe. + + +## Config file: `ola-e133.conf` + +`cid = 00010203-0405-0607-0809-0A0B0C0D0E0F` +The CID to use for this device. + +#`dscp = [int]` +#The DSCP value to tag the packets with, range is 0 to 63. + +`input_ports = [int]` +The number of input ports to create up to an arbitrary max of 512. + +`ip = [a.b.c.d|]` +The IP address or interface name to bind to. If not specified it will use +the first non-loopback interface. + +`output_ports = [int]` +The number of output ports to create up to an arbitrary max of 512. From 2350e26e12045a85d531dd6972b535e5d2b68f36 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 17 Mar 2024 12:31:37 +0000 Subject: [PATCH 089/138] Add the BrokerConnectReplyInflator class and tests --- libs/acn/BrokerConnectReplyInflator.cpp | 76 +++++++++++++ libs/acn/BrokerConnectReplyInflator.h | 98 +++++++++++++++++ libs/acn/BrokerConnectReplyInflatorTest.cpp | 115 ++++++++++++++++++++ 3 files changed, 289 insertions(+) create mode 100644 libs/acn/BrokerConnectReplyInflator.cpp create mode 100644 libs/acn/BrokerConnectReplyInflator.h create mode 100644 libs/acn/BrokerConnectReplyInflatorTest.cpp diff --git a/libs/acn/BrokerConnectReplyInflator.cpp b/libs/acn/BrokerConnectReplyInflator.cpp new file mode 100644 index 0000000000..1e14393fe6 --- /dev/null +++ b/libs/acn/BrokerConnectReplyInflator.cpp @@ -0,0 +1,76 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerConnectReplyInflator.cpp + * The Inflator for BrokerConnectReply PDU + * Copyright (C) 2023 Peter Newman + */ + +#include +#include + +#include "ola/Logging.h" +#include "ola/network/NetworkUtils.h" +#include "ola/rdm/UID.h" +#include "libs/acn/BrokerConnectReplyInflator.h" + +namespace ola { +namespace acn { + +using ola::network::NetworkToHost; +using ola::rdm::UID; + +/** + * Set a BrokerConnectReplyHandler to run when receiving a Broker Connect Reply + * message. + * @param handler the callback to invoke when there is a Broker Connect Reply. + */ +void BrokerConnectReplyInflator::SetBrokerConnectReplyHandler( + BrokerConnectReplyHandler *handler) { + m_broker_connect_reply_handler.reset(handler); +} + +unsigned int BrokerConnectReplyInflator::InflatePDUBlock(HeaderSet *headers, + const uint8_t *data, + unsigned int len) { + broker_connect_reply_pdu_data pdu_data; + if (len > sizeof(pdu_data)) { + OLA_WARN << "Got too much data, received " << len << " only expecting " + << sizeof(pdu_data); + return 0; + } + + memcpy(reinterpret_cast(&pdu_data), data, sizeof(pdu_data)); + + OLA_DEBUG << "Connect reply from " << UID(pdu_data.broker_uid) << " for " + << UID(pdu_data.client_uid) << " with connection code " + << pdu_data.connection_code << " using E1.33 version " + << NetworkToHost(pdu_data.e133_version); + + BrokerConnectReply reply(pdu_data.connection_code, + NetworkToHost(pdu_data.e133_version), + UID(pdu_data.broker_uid), + UID(pdu_data.client_uid)); + + if (m_broker_connect_reply_handler.get()) { + m_broker_connect_reply_handler->Run(headers, + reply); + } else { + OLA_WARN << "No Broker Connect Reply handler defined!"; + } + return sizeof(pdu_data); +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/BrokerConnectReplyInflator.h b/libs/acn/BrokerConnectReplyInflator.h new file mode 100644 index 0000000000..ae8c647b35 --- /dev/null +++ b/libs/acn/BrokerConnectReplyInflator.h @@ -0,0 +1,98 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerConnectReplyInflator.h + * Interface for the BrokerConnectReplyInflator class. + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_BROKERCONNECTREPLYINFLATOR_H_ +#define LIBS_ACN_BROKERCONNECTREPLYINFLATOR_H_ + +#include "ola/Callback.h" +#include "ola/acn/ACNVectors.h" +#include "ola/rdm/UID.h" +#include "libs/acn/BaseInflator.h" + +namespace ola { +namespace acn { + +class BrokerConnectReplyInflator: public BaseInflator { + friend class BrokerConnectReplyInflatorTest; + + public: + struct BrokerConnectReply { + BrokerConnectReply(uint16_t _connection_code, + uint16_t _e133_version, + const ola::rdm::UID &_broker_uid, + const ola::rdm::UID &_client_uid) + : connection_code(_connection_code), + e133_version(_e133_version), + broker_uid(_broker_uid), + client_uid(_client_uid) { + } + uint16_t connection_code; + uint16_t e133_version; + ola::rdm::UID broker_uid; + ola::rdm::UID client_uid; + }; + + + // These are pointers so the callers don't have to pull in all the headers. + typedef ola::Callback2 BrokerConnectReplyHandler; + + BrokerConnectReplyInflator() + : BaseInflator() { + } + ~BrokerConnectReplyInflator() {} + + uint32_t Id() const { return ola::acn::VECTOR_BROKER_CONNECT_REPLY; } + + PACK( + struct broker_connect_reply_pdu_data_s { + uint16_t connection_code; + uint16_t e133_version; + uint8_t broker_uid[ola::rdm::UID::LENGTH]; + uint8_t client_uid[ola::rdm::UID::LENGTH]; + }); + typedef struct broker_connect_reply_pdu_data_s broker_connect_reply_pdu_data; + + void SetBrokerConnectReplyHandler(BrokerConnectReplyHandler *handler); + + protected: + // The 'header' is 0 bytes in length. + bool DecodeHeader(HeaderSet*, + const uint8_t*, + unsigned int, + unsigned int *bytes_used) { + *bytes_used = 0; + return true; + } + + void ResetHeaderField() {} // namespace noop + + unsigned int InflatePDUBlock(HeaderSet *headers, + const uint8_t *data, + unsigned int len); + + private: + std::auto_ptr m_broker_connect_reply_handler; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_BROKERCONNECTREPLYINFLATOR_H_ diff --git a/libs/acn/BrokerConnectReplyInflatorTest.cpp b/libs/acn/BrokerConnectReplyInflatorTest.cpp new file mode 100644 index 0000000000..99789fde31 --- /dev/null +++ b/libs/acn/BrokerConnectReplyInflatorTest.cpp @@ -0,0 +1,115 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerConectReplyInflatorTest.cpp + * Test fixture for the BrokerConnectReplyInflator class + * Copyright (C) 2023 Peter Newman + */ + +#include + +#include "ola/Logging.h" +#include "ola/network/NetworkUtils.h" +#include "libs/acn/HeaderSet.h" +#include "libs/acn/PDUTestCommon.h" +#include "libs/acn/BrokerInflator.h" +#include "libs/acn/BrokerPDU.h" +#include "ola/testing/TestUtils.h" + + +namespace ola { +namespace acn { + +using ola::network::HostToNetwork; + +class BrokerConnectReplyInflatorTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(BrokerConnectReplyInflatorTest); + CPPUNIT_TEST(testDecodeHeader); + CPPUNIT_TEST(testInflatePDU); + CPPUNIT_TEST_SUITE_END(); + + public: + void testDecodeHeader(); + void testInflatePDU(); + private: + static const uint8_t TEST_DATA[]; + static const uint8_t TEST_DATA2[]; +}; + +const uint8_t BrokerConnectReplyInflatorTest::TEST_DATA[] = {0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, + 11, 12, 13, 14, + 15}; +const uint8_t BrokerConnectReplyInflatorTest::TEST_DATA2[] = {10, 11, 12, 13, + 14, 15, 16, 17, + 18, 19, 20, 21, + 22, 23, 24, 25}; +CPPUNIT_TEST_SUITE_REGISTRATION(BrokerConnectReplyInflatorTest); + + +/* + * Check that we can decode headers properly + */ +void BrokerConnectReplyInflatorTest::testDecodeHeader() { + OLA_ASSERT(inflator.DecodeHeader(&header_set, + reinterpret_cast(&header), + sizeof(header), + &bytes_used)); + OLA_ASSERT_EQ((unsigned int) sizeof(header), bytes_used); + BrokerHeader decoded_header = header_set.GetBrokerHeader(); + + // try an undersized header + OLA_ASSERT_FALSE(inflator.DecodeHeader( + &header_set, + reinterpret_cast(&header), + static_cast(sizeof(header) - 1), + &bytes_used)); + OLA_ASSERT_EQ((unsigned int) 0, bytes_used); + + // test inheriting the header from the prev call + OLA_ASSERT(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); + OLA_ASSERT_EQ((unsigned int) 0, bytes_used); + decoded_header = header_set2.GetBrokerHeader(); + OLA_ASSERT(destination_cid == decoded_header.DestinationCid()); + OLA_ASSERT_EQ((uint32_t) 72650, decoded_header.TransactionNumber()); + + inflator.ResetHeaderField(); + OLA_ASSERT_FALSE(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); + OLA_ASSERT_EQ((unsigned int) 0, bytes_used); +} + + +/* + * Check that we can inflate a BrokerConnectReply PDU that contains other PDUs + */ +void BrokerConnectReplyInflatorTest::testInflatePDU() { + // TODO(Peter): pass a different type of msg here as well + BrokerConnectReplyPDU pdu(3, NULL); + OLA_ASSERT_EQ((unsigned int) 23, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ((unsigned int) size, bytes_used); + + BrokerConnectReplyInflator inflator; + HeaderSet header_set; + OLA_ASSERT(inflator.InflatePDUBlock(&header_set, data, size)); + // TODO(Peter): Test that the callback has the right data + delete[] data; +} +} // namespace acn +} // namespace ola From 7feb4c352c0b6ff45d13997e27b4c8ebaf8e6a1b Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 17 Mar 2024 13:02:14 +0000 Subject: [PATCH 090/138] Add the BrokerClientEntryRPTPDU class and tests --- libs/acn/BrokerClientEntryRPTPDU.cpp | 149 ++++++++++++++++++ libs/acn/BrokerClientEntryRPTPDU.h | 80 ++++++++++ libs/acn/BrokerClientEntryRPTPDUTest.cpp | 192 +++++++++++++++++++++++ 3 files changed, 421 insertions(+) create mode 100644 libs/acn/BrokerClientEntryRPTPDU.cpp create mode 100644 libs/acn/BrokerClientEntryRPTPDU.h create mode 100644 libs/acn/BrokerClientEntryRPTPDUTest.cpp diff --git a/libs/acn/BrokerClientEntryRPTPDU.cpp b/libs/acn/BrokerClientEntryRPTPDU.cpp new file mode 100644 index 0000000000..0937f5df8e --- /dev/null +++ b/libs/acn/BrokerClientEntryRPTPDU.cpp @@ -0,0 +1,149 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerClientEntryRPTPDU.cpp + * The BrokerClientEntryRPTPDU + * Copyright (C) 2023 Peter Newman + */ + + +#include "ola/Logging.h" +#include "ola/acn/CID.h" +#include "ola/base/Array.h" +#include "ola/network/NetworkUtils.h" +#include "ola/rdm/UID.h" +#include "libs/acn/BrokerClientEntryRPTPDU.h" +#include "libs/acn/BrokerClientEntryPDU.h" + +namespace ola { +namespace acn { + +using ola::acn::CID; +using ola::io::OutputStream; +using ola::network::HostToNetwork; +using ola::rdm::UID; + +/* + * Size of the header portion. + */ +unsigned int BrokerClientEntryRPTPDU::HeaderSize() const { + return sizeof(BrokerClientEntryHeader::broker_client_entry_pdu_header); +} + + +/* + * Size of the data portion + */ +unsigned int BrokerClientEntryRPTPDU::DataSize() const { + return sizeof(broker_client_entry_rpt_pdu_data); +} + + +/* + * Pack the header portion. + */ +bool BrokerClientEntryRPTPDU::PackHeader(uint8_t *data, + unsigned int *length) const { + unsigned int header_size = HeaderSize(); + + if (*length < header_size) { + OLA_WARN << "BrokerClientEntryRPTPDU::PackHeader: buffer too small, got " + << *length << " required " << header_size; + *length = 0; + return false; + } + + BrokerClientEntryHeader::broker_client_entry_pdu_header header; + m_header.ClientCid().Pack(header.client_cid); + *length = sizeof(BrokerClientEntryHeader::broker_client_entry_pdu_header); + memcpy(data, &header, *length); + return true; +} + + +/* + * Pack the data portion. + */ +bool BrokerClientEntryRPTPDU::PackData(uint8_t *data, + unsigned int *length) const { + unsigned int data_size = DataSize(); + + if (*length < data_size) { + OLA_WARN << "BrokerClientEntryRPTPDU::PackData: buffer too small, got " + << *length << " required " << data_size; + *length = 0; + return false; + } + + broker_client_entry_rpt_pdu_data pdu_data; + + m_client_uid.Pack(pdu_data.client_uid, sizeof(pdu_data.client_uid)); + pdu_data.rpt_client_type = m_rpt_client_type; + m_binding_cid.Pack(pdu_data.binding_cid); + + *length = sizeof(broker_client_entry_rpt_pdu_data); + memcpy(data, &pdu_data, *length); + return true; +} + + +/* + * Pack the header into a buffer. + */ +void BrokerClientEntryRPTPDU::PackHeader(OutputStream *stream) const { + BrokerClientEntryHeader::broker_client_entry_pdu_header header; + m_header.ClientCid().Pack(header.client_cid); + stream->Write( + reinterpret_cast(&header), + sizeof(BrokerClientEntryHeader::broker_client_entry_pdu_header)); +} + + +/* + * Pack the data into a buffer + */ +void BrokerClientEntryRPTPDU::PackData(OutputStream *stream) const { + broker_client_entry_rpt_pdu_data pdu_data; + + m_client_uid.Pack(pdu_data.client_uid, sizeof(pdu_data.client_uid)); + pdu_data.rpt_client_type = m_rpt_client_type; + m_binding_cid.Pack(pdu_data.binding_cid); + + stream->Write( + reinterpret_cast(&pdu_data), + static_cast(sizeof(broker_client_entry_rpt_pdu_data))); +} + + +void BrokerClientEntryRPTPDU::PrependPDU(ola::io::IOStack *stack, + uint32_t vector, + const ola::acn::CID &client_cid, + const ola::rdm::UID &client_uid, + uint8_t rpt_client_type, + const ola::acn::CID &binding_cid) { + broker_client_entry_rpt_pdu_data pdu_data; + + client_uid.Pack(pdu_data.client_uid, sizeof(pdu_data.client_uid)); + pdu_data.rpt_client_type = rpt_client_type; + binding_cid.Pack(pdu_data.binding_cid); + + stack->Write( + reinterpret_cast(&pdu_data), + static_cast(sizeof(broker_client_entry_rpt_pdu_data))); + + BrokerClientEntryPDU::PrependPDU(stack, vector, client_cid); +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/BrokerClientEntryRPTPDU.h b/libs/acn/BrokerClientEntryRPTPDU.h new file mode 100644 index 0000000000..277bab5146 --- /dev/null +++ b/libs/acn/BrokerClientEntryRPTPDU.h @@ -0,0 +1,80 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerClientEntryRPTPDU.h + * Interface for the BrokerClientEntryRPTPDU class + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_BROKERCLIENTENTRYRPTPDU_H_ +#define LIBS_ACN_BROKERCLIENTENTRYRPTPDU_H_ + +#include +#include +#include + +#include "libs/acn/PDU.h" +#include "libs/acn/BrokerClientEntryHeader.h" + +namespace ola { +namespace acn { + +class BrokerClientEntryRPTPDU: public PDU { + public: + BrokerClientEntryRPTPDU(unsigned int vector, + const BrokerClientEntryHeader &header, + const ola::rdm::UID &client_uid, + uint8_t rpt_client_type, + const ola::acn::CID &binding_cid): + PDU(vector, FOUR_BYTES, true), + m_header(header), + m_client_uid(client_uid), + m_rpt_client_type(rpt_client_type), + m_binding_cid(binding_cid) {} + ~BrokerClientEntryRPTPDU() {} + + unsigned int HeaderSize() const; + unsigned int DataSize() const; + bool PackHeader(uint8_t *data, unsigned int *length) const; + bool PackData(uint8_t *data, unsigned int *length) const; + + void PackHeader(ola::io::OutputStream *stream) const; + void PackData(ola::io::OutputStream *stream) const; + + static void PrependPDU(ola::io::IOStack *stack, + uint32_t vector, + const ola::acn::CID &client_cid, + const ola::rdm::UID &client_uid, + uint8_t rpt_client_type, + const ola::acn::CID &binding_cid); + + PACK( + struct broker_client_entry_rpt_pdu_data_s { + uint8_t client_uid[ola::rdm::UID::LENGTH]; + uint8_t rpt_client_type; + uint8_t binding_cid[ola::acn::CID::CID_LENGTH]; + }); + typedef struct broker_client_entry_rpt_pdu_data_s + broker_client_entry_rpt_pdu_data; + + private: + BrokerClientEntryHeader m_header; + ola::rdm::UID m_client_uid; + uint8_t m_rpt_client_type; + ola::acn::CID m_binding_cid; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_BROKERCLIENTENTRYRPTPDU_H_ diff --git a/libs/acn/BrokerClientEntryRPTPDUTest.cpp b/libs/acn/BrokerClientEntryRPTPDUTest.cpp new file mode 100644 index 0000000000..6390eb09ca --- /dev/null +++ b/libs/acn/BrokerClientEntryRPTPDUTest.cpp @@ -0,0 +1,192 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerClientEntryRPTPDUTest.cpp + * Test fixture for the BrokerClientEntryRPTPDU class + * Copyright (C) 2023 Peter Newman + */ + +#include + +#include "ola/Logging.h" +#include "ola/io/IOQueue.h" +#include "ola/io/IOStack.h" +#include "ola/io/OutputStream.h" +#include "ola/network/NetworkUtils.h" +#include "ola/testing/TestUtils.h" +#include "libs/acn/BrokerClientEntryRPTPDU.h" +#include "libs/acn/PDUTestCommon.h" + + +namespace ola { +namespace acn { + +using ola::io::IOQueue; +using ola::io::IOStack; +using ola::io::OutputStream; +using ola::network::HostToNetwork; +using ola::rdm::UID; + +class BrokerClientEntryRPTPDUTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(BrokerClientEntryRPTPDUTest); + CPPUNIT_TEST(testSimpleBrokerClientEntryRPTPDU); + CPPUNIT_TEST(testSimpleBrokerClientEntryRPTPDUToOutputStream); + CPPUNIT_TEST(testPrepend); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSimpleBrokerClientEntryRPTPDU(); + void testSimpleBrokerClientEntryRPTPDUToOutputStream(); + void testPrepend(); + + void setUp() { + ola::InitLogging(ola::OLA_LOG_DEBUG, ola::OLA_LOG_STDERR); + } + + private: + static const unsigned int TEST_VECTOR; + static const uint8_t TEST_DATA_1[]; + static const uint8_t TEST_DATA_2[]; +}; + +const uint8_t BrokerClientEntryRPTPDUTest::TEST_DATA_1[] = {0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15}; + +const uint8_t BrokerClientEntryRPTPDUTest::TEST_DATA_2[] = {16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, + 26, 27, 28, 29, + 30, 31}; + +CPPUNIT_TEST_SUITE_REGISTRATION(BrokerClientEntryRPTPDUTest); + +const unsigned int BrokerClientEntryRPTPDUTest::TEST_VECTOR = 39; + + +/* + * Test that packing a BrokerClientEntryRPTPDU without data works. + */ +void BrokerClientEntryRPTPDUTest::testSimpleBrokerClientEntryRPTPDU() { + const CID client_cid = CID::FromData(TEST_DATA_1); + const UID client_uid = UID(0x4321, 0x12345678); + const CID bounding_cid = CID::FromData(TEST_DATA_2); + BrokerClientEntryHeader header(client_cid); + BrokerClientEntryRPTPDU pdu(TEST_VECTOR, header, client_uid, 3, bounding_cid); + + OLA_ASSERT_EQ(16u, pdu.HeaderSize()); + OLA_ASSERT_EQ(23u, pdu.DataSize()); + OLA_ASSERT_EQ(46u, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + + // spot check the data + OLA_ASSERT_EQ((uint8_t) 0xf0, data[0]); + // bytes_used is technically data[1] and data[2] if > 255 + OLA_ASSERT_EQ((uint8_t) bytes_used, data[2]); + unsigned int actual_value; + memcpy(&actual_value, data + 3, sizeof(actual_value)); + OLA_ASSERT_EQ(HostToNetwork(TEST_VECTOR), actual_value); + + uint8_t buffer[CID::CID_LENGTH]; + client_cid.Pack(buffer); + OLA_ASSERT_DATA_EQUALS(&data[7], CID::CID_LENGTH, buffer, sizeof(buffer)); + + // test undersized buffer + bytes_used = size - 1; + OLA_ASSERT_FALSE(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(0u, bytes_used); + + // test oversized buffer + bytes_used = size + 1; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + delete[] data; +} + + +/* + * Test that writing to an output stream works. + */ +void BrokerClientEntryRPTPDUTest:: + testSimpleBrokerClientEntryRPTPDUToOutputStream() { + const ola::acn::CID client_cid = CID::FromData(TEST_DATA_1); + const UID client_uid = UID(0x4321, 0x12345678); + const CID bounding_cid = CID::FromData(TEST_DATA_2); + BrokerClientEntryHeader header(client_cid); + BrokerClientEntryRPTPDU pdu(TEST_VECTOR, header, client_uid, 3, bounding_cid); + + OLA_ASSERT_EQ(16u, pdu.HeaderSize()); + OLA_ASSERT_EQ(23u, pdu.DataSize()); + OLA_ASSERT_EQ(46u, pdu.Size()); + + IOQueue output; + OutputStream stream(&output); + pdu.Write(&stream); + OLA_ASSERT_EQ(46u, output.Size()); + + uint8_t *pdu_data = new uint8_t[output.Size()]; + unsigned int pdu_size = output.Peek(pdu_data, output.Size()); + OLA_ASSERT_EQ(output.Size(), pdu_size); + + uint8_t EXPECTED[] = { + 0xf0, 0x00, 0x2e, + 0, 0, 0, 39, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 0x43, 0x21, 0x12, 0x34, 0x56, 0x78, + 3, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31 + }; + OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), pdu_data, pdu_size); + output.Pop(output.Size()); + delete[] pdu_data; +} + +void BrokerClientEntryRPTPDUTest::testPrepend() { + const CID client_cid = CID::FromData(TEST_DATA_1); + const UID client_uid = UID(0x4321, 0x12345678); + const CID bounding_cid = CID::FromData(TEST_DATA_2); + IOStack stack; + BrokerClientEntryRPTPDU::PrependPDU(&stack, + TEST_VECTOR, + client_cid, + client_uid, + 3, + bounding_cid); + + unsigned int length = stack.Size(); + uint8_t *buffer = new uint8_t[length]; + OLA_ASSERT(stack.Read(buffer, length)); + + const uint8_t expected_data[] = { + 0xf0, 0x00, 0x2e, + 0, 0, 0, 39, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 0x43, 0x21, 0x12, 0x34, 0x56, 0x78, + 3, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31 + }; + OLA_ASSERT_DATA_EQUALS(expected_data, sizeof(expected_data), buffer, length); + delete[] buffer; +} +} // namespace acn +} // namespace ola From 93253cd4a0a64c35fdfc9e59a8c4d71ac011b2fd Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 17 Mar 2024 13:19:31 +0000 Subject: [PATCH 091/138] Fix a minor typo --- libs/acn/BrokerConnectReplyInflatorTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/acn/BrokerConnectReplyInflatorTest.cpp b/libs/acn/BrokerConnectReplyInflatorTest.cpp index 99789fde31..b042e67f13 100644 --- a/libs/acn/BrokerConnectReplyInflatorTest.cpp +++ b/libs/acn/BrokerConnectReplyInflatorTest.cpp @@ -13,7 +13,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * BrokerConectReplyInflatorTest.cpp + * BrokerConnectReplyInflatorTest.cpp * Test fixture for the BrokerConnectReplyInflator class * Copyright (C) 2023 Peter Newman */ From 773a4ad3051ec9785b126b98636c4a628ea62650 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 28 Mar 2024 15:40:13 +0000 Subject: [PATCH 092/138] Fix a broken merge --- libs/acn/Makefile.mk | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index 87077deec6..31184b5ced 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -38,20 +38,6 @@ noinst_LTLIBRARIES += libs/acn/libolae131core.la libs_acn_libolae131core_la_SOURCES = \ libs/acn/BaseInflator.cpp \ libs/acn/BaseInflator.h \ - libs/acn/BrokerClientAddInflator.h \ - libs/acn/BrokerClientEntryChangeInflator.h \ - libs/acn/BrokerClientEntryHeader.h \ - libs/acn/BrokerClientEntryPDU.cpp \ - libs/acn/BrokerClientEntryPDU.h \ - libs/acn/BrokerClientRemoveInflator.h \ - libs/acn/BrokerConnectPDU.cpp \ - libs/acn/BrokerConnectPDU.h \ - libs/acn/BrokerInflator.h \ - libs/acn/BrokerNullInflator.h \ - libs/acn/BrokerNullPDU.cpp \ - libs/acn/BrokerNullPDU.h \ - libs/acn/BrokerPDU.cpp \ - libs/acn/BrokerPDU.h \ libs/acn/DMPAddress.cpp \ libs/acn/DMPAddress.h \ libs/acn/DMPE131Inflator.cpp \ From 6ea9f016dae125e01226e9ed32a1ac1fdb649e8a Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 28 Mar 2024 18:22:58 +0000 Subject: [PATCH 093/138] Add more logging to a test and remove unnecessary includes --- libs/acn/BrokerNullPDUTest.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/acn/BrokerNullPDUTest.cpp b/libs/acn/BrokerNullPDUTest.cpp index 46fa712b50..6c90c4d907 100644 --- a/libs/acn/BrokerNullPDUTest.cpp +++ b/libs/acn/BrokerNullPDUTest.cpp @@ -19,8 +19,6 @@ */ #include -#include -#include #include "ola/Logging.h" #include "ola/io/IOQueue.h" @@ -52,6 +50,10 @@ class BrokerNullPDUTest: public CppUnit::TestFixture { void testSimpleBrokerNullPDUToOutputStream(); void testPrepend(); + void setUp() { + ola::InitLogging(ola::OLA_LOG_DEBUG, ola::OLA_LOG_STDERR); + } + private: static const uint16_t TEST_VECTOR; }; From d2940429d0949651cbce818c91ae888b5e55dc42 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 30 Mar 2024 11:39:22 +0000 Subject: [PATCH 094/138] Add some RPT Status handling helpers --- include/ola/e133/E133StatusHelper.h | 10 +++ libs/acn/E133StatusHelper.cpp | 99 +++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) diff --git a/include/ola/e133/E133StatusHelper.h b/include/ola/e133/E133StatusHelper.h index 7ca19412df..9d82ddc32b 100644 --- a/include/ola/e133/E133StatusHelper.h +++ b/include/ola/e133/E133StatusHelper.h @@ -22,15 +22,19 @@ #define INCLUDE_OLA_E133_E133STATUSHELPER_H_ #include +#include #include +#include #include namespace ola { namespace e133 { using std::string; +using ola::acn::RPTStatusVector; using ola::e133::E133StatusCode; using ola::e133::E133ConnectStatusCode; +using ola::rdm::RDMStatusCode; bool IntToStatusCode(uint16_t input, E133StatusCode *status_code); string StatusCodeToString(E133StatusCode status_code); @@ -38,6 +42,12 @@ string StatusCodeToString(E133StatusCode status_code); bool IntToConnectStatusCode(uint16_t input, E133ConnectStatusCode *connect_status_code); string ConnectStatusCodeToString(E133ConnectStatusCode connect_status_code); + +bool IntToRPTStatusCode(uint16_t input, + RPTStatusVector *rpt_status_code); +string RPTStatusCodeToString(RPTStatusVector rpt_status_code); +bool RPTStatusCodeToRDMStatusCode(RPTStatusVector rpt_status_code, + RDMStatusCode *rdm_status_code); } // namespace e133 } // namespace ola #endif // INCLUDE_OLA_E133_E133STATUSHELPER_H_ diff --git a/libs/acn/E133StatusHelper.cpp b/libs/acn/E133StatusHelper.cpp index a1ec71627c..3edcd7889d 100644 --- a/libs/acn/E133StatusHelper.cpp +++ b/libs/acn/E133StatusHelper.cpp @@ -25,6 +25,7 @@ namespace ola { namespace e133 { +using ola::rdm::RDMStatusCode; using std::string; /** @@ -142,5 +143,103 @@ string ConnectStatusCodeToString(E133ConnectStatusCode connect_status_code) { } return "Unknown E1.33 Connect Status Code"; } + + +bool IntToRPTStatusCode(uint16_t input, + RPTStatusVector *rpt_status_code) { + switch (input) { + case ola::acn::VECTOR_RPT_STATUS_UNKNOWN_RPT_UID: + *rpt_status_code = ola::acn::VECTOR_RPT_STATUS_UNKNOWN_RPT_UID; + return true; + case ola::acn::VECTOR_RPT_STATUS_RDM_TIMEOUT: + *rpt_status_code = ola::acn::VECTOR_RPT_STATUS_RDM_TIMEOUT; + return true; + case ola::acn::VECTOR_RPT_STATUS_RDM_INVALID_RESPONSE: + *rpt_status_code = ola::acn::VECTOR_RPT_STATUS_RDM_INVALID_RESPONSE; + return true; + case ola::acn::VECTOR_RPT_STATUS_UNKNOWN_RDM_UID: + *rpt_status_code = ola::acn::VECTOR_RPT_STATUS_UNKNOWN_RDM_UID; + return true; + case ola::acn::VECTOR_RPT_STATUS_UNKNOWN_ENDPOINT: + *rpt_status_code = ola::acn::VECTOR_RPT_STATUS_UNKNOWN_ENDPOINT; + return true; + case ola::acn::VECTOR_RPT_STATUS_BROADCAST_COMPLETE: + *rpt_status_code = ola::acn::VECTOR_RPT_STATUS_BROADCAST_COMPLETE; + return true; + case ola::acn::VECTOR_RPT_STATUS_UNKNOWN_VECTOR: + *rpt_status_code = ola::acn::VECTOR_RPT_STATUS_UNKNOWN_VECTOR; + return true; + case ola::acn::VECTOR_RPT_STATUS_INVALID_MESSAGE: + *rpt_status_code = ola::acn::VECTOR_RPT_STATUS_INVALID_MESSAGE; + return true; + case ola::acn::VECTOR_RPT_STATUS_INVALID_COMMAND_CLASS: + *rpt_status_code = ola::acn::VECTOR_RPT_STATUS_INVALID_COMMAND_CLASS; + return true; + default: + return false; + } +} + + +string RPTStatusCodeToString(RPTStatusVector rpt_status_code) { + switch (rpt_status_code) { + case ola::acn::VECTOR_RPT_STATUS_UNKNOWN_RPT_UID: + return "Unknown RPT UID"; + case ola::acn::VECTOR_RPT_STATUS_RDM_TIMEOUT: + return "RDM Timeout"; + case ola::acn::VECTOR_RPT_STATUS_RDM_INVALID_RESPONSE: + return "RDM Invalid Response"; + case ola::acn::VECTOR_RPT_STATUS_UNKNOWN_RDM_UID: + return "Unknown RDM UID"; + case ola::acn::VECTOR_RPT_STATUS_UNKNOWN_ENDPOINT: + return "Unknown Endpoint"; + case ola::acn::VECTOR_RPT_STATUS_BROADCAST_COMPLETE: + return "Broadcast Complete"; + case ola::acn::VECTOR_RPT_STATUS_UNKNOWN_VECTOR: + return "Unknown Vector"; + case ola::acn::VECTOR_RPT_STATUS_INVALID_MESSAGE: + return "Invalid Message"; + case ola::acn::VECTOR_RPT_STATUS_INVALID_COMMAND_CLASS: + return "Invalid Command Class"; + } + return "Unknown E1.33 RPT Status Code"; +} + + +bool RPTStatusCodeToRDMStatusCode(RPTStatusVector rpt_status_code, + RDMStatusCode *rdm_status_code) { + // TODO(Peter): Fill in the gaps, possibly adding other RDMStatusCodes if required + switch (rpt_status_code) { +// case ola::acn::VECTOR_RPT_STATUS_UNKNOWN_RPT_UID: +// *rdm_status_code = ola::rdm::; +// return true; + case ola::acn::VECTOR_RPT_STATUS_RDM_TIMEOUT: + *rdm_status_code = ola::rdm::RDM_TIMEOUT; + return true; + case ola::acn::VECTOR_RPT_STATUS_RDM_INVALID_RESPONSE: + *rdm_status_code = ola::rdm::RDM_INVALID_RESPONSE; + return true; + case ola::acn::VECTOR_RPT_STATUS_UNKNOWN_RDM_UID: + *rdm_status_code = ola::rdm::RDM_UNKNOWN_UID; + return true; +// case ola::acn::VECTOR_RPT_STATUS_UNKNOWN_ENDPOINT: +// *rdm_status_code = ola::rdm::; +// return true; + case ola::acn::VECTOR_RPT_STATUS_BROADCAST_COMPLETE: + *rdm_status_code = ola::rdm::RDM_WAS_BROADCAST; + return true; +// case ola::acn::VECTOR_RPT_STATUS_UNKNOWN_VECTOR: +// *rdm_status_code = ola::rdm::; +// return true; +// case ola::acn::VECTOR_RPT_STATUS_INVALID_MESSAGE: +// *rdm_status_code = ola::rdm::; +// return true; + case ola::acn::VECTOR_RPT_STATUS_INVALID_COMMAND_CLASS: + *rdm_status_code = ola::rdm::RDM_INVALID_COMMAND_CLASS; + return true; + default: + return false; + } +} } // namespace e133 } // namespace ola From d1cbab9d16cea82566a01498a16e090949f77607 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 30 Mar 2024 15:39:27 +0000 Subject: [PATCH 095/138] Move more stuff to the E1.33 lib and fix the LLRP build --- libs/acn/Makefile.mk | 68 ++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index 31184b5ced..9a9d3e434b 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -59,28 +59,11 @@ libs_acn_libolae131core_la_SOURCES = \ libs/acn/E131Sender.cpp \ libs/acn/E131Sender.h \ libs/acn/HeaderSet.h \ - libs/acn/LLRPHeader.h \ - libs/acn/LLRPInflator.cpp \ - libs/acn/LLRPInflator.h \ - libs/acn/LLRPProbeReplyInflator.cpp \ - libs/acn/LLRPProbeReplyInflator.h \ - libs/acn/LLRPProbeReplyPDU.cpp \ - libs/acn/LLRPProbeReplyPDU.h \ - libs/acn/LLRPProbeRequestInflator.cpp \ - libs/acn/LLRPProbeRequestInflator.h \ - libs/acn/LLRPProbeRequestPDU.cpp \ - libs/acn/LLRPProbeRequestPDU.h \ - libs/acn/LLRPPDU.cpp \ - libs/acn/LLRPPDU.h \ libs/acn/PDU.cpp \ libs/acn/PDU.h \ libs/acn/PDUTestCommon.h \ libs/acn/PreamblePacker.cpp \ libs/acn/PreamblePacker.h \ - libs/acn/RDMInflator.cpp \ - libs/acn/RDMInflator.h \ - libs/acn/RDMPDU.cpp \ - libs/acn/RDMPDU.h \ libs/acn/RootHeader.h \ libs/acn/RootInflator.cpp \ libs/acn/RootInflator.h \ @@ -88,15 +71,6 @@ libs_acn_libolae131core_la_SOURCES = \ libs/acn/RootPDU.h \ libs/acn/RootSender.cpp \ libs/acn/RootSender.h \ - libs/acn/RPTHeader.h \ - libs/acn/RPTInflator.cpp \ - libs/acn/RPTInflator.h \ - libs/acn/RPTNotificationInflator.h \ - libs/acn/RPTPDU.cpp \ - libs/acn/RPTPDU.h \ - libs/acn/RPTRequestInflator.h \ - libs/acn/RPTRequestPDU.cpp \ - libs/acn/RPTRequestPDU.h \ libs/acn/TCPTransport.cpp \ libs/acn/TCPTransport.h \ libs/acn/Transport.h \ @@ -156,7 +130,35 @@ libs_acn_libolae133core_la_SOURCES = \ libs/acn/E133StatusInflator.h \ libs/acn/E133StatusPDU.cpp \ libs/acn/E133StatusPDU.h \ - libs/acn/MessageBuilder.cpp + libs/acn/LLRPHeader.h \ + libs/acn/LLRPInflator.cpp \ + libs/acn/LLRPInflator.h \ + libs/acn/LLRPProbeReplyInflator.cpp \ + libs/acn/LLRPProbeReplyInflator.h \ + libs/acn/LLRPProbeReplyPDU.cpp \ + libs/acn/LLRPProbeReplyPDU.h \ + libs/acn/LLRPProbeRequestInflator.cpp \ + libs/acn/LLRPProbeRequestInflator.h \ + libs/acn/LLRPProbeRequestPDU.cpp \ + libs/acn/LLRPProbeRequestPDU.h \ + libs/acn/LLRPPDU.cpp \ + libs/acn/LLRPPDU.h \ + libs/acn/MessageBuilder.cpp \ + libs/acn/RDMInflator.cpp \ + libs/acn/RDMInflator.h \ + libs/acn/RDMPDU.cpp \ + libs/acn/RDMPDU.h \ + libs/acn/RPTHeader.h \ + libs/acn/RPTInflator.cpp \ + libs/acn/RPTInflator.h \ + libs/acn/RPTNotificationInflator.h \ + libs/acn/RPTPDU.cpp \ + libs/acn/RPTPDU.h \ + libs/acn/RPTRequestInflator.h \ + libs/acn/RPTRequestPDU.cpp \ + libs/acn/RPTRequestPDU.h \ + libs/acn/RPTStatusInflator.cpp \ + libs/acn/RPTStatusInflator.h libs_acn_libolae133core_la_CXXFLAGS = \ $(COMMON_E133_CXXFLAGS) $(uuid_CFLAGS) @@ -208,6 +210,7 @@ libs_acn_E131Tester_LDADD = \ $(COMMON_TESTING_LIBS) # libs/acn/BrokerInflatorTest.cpp +# libs/acn/BrokerClientEntryRPTInflatorTest.cpp libs_acn_E133Tester_SOURCES = \ libs/acn/BrokerClientEntryPDUTest.cpp \ libs/acn/BrokerClientEntryRPTPDUTest.cpp \ @@ -236,16 +239,7 @@ libs_acn_LLRPTester_SOURCES = \ libs_acn_LLRPTester_CPPFLAGS = $(COMMON_TESTING_FLAGS) libs_acn_LLRPTester_LDADD = \ libs/acn/libolae131core.la \ - $(COMMON_TESTING_LIBS) - -libs_acn_LLRPTester_SOURCES = \ - libs/acn/LLRPInflatorTest.cpp \ - libs/acn/LLRPPDUTest.cpp \ - libs/acn/LLRPProbeReplyPDUTest.cpp \ - libs/acn/LLRPProbeRequestPDUTest.cpp -libs_acn_LLRPTester_CPPFLAGS = $(COMMON_TESTING_FLAGS) -libs_acn_LLRPTester_LDADD = \ - libs/acn/libolae131core.la \ + libs/acn/libolae133core.la \ $(COMMON_TESTING_LIBS) libs_acn_TransportTester_SOURCES = \ From d4378b94e50d96df90313cdf12fcee8a19dcf4bd Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 30 Mar 2024 18:29:28 +0000 Subject: [PATCH 096/138] Fix a typo --- tools/e133/E133Endpoint.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/e133/E133Endpoint.h b/tools/e133/E133Endpoint.h index cbcc1cb3d6..d57a6830f1 100644 --- a/tools/e133/E133Endpoint.h +++ b/tools/e133/E133Endpoint.h @@ -96,7 +96,7 @@ class E133EndpointInterface /** * An E133Endpoint which wraps another RDM controller. This just passes - * everything through the to controller. + * everything through to the controller. */ class E133Endpoint: public E133EndpointInterface { public: From e1e94e3578a129504c3e953c19cc5415051232d3 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 30 Mar 2024 22:28:25 +0000 Subject: [PATCH 097/138] Add more E1.33 Enums --- include/ola/e133/E133Enums.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/ola/e133/E133Enums.h b/include/ola/e133/E133Enums.h index 2bf81d75b0..e242a163f2 100644 --- a/include/ola/e133/E133Enums.h +++ b/include/ola/e133/E133Enums.h @@ -24,6 +24,12 @@ namespace ola { namespace e133 { +// Appendix A - Endpoints and Table 3-1: Endpoint ID Allocation +static const uint16_t NULL_ENDPOINT = 0x0000; +static const uint16_t MIN_DEVICE_ENDPOINT = 0x0001; +static const uint16_t MAX_DEVICE_ENDPOINT = 0xF9FF; +static const uint16_t BROADCAST_ENDPOINT = 0xFFFF; + // Table A-6, Discovery Stats enum DiscoveryState { DISCOVERY_INCOMPLETE = 0, From d9764669872b6717fc87cf2812738209a3a0f957 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 30 Mar 2024 22:38:37 +0000 Subject: [PATCH 098/138] Add some RPT UID functionality and more tests --- common/rdm/UIDTest.cpp | 58 +++++++++++++++++++++++++++++++++++++ include/ola/rdm/UID.h | 66 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 123 insertions(+), 1 deletion(-) diff --git a/common/rdm/UIDTest.cpp b/common/rdm/UIDTest.cpp index 3a114150d3..9949fb9e43 100644 --- a/common/rdm/UIDTest.cpp +++ b/common/rdm/UIDTest.cpp @@ -34,6 +34,7 @@ using ola::rdm::UIDSet; class UIDTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(UIDTest); CPPUNIT_TEST(testUID); + CPPUNIT_TEST(testRPTUID); CPPUNIT_TEST(testUIDInequalities); CPPUNIT_TEST(testUIDSet); CPPUNIT_TEST(testUIDSetUnion); @@ -43,6 +44,7 @@ class UIDTest: public CppUnit::TestFixture { public: void testUID(); + void testRPTUID(); void testUIDInequalities(); void testUIDSet(); void testUIDSetUnion(); @@ -58,6 +60,8 @@ CPPUNIT_TEST_SUITE_REGISTRATION(UIDTest); */ void UIDTest::testUID() { UID uid(1, 2); + OLA_ASSERT_FALSE(uid.IsBroadcast()); + OLA_ASSERT_FALSE(uid.IsVendorcast()); UID uid2 = uid; OLA_ASSERT_EQ(uid, uid2); OLA_ASSERT_FALSE(uid != uid2); @@ -84,9 +88,12 @@ void UIDTest::testUID() { UID all_devices = UID::AllDevices(); UID manufacturer_devices = UID::VendorcastAddress(0x52); + UID manufacturer_devices2 = UID::VendorcastAddress(uid); OLA_ASSERT_EQ(string("ffff:ffffffff"), all_devices.ToString()); OLA_ASSERT_EQ(string("0052:ffffffff"), manufacturer_devices.ToString()); + OLA_ASSERT_EQ(string("0001:ffffffff"), + manufacturer_devices2.ToString()); OLA_ASSERT_EQ(all_devices.ManufacturerId(), static_cast(0xffff)); OLA_ASSERT_EQ(all_devices.DeviceId(), @@ -95,8 +102,16 @@ void UIDTest::testUID() { static_cast(0x0052)); OLA_ASSERT_EQ(manufacturer_devices.DeviceId(), static_cast(0xffffffff)); + OLA_ASSERT_EQ(manufacturer_devices2.ManufacturerId(), + static_cast(0x0001)); + OLA_ASSERT_EQ(manufacturer_devices2.DeviceId(), + static_cast(0xffffffff)); OLA_ASSERT_TRUE(all_devices.IsBroadcast()); + OLA_ASSERT_FALSE(all_devices.IsVendorcast()); OLA_ASSERT_TRUE(manufacturer_devices.IsBroadcast()); + OLA_ASSERT_TRUE(manufacturer_devices.IsVendorcast()); + OLA_ASSERT_TRUE(manufacturer_devices2.IsBroadcast()); + OLA_ASSERT_TRUE(manufacturer_devices2.IsVendorcast()); // now test the packing & unpacking unsigned int buffer_size = UID::UID_SIZE; @@ -118,6 +133,49 @@ void UIDTest::testUID() { } +/* + * Test the RPT UIDs work. + */ +void UIDTest::testRPTUID() { + UID uid(1, 2); + UID rpt_all_controllers = UID::RPTAllControllers(); + UID rpt_all_devices = UID::RPTAllDevices(); + UID rpt_manufacturer_devices = UID::RPTVendorcastAddressDevices(0x52); + UID rpt_manufacturer_devices2 = UID::RPTVendorcastAddressDevices(uid); + OLA_ASSERT_EQ(string("fffc:ffffffff"), rpt_all_controllers.ToString()); + OLA_ASSERT_EQ(string("fffd:ffffffff"), rpt_all_devices.ToString()); + OLA_ASSERT_EQ(string("fffd:0052ffff"), + rpt_manufacturer_devices.ToString()); + OLA_ASSERT_EQ(string("fffd:0001ffff"), + rpt_manufacturer_devices2.ToString()); + OLA_ASSERT_EQ(rpt_all_controllers.ManufacturerId(), + static_cast(0xfffc)); + OLA_ASSERT_EQ(rpt_all_controllers.DeviceId(), + static_cast(0xffffffff)); + OLA_ASSERT_EQ(rpt_all_devices.ManufacturerId(), + static_cast(0xfffd)); + OLA_ASSERT_EQ(rpt_all_devices.DeviceId(), + static_cast(0xffffffff)); + OLA_ASSERT_EQ(rpt_manufacturer_devices.ManufacturerId(), + static_cast(0xfffd)); + OLA_ASSERT_EQ(rpt_manufacturer_devices.DeviceId(), + static_cast(0x0052ffff)); + OLA_ASSERT_EQ(rpt_manufacturer_devices2.ManufacturerId(), + static_cast(0xfffd)); + OLA_ASSERT_EQ(rpt_manufacturer_devices2.DeviceId(), + static_cast(0x0001ffff)); + OLA_ASSERT_TRUE(rpt_all_controllers.IsBroadcast()); + OLA_ASSERT_FALSE(rpt_all_controllers.IsVendorcast()); + OLA_ASSERT_TRUE(rpt_all_devices.IsBroadcast()); + OLA_ASSERT_FALSE(rpt_all_devices.IsVendorcast()); + // TODO(Peter): Handle the more complicated RPT vendorcast tests + // OLA_ASSERT_TRUE(rpt_manufacturer_devices.IsBroadcast()); + // OLA_ASSERT_TRUE(rpt_manufacturer_devices.IsVendorcast()); + // OLA_ASSERT_TRUE(rpt_manufacturer_devices2.IsBroadcast()); + // OLA_ASSERT_TRUE(rpt_manufacturer_devices2.IsVendorcast()); +} + + /* * Test the UIDs inequalities work */ diff --git a/include/ola/rdm/UID.h b/include/ola/rdm/UID.h index dc1ff4c982..fb2defd87b 100644 --- a/include/ola/rdm/UID.h +++ b/include/ola/rdm/UID.h @@ -174,6 +174,16 @@ class UID { */ bool IsBroadcast() const { return m_uid.device_id == ALL_DEVICES; } + /** + * @brief Check if this UID is a vendorcast UID. + * @returns true if the manufacturer id is not 0xffff and the device id is + * 0xffffffff. + */ + bool IsVendorcast() const { + return ((m_uid.esta_id != ALL_MANUFACTURERS) && + (m_uid.device_id == ALL_DEVICES)); + } + /** * @brief Check if this UID matches against another. * @param uid the UID to check against @@ -260,7 +270,7 @@ class UID { /** * @brief Returns a UID that matches all devices for a particular - * manufacturer. + * manufacturer. * @param esta_id the manufacturer id of the devices to match. * @returns a UID(X, 0xffffffff). */ @@ -278,6 +288,44 @@ class UID { return UID(uid.ManufacturerId(), ALL_DEVICES); } + /** + * @brief Returns a UID that matches all RPT controllers (fffc:ffffffff). + * @returns a UID(0xfffc, 0xffffffff). + */ + static UID RPTAllControllers() { + return UID(RPT_ALL_CONTROLLERS_MANUFACTURER, ALL_DEVICES); + } + + /** + * @brief Returns a UID that matches all RPT devices (fffd:ffffffff). + * @returns a UID(0xfffd, 0xffffffff). + */ + static UID RPTAllDevices() { + return UID(RPT_ALL_DEVICES_MANUFACTURER, ALL_DEVICES); + } + + /** + * @brief Returns a UID that matches all RPT devices for a particular + * manufacturer. + * @param esta_id the manufacturer id of the devices to match. + * @returns a UID(0xfffd, 0xXXXXffff). + */ + static UID RPTVendorcastAddressDevices(uint16_t esta_id) { + return UID(RPT_ALL_DEVICES_MANUFACTURER, + RPTVendorcastDevicesDeviceId(esta_id)); + } + + /** + * @brief Returns a UID that matches all RPT devices for a particular + * manufacturer. + * @param uid a UID whose manufacturer id you want to match. + * @returns a UID(0xfffd, 0xXXXXffff). + */ + static UID RPTVendorcastAddressDevices(UID uid) { + return UID(RPT_ALL_DEVICES_MANUFACTURER, + RPTVendorcastDevicesDeviceId(uid.ManufacturerId())); + } + /** * @brief Return a new UID from a string. * @param uid the UID as a string i.e. XXXX:YYYYYYYY. @@ -300,9 +348,21 @@ class UID { /** * @brief The value for the 'all devices' id. + * + * This is also the value for RPT all controllers and all devices. */ static const uint32_t ALL_DEVICES = 0xffffffff; + /** + * @brief The value for the RPT 'all controllers' manufacturer. + */ + static const uint16_t RPT_ALL_CONTROLLERS_MANUFACTURER = 0xfffc; + + /** + * @brief The value for the RPT 'all devices' manufacturer. + */ + static const uint16_t RPT_ALL_DEVICES_MANUFACTURER = 0xfffd; + private: struct rdm_uid { uint16_t esta_id; @@ -324,6 +384,10 @@ class UID { } return a < b ? -1 : 1; } + + static uint32_t RPTVendorcastDevicesDeviceId(uint16_t esta_id) { + return ((static_cast(esta_id) << 16) | 0xffff); + } }; } // namespace rdm } // namespace ola From a5ddef03753a02bec11ecdfe8ca622c2e5bfc49f Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 1 Apr 2024 00:35:10 +0100 Subject: [PATCH 099/138] Add a first version of the RPTStatusInflator. Still needs some tests added... --- libs/acn/RPTStatusInflator.cpp | 94 ++++++++++++++++++++++++++++++++++ libs/acn/RPTStatusInflator.h | 72 ++++++++++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 libs/acn/RPTStatusInflator.cpp create mode 100644 libs/acn/RPTStatusInflator.h diff --git a/libs/acn/RPTStatusInflator.cpp b/libs/acn/RPTStatusInflator.cpp new file mode 100644 index 0000000000..83cb2d9eb6 --- /dev/null +++ b/libs/acn/RPTStatusInflator.cpp @@ -0,0 +1,94 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * RPTStatusInflator.cpp + * The Inflator for the RPT Status PDUs + * Copyright (C) 2024 Peter Newman + */ + +#include +#include +#include "ola/Logging.h" +#include "ola/e133/E133StatusHelper.h" +#include "libs/acn/RPTStatusInflator.h" + +namespace ola { +namespace acn { + +using std::string; + +/** + * Create a new RPT Status inflator + */ +RPTStatusInflator::RPTStatusInflator() + : BaseInflator(PDU::TWO_BYTES) { +} + +/** + * Set an RPTStatusHandler to run when receiving an RPT Status message. + * @param handler the callback to invoke when there is an RPT status message. + */ +void RPTStatusInflator::SetRPTStatusHandler(RPTStatusHandler *handler) { + m_rpt_status_handler.reset(handler); +} + + +/* + * Decode the RPT Status 'header', which is 0 bytes in length. + * @param headers the HeaderSet to add to + * @param data a pointer to the data + * @param length length of the data + * @returns true if successful, false otherwise + */ +bool RPTStatusInflator::DecodeHeader(HeaderSet *, + const uint8_t*, + unsigned int, + unsigned int *bytes_used) { + *bytes_used = 0; + return true; +} + + +/* + * Handle an RPT Status PDU for E1.33. + */ +bool RPTStatusInflator::HandlePDUData(uint32_t vector, + OLA_UNUSED const HeaderSet &headers, + OLA_UNUSED const uint8_t *data, + OLA_UNUSED unsigned int pdu_len) { + ola::acn::RPTStatusVector status_vector; + if (!ola::e133::IntToRPTStatusCode(static_cast(vector), + &status_vector)) { + OLA_WARN << "Unknown RPT status message vector was " << vector; + return true; + } else { + OLA_INFO << "RPT status message vector was " + << ola::e133::RPTStatusCodeToString(status_vector); + } + // TODO(Peter): Handle the optional string message for the vectors that can + // have it/alert for those that can't if they do + + if (m_rpt_status_handler.get()) { + E133Header e133_header = headers.GetE133Header(); + + m_rpt_status_handler->Run(&headers.GetTransportHeader(), &e133_header, + status_vector, ""); + } else { + OLA_WARN << "No RPT Status handler defined!"; + } + return true; +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/RPTStatusInflator.h b/libs/acn/RPTStatusInflator.h new file mode 100644 index 0000000000..85c0946030 --- /dev/null +++ b/libs/acn/RPTStatusInflator.h @@ -0,0 +1,72 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * RPTStatusInflator.h + * Interface for the RPTStatusInflator class. + * Copyright (C) 2024 Peter Newman + */ + +#ifndef LIBS_ACN_RPTSTATUSINFLATOR_H_ +#define LIBS_ACN_RPTSTATUSINFLATOR_H_ + +#include +#include "ola/Callback.h" +#include "ola/acn/ACNVectors.h" +#include "libs/acn/BaseInflator.h" +#include "libs/acn/TransportHeader.h" +#include "libs/acn/E133Header.h" + +namespace ola { +namespace acn { + +class RPTStatusInflator: public BaseInflator { + friend class RPTStatusInflatorTest; + + public: + // These are pointers so the callers don't have to pull in all the headers. + // TODO(Peter): Should this be the E133Header or the RPTHeader? + typedef ola::Callback4 RPTStatusHandler; + + RPTStatusInflator(); + ~RPTStatusInflator() {} + + uint32_t Id() const { return ola::acn::VECTOR_RPT_STATUS; } + + void SetRPTStatusHandler(RPTStatusHandler *handler); + + protected: + bool DecodeHeader(HeaderSet *headers, + const uint8_t *data, + unsigned int len, + unsigned int *bytes_used); + + void ResetHeaderField() {} // namespace noop + + virtual bool HandlePDUData(uint32_t vector, + const HeaderSet &headers, + const uint8_t *data, + unsigned int pdu_len); + + private: + std::auto_ptr m_rpt_status_handler; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_RPTSTATUSINFLATOR_H_ From 2bfeb5510825c29071c88421298ccb9251834b30 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Fri, 5 Apr 2024 21:59:09 +0100 Subject: [PATCH 100/138] Fix some comments --- libs/acn/RPTPDU.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/acn/RPTPDU.cpp b/libs/acn/RPTPDU.cpp index f7eaf0b422..1cbd35eb95 100644 --- a/libs/acn/RPTPDU.cpp +++ b/libs/acn/RPTPDU.cpp @@ -76,8 +76,9 @@ bool RPTPDU::PackHeader(uint8_t *data, unsigned int *length) const { * Pack the data portion. */ bool RPTPDU::PackData(uint8_t *data, unsigned int *length) const { - if (m_pdu) + if (m_pdu) { return m_pdu->Pack(data, length); + } *length = 0; return true; } @@ -103,8 +104,9 @@ void RPTPDU::PackHeader(OutputStream *stream) const { * Pack the data into a buffer */ void RPTPDU::PackData(OutputStream *stream) const { - if (m_pdu) + if (m_pdu) { m_pdu->Write(stream); + } } From 14d56c91545ff672ab2055a2915310a0a9f5ecad Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 6 Apr 2024 00:34:52 +0100 Subject: [PATCH 101/138] Fix some null pointer exceptions --- libs/acn/PDU.cpp | 10 ++++++++ libs/acn/PDU.h | 11 +++++++++ libs/acn/PDUTest.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/libs/acn/PDU.cpp b/libs/acn/PDU.cpp index 0f256eca13..33e40f7205 100644 --- a/libs/acn/PDU.cpp +++ b/libs/acn/PDU.cpp @@ -50,6 +50,16 @@ unsigned int PDU::Size() const { * @return false on error, true otherwise */ bool PDU::Pack(uint8_t *buffer, unsigned int *length) const { + if (!buffer) { + OLA_WARN << "PDU::Pack: missing buffer"; + return false; + } + + if (!length) { + OLA_WARN << "PDU::Pack: missing length"; + return false; + } + unsigned int size = Size(); unsigned int offset = 0; diff --git a/libs/acn/PDU.h b/libs/acn/PDU.h index 2be285dead..531a8e96b5 100644 --- a/libs/acn/PDU.h +++ b/libs/acn/PDU.h @@ -22,6 +22,7 @@ #define LIBS_ACN_PDU_H_ #include +#include #include #include #include @@ -160,6 +161,16 @@ class PDUBlock { */ template bool PDUBlock::Pack(uint8_t *data, unsigned int *length) const { + if (!data) { + OLA_WARN << "PDUBlock::Pack: missing buffer"; + return false; + } + + if (!length) { + OLA_WARN << "PDUBock::Pack: missing length"; + return false; + } + bool status = true; unsigned int i = 0; typename std::vector::const_iterator iter; diff --git a/libs/acn/PDUTest.cpp b/libs/acn/PDUTest.cpp index a5d86cc5d1..fd6e9de057 100644 --- a/libs/acn/PDUTest.cpp +++ b/libs/acn/PDUTest.cpp @@ -35,11 +35,13 @@ using ola::io::OutputStream; class PDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(PDUTest); + CPPUNIT_TEST(testPDU); CPPUNIT_TEST(testPDUBlock); CPPUNIT_TEST(testBlockToOutputStream); CPPUNIT_TEST_SUITE_END(); public: + void testPDU(); void testPDUBlock(); void testBlockToOutputStream(); @@ -51,6 +53,41 @@ class PDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE_REGISTRATION(PDUTest); +/* + * Test that packing a PDUBlock works. + */ +void PDUTest::testPDU() { + MockPDU pdu(0x1234, 0x2468); + + OLA_ASSERT_EQ(4u, pdu.HeaderSize()); + OLA_ASSERT_EQ(4u, pdu.DataSize()); + OLA_ASSERT_EQ(14u, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + + // test null data + OLA_ASSERT_FALSE(pdu.Pack(NULL, &bytes_used)); + + // test a null length + OLA_ASSERT_FALSE(pdu.Pack(data, NULL)); + + // test undersized buffer + bytes_used = size - 1; + OLA_ASSERT_FALSE(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(0u, bytes_used); + + // test oversized buffer + bytes_used = size + 1; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(size, bytes_used); + delete[] data; +} + + /* * Test that packing a PDUBlock works. */ @@ -74,6 +111,24 @@ void PDUTest::testPDUBlock() { OLA_ASSERT_EQ(1u, *test++); OLA_ASSERT_EQ(2u, *test++); OLA_ASSERT_EQ(42u, *test); + + // test null data + OLA_ASSERT_FALSE(block.Pack(NULL, &bytes_used)); + + // test a null length + OLA_ASSERT_FALSE(block.Pack(data, NULL)); + + // test undersized buffer + bytes_used = block_size - 1; + OLA_ASSERT_FALSE(block.Pack(data, &bytes_used)); + // TODO(Peter): Work out what behaviour we want for the bytes used, it's + // currently the actual total used, not zero like the PDU::Pack returns + // OLA_ASSERT_EQ(0u, bytes_used); + + // test oversized buffer + bytes_used = block_size + 1; + OLA_ASSERT(block.Pack(data, &bytes_used)); + OLA_ASSERT_EQ(block_size, bytes_used); delete[] data; block.Clear(); From 91e014f048cdfc1ff21948b3eb1a7e5d9a3487c7 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 6 Apr 2024 01:24:50 +0100 Subject: [PATCH 102/138] Fix more null pointer exceptions --- libs/acn/PDU.cpp | 15 +++++++++++++++ libs/acn/PDU.h | 5 +++++ libs/acn/PDUTest.cpp | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/libs/acn/PDU.cpp b/libs/acn/PDU.cpp index 33e40f7205..0fa3ef744e 100644 --- a/libs/acn/PDU.cpp +++ b/libs/acn/PDU.cpp @@ -131,6 +131,11 @@ bool PDU::Pack(uint8_t *buffer, unsigned int *length) const { * Write this PDU to an OutputStream. */ void PDU::Write(OutputStream *stream) const { + if (!stream) { + OLA_WARN << "PDU::Write: missing stream"; + return; + } + unsigned int size = Size(); if (size <= TWOB_LENGTH_LIMIT && !m_force_length_flag) { @@ -173,6 +178,11 @@ void PDU::Write(OutputStream *stream) const { void PDU::PrependFlagsAndLength(ola::io::OutputBufferInterface *output, uint8_t flags, bool force_length_flag) { + if (!output) { + OLA_WARN << "PDU::PrependFlagsAndLength: missing output"; + return; + } + PrependFlagsAndLength(output, output->Size(), flags, force_length_flag); } @@ -184,6 +194,11 @@ void PDU::PrependFlagsAndLength(ola::io::OutputBufferInterface *output, unsigned int size, uint8_t flags, bool force_length_flag) { + if (!output) { + OLA_WARN << "PDU::PrependFlagsAndLength: missing output"; + return; + } + if (size + 2 <= TWOB_LENGTH_LIMIT && !force_length_flag) { size += 2; uint16_t flags_and_length = static_cast(size); diff --git a/libs/acn/PDU.h b/libs/acn/PDU.h index 531a8e96b5..18193c2044 100644 --- a/libs/acn/PDU.h +++ b/libs/acn/PDU.h @@ -192,6 +192,11 @@ bool PDUBlock::Pack(uint8_t *data, unsigned int *length) const { */ template void PDUBlock::Write(ola::io::OutputStream *stream) const { + if (!stream) { + OLA_WARN << "PDUBlock::Write: missing stream"; + return; + } + typename std::vector::const_iterator iter; for (iter = m_pdus.begin(); iter != m_pdus.end(); ++iter) { // TODO(simon): optimize repeated headers & vectors here diff --git a/libs/acn/PDUTest.cpp b/libs/acn/PDUTest.cpp index fd6e9de057..cdeec18320 100644 --- a/libs/acn/PDUTest.cpp +++ b/libs/acn/PDUTest.cpp @@ -37,12 +37,14 @@ class PDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(PDUTest); CPPUNIT_TEST(testPDU); CPPUNIT_TEST(testPDUBlock); + CPPUNIT_TEST(testPDUToOutputStream); CPPUNIT_TEST(testBlockToOutputStream); CPPUNIT_TEST_SUITE_END(); public: void testPDU(); void testPDUBlock(); + void testPDUToOutputStream(); void testBlockToOutputStream(); void setUp() { @@ -136,6 +138,36 @@ void PDUTest::testPDUBlock() { } +/* + * Test that writing a PDU to an OutputStream works. + */ +void PDUTest::testPDUToOutputStream() { + MockPDU pdu(0x1234, 0x2468); + + IOQueue output; + OutputStream stream(&output); + pdu.Write(&stream); + OLA_ASSERT_EQ(14u, output.Size()); + + uint8_t *data = new uint8_t[output.Size()]; + unsigned int data_size = output.Peek(data, output.Size()); + OLA_ASSERT_EQ(output.Size(), data_size); + + uint8_t EXPECTED[] = { + 0x70, 0x0e, 0, 0, + 0, 0x2b, + 0x34, 0x12, 0, 0, + 0x68, 0x24, 0, 0 + }; + OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), data, data_size); + output.Pop(output.Size()); + + // test null stream + pdu.Write(NULL); + delete[] data; +} + + /* * Test that writing to an OutputStream works. */ @@ -164,6 +196,9 @@ void PDUTest::testBlockToOutputStream() { }; OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), block_data, block_size); output.Pop(output.Size()); + + // test null stream + block.Write(NULL); delete[] block_data; } } // namespace acn From 4bdfdbd956dc4456e784b604b685f73773577252 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 11 Apr 2024 15:00:13 +0100 Subject: [PATCH 103/138] RPTPDU test PrependPDU and fix a NPE error in that --- libs/acn/RPTPDU.cpp | 5 +++++ libs/acn/RPTPDUTest.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/libs/acn/RPTPDU.cpp b/libs/acn/RPTPDU.cpp index 1cbd35eb95..3a3330e023 100644 --- a/libs/acn/RPTPDU.cpp +++ b/libs/acn/RPTPDU.cpp @@ -117,6 +117,11 @@ void RPTPDU::PrependPDU(ola::io::IOStack *stack, const ola::rdm::UID &destination_uid, uint16_t destination_endpoint, uint32_t sequence_number) { + if (!stack) { + OLA_WARN << "RPTPDU::PrependPDU: missing stack"; + return; + } + RPTHeader::rpt_pdu_header header; source_uid.Pack(header.source_uid, sizeof(header.source_uid)); header.source_endpoint = HostToNetwork(source_endpoint); diff --git a/libs/acn/RPTPDUTest.cpp b/libs/acn/RPTPDUTest.cpp index 075b2b52e3..422f6a2152 100644 --- a/libs/acn/RPTPDUTest.cpp +++ b/libs/acn/RPTPDUTest.cpp @@ -22,6 +22,7 @@ #include "ola/Logging.h" #include "ola/io/IOQueue.h" +#include "ola/io/IOStack.h" #include "ola/io/OutputStream.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/UID.h" @@ -34,6 +35,7 @@ namespace ola { namespace acn { using ola::io::IOQueue; +using ola::io::IOStack; using ola::io::OutputStream; using ola::network::HostToNetwork; using ola::rdm::UID; @@ -42,11 +44,13 @@ class RPTPDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RPTPDUTest); CPPUNIT_TEST(testSimpleRPTPDU); CPPUNIT_TEST(testSimpleRPTPDUToOutputStream); + CPPUNIT_TEST(testPrepend); CPPUNIT_TEST_SUITE_END(); public: void testSimpleRPTPDU(); void testSimpleRPTPDUToOutputStream(); + void testPrepend(); void setUp() { ola::InitLogging(ola::OLA_LOG_DEBUG, ola::OLA_LOG_STDERR); @@ -148,5 +152,40 @@ void RPTPDUTest::testSimpleRPTPDUToOutputStream() { output.Pop(output.Size()); delete[] pdu_data; } + + +void RPTPDUTest::testPrepend() { + IOStack stack; + RPTPDU::PrependPDU(&stack, + TEST_VECTOR, + UID(0x0102, 0x03040506), 3456, + UID(0x4050, 0x60708090), 7890, + 2370); + + unsigned int length = stack.Size(); + uint8_t *buffer = new uint8_t[length]; + OLA_ASSERT(stack.Read(buffer, length)); + + const uint8_t expected_data[] = { + 0xf0, 0x00, 0x1c, + 0, 0, 0, 39, + 1, 2, 3, 4, 5, 6, // source UID + 13, 128, // source endpoint + 64, 80, 96, 112, 128, 144, // dest UID + 30, 210, // dest endpoint + 0, 0, 9, 66, // sequence number + 0 // reserved + }; + OLA_ASSERT_DATA_EQUALS(expected_data, sizeof(expected_data), buffer, length); + + // test null stack + RPTPDU::PrependPDU(NULL, + TEST_VECTOR, + UID(0x0102, 0x03040506), 3456, + UID(0x4050, 0x60708090), 7890, + 2370); + + delete[] buffer; +} } // namespace acn } // namespace ola From b1dbef002908158a01a28b7bd68854efaedd6f67 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 11 Apr 2024 15:06:15 +0100 Subject: [PATCH 104/138] RPTRequestPDU fix a NPE error in PrependPDU --- libs/acn/RPTRequestPDU.cpp | 5 +++++ libs/acn/RPTRequestPDUTest.cpp | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/libs/acn/RPTRequestPDU.cpp b/libs/acn/RPTRequestPDU.cpp index 577e382b11..db61797554 100644 --- a/libs/acn/RPTRequestPDU.cpp +++ b/libs/acn/RPTRequestPDU.cpp @@ -30,6 +30,11 @@ using ola::io::OutputStream; using ola::network::HostToNetwork; void RPTRequestPDU::PrependPDU(ola::io::IOStack *stack) { + if (!stack) { + OLA_WARN << "RPTRequestPDU::PrependPDU: missing stack"; + return; + } + uint32_t vector = HostToNetwork( static_cast(VECTOR_REQUEST_RDM_CMD)); stack->Write(reinterpret_cast(&vector), sizeof(vector)); diff --git a/libs/acn/RPTRequestPDUTest.cpp b/libs/acn/RPTRequestPDUTest.cpp index d04b88712b..f40b30b7ac 100644 --- a/libs/acn/RPTRequestPDUTest.cpp +++ b/libs/acn/RPTRequestPDUTest.cpp @@ -139,6 +139,10 @@ void RPTRequestPDUTest::testPrepend() { 0, 0, 0, 0x01 }; OLA_ASSERT_DATA_EQUALS(expected_data, sizeof(expected_data), buffer, length); + + // test null stack + RPTRequestPDU::PrependPDU(NULL); + delete[] buffer; } } // namespace acn From 9e113f0afaa504e996381d908b61ebd9087ecf5d Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 11 Apr 2024 22:07:34 +0100 Subject: [PATCH 105/138] Handle vendorcast/broadcast when sending RDM commands via E1.33 --- libs/acn/MessageBuilder.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/libs/acn/MessageBuilder.cpp b/libs/acn/MessageBuilder.cpp index 41d352539b..0216cfed64 100644 --- a/libs/acn/MessageBuilder.cpp +++ b/libs/acn/MessageBuilder.cpp @@ -25,6 +25,7 @@ #include "ola/e133/MessageBuilder.h" #include "ola/io/IOStack.h" #include "ola/rdm/RDMCommandSerializer.h" +#include "ola/rdm/UID.h" #include "libs/acn/BrokerPDU.h" #include "libs/acn/E133PDU.h" @@ -72,12 +73,27 @@ void MessageBuilder::BuildTCPRDMCommandPDU(IOStack *packet, uint16_t source_endpoint_id, uint16_t destination_endpoint_id, uint32_t sequence_number) { + // TODO(Peter): Potentially need some future way to handle controller + // messages here + ola::rdm::UID rpt_destination_uid = request->DestinationUID(); + if (rpt_destination_uid.IsBroadcast()) { + if (rpt_destination_uid.IsVendorcast()) { + rpt_destination_uid = ola::rdm::UID::RPTVendorcastAddressDevices( + rpt_destination_uid); + } else { + rpt_destination_uid = ola::rdm::UID::RPTAllDevices(); + } + if (destination_endpoint_id != NULL_ENDPOINT) { + // TODO(Peter): Should we handle the reserved endpoints now? + destination_endpoint_id = BROADCAST_ENDPOINT; + } + } ola::rdm::RDMCommandSerializer::Write(*request, packet); ola::acn::RDMPDU::PrependPDU(packet); ola::acn::RPTRequestPDU::PrependPDU(packet); RPTPDU::PrependPDU(packet, ola::acn::VECTOR_RPT_REQUEST, request->SourceUID(), source_endpoint_id, - request->DestinationUID(), destination_endpoint_id, + rpt_destination_uid, destination_endpoint_id, sequence_number); RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_RPT, m_cid, true); PreamblePacker::AddTCPPreamble(packet); From 49d4e2ccad236be7742fb22422e84f889ecedf42 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Thu, 11 Apr 2024 22:08:31 +0100 Subject: [PATCH 106/138] Add a TODO for future tidying up --- tools/e133/E133Endpoint.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/e133/E133Endpoint.h b/tools/e133/E133Endpoint.h index d57a6830f1..0cae80cd8d 100644 --- a/tools/e133/E133Endpoint.h +++ b/tools/e133/E133Endpoint.h @@ -29,7 +29,7 @@ using ola::rdm::UIDSet; using std::string; - +// TODO(Peter): Can this become NULL_ENDPOINT? static const uint16_t ROOT_E133_ENDPOINT = 0; /** From 1c8e4edb9d4b8ce2f58d08f1e965c3935c6a5de2 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Fri, 12 Apr 2024 10:09:19 +0100 Subject: [PATCH 107/138] Fix a lint error --- libs/acn/E133StatusHelper.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/acn/E133StatusHelper.cpp b/libs/acn/E133StatusHelper.cpp index 3edcd7889d..00457ea5c0 100644 --- a/libs/acn/E133StatusHelper.cpp +++ b/libs/acn/E133StatusHelper.cpp @@ -208,7 +208,8 @@ string RPTStatusCodeToString(RPTStatusVector rpt_status_code) { bool RPTStatusCodeToRDMStatusCode(RPTStatusVector rpt_status_code, RDMStatusCode *rdm_status_code) { - // TODO(Peter): Fill in the gaps, possibly adding other RDMStatusCodes if required + // TODO(Peter): Fill in the gaps, possibly adding additional RDMStatusCodes + // if required switch (rpt_status_code) { // case ola::acn::VECTOR_RPT_STATUS_UNKNOWN_RPT_UID: // *rdm_status_code = ola::rdm::; From 31c6af091fd9c0344436f2b94ca1e7335ae34dc7 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Fri, 12 Apr 2024 10:35:31 +0100 Subject: [PATCH 108/138] Add BrokerClientEntryRPT Inflator --- libs/acn/BrokerClientEntryRPTInflator.cpp | 89 +++++++++++++++++++ libs/acn/BrokerClientEntryRPTInflator.h | 100 ++++++++++++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 libs/acn/BrokerClientEntryRPTInflator.cpp create mode 100644 libs/acn/BrokerClientEntryRPTInflator.h diff --git a/libs/acn/BrokerClientEntryRPTInflator.cpp b/libs/acn/BrokerClientEntryRPTInflator.cpp new file mode 100644 index 0000000000..6b1b2258ba --- /dev/null +++ b/libs/acn/BrokerClientEntryRPTInflator.cpp @@ -0,0 +1,89 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerClientEntryRPTInflator.cpp + * The Inflator for BrokerClientEntryRPT PDU + * Copyright (C) 2023 Peter Newman + */ + +#include +#include + +#include "ola/Logging.h" +#include "ola/acn/CID.h" +#include "ola/e133/E133Helper.h" +#include "ola/network/NetworkUtils.h" +#include "ola/rdm/UID.h" +#include "include/ola/strings/Format.h" +#include "libs/acn/BrokerClientEntryRPTInflator.h" + +namespace ola { +namespace acn { + +using ola::acn::CID; +using ola::network::NetworkToHost; +using ola::rdm::UID; +using ola::strings::IntToString; + +/** + * Set a BrokerClientEntryRPTHandler to run when receiving a Broker Client + * Entry RPT message. + * @param handler the callback to invoke when there is a Broker Client Entry + * RPT. + */ +void BrokerClientEntryRPTInflator::SetBrokerClientEntryRPTHandler( + BrokerClientEntryRPTHandler *handler) { + m_broker_client_entry_rpt_handler.reset(handler); +} + + +unsigned int BrokerClientEntryRPTInflator::InflatePDUBlock( + OLA_UNUSED HeaderSet *headers, + const uint8_t *data, + unsigned int len) { + broker_client_entry_rpt_pdu_data pdu_data; + if (len > sizeof(pdu_data)) { + OLA_WARN << "Got too much data, received " << len << " only expecting " + << sizeof(pdu_data); + return 0; + } + + memcpy(reinterpret_cast(&pdu_data), data, sizeof(pdu_data)); + + OLA_DEBUG << "Client Entry RPT from " << CID::FromData(pdu_data.client_cid) + << " (" << UID(pdu_data.client_uid) << ") of RPT Client Type " + << IntToString(pdu_data.rpt_client_type); + + ola::e133::E133RPTClientTypeCode client_type; + if (!ola::e133::IntToRPTClientType(pdu_data.rpt_client_type, &client_type)) { + OLA_WARN << "Unknown E1.33 RPT Client Type code " + << IntToString(pdu_data.rpt_client_type); + } + + BrokerClientEntryRPT client_entry(CID::FromData(pdu_data.client_cid), + UID(pdu_data.client_uid), + client_type, + CID::FromData(pdu_data.binding_cid)); + + if (m_broker_client_entry_rpt_handler.get()) { + m_broker_client_entry_rpt_handler->Run(headers, + client_entry); + } else { + OLA_WARN << "No Broker Client Entry RPT handler defined!"; + } + return sizeof(pdu_data); +} +} // namespace acn +} // namespace ola diff --git a/libs/acn/BrokerClientEntryRPTInflator.h b/libs/acn/BrokerClientEntryRPTInflator.h new file mode 100644 index 0000000000..c7db73c4fa --- /dev/null +++ b/libs/acn/BrokerClientEntryRPTInflator.h @@ -0,0 +1,100 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerClientEntryRPTInflator.h + * Interface for the BrokerClientEntryRPTInflator class. + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_BROKERCLIENTENTRYRPTINFLATOR_H_ +#define LIBS_ACN_BROKERCLIENTENTRYRPTINFLATOR_H_ + +#include "ola/Callback.h" +#include "ola/acn/ACNVectors.h" +#include "ola/e133/E133Enums.h" +#include "ola/rdm/UID.h" +#include "libs/acn/BaseInflator.h" + +namespace ola { +namespace acn { + +class BrokerClientEntryRPTInflator: public BaseInflator { + friend class BrokerClientEntryRPTInflatorTest; + + public: + struct BrokerClientEntryRPT { + BrokerClientEntryRPT(const ola::acn::CID &_client_cid, + const ola::rdm::UID &_client_uid, + ola::e133::E133RPTClientTypeCode _client_type_code, + const ola::acn::CID &_binding_cid) + : client_cid(_client_cid), + client_uid(_client_uid), + client_type_code(_client_type_code), + binding_cid(_binding_cid) { + } + ola::acn::CID client_cid; + ola::rdm::UID client_uid; + ola::e133::E133RPTClientTypeCode client_type_code; + ola::acn::CID binding_cid; + }; + + + // These are pointers so the callers don't have to pull in all the headers. + typedef ola::Callback2 BrokerClientEntryRPTHandler; + + BrokerClientEntryRPTInflator() + : BaseInflator() { + } + ~BrokerClientEntryRPTInflator() {} + + uint32_t Id() const { return ola::acn::CLIENT_PROTOCOL_RPT; } + + PACK( + struct broker_client_entry_rpt_pdu_data_s { + uint8_t client_cid[ola::acn::CID::CID_LENGTH]; + uint8_t client_uid[ola::rdm::UID::LENGTH]; + uint8_t rpt_client_type; + uint8_t binding_cid[ola::acn::CID::CID_LENGTH]; + }); + typedef struct broker_client_entry_rpt_pdu_data_s + broker_client_entry_rpt_pdu_data; + + void SetBrokerClientEntryRPTHandler(BrokerClientEntryRPTHandler *handler); + + protected: + // The 'header' is 0 bytes in length. + bool DecodeHeader(HeaderSet*, + const uint8_t*, + unsigned int, + unsigned int *bytes_used) { + *bytes_used = 0; + return true; + } + + void ResetHeaderField() {} // namespace noop + + unsigned int InflatePDUBlock(HeaderSet *headers, + const uint8_t *data, + unsigned int len); + + private: + std::auto_ptr m_broker_client_entry_rpt_handler; +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_BROKERCLIENTENTRYRPTINFLATOR_H_ From 0dc3e4a5de06ecccbc32c3859e179bdbaa503b67 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Fri, 12 Apr 2024 13:03:03 +0100 Subject: [PATCH 109/138] Fix a licence --- libs/acn/E133Helper.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libs/acn/E133Helper.cpp b/libs/acn/E133Helper.cpp index 1905a16bce..61d0d053e6 100644 --- a/libs/acn/E133Helper.cpp +++ b/libs/acn/E133Helper.cpp @@ -1,17 +1,17 @@ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E133Helper.cpp * Various misc E1.33 functions. From 157e7d0c99671b8e202a76b64904732188f27d12 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Fri, 12 Apr 2024 13:12:44 +0100 Subject: [PATCH 110/138] Sort some sources for the lib --- libs/acn/Makefile.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index 9a9d3e434b..f4e364dd8e 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -93,10 +93,10 @@ libs_acn_libolae133core_la_SOURCES = \ libs/acn/BrokerClientEntryHeader.h \ libs/acn/BrokerClientEntryPDU.cpp \ libs/acn/BrokerClientEntryPDU.h \ - libs/acn/BrokerClientEntryRPTPDU.cpp \ - libs/acn/BrokerClientEntryRPTPDU.h \ libs/acn/BrokerClientEntryRPTInflator.cpp \ libs/acn/BrokerClientEntryRPTInflator.h \ + libs/acn/BrokerClientEntryRPTPDU.cpp \ + libs/acn/BrokerClientEntryRPTPDU.h \ libs/acn/BrokerClientEntryUpdateInflator.h \ libs/acn/BrokerClientRemoveInflator.h \ libs/acn/BrokerConnectedClientListInflator.cpp \ From f302dfcbdba6663abcda926dc40db0937097e931 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Fri, 12 Apr 2024 13:34:20 +0100 Subject: [PATCH 111/138] Add another basic inflator --- libs/acn/BrokerClientEntryUpdateInflator.h | 55 ++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 libs/acn/BrokerClientEntryUpdateInflator.h diff --git a/libs/acn/BrokerClientEntryUpdateInflator.h b/libs/acn/BrokerClientEntryUpdateInflator.h new file mode 100644 index 0000000000..be2560071c --- /dev/null +++ b/libs/acn/BrokerClientEntryUpdateInflator.h @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerClientEntryUpdateInflator.h + * Interface for the BrokerClientEntryUpdateInflator class. + * Copyright (C) 2023 Peter Newman + */ + +#ifndef LIBS_ACN_BROKERCLIENTEENTRYUPDATEINFLATOR_H_ +#define LIBS_ACN_BROKERCLIENTENTRYUPDATEINFLATOR_H_ + +#include "ola/acn/ACNVectors.h" +#include "libs/acn/BaseInflator.h" + +namespace ola { +namespace acn { + +class BrokerClientEntryUpdateInflator: public BaseInflator { + friend class BrokerClientEntryUpdateInflatorTest; + + public: + BrokerClientEntryUpdateInflator() + : BaseInflator() { + } + ~BrokerClientEntryUpdateInflator() {} + + uint32_t Id() const { return ola::acn::VECTOR_BROKER_CLIENT_ENTRY_UPDATE; } + + protected: + // The 'header' is 0 bytes in length. + bool DecodeHeader(HeaderSet*, + const uint8_t*, + unsigned int, + unsigned int *bytes_used) { + *bytes_used = 0; + return true; + } + + void ResetHeaderField() {} // namespace noop +}; +} // namespace acn +} // namespace ola +#endif // LIBS_ACN_BROKERCLIENTENTRYUPDATEINFLATOR_H_ From af12b76d28d4f424349bdd8aa0483f5d38ca3c1b Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 13 Apr 2024 08:54:47 +0100 Subject: [PATCH 112/138] Initial BrokerNullInflator test --- libs/acn/BrokerNullInflatorTest.cpp | 71 +++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 libs/acn/BrokerNullInflatorTest.cpp diff --git a/libs/acn/BrokerNullInflatorTest.cpp b/libs/acn/BrokerNullInflatorTest.cpp new file mode 100644 index 0000000000..f6f657bbd2 --- /dev/null +++ b/libs/acn/BrokerNullInflatorTest.cpp @@ -0,0 +1,71 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * BrokerNullInflatorTest.cpp + * Test fixture for the BrokerNullInflator class + * Copyright (C) 2023 Peter Newman + */ + +#include + +#include "ola/Logging.h" +#include "ola/network/NetworkUtils.h" +#include "libs/acn/HeaderSet.h" +#include "libs/acn/PDUTestCommon.h" +#include "libs/acn/BrokerNullInflator.h" +#include "libs/acn/BrokerNullPDU.h" +#include "ola/testing/TestUtils.h" + + +namespace ola { +namespace acn { + +using ola::network::HostToNetwork; + +class BrokerNullInflatorTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(BrokerNullInflatorTest); + CPPUNIT_TEST(testDecodeHeader); + CPPUNIT_TEST(testInflatePDU); + CPPUNIT_TEST_SUITE_END(); + + public: + void testInflatePDU(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(BrokerNullInflatorTest); + + +/* + * Check that we can inflate a BrokerNull PDU that contains other PDUs + */ +void BrokerNullInflatorTest::testInflatePDU() { + // TODO(Peter): pass a different type of msg here as well + BrokerNullPDU pdu(3); + OLA_ASSERT_EQ((unsigned int) 5, pdu.Size()); + + unsigned int size = pdu.Size(); + uint8_t *data = new uint8_t[size]; + unsigned int bytes_used = size; + OLA_ASSERT(pdu.Pack(data, &bytes_used)); + OLA_ASSERT_EQ((unsigned int) size, bytes_used); + + BrokerNullInflator inflator; + HeaderSet header_set; + OLA_ASSERT(inflator.InflatePDUBlock(&header_set, data, size)); +// OLA_ASSERT(header == header_set.GetBrokerHeader()); + delete[] data; +} +} // namespace acn +} // namespace ola From d6ff72387295d7f7b7b36ed7a07eaa9063794c1e Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 13 Apr 2024 16:49:11 +0100 Subject: [PATCH 113/138] Fix a typo in a header guard --- libs/acn/BrokerClientEntryUpdateInflator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/acn/BrokerClientEntryUpdateInflator.h b/libs/acn/BrokerClientEntryUpdateInflator.h index be2560071c..497fedd3be 100644 --- a/libs/acn/BrokerClientEntryUpdateInflator.h +++ b/libs/acn/BrokerClientEntryUpdateInflator.h @@ -18,7 +18,7 @@ * Copyright (C) 2023 Peter Newman */ -#ifndef LIBS_ACN_BROKERCLIENTEENTRYUPDATEINFLATOR_H_ +#ifndef LIBS_ACN_BROKERCLIENTENTRYUPDATEINFLATOR_H_ #define LIBS_ACN_BROKERCLIENTENTRYUPDATEINFLATOR_H_ #include "ola/acn/ACNVectors.h" From 5b8e4d76cada2aeb339759be1943b4d088b212ae Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 13 Apr 2024 17:45:56 +0100 Subject: [PATCH 114/138] Fix NPE and add tests for E133StatusHelper functions --- libs/acn/E133StatusHelper.cpp | 23 ++++++ libs/acn/E133StatusHelperTest.cpp | 124 ++++++++++++++++++++++++++++++ libs/acn/Makefile.mk | 1 + 3 files changed, 148 insertions(+) create mode 100644 libs/acn/E133StatusHelperTest.cpp diff --git a/libs/acn/E133StatusHelper.cpp b/libs/acn/E133StatusHelper.cpp index 00457ea5c0..97a8bdf0d9 100644 --- a/libs/acn/E133StatusHelper.cpp +++ b/libs/acn/E133StatusHelper.cpp @@ -20,6 +20,7 @@ #include #include +#include "ola/Logging.h" #include "ola/e133/E133StatusHelper.h" namespace ola { @@ -32,6 +33,11 @@ using std::string; * Verify that the int is a valid E1.33 Status Code. */ bool IntToStatusCode(uint16_t input, E133StatusCode *status_code) { + if (!status_code) { + OLA_WARN << "ola:e133::IntToStatusCode: missing status_code"; + return false; + } + switch (input) { case ola::e133::SC_E133_ACK: *status_code = ola::e133::SC_E133_ACK; @@ -101,6 +107,12 @@ string StatusCodeToString(E133StatusCode status_code) { bool IntToConnectStatusCode(uint16_t input, E133ConnectStatusCode *connect_status_code) { + if (!connect_status_code) { + OLA_WARN << "ola:e133::IntToConnectStatusCode: missing " + << "connect_status_code"; + return false; + } + switch (input) { case ola::e133::CONNECT_OK: *connect_status_code = ola::e133::CONNECT_OK; @@ -147,6 +159,11 @@ string ConnectStatusCodeToString(E133ConnectStatusCode connect_status_code) { bool IntToRPTStatusCode(uint16_t input, RPTStatusVector *rpt_status_code) { + if (!rpt_status_code) { + OLA_WARN << "ola:e133::IntToRPTStatusCode: missing rpt_status_code"; + return false; + } + switch (input) { case ola::acn::VECTOR_RPT_STATUS_UNKNOWN_RPT_UID: *rpt_status_code = ola::acn::VECTOR_RPT_STATUS_UNKNOWN_RPT_UID; @@ -208,6 +225,12 @@ string RPTStatusCodeToString(RPTStatusVector rpt_status_code) { bool RPTStatusCodeToRDMStatusCode(RPTStatusVector rpt_status_code, RDMStatusCode *rdm_status_code) { + if (!rdm_status_code) { + OLA_WARN << "ola:e133::RPTStatusCodeToRDMStatusCode: missing " + << "rdm_status_code"; + return false; + } + // TODO(Peter): Fill in the gaps, possibly adding additional RDMStatusCodes // if required switch (rpt_status_code) { diff --git a/libs/acn/E133StatusHelperTest.cpp b/libs/acn/E133StatusHelperTest.cpp new file mode 100644 index 0000000000..21b8b3b2dd --- /dev/null +++ b/libs/acn/E133StatusHelperTest.cpp @@ -0,0 +1,124 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * E133StatusHelperTest.cpp + * Test fixture for the E133 Status Helper code + * Copyright (C) 2024 Peter Newman + */ + +#include +#include +#include + +#include "ola/e133/E133Enums.h" +#include "ola/e133/E133StatusHelper.h" +#include "ola/testing/TestUtils.h" + +using std::string; +using ola::e133::IntToStatusCode; +using ola::e133::IntToConnectStatusCode; +using ola::e133::IntToRPTStatusCode; +using ola::e133::RPTStatusCodeToRDMStatusCode; + +class E133StatusHelperTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(E133StatusHelperTest); + CPPUNIT_TEST(testIntToStatusCode); + CPPUNIT_TEST(testIntToConnectStatusCode); + CPPUNIT_TEST(testIntToRPTStatusCode); + CPPUNIT_TEST(testRPTStatusCodeToRDMStatusCode); + CPPUNIT_TEST_SUITE_END(); + + public: + void testIntToStatusCode(); + void testIntToConnectStatusCode(); + void testIntToRPTStatusCode(); + void testRPTStatusCodeToRDMStatusCode(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(E133StatusHelperTest); + + +/* + * Test the IntToStatusCode function. + */ +void E133StatusHelperTest::testIntToStatusCode() { + ola::e133::E133StatusCode value; + OLA_ASSERT_TRUE(IntToStatusCode(0, &value)); + OLA_ASSERT_EQ(value, ola::e133::SC_E133_ACK); + OLA_ASSERT_TRUE(IntToStatusCode(1, &value)); + OLA_ASSERT_EQ(value, ola::e133::SC_E133_RDM_TIMEOUT); + OLA_ASSERT_TRUE(IntToStatusCode(9, &value)); + OLA_ASSERT_EQ(value, ola::e133::SC_E133_BROADCAST_COMPLETE); + // Update this if additional entries are added to the enum + OLA_ASSERT_FALSE(IntToStatusCode((ola::e133::SC_E133_BROADCAST_COMPLETE + 1), &value)); + // test null status code + OLA_ASSERT_FALSE(IntToStatusCode(0, NULL)); +} + + +/* + * Test the IntToConnectStatusCode function. + */ +void E133StatusHelperTest::testIntToConnectStatusCode() { + ola::e133::E133ConnectStatusCode value; + OLA_ASSERT_TRUE(IntToConnectStatusCode(0, &value)); + OLA_ASSERT_EQ(value, ola::e133::CONNECT_OK); + OLA_ASSERT_TRUE(IntToConnectStatusCode(1, &value)); + OLA_ASSERT_EQ(value, ola::e133::CONNECT_SCOPE_MISMATCH); + OLA_ASSERT_TRUE(IntToConnectStatusCode(5, &value)); + OLA_ASSERT_EQ(value, ola::e133::CONNECT_INVALID_UID); + // Update this if additional entries are added to the enum + OLA_ASSERT_FALSE(IntToConnectStatusCode((ola::e133::CONNECT_INVALID_UID + 1), &value)); + // test null status code + OLA_ASSERT_FALSE(IntToConnectStatusCode(0, NULL)); +} + + +/* + * Test the IntToRPTStatusCode function. + */ +void E133StatusHelperTest::testIntToRPTStatusCode() { + ola::acn::RPTStatusVector value; + OLA_ASSERT_TRUE(IntToRPTStatusCode(1, &value)); + OLA_ASSERT_EQ(value, ola::acn::VECTOR_RPT_STATUS_UNKNOWN_RPT_UID); + OLA_ASSERT_TRUE(IntToRPTStatusCode(2, &value)); + OLA_ASSERT_EQ(value, ola::acn::VECTOR_RPT_STATUS_RDM_TIMEOUT); + OLA_ASSERT_TRUE(IntToRPTStatusCode(9, &value)); + OLA_ASSERT_EQ(value, ola::acn::VECTOR_RPT_STATUS_INVALID_COMMAND_CLASS); + // Update this if additional entries are added to the enum + OLA_ASSERT_FALSE(IntToRPTStatusCode((ola::acn::VECTOR_RPT_STATUS_INVALID_COMMAND_CLASS + 1), &value)); + // test null status code + OLA_ASSERT_FALSE(IntToRPTStatusCode(1, NULL)); +} + + +/* + * Test the RPTStatusCodeToRDMStatusCode function. + */ +void E133StatusHelperTest::testRPTStatusCodeToRDMStatusCode() { + ola::rdm::RDMStatusCode value; + // Update this if earlier entries are added to the conversion + OLA_ASSERT_TRUE(RPTStatusCodeToRDMStatusCode(ola::acn::VECTOR_RPT_STATUS_RDM_TIMEOUT, &value)); + OLA_ASSERT_EQ(value, ola::rdm::RDM_TIMEOUT); + OLA_ASSERT_TRUE(RPTStatusCodeToRDMStatusCode(ola::acn::VECTOR_RPT_STATUS_RDM_INVALID_RESPONSE, &value)); + OLA_ASSERT_EQ(value, ola::rdm::RDM_INVALID_RESPONSE); + OLA_ASSERT_TRUE(RPTStatusCodeToRDMStatusCode(ola::acn::VECTOR_RPT_STATUS_INVALID_COMMAND_CLASS, &value)); + OLA_ASSERT_EQ(value, ola::rdm::RDM_INVALID_COMMAND_CLASS); + // Because the function accepts an enum as input, the compile traps any out of range source entry + // Remove this once we provide suitable mapping for all statuses + OLA_ASSERT_FALSE(RPTStatusCodeToRDMStatusCode(ola::acn::VECTOR_RPT_STATUS_UNKNOWN_RPT_UID, &value)); + // test null status code + OLA_ASSERT_FALSE(RPTStatusCodeToRDMStatusCode(ola::acn::VECTOR_RPT_STATUS_RDM_TIMEOUT, NULL)); +} diff --git a/libs/acn/Makefile.mk b/libs/acn/Makefile.mk index f4e364dd8e..62c31386d2 100644 --- a/libs/acn/Makefile.mk +++ b/libs/acn/Makefile.mk @@ -219,6 +219,7 @@ libs_acn_E133Tester_SOURCES = \ libs/acn/BrokerNullInflatorTest.cpp \ libs/acn/BrokerNullPDUTest.cpp \ libs/acn/BrokerPDUTest.cpp \ + libs/acn/E133StatusHelperTest.cpp \ libs/acn/E133InflatorTest.cpp \ libs/acn/E133PDUTest.cpp \ libs/acn/RDMPDUTest.cpp \ From 3a02f31c2948ec066fa55fe01a5e48f2db974997 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 13 Apr 2024 20:24:38 +0100 Subject: [PATCH 115/138] Fix some lint errors --- libs/acn/E133StatusHelperTest.cpp | 47 ++++++++++++++++++------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/libs/acn/E133StatusHelperTest.cpp b/libs/acn/E133StatusHelperTest.cpp index 21b8b3b2dd..058feaa42d 100644 --- a/libs/acn/E133StatusHelperTest.cpp +++ b/libs/acn/E133StatusHelperTest.cpp @@ -1,17 +1,17 @@ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E133StatusHelperTest.cpp * Test fixture for the E133 Status Helper code @@ -62,7 +62,8 @@ void E133StatusHelperTest::testIntToStatusCode() { OLA_ASSERT_TRUE(IntToStatusCode(9, &value)); OLA_ASSERT_EQ(value, ola::e133::SC_E133_BROADCAST_COMPLETE); // Update this if additional entries are added to the enum - OLA_ASSERT_FALSE(IntToStatusCode((ola::e133::SC_E133_BROADCAST_COMPLETE + 1), &value)); + OLA_ASSERT_FALSE(IntToStatusCode((ola::e133::SC_E133_BROADCAST_COMPLETE + 1), + &value)); // test null status code OLA_ASSERT_FALSE(IntToStatusCode(0, NULL)); } @@ -80,7 +81,8 @@ void E133StatusHelperTest::testIntToConnectStatusCode() { OLA_ASSERT_TRUE(IntToConnectStatusCode(5, &value)); OLA_ASSERT_EQ(value, ola::e133::CONNECT_INVALID_UID); // Update this if additional entries are added to the enum - OLA_ASSERT_FALSE(IntToConnectStatusCode((ola::e133::CONNECT_INVALID_UID + 1), &value)); + OLA_ASSERT_FALSE(IntToConnectStatusCode((ola::e133::CONNECT_INVALID_UID + 1), + &value)); // test null status code OLA_ASSERT_FALSE(IntToConnectStatusCode(0, NULL)); } @@ -98,7 +100,8 @@ void E133StatusHelperTest::testIntToRPTStatusCode() { OLA_ASSERT_TRUE(IntToRPTStatusCode(9, &value)); OLA_ASSERT_EQ(value, ola::acn::VECTOR_RPT_STATUS_INVALID_COMMAND_CLASS); // Update this if additional entries are added to the enum - OLA_ASSERT_FALSE(IntToRPTStatusCode((ola::acn::VECTOR_RPT_STATUS_INVALID_COMMAND_CLASS + 1), &value)); + OLA_ASSERT_FALSE(IntToRPTStatusCode( + (ola::acn::VECTOR_RPT_STATUS_INVALID_COMMAND_CLASS + 1), &value)); // test null status code OLA_ASSERT_FALSE(IntToRPTStatusCode(1, NULL)); } @@ -110,15 +113,21 @@ void E133StatusHelperTest::testIntToRPTStatusCode() { void E133StatusHelperTest::testRPTStatusCodeToRDMStatusCode() { ola::rdm::RDMStatusCode value; // Update this if earlier entries are added to the conversion - OLA_ASSERT_TRUE(RPTStatusCodeToRDMStatusCode(ola::acn::VECTOR_RPT_STATUS_RDM_TIMEOUT, &value)); + OLA_ASSERT_TRUE(RPTStatusCodeToRDMStatusCode( + ola::acn::VECTOR_RPT_STATUS_RDM_TIMEOUT, &value)); OLA_ASSERT_EQ(value, ola::rdm::RDM_TIMEOUT); - OLA_ASSERT_TRUE(RPTStatusCodeToRDMStatusCode(ola::acn::VECTOR_RPT_STATUS_RDM_INVALID_RESPONSE, &value)); + OLA_ASSERT_TRUE(RPTStatusCodeToRDMStatusCode( + ola::acn::VECTOR_RPT_STATUS_RDM_INVALID_RESPONSE, &value)); OLA_ASSERT_EQ(value, ola::rdm::RDM_INVALID_RESPONSE); - OLA_ASSERT_TRUE(RPTStatusCodeToRDMStatusCode(ola::acn::VECTOR_RPT_STATUS_INVALID_COMMAND_CLASS, &value)); + OLA_ASSERT_TRUE(RPTStatusCodeToRDMStatusCode( + ola::acn::VECTOR_RPT_STATUS_INVALID_COMMAND_CLASS, &value)); OLA_ASSERT_EQ(value, ola::rdm::RDM_INVALID_COMMAND_CLASS); - // Because the function accepts an enum as input, the compile traps any out of range source entry + // Because the function accepts an enum as input, the compile traps any out + // of range source entry // Remove this once we provide suitable mapping for all statuses - OLA_ASSERT_FALSE(RPTStatusCodeToRDMStatusCode(ola::acn::VECTOR_RPT_STATUS_UNKNOWN_RPT_UID, &value)); + OLA_ASSERT_FALSE(RPTStatusCodeToRDMStatusCode( + ola::acn::VECTOR_RPT_STATUS_UNKNOWN_RPT_UID, &value)); // test null status code - OLA_ASSERT_FALSE(RPTStatusCodeToRDMStatusCode(ola::acn::VECTOR_RPT_STATUS_RDM_TIMEOUT, NULL)); + OLA_ASSERT_FALSE(RPTStatusCodeToRDMStatusCode( + ola::acn::VECTOR_RPT_STATUS_RDM_TIMEOUT, NULL)); } From 14d84e5941259922debd056319c14a6110b14601 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 13 Apr 2024 20:33:36 +0100 Subject: [PATCH 116/138] Fix a comment --- libs/acn/BrokerConnectReplyInflator.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/acn/BrokerConnectReplyInflator.cpp b/libs/acn/BrokerConnectReplyInflator.cpp index 1e14393fe6..313f4958b1 100644 --- a/libs/acn/BrokerConnectReplyInflator.cpp +++ b/libs/acn/BrokerConnectReplyInflator.cpp @@ -65,8 +65,7 @@ unsigned int BrokerConnectReplyInflator::InflatePDUBlock(HeaderSet *headers, UID(pdu_data.client_uid)); if (m_broker_connect_reply_handler.get()) { - m_broker_connect_reply_handler->Run(headers, - reply); + m_broker_connect_reply_handler->Run(headers, reply); } else { OLA_WARN << "No Broker Connect Reply handler defined!"; } From ebe7f20def50be8fb7fcb381604e0caceccc7820 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 14 Apr 2024 20:21:17 +0100 Subject: [PATCH 117/138] Expose the default UID via the PluginAdaptor --- include/olad/PluginAdaptor.h | 12 +++++++++++- olad/OlaServer.cpp | 2 +- olad/PluginManagerTest.cpp | 4 ++-- olad/plugin_api/PluginAdaptor.cpp | 14 ++++++++++++-- olad/plugin_api/PortTest.cpp | 2 +- olad/plugin_api/UniverseTest.cpp | 6 +++--- 6 files changed, 30 insertions(+), 10 deletions(-) diff --git a/include/olad/PluginAdaptor.h b/include/olad/PluginAdaptor.h index 222a56d157..b2a6f0757a 100644 --- a/include/olad/PluginAdaptor.h +++ b/include/olad/PluginAdaptor.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -48,13 +49,15 @@ class PluginAdaptor: public ola::io::SelectServerInterface { * @param preferences_factory pointer to the PreferencesFactory object * @param port_broker pointer to the PortBroker object * @param instance_name the instance name of this OlaServer + * @param uid the ola::rdm::UID of this OlaServer */ PluginAdaptor(class DeviceManager *device_manager, ola::io::SelectServerInterface *select_server, ExportMap *export_map, class PreferencesFactory *preferences_factory, class PortBrokerInterface *port_broker, - const std::string *instance_name); + const std::string *instance_name, + const ola::rdm::UID *default_uid); // The following methods are part of the SelectServerInterface bool AddReadDescriptor(ola::io::ReadFileDescriptor *descriptor); @@ -98,6 +101,12 @@ class PluginAdaptor: public ola::io::SelectServerInterface { */ const std::string InstanceName() const; + /** + * @brief Return the default UID for the OLA server + * @return an ola::rdm::UID which is the UID for the server + */ + const ola::rdm::UID DefaultUID() const; + ExportMap *GetExportMap() const { return m_export_map; } @@ -134,6 +143,7 @@ class PluginAdaptor: public ola::io::SelectServerInterface { class PreferencesFactory *m_preferences_factory; class PortBrokerInterface *m_port_broker; const std::string *m_instance_name; + const ola::rdm::UID *m_uid; DISALLOW_COPY_AND_ASSIGN(PluginAdaptor); }; diff --git a/olad/OlaServer.cpp b/olad/OlaServer.cpp index 2921a6f996..1050a0bc69 100644 --- a/olad/OlaServer.cpp +++ b/olad/OlaServer.cpp @@ -225,7 +225,7 @@ bool OlaServer::Init() { auto_ptr plugin_adaptor( new PluginAdaptor(device_manager.get(), m_ss, m_export_map, m_preferences_factory, port_broker.get(), - &m_instance_name)); + &m_instance_name, &m_default_uid)); auto_ptr plugin_manager( new PluginManager(m_plugin_loaders, plugin_adaptor.get())); diff --git a/olad/PluginManagerTest.cpp b/olad/PluginManagerTest.cpp index a769f66926..2045547555 100644 --- a/olad/PluginManagerTest.cpp +++ b/olad/PluginManagerTest.cpp @@ -103,7 +103,7 @@ class MockLoader: public ola::PluginLoader { */ void PluginManagerTest::testPluginManager() { ola::MemoryPreferencesFactory factory; - ola::PluginAdaptor adaptor(NULL, NULL, NULL, &factory, NULL, NULL); + ola::PluginAdaptor adaptor(NULL, NULL, NULL, &factory, NULL, NULL, NULL); TestMockPlugin plugin1(&adaptor, ola::OLA_PLUGIN_ARTNET); TestMockPlugin plugin2(&adaptor, ola::OLA_PLUGIN_ESPNET, false); @@ -133,7 +133,7 @@ void PluginManagerTest::testPluginManager() { */ void PluginManagerTest::testConflictingPlugins() { ola::MemoryPreferencesFactory factory; - ola::PluginAdaptor adaptor(NULL, NULL, NULL, &factory, NULL, NULL); + ola::PluginAdaptor adaptor(NULL, NULL, NULL, &factory, NULL, NULL, NULL); set conflict_set1, conflict_set2, conflict_set3; conflict_set1.insert(ola::OLA_PLUGIN_ARTNET); diff --git a/olad/plugin_api/PluginAdaptor.cpp b/olad/plugin_api/PluginAdaptor.cpp index da50565cf9..7061050590 100644 --- a/olad/plugin_api/PluginAdaptor.cpp +++ b/olad/plugin_api/PluginAdaptor.cpp @@ -37,13 +37,15 @@ PluginAdaptor::PluginAdaptor(DeviceManager *device_manager, ExportMap *export_map, PreferencesFactory *preferences_factory, PortBrokerInterface *port_broker, - const std::string *instance_name): + const std::string *instance_name, + const ola::rdm::UID *default_uid): m_device_manager(device_manager), m_ss(select_server), m_export_map(export_map), m_preferences_factory(preferences_factory), m_port_broker(port_broker), - m_instance_name(instance_name) { + m_instance_name(instance_name), + m_default_uid(default_uid) { } bool PluginAdaptor::AddReadDescriptor( @@ -136,4 +138,12 @@ const std::string PluginAdaptor::InstanceName() const { return ""; } } + +const ola::rdm::UID PluginAdaptor::DefaultUID() const { + if (m_default_uid) { + return *m_default_uid; + } else { + return ola::rdm::UID(0, 0); + } +} } // namespace ola diff --git a/olad/plugin_api/PortTest.cpp b/olad/plugin_api/PortTest.cpp index f7379507c5..42849d71d3 100644 --- a/olad/plugin_api/PortTest.cpp +++ b/olad/plugin_api/PortTest.cpp @@ -91,7 +91,7 @@ void PortTest::testInputPortPriorities() { MockDevice device(NULL, "foo"); TimeStamp time_stamp; MockSelectServer ss(&time_stamp); - ola::PluginAdaptor plugin_adaptor(NULL, &ss, NULL, NULL, NULL, NULL); + ola::PluginAdaptor plugin_adaptor(NULL, &ss, NULL, NULL, NULL, NULL, NULL); // This port operates in static priority mode TestMockInputPort input_port(&device, 1, &plugin_adaptor); port_manager.PatchPort(&input_port, universe_id); diff --git a/olad/plugin_api/UniverseTest.cpp b/olad/plugin_api/UniverseTest.cpp index 7b5d2d5b5b..69f0904fd7 100644 --- a/olad/plugin_api/UniverseTest.cpp +++ b/olad/plugin_api/UniverseTest.cpp @@ -241,7 +241,7 @@ void UniverseTest::testReceiveDmx() { ola::PortManager port_manager(m_store, &broker); TimeStamp time_stamp; MockSelectServer ss(&time_stamp); - ola::PluginAdaptor plugin_adaptor(NULL, &ss, NULL, NULL, NULL, NULL); + ola::PluginAdaptor plugin_adaptor(NULL, &ss, NULL, NULL, NULL, NULL, NULL); MockDevice device(NULL, "foo"); TestMockInputPort port(&device, 1, &plugin_adaptor); // input port @@ -366,7 +366,7 @@ void UniverseTest::testLtpMerging() { TimeStamp time_stamp; MockSelectServer ss(&time_stamp); - ola::PluginAdaptor plugin_adaptor(NULL, &ss, NULL, NULL, NULL, NULL); + ola::PluginAdaptor plugin_adaptor(NULL, &ss, NULL, NULL, NULL, NULL, NULL); MockDevice device(NULL, "foo"); MockDevice device2(NULL, "bar"); TestMockInputPort port(&device, 1, &plugin_adaptor); // input port @@ -446,7 +446,7 @@ void UniverseTest::testHtpMerging() { TimeStamp time_stamp; MockSelectServer ss(&time_stamp); - ola::PluginAdaptor plugin_adaptor(NULL, &ss, NULL, NULL, NULL, NULL); + ola::PluginAdaptor plugin_adaptor(NULL, &ss, NULL, NULL, NULL, NULL, NULL); MockDevice device(NULL, "foo"); MockDevice device2(NULL, "bar"); TestMockInputPort port(&device, 1, &plugin_adaptor); // input port From 44ad498bed5127e63c4d754a62cdcb45cd473cec Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 14 Apr 2024 20:33:44 +0100 Subject: [PATCH 118/138] Fix the missed rename --- include/olad/PluginAdaptor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/olad/PluginAdaptor.h b/include/olad/PluginAdaptor.h index b2a6f0757a..7105dfe684 100644 --- a/include/olad/PluginAdaptor.h +++ b/include/olad/PluginAdaptor.h @@ -143,7 +143,7 @@ class PluginAdaptor: public ola::io::SelectServerInterface { class PreferencesFactory *m_preferences_factory; class PortBrokerInterface *m_port_broker; const std::string *m_instance_name; - const ola::rdm::UID *m_uid; + const ola::rdm::UID *m_default_uid; DISALLOW_COPY_AND_ASSIGN(PluginAdaptor); }; From 3d752e7daf5e3e4a270687ffbd1a153e167c480f Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 14 Apr 2024 20:52:51 +0100 Subject: [PATCH 119/138] Fix some cpplint issues --- libs/acn/LLRPProbeReplyPDU.cpp | 3 ++- libs/acn/LLRPProbeReplyPDUTest.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/acn/LLRPProbeReplyPDU.cpp b/libs/acn/LLRPProbeReplyPDU.cpp index a7822e7dc9..f92ad721b3 100644 --- a/libs/acn/LLRPProbeReplyPDU.cpp +++ b/libs/acn/LLRPProbeReplyPDU.cpp @@ -35,7 +35,8 @@ using ola::rdm::UID; bool LLRPProbeReplyPDU::PackData(uint8_t *data, unsigned int *length) const { llrp_probe_reply_pdu_data pdu_data; m_target_uid.Pack(pdu_data.target_uid, sizeof(pdu_data.target_uid)); - m_hardware_address.Pack(pdu_data.hardware_address, sizeof(pdu_data.hardware_address)); + m_hardware_address.Pack(pdu_data.hardware_address, + sizeof(pdu_data.hardware_address)); pdu_data.type = HostToNetwork(static_cast(m_type)); *length = sizeof(llrp_probe_reply_pdu_data); diff --git a/libs/acn/LLRPProbeReplyPDUTest.cpp b/libs/acn/LLRPProbeReplyPDUTest.cpp index ae25918683..1ce2ca86f4 100644 --- a/libs/acn/LLRPProbeReplyPDUTest.cpp +++ b/libs/acn/LLRPProbeReplyPDUTest.cpp @@ -99,7 +99,8 @@ void LLRPProbeReplyPDUTest::testSimpleLLRPProbeReplyPDU() { OLA_ASSERT_DATA_EQUALS(&data[4], UID::LENGTH, buffer, sizeof(buffer)); uint8_t buffer2[MACAddress::LENGTH]; hardware_address.Pack(buffer2, sizeof(buffer2)); - OLA_ASSERT_DATA_EQUALS(&data[10], MACAddress::LENGTH, buffer2, sizeof(buffer2)); + OLA_ASSERT_DATA_EQUALS(&data[10], MACAddress::LENGTH, + buffer2, sizeof(buffer2)); // test undersized buffer bytes_used = size - 1; From 71378c9689e167ba95ba3997f9f219642c41c467 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Tue, 16 Apr 2024 13:35:23 +0100 Subject: [PATCH 120/138] Update the E1.33/E1.37-7 PIDs within RDMEnums.h --- include/ola/rdm/RDMEnums.h | 46 ++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/include/ola/rdm/RDMEnums.h b/include/ola/rdm/RDMEnums.h index 72bc8aabe0..b4c7230c0e 100644 --- a/include/ola/rdm/RDMEnums.h +++ b/include/ola/rdm/RDMEnums.h @@ -159,28 +159,6 @@ typedef enum { PID_PRESET_MERGEMODE = 0x1043, PID_POWER_ON_SELF_TEST = 0x1044, - // Draft E1.33 PIDs - DO NOT USE - PID_ENDPOINT_LIST = 0x7FE0, - PID_ENDPOINT_TO_UNIVERSE = 0x7FE1, - PID_RDM_TRAFFIC_ENABLE = 0x7FE2, - PID_ENDPOINT_MODE = 0x7FE3, - PID_ENDPOINT_LABEL = 0x7FE4, - PID_DISCOVERY_STATE = 0x7FE5, - PID_ENDPOINT_TIMING = 0x7FE6, - PID_ENDPOINT_TIMING_DESCRIPTION = 0x7FE7, - PID_BINDING_CONTROL_FIELDS = 0x7FE8, - PID_ENDPOINT_IDENTIFY = 0x7FE9, - PID_BACKGROUND_DISCOVERY = 0x7FEA, - PID_ENDPOINT_DEVICE_LIST_CHANGE = 0x7FEB, - PID_ENDPOINT_DEVICES = 0x7FEC, - PID_TCP_COMMS_STATUS = 0x7FED, - PID_ENDPOINT_LIST_CHANGE = 0x7FEE, - PID_BACKGROUND_QUEUED_STATUS_POLICY = 0x7FD0, - PID_BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION = 0x7FD1, - PID_BACKGROUND_STATUS_TYPE = 0x7FD2, - PID_QUEUED_STATUS_ENDPOINT_COLLECTION = 0x7FD3, - PID_QUEUED_STATUS_UID_COLLECTION = 0x7FD4, - // E1.37-2 PIDs PID_LIST_INTERFACES = 0x0700, PID_INTERFACE_LABEL = 0x0701, @@ -196,6 +174,30 @@ typedef enum { PID_DNS_NAME_SERVER = 0x070B, PID_DNS_HOSTNAME = 0x070C, PID_DNS_DOMAIN_NAME = 0x070D, + + // E1.33 PIDs + PID_COMPONENT_SCOPE = 0x0800, + PID_SEARCH_DOMAIN = 0x0801, + PID_TCP_COMMS_STATUS = 0x0802, + PID_BROKER_STATUS = 0x0803, + + // E1.37-7 PIDs + PID_ENDPOINT_LIST = 0x0900, + PID_ENDPOINT_LIST_CHANGE = 0x0901, + PID_IDENTIFY_ENDPOINT = 0x0902, + PID_ENDPOINT_TO_UNIVERSE = 0x0903, + PID_ENDPOINT_MODE = 0x0904, + PID_ENDPOINT_LABEL = 0x0905, + PID_RDM_TRAFFIC_ENABLE = 0x0906, + PID_DISCOVERY_STATE = 0x0907, + PID_BACKGROUND_DISCOVERY = 0x908, + PID_ENDPOINT_TIMING = 0x0909, + PID_ENDPOINT_TIMING_DESCRIPTION = 0x090A, + PID_ENDPOINT_RESPONDERS = 0x090B, + PID_ENDPOINT_RESPONDER_LIST_CHANGE = 0x090C, + PID_BINDING_CONTROL_FIELDS = 0x090D, + PID_BACKGROUND_QUEUED_STATUS_POLICY = 0x090E, + PID_BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION = 0x090F, } rdm_pid; From 05404c75a315ebf8b298641bab6c2fa9793cd070 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 21 Apr 2024 01:50:59 +0100 Subject: [PATCH 121/138] Fix a presumed broken merge and a lint issue --- libs/acn/LLRPProbeRequestPDU.cpp | 50 -------------------------------- 1 file changed, 50 deletions(-) diff --git a/libs/acn/LLRPProbeRequestPDU.cpp b/libs/acn/LLRPProbeRequestPDU.cpp index 4302fa0ee8..c29beb9338 100644 --- a/libs/acn/LLRPProbeRequestPDU.cpp +++ b/libs/acn/LLRPProbeRequestPDU.cpp @@ -31,56 +31,6 @@ using ola::io::OutputStream; using ola::network::HostToNetwork; using ola::rdm::UID; -unsigned int LLRPProbeRequestPDU::DataSize() const { - llrp_probe_request_pdu_data data; - return static_cast(sizeof(llrp_probe_request_pdu_data) - - sizeof(data.known_uids) + - (m_known_uids.Size() * UID::LENGTH)); - -} - -bool LLRPProbeRequestPDU::PackData(uint8_t *data, unsigned int *length) const { - llrp_probe_request_pdu_data pdu_data; - m_lower_uid.Pack(pdu_data.lower_uid, sizeof(pdu_data.lower_uid)); - m_upper_uid.Pack(pdu_data.upper_uid, sizeof(pdu_data.upper_uid)); - uint16_t filter = 0; - if (m_client_tcp_connection_inactive) { - filter |= FILTER_CLIENT_TCP_CONNECTION_INACTIVE; - } - if (m_brokers_only) { - filter |= FILTER_BROKERS_ONLY; - } - pdu_data.filter = HostToNetwork(filter); - // TODO(Peter): We need to check we've got <= 200 UIDs here - m_known_uids.Pack(pdu_data.known_uids, sizeof(pdu_data.known_uids)); - *length = static_cast(sizeof(llrp_probe_request_pdu_data) - - sizeof(pdu_data.known_uids) + - (m_known_uids.Size() * UID::LENGTH)); - - memcpy(data, &pdu_data, *length); - return true; -} - -void LLRPProbeRequestPDU::PackData(ola::io::OutputStream *stream) const { - llrp_probe_request_pdu_data data; - m_lower_uid.Pack(data.lower_uid, sizeof(data.lower_uid)); - m_upper_uid.Pack(data.upper_uid, sizeof(data.upper_uid)); - uint16_t filter = 0; - if (m_client_tcp_connection_inactive) { - filter |= FILTER_CLIENT_TCP_CONNECTION_INACTIVE; - } - if (m_brokers_only) { - filter |= FILTER_BROKERS_ONLY; - } - data.filter = HostToNetwork(filter); - // TODO(Peter): We need to check we've got <= 200 UIDs here - m_known_uids.Pack(data.known_uids, sizeof(data.known_uids)); - stream->Write(reinterpret_cast(&data), - static_cast(sizeof(llrp_probe_request_pdu_data) - - sizeof(data.known_uids) + - (m_known_uids.Size() * UID::LENGTH))); -} - unsigned int LLRPProbeRequestPDU::DataSize() const { llrp_probe_request_pdu_data data; return static_cast(sizeof(llrp_probe_request_pdu_data) - From 2c2fdc792348c8a961cf92c024c1beff0406fa06 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 21 Apr 2024 02:01:07 +0100 Subject: [PATCH 122/138] Tidy a header file --- include/ola/e133/E133StatusHelper.h | 26 +++++++++++--------------- libs/acn/E133StatusHelper.cpp | 5 ++++- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/include/ola/e133/E133StatusHelper.h b/include/ola/e133/E133StatusHelper.h index 9d82ddc32b..c48a0fde39 100644 --- a/include/ola/e133/E133StatusHelper.h +++ b/include/ola/e133/E133StatusHelper.h @@ -30,24 +30,20 @@ namespace ola { namespace e133 { -using std::string; -using ola::acn::RPTStatusVector; -using ola::e133::E133StatusCode; -using ola::e133::E133ConnectStatusCode; -using ola::rdm::RDMStatusCode; +bool IntToStatusCode(uint16_t input, ola::e133::E133StatusCode *status_code); +std::string StatusCodeToString(ola::e133::E133StatusCode status_code); -bool IntToStatusCode(uint16_t input, E133StatusCode *status_code); -string StatusCodeToString(E133StatusCode status_code); - -bool IntToConnectStatusCode(uint16_t input, - E133ConnectStatusCode *connect_status_code); -string ConnectStatusCodeToString(E133ConnectStatusCode connect_status_code); +bool IntToConnectStatusCode( + uint16_t input, + ola::e133::E133ConnectStatusCode *connect_status_code); +std::string ConnectStatusCodeToString( + E133ConnectStatusCode connect_status_code); bool IntToRPTStatusCode(uint16_t input, - RPTStatusVector *rpt_status_code); -string RPTStatusCodeToString(RPTStatusVector rpt_status_code); -bool RPTStatusCodeToRDMStatusCode(RPTStatusVector rpt_status_code, - RDMStatusCode *rdm_status_code); + ala::acn::RPTStatusVector *rpt_status_code); +std::string RPTStatusCodeToString(ola::acn::RPTStatusVector rpt_status_code); +bool RPTStatusCodeToRDMStatusCode(ola::acn::RPTStatusVector rpt_status_code, + ola::rdm::RDMStatusCode *rdm_status_code); } // namespace e133 } // namespace ola #endif // INCLUDE_OLA_E133_E133STATUSHELPER_H_ diff --git a/libs/acn/E133StatusHelper.cpp b/libs/acn/E133StatusHelper.cpp index 97a8bdf0d9..5345255216 100644 --- a/libs/acn/E133StatusHelper.cpp +++ b/libs/acn/E133StatusHelper.cpp @@ -26,8 +26,11 @@ namespace ola { namespace e133 { -using ola::rdm::RDMStatusCode; using std::string; +using ola::acn::RPTStatusVector; +using ola::e133::E133StatusCode; +using ola::e133::E133ConnectStatusCode; +using ola::rdm::RDMStatusCode; /** * Verify that the int is a valid E1.33 Status Code. From ed8d5324928c89a47840995ee6624461648afe2c Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 21 Apr 2024 02:06:42 +0100 Subject: [PATCH 123/138] Fix a comment --- include/olad/PluginAdaptor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/olad/PluginAdaptor.h b/include/olad/PluginAdaptor.h index 7105dfe684..59a33bbc7b 100644 --- a/include/olad/PluginAdaptor.h +++ b/include/olad/PluginAdaptor.h @@ -49,7 +49,7 @@ class PluginAdaptor: public ola::io::SelectServerInterface { * @param preferences_factory pointer to the PreferencesFactory object * @param port_broker pointer to the PortBroker object * @param instance_name the instance name of this OlaServer - * @param uid the ola::rdm::UID of this OlaServer + * @param uid the default ola::rdm::UID of this OlaServer */ PluginAdaptor(class DeviceManager *device_manager, ola::io::SelectServerInterface *select_server, From 2d5280c0f9629ad839bd75cb74e14da8c93bc168 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 21 Apr 2024 14:30:50 +0100 Subject: [PATCH 124/138] Fix a typo --- include/ola/e133/E133StatusHelper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ola/e133/E133StatusHelper.h b/include/ola/e133/E133StatusHelper.h index c48a0fde39..62c4f223d0 100644 --- a/include/ola/e133/E133StatusHelper.h +++ b/include/ola/e133/E133StatusHelper.h @@ -40,7 +40,7 @@ std::string ConnectStatusCodeToString( E133ConnectStatusCode connect_status_code); bool IntToRPTStatusCode(uint16_t input, - ala::acn::RPTStatusVector *rpt_status_code); + ola::acn::RPTStatusVector *rpt_status_code); std::string RPTStatusCodeToString(ola::acn::RPTStatusVector rpt_status_code); bool RPTStatusCodeToRDMStatusCode(ola::acn::RPTStatusVector rpt_status_code, ola::rdm::RDMStatusCode *rdm_status_code); From 720bb248c281983138b8e8cd5c6f5542854a657b Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 21 Apr 2024 14:43:47 +0100 Subject: [PATCH 125/138] Fix a comment typo --- plugins/spi/SPIOutput.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/spi/SPIOutput.h b/plugins/spi/SPIOutput.h index 745e6c7c07..ed37e9b3e7 100644 --- a/plugins/spi/SPIOutput.h +++ b/plugins/spi/SPIOutput.h @@ -94,7 +94,7 @@ class SPIOutput: public ola::rdm::DiscoverableRDMControllerInterface { private: /** - * The RDM Operations for the MovingLightResponder. + * The RDM Operations for the SPIOutput. */ class RDMOps : public ola::rdm::ResponderOps { public: From 672ca47b8ddb8f56b5ebbf928d73299c727a1020 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 21 Apr 2024 15:05:26 +0100 Subject: [PATCH 126/138] Update to the standardised PID names for E1.37-7 --- tools/e133/E133Endpoint.cpp | 2 +- tools/e133/E133Endpoint.h | 14 ++++---- tools/e133/ManagementEndpoint.cpp | 58 +++++++++++++++---------------- tools/e133/ManagementEndpoint.h | 12 +++---- 4 files changed, 43 insertions(+), 43 deletions(-) diff --git a/tools/e133/E133Endpoint.cpp b/tools/e133/E133Endpoint.cpp index f0fbd44927..58efa583fa 100644 --- a/tools/e133/E133Endpoint.cpp +++ b/tools/e133/E133Endpoint.cpp @@ -44,7 +44,7 @@ E133Endpoint::E133Endpoint(DiscoverableRDMControllerInterface *controller, m_is_physical(properties.is_physical), m_universe(UNPATCHED_UNIVERSE), m_endpoint_label(""), - m_device_list_change(0), + m_responder_list_change(0), m_controller(controller) { } diff --git a/tools/e133/E133Endpoint.h b/tools/e133/E133Endpoint.h index 0cae80cd8d..f1d9e174e5 100644 --- a/tools/e133/E133Endpoint.h +++ b/tools/e133/E133Endpoint.h @@ -81,11 +81,11 @@ class E133EndpointInterface // ENDPOINT_TIMING_DESCRIPTION - // ENDPOINT_DEVICE_LIST_CHANGE - virtual uint32_t device_list_change() const = 0; + // ENDPOINT_RESPONDER_LIST_CHANGE + virtual uint32_t responder_list_change() const = 0; - // ENDPOINT_DEVICES - virtual void EndpointDevices(UIDSet *uids) const = 0; + // ENDPOINT_RESPONDERS + virtual void EndpointResponders(UIDSet *uids) const = 0; // BINDING_AND_CONTROL_FIELDS @@ -141,8 +141,8 @@ class E133Endpoint: public E133EndpointInterface { m_endpoint_label = endpoint_label; } - uint32_t device_list_change() const { return m_device_list_change; } - void EndpointDevices(UIDSet *uids) const { *uids = m_uids; } + uint32_t responder_list_change() const { return m_responder_list_change; } + void EndpointResponders(UIDSet *uids) const { *uids = m_uids; } virtual void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback); virtual void RunIncrementalDiscovery( @@ -156,7 +156,7 @@ class E133Endpoint: public E133EndpointInterface { const bool m_is_physical; uint16_t m_universe; string m_endpoint_label; - uint32_t m_device_list_change; + uint32_t m_responder_list_change; UIDSet m_uids; DiscoverableRDMControllerInterface *m_controller; }; diff --git a/tools/e133/ManagementEndpoint.cpp b/tools/e133/ManagementEndpoint.cpp index af67274a5c..1ed6127da9 100644 --- a/tools/e133/ManagementEndpoint.cpp +++ b/tools/e133/ManagementEndpoint.cpp @@ -59,9 +59,9 @@ const ola::rdm::ResponderOps::ParamHandler { ola::rdm::PID_ENDPOINT_LIST_CHANGE, &ManagementEndpoint::GetEndpointListChange, NULL}, - { ola::rdm::PID_ENDPOINT_IDENTIFY, - &ManagementEndpoint::GetEndpointIdentify, - &ManagementEndpoint::SetEndpointIdentify}, + { ola::rdm::PID_IDENTIFY_ENDPOINT, + &ManagementEndpoint::GetIdentifyEndpoint, + &ManagementEndpoint::SetIdentifyEndpoint}, { ola::rdm::PID_ENDPOINT_TO_UNIVERSE, &ManagementEndpoint::GetEndpointToUniverse, &ManagementEndpoint::SetEndpointToUniverse}, @@ -76,11 +76,11 @@ const ola::rdm::ResponderOps::ParamHandler // PID_BACKGROUND_DISCOVERY // PID_ENDPOINT_TIMING // PID_ENDPOINT_TIMING_DESCRIPTION - { ola::rdm::PID_ENDPOINT_LIST_CHANGE, - &ManagementEndpoint::GetEndpointDeviceListChange, + { ola::rdm::PID_ENDPOINT_RESPONDER_LIST_CHANGE, + &ManagementEndpoint::GetEndpointResponderListChange, NULL}, - { ola::rdm::PID_ENDPOINT_DEVICES, - &ManagementEndpoint::GetEndpointDevices, + { ola::rdm::PID_ENDPOINT_RESPONDERS, + &ManagementEndpoint::GetEndpointResponders, NULL}, // PID_BINDING_AND_CONTROL_FIELDS { ola::rdm::PID_TCP_COMMS_STATUS, @@ -222,9 +222,9 @@ RDMResponse *ManagementEndpoint::GetEndpointListChange( /** - * Handle PID_ENDPOINT_IDENTIFY + * Handle PID_IDENTIFY_ENDPOINT */ -RDMResponse *ManagementEndpoint::GetEndpointIdentify( +RDMResponse *ManagementEndpoint::GetIdentifyEndpoint( const RDMRequest *request) { uint16_t endpoint_id; if (!ResponderHelper::ExtractUInt16(request, &endpoint_id)) { @@ -243,41 +243,41 @@ RDMResponse *ManagementEndpoint::GetEndpointIdentify( uint16_t endpoint_number; uint8_t identify_mode; }); - IdentifyEndpointParamData endpoint_identify_message = { + IdentifyEndpointParamData identify_endpoint_message = { HostToNetwork(endpoint_id), endpoint->identify_mode() }; return GetResponseFromData( request, - reinterpret_cast(&endpoint_identify_message), - sizeof(endpoint_identify_message)); + reinterpret_cast(&identify_endpoint_message), + sizeof(identify_endpoint_message)); } -RDMResponse *ManagementEndpoint::SetEndpointIdentify( +RDMResponse *ManagementEndpoint::SetIdentifyEndpoint( const RDMRequest *request) { PACK( struct IdentifyEndpointParamData { uint16_t endpoint_number; uint8_t identify_mode; }); - IdentifyEndpointParamData endpoint_identify_message; + IdentifyEndpointParamData identify_endpoint_message; - if (request->ParamDataSize() != sizeof(endpoint_identify_message)) { + if (request->ParamDataSize() != sizeof(identify_endpoint_message)) { return NackWithReason(request, NR_FORMAT_ERROR); } - memcpy(reinterpret_cast(&endpoint_identify_message), + memcpy(reinterpret_cast(&identify_endpoint_message), request->ParamData(), - sizeof(endpoint_identify_message)); + sizeof(identify_endpoint_message)); E133Endpoint *endpoint = m_endpoint_manager->GetEndpoint( - ola::network::NetworkToHost(endpoint_identify_message.endpoint_number)); + ola::network::NetworkToHost(identify_endpoint_message.endpoint_number)); // endpoint not found if (!endpoint) { return NackWithReason(request, ola::rdm::NR_ENDPOINT_NUMBER_INVALID); } - endpoint->set_identify_mode(endpoint_identify_message.identify_mode); + endpoint->set_identify_mode(identify_endpoint_message.identify_mode); return GetResponseFromData(request, NULL, 0); } @@ -324,9 +324,9 @@ RDMResponse *ManagementEndpoint::SetEndpointLabel(const RDMRequest *request) { } /** - * Handle PID_ENDPOINT_DEVICE_LIST_CHANGE + * Handle PID_ENDPOINT_RESPONDER_LIST_CHANGE */ -RDMResponse *ManagementEndpoint::GetEndpointDeviceListChange( +RDMResponse *ManagementEndpoint::GetEndpointResponderListChange( const RDMRequest *request) { uint16_t endpoint_id; if (!ResponderHelper::ExtractUInt16(request, &endpoint_id)) { @@ -340,7 +340,7 @@ RDMResponse *ManagementEndpoint::GetEndpointDeviceListChange( return NackWithReason(request, ola::rdm::NR_ENDPOINT_NUMBER_INVALID); } - uint32_t list_change_id = HostToNetwork(endpoint->device_list_change()); + uint32_t list_change_id = HostToNetwork(endpoint->responder_list_change()); return GetResponseFromData( request, reinterpret_cast(&list_change_id), @@ -348,9 +348,9 @@ RDMResponse *ManagementEndpoint::GetEndpointDeviceListChange( } /** - * Handle PID_ENDPOINT_DEVICES + * Handle PID_ENDPOINT_RESPONDERS */ -RDMResponse *ManagementEndpoint::GetEndpointDevices(const RDMRequest *request) { +RDMResponse *ManagementEndpoint::GetEndpointResponders(const RDMRequest *request) { uint16_t endpoint_id; if (!ResponderHelper::ExtractUInt16(request, &endpoint_id)) { return NackWithReason(request, NR_FORMAT_ERROR); @@ -369,20 +369,20 @@ RDMResponse *ManagementEndpoint::GetEndpointDevices(const RDMRequest *request) { } UIDSet uids; - uint32_t list_change_id = HostToNetwork(endpoint->device_list_change()); - endpoint->EndpointDevices(&uids); + uint32_t list_change_id = HostToNetwork(endpoint->responder_list_change()); + endpoint->EndpointResponders(&uids); - struct DeviceListParamData { + struct ResponderListParamData { uint16_t endpoint; uint32_t list_change; uint8_t data[0]; }; // TODO(simon): fix this - we can overflow an RDM packet if there are too - // many devices! + // many responders! unsigned int param_data_size = 2 + 4 + uids.Size() * UID::UID_SIZE; uint8_t *raw_data = new uint8_t[param_data_size]; - DeviceListParamData *param_data = reinterpret_cast( + ResponderListParamData *param_data = reinterpret_cast( raw_data); // TODO(simon): fix this to track changes. diff --git a/tools/e133/ManagementEndpoint.h b/tools/e133/ManagementEndpoint.h index d54b508eb4..79ccc80cfe 100644 --- a/tools/e133/ManagementEndpoint.h +++ b/tools/e133/ManagementEndpoint.h @@ -30,7 +30,7 @@ using ola::rdm::RDMResponse; using ola::rdm::RDMCallback; /** - * The ManagementEndpoint handles RDMCommands directed at this E1.33 device. It + * The ManagementEndpoint handles RDMCommands directed at this E1.33 Component. It * can also pass through commands to another controller if there is one * supplied. */ @@ -50,7 +50,7 @@ class ManagementEndpoint: public E133Endpoint { private: /** - * The RDM Operations for the MovingLightResponder. + * The RDM Operations for the ManagementEndpoint. */ class RDMOps : public ola::rdm::ResponderOps { public: @@ -74,16 +74,16 @@ class ManagementEndpoint: public E133Endpoint { // RDM PID handlers. RDMResponse *GetEndpointList(const RDMRequest *request); RDMResponse *GetEndpointListChange(const RDMRequest *request); - RDMResponse *GetEndpointIdentify(const RDMRequest *request); - RDMResponse *SetEndpointIdentify(const RDMRequest *request); + RDMResponse *GetIdentifyEndpoint(const RDMRequest *request); + RDMResponse *SetIdentifyEndpoint(const RDMRequest *request); RDMResponse *GetEndpointToUniverse(const RDMRequest *request); RDMResponse *SetEndpointToUniverse(const RDMRequest *request); RDMResponse *GetEndpointMode(const RDMRequest *request); RDMResponse *SetEndpointMode(const RDMRequest *request); RDMResponse *GetEndpointLabel(const RDMRequest *request); RDMResponse *SetEndpointLabel(const RDMRequest *request); - RDMResponse *GetEndpointDeviceListChange(const RDMRequest *request); - RDMResponse *GetEndpointDevices(const RDMRequest *request); + RDMResponse *GetEndpointResponderListChange(const RDMRequest *request); + RDMResponse *GetEndpointResponders(const RDMRequest *request); RDMResponse *GetTCPCommsStatus(const RDMRequest *request); RDMResponse *SetTCPCommsStatus(const RDMRequest *request); From 3d070a6192b06a57b313947ce701da2fd58dcd7d Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 21 Apr 2024 15:18:40 +0100 Subject: [PATCH 127/138] Fix the formatting of some PID values in some Python exceptions --- python/ola/PidStore.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ola/PidStore.py b/python/ola/PidStore.py index f48db9656b..5742b35e92 100644 --- a/python/ola/PidStore.py +++ b/python/ola/PidStore.py @@ -1067,7 +1067,7 @@ def LoadFile(self, pid_file_name, validate, override=False): if validate: if ((pid_pb.value >= RDMConstants.RDM_MANUFACTURER_PID_MIN) and (pid_pb.value <= RDMConstants.RDM_MANUFACTURER_PID_MAX)): - raise InvalidPidFormat('%0x04hx between %0x04hx and %0x04hx in %s' % + raise InvalidPidFormat('0x%04hx between 0x%04hx and 0x%04hx in %s' % (pid_pb.value, RDMConstants.RDM_MANUFACTURER_PID_MIN, RDMConstants.RDM_MANUFACTURER_PID_MAX, @@ -1103,7 +1103,7 @@ def LoadFile(self, pid_file_name, validate, override=False): if ((pid_pb.value < RDMConstants.RDM_MANUFACTURER_PID_MIN) or (pid_pb.value > RDMConstants.RDM_MANUFACTURER_PID_MAX)): raise InvalidPidFormat( - 'Manufacturer pid 0x%04hx not between %0x04hx and %0x04hx' % + 'Manufacturer pid 0x%04hx not between 0x%04hx and 0x%04hx' % (pid_pb.value, RDMConstants.RDM_MANUFACTURER_PID_MIN, RDMConstants.RDM_MANUFACTURER_PID_MAX)) From bc812756c270fcb4439731fc2ffee7d170ca9c2b Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 21 Apr 2024 15:24:39 +0100 Subject: [PATCH 128/138] Fix some lint issues --- tools/e133/ManagementEndpoint.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/e133/ManagementEndpoint.cpp b/tools/e133/ManagementEndpoint.cpp index 1ed6127da9..4c1ca18ed6 100644 --- a/tools/e133/ManagementEndpoint.cpp +++ b/tools/e133/ManagementEndpoint.cpp @@ -350,7 +350,8 @@ RDMResponse *ManagementEndpoint::GetEndpointResponderListChange( /** * Handle PID_ENDPOINT_RESPONDERS */ -RDMResponse *ManagementEndpoint::GetEndpointResponders(const RDMRequest *request) { +RDMResponse *ManagementEndpoint::GetEndpointResponders( + const RDMRequest *request) { uint16_t endpoint_id; if (!ResponderHelper::ExtractUInt16(request, &endpoint_id)) { return NackWithReason(request, NR_FORMAT_ERROR); @@ -382,8 +383,8 @@ RDMResponse *ManagementEndpoint::GetEndpointResponders(const RDMRequest *request // many responders! unsigned int param_data_size = 2 + 4 + uids.Size() * UID::UID_SIZE; uint8_t *raw_data = new uint8_t[param_data_size]; - ResponderListParamData *param_data = reinterpret_cast( - raw_data); + ResponderListParamData *param_data = + reinterpret_cast(raw_data); // TODO(simon): fix this to track changes. param_data->endpoint = HostToNetwork(endpoint_id); From 54d2743269b084eba0916ceddf98a5e6e19a7ab4 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sun, 21 Apr 2024 17:25:22 +0100 Subject: [PATCH 129/138] Ensure we don't get an NPE if the Stack is missing --- libs/acn/LLRPProbeReplyPDU.cpp | 5 +++++ libs/acn/LLRPProbeReplyPDUTest.cpp | 8 ++++++++ libs/acn/LLRPProbeRequestPDU.cpp | 5 +++++ libs/acn/LLRPProbeRequestPDUTest.cpp | 9 +++++++++ 4 files changed, 27 insertions(+) diff --git a/libs/acn/LLRPProbeReplyPDU.cpp b/libs/acn/LLRPProbeReplyPDU.cpp index f92ad721b3..b0f8419028 100644 --- a/libs/acn/LLRPProbeReplyPDU.cpp +++ b/libs/acn/LLRPProbeReplyPDU.cpp @@ -57,6 +57,11 @@ void LLRPProbeReplyPDU::PrependPDU(ola::io::IOStack *stack, const UID &target_uid, const MACAddress &hardware_address, const LLRPComponentType type) { + if (!stack) { + OLA_WARN << "LLRPProbeReplyPDU::PrependPDU: missing stack"; + return; + } + llrp_probe_reply_pdu_data data; target_uid.Pack(data.target_uid, sizeof(data.target_uid)); hardware_address.Pack(data.hardware_address, sizeof(data.hardware_address)); diff --git a/libs/acn/LLRPProbeReplyPDUTest.cpp b/libs/acn/LLRPProbeReplyPDUTest.cpp index 1ce2ca86f4..6c27667475 100644 --- a/libs/acn/LLRPProbeReplyPDUTest.cpp +++ b/libs/acn/LLRPProbeReplyPDUTest.cpp @@ -176,6 +176,14 @@ void LLRPProbeReplyPDUTest::testPrepend() { 0xff }; OLA_ASSERT_DATA_EQUALS(expected_data, sizeof(expected_data), buffer, length); + + // test null stack + LLRPProbeReplyPDU::PrependPDU( + NULL, + target_uid, + hardware_address, + LLRPProbeReplyPDU::LLRP_COMPONENT_TYPE_NON_RDMNET); + delete[] buffer; } } // namespace acn diff --git a/libs/acn/LLRPProbeRequestPDU.cpp b/libs/acn/LLRPProbeRequestPDU.cpp index c29beb9338..ecb9c9b21f 100644 --- a/libs/acn/LLRPProbeRequestPDU.cpp +++ b/libs/acn/LLRPProbeRequestPDU.cpp @@ -86,6 +86,11 @@ void LLRPProbeRequestPDU::PrependPDU(ola::io::IOStack *stack, bool client_tcp_connection_inactive, bool brokers_only, const ola::rdm::UIDSet &known_uids) { + if (!stack) { + OLA_WARN << "LLRPProbeRequestPDU::PrependPDU: missing stack"; + return; + } + llrp_probe_request_pdu_data data; lower_uid.Pack(data.lower_uid, sizeof(data.lower_uid)); upper_uid.Pack(data.upper_uid, sizeof(data.upper_uid)); diff --git a/libs/acn/LLRPProbeRequestPDUTest.cpp b/libs/acn/LLRPProbeRequestPDUTest.cpp index 88f39d587c..23e4e61a37 100644 --- a/libs/acn/LLRPProbeRequestPDUTest.cpp +++ b/libs/acn/LLRPProbeRequestPDUTest.cpp @@ -191,6 +191,15 @@ void LLRPProbeRequestPDUTest::testPrepend() { 0x56, 0x78, 0, 0, 0, 2, }; OLA_ASSERT_DATA_EQUALS(expected_data, sizeof(expected_data), buffer, length); + + // test null stack + LLRPProbeRequestPDU::PrependPDU(NULL, + UID(0x0000, 0x00000000), + UID(0xffff, 0xffffffff), + false, + false, + known_uids); + delete[] buffer; } } // namespace acn From 4cf3d174e2d3bb27d0ae3e1409ea62c205fccb0a Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 9 Mar 2026 00:01:17 +0000 Subject: [PATCH 130/138] Refine some test categories and add and use some more constants in the RDM tests --- python/ola/RDMConstants.py | 4 ++++ tools/rdm/TestCategory.py | 1 + tools/rdm/TestDefinitions.py | 29 ++++++++++++++--------------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/python/ola/RDMConstants.py b/python/ola/RDMConstants.py index a5a61dd078..5cfd4a0b21 100644 --- a/python/ola/RDMConstants.py +++ b/python/ola/RDMConstants.py @@ -20,6 +20,8 @@ __author__ = 'nomis52@gmail.com (Simon Newton)' +RDM_MAX_PARAM_DATA_LENGTH = 231 + RDM_ZERO_FOOTPRINT_DMX_ADDRESS = 0xFFFF RDM_MANUFACTURER_PID_MIN = 0x8000 @@ -39,6 +41,8 @@ RDM_DNS_NAME_SERVER_MAX_INDEX = 2 +RDM_MAX_SEARCH_DOMAIN_LENGTH = 231 + def _ReverseDict(input): output = {} diff --git a/tools/rdm/TestCategory.py b/tools/rdm/TestCategory.py index cecd7aa9e7..81830f07be 100644 --- a/tools/rdm/TestCategory.py +++ b/tools/rdm/TestCategory.py @@ -34,6 +34,7 @@ class TestCategory(object): 'DISPLAY_SETTINGS': 'Display Settings', 'CONFIGURATION': 'Configuration', 'CONTROL': 'Control', + 'E133_MANAGEMENT': 'E1.33 (RDMnet) Management', # And others for things that don't quite fit 'CORE': 'Core Functionality', 'ERROR_CONDITIONS': 'Error Conditions', diff --git a/tools/rdm/TestDefinitions.py b/tools/rdm/TestDefinitions.py index 68069ea354..eb13fc2fab 100644 --- a/tools/rdm/TestDefinitions.py +++ b/tools/rdm/TestDefinitions.py @@ -27,7 +27,9 @@ RDM_MANUFACTURER_PID_MIN, RDM_MANUFACTURER_SD_MAX, RDM_MANUFACTURER_SD_MIN, RDM_MAX_DOMAIN_NAME_LENGTH, - RDM_MAX_HOSTNAME_LENGTH, RDM_MIN_HOSTNAME_LENGTH, + RDM_MAX_HOSTNAME_LENGTH, + RDM_MAX_SEARCH_DOMAIN_LENGTH, + RDM_MIN_HOSTNAME_LENGTH, RDM_ZERO_FOOTPRINT_DMX_ADDRESS) from ola.StringUtils import StringEscape from ola.testing.rdm import TestMixins @@ -7932,11 +7934,14 @@ class AllSubDevicesGetSearchDomain(TestMixins.AllSubDevicesGetMixin, PID = 'SEARCH_DOMAIN' -# class GetSearchDomain(TestMixins., -# OptionalParameterTestFixture): -# CATEGORY = TestCategory. -# PID = 'SEARCH_DOMAIN' -# TODO(peter): Test get +class GetSearchDomain(TestMixins.GetStringMixin, + OptionalParameterTestFixture): + CATEGORY = TestCategory.E133_MANAGEMENT + PID = 'SEARCH_DOMAIN' + EXPECTED_FIELDS = ['search_domain'] + PROVIDES = ['search_domain'] + MAX_LENGTH = RDM_MAX_SEARCH_DOMAIN_LENGTH + # TODO(Peter): Validate invalid search domains? class GetSearchDomainWithData(TestMixins.GetWithDataMixin, @@ -7947,7 +7952,7 @@ class GetSearchDomainWithData(TestMixins.GetWithDataMixin, # class SetSearchDomain(TestMixins., # OptionalParameterTestFixture): -# CATEGORY = TestCategory. +# CATEGORY = TestCategory.E133_MANAGEMENT # PID = 'SEARCH_DOMAIN' # TODO(peter): Test set @@ -7958,12 +7963,6 @@ class SetSearchDomainWithNoData(TestMixins.SetWithNoDataMixin, PID = 'SEARCH_DOMAIN' -class SetSearchDomainWithExtraData(TestMixins.SetWithDataMixin, - OptionalParameterTestFixture): - """Send a SET SEARCH_DOMAIN command with extra data.""" - PID = 'SEARCH_DOMAIN' - - class AllSubDevicesGetBrokerStatus(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a get BROKER_STATUS to ALL_SUB_DEVICES.""" @@ -7972,7 +7971,7 @@ class AllSubDevicesGetBrokerStatus(TestMixins.AllSubDevicesGetMixin, # class GetBrokerStatus(TestMixins., # OptionalParameterTestFixture): -# CATEGORY = TestCategory. +# CATEGORY = TestCategory.E133_MANAGEMENT # PID = 'BROKER_STATUS' # TODO(peter): Test get @@ -7985,7 +7984,7 @@ class GetBrokerStatusWithData(TestMixins.GetWithDataMixin, # class SetBrokerStatus(TestMixins., # OptionalParameterTestFixture): -# CATEGORY = TestCategory. +# CATEGORY = TestCategory.E133_MANAGEMENT # PID = 'BROKER_STATUS' # TODO(peter): Test set From 372edee264de4fb307e45620d3b946dc56c5c5a1 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 9 Mar 2026 00:11:44 +0000 Subject: [PATCH 131/138] Flag within our list_rdm_tests tool if the WithExtraData tests are likely to be redundant due to a PID's maximum data size already being at the max PDL --- tools/rdm/list_rdm_tests.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tools/rdm/list_rdm_tests.py b/tools/rdm/list_rdm_tests.py index fc7a818469..1182169713 100755 --- a/tools/rdm/list_rdm_tests.py +++ b/tools/rdm/list_rdm_tests.py @@ -25,6 +25,7 @@ import textwrap from ola import PidStore +from ola.RDMConstants import RDM_MAX_PARAM_DATA_LENGTH __author__ = 'Peter Newman' @@ -151,20 +152,22 @@ def GetWithExtraData(names, pid, pid_test_base_name, get_size): print(' """GET %s with more than %d byte%s of data."""' % (pid.name, get_size, 's' if get_size > 1 else '')) print(' PID = \'%s\'' % (pid.name)) + if get_size >= RDM_MAX_PARAM_DATA_LENGTH: + print((" # TODO(%s): Should we even have this test, get_size is " + "already at least the max PDL!") % (getpass.getuser())) dummy_data = GenerateDummyData(get_size) if dummy_data is None: print((" # DATA = b'foo' # TODO(%s): Specify extra data if this isn't " "enough.") % (getpass.getuser())) - print(" # Ensure the first %d bytes are sane/valid." % (get_size)) elif dummy_data != 'foo': # Doesn't match default, explicitly set value print((" DATA = b'%s' # TODO(%s): Specify extra data if this isn't " "enough.") % (dummy_data, getpass.getuser())) - print(" # Ensure the first %d bytes are sane/valid." % (get_size)) else: print((" # DATA = b'%s' # TODO(%s): Specify extra data if this isn't " "enough.") % (dummy_data, getpass.getuser())) - print(" # Ensure the first %d bytes are sane/valid." % (get_size)) + + print(" # Ensure the first %d bytes are sane/valid." % (get_size)) print('') print('') @@ -277,20 +280,22 @@ def SetWithExtraData(names, pid, pid_test_base_name, set_size): 'OptionalParameterTestFixture']) print(' """Send a SET %s command with extra data."""' % (pid.name)) print(' PID = \'%s\'' % (pid.name)) + if set_size >= RDM_MAX_PARAM_DATA_LENGTH: + print((" # TODO(%s): Should we even have this test, set_size is " + "already at least the max PDL!") % (getpass.getuser())) dummy_data = GenerateDummyData(set_size) if dummy_data is None: print((" # DATA = b'foo' # TODO(%s): Specify extra data if this isn't " "enough.") % (getpass.getuser())) - print(" # Ensure the first %d bytes are sane/valid." % (set_size)) elif dummy_data != 'foo': # Doesn't match default, explicitly set value print((" DATA = b'%s' # TODO(%s): Specify extra data if this isn't " "enough.") % (dummy_data, getpass.getuser())) - print(" # Ensure the first %d bytes are sane/valid." % (set_size)) else: print((" # DATA = b'%s' # TODO(%s): Specify extra data if this isn't " "enough.") % (dummy_data, getpass.getuser())) - print(" # Ensure the first %d bytes are sane/valid." % (set_size)) + + print(" # Ensure the first %d bytes are sane/valid." % (set_size)) print('') print('') From d600af98da3c13ce2c272cb00e30d04aca53295a Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 9 Mar 2026 00:14:54 +0000 Subject: [PATCH 132/138] Handle a device info field being unavailable for some reason --- tools/rdm/ModelCollector.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/rdm/ModelCollector.py b/tools/rdm/ModelCollector.py index fb4aa2be75..f4cd9879d7 100644 --- a/tools/rdm/ModelCollector.py +++ b/tools/rdm/ModelCollector.py @@ -211,7 +211,10 @@ def _HandleDeviceInfo(self, data): 'sensor_count', 'sub_device_count'] for field in fields: - this_device[field] = data[field] + if field in data: + this_device[field] = data[field] + else: + print('Failed to get %s from device info for UID %s' % (field, self.uid)) this_device['software_versions'][data['software_version']] = { 'languages': [], From 8dfdaf7b1a17371dc4cd59b0405d064fc33a1e3d Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 9 Mar 2026 14:57:36 +0000 Subject: [PATCH 133/138] Fix import order --- tools/rdm/list_rdm_tests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/rdm/list_rdm_tests.py b/tools/rdm/list_rdm_tests.py index 46b06b2e22..dd898e57f4 100755 --- a/tools/rdm/list_rdm_tests.py +++ b/tools/rdm/list_rdm_tests.py @@ -24,9 +24,10 @@ import sys import textwrap -from ola import PidStore from ola.RDMConstants import RDM_MAX_PARAM_DATA_LENGTH +from ola import PidStore + __author__ = 'Peter Newman' From 15698a1bbe02a63a703e3381e7b605e76042ff62 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 9 Mar 2026 16:29:49 +0000 Subject: [PATCH 134/138] Fix a flake8 issue --- tools/rdm/ModelCollector.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/rdm/ModelCollector.py b/tools/rdm/ModelCollector.py index 8ef0d30d11..e26c613921 100644 --- a/tools/rdm/ModelCollector.py +++ b/tools/rdm/ModelCollector.py @@ -223,7 +223,8 @@ def _HandleDeviceInfo(self, data): if field in data: this_device[field] = data[field] else: - print('Failed to get %s from device info for UID %s' % (field, self.uid)) + print('Failed to get %s from device info for UID %s' + % (field, self.uid)) this_device['software_versions'][data['software_version']] = { 'languages': [], From 7edce3a25883b647d82b628867d05c4606572e31 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Mon, 9 Mar 2026 22:42:53 +0000 Subject: [PATCH 135/138] Correct the naming of RDMnet - easy stuff --- NEWS | 2 +- doxygen/namespaces.dox | 2 +- include/ola/acn/ACNPort.h | 2 +- include/ola/acn/ACNVectors.h | 2 +- include/ola/e133/DeviceManager.h | 2 +- tools/e133/DeviceManager.cpp | 2 +- tools/e133/DeviceManagerImpl.cpp | 2 +- tools/e133/DeviceManagerImpl.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/NEWS b/NEWS index 6a58b4a0d9..86c3ee55b7 100644 --- a/NEWS +++ b/NEWS @@ -662,7 +662,7 @@ Documentation: * Fix the build on OS X Lion 10.7 - #231 * Fix the build with clang 4.2 * Added a simple E1.31 load test tool - * Added the first E1.33 (RDMNet) tools + * Added the first E1.33 (RDMnet) tools * Switched to using the new command line flags module in some programs. * Man page for dmxmonitor - #219 * Rename ola_universe_stats to ola_uni_stats, standardising names diff --git a/doxygen/namespaces.dox b/doxygen/namespaces.dox index 78e52d8b05..bd1cabda72 100644 --- a/doxygen/namespaces.dox +++ b/doxygen/namespaces.dox @@ -15,7 +15,7 @@ * @brief DMX512 related code. * * @namespace ola::e133 - * @brief E1.33 (RDMNet) + * @brief E1.33 (RDMnet) * * @namespace ola::file * @brief File helper functions. diff --git a/include/ola/acn/ACNPort.h b/include/ola/acn/ACNPort.h index 97f98a1ab2..50771e1844 100644 --- a/include/ola/acn/ACNPort.h +++ b/include/ola/acn/ACNPort.h @@ -27,7 +27,7 @@ * [ACN on * wikipedia](http://en.wikipedia.org/wiki/Architecture_for_Control_Networks). * - * This covers code for E1.31 (Streaming ACN) and E1.33 (RDMNet). + * This covers code for E1.31 (Streaming ACN) and E1.33 (RDMnet). */ /** diff --git a/include/ola/acn/ACNVectors.h b/include/ola/acn/ACNVectors.h index b058beb810..e8d88e87df 100644 --- a/include/ola/acn/ACNVectors.h +++ b/include/ola/acn/ACNVectors.h @@ -74,7 +74,7 @@ enum E131Vector { * @brief Vectors used at the E1.33 layer. */ enum E133Vector { - VECTOR_FRAMING_RDMNET = 1, /**< RDMNet data */ + VECTOR_FRAMING_RDMNET = 1, /**< RDMnet data */ VECTOR_FRAMING_STATUS = 2, /**< Status message */ VECTOR_FRAMING_CONTROLLER = 3, /**< Controller message */ VECTOR_FRAMING_CHANGE_NOTIFICATION = 4, /**< Controller change message */ diff --git a/include/ola/e133/DeviceManager.h b/include/ola/e133/DeviceManager.h index 023e8d9f1b..213511cff5 100644 --- a/include/ola/e133/DeviceManager.h +++ b/include/ola/e133/DeviceManager.h @@ -49,7 +49,7 @@ using std::vector; class DeviceManager { public: /* - * The callback used to receive RDMNet layer messages from the devices. + * The callback used to receive RDMnet layer messages from the devices. * @returns true if the data should be acknowledged, false otherwise. */ typedef ola::Callback3 Date: Mon, 9 Mar 2026 22:45:49 +0000 Subject: [PATCH 136/138] Correct the naming of RDMnet - in the E1.33 plugin --- plugins/e133/E133Plugin.cpp | 2 +- plugins/e133/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/e133/E133Plugin.cpp b/plugins/e133/E133Plugin.cpp index 02018a957f..3bf7fe29ff 100644 --- a/plugins/e133/E133Plugin.cpp +++ b/plugins/e133/E133Plugin.cpp @@ -46,7 +46,7 @@ const char E133Plugin::DSCP_KEY[] = "dscp"; const char E133Plugin::INPUT_PORT_COUNT_KEY[] = "input_ports"; const char E133Plugin::IP_KEY[] = "ip"; const char E133Plugin::OUTPUT_PORT_COUNT_KEY[] = "output_ports"; -const char E133Plugin::PLUGIN_NAME[] = "E1.33 (RDMNet)"; +const char E133Plugin::PLUGIN_NAME[] = "E1.33 (RDMnet)"; const char E133Plugin::PLUGIN_PREFIX[] = "e133"; const char E133Plugin::PREPEND_HOSTNAME_KEY[] = "prepend_hostname"; const char E133Plugin::TARGET_SOCKET_KEY[] = "target_socket"; diff --git a/plugins/e133/README.md b/plugins/e133/README.md index 56ca954d07..2821e9ff15 100644 --- a/plugins/e133/README.md +++ b/plugins/e133/README.md @@ -1,4 +1,4 @@ -E1.33 (RDMNet) Plugin +E1.33 (RDMnet) Plugin ===================================== This plugin creates a single device with a configurable number of input and From 473a5d03a50ba1665d2314ac634931950284f758 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 14 Mar 2026 23:42:07 +0000 Subject: [PATCH 137/138] Correctly set the rpt_destination_uid into BuildTCPRDMCommandPDU --- include/ola/e133/MessageBuilder.h | 6 ++++-- libs/acn/MessageBuilder.cpp | 21 ++++----------------- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/include/ola/e133/MessageBuilder.h b/include/ola/e133/MessageBuilder.h index ace419b40f..ed79f06208 100644 --- a/include/ola/e133/MessageBuilder.h +++ b/include/ola/e133/MessageBuilder.h @@ -28,6 +28,7 @@ #include #include #include +#include #include namespace ola { @@ -48,7 +49,8 @@ class MessageBuilder { void PrependRDMHeader(IOStack *packet); void BuildTCPRDMCommandPDU(IOStack *packet, - ola::rdm::RDMRequest *request, + const ola::rdm::RDMRequest *request, + const ola::rdm::UID *rpt_destination_uid, uint16_t source_endpoint_id, uint16_t destination_endpoint_id, uint32_t sequence_number); @@ -65,7 +67,7 @@ class MessageBuilder { const string &description); void BuildUDPE133StatusPDU(IOStack *packet, uint32_t sequence_number, uint16_t endpoint_id, - ola::e133::E133StatusCode status_code, + const ola::e133::E133StatusCode status_code, const string &description); void BuildTCPRootE133(IOStack *packet, uint32_t vector, diff --git a/libs/acn/MessageBuilder.cpp b/libs/acn/MessageBuilder.cpp index 0216cfed64..6889654397 100644 --- a/libs/acn/MessageBuilder.cpp +++ b/libs/acn/MessageBuilder.cpp @@ -46,6 +46,7 @@ using ola::acn::E133PDU; using ola::acn::PreamblePacker; using ola::acn::RootPDU; using ola::acn::RPTPDU; +using ola::rdm::UID; MessageBuilder::MessageBuilder(const CID &cid, const string &source_name) @@ -69,31 +70,17 @@ void MessageBuilder::PrependRDMHeader(IOStack *packet) { * Build a TCP E1.33 RDM Command PDU response. */ void MessageBuilder::BuildTCPRDMCommandPDU(IOStack *packet, - ola::rdm::RDMRequest *request, + const ola::rdm::RDMRequest *request, + const UID *rpt_destination_uid, uint16_t source_endpoint_id, uint16_t destination_endpoint_id, uint32_t sequence_number) { - // TODO(Peter): Potentially need some future way to handle controller - // messages here - ola::rdm::UID rpt_destination_uid = request->DestinationUID(); - if (rpt_destination_uid.IsBroadcast()) { - if (rpt_destination_uid.IsVendorcast()) { - rpt_destination_uid = ola::rdm::UID::RPTVendorcastAddressDevices( - rpt_destination_uid); - } else { - rpt_destination_uid = ola::rdm::UID::RPTAllDevices(); - } - if (destination_endpoint_id != NULL_ENDPOINT) { - // TODO(Peter): Should we handle the reserved endpoints now? - destination_endpoint_id = BROADCAST_ENDPOINT; - } - } ola::rdm::RDMCommandSerializer::Write(*request, packet); ola::acn::RDMPDU::PrependPDU(packet); ola::acn::RPTRequestPDU::PrependPDU(packet); RPTPDU::PrependPDU(packet, ola::acn::VECTOR_RPT_REQUEST, request->SourceUID(), source_endpoint_id, - rpt_destination_uid, destination_endpoint_id, + *rpt_destination_uid, destination_endpoint_id, sequence_number); RootPDU::PrependPDU(packet, ola::acn::VECTOR_ROOT_RPT, m_cid, true); PreamblePacker::AddTCPPreamble(packet); From 96a98ff852476c299ee50161d160a9dbec434c97 Mon Sep 17 00:00:00 2001 From: Peter Newman Date: Sat, 14 Mar 2026 23:53:42 +0000 Subject: [PATCH 138/138] Improve the logging of out of range manufacturer PIDs --- python/ola/PidStore.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/python/ola/PidStore.py b/python/ola/PidStore.py index d1dcd6aa43..a8acf20ed2 100644 --- a/python/ola/PidStore.py +++ b/python/ola/PidStore.py @@ -1126,8 +1126,12 @@ def LoadFile(self, pid_file_name, validate, override=False): if ((pid_pb.value < RDMConstants.RDM_MANUFACTURER_PID_MIN) or (pid_pb.value > RDMConstants.RDM_MANUFACTURER_PID_MAX)): raise InvalidPidFormat( - 'Manufacturer pid 0x%04hx not between 0x%04hx and 0x%04hx' % - (pid_pb.value, + 'Manufacturer %s (0x%04hx) manufacturer pid 0x%04hx (%s) not ' + 'between 0x%04hx and 0x%04hx' % + (manufacturer.manufacturer_name, + manufacturer.manufacturer_id, + pid_pb.value, + pid_pb.name, RDMConstants.RDM_MANUFACTURER_PID_MIN, RDMConstants.RDM_MANUFACTURER_PID_MAX)) if pid_pb.value in pid_dict: