#pragma once #include "Relay.h" namespace MWR::C3::Core { /// Relay class specialization that implements a "client" Relay. struct NodeRelay : Relay, ProceduresG2X::RequestHandler { /// Factory method. /// @param callbackOnLog callback fired whenever a new Log entry is being added. /// @param interfaceFactory reference to interface factory. /// @param gatewaySignature public signature used by Network's Gateway to authenticate itself. /// @param broadcastKey Network's symmetric key. /// @param gatewayInitialPackets initial Procedures for this NodeRelay. Should contain creation of a at least a single Channel. /// @param buildId Build identifier. /// @param agentId Agent identifier. /// @param asymmetricKeys asymmetric keys used to communicate with the Gateway. static std::shared_ptr CreateAndRun(LoggerCallback callbackOnLog, InterfaceFactory& interfaceFactory, Crypto::PublicSignature const& gatewaySignature, Crypto::SymmetricKey const& broadcastKey, std::vector const& gatewayInitialPackets, BuildId buildId, AgentId agentId = AgentId::GenerateRandom(), Crypto::AsymmetricKeys const& asymmetricKeys = Crypto::GenerateAsymmetricKeys()); protected: /// A protected constructor. @see Relay::Relay. /// @param callbackOnLog callback fired whenever a new Log entry is being added. /// @param interfaceFactory reference to interface factory. /// @param gatewaySignature public signature used by Network's Gateway to authenticate itself. /// @param broadcastKey Network's symmetric key. /// @param buildId Build identifier. /// @param agentId Agent identifier. /// @param asymmetricKeys asymmetric keys used to communicate with the Gateway. NodeRelay(LoggerCallback callbackOnLog, InterfaceFactory& interfaceFactory, Crypto::PublicSignature const& gatewaySignature, Crypto::SymmetricKey const& broadcastKey, BuildId buildId, AgentId agentId = AgentId::GenerateRandom(), Crypto::AsymmetricKeys const& asymmetricKeys = Crypto::GenerateAsymmetricKeys()); /// Fired when a S2G protocol packet arrives. /// @param packet0 a buffer that contains whole packet. /// @param sender a Channel that provided the packet. void OnProtocolS2G(ByteView packet0, std::shared_ptr sender) override; /// Fired when a G2A protocol packet arrives. /// @param packet0 a buffer that contains whole packet. /// @param sender a Channel that provided the packet. void OnProtocolG2A(ByteView packet0, std::shared_ptr sender) override; /// Fired when a G2R protocol packet arrives. /// @param packet0 a buffer that contains whole packet. /// @param sender a Channel that provided the packet. void OnProtocolG2R(ByteView packet0, std::shared_ptr sender) override; /// Passes provided (most probably an S2X) packet further. /// @param packet0 a buffer that contains whole packet. /// @param routeId packet's destination. virtual void MultiSendPacketFurtherThroughRouteId(ByteView packet0, RouteId routeId); /// Called whenever an attached Binder Peripheral wants to send a Command to its Connector Binder. /// @param command full Command with arguments. /// @param channel Interface that will be used to send the packet. void PostCommandToConnector(ByteView command, std::shared_ptr channel) override; /// Expose all base classes `On` methods. using Relay::On; using ProceduresG2X::RequestHandler::On; /// Handler fired when a N2N::InitializeRoute Procedure Query arrives. /// @param query object representing the Query. void On(ProceduresN2N::InitializeRouteQuery query) override; /// Handler fired when a N2N::InitializeRoute Procedure arrives. /// @param query object representing the Query. void On(ProceduresS2G::InitializeRouteQuery query) override; /// Handler fired when a G2X::AddRoute Procedure Query arrives. /// @param query object representing the Query. void On(ProceduresG2X::AddRoute query) override; /// Handler Fired N2N::ChannelIdExchangeStep1 Procedure Query arrives. /// This query indicates that some relay wants to negotiate joining the network. /// @param query object representing the Query. void On(ProceduresN2N::ChannelIdExchangeStep1 query) override; /// Handler Fired N2N::ChannelIdExchangeStep2 Procedure Query arrives. /// This query contains parameters for unique connection. Relay can send initialization query to GateRelay to registration in network. /// @param query object representing the Query. void On(ProceduresN2N::ChannelIdExchangeStep2 query) override; /// Sets the default Device used in communication with the server. /// @param gatewayReturnChannel Device to set as a new return channel. void SetGatewayReturnChannel(std::shared_ptr const& gatewayReturnChannel); /// Sets the default Device used in communication with the server. /// @param args Device id stored in byte form. void SetGatewayReturnChannel(MWR::ByteView args); /// Returns timestamp to Gateway. /// @param args unused. void Ping(MWR::ByteView args); /// Gets the default Device used in communication with the server. /// @return current Gateway return channel. std::shared_ptr GetGatewayReturnChannel() const; /// Creates and attaches a new Device. /// @param iid address of Device in Relay. /// @param deviceNameHash hash to distinguish devices types. /// @param isNegotiationChannel true if channel will support negotiation procedure. /// @param commandLine buffer containing Device's construction parameters. /// @param negotiationClient true if channel will support negotiation procedure, and should start it. /// @return newly created Device or null if there was no factory able to process provided command-line. /// @throws std::runtime_error if device cannot be created becouse it was not registrated or commandLine is invalid. std::shared_ptr CreateAndAttachDevice(DeviceId iid, HashT deviceNameHash, bool isNegotiationChannel, ByteView commandLine, bool negotiationClient = false) override; /// Send packet through first interface to gateway, with registration request. void InitializeRoute(); /// Starts procedure of unique channel negotiation. /// @param device channel that will perform negotiation. void NegotiateChannel(std::shared_ptr const& device); /// Handler fired when a G2X::RunCommandOnAgentQuery Procedure Query arrives. /// @param query object representing the Query. void On(ProceduresG2X::RunCommandOnAgentQuery) override; /// Handler fired when a G2X::RunCommandOnDeviceQuery Procedure Query arrives. /// @param query object representing the Query. void On(ProceduresG2X::RunCommandOnDeviceQuery) override; /// Handler fired when a G2X::DeliverToBinder Procedure Query arrives. /// @param query object representing the Query. void On(ProceduresG2X::DeliverToBinder query) override; /// Inform gateway that new Device was added correctly. /// @param device pointer to newly created device. void SendNewDeviceNotification(std::shared_ptr const& device); /// Inform gateway that new Device was added by negotiation process. /// @param newDeviceId id of new device in relay. /// @param negotiatorId id of device that was used for negotiation. /// @param inId negotiated input parameter. /// @param outId negotiated output parameter. void SendNewNegotiatedChannelNotification(DeviceId newDeviceId, DeviceId negotiatorId, ByteView inId, ByteView outId); /// Creates device from provided byte form of arguments @see CreateAndAttachDevice. /// @param commandArgs all arguments for CreateAndAttachDevice packed in byte form. std::shared_ptr RunCommandAddDevice(ByteView commandArgs); private: std::atomic m_LastResevedDeviceId = ~(1 << (8 * DeviceId::BinarySize - 1)); ///< DeviceId with MSB set are used for deviceId assigned by Node std::weak_ptr m_GatewayReturnChannel; ///< Channel used to communicate with the Gateway by default. Crypto::PublicSignature m_GatewaySignature; ///< A public signature used by Network's Gateway to authenticate itself. Crypto::PublicKey m_GatewayEncryptionKey; ///< Gateway's public key (converted from signature) used to encrypt N2G packets. Crypto::PublicKey m_MyEncryptionKey; ///< This is going to be sent to Gateway. }; }