290 lines
8.3 KiB
C++
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;
|
|
};
|
|
} |