// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Core/Types/BaseTypes.h"
#include "Engine/Core/Types/String.h"
API_INJECT_CPP_CODE("#include \"Engine/Platform/Network.h\"");
#define SOCKGROUP_ITEMSIZE 16
enum class FLAXENGINE_API NetworkProtocol
{
/// Not specified.
Undefined,
/// User Datagram Protocol.
Udp,
/// Transmission Control Protocol.
Tcp
};
enum class FLAXENGINE_API NetworkIPVersion
{
/// Not specified.
Undefined,
/// Internet Protocol version 4.
IPv4,
/// Internet Protocol version 6.
IPv6
};
struct FLAXENGINE_API NetworkSocket
{
NetworkProtocol Protocol = NetworkProtocol::Undefined;
NetworkIPVersion IPVersion = NetworkIPVersion::Undefined;
byte Data[8] = {};
};
struct FLAXENGINE_API NetworkAddress
{
String Address;
String Port;
};
struct FLAXENGINE_API NetworkEndPoint
{
NetworkIPVersion IPVersion = NetworkIPVersion::Undefined;
byte Data[28] = {};
};
enum class FLAXENGINE_API 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
};
struct FLAXENGINE_API NetworkSocketState
{
bool Error = false;
bool Invalid = false;
bool Disconnected = false;
bool Readable = false;
bool Writeable = false;
};
struct FLAXENGINE_API NetworkSocketGroup
{
uint32 Count = 0;
uint32 Capacity = 0;
byte *Data;
};
class FLAXENGINE_API NetworkBase
{
public:
///
/// Creates a new native socket.
///
/// The socket struct to fill in.
/// The protocol.
/// The ip version.
/// Returns true on error, otherwise false.
static bool CreateSocket(NetworkSocket& socket, NetworkProtocol proto, NetworkIPVersion ipv);
///
/// Closes native socket.
///
/// The socket.
/// Returns true on error, otherwise false.
static bool DestroySocket(NetworkSocket& socket);
///
/// Sets the specified socket option.
///
/// The socket.
/// The option.
/// The value.
/// Returns true on error, otherwise false.
static bool SetSocketOption(NetworkSocket& socket, NetworkSocketOption option, bool value);
///
/// Sets the specified socket option.
///
/// The socket.
/// The option.
/// The value.
/// Returns true on error, otherwise false.
static bool SetSocketOption(NetworkSocket& socket, NetworkSocketOption option, int32 value);
///
/// Gets the specified socket option.
///
/// The socket.
/// The option.
/// The returned value.
/// Returns true on error, otherwise false.
static bool GetSocketOption(NetworkSocket& socket, NetworkSocketOption option, bool* value);
///
/// Gets the specified socket option.
///
/// The socket.
/// The option.
/// The returned value.
/// Returns true on error, otherwise false.
static bool GetSocketOption(NetworkSocket& socket, NetworkSocketOption option, int32* value);
///
/// Connects a socket to the specified end point.
///
/// The socket.
/// The end point.
/// Returns true on error, otherwise false.
static bool ConnectSocket(NetworkSocket& socket, NetworkEndPoint& endPoint);
///
/// Binds a socket to the specified end point.
///
/// The socket.
/// The end point.
/// Returns true on error, otherwise false.
static bool BindSocket(NetworkSocket& socket, NetworkEndPoint& endPoint);
///
/// Listens for incoming connection.
///
/// The socket.
/// Pending connection queue size.
/// Returns true on error, otherwise false.
static bool Listen(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.
static bool Accept(NetworkSocket& serverSocket, NetworkSocket& newSocket, NetworkEndPoint& newEndPoint);
///
/// Checks for socket readability.
///
/// The socket.
/// Returns true when data is available. Otherwise false.
static bool IsReadable(NetworkSocket& socket);
///
/// Checks for socket writeability.
///
/// The socket.
/// Returns true when data can be written. Otherwise false.
static bool IsWritable(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.
static bool CreateSocketGroup(uint32 capacity, NetworkSocketGroup& group);
///
/// Destroy the socket group, and free the allocated memory.
///
/// The group.
/// Returns true if the group is already destroyed, otherwise false.
static bool DestroySocketGroup(NetworkSocketGroup& group);
///
/// Updates sockets states.
///
/// The sockets group.
/// Returns -1 on error, The number of elements where states are nonzero, otherwise 0.
static int32 Poll(NetworkSocketGroup& group);
///
/// Retrieves socket state.
///
/// The group.
/// The socket index in group.
/// The returned state.
/// Returns true on error, otherwise false.
static bool GetSocketState(NetworkSocketGroup& group, uint32 index, NetworkSocketState& state);
///
/// Adds a socket to a group.
///
/// The group.
/// The socket.
/// Returns the socket index in group or -1 on error.
static int32 AddSocketToGroup(NetworkSocketGroup& group, 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.
static bool GetSocketFromGroup(NetworkSocketGroup& group, uint32 index, NetworkSocket* socket);
///
/// Removes the socket at the specified index.
///
/// The group.
/// The index.
static void RemoveSocketFromGroup(NetworkSocketGroup& group, uint32 index);
///
/// Removes the socket if present.
///
/// The group.
/// The socket.
/// Returns true if the socket is not found, otherwise false.
static bool RemoveSocketFromGroup(NetworkSocketGroup& group, NetworkSocket& socket);
///
/// Clears the socket group.
///
/// The group.
static void ClearGroup(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.
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.
static int32 ReadSocket(NetworkSocket socket, byte* buffer, uint32 bufferSize, NetworkEndPoint* endPoint = nullptr);
///
/// Creates an end point.
///
/// The address.
/// The ip version.
/// The created end point.
/// True if the end point will be connected or binded.
/// Returns true on error, otherwise false.
static bool CreateEndPoint(NetworkAddress& address, NetworkIPVersion ipv, NetworkEndPoint& endPoint, bool bindable = true);
///
/// Remaps an ipv4 end point to an ipv6 one.
///
/// The ipv4 end point.
/// The ipv6 end point.
static NetworkEndPoint RemapEndPointToIPv6(NetworkEndPoint& endPoint);
};