AuroraRuntime/Include/Aurora/IO/Net/Net.hpp
2021-09-06 11:58:08 +01:00

290 lines
8.3 KiB
C++

/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: Net.hpp
Date: 2021-6-9
Author: Reece
***/
#pragma once
namespace Aurora::IO::Net
{
enum TransportProtocol
{
kProtocolUDP,
kProtocolTCP
};
enum IPProtocol
{
kIPProtocolV4,
kIPProtocolV6
};
struct IPAddress
{
IPProtocol ip;
bool hasIP;
AuString address;
union
{
AuUInt8 v4[4];
AuUInt16 v6[8];
};
AUKN_SYM AuString toString();
};
struct Endpoint
{
TransportProtocol protocol;
IPAddress address;
AuUInt16 port;
// 0 - destination is a stateless datagram server
// 1 - destination is a psuedo-stateful server
AuUInt UDPTimeout;
AUKN_SYM AuString toString();
};
class INetworkStream;
class IBasicSocket;
class IClientSocket;
/**
* DTLS/UDP/TCP/TLS -> TRUE = expects another datagram or read pump
* -> FALSE = end of socket life
*/
using StreamHasData_cb = std::function<bool(const AuSPtr<IClientSocket> &socket)>;
using InitializeSocket_cb = std::function<bool(const AuSPtr<IClientSocket> &socket)>;
using ShutdownSocket_cb = std::function<void(const AuSPtr<IClientSocket> &socket)>;
class IClientHasData
{
public:
// DTLS/UDP/TCP/TLS -> TRUE = expects another datagram or read pump
// FALSE = end of socket life
virtual bool OnSocketHasData(const AuSPtr<IClientSocket> &socket) = 0;
};
class FunctionalClientHasData : public IClientHasData
{
private:
StreamHasData_cb socket_;
public:
FunctionalClientHasData(const StreamHasData_cb &socket) : socket_(socket)
{}
FunctionalClientHasData(StreamHasData_cb &&socket) : socket_(std::move(socket))
{}
};
class IClientShutdown
{
public:
virtual void OnSocketShutdown(const AuSPtr<IClientSocket> &socket) = 0;
};
class FunctionalClientShutdown : public IClientShutdown
{
private:
ShutdownSocket_cb socket_;
public:
FunctionalClientShutdown(const ShutdownSocket_cb &socket) : socket_(socket)
{}
FunctionalClientShutdown(ShutdownSocket_cb &&socket) : socket_(std::move(socket))
{}
};
class IClientDoS
{
public:
virtual void OnSocketDoS(const AuSPtr<IClientSocket> &socket) = 0;
};
class FunctionalClientDoS: public IClientDoS
{
private:
ShutdownSocket_cb socket_;
public:
FunctionalClientDoS(const ShutdownSocket_cb &socket) : socket_(socket)
{}
FunctionalClientDoS(ShutdownSocket_cb &&socket) : socket_(std::move(socket))
{}
};
class IClientTLSBreakdown
{
public:
virtual void OnSocketTLSBreakdown(const AuSPtr<IClientSocket> &socket) = 0;
};
class FunctionalClientTLSBreakdown : public IClientTLSBreakdown
{
private:
ShutdownSocket_cb socket_;
public:
FunctionalClientTLSBreakdown(const ShutdownSocket_cb &socket) : socket_(socket)
{}
FunctionalClientTLSBreakdown(ShutdownSocket_cb &&socket) : socket_(std::move(socket))
{}
};
class IClientEvents
{
public:
virtual void AddSubscriptionHasData(const AuSPtr<IClientHasData> &iface) = 0;
virtual void RemoveSubscriptionHasData(const AuSPtr<IClientHasData> &iface) = 0;
virtual void AddSubscriptionShutdown(const AuSPtr<IClientShutdown> &iface) = 0;
virtual void RemoveSubscriptionShutdown(const AuSPtr<IClientShutdown> &iface) = 0;
virtual void AddSubscriptionDoS(const AuSPtr<IClientDoS> &iface) = 0;
virtual void RemoveSubscriptionDoS(const AuSPtr<IClientDoS> &iface) = 0;
virtual void AddSubscriptionTlsBreakdown(const AuSPtr<IClientTLSBreakdown> &iface) = 0;
virtual void RemoveSubscriptionTlsBreakdown(const AuSPtr<IClientTLSBreakdown> &iface) = 0;
};
using Error_t = std::error_code;
class IBasicSocket
{
public:
virtual bool IsActive() = 0;
virtual Error_t GetLastError() = 0;
virtual void Shutdown() = 0;
virtual bool GetLocalEndpoint(Endpoint &out) = 0;
};
class IClientSocket : public IBasicSocket
{
public:
virtual IClientEvents *GetClientEvents() = 0;
virtual bool Initialize() = 0;
virtual bool GetRemoteEndpoint(Endpoint &out) = 0;
virtual bool PumpRead() = 0;
virtual bool PumpWrite() = 0;
virtual bool ReadAsync(AuUInt8 *buffer, AuUInt32 &length, bool all = false) = 0;
virtual bool PeakAsync(AuUInt8 *buffer, AuUInt32 &length) = 0;
virtual bool ReadSync(AuUInt8 *buffer, AuUInt32 &length, bool all = true) = 0;
virtual bool WriteAsync(const AuUInt8 *buffer, AuUInt32 length) = 0;
virtual bool WriteAsync(const AuUInt8 *buffer, AuUInt32 length, std::function<void(bool)>) = 0;
virtual bool WriteSync(const AuUInt8 *buffer, AuUInt32 length) = 0;
/**
* Sets the internal application buffer size
* Noting that Linux's default network buffer looks like this:
* Minimum, Initial, Maximum: 10240 87380 12582912 | 10KB, 86KB, 12MB
*/
virtual AuUInt GetInternalRingBuffer() = 0;
virtual bool SetInternalRingBuffer(AuUInt bytes) = 0;
/**
* Defines the maximum amount of bytes each recieve frame can ingest
*/
virtual void SetRecvLength(AuOptional<AuUInt32> length) = 0;
virtual AuUInt32 GetRecvLength() = 0;
/**
* Enable ad-hoc input buffer ingestion into our internal buffer
* Only use when PumpRead will not suffice by design (ie: sync apps)
*/
virtual void BufferAdhoc(AuOptional<bool> value) = 0;
};
class ILocalClientSocket : public IClientSocket
{
public:
using ConnectCallback_cb = std::function<void(bool success)>;
virtual bool Connect() = 0;
virtual void ConnectAsync(ConnectCallback_cb cb) = 0;
};
struct TlsConnect
{
Aurora::Crypto::X509::Certificate serverCertificate;
AuSPtr<IBasicSocket> socket;
};
using TlsConnect_cb = std::function<bool(const TlsConnect &info)>;
struct ServerInfo
{
Endpoint listen;
};
struct TLSServerInfo : ServerInfo
{
Aurora::Crypto::RSAPair cert;
};
struct ClientInfo
{
Endpoint socket;
AuString service;
};
struct TLSClientInfo : ClientInfo
{
TlsConnect_cb pinning;
};
class IServer : public IBasicSocket
{
public:
virtual bool AddAcceptCallback(const InitializeSocket_cb &accept) = 0; // on accept*
virtual bool AddExitCallback(const ShutdownSocket_cb &accept) = 0; // server shutdown*
virtual void GetClients(AuList<AuSPtr<IClientSocket>> &clients) = 0;
virtual bool Listen() = 0;
};
class INetworkingPool
{
public:
/**
Supported thread models:
while (true)
{
// read from sockets pre-frame
PumpRead();
// process other async network logic here
// process writes and a few early reads before we sleep
PumpWrite();
// yield
Yield();
}
while (true)
{
// process other async network logic here
// run once
Pump()
}
...and none with BufferAdhoc enabled
*/
virtual void PumpRead() = 0;
virtual void PumpWrite() = 0;
virtual void Pump() = 0;
virtual bool NewServer(const ServerInfo &listen, AuSPtr<IServer> &out) = 0;
virtual bool NewTlsServer(const TLSServerInfo &keys, AuSPtr<IServer> &out) = 0;
virtual bool NewClient(const ClientInfo &info, AuSPtr<ILocalClientSocket> &out) = 0;
virtual bool NewTlsClient(const TLSClientInfo &info, AuSPtr<ILocalClientSocket> &out) = 0;
};
}