// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
#pragma once
#include "Types.h"
#include "NetworkConfig.h"
#include "Engine/Core/Collections/Array.h"
#include "Engine/Scripting/ScriptingType.h"
#include "Engine/Scripting/ScriptingObjectReference.h"
///
/// Low-level network peer class. Provides server-client communication functions, message processing and sending.
///
API_CLASS(sealed, NoSpawn, Namespace="FlaxEngine.Networking") class FLAXENGINE_API NetworkPeer final : public ScriptingObject
{
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(NetworkPeer, ScriptingObject);
// List with all active peers.
API_FIELD(ReadOnly) static Array Peers;
public:
int HostId = -1;
NetworkConfig Config;
uint8* MessageBuffer = nullptr;
Array MessagePool;
public:
///
/// Low-level network transport driver used by this peer.
///
API_FIELD() INetworkDriver* NetworkDriver = nullptr;
public:
///
/// Starts listening for incoming connections.
/// Once this is called, this peer becomes a server.
///
/// True when succeeded.
API_FUNCTION() bool Listen();
///
/// Starts connection handshake with the end point specified in the structure.
/// Once this is called, this peer becomes a client.
///
/// True when succeeded.
API_FUNCTION() bool Connect();
///
/// Disconnects from the server.
///
/// Can be used only by the client!
API_FUNCTION() void Disconnect();
///
/// Disconnects given connection from the server.
///
/// Can be used only by the server!
API_FUNCTION() void Disconnect(const NetworkConnection& connection);
///
/// Tries to pop an network event from the queue.
///
/// The reference to event structure.
/// True when succeeded and the event can be processed.
/// If this returns message event, make sure to recycle the message using function after processing it!
API_FUNCTION() bool PopEvent(API_PARAM(Out) NetworkEvent& eventRef);
///
/// Acquires new message from the pool.
/// Cannot acquire more messages than the limit specified in the structure.
///
/// The acquired message.
/// Make sure to recycle the message to this peer once it is no longer needed!
API_FUNCTION() NetworkMessage CreateMessage();
///
/// Returns given message to the pool.
///
/// Make sure that this message belongs to the peer and has not been recycled already (debug build checks for this)!
API_FUNCTION() void RecycleMessage(const NetworkMessage& message);
///
/// Acquires new message from the pool and setups it for sending.
///
/// The acquired message.
API_FUNCTION() NetworkMessage BeginSendMessage();
///
/// Aborts given message send. This effectively deinitializes the message and returns it to the pool.
///
/// The message.
API_FUNCTION() void AbortSendMessage(const NetworkMessage& message);
///
/// Sends given message over specified channel to the server.
///
/// The channel to send the message over.
/// The message.
/// Can be used only by the client!
///
/// Do not recycle the message after calling this.
/// This function automatically recycles the message.
///
API_FUNCTION() bool EndSendMessage(NetworkChannelType channelType, const NetworkMessage& message);
///
/// Sends given message over specified channel to the given client connection (target).
///
/// The channel to send the message over.
/// The message.
/// The client connection to send the message to.
/// Can be used only by the server!
///
/// Do not recycle the message after calling this.
/// This function automatically recycles the message.
///
API_FUNCTION() bool EndSendMessage(NetworkChannelType channelType, const NetworkMessage& message, const NetworkConnection& target);
///
/// Sends given message over specified channel to the given client connection (target).
///
/// The channel to send the message over.
/// The message.
/// The connections list to send the message to.
/// Can be used only by the server!
///
/// Do not recycle the message after calling this.
/// This function automatically recycles the message.
///
API_FUNCTION() bool EndSendMessage(NetworkChannelType channelType, const NetworkMessage& message, const Array& targets);
///
/// Creates new peer using given configuration.
///
/// The configuration to create and setup new peer.
/// The peer.
/// Peer should be destroyed using once it is no longer in use. Returns null if failed to create a peer (eg. config is invalid).
API_FUNCTION() static NetworkPeer* CreatePeer(const NetworkConfig& config);
///
/// Shutdowns and destroys given peer.
///
/// The peer to destroy.
API_FUNCTION() static void ShutdownPeer(NetworkPeer* peer);
public:
bool IsValid() const
{
return NetworkDriver != nullptr && HostId >= 0;
}
uint8* GetMessageBuffer(const uint32 messageId) const
{
// Calculate and return the buffer slice using previously calculated slice.
return MessageBuffer + Config.MessageSize * messageId;
}
public:
FORCE_INLINE bool operator==(const NetworkPeer& other) const
{
return HostId == other.HostId;
}
FORCE_INLINE bool operator!=(const NetworkPeer& other) const
{
return HostId != other.HostId;
}
private:
bool Initialize(const NetworkConfig& config);
void Shutdown();
void CreateMessageBuffers();
void DisposeMessageBuffers();
};