diff --git a/acn/appliance.cpp b/acn/appliance.cpp index 948dbeb..3ad9fb1 100644 --- a/acn/appliance.cpp +++ b/acn/appliance.cpp @@ -90,6 +90,11 @@ void Appliance::TcpPacketReceiver(PDU::Stream stream) */ void Appliance::RlpReceiver(std::shared_ptr root) { + /// To this point, the data segment of the RLP PDU will not have been read. + /// The root PDU must have not failed, and still have bytes available to read. + if (!root->stream()->good()) + return; + if (rlp_vectors_.count(root->vector())) for(auto const &handler : rlp_vectors_[root->vector()]) handler(root); diff --git a/acn/dmp.cpp b/acn/dmp.cpp index a924cfe..d73e318 100644 --- a/acn/dmp.cpp +++ b/acn/dmp.cpp @@ -88,10 +88,12 @@ size_t range::streamSize() const */ void range::iStream(PDU::Stream stream) { - address = read_(stream); - if (type_ == SINGLE) return; - incriment = read_(stream); - count = read_(stream); + if (!stream->good()) + return; + address = read_(stream); + if (type_ == SINGLE) return; + incriment = read_(stream); + count = read_(stream); } @@ -229,61 +231,59 @@ Pdu::Pdu() */ void Pdu::iStream(PDU::Stream stream) { - PDU::Pdu::iStream(stream); - if (stream->fail()) return; + PDU::Pdu::iStream(stream); // flags, length, and vector + createHeader(); // header - createHeader(); + if (!flags_.hasData) + return; - if (!flags_.hasData) - return; + auto header = static_cast(this->header()); - auto header = static_cast(this->header()); + auto dataIsAddressList = [this, header] () { + data_ = new address_list(header); + data_->iStream(stream_); + }; - auto dataIsAddressList = [this, header] () { - data_ = new address_list(header); - data_->iStream(stream_); - }; + auto dataIsAdddresPairList = [this, header] () { + data_ = new address_pair_list(header); + data_->iStream(stream_); + }; - auto dataIsAdddresPairList = [this, header] () { - data_ = new address_pair_list(header); - data_->iStream(stream_); - }; - - switch(vector()) { - case GET_PROPERTY: - dataIsAddressList(); - break; - case SET_PROPERTY: - dataIsAdddresPairList(); - break; - case GET_PROPERTY_REPLY: - dataIsAdddresPairList(); - break; - case EVENT: - dataIsAdddresPairList(); - break; - case SUBSCRIBE: - dataIsAddressList(); - break; - case UNSUBSCRIBE: - dataIsAddressList(); - break; - case GET_PROPERTY_FAIL: - dataIsAdddresPairList(); - break; - case SET_PROPERTY_FAIL: - dataIsAdddresPairList(); - break; - case SUBSCRIBE_ACCEPT: - dataIsAddressList(); - break; - case SUBSCRIBE_REJECT: - dataIsAdddresPairList(); - break; - case SYNC_EVENT: - dataIsAdddresPairList(); - break; - } + switch(vector()) { + case GET_PROPERTY: + dataIsAddressList(); + break; + case SET_PROPERTY: + dataIsAdddresPairList(); + break; + case GET_PROPERTY_REPLY: + dataIsAdddresPairList(); + break; + case EVENT: + dataIsAdddresPairList(); + break; + case SUBSCRIBE: + dataIsAddressList(); + break; + case UNSUBSCRIBE: + dataIsAddressList(); + break; + case GET_PROPERTY_FAIL: + dataIsAdddresPairList(); + break; + case SET_PROPERTY_FAIL: + dataIsAdddresPairList(); + break; + case SUBSCRIBE_ACCEPT: + dataIsAddressList(); + break; + case SUBSCRIBE_REJECT: + dataIsAdddresPairList(); + break; + case SYNC_EVENT: + dataIsAdddresPairList(); + break; + } } } // DMP diff --git a/acn/pdu-stream.h b/acn/pdu-stream.h index e0b4288..a3cbfe2 100644 --- a/acn/pdu-stream.h +++ b/acn/pdu-stream.h @@ -51,7 +51,7 @@ public: { if (in_avail() < sizeof(T)) setstate(std::ios_base::failbit); - if (fail()) + if (!good()) return 0; T ret = 0; auto data = reinterpret_cast(&ret); diff --git a/acn/rlp-tcp.cpp b/acn/rlp-tcp.cpp index 354cf88..0b10753 100644 --- a/acn/rlp-tcp.cpp +++ b/acn/rlp-tcp.cpp @@ -49,6 +49,8 @@ transport::transport(bool filled) */ void transport::iStream(PDU::Stream stream) { + if (!stream->good()) + return; /** * 2. Preamble Format: * The ACN Packet Identifier shall be the text string “ASC-E1.17\0\0\0” diff --git a/acn/rlp-udp.cpp b/acn/rlp-udp.cpp index 89a4b4f..b14591e 100644 --- a/acn/rlp-udp.cpp +++ b/acn/rlp-udp.cpp @@ -52,6 +52,8 @@ transport::transport(bool filled) */ void transport::iStream(PDU::Stream stream) { + if (!stream->good()) + return; /** * 2. Preamble Format: * The preamble size includes both size fields so the diff --git a/acn/rlp.cpp b/acn/rlp.cpp index c94b181..60b350e 100644 --- a/acn/rlp.cpp +++ b/acn/rlp.cpp @@ -43,11 +43,14 @@ size_t rlp_header::streamSize() const */ void rlp_header::iStream(PDU::Stream stream) { - uint8_t buffer[UUID_LENGTH]; - stream->read(buffer, UUID_LENGTH); - if (stream->gcount() != UUID_LENGTH) - return stream->setstate(std::ios_base::failbit); - cid = UUID::uuid(buffer); + if (!stream->good()) + return; + + uint8_t buffer[UUID_LENGTH]; + stream->read(buffer, UUID_LENGTH); + if (stream->gcount() != UUID_LENGTH) + return stream->setstate(std::ios_base::failbit); + cid = UUID::uuid(buffer); } @@ -57,7 +60,7 @@ void rlp_header::iStream(PDU::Stream stream) */ void rlp_header::oStream(PDU::Stream stream) const { - stream->write(cid.bytes(), UUID_LENGTH); + stream->write(cid.bytes(), UUID_LENGTH); } @@ -77,10 +80,9 @@ Pdu::Pdu() */ void Pdu::iStream(PDU::Stream stream) { - PDU::Pdu::iStream(stream); //! do base class first - if (stream->fail()) return; - - createHeader(); + PDU::Pdu::iStream(stream); // flags, length, and vector + createHeader(); // header + // protocol dependent data segment // data } } // RLP diff --git a/acn/sdt-udp.cpp b/acn/sdt-udp.cpp index 5c497b0..90bbe13 100644 --- a/acn/sdt-udp.cpp +++ b/acn/sdt-udp.cpp @@ -32,9 +32,12 @@ namespace UDP { * @brief address_t::iStream * @param stream */ -void address_t::iStream(PDU::Stream stream) { - *stream >> type; +void address_t::iStream(PDU::Stream stream) +{ + if (!stream->good()) + return; + *stream >> type; if (type != SDT_ADDR_NULL) *stream >> port; diff --git a/acn/sdt.cpp b/acn/sdt.cpp index 317e97e..ab5a8c7 100644 --- a/acn/sdt.cpp +++ b/acn/sdt.cpp @@ -33,6 +33,8 @@ namespace SDT { */ void params_t::iStream(PDU::Stream stream) { + if (!stream->good()) + return; *stream >> Expiry; uint8_t packed; *stream >> packed; @@ -50,6 +52,8 @@ void params_t::iStream(PDU::Stream stream) */ void join_data_t::iStream(PDU::Stream stream) { + if (!stream->good()) + return; *stream >> mid; *stream >> number; *stream >> reciprocal; @@ -67,6 +71,8 @@ void join_data_t::iStream(PDU::Stream stream) */ void join_accept_data_t::iStream(PDU::Stream stream) { + if (!stream->good()) + return; uint8_t buf[16]; stream->read(buf, sizeof(buf)); leader = UUID::uuid(buf); @@ -83,6 +89,8 @@ void join_accept_data_t::iStream(PDU::Stream stream) */ void join_refuse_data_t::iStream(PDU::Stream stream) { + if (!stream->good()) + return; uint8_t buf[16]; stream->read(buf, sizeof(buf)); leader = UUID::uuid(buf); @@ -99,6 +107,8 @@ void join_refuse_data_t::iStream(PDU::Stream stream) */ void nak_data_t::iStream(PDU::Stream stream) { + if (!stream->good()) + return; uint8_t buf[16]; stream->read(buf, sizeof(buf)); leader = UUID::uuid(buf); @@ -116,6 +126,8 @@ void nak_data_t::iStream(PDU::Stream stream) */ void wrapper_data_t::iStream(PDU::Stream stream) { + if (!stream->good()) + return; *stream >> number; } @@ -194,9 +206,9 @@ Pdu::Pdu() */ void Pdu::iStream(PDU::Stream stream) { - PDU::Pdu::iStream(stream); //! do base class first - if (stream->fail()) return; - if (!stream_->good()) return; + PDU::Pdu::iStream(stream); // flags, length, and vector + // TODO: header segment // header + // TODO: data segment // data } /** @@ -226,10 +238,9 @@ ClientPdu::ClientPdu() */ void ClientPdu::iStream(PDU::Stream stream) { - PDU::Pdu::iStream(stream); - if (stream->fail()) return; - - createHeader(); + PDU::Pdu::iStream(stream); // flags, length, and vector + createHeader(); // header + // TODO: data segment // data } }; // SDT diff --git a/rdmnet/broker-protocol.cpp b/rdmnet/broker-protocol.cpp index f94ed06..3d5071a 100644 --- a/rdmnet/broker-protocol.cpp +++ b/rdmnet/broker-protocol.cpp @@ -40,8 +40,11 @@ Pdu::Pdu() * @brief BrokerProtocol::Pdu::iStream * @param stream */ -void Pdu::iStream([[maybe_unused]] ACN::PDU::Stream stream) +void Pdu::iStream(ACN::PDU::Stream stream) { + RDMnet::Pdu::iStream(stream); // flags, length, and vector + // TODO: header segment // header + // TODO: data segment // data } diff --git a/rdmnet/ept.cpp b/rdmnet/ept.cpp index 83da372..5afe10c 100644 --- a/rdmnet/ept.cpp +++ b/rdmnet/ept.cpp @@ -40,8 +40,11 @@ Pdu::Pdu() * @brief EPT::Pdu::iStream * @param stream */ -void Pdu::iStream([[maybe_unused]] ACN::PDU::Stream stream) +void Pdu::iStream(ACN::PDU::Stream stream) { + RDMnet::Pdu::iStream(stream); // flags, length, and vector + // TODO: header segment // header + // TODO: data segment // data } @@ -60,8 +63,11 @@ Pdu::Pdu() * @brief EPT::DATA::Pdu::iStream * @param stream */ -void Pdu::iStream([[maybe_unused]] ACN::PDU::Stream stream) +void Pdu::iStream(ACN::PDU::Stream stream) { + RDMnet::Pdu::iStream(stream); // flags, length, and vector + // TODO: header segment // header + // TODO: data segment // data } } // namespace DATA @@ -82,8 +88,11 @@ Pdu::Pdu() * @brief EPT::STATUS::Pdu::iStream * @param stream */ -void Pdu::iStream([[maybe_unused]] ACN::PDU::Stream stream) +void Pdu::iStream(ACN::PDU::Stream stream) { + RDMnet::Pdu::iStream(stream); // flags, length, and vector + // TODO: header segment // header + // TODO: data segment // data } } // namespace STATUS diff --git a/rdmnet/llrp.cpp b/rdmnet/llrp.cpp index 464cc8a..554e985 100644 --- a/rdmnet/llrp.cpp +++ b/rdmnet/llrp.cpp @@ -33,6 +33,8 @@ namespace LLRP { */ void llrp_data::iStream(ACN::PDU::Stream stream) { + if (!stream->good()) + return; /// Destination CID - The Destination CID indicates the CID of the intended /// recipient of this PDU. uint8_t * buffer = new uint8_t[UUID_LENGTH]; @@ -76,16 +78,11 @@ Pdu::Pdu() */ void Pdu::iStream(ACN::PDU::Stream stream) { - RDMnet::Pdu::iStream(stream); // do base class first - if (stream->fail()) return; - if (!stream_->good()) return; - - /// has no header - - auto payload = new llrp_data(); - payload->iStream(stream_); - data_ = payload; + RDMnet::Pdu::iStream(stream); // flags, length, and vector + // hase no header // header + createData(); // data + auto payload = static_cast(data_); switch (vector_) { case VECTOR_LLRP_PROBE_REQUEST: { @@ -129,6 +126,9 @@ namespace ProbeRequest { */ void request_data::iStream(ACN::PDU::Stream stream) { + if (!stream->good()) + return; + auto readUID = [stream] (RDM::UID& uid) { *stream >> uid.device; *stream >> uid.manufacturer; @@ -178,14 +178,9 @@ Pdu::Pdu() */ void Pdu::iStream(ACN::PDU::Stream stream) { - RDMnet::Pdu::iStream(stream); // do base class first - if (stream->fail()) return; - if (!stream_->good()) return; - - /// LLRP::PDU has no header - - data_ = new request_data(); - data_->iStream(stream_); + RDMnet::Pdu::iStream(stream); // flags, length, and vector + // hase no header // header + createData(); // data } } // namespace ProbeRequest @@ -198,6 +193,9 @@ namespace ProbeReply { */ void reply_data::iStream(ACN::PDU::Stream stream) { + if (!stream->good()) + return; + *stream >> id.device; *stream >> id.manufacturer; stream->read(address, sizeof(address)); @@ -233,14 +231,9 @@ Pdu::Pdu() */ void Pdu::iStream(ACN::PDU::Stream stream) { - RDMnet::Pdu::iStream(stream); // do base class first - if (stream->fail()) return; - if (!stream_->good()) return; - - /// has no header - - data_ = new reply_data(); - data_->iStream(stream_); + RDMnet::Pdu::iStream(stream); // flags, length, and vector + // hase no header // header + createData(); // data } } // namespace ProbeReply @@ -253,6 +246,9 @@ namespace RdmCmd { */ void rdm_data::iStream(ACN::PDU::Stream stream) { + if (!stream->good()) + return; + auto buffer = std::vector(); buffer.push_back(RDM::SC_RDM); while (stream->good()) @@ -288,14 +284,9 @@ Pdu::Pdu() */ void Pdu::iStream(ACN::PDU::Stream stream) { - RDMnet::Pdu::iStream(stream); // do base class first - if (stream->fail()) return; - if (!stream_->good()) return; - - /// has no header - - data_ = new rdm_data(); - data_->iStream(stream_); + RDMnet::Pdu::iStream(stream); // flags, length, and vector + // hase no header // header + createData(); // data } } // namespace RdmCmd diff --git a/rdmnet/rpt.cpp b/rdmnet/rpt.cpp index 681d52e..8d76136 100644 --- a/rdmnet/rpt.cpp +++ b/rdmnet/rpt.cpp @@ -40,8 +40,11 @@ Pdu::Pdu() * @brief RPT::Pdu::iStream * @param stream */ -void Pdu::iStream([[maybe_unused]] ACN::PDU::Stream stream) +void Pdu::iStream(ACN::PDU::Stream stream) { + RDMnet::Pdu::iStream(stream); // flags, length, and vector + // hase no header // header + // TODO: data segment // data } @@ -60,8 +63,11 @@ Pdu::Pdu() * @brief RPT::REQUEST::Pdu::iStream * @param stream */ -void Pdu::iStream([[maybe_unused]] ACN::PDU::Stream stream) +void Pdu::iStream(ACN::PDU::Stream stream) { + RDMnet::Pdu::iStream(stream); // flags, length, and vector + // hase no header // header + // TODO: data segment // data } } // namespace DATA @@ -82,8 +88,11 @@ Pdu::Pdu() * @brief RPT::STATUS::Pdu::iStream * @param stream */ -void Pdu::iStream([[maybe_unused]] ACN::PDU::Stream stream) +void Pdu::iStream(ACN::PDU::Stream stream) { + RDMnet::Pdu::iStream(stream); // flags, length, and vector + // hase no header // header + // TODO: data segment // data } } // namespace STATUS @@ -104,8 +113,11 @@ Pdu::Pdu() * @brief RPT::NOTIFICATION::Pdu::iStream * @param stream */ -void Pdu::iStream([[maybe_unused]] ACN::PDU::Stream stream) +void Pdu::iStream(ACN::PDU::Stream stream) { + RDMnet::Pdu::iStream(stream); // flags, length, and vector + // hase no header // header + // TODO: data segment // data } } // namespace NOTIFICATION @@ -127,8 +139,11 @@ Pdu::Pdu() * @brief RPT::COMMAND::Pdu::iStream * @param stream */ -void Pdu::iStream([[maybe_unused]] ACN::PDU::Stream stream) +void Pdu::iStream(ACN::PDU::Stream stream) { + RDMnet::Pdu::iStream(stream); // flags, length, and vector + // hase no header // header + // TODO: data segment // data } } // namespace COMMAND diff --git a/rdmnet/rpt.h b/rdmnet/rpt.h index e7ec0b7..2a6ca1b 100644 --- a/rdmnet/rpt.h +++ b/rdmnet/rpt.h @@ -24,6 +24,8 @@ #pragma once #include "pdu.h" +#include "config.h" +#include "rdm/uid.h" namespace RDMnet { namespace RPT { @@ -40,6 +42,13 @@ namespace RPT { */ +/** + * @brief 3.3.2 Dynamic UID Request + * RPT Components wishing to obtain Dynamic UIDs from the Broker use a special + * Dynamic UID value known as a Dynamic UID Request. + */ +static const RDM::UID DynamicUidRequest = RDM::UID(0, MY_ESTA_MANUFACTURER_ID, + true); /** * @brief The RPT::Pdu class diff --git a/sacn/data.cpp b/sacn/data.cpp index 3a370dd..054b39c 100644 --- a/sacn/data.cpp +++ b/sacn/data.cpp @@ -49,6 +49,9 @@ size_t data_header::streamSize() const */ void data_header::iStream(ACN::PDU::Stream stream) { + if (!stream->good()) + return; + stream->read(source_name, sizeof(source_name)); if (stream->gcount() != sizeof(source_name)) return stream->setstate(std::ios_base::failbit); @@ -91,11 +94,9 @@ Pdu::Pdu() */ void Pdu::iStream(ACN::PDU::Stream stream) { - ACN::PDU::Pdu::iStream(stream); - if (stream->fail()) return; - - createHeader(); - createDataBlock(); + ACN::PDU::Pdu::iStream(stream); // flags, length, and vector + createHeader(); // header + createDataBlock(); // data } } // DATA diff --git a/sacn/extended.cpp b/sacn/extended.cpp index bab840a..cd57e0f 100644 --- a/sacn/extended.cpp +++ b/sacn/extended.cpp @@ -47,6 +47,9 @@ size_t sync_header::streamSize() const */ void sync_header::iStream(ACN::PDU::Stream stream) { + if (!stream->good()) + return; + *stream >> sequence_number; *stream >> sync_address; stream->read(reserved, sizeof(reserved)); @@ -82,6 +85,9 @@ size_t discovery_header::streamSize() const */ void discovery_header::iStream(ACN::PDU::Stream stream) { + if (!stream->good()) + return; + stream->read(source_name, sizeof(source_name)); if (stream->gcount() != sizeof(source_name)) return stream->setstate(std::ios_base::failbit); @@ -112,17 +118,15 @@ Pdu::Pdu() void Pdu::iStream(ACN::PDU::Stream stream) { - ACN::PDU::Pdu::iStream(stream); - if (stream->fail()) return; - + ACN::PDU::Pdu::iStream(stream); // flags, length, and vector switch(vector_) { case VECTOR_E131_EXTENDED_SYNCHRONIZATION: - createHeader(); - break; + createHeader(); // header + break; // has no data // data case VECTOR_E131_EXTENDED_DISCOVERY: - createHeader(); - createDataBlock(); + createHeader(); // header + createDataBlock(); // data break; default: break; @@ -148,6 +152,9 @@ size_t discovery_list_header::streamSize() const */ void discovery_list_header::iStream(ACN::PDU::Stream stream) { + if (!stream->good()) + return; + *stream >> page; *stream >> last_page; } @@ -205,11 +212,9 @@ Pdu::Pdu() */ void Pdu::iStream(ACN::PDU::Stream stream) { - ACN::PDU::Pdu::iStream(stream); - if (stream->fail()) return; - - createHeader(); - createData(); + ACN::PDU::Pdu::iStream(stream); // flags, length, and vector + createHeader(); // header + createData(); // data if (data_) { diff --git a/sacn/receiver.cpp b/sacn/receiver.cpp index e7f3443..4aaf2bd 100644 --- a/sacn/receiver.cpp +++ b/sacn/receiver.cpp @@ -126,8 +126,10 @@ void Receiver::onDiscovered(const EXTENDED::DISCOVERY::Watcher cb) { void Receiver::dataReceiver(std::shared_ptr root) { root->createDataBlock(); + // a PDU::Block is guaranteed to have been instantiated, but if the input + // stream failed, it will not list any PDU. OK to loop without checking + // the state of the stream. auto block = static_cast*>(root->data()); - for(auto const &frame : *block->pdu) { /// 6.2.1 E1.31 Data Packet: Vector @@ -154,8 +156,10 @@ void Receiver::dataReceiver(std::shared_ptr root) void Receiver::extendedReceiver(std::shared_ptr root) { root->createDataBlock(); + // a PDU::Block is guaranteed to have been instantiated, but if the input + // stream failed, it will not list any PDU. OK to loop without checking + // the state of the stream. auto block = static_cast*>(root->data()); - for(auto const &frame : *block->pdu) { switch(frame->vector()) {