continuing SDT development
This commit is contained in:
parent
149f5b809d
commit
8f0822f719
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "appliance.h"
|
||||
|
||||
#include "dmp.h"
|
||||
#include "sdt.h"
|
||||
#include "rlp.h"
|
||||
#include "rlp-udp.h"
|
||||
|
@ -35,7 +36,11 @@ Appliance::Appliance(UUID::uuid cid)
|
|||
: Component(cid)
|
||||
{
|
||||
registerRlpVectorHandler(SDT::SDT_PROTOCOL_ID,
|
||||
std::bind(&Appliance::rootSdtHandler, this, std::placeholders::_1));
|
||||
std::bind(&Appliance::rootSdtHandler, this,
|
||||
std::placeholders::_1));
|
||||
registerRlpVectorHandler(DMP::DMP_PROTOCOL_ID,
|
||||
std::bind(&Appliance::rootDmpHandler, this,
|
||||
std::placeholders::_1));
|
||||
};
|
||||
|
||||
|
||||
|
@ -74,6 +79,9 @@ void Appliance::UdpStreamHandler(PDU::Stream stream) {
|
|||
void Appliance::TcpStreamHandler(PDU::Stream stream) {
|
||||
// verify the TCP preamble
|
||||
RLP::TCP::preamble_t preamble(stream);
|
||||
|
||||
// implementations shall check the ACN Packet Identifier. If the ACN Packet
|
||||
// Identifier is not correct the receiver shall close the connection.
|
||||
if (!preamble)
|
||||
stream->setstate(stream->rdstate() | std::ios_base::failbit);
|
||||
|
||||
|
@ -129,7 +137,15 @@ void Appliance::deregisterRlpVector() {
|
|||
/**
|
||||
|
||||
*/
|
||||
void Appliance::rootSdtHandler(std::shared_ptr<RLP::Pdu>) {
|
||||
void Appliance::rootSdtHandler(std::shared_ptr<RLP::Pdu> rlp) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
*/
|
||||
void Appliance::rootDmpHandler(std::shared_ptr<RLP::Pdu> rlp) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,9 @@ protected:
|
|||
virtual void GetSessions() {};
|
||||
virtual void Sessions() {};
|
||||
|
||||
// process DMP frames
|
||||
virtual void rootDmpHandler(std::shared_ptr<RLP::Pdu>);
|
||||
|
||||
private:
|
||||
std::map<uint32_t, std::vector<PDU::Handler<RLP::Pdu>>> rlp_vectors_;
|
||||
std::vector<std::shared_ptr<SDT::Session>> sessions_;
|
||||
|
|
|
@ -24,28 +24,20 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "sdt.h"
|
||||
|
||||
// ACN EPI 17. Operation of SDT on UDP Networks
|
||||
// ACN EPI 18 - Operation of SDT on UDP Networks
|
||||
namespace ACN {
|
||||
namespace SDT {
|
||||
namespace UDP {
|
||||
|
||||
using std::uint8_t;
|
||||
using std::uint16_t;
|
||||
|
||||
// Table 1. IPv4 Address Specification
|
||||
struct acn_sdt_udp_ipv4_addr_t {
|
||||
ip_addr_spec_t type; // SDT_ADDR_IPV4
|
||||
// 3 Address Specification
|
||||
struct address_t {
|
||||
uint8_t type;
|
||||
uint16_t udp_port;
|
||||
uint8_t ipv4[4];
|
||||
};
|
||||
|
||||
// Table 2. IPv6 Address Specification
|
||||
struct acn_sdt_udp_ipv6_addr_t {
|
||||
ip_addr_spec_t type; // SDT_ADDR_IPV6
|
||||
uint16_t udp_port;
|
||||
uint8_t ipv4[16];
|
||||
union {
|
||||
uint8_t ipv4[4];
|
||||
uint8_t ipv6[16];
|
||||
};
|
||||
};
|
||||
|
||||
// Table 3. SDT symbolic parameters
|
||||
|
|
|
@ -38,27 +38,73 @@ bool SessionId::operator== (const SessionId & other) const {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
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;
|
||||
ret.number = number_;
|
||||
ret.protocol = protocol_;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Pdu::Pdu(PDU::Stream stream)
|
||||
: PDU::Pdu(stream, 1) // vectors are 1 octet
|
||||
{
|
||||
// if (stream->fail()) return;
|
||||
// if (!buffer_->good()) return;
|
||||
}
|
||||
|
||||
client_pdu_header_t::client_pdu_header_t(PDU::Stream stream) {
|
||||
protocol = stream->read32();
|
||||
association = stream->read16();
|
||||
}
|
||||
|
||||
ClientPdu::ClientPdu(PDU::Stream stream)
|
||||
: PDU::Pdu(stream, 2) // vectors are 2 octets (MID)
|
||||
{
|
||||
if (stream->fail()) return;
|
||||
if (!buffer_->good()) return;
|
||||
|
||||
// SDT client blocks are the only SDT type to have a header.
|
||||
// SDT client blocks have a different vector length?!?
|
||||
// if (flags_.hasHeader)
|
||||
// setHeader(new sdt_header(buffer_));
|
||||
if (flags_.hasHeader)
|
||||
setHeader(new client_pdu_header_t(buffer_));
|
||||
}
|
||||
|
||||
}; // SDT
|
||||
|
|
|
@ -24,10 +24,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include "component.h"
|
||||
#include "pdu.h"
|
||||
#include "sdt-udp.h" // EPI 18
|
||||
|
||||
// ANSI E1.17- 2015, Architecture for Control Networks–
|
||||
// Session Data Transport Protocol
|
||||
|
@ -50,26 +52,147 @@ enum Direction {
|
|||
upstream // Session upstream traffic
|
||||
};
|
||||
|
||||
struct Channel {
|
||||
std::shared_ptr<Component> owner;
|
||||
Direction direction = internal;
|
||||
};
|
||||
|
||||
// 3.5.1.1 Member Identifiers
|
||||
using MID = uint16_t;
|
||||
|
||||
|
||||
struct Session {
|
||||
uint16_t number;
|
||||
uint32_t protocol;
|
||||
std::shared_ptr<ACN::Component> leader;
|
||||
std::shared_ptr<Channel> downstream;
|
||||
std::unordered_map<MID, std::shared_ptr<Channel>> upstream;
|
||||
SessionId id();
|
||||
private:
|
||||
MID next_id_ = 1;
|
||||
// 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 zero : 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.
|
||||
};
|
||||
|
||||
// 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;
|
||||
uint32_t expiry;
|
||||
};
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
// 4.4.3 Join Refuse
|
||||
struct join_refuse_data_t : PDU::pdu_data {
|
||||
UUID::uuid leader;
|
||||
uint16_t number;
|
||||
MID mid;
|
||||
uint32_t reliable;
|
||||
uint8_t code;
|
||||
};
|
||||
|
||||
// 4.4.4 Leaving
|
||||
struct leaving_data_t : PDU::pdu_data {
|
||||
UUID::uuid leader;
|
||||
uint16_t number;
|
||||
MID mid;
|
||||
uint32_t reliable;
|
||||
uint8_t code;
|
||||
};
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
// 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;
|
||||
// SDT client block
|
||||
};
|
||||
|
||||
// 4.4.7 SDT Client Block
|
||||
struct client_pdu_header_t : PDU::pdu_header {
|
||||
uint32_t protocol;
|
||||
uint16_t association;
|
||||
client_pdu_header_t(PDU::Stream);
|
||||
};
|
||||
|
||||
// Client Block PDU
|
||||
class ClientPdu
|
||||
: public PDU::Pdu
|
||||
{
|
||||
public:
|
||||
ClientPdu(PDU::Stream);
|
||||
};
|
||||
|
||||
// 4.4.8 Get Sessions
|
||||
struct get_sessions_data_t : PDU::pdu_data {
|
||||
UUID::uuid cid;
|
||||
};
|
||||
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
// 4.4.9 Sessions
|
||||
struct sessions_data_t : PDU::pdu_data {
|
||||
std::list<channel_info_block_t> list;
|
||||
};
|
||||
|
||||
// 4.5.1 ACK
|
||||
struct ack_data_t : PDU::pdu_data {
|
||||
uint32_t reliable;
|
||||
};
|
||||
|
||||
// 4.5.2 Channel Params
|
||||
struct channel_params_data_t : PDU::pdu_data {
|
||||
params_t parameters;
|
||||
UDP::address_t address;
|
||||
uint8_t expiry;
|
||||
};
|
||||
|
||||
// 4.5.3 Connect
|
||||
// 4.5.4 Connect Accept
|
||||
// 4.5.6 Disconnect
|
||||
struct connect_data_t : PDU::pdu_data {
|
||||
uint32_t protocol;
|
||||
};
|
||||
|
||||
// 4.5.5 Connect Refuse
|
||||
// 4.5.7 Disconnecting
|
||||
struct connect_refuse_data_t : PDU::pdu_data {
|
||||
uint32_t protocol;
|
||||
uint8_t code;
|
||||
};
|
||||
|
||||
|
||||
// 7.1 Protocol Code
|
||||
static const uint32_t SDT_PROTOCOL_ID = 1; // PDU protocol value
|
||||
|
||||
|
@ -94,13 +217,33 @@ enum sdt_vector_t {
|
|||
SESSIONS = 17,
|
||||
};
|
||||
|
||||
// Table 7: Address Specification Types
|
||||
enum ip_addr_spec_t {
|
||||
SDT_ADDR_NULL = 0,
|
||||
SDT_ADDR_IPV4 = 1,
|
||||
SDT_ADDR_IPV6 = 2
|
||||
// 7.4 Other Symbolic Parameters
|
||||
|
||||
// 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
|
||||
};
|
||||
|
||||
// Table 7: Address Specification Types
|
||||
enum ip_addr_spec_t {
|
||||
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
|
||||
};
|
||||
|
||||
// PDU type for this protocol
|
||||
class Pdu
|
||||
: public PDU::Pdu
|
||||
{
|
||||
|
@ -108,5 +251,59 @@ public:
|
|||
Pdu(PDU::Stream);
|
||||
};
|
||||
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
} // SDT
|
||||
} // ACN
|
||||
|
|
Loading…
Reference in New Issue