/*** 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; using StreamHasData_cb = std::function socket)>; // DTLS/UDP/TCP/TLS -> TRUE = expects another frame or stream buffer, FALSE = end of socket life using InitializeSocket_cb = std::function socket)>; using ShutdownSocket_cb = std::function socket)>; 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: // called during loop pump struct ClientCallbacks { StreamHasData_cb hasData; // on data available ShutdownSocket_cb onShutdown; // Socket shutdown or otherwise dead ShutdownSocket_cb onStreamOverSaturation; // DoS? ShutdownSocket_cb onTLSHandshakeAbort; }; virtual bool Initialize(const ClientCallbacks &callbacks) = 0; virtual bool Initialize() = 0; virtual bool GetRemoteEndpoint(Endpoint &out) = 0; virtual bool ReadAsync(AuUInt8 *buffer, bool all, AuUInt32 &length) = 0; virtual bool WriteAsync(const AuUInt8 *buffer, AuUInt32 length) = 0; virtual bool WriteAsync(const AuUInt8 *buffer, AuUInt32 length, std::function) = 0; virtual AuUInt GetInternalRecvBuffer() = 0; virtual bool SetInternalRecvBuffer(AuUInt bytes) = 0; }; class ILocalClientSocket : public IClientSocket { public: using ConnectCallback_cb = std::function; virtual bool Connect() = 0; virtual void ConnectAsync(ConnectCallback_cb cb) = 0; }; struct TlsConnect { Aurora::Crypto::X509::Certificate serverCertificate; AuSPtr socket; }; using TlsConnect_cb = std::function; 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> &soccies) = 0; virtual bool Listen() = 0; }; class INetworkingPool { public: /** Supported thread models: while (true) { // read from sockets pre-frame PumpSOL(); // process other async network logic here // process writes and a few early reads before we sleep PumpEOL(); // yield Yield(); } while (true) { // process other async network logic here // run Run() } */ virtual void PumpSOL() = 0; virtual void PumpEOL() = 0; virtual void Run() = 0; virtual bool NewServer(const ServerInfo &listen, IServer *&out) = 0; virtual bool NewTlsServer(const TLSServerInfo &keys, IServer *&out) = 0; virtual void DeleteServer(IServer *socket) = 0; virtual bool NewClient(const ClientInfo &info, ILocalClientSocket *&out) = 0; virtual bool NewTlsClient(const TLSClientInfo &info, ILocalClientSocket *&out) = 0; virtual void DeleteClient(ILocalClientSocket *socket) = 0; }; }