/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: ISocketChannel.hpp Date: 2022-8-15 Author: Reece ***/ #pragma once namespace Aurora::IO::Protocol { struct IProtocolStack; } namespace Aurora::IO::Net { struct ISocket; struct ISocketChannelEventListener; struct ISocketChannel : Protocol::IProtocolBaseReader, Protocol::IProtocolBaseWriter { /** * @brief * @return */ virtual AuSPtr ToParent() = 0; /** * @brief If not under the drivers data available tick, * schedules the buffered data */ virtual void ScheduleOutOfFrameWrite() = 0; /** * @brief * @return * @warning [not recommended] * @warning requires: SpecifyManualRead */ virtual AuSPtr ToReadTransaction() = 0; /** * @brief * @return * @warning [not recommended] * @warning requires: SpecifyManualWrite */ virtual AuSPtr ToWriteTransaction() = 0; // // Protocol stack APIs // [used for tls, compression, encryption, and friends] // /** * @brief * @return */ virtual AuSPtr NewProtocolRecvStack() = 0; /** * @brief * @return */ virtual AuSPtr NewProtocolSendStack() = 0; /** * @brief * @param pRecvProtocol */ virtual void SpecifyRecvProtocol(const AuSPtr &pRecvProtocol) = 0; /** * @brief * @param pSendProtocol */ virtual void SpecifySendProtocol(const AuSPtr &pSendProtocol) = 0; /** * @brief * @param uNextFrameSize */ virtual void SetNextFrameTargetLength(AuUInt uNextFrameSize) = 0; /** * @brief * @return */ virtual AuUInt GetNextFrameTargetLength() = 0; // // The following specify functions are to be used before the socket has established / during preestablish. // Exceptions will be noted. // /** * @brief Disables usage of the ToWriteTransaction api. * @param bEnableDirectAIOWrite when true, disables protocol handler behaviour * and enables the ::ToWriteTransaction() routine * @return */ virtual bool SpecifyManualWrite(bool bEnableDirectAIOWrite) = 0; /** * @brief Disables automatic pipe processing of the socket. Instead, * you must use the ToReadTransaction to read until EoS. * @param bEnableDirectAIOWrite when true, disables the pipe procoessor * @return */ virtual bool SpecifyManualRead(bool bEnableDirectAIORead) = 0; /** * @brief * @param * @return * @warning May only succeed after preestablish if SpecifyManualWrite was set true. * * Otherwise, nagle is disabled bc it is a beyond dumb optimization of an era of TTY. * It is not unreasonable for a client and server to use a similar tick rate, with * identical io-constraints, doing things at a similar rate, to process packets given * shared bandwidth constraints before DoS-dropping. * (just configure your buffer sizes correctly - perhaps in real time) * * Point is, any reasonably buffered protocol *wants* a flush after a frame or more has * been written in an IO/application tick. * If you don't, you end up waiting on the other side to send a response to a request you've * never actually sent. * * As a frame of reference, NGINX, CURL, chromium, all either use nodelay by default or the * community recommends its' usage as a default. * https://bugzilla.mozilla.org/show_bug.cgi?id=542401 * https://curl.se/libcurl/c/CURLOPT_TCP_NODELAY.html * https://github.com/websocket-client/websocket-client/issues/41 */ virtual bool SpecifyTCPNoDelay(bool bFuckNagle) = 0; /** * @brief [...] * @return */ virtual bool GetCurrentTCPNoDelay() = 0; /** * @brief In manual mode, you may wish to use the loop source * interface of the IAsyncTransaction. By default, Network * io is optimized in such a way that IO fences aren't * required for use. * default: false * @param bAllocateFence * @return */ virtual bool SpecifyTransactionsHaveIOFence(bool bAllocateFence) = 0; /** * @brief Specifies the READ-bound rate-limit per IO tick * @param uBytes * @param pCallbackOptional * @return */ virtual bool SpecifyPerTickAsyncReadLimit(AuUInt uBytes) = 0; /** * @brief Reallocate both the input and output bytebuffer * @param uBytes ... * @param pCallbackOptional optional if on thread * @return * [can work after establish under the right conditions] */ virtual bool SpecifyBufferSize(AuUInt uBytes, const AuSPtr> &pCallbackOptional) = 0; /** * @brief * @param uBytes ... * @param pCallbackOptional optional if on thread * @return * @warning The size specified must not interfer with the current * operation or state of the underlying stream. * You cannot resize a buffer, mid-pipe, if it means dropping buffered data * [can work after establish under the right conditions] */ virtual bool SpecifyInputBufferSize(AuUInt uBytes, const AuSPtr> &pCallbackOptional) = 0; /** * @brief [...] * @return */ virtual AuUInt GetInputBufferSize() = 0; /** * @brief * @param uBytes ... * @param pCallbackOptional optional if on thread * @return * @warning The size specified must not interfer with the current * operation or state of the underlying stream. * You cannot resize a buffer, mid-pipe, if it means dropping buffered data * [can work after establish under the right conditions] */ virtual bool SpecifyOutputBufferSize(AuUInt uBytes, const AuSPtr> &pCallbackOptional) = 0; /** * @brief [...] * @return */ virtual AuUInt GetOutputBufferSize() = 0; /** * @brief * @return */ virtual AuSPtr GetRecvStats() = 0; /** * @brief * @return */ virtual AuSPtr GetSendStats() = 0; /** * @brief * @param pListener */ virtual void AddEventListener(const AuSPtr &pListener) = 0; /** * @brief * @param pListener */ virtual void RemoveEventListener(const AuSPtr &pListener) = 0; AURT_ADD_USR_DATA; }; }