SDT i/o cleanup, with class files for session and channel
This commit is contained in:
parent
a746cb9022
commit
10606810cb
|
@ -42,6 +42,10 @@ set(SOURCE_FILES
|
|||
acn/rlp-udp.h
|
||||
acn/rlp.cpp
|
||||
acn/rlp.h
|
||||
acn/sdt-channel.h
|
||||
acn/sdt-channel.cpp
|
||||
acn/sdt-session.h
|
||||
acn/sdt-session.cpp
|
||||
acn/sdt-udp.cpp
|
||||
acn/sdt-udp.h
|
||||
acn/sdt.cpp
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "component.h"
|
||||
#include "pdu.h"
|
||||
#include "rlp.h"
|
||||
#include "sdt.h"
|
||||
#include "sdt-session.h"
|
||||
#include "uuid/uuid.h"
|
||||
|
||||
#include <map>
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
sdt-channel.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-channel.h"
|
||||
|
||||
namespace ACN {
|
||||
namespace SDT {
|
||||
|
||||
/**
|
||||
* @brief Channel::Channel
|
||||
* @param owner
|
||||
* @param direction
|
||||
*/
|
||||
Channel::Channel(std::shared_ptr<Component> owner, Direction direction) {
|
||||
owner_ = owner;
|
||||
direction_ = direction;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Channel::~Channel & closes the channel cleanly.
|
||||
*/
|
||||
Channel::~Channel() {
|
||||
// TODO: close the channel.
|
||||
}
|
||||
|
||||
} // namespace SDT
|
||||
} // namespace ACN
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
sdt-channel.h
|
||||
|
||||
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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "component.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace ACN {
|
||||
namespace SDT {
|
||||
|
||||
/**
|
||||
* @brief 3.3 Sequenced Channels
|
||||
* Sequenced channels transport three categories of traffic:
|
||||
*/
|
||||
enum Direction {
|
||||
internal, // SDT internal traffic
|
||||
downstream, // Session downstream traffic
|
||||
upstream // Session upstream traffic
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief The Channel class
|
||||
* Sequenced channels are unidirectional communication channels (unicast or
|
||||
* multicast) from an owner component to one or more member components.
|
||||
*/
|
||||
class Channel {
|
||||
public:
|
||||
Channel(std::shared_ptr<Component>, Direction);
|
||||
~Channel();
|
||||
|
||||
private:
|
||||
std::shared_ptr<Component> owner_;
|
||||
Direction direction_ = internal;
|
||||
};
|
||||
|
||||
} // namespace SDT
|
||||
} // namespace ACN
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
sdt-session.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-session.h"
|
||||
|
||||
namespace ACN {
|
||||
namespace SDT {
|
||||
|
||||
/**
|
||||
* @brief SessionId::operator == sessionID comparitor
|
||||
* @param other
|
||||
* @return
|
||||
*/
|
||||
bool SessionId::operator== (const SessionId & other) const {
|
||||
return ((other.cid == cid) &
|
||||
(other.number == number) &
|
||||
(other.protocol == protocol));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Session::Session
|
||||
*/
|
||||
Session::Session() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Session::~Session & leaves the session gracefully.
|
||||
*/
|
||||
Session::~Session() {
|
||||
// TODO: Disconnect the session.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Session::id
|
||||
* @return
|
||||
*/
|
||||
SessionId Session::id() {
|
||||
SessionId ret;
|
||||
ret.cid = leader->cid();
|
||||
ret.number = number_;
|
||||
ret.protocol = protocol_;
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace SDT
|
||||
} // namespace ACN
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
sdt-session.h
|
||||
|
||||
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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "sdt.h"
|
||||
#include "sdt-channel.h"
|
||||
|
||||
namespace ACN {
|
||||
namespace SDT {
|
||||
|
||||
|
||||
/**
|
||||
* @brief 3.1 Session Identity
|
||||
*/
|
||||
struct SessionId {
|
||||
UUID::uuid cid; // the component ID (CID) of the session leader
|
||||
uint16_t number; // the session number the leader has assigned
|
||||
uint32_t protocol; // the ID of the protocol carried by the session
|
||||
bool operator== (const SessionId &) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The Session class
|
||||
* A session has a single leader and zero or more session members. The leader
|
||||
* communicates to members using the downstream address. Members respond to
|
||||
* the leader on the upstream address. A unique session identifier identifies
|
||||
* a session.
|
||||
*/
|
||||
class Session {
|
||||
public:
|
||||
Session();
|
||||
~Session();
|
||||
|
||||
SessionId id();
|
||||
|
||||
// 4.4 SDT Base Layer Messages (non ad-hoc)
|
||||
void join_accept() {};
|
||||
void join_refuse() {};
|
||||
void leaving() {};
|
||||
void nak() {};
|
||||
void reliable_wrapper() {};
|
||||
void unreliable_wrapper() {};
|
||||
|
||||
// 4.5 SDT Wrapped Messages
|
||||
void ack();
|
||||
void channel_params();
|
||||
void leave();
|
||||
void connect();
|
||||
void connect_accept();
|
||||
void connect_refuse();
|
||||
void disconnect();
|
||||
void disconnecting();
|
||||
|
||||
protected:
|
||||
std::shared_ptr<ACN::Component> leader;
|
||||
std::shared_ptr<Channel> downstream;
|
||||
std::unordered_map<MID, std::shared_ptr<Channel>> upstream;
|
||||
|
||||
private:
|
||||
uint16_t number_;
|
||||
uint32_t protocol_;
|
||||
MID next_id_ = 1;
|
||||
};
|
||||
|
||||
|
||||
} // namespace SDT
|
||||
} // namespace ACN
|
577
acn/sdt.cpp
577
acn/sdt.cpp
|
@ -27,154 +27,56 @@
|
|||
namespace ACN {
|
||||
namespace SDT {
|
||||
|
||||
namespace CLIENT {
|
||||
|
||||
/**
|
||||
* @brief params_t::iStream
|
||||
* @brief ClientPdu::ClientPdu
|
||||
* @param stream
|
||||
*/
|
||||
void params_t::iStream(PDU::Stream stream)
|
||||
Pdu::Pdu()
|
||||
: PDU::Pdu(2) // vectors are 2 octets (MID)
|
||||
{
|
||||
*stream >> Expiry;
|
||||
uint8_t packed;
|
||||
*stream >> packed;
|
||||
NAK_Outbound = packed >> 7;
|
||||
reserved = packed & 0xef;
|
||||
*stream >> NAKholdoff;
|
||||
*stream >> NAKmodulus;
|
||||
*stream >> NAKmaxwait;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief join_data_t::iStream
|
||||
* @brief ClientPdu::iStream
|
||||
* @param stream
|
||||
*/
|
||||
void join_data_t::iStream(PDU::Stream stream)
|
||||
void Pdu::iStream(PDU::Stream stream)
|
||||
{
|
||||
*stream >> mid;
|
||||
*stream >> number;
|
||||
*stream >> reciprocal;
|
||||
*stream >> sequence;
|
||||
*stream >> reliable;
|
||||
destination.iStream(stream);
|
||||
parameters.iStream(stream);
|
||||
*stream >> expiry;
|
||||
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 join_accept_data_t::iStream
|
||||
* @brief client_pdu_header_t::iStream
|
||||
* @param stream
|
||||
*/
|
||||
void join_accept_data_t::iStream(PDU::Stream stream)
|
||||
void client_header::iStream(PDU::Stream stream)
|
||||
{
|
||||
*stream >> leader;
|
||||
*stream >> number;
|
||||
*stream >> mid;
|
||||
*stream >> reliable;
|
||||
*stream >> reciprocal;
|
||||
*stream >> protocol;
|
||||
*stream >> association;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief join_refuse_data_t::iStream
|
||||
* @brief client_header::oStream
|
||||
* @param stream
|
||||
*/
|
||||
void join_refuse_data_t::iStream(PDU::Stream stream)
|
||||
void client_header::oStream(PDU::Stream stream) const
|
||||
{
|
||||
*stream >> leader;
|
||||
*stream >> number;
|
||||
*stream >> mid;
|
||||
*stream >> reliable;
|
||||
*stream >> code;
|
||||
*stream << protocol;
|
||||
*stream << association;
|
||||
}
|
||||
|
||||
} // namespace CLIENT
|
||||
|
||||
|
||||
/**
|
||||
* @brief nak_data_t::iStream
|
||||
* @param stream
|
||||
*/
|
||||
void nak_data_t::iStream(PDU::Stream stream)
|
||||
{
|
||||
*stream >> leader;
|
||||
*stream >> number;
|
||||
*stream >> mid;
|
||||
*stream >> reliable;
|
||||
*stream >> missed_first;
|
||||
*stream >> missed_last;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief wrapper_data_t::iStream
|
||||
* @param stream
|
||||
*/
|
||||
void wrapper_data_t::iStream(PDU::Stream stream)
|
||||
{
|
||||
*stream >> number;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
compare to another sessionID
|
||||
*/
|
||||
bool SessionId::operator== (const SessionId & other) const {
|
||||
return ((other.cid == cid) &
|
||||
(other.number == number) &
|
||||
(other.protocol == protocol));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Constuct a sequenced channel with an owner and a direction.
|
||||
|
||||
@param owner the owner of the channel
|
||||
@param direction the direction of channel communication
|
||||
*/
|
||||
Channel::Channel(std::shared_ptr<Component> owner, Direction direction) {
|
||||
owner_ = owner;
|
||||
direction_ = direction;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
deconstructor that closes the channel cleanly.
|
||||
*/
|
||||
Channel::~Channel() {
|
||||
// TODO: close the channel.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Construct a new session.
|
||||
*/
|
||||
Session::Session() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
deconstructor that leaves the session gracefully.
|
||||
*/
|
||||
Session::~Session() {
|
||||
// TODO: Disconnect the session.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
get the ID of the session
|
||||
*/
|
||||
SessionId Session::id() {
|
||||
SessionId ret;
|
||||
ret.cid = leader->cid();
|
||||
ret.number = number_;
|
||||
ret.protocol = protocol_;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Pdu::Pdu
|
||||
* @brief SDT::Pdu
|
||||
*/
|
||||
Pdu::Pdu()
|
||||
: PDU::Pdu(1) // vectors are 1 octet
|
||||
|
@ -189,41 +91,436 @@ Pdu::Pdu()
|
|||
void Pdu::iStream(PDU::Stream stream)
|
||||
{
|
||||
PDU::Pdu::iStream(stream); // flags, length, and vector
|
||||
// TODO: header segment // header
|
||||
// TODO: data segment // data
|
||||
// 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 client_pdu_header_t::iStream
|
||||
* @brief params::iStream
|
||||
* @param stream
|
||||
*/
|
||||
void client_pdu_header::iStream(PDU::Stream stream)
|
||||
void params::iStream(PDU::Stream stream)
|
||||
{
|
||||
*stream >> Expiry;
|
||||
*stream >> flags;
|
||||
*stream >> NAKholdoff;
|
||||
*stream >> NAKmodulus;
|
||||
*stream >> NAKmaxwait;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @param stream
|
||||
*/
|
||||
void join_data::iStream(PDU::Stream stream)
|
||||
{
|
||||
*stream >> cid;
|
||||
*stream >> mid;
|
||||
*stream >> channel;
|
||||
*stream >> reciprocal;
|
||||
*stream >> sequence;
|
||||
*stream >> reliable;
|
||||
destination.iStream(stream);
|
||||
parameters.iStream(stream);
|
||||
*stream >> expiry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @param stream
|
||||
*/
|
||||
void join_accept_data::iStream(PDU::Stream stream)
|
||||
{
|
||||
*stream >> leader;
|
||||
*stream >> number;
|
||||
*stream >> mid;
|
||||
*stream >> reliable;
|
||||
*stream >> reciprocal;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief join_accept_data::oStream
|
||||
* @param stream
|
||||
*/
|
||||
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)
|
||||
{
|
||||
*stream >> leader;
|
||||
*stream >> number;
|
||||
*stream >> mid;
|
||||
*stream >> reliable;
|
||||
*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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief nak_data_t::iStream
|
||||
* @param stream
|
||||
*/
|
||||
void nak_data::iStream(PDU::Stream stream)
|
||||
{
|
||||
*stream >> leader;
|
||||
*stream >> number;
|
||||
*stream >> mid;
|
||||
*stream >> reliable;
|
||||
*stream >> missed_first;
|
||||
*stream >> missed_last;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief nak_data::oStream
|
||||
* @param stream
|
||||
*/
|
||||
void nak_data::oStream(PDU::Stream stream) const
|
||||
{
|
||||
*stream << leader;
|
||||
*stream << number;
|
||||
*stream << mid;
|
||||
*stream << reliable;
|
||||
*stream << missed_first;
|
||||
*stream << missed_last;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief wrapper_data::streamSize
|
||||
* @return
|
||||
*/
|
||||
size_t wrapper_data::streamSize() const
|
||||
{
|
||||
return 20 + block.streamSize();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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>());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief sessions_data::oStream
|
||||
* @param stream
|
||||
*/
|
||||
void sessions_data::oStream(PDU::Stream stream) const
|
||||
{
|
||||
for (const auto & info : list)
|
||||
info.oStream(stream);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief channel_params_data::streamSize
|
||||
* @return
|
||||
*/
|
||||
size_t channel_params_data::streamSize() const
|
||||
{
|
||||
return 1
|
||||
+ parameters.streamSize()
|
||||
+ address.streamSize();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief channel_params_data::iStream
|
||||
* @param stream
|
||||
*/
|
||||
void channel_params_data::iStream(PDU::Stream stream)
|
||||
{
|
||||
parameters.iStream(stream);
|
||||
address.iStream(stream);
|
||||
*stream >> expiry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief channel_params_data::oStream
|
||||
* @param stream
|
||||
*/
|
||||
void channel_params_data::oStream(PDU::Stream stream) const
|
||||
{
|
||||
parameters.oStream(stream);
|
||||
address.oStream(stream);
|
||||
*stream << expiry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief disconnecting_data::iStream
|
||||
* @param stream
|
||||
*/
|
||||
void disconnecting_data::iStream(PDU::Stream stream)
|
||||
{
|
||||
*stream >> protocol;
|
||||
*stream >> association;
|
||||
*stream >> reason;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief ClientPdu::ClientPdu
|
||||
* @brief disconnecting_data::oStream
|
||||
* @param stream
|
||||
*/
|
||||
ClientPdu::ClientPdu()
|
||||
: PDU::Pdu(2) // vectors are 2 octets (MID)
|
||||
void disconnecting_data::oStream(PDU::Stream stream) const
|
||||
{
|
||||
*stream << protocol;
|
||||
*stream << reason;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief ClientPdu::iStream
|
||||
* @param stream
|
||||
*/
|
||||
void ClientPdu::iStream(PDU::Stream stream)
|
||||
{
|
||||
PDU::Pdu::iStream(stream); // flags, length, and vector
|
||||
createHeader<client_pdu_header>(); // header
|
||||
// TODO: data segment // data
|
||||
}
|
||||
|
||||
}; // SDT
|
||||
}; // ACN
|
||||
} // namespace SDT
|
||||
} // namespace ACN
|
||||
|
|
646
acn/sdt.h
646
acn/sdt.h
|
@ -23,288 +23,17 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include "component.h"
|
||||
#include "pdu.h"
|
||||
#include "sdt-udp.h" // EPI 18
|
||||
|
||||
#include <vector>
|
||||
|
||||
// ANSI E1.17- 2015, Architecture for Control Networks–
|
||||
// Session Data Transport Protocol
|
||||
namespace ACN {
|
||||
namespace SDT {
|
||||
|
||||
/**
|
||||
* @brief 3.1 Session Identity
|
||||
*/
|
||||
struct SessionId {
|
||||
UUID::uuid cid; // the component ID (CID) of the session leader
|
||||
uint16_t number; // the session number the leader has assigned
|
||||
uint32_t protocol; // the ID of the protocol carried by the session
|
||||
bool operator== (const SessionId &) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 3.3 Sequenced Channels
|
||||
* Sequenced channels transport three categories of traffic:
|
||||
*/
|
||||
enum Direction {
|
||||
internal, // SDT internal traffic
|
||||
downstream, // Session downstream traffic
|
||||
upstream // Session upstream traffic
|
||||
};
|
||||
|
||||
|
||||
// 3.5.1.1 Member Identifiers
|
||||
using MID = uint16_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.4.1.2 Channel Parameter Block
|
||||
*/
|
||||
struct params_t
|
||||
{
|
||||
uint8_t Expiry; // number of seconds without traffic before leaving
|
||||
struct {
|
||||
uint8_t NAK_Outbound : 1; // NAK to channel (1) or destination address (0)
|
||||
uint8_t reserved : 7;
|
||||
};
|
||||
uint16_t NAKholdoff; // calculation of a standoff time for sending NAKs
|
||||
uint16_t NAKmodulus; // calculation of a standoff time for sending NAKs
|
||||
uint16_t NAKmaxwait; // maximum milliseconds to wait before sending a NAK.
|
||||
void iStream(PDU::Stream);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.4.1 Join
|
||||
*/
|
||||
struct join_data_t
|
||||
: PDU::pdu_data
|
||||
{
|
||||
MID mid;
|
||||
uint16_t number;
|
||||
uint16_t reciprocal;
|
||||
uint32_t sequence;
|
||||
uint32_t reliable;
|
||||
UDP::address_t destination;
|
||||
params_t parameters;
|
||||
uint8_t expiry;
|
||||
|
||||
size_t streamSize() const override { return 0; }
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.4.2 Join Accept
|
||||
*/
|
||||
struct join_accept_data_t
|
||||
: PDU::pdu_data
|
||||
{
|
||||
UUID::uuid leader;
|
||||
uint16_t number;
|
||||
MID mid;
|
||||
uint32_t reliable;
|
||||
uint16_t reciprocal;
|
||||
|
||||
size_t streamSize() const override { return 26; }
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.4.3 Join Refuse & 4.4.4 Leaving
|
||||
*/
|
||||
struct join_refuse_data_t
|
||||
: PDU::pdu_data
|
||||
{
|
||||
UUID::uuid leader;
|
||||
uint16_t number;
|
||||
MID mid;
|
||||
uint32_t reliable;
|
||||
uint8_t code;
|
||||
|
||||
size_t streamSize() const override { return 25; }
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.4.5 NAK
|
||||
*/
|
||||
struct nak_data_t
|
||||
: PDU::pdu_data
|
||||
{
|
||||
UUID::uuid leader;
|
||||
uint16_t number;
|
||||
MID mid;
|
||||
uint32_t reliable;
|
||||
uint32_t missed_first;
|
||||
uint32_t missed_last;
|
||||
|
||||
size_t streamSize() const override { return 32; }
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.4.6 Reliable Wrapper and Unreliable Wrapper
|
||||
*/
|
||||
struct wrapper_data_t
|
||||
: PDU::pdu_data
|
||||
{
|
||||
uint16_t number;
|
||||
uint32_t sequence;
|
||||
uint32_t reliable;
|
||||
uint32_t oldest;
|
||||
MID ack_range_begin;
|
||||
MID ack_range_end;
|
||||
uint16_t MAK_threshold;
|
||||
|
||||
size_t streamSize() const override { return 20; }
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.4.7 SDT Client Block
|
||||
*/
|
||||
struct client_pdu_header
|
||||
: PDU::pdu_header
|
||||
{
|
||||
uint32_t protocol;
|
||||
uint16_t association;
|
||||
|
||||
size_t streamSize() const override { return 6; };
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief The ClientPdu class
|
||||
*/
|
||||
class ClientPdu
|
||||
: public PDU::Pdu
|
||||
{
|
||||
public:
|
||||
ClientPdu();
|
||||
void iStream(PDU::Stream) override;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.4.8 Get Sessions
|
||||
*/
|
||||
struct get_sessions_data_t
|
||||
: PDU::pdu_data
|
||||
{
|
||||
UUID::uuid cid;
|
||||
|
||||
size_t streamSize() const override { return 0; }
|
||||
void iStream(PDU::Stream) override {};
|
||||
void oStream(PDU::Stream) const override {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.4.9.1 Channel Owner Info Block
|
||||
*/
|
||||
struct channel_info_block_t
|
||||
{
|
||||
MID mid;
|
||||
UUID::uuid owner;
|
||||
uint16_t number;
|
||||
UDP::address_t destination;
|
||||
UDP::address_t source;
|
||||
uint16_t reciprocal;
|
||||
uint16_t count;
|
||||
std::list<uint32_t> protocols;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.4.9 Sessions
|
||||
*/
|
||||
struct sessions_data_t
|
||||
: PDU::pdu_data
|
||||
{
|
||||
std::list<channel_info_block_t> list;
|
||||
|
||||
size_t streamSize() const override { return 0; }
|
||||
void iStream(PDU::Stream) override {};
|
||||
void oStream(PDU::Stream) const override {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.5.1 ACK
|
||||
*/
|
||||
struct ack_data_t
|
||||
: PDU::pdu_data
|
||||
{
|
||||
uint32_t reliable;
|
||||
|
||||
size_t streamSize() const override { return 4; }
|
||||
void iStream(PDU::Stream) override {};
|
||||
void oStream(PDU::Stream) const override {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.5.2 Channel Params
|
||||
*/
|
||||
struct channel_params_data_t
|
||||
: PDU::pdu_data
|
||||
{
|
||||
params_t parameters;
|
||||
UDP::address_t address;
|
||||
uint8_t expiry;
|
||||
|
||||
size_t streamSize() const override { return 0; }
|
||||
void iStream(PDU::Stream) override {};
|
||||
void oStream(PDU::Stream) const override {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.5.3 Connect, 4.5.4 Connect Accept, & 4.5.6 Disconnect
|
||||
*/
|
||||
struct connect_data_t
|
||||
: PDU::pdu_data
|
||||
{
|
||||
uint32_t protocol;
|
||||
|
||||
size_t streamSize() const override { return 4; }
|
||||
void iStream(PDU::Stream) override {};
|
||||
void oStream(PDU::Stream) const override {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.5.5 Connect Refuse & 4.5.7 Disconnecting
|
||||
*/
|
||||
struct connect_refuse_data_t
|
||||
: PDU::pdu_data
|
||||
{
|
||||
uint32_t protocol;
|
||||
uint8_t code;
|
||||
|
||||
size_t streamSize() const override { return 0; }
|
||||
void iStream(PDU::Stream) override {};
|
||||
void oStream(PDU::Stream) const override {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 7.1 Protocol Code
|
||||
*/
|
||||
|
@ -312,60 +41,91 @@ static const uint32_t SDT_PROTOCOL_ID = 1; // PDU protocol value
|
|||
|
||||
|
||||
/**
|
||||
* @brief 7.2 PDU Vector Codes
|
||||
* @brief SDT vector codes
|
||||
*/
|
||||
enum sdt_vector_t {
|
||||
REL_WRAP = 1,
|
||||
UNREL_WRAP = 2,
|
||||
CHANNEL_PARAMS = 3,
|
||||
JOIN = 4,
|
||||
JOIN_REFUSE = 5,
|
||||
JOIN_ACCEPT = 6,
|
||||
LEAVE = 7,
|
||||
LEAVING = 8,
|
||||
CONNECT = 9,
|
||||
CONNECT_ACCEPT = 10,
|
||||
CONNECT_REFUSE = 11,
|
||||
DISCONNECT = 12,
|
||||
DISCONNECTING = 13,
|
||||
ACK = 14,
|
||||
NAK = 15,
|
||||
GET_SESSIONS = 16,
|
||||
SESSIONS = 17,
|
||||
};
|
||||
const static uint8_t REL_WRAP = 1; //!< 4.4 SDT Base Layer Message
|
||||
const static uint8_t UNREL_WRAP = 2; //!< 4.4 SDT Base Layer Message
|
||||
const static uint8_t CHANNEL_PARAMS = 3; //!< 4.5 SDT Wrapped Messages
|
||||
const static uint8_t JOIN = 4; //!< 4.4 SDT Base Layer Message
|
||||
const static uint8_t JOIN_REFUSE = 5; //!< 4.4 SDT Base Layer Message
|
||||
const static uint8_t JOIN_ACCEPT = 6; //!< 4.4 SDT Base Layer Message
|
||||
const static uint8_t LEAVE = 7; //!< 4.4 SDT Base Layer Message
|
||||
const static uint8_t LEAVING = 8; //!< 4.5 SDT Wrapped Messages
|
||||
const static uint8_t CONNECT = 9; //!< 4.5 SDT Wrapped Messages
|
||||
const static uint8_t CONNECT_ACCEPT = 10; //!< 4.5 SDT Wrapped Messages
|
||||
const static uint8_t CONNECT_REFUSE = 11; //!< 4.5 SDT Wrapped Messages
|
||||
const static uint8_t DISCONNECT = 12; //!< 4.5 SDT Wrapped Messages
|
||||
const static uint8_t DISCONNECTING = 13; //!< 4.5 SDT Wrapped Messages
|
||||
const static uint8_t ACK = 14; //!< 4.5 SDT Wrapped Messages
|
||||
const static uint8_t NAK = 15; //!< 4.4 SDT Base Layer Message
|
||||
const static uint8_t GET_SESSIONS = 16; //!< 4.4 SDT Base Layer Message
|
||||
const static uint8_t SESSIONS = 17; //!< 4.4 SDT Base Layer Message
|
||||
|
||||
// 7.4 Other Symbolic Parameters
|
||||
|
||||
/**
|
||||
* @brief Table 6: Reason Codes
|
||||
*/
|
||||
enum reason_code_t {
|
||||
NONSPECIFIC = 1, // Non-specific, non-SDT reason.
|
||||
ILLEGAL_PARAMETERS = 2, // Illegal channel parameters.
|
||||
LOW_RESOURCES = 3, // Insufficient resources.
|
||||
ALREADY_MEMBER = 4, // Multiple MIDs for single component.
|
||||
BAD_ADDRESS_TYPE = 5, // Unrecognized transport address type.
|
||||
NO_RECIPROCAL_CHANNEL = 6, // No upstream channel and can’t create one
|
||||
CHANNEL_EXPIRED = 7, // Channel has expired.
|
||||
LOST_SEQUENCE = 8, // Unrecoverable packets missed.
|
||||
SATURATED = 9, // Can’t keep up, processor saturation.
|
||||
TRANSPORT_ADDRESS_CHANGING = 10, // (e.g., IP number lease expired).
|
||||
ASKED_TO_LEAVE = 11, // Asked to leave the channel.
|
||||
NO_RECIPIENT = 12, // Component does not support protocol ID.
|
||||
ONLY_UNICAST_SUPPORTED = 13 // Only unicast channels are supported
|
||||
};
|
||||
const static uint8_t NONSPECIFIC = 1; //!< Non-specific, non-SDT reason.
|
||||
const static uint8_t ILLEGAL_PARAMETERS = 2; //!< Illegal channel parameters.
|
||||
const static uint8_t LOW_RESOURCES = 3; //!< Insufficient resources.
|
||||
const static uint8_t ALREADY_MEMBER = 4; //!< Multiple MIDs for single component.
|
||||
const static uint8_t BAD_ADDRESS_TYPE = 5; //!< Unrecognized transport address type.
|
||||
const static uint8_t NO_RECIPROCAL_CHANNEL = 6; //!< No upstream channel and can’t create one
|
||||
const static uint8_t CHANNEL_EXPIRED = 7; //!< Channel has expired.
|
||||
const static uint8_t LOST_SEQUENCE = 8; //!< Unrecoverable packets missed.
|
||||
const static uint8_t SATURATED = 9; //!< Can’t keep up, processor saturation.
|
||||
const static uint8_t TRANSPORT_ADDRESS_CHANGING = 10; //!< (e.g., IP number lease expired).
|
||||
const static uint8_t ASKED_TO_LEAVE = 11; //!< Asked to leave the channel.
|
||||
const static uint8_t NO_RECIPIENT = 12; //!< Component does not support protocol ID.
|
||||
const static uint8_t ONLY_UNICAST_SUPPORTED = 13; //!< Only unicast channels are supported
|
||||
|
||||
|
||||
/**
|
||||
* @brief Table 7: Address Specification Types
|
||||
*/
|
||||
enum ip_addr_spec_t {
|
||||
enum ip_addr_spec {
|
||||
SDT_ADDR_NULL = 0, //!< Address is not present (0 octets).
|
||||
SDT_ADDR_IPV4 = 1, //!< Address specified is in IP v4 format
|
||||
SDT_ADDR_IPV6 = 2 //!< Address specified is in IP v6 format
|
||||
};
|
||||
|
||||
|
||||
/// 3.5.1.1 Member Identifiers
|
||||
using MID = uint16_t;
|
||||
|
||||
|
||||
namespace CLIENT {
|
||||
|
||||
/**
|
||||
* @brief The CLIENT::Pdu class
|
||||
*/
|
||||
class Pdu
|
||||
: public PDU::Pdu
|
||||
{
|
||||
public:
|
||||
Pdu();
|
||||
void iStream(PDU::Stream) override;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.4.7 SDT Client Block
|
||||
*/
|
||||
struct client_header
|
||||
: PDU::pdu_header
|
||||
{
|
||||
uint32_t protocol;
|
||||
uint16_t association;
|
||||
|
||||
size_t streamSize() const override { return 6; };
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override;
|
||||
};
|
||||
|
||||
|
||||
} // namespace CLIENT
|
||||
|
||||
|
||||
/**
|
||||
* @brief The SDT::Pdu class
|
||||
*/
|
||||
|
@ -378,63 +138,237 @@ public:
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief The Channel class
|
||||
* Sequenced channels are unidirectional communication channels (unicast or
|
||||
* multicast) from an owner component to one or more member components.
|
||||
*/
|
||||
class Channel {
|
||||
public:
|
||||
Channel(std::shared_ptr<Component>, Direction);
|
||||
~Channel();
|
||||
|
||||
private:
|
||||
std::shared_ptr<Component> owner_;
|
||||
Direction direction_ = internal;
|
||||
/**
|
||||
* @brief 4.4.1.2 Channel Parameter Block
|
||||
*/
|
||||
struct params
|
||||
: PDU::pdu_stream_object
|
||||
{
|
||||
uint8_t Expiry; //!< number of seconds without traffic before leaving
|
||||
union {
|
||||
uint8_t flags = 0; //!< packed field of parameter flags
|
||||
struct {
|
||||
uint8_t reserved : 7;
|
||||
bool NAK_Outbound : 1; //!< NAK to channel (true) or destination address (false)
|
||||
};
|
||||
};
|
||||
|
||||
uint16_t NAKholdoff; //!< calculation of a standoff time for sending NAKs
|
||||
uint16_t NAKmodulus; //!< calculation of a standoff time for sending NAKs
|
||||
uint16_t NAKmaxwait; //!< maximum milliseconds to wait before sending a NAK.
|
||||
|
||||
size_t streamSize() const override { return 8; }
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief The Session class
|
||||
* A session has a single leader and zero or more session members. The leader
|
||||
* communicates to members using the downstream address. Members respond to
|
||||
* the leader on the upstream address. A unique session identifier identifies
|
||||
* a session.
|
||||
* @brief 4.4.1 Join
|
||||
*/
|
||||
class Session {
|
||||
public:
|
||||
Session();
|
||||
~Session();
|
||||
struct join_data
|
||||
: PDU::pdu_data
|
||||
{
|
||||
UUID::uuid cid;
|
||||
MID mid;
|
||||
uint16_t channel;
|
||||
uint16_t reciprocal;
|
||||
uint32_t sequence;
|
||||
uint32_t reliable;
|
||||
UDP::ipAddress destination;
|
||||
params parameters;
|
||||
uint8_t expiry;
|
||||
|
||||
SessionId id();
|
||||
size_t streamSize() const override;
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override;
|
||||
};
|
||||
|
||||
// 4.4 SDT Base Layer Messages (non ad-hoc)
|
||||
void join_accept() {};
|
||||
void join_refuse() {};
|
||||
void leaving() {};
|
||||
void nak() {};
|
||||
void reliable_wrapper() {};
|
||||
void unreliable_wrapper() {};
|
||||
|
||||
// 4.5 SDT Wrapped Messages
|
||||
void ack();
|
||||
void channel_params();
|
||||
void leave();
|
||||
void connect();
|
||||
void connect_accept();
|
||||
void connect_refuse();
|
||||
void disconnect();
|
||||
void disconnecting();
|
||||
/**
|
||||
* @brief 4.4.2 Join Accept
|
||||
*/
|
||||
struct join_accept_data
|
||||
: PDU::pdu_data
|
||||
{
|
||||
UUID::uuid leader;
|
||||
uint16_t number;
|
||||
MID mid;
|
||||
uint32_t reliable;
|
||||
uint16_t reciprocal;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<ACN::Component> leader;
|
||||
std::shared_ptr<Channel> downstream;
|
||||
std::unordered_map<MID, std::shared_ptr<Channel>> upstream;
|
||||
size_t streamSize() const override { return 26; }
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override;
|
||||
};
|
||||
|
||||
private:
|
||||
uint16_t number_;
|
||||
uint32_t protocol_;
|
||||
MID next_id_ = 1;
|
||||
|
||||
/**
|
||||
* @brief 4.4.3 Join Refuse & 4.4.4 Leaving
|
||||
*/
|
||||
struct join_refuse_data
|
||||
: PDU::pdu_data
|
||||
{
|
||||
UUID::uuid leader;
|
||||
uint16_t number;
|
||||
MID mid;
|
||||
uint32_t reliable;
|
||||
uint8_t reason;
|
||||
|
||||
size_t streamSize() const override { return 25; }
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.4.5 NAK
|
||||
*/
|
||||
struct nak_data
|
||||
: PDU::pdu_data
|
||||
{
|
||||
UUID::uuid leader;
|
||||
uint16_t number;
|
||||
MID mid;
|
||||
uint32_t reliable;
|
||||
uint32_t missed_first;
|
||||
uint32_t missed_last;
|
||||
|
||||
size_t streamSize() const override { return 32; }
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.4.6 Reliable Wrapper and Unreliable Wrapper
|
||||
*/
|
||||
struct wrapper_data
|
||||
: PDU::pdu_data
|
||||
{
|
||||
uint16_t channel;
|
||||
uint32_t sequence;
|
||||
uint32_t reliable;
|
||||
uint32_t oldest;
|
||||
MID ack_range_begin;
|
||||
MID ack_range_end;
|
||||
uint16_t MAK_threshold;
|
||||
PDU::Block<CLIENT::Pdu> block;
|
||||
|
||||
size_t streamSize() const override;
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.4.8 Get Sessions
|
||||
*/
|
||||
struct get_sessions_data
|
||||
: PDU::pdu_data
|
||||
{
|
||||
UUID::uuid cid;
|
||||
|
||||
size_t streamSize() const override { return UUID_LENGTH; }
|
||||
void iStream(PDU::Stream s) override { *s >> cid; }
|
||||
void oStream(PDU::Stream s) const override { *s << cid; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.4.9.1 Channel Owner Info Block
|
||||
* 4.4.9.2 Channel Member Info Block
|
||||
*/
|
||||
struct channel_info_block
|
||||
: PDU::pdu_stream_object
|
||||
{
|
||||
MID mid;
|
||||
UUID::uuid owner;
|
||||
uint16_t channel;
|
||||
UDP::ipAddress destination;
|
||||
UDP::ipAddress source;
|
||||
uint16_t reciprocal;
|
||||
uint16_t sessions;
|
||||
std::vector<uint32_t> protocols;
|
||||
|
||||
size_t streamSize() const override;
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.4.9 Sessions
|
||||
*/
|
||||
struct sessions_data
|
||||
: PDU::pdu_data
|
||||
{
|
||||
std::vector<channel_info_block> list;
|
||||
|
||||
size_t streamSize() const override;
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.5.1 ACK
|
||||
*/
|
||||
struct ack_data
|
||||
: PDU::pdu_data
|
||||
{
|
||||
uint32_t sequence;
|
||||
|
||||
size_t streamSize() const override { return 4; }
|
||||
void iStream(PDU::Stream s) override { *s >> sequence; }
|
||||
void oStream(PDU::Stream s) const override { *s << sequence; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.5.2 Channel Params
|
||||
*/
|
||||
struct channel_params_data
|
||||
: PDU::pdu_data
|
||||
{
|
||||
params parameters;
|
||||
UDP::ipAddress address;
|
||||
uint8_t expiry;
|
||||
|
||||
size_t streamSize() const override;
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.5.3 Connect, 4.5.4 Connect Accept, & 4.5.6 Disconnect
|
||||
*/
|
||||
struct connect_data
|
||||
: PDU::pdu_data
|
||||
{
|
||||
uint32_t protocol;
|
||||
|
||||
size_t streamSize() const override { return 4; }
|
||||
void iStream(PDU::Stream s) override { *s >> protocol; }
|
||||
void oStream(PDU::Stream s) const override { *s << protocol; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 4.5.5 Connect Refuse & 4.5.7 Disconnecting
|
||||
*/
|
||||
struct disconnecting_data
|
||||
: PDU::pdu_data
|
||||
{
|
||||
uint32_t protocol;
|
||||
uint8_t reason;
|
||||
|
||||
size_t streamSize() const override { return 5; }
|
||||
void iStream(PDU::Stream) override;
|
||||
void oStream(PDU::Stream) const override;
|
||||
};
|
||||
|
||||
} // SDT
|
||||
|
|
Loading…
Reference in New Issue