Merge pull request #1372 from aws-lumberyard-dev/stramer/az-networking-docs
Networking libraries + Gems API documentation
This commit is contained in:
@@ -44,6 +44,11 @@ namespace AzNetworking
|
||||
|
||||
//! @class IConnection
|
||||
//! @brief interface class for network connections.
|
||||
//!
|
||||
//! IConnection provides a pure-virtual interface for all network connection types. IConnections provide access to
|
||||
//! a ConnectionMetrics object which provides a variety of metrics on the connection itself such as data rate, RTT and
|
||||
//! packet statistics.
|
||||
|
||||
class IConnection
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -22,6 +22,12 @@ namespace AzNetworking
|
||||
{
|
||||
//! @class IConnectionListener
|
||||
//! @brief interface class for application layer dealing with connection level events.
|
||||
//!
|
||||
//! IConnectionListener defines an abstract interface that the user of AzNetworking is expected to implement to react and
|
||||
//! handle all IConnection related events, including the handling of any received IPacket derived packets. The AzNetworking
|
||||
//! user should derive a handler class from IConnectionListener, and provide an instance of that handler to any
|
||||
//! INetworkInterface the user instantiates. The lifetime of the IConnectionListener must outlive the lifetime of the
|
||||
//! INetworkInterface.
|
||||
class IConnectionListener
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -18,6 +18,11 @@ namespace AzNetworking
|
||||
{
|
||||
//! @class IConnectionSet
|
||||
//! @brief interface class for managing a set of connections.
|
||||
//!
|
||||
//! IConnectionSet defines a simple interface for working with an abstract set of IConnections bound to an
|
||||
//! INetworkInterface. Generally users of AzNetworking will not have reason to interact directly with the IConnectionSet,
|
||||
//! as its interface is completely wrapped by INetworkInterface.
|
||||
|
||||
class IConnectionSet
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -23,10 +23,10 @@ namespace AzNetworking
|
||||
//! Collection of compression related error codes
|
||||
enum class CompressorError
|
||||
{
|
||||
Ok, ///< No error, operation finished successfully
|
||||
InsufficientBuffer, ///< Buffer size is insufficient for the operation to complete, increase the size and try again
|
||||
CorruptData, ///< Malformed or hacked packet, potentially security issue
|
||||
Uninitialized ///< Compressor or supplied buffers are uninitialized
|
||||
Ok, //!< No error, operation finished successfully
|
||||
InsufficientBuffer, //!< Buffer size is insufficient for the operation to complete, increase the size and try again
|
||||
CorruptData, //!< Malformed or hacked packet, potentially security issue
|
||||
Uninitialized //!< Compressor or supplied buffers are uninitialized
|
||||
};
|
||||
|
||||
//! Unique identifier of a given compressor
|
||||
@@ -34,6 +34,12 @@ namespace AzNetworking
|
||||
|
||||
//! @class ICompressor
|
||||
//! @brief Packet data compressor interface.
|
||||
//!
|
||||
//! ICompressor is an abstract compression interface meant for user provided GEMs to implement (such as the [Multiplayer
|
||||
//! Compression Gem](http://docs.o3de.org/docs/user-guide/gems/reference/multiplayer-compression)).
|
||||
//! Compression is supported for both TCP and UDP connections. Instantiation of a compressor is controlled by the
|
||||
//! `net_UdpCompressor` or `net_TcpCompressor` cvar for their respective protocols.
|
||||
|
||||
class ICompressor
|
||||
{
|
||||
public:
|
||||
@@ -87,8 +93,16 @@ namespace AzNetworking
|
||||
) = 0;
|
||||
};
|
||||
|
||||
//! Abstract factory to instantiate compressors.
|
||||
//! Used by the network interface to create a compressor
|
||||
//! @class ICompressorFactory
|
||||
//! @brief Abstract factory to instantiate compressors.
|
||||
//!
|
||||
//! ICompressorFactory is an abstract compression interface meant for user provided GEMs to implement. ICompressorFactory
|
||||
//! implementations can be registered to classes implementing INetworking. Registered factories can then be used to create
|
||||
//! ICompressor implementations on demand. The [Multiplayer Compression
|
||||
//! Gem](http://docs.o3de.org/docs/user-guide/gems/reference/multiplayer-compression) is an example of an ICompressorFactory
|
||||
//! for an LZ4 Compressor. In it, MultiplayerCompressionSystemComponent registers its ICompressorFactory with
|
||||
//! NetworkingSystemComponent, which is an implementation of INetworking. Registered factories are keyed by their AZ Name
|
||||
//! which is accessed through the factory's GetFactoryName method.
|
||||
class ICompressorFactory
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -22,7 +22,16 @@
|
||||
namespace AzNetworking
|
||||
{
|
||||
//! @class INetworkInterface
|
||||
//! @brief pure virtual network interface class to abstract client/server and tcp/udp concerns from application code.
|
||||
//! @brief Network interface class to abstract client/server and protocol concerns from application code.
|
||||
//!
|
||||
//! INetworkInterface provides an abstract API capable of receiving and opening IConnection objects, sending IPacket objects with optional
|
||||
//! reliability, and determining the delivery status of packets that have been sent unreliably (delivery of reliable packets
|
||||
//! is guaranteed as long as the associated connection remains open). INetworkInterface must be provided an
|
||||
//! IConnectionListener instance that outlives the INetworkInterface itself. The INetworkInterface also creates and manages
|
||||
//! the IConnectionSet, which tracks all open connections bound to the interface. INetworkInterface also provides GetMetrics
|
||||
//! functions which can be used to fetch a struct detailing a variety of metrics relating to send and receive rates for both
|
||||
//! packets and bytes in addition to the effect of features on those rates (such as packet size reduction due to compression.)
|
||||
|
||||
class INetworkInterface
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -23,6 +23,17 @@ namespace AzNetworking
|
||||
|
||||
//! @class INetworking
|
||||
//! @brief The interface for creating and working with network interfaces.
|
||||
//!
|
||||
//! INetworking is an Az::Interface<T> that provides applications access to higher level networking abstractions.
|
||||
//! AzNetworking::INetworking can be used to instantiate new INetworkInterfaces that can be configured to operate over
|
||||
//! either TCP or UDP, enable or disable encryption, and be assigned a trust level.
|
||||
//!
|
||||
//! INetworking is also responsible for registering ICompressorFactory implementations. This allows a developer to have
|
||||
//! access to multiple ICompressorFactory implementations by name. The [MultiplayerCompressor
|
||||
//! Gem](http://docs.o3de.org/docs/user-guide/gems/reference/multiplayer-compression) is an example of this using the
|
||||
//! [LZ4](https://wikipedia.org/wiki/LZ4_%28compression_algorithm%29) algorithm.
|
||||
//!
|
||||
|
||||
class INetworking
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -24,6 +24,15 @@ namespace AzNetworking
|
||||
|
||||
//! @class IPacket
|
||||
//! @brief Base class for all packets.
|
||||
//!
|
||||
//! IPacket defines an abstract interface that all packets transmitted using AzNetworking must conform to. While there are
|
||||
//! a number of core packets used internally by AzNetworking, it is fully possible for end-users to define their own custom
|
||||
//! packets using this interface. PacketType should be distinct, and should be greater than
|
||||
//! AzNetworking::CorePackets::MAX. The Serialize method allows the IPacket to be used by an
|
||||
//! ISerializer to move data between hosts safely and efficiently.
|
||||
//!
|
||||
//! For more information on the packet format and best practices for extending the packet system, read
|
||||
//! [Networking Packets](http://docs.o3de.org/docs/user-guide/networking/packets) on the O3DE documentation site.
|
||||
class IPacket
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -28,6 +28,19 @@ namespace AzNetworking
|
||||
|
||||
//! @class IPacketHeader
|
||||
//! @brief A packet header that lets us deduce packet type for any incoming packet.
|
||||
//!
|
||||
//! IPacketHeader defines an abstract interface for a descriptor of all AzNetworking::IPacket sent through AzNetworking. The
|
||||
//! PacketHeader is used to identify and describe the contents of a Packet so that transport logic can identify what
|
||||
//! additional processing steps need to be taken (if any) and what type of Packet is being inspected.
|
||||
//!
|
||||
//! The PacketFlags portion of the header represents the first byte of the header. While it can be encrypted it is
|
||||
//! otherwise not exposed to additional processing (such as an AzNetworking::ICompressor). PacketFlags are a bitfield use to provide up
|
||||
//! front information about the state of the packet. Currently there is only one flag to indicate if the Packet is
|
||||
//! compressed or not.
|
||||
//!
|
||||
//! The remainder of the header contains the PacketType and the PacketId. While the PacketFlags byte is exempt from most
|
||||
//! additional forms of processing, the remainder of the header is not.
|
||||
|
||||
class IPacketHeader
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -27,6 +27,18 @@ namespace AzNetworking
|
||||
|
||||
//! @class ISerializer
|
||||
//! @brief Interface class for all serializers to derive from.
|
||||
//!
|
||||
//! ISerializer defines an abstract interface for visiting an object hierarchy and performing operations upon that hierarchy,
|
||||
//! typically reading from or writing data to the object hierarchy for reasons of persistence or network transmission.
|
||||
//!
|
||||
//! While the most common types of serializers are provided by the AzNetworking framework, users can implement custom
|
||||
//! serializers and perform complex operations on any serializable structures. A few types native to AzNetworking, many of which
|
||||
//! relate to packets, demonstrate this.
|
||||
//!
|
||||
//! Provided serializers include NetworkInputSerializer for writing an object model into a bytestream, NetworkOutputSerializer
|
||||
//! for writing to an object model, TrackChangesSerializer which is used to efficiently serialize objects without incurring significant
|
||||
//! copy or comparison overhead, and HashSerializer which can be used to generate a hash of all visited data which is important for
|
||||
//! automated desync detection.
|
||||
class ISerializer
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -25,6 +25,44 @@ namespace AzNetworking
|
||||
|
||||
//! @class TcpNetworkInterface
|
||||
//! @brief This class implements a TCP network interface.
|
||||
//!
|
||||
//! TcpNetworkInterface is an implementation of AzNetworking::INetworkInterface.
|
||||
//! Unlike UDP, TCP implements a variety of transport features such as congestion
|
||||
//! avoidance, flow control, and reliability. These features are valuable, but TCP
|
||||
//! offers minimal configuration of them. This is why UdpNetworkInterface offers
|
||||
//! similar features, but with greater flexibility in configuration. If your project doesn't
|
||||
//! require the low latency of UDP, consider using TCP.
|
||||
//!
|
||||
//! ## Packet structure
|
||||
//!
|
||||
//! * Flags - A bitfield a receiving endpoint can quickly inspect to learn about configuration of a packet
|
||||
//! * Header - Details the type of packet and other information related to reliability
|
||||
//! * Payload - The actual serialized content of the packet
|
||||
//!
|
||||
//! For more information, read [Networking Packets](http://docs.o3de.org/docs/user-guide/networking/packets) in the O3DE documentation.
|
||||
//!
|
||||
//! ## Reliability
|
||||
//!
|
||||
//! TCP packets can only be sent reliably. This is a feature of TCP itself.
|
||||
//!
|
||||
//! ## Fragmentation
|
||||
//!
|
||||
//! TCP implements fragmentation under the hood. Consumers of TCP packets will never
|
||||
//! need to worry about reconstructing the contents over multiple transmissions.
|
||||
//!
|
||||
//! ## Compression
|
||||
//!
|
||||
//! Compression here refers to content insensitive compression using libraries like
|
||||
//! LZ4. If enabled, the target payload is run through the compressor and replaces
|
||||
//! the original payload if it's in fact smaller. To tell if compression is enabled
|
||||
//! on a given packet, we operate on a bit in the packet's Flags. The Sender writes
|
||||
//! this bit while the Receiver checks it to see if a packet needs to be
|
||||
//! decompressed.
|
||||
//!
|
||||
//! ## Encryption
|
||||
//!
|
||||
//! AzNetworking uses the [OpenSSL](https://www.openssl.org/) library to implement TLS encryption. If enabled,
|
||||
//! the O3DE network layer handles the OpenSSL handshake under the hood using provided certificates.
|
||||
class TcpNetworkInterface final
|
||||
: public INetworkInterface
|
||||
{
|
||||
|
||||
@@ -27,12 +27,58 @@ namespace AzNetworking
|
||||
class IConnectionListener;
|
||||
class ICompressor;
|
||||
|
||||
// 20 byte IPv4 header + 8 byte UDP header
|
||||
static const uint32_t UdpPacketHeaderSize = 20 + 8;
|
||||
static const uint32_t DtlsPacketHeaderSize = 13; // DTLS1_RT_HEADER_LENGTH
|
||||
static const uint32_t UdpPacketHeaderSize = 20 + 8; //!< 20 byte IPv4 header + 8 byte UDP header
|
||||
static const uint32_t DtlsPacketHeaderSize = 13; //!< DTLS1_RT_HEADER_LENGTH
|
||||
|
||||
//! @class UdpNetworkInterface
|
||||
//! @brief This class implements a UDP network interface.
|
||||
//!
|
||||
//! UdpNetworkInterface is an implementation of AzNetworking::INetworkInterface. Since UDP is a very bare bones protocol,
|
||||
//! the Open 3D Engine implementation has to provide significantly more than its TCP counterpart (since TCP implements a
|
||||
//! significant number of reliability features.)
|
||||
//!
|
||||
//! When sent through UDP, a packet can have additional actions performed on it depending on which features are enabled and
|
||||
//! configured. Each feature listed in this description is in the order a packet will see them on Send.
|
||||
//!
|
||||
//! ### Packet structure
|
||||
//!
|
||||
//! The general structure of a UDP packet is:
|
||||
//!
|
||||
//! * Flags - A bitfield a receiving endpoint can quickly inspect to learn about configuration of a packet
|
||||
//! * Header - Details the type of packet and other information related to reliability
|
||||
//! * Payload - The actual serialized content of the packet
|
||||
//!
|
||||
//! For more information, read [Networking Packets](http://docs.o3de.org/docs/user-guide/networking/packets) in the O3DE documentation.
|
||||
//!
|
||||
//! ### Reliability
|
||||
//!
|
||||
//! UDP packets can be sent reliably or unreliably. Reliably sent packets are registered for tracking first. This causes the
|
||||
//! reliable packet to be resent if a timeout on the packet is reached. Once the packet is acknowledged, the packet is
|
||||
//! unregistered.
|
||||
//!
|
||||
//! ### Fragmentation
|
||||
//!
|
||||
//! If the raw packet size exceeds the configured maximum transmission unit (MTU) then the packet is broken into
|
||||
//! multiple reliable fragments to avoid fragmentation at the routing level. Fragments are always reliable so the original
|
||||
//! packet can be reconstructed. Operations that alter the payload generally follow this step so that they can be
|
||||
//! separately applied to the Fragments in addition to not being applied to both the original and Fragments.
|
||||
//!
|
||||
//! ### Compression
|
||||
//!
|
||||
//! Compression here refers to content insensitive compression using libraries like LZ4. If enabled, the target payload is
|
||||
//! run through the compressor and replaces the original payload if it's in fact smaller. To tell if compression is enabled
|
||||
//! on a given packet, we operate on a bit in the packet's Flags. The Sender writes this bit while the Receiver checks it to
|
||||
//! see if a packet needs to be decompressed.
|
||||
//!
|
||||
//! O3DE could potentially move from over MTU to under with compression, and the UDP interface doesn't check for this. Detecting a change
|
||||
//! that would reduce the number of fragmented packets would require pre-emptively compressing payloads to tell if that change happened,
|
||||
//! which could potentially lead to a lot of unnecessary calls to the compressor.
|
||||
//!
|
||||
//! ### Encryption
|
||||
//!
|
||||
//! AzNetworking uses the [OpenSSL](https://www.openssl.org/) library to implement Datagram Layer Transport Security (DTLS) encryption
|
||||
//! on UDP traffic. Encryption operates as described in [O3DE Networking Encryption](http://docs.o3de.org/docs/user-guide/networking/encryption)
|
||||
//! on the documentation website. Once both endpoints have completed their handshake, all traffic is expected to be fully encrypted.
|
||||
class UdpNetworkInterface final
|
||||
: public INetworkInterface
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user