// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Core/Types/BaseTypes.h"
#include "Engine/Core/Types/String.h"
API_INJECT_CODE(cpp, "#include \"Engine/Platform/Network.h\"");
///
/// Network connection protocol type.
///
API_ENUM() enum class NetworkProtocol
{
/// Not specified.
Undefined,
/// User Datagram Protocol.
Udp,
/// Transmission Control Protocol.
Tcp,
};
///
/// IP version type.
///
API_ENUM() enum class NetworkIPVersion
{
/// Not specified.
Undefined,
/// Internet Protocol version 4.
IPv4,
/// Internet Protocol version 6.
IPv6,
};
///
/// Network socket.
///
API_STRUCT() struct FLAXENGINE_API NetworkSocket
{
DECLARE_SCRIPTING_TYPE_MINIMAL(NetworkSocketGroup);
/// Socket protocol type.
API_FIELD() NetworkProtocol Protocol = NetworkProtocol::Undefined;
/// Socket address IP version.
API_FIELD() NetworkIPVersion IPVersion = NetworkIPVersion::Undefined;
API_FIELD(Private, NoArray) byte Data[8] = {};
};
///
/// Network end-point.
///
API_STRUCT() struct FLAXENGINE_API NetworkEndPoint
{
DECLARE_SCRIPTING_TYPE_MINIMAL(NetworkSocketGroup);
/// End-point IP version.
API_FIELD(ReadOnly) NetworkIPVersion IPVersion = NetworkIPVersion::Undefined;
API_FIELD(Private, NoArray) byte Data[28] = {};
};
///
/// Network socket options.
///
API_ENUM() enum class NetworkSocketOption
{
/// Enables debugging info recording.
Debug,
/// Allows local address reusing.
ReuseAddr,
/// Keeps connections alive.
KeepAlive,
/// Indicates that outgoing data should be sent on whatever interface the socket is bound to and not a routed on some other interface.
DontRoute,
/// Allows for sending broadcast data.
Broadcast,
/// Uses the local loopback address when sending data from this socket.
UseLoopback,
/// Lingers on close if data present.
Linger,
/// Allows out-of-bound data to be returned in-line with regular data.
OOBInline,
/// Socket send data buffer size.
SendBuffer,
/// Socket receive data buffer size.
RecvBuffer,
/// The timeout in milliseconds for blocking send calls.
SendTimeout,
/// The timeout in milliseconds for blocking receive calls.
RecvTimeout,
/// The last socket error code.
Error,
/// Enables the Nagle algorithm for TCP sockets.
NoDelay,
/// Enables IPv6/Ipv4 dual-stacking, UDP/TCP.
IPv6Only,
/// Retrieve the current path MTU, the socket must be connected UDP/TCP.
Mtu,
/// Socket type, DGRAM, STREAM ..
Type,
};
///
/// Network socket state.
///
API_ENUM() enum class NetworkSocketState
{
/// Nothing.
None = 0,
/// Socket error.
Error = 1 << 0,
/// Invalid request.
Invalid = 1 << 1,
/// Socket disconnected.
Disconnected = 1 << 2,
/// Socket is readable.
Readable = 1 << 3,
/// Socket is writable.
Writeable = 1 << 4,
};
DECLARE_ENUM_OPERATORS(NetworkSocketState);
///
/// Network sockets group.
///
API_STRUCT() struct FLAXENGINE_API NetworkSocketGroup
{
DECLARE_SCRIPTING_TYPE_MINIMAL(NetworkSocketGroup);
/// Group size.
API_FIELD(ReadOnly) uint32 Count = 0;
/// Group capacity.
API_FIELD(ReadOnly) uint32 Capacity = 0;
API_FIELD(Private) byte* Data = nullptr;
};
///
/// Low-level networking implementation interface with Berkeley sockets.
///
API_CLASS(Static, Name="Network", Tag="NativeInvokeUseName")
class FLAXENGINE_API NetworkBase
{
public:
static struct FLAXENGINE_API ScriptingTypeInitializer TypeInitializer;
///
/// Creates a new native socket.
///
/// The socket struct to fill in.
/// The protocol.
/// The ip version.
/// Returns true on error, otherwise false.
API_FUNCTION() static bool CreateSocket(API_PARAM(Ref) NetworkSocket& socket, NetworkProtocol proto, NetworkIPVersion ipv);
///
/// Closes native socket.
///
/// The socket.
/// Returns true on error, otherwise false.
API_FUNCTION() static bool DestroySocket(API_PARAM(Ref) NetworkSocket& socket);
///
/// Sets the specified socket option.
///
/// The socket.
/// The option.
/// The value.
/// Returns true on error, otherwise false.
API_FUNCTION() static bool SetSocketOption(API_PARAM(Ref) NetworkSocket& socket, NetworkSocketOption option, int32 value);
///
/// Gets the specified socket option.
///
/// The socket.
/// The option.
/// The returned value.
/// Returns true on error, otherwise false.
API_FUNCTION() static bool GetSocketOption(API_PARAM(Ref) NetworkSocket& socket, NetworkSocketOption option, API_PARAM(Out) int32& value);
///
/// Connects a socket to the specified end point.
///
/// The socket.
/// The end point.
/// Returns true on error, otherwise false.
API_FUNCTION() static bool ConnectSocket(API_PARAM(Ref) NetworkSocket& socket, API_PARAM(Ref) NetworkEndPoint& endPoint);
///
/// Binds a socket to the specified end point.
///
/// The socket.
/// The end point.
/// Returns true on error, otherwise false.
API_FUNCTION() static bool BindSocket(API_PARAM(Ref) NetworkSocket& socket, API_PARAM(Ref) NetworkEndPoint& endPoint);
///
/// Listens for incoming connection.
///
/// The socket.
/// Pending connection queue size.
/// Returns true on error, otherwise false.
API_FUNCTION() static bool Listen(API_PARAM(Ref) NetworkSocket& socket, uint16 queueSize);
///
/// Accepts a pending connection.
///
/// The socket.
/// The newly connected socket.
/// The end point of the new socket.
/// Returns true on error, otherwise false.
API_FUNCTION() static bool Accept(API_PARAM(Ref) NetworkSocket& serverSocket, API_PARAM(Ref) NetworkSocket& newSocket, API_PARAM(Out) NetworkEndPoint& newEndPoint);
///
/// Checks for socket readability.
///
/// The socket.
/// Returns true when data is available. Otherwise false.
API_FUNCTION() static bool IsReadable(API_PARAM(Ref) NetworkSocket& socket);
///
/// Checks for socket writeability.
///
/// The socket.
/// Returns true when data can be written. Otherwise false.
API_FUNCTION() static bool IsWritable(API_PARAM(Ref) NetworkSocket& socket);
///
/// Creates a socket group. It allocate memory based on the desired capacity.
///
/// The group capacity (fixed).
/// The group.
/// Returns true on error, otherwise false.
API_FUNCTION() static bool CreateSocketGroup(uint32 capacity, API_PARAM(Out) NetworkSocketGroup& group);
///
/// Destroy the socket group, and free the allocated memory.
///
/// The group.
/// Returns true if the group is already destroyed, otherwise false.
API_FUNCTION() static bool DestroySocketGroup(API_PARAM(Ref) NetworkSocketGroup& group);
///
/// Updates sockets states.
///
/// The sockets group.
/// Returns -1 on error, The number of elements where states are nonzero, otherwise 0.
API_FUNCTION() static int32 Poll(API_PARAM(Ref) NetworkSocketGroup& group);
///
/// Retrieves socket state.
///
/// The group.
/// The socket index in group.
/// The returned state.
/// Returns true on error, otherwise false.
API_FUNCTION() static bool GetSocketState(API_PARAM(Ref) NetworkSocketGroup& group, uint32 index, API_PARAM(Out) NetworkSocketState& state);
///
/// Adds a socket to a group.
///
/// The group.
/// The socket.
/// Returns the socket index in group or -1 on error.
API_FUNCTION() static int32 AddSocketToGroup(API_PARAM(Ref) NetworkSocketGroup& group, API_PARAM(Ref) NetworkSocket& socket);
///
/// Gets a socket by index. Some data like socket IPVersion might be undefined.
///
/// The group.
/// The index.
/// The returned socket.
/// Returns true on error, otherwise false.
API_FUNCTION() static bool GetSocketFromGroup(API_PARAM(Ref) NetworkSocketGroup& group, uint32 index, API_PARAM(Out) NetworkSocket& socket);
///
/// Removes the socket at the specified index.
///
/// The group.
/// The index.
API_FUNCTION() static void RemoveSocketFromGroup(API_PARAM(Ref) NetworkSocketGroup& group, uint32 index);
///
/// Removes the socket if present.
///
/// The group.
/// The socket.
/// Returns true if the socket is not found, otherwise false.
API_FUNCTION() static bool RemoveSocketFromGroup(API_PARAM(Ref) NetworkSocketGroup& group, API_PARAM(Ref) NetworkSocket& socket);
///
/// Clears the socket group.
///
/// The group.
API_FUNCTION() static void ClearGroup(API_PARAM(Ref) NetworkSocketGroup& group);
///
/// Writes data to the socket.
///
/// The socket.
/// The data to write.
/// The length of data.
/// If protocol is UDP, the destination end point. Otherwise nullptr.
/// Returns -1 on error, otherwise bytes written.
API_FUNCTION() static int32 WriteSocket(NetworkSocket socket, byte* data, uint32 length, NetworkEndPoint* endPoint = nullptr);
///
/// Reads data on the socket.
///
/// The socket.
/// The buffer.
/// Size of the buffer.
/// If UDP, the end point from where data is coming. Otherwise nullptr.
/// Returns -1 on error, otherwise bytes read.
API_FUNCTION() static int32 ReadSocket(NetworkSocket socket, byte* buffer, uint32 bufferSize, NetworkEndPoint* endPoint = nullptr);
///
/// Creates an end point.
///
/// The network address.
/// The network port.
/// The ip version.
/// The created end point.
/// True if the end point will be connected or binded.
/// Returns true on error, otherwise false.
API_FUNCTION() static bool CreateEndPoint(const String& address, const String& port, NetworkIPVersion ipv, API_PARAM(Out) NetworkEndPoint& endPoint, bool bindable = true);
///
/// Remaps an ipv4 end point to an ipv6 one.
///
/// The ipv4 end point.
/// The ipv6 end point.
API_FUNCTION() static NetworkEndPoint RemapEndPointToIPv6(API_PARAM(Ref) NetworkEndPoint& endPoint);
};