2021-05-27 10:59:22 -04:00
|
|
|
/*
|
|
|
|
sdt.cpp
|
|
|
|
|
|
|
|
Copyright (c) 2021 Kevin Matz (kevin.matz@gmail.com)
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
|
|
copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "sdt.h"
|
|
|
|
|
2021-08-24 18:10:20 -04:00
|
|
|
namespace ACN::SDT {
|
2021-05-27 10:59:22 -04:00
|
|
|
|
2021-08-18 16:55:57 -04:00
|
|
|
namespace CLIENT {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief ClientPdu::ClientPdu
|
|
|
|
* @param stream
|
|
|
|
*/
|
|
|
|
Pdu::Pdu()
|
|
|
|
: PDU::Pdu(2) // vectors are 2 octets (MID)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-29 19:26:49 -04:00
|
|
|
/**
|
2021-08-18 16:55:57 -04:00
|
|
|
* @brief ClientPdu::iStream
|
2021-07-29 19:26:49 -04:00
|
|
|
* @param stream
|
|
|
|
*/
|
2021-08-18 16:55:57 -04:00
|
|
|
void Pdu::iStream(PDU::Stream stream)
|
|
|
|
{
|
|
|
|
PDU::Pdu::iStream(stream); // flags, length, and vector
|
|
|
|
createHeader<client_header>(); // header
|
|
|
|
// data segment is PDU block of type determed by client_header.protocol
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief client_pdu_header_t::iStream
|
|
|
|
* @param stream
|
|
|
|
*/
|
|
|
|
void client_header::iStream(PDU::Stream stream)
|
|
|
|
{
|
|
|
|
*stream >> protocol;
|
|
|
|
*stream >> association;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief client_header::oStream
|
|
|
|
* @param stream
|
|
|
|
*/
|
|
|
|
void client_header::oStream(PDU::Stream stream) const
|
|
|
|
{
|
|
|
|
*stream << protocol;
|
|
|
|
*stream << association;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace CLIENT
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief SDT::Pdu
|
|
|
|
*/
|
|
|
|
Pdu::Pdu()
|
|
|
|
: PDU::Pdu(1) // vectors are 1 octet
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Pdu::iStream
|
|
|
|
* @param stream
|
|
|
|
*/
|
|
|
|
void Pdu::iStream(PDU::Stream stream)
|
|
|
|
{
|
|
|
|
PDU::Pdu::iStream(stream); // flags, length, and vector
|
|
|
|
// has no header segment // header
|
|
|
|
|
|
|
|
// 4.4 SDT Base Layer Messages
|
|
|
|
switch (vector()) // data
|
|
|
|
{
|
|
|
|
case JOIN:
|
|
|
|
createData<join_data>();
|
|
|
|
return;
|
|
|
|
case JOIN_ACCEPT:
|
|
|
|
createData<join_accept_data>();
|
|
|
|
return;
|
|
|
|
case JOIN_REFUSE:
|
|
|
|
createData<join_refuse_data>();
|
|
|
|
return;
|
|
|
|
case LEAVING:
|
|
|
|
createData<join_refuse_data>();
|
|
|
|
return;
|
|
|
|
case NAK:
|
|
|
|
createData<nak_data>();
|
|
|
|
return;
|
|
|
|
case REL_WRAP:
|
|
|
|
createData<wrapper_data>();
|
|
|
|
break;
|
|
|
|
case UNREL_WRAP:
|
|
|
|
createData<wrapper_data>();
|
|
|
|
break;
|
|
|
|
case GET_SESSIONS:
|
|
|
|
createData<get_sessions_data>();
|
|
|
|
return;
|
|
|
|
case SESSIONS:
|
|
|
|
createData<sessions_data>();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vector() == REL_WRAP ||
|
|
|
|
vector() == UNREL_WRAP)
|
|
|
|
{
|
|
|
|
if (!data_)
|
|
|
|
return;
|
|
|
|
auto data = static_cast<wrapper_data*>(data_);
|
|
|
|
data->block.setParent(shared_from_this());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 4.5 SDT Wrapped Messages
|
|
|
|
switch (vector())
|
|
|
|
{
|
|
|
|
case ACK:
|
|
|
|
createData<ack_data>();
|
|
|
|
return;
|
|
|
|
case CHANNEL_PARAMS:
|
|
|
|
createData<channel_params_data>();
|
|
|
|
return;
|
|
|
|
case LEAVE:
|
|
|
|
// has no data segment
|
|
|
|
return;
|
|
|
|
case CONNECT:
|
|
|
|
createData<connect_data>();
|
|
|
|
return;
|
|
|
|
case CONNECT_ACCEPT:
|
|
|
|
createData<connect_data>();
|
|
|
|
return;
|
|
|
|
case CONNECT_REFUSE:
|
|
|
|
createData<disconnecting_data>();
|
|
|
|
return;
|
|
|
|
case DISCONNECT:
|
|
|
|
createData<connect_data>();
|
|
|
|
return;
|
|
|
|
case DISCONNECTING:
|
|
|
|
createData<disconnecting_data>();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief params::iStream
|
|
|
|
* @param stream
|
|
|
|
*/
|
|
|
|
void params::iStream(PDU::Stream stream)
|
2021-07-29 19:26:49 -04:00
|
|
|
{
|
2021-08-15 23:36:29 -04:00
|
|
|
*stream >> Expiry;
|
2021-08-18 16:55:57 -04:00
|
|
|
*stream >> flags;
|
2021-08-15 23:36:29 -04:00
|
|
|
*stream >> NAKholdoff;
|
|
|
|
*stream >> NAKmodulus;
|
|
|
|
*stream >> NAKmaxwait;
|
2021-05-27 10:59:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-29 19:26:49 -04:00
|
|
|
/**
|
2021-08-18 16:55:57 -04:00
|
|
|
* @brief params::oStream
|
|
|
|
* @param stream
|
|
|
|
*/
|
|
|
|
void params::oStream(PDU::Stream stream) const
|
|
|
|
{
|
|
|
|
*stream << Expiry;
|
|
|
|
*stream << flags;
|
|
|
|
*stream << NAKholdoff;
|
|
|
|
*stream << NAKmodulus;
|
|
|
|
*stream << NAKmaxwait;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief join_data::streamSize
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
size_t join_data::streamSize() const
|
|
|
|
{
|
|
|
|
return 15
|
|
|
|
+ UUID_LENGTH
|
|
|
|
+ destination.streamSize()
|
|
|
|
+ parameters.streamSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief join_data::iStream
|
2021-07-29 19:26:49 -04:00
|
|
|
* @param stream
|
|
|
|
*/
|
2021-08-18 16:55:57 -04:00
|
|
|
void join_data::iStream(PDU::Stream stream)
|
2021-07-29 19:26:49 -04:00
|
|
|
{
|
2021-08-18 16:55:57 -04:00
|
|
|
*stream >> cid;
|
2021-08-15 23:36:29 -04:00
|
|
|
*stream >> mid;
|
2021-08-18 16:55:57 -04:00
|
|
|
*stream >> channel;
|
2021-08-15 23:36:29 -04:00
|
|
|
*stream >> reciprocal;
|
|
|
|
*stream >> sequence;
|
|
|
|
*stream >> reliable;
|
|
|
|
destination.iStream(stream);
|
|
|
|
parameters.iStream(stream);
|
|
|
|
*stream >> expiry;
|
2021-05-27 10:59:22 -04:00
|
|
|
}
|
|
|
|
|
2021-07-29 19:26:49 -04:00
|
|
|
|
|
|
|
/**
|
2021-08-18 16:55:57 -04:00
|
|
|
* @brief join_data::oStream
|
|
|
|
* @param stream
|
|
|
|
*/
|
|
|
|
void join_data::oStream(PDU::Stream stream) const
|
|
|
|
{
|
|
|
|
*stream << cid;
|
|
|
|
*stream << mid;
|
|
|
|
*stream << channel;
|
|
|
|
*stream << reciprocal;
|
|
|
|
*stream << sequence;
|
|
|
|
*stream << reliable;
|
|
|
|
destination.oStream(stream);
|
|
|
|
parameters.oStream(stream);
|
|
|
|
*stream << expiry;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief join_accept_data::iStream
|
2021-07-29 19:26:49 -04:00
|
|
|
* @param stream
|
|
|
|
*/
|
2021-08-18 16:55:57 -04:00
|
|
|
void join_accept_data::iStream(PDU::Stream stream)
|
2021-07-29 19:26:49 -04:00
|
|
|
{
|
2021-08-16 21:20:19 -04:00
|
|
|
*stream >> leader;
|
2021-08-15 23:36:29 -04:00
|
|
|
*stream >> number;
|
|
|
|
*stream >> mid;
|
|
|
|
*stream >> reliable;
|
|
|
|
*stream >> reciprocal;
|
2021-05-27 10:59:22 -04:00
|
|
|
}
|
|
|
|
|
2021-07-29 19:26:49 -04:00
|
|
|
|
|
|
|
/**
|
2021-08-18 16:55:57 -04:00
|
|
|
* @brief join_accept_data::oStream
|
2021-07-29 19:26:49 -04:00
|
|
|
* @param stream
|
|
|
|
*/
|
2021-08-18 16:55:57 -04:00
|
|
|
void join_accept_data::oStream(PDU::Stream stream) const
|
|
|
|
{
|
|
|
|
*stream << leader;
|
|
|
|
*stream << number;
|
|
|
|
*stream << mid;
|
|
|
|
*stream << reliable;
|
|
|
|
*stream << reciprocal;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief join_refuse_data::iStream
|
|
|
|
* @param stream
|
|
|
|
*/
|
|
|
|
void join_refuse_data::iStream(PDU::Stream stream)
|
2021-07-29 19:26:49 -04:00
|
|
|
{
|
2021-08-16 21:20:19 -04:00
|
|
|
*stream >> leader;
|
2021-07-29 19:26:49 -04:00
|
|
|
*stream >> number;
|
|
|
|
*stream >> mid;
|
|
|
|
*stream >> reliable;
|
2021-08-18 16:55:57 -04:00
|
|
|
*stream >> reason;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief join_refuse_data::oStream
|
|
|
|
* @param stream
|
|
|
|
*/
|
|
|
|
void join_refuse_data::oStream(PDU::Stream stream) const
|
|
|
|
{
|
|
|
|
*stream << leader;
|
|
|
|
*stream << number;
|
|
|
|
*stream << mid;
|
|
|
|
*stream << reliable;
|
|
|
|
*stream << reason;
|
2021-05-27 10:59:22 -04:00
|
|
|
}
|
|
|
|
|
2021-07-29 19:26:49 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief nak_data_t::iStream
|
|
|
|
* @param stream
|
|
|
|
*/
|
2021-08-18 16:55:57 -04:00
|
|
|
void nak_data::iStream(PDU::Stream stream)
|
2021-07-29 19:26:49 -04:00
|
|
|
{
|
2021-08-16 21:20:19 -04:00
|
|
|
*stream >> leader;
|
2021-08-15 23:36:29 -04:00
|
|
|
*stream >> number;
|
|
|
|
*stream >> mid;
|
|
|
|
*stream >> reliable;
|
|
|
|
*stream >> missed_first;
|
|
|
|
*stream >> missed_last;
|
2021-05-27 10:59:22 -04:00
|
|
|
}
|
|
|
|
|
2021-07-29 19:26:49 -04:00
|
|
|
|
|
|
|
/**
|
2021-08-18 16:55:57 -04:00
|
|
|
* @brief nak_data::oStream
|
2021-07-29 19:26:49 -04:00
|
|
|
* @param stream
|
|
|
|
*/
|
2021-08-18 16:55:57 -04:00
|
|
|
void nak_data::oStream(PDU::Stream stream) const
|
2021-07-29 19:26:49 -04:00
|
|
|
{
|
2021-08-18 16:55:57 -04:00
|
|
|
*stream << leader;
|
|
|
|
*stream << number;
|
|
|
|
*stream << mid;
|
|
|
|
*stream << reliable;
|
|
|
|
*stream << missed_first;
|
|
|
|
*stream << missed_last;
|
2021-05-27 10:59:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-08-18 16:55:57 -04:00
|
|
|
/**
|
|
|
|
* @brief wrapper_data::streamSize
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
size_t wrapper_data::streamSize() const
|
|
|
|
{
|
|
|
|
return 20 + block.streamSize();
|
|
|
|
}
|
|
|
|
|
2021-05-27 10:59:22 -04:00
|
|
|
|
|
|
|
/**
|
2021-08-18 16:55:57 -04:00
|
|
|
* @brief wrapper_data::iStream
|
|
|
|
* @param stream
|
|
|
|
*/
|
|
|
|
void wrapper_data::iStream(PDU::Stream stream)
|
|
|
|
{
|
|
|
|
*stream >> channel;
|
|
|
|
*stream >> sequence;
|
|
|
|
*stream >> reliable;
|
|
|
|
*stream >> oldest;
|
|
|
|
*stream >> ack_range_begin;
|
|
|
|
*stream >> ack_range_end;
|
|
|
|
*stream >> MAK_threshold;
|
|
|
|
block.iStream(stream);
|
2021-05-27 10:59:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2021-08-18 16:55:57 -04:00
|
|
|
* @brief wrapper_data::oStream
|
|
|
|
* @param stream
|
|
|
|
*/
|
|
|
|
void wrapper_data::oStream(PDU::Stream stream) const
|
|
|
|
{
|
|
|
|
*stream << channel;
|
|
|
|
*stream << sequence;
|
|
|
|
*stream << reliable;
|
|
|
|
*stream << oldest;
|
|
|
|
*stream << ack_range_begin;
|
|
|
|
*stream << ack_range_end;
|
|
|
|
*stream << MAK_threshold;
|
|
|
|
block.oStream(stream);
|
|
|
|
}
|
2021-05-27 10:59:22 -04:00
|
|
|
|
2021-08-18 16:55:57 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief channel_info_block::streamSize
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
size_t channel_info_block::streamSize() const
|
|
|
|
{
|
|
|
|
return (mid == 0 ? 6 : 8 + UUID_LENGTH)
|
|
|
|
+ destination.streamSize()
|
|
|
|
+ source.streamSize()
|
|
|
|
+ (4 * protocols.size());
|
2021-05-27 10:59:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2021-08-18 16:55:57 -04:00
|
|
|
* @brief channel_member_info_block::iStream
|
|
|
|
* @param stream
|
|
|
|
*/
|
|
|
|
void channel_info_block::iStream(PDU::Stream stream)
|
|
|
|
{
|
|
|
|
*stream >> mid;
|
|
|
|
if (mid != 0)
|
|
|
|
*stream >> owner;
|
|
|
|
*stream >> channel;
|
|
|
|
destination.iStream(stream);
|
|
|
|
source.iStream(stream);
|
|
|
|
if (mid != 0)
|
|
|
|
*stream >> reciprocal;
|
|
|
|
*stream >> sessions;
|
|
|
|
while (stream->good())
|
|
|
|
protocols.push_back(stream->readType<uint32_t>());
|
2021-05-27 10:59:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2021-08-18 16:55:57 -04:00
|
|
|
* @brief channel_member_info_block::oStream
|
|
|
|
* @param stream
|
|
|
|
*/
|
|
|
|
void channel_info_block::oStream(PDU::Stream stream) const
|
|
|
|
{
|
|
|
|
*stream << mid;
|
|
|
|
if (mid != 0)
|
|
|
|
*stream << owner;
|
|
|
|
*stream << channel;
|
|
|
|
destination.oStream(stream);
|
|
|
|
source.oStream(stream);
|
|
|
|
if (mid != 0)
|
|
|
|
*stream << reciprocal;
|
|
|
|
*stream << sessions;
|
|
|
|
for (const auto & p : protocols)
|
|
|
|
*stream << p;
|
|
|
|
}
|
2021-05-27 10:59:22 -04:00
|
|
|
|
2021-08-18 16:55:57 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief sessions_data::streamSize
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
size_t sessions_data::streamSize() const
|
|
|
|
{
|
|
|
|
size_t ret = 0;
|
|
|
|
for (const auto & info : list)
|
|
|
|
ret += info.streamSize();
|
|
|
|
return ret;
|
2021-05-27 10:59:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2021-08-18 16:55:57 -04:00
|
|
|
* @brief sessions_data::iStream
|
|
|
|
* @param stream
|
|
|
|
*/
|
|
|
|
void sessions_data::iStream(PDU::Stream stream)
|
|
|
|
{
|
|
|
|
while (stream->good())
|
|
|
|
{
|
|
|
|
list.emplace_back(channel_info_block());
|
|
|
|
list.back().iStream(stream);
|
|
|
|
}
|
2021-05-27 10:59:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2021-08-18 16:55:57 -04:00
|
|
|
* @brief sessions_data::oStream
|
|
|
|
* @param stream
|
|
|
|
*/
|
|
|
|
void sessions_data::oStream(PDU::Stream stream) const
|
|
|
|
{
|
|
|
|
for (const auto & info : list)
|
|
|
|
info.oStream(stream);
|
2021-05-27 10:59:22 -04:00
|
|
|
}
|
|
|
|
|
2021-07-29 19:26:49 -04:00
|
|
|
|
|
|
|
/**
|
2021-08-18 16:55:57 -04:00
|
|
|
* @brief channel_params_data::streamSize
|
|
|
|
* @return
|
2021-07-29 19:26:49 -04:00
|
|
|
*/
|
2021-08-18 16:55:57 -04:00
|
|
|
size_t channel_params_data::streamSize() const
|
2021-05-27 10:59:22 -04:00
|
|
|
{
|
2021-08-18 16:55:57 -04:00
|
|
|
return 1
|
|
|
|
+ parameters.streamSize()
|
|
|
|
+ address.streamSize();
|
2021-05-27 10:59:22 -04:00
|
|
|
}
|
|
|
|
|
2021-07-29 19:26:49 -04:00
|
|
|
|
|
|
|
/**
|
2021-08-18 16:55:57 -04:00
|
|
|
* @brief channel_params_data::iStream
|
2021-07-29 19:26:49 -04:00
|
|
|
* @param stream
|
|
|
|
*/
|
2021-08-18 16:55:57 -04:00
|
|
|
void channel_params_data::iStream(PDU::Stream stream)
|
2021-07-29 19:26:49 -04:00
|
|
|
{
|
2021-08-18 16:55:57 -04:00
|
|
|
parameters.iStream(stream);
|
|
|
|
address.iStream(stream);
|
|
|
|
*stream >> expiry;
|
2021-07-29 19:26:49 -04:00
|
|
|
}
|
|
|
|
|
2021-08-18 16:55:57 -04:00
|
|
|
|
2021-07-29 19:26:49 -04:00
|
|
|
/**
|
2021-08-18 16:55:57 -04:00
|
|
|
* @brief channel_params_data::oStream
|
2021-07-29 19:26:49 -04:00
|
|
|
* @param stream
|
|
|
|
*/
|
2021-08-18 16:55:57 -04:00
|
|
|
void channel_params_data::oStream(PDU::Stream stream) const
|
2021-07-29 19:26:49 -04:00
|
|
|
{
|
2021-08-18 16:55:57 -04:00
|
|
|
parameters.oStream(stream);
|
|
|
|
address.oStream(stream);
|
|
|
|
*stream << expiry;
|
2021-05-27 10:59:22 -04:00
|
|
|
}
|
|
|
|
|
2021-07-29 11:20:03 -04:00
|
|
|
|
|
|
|
/**
|
2021-08-18 16:55:57 -04:00
|
|
|
* @brief disconnecting_data::iStream
|
2021-07-29 11:20:03 -04:00
|
|
|
* @param stream
|
|
|
|
*/
|
2021-08-18 16:55:57 -04:00
|
|
|
void disconnecting_data::iStream(PDU::Stream stream)
|
2021-05-27 10:59:22 -04:00
|
|
|
{
|
2021-08-18 16:55:57 -04:00
|
|
|
*stream >> protocol;
|
|
|
|
*stream >> reason;
|
2021-07-29 19:26:49 -04:00
|
|
|
}
|
|
|
|
|
2021-05-27 10:59:22 -04:00
|
|
|
|
2021-07-29 19:26:49 -04:00
|
|
|
/**
|
2021-08-18 16:55:57 -04:00
|
|
|
* @brief disconnecting_data::oStream
|
2021-07-29 19:26:49 -04:00
|
|
|
* @param stream
|
|
|
|
*/
|
2021-08-18 16:55:57 -04:00
|
|
|
void disconnecting_data::oStream(PDU::Stream stream) const
|
2021-07-29 19:26:49 -04:00
|
|
|
{
|
2021-08-18 16:55:57 -04:00
|
|
|
*stream << protocol;
|
|
|
|
*stream << reason;
|
2021-05-27 10:59:22 -04:00
|
|
|
}
|
|
|
|
|
2021-08-24 18:10:20 -04:00
|
|
|
} // namespace ACN::SDT
|