// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include #include "httpsys_iocontext.h" #include #if ZEN_WITH_HTTPSYS # define _WINSOCKAPI_ # include # include # include # include # include namespace zen { /** * WebSocket connection over an http.sys opaque-mode connection * * After the 101 Switching Protocols response is sent with * HTTP_SEND_RESPONSE_FLAG_OPAQUE, http.sys stops parsing HTTP on the * connection. Raw bytes are exchanged via HttpReceiveRequestEntityBody / * HttpSendResponseEntityBody using the original RequestId. * * All I/O is performed asynchronously via the same IOCP threadpool used * for normal http.sys traffic, eliminating per-connection threads. * * Lifetime is managed through intrusive reference counting (RefCounted). * A self-reference (m_SelfRef) is held from Start() until all outstanding * async operations have drained, preventing premature destruction. */ class WsHttpSysConnection : public WebSocketConnection { public: WsHttpSysConnection(HANDLE RequestQueueHandle, HTTP_REQUEST_ID RequestId, IWebSocketHandler& Handler, PTP_IO Iocp); ~WsHttpSysConnection() override; /** * Start the async read loop. Must be called once after construction * and after the 101 response has been sent. */ void Start(); /** * Shut down the connection. Cancels pending I/O; IOCP completions * will fire with ERROR_OPERATION_ABORTED and drain naturally. */ void Shutdown(); // WebSocketConnection interface void SendText(std::string_view Text) override; void SendBinary(std::span Data) override; void Close(uint16_t Code, std::string_view Reason) override; bool IsOpen() const override; // Called from IoCompletionCallback via tagged dispatch void OnReadCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTransferred); void OnWriteCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTransferred); private: void IssueAsyncRead(); void ProcessReceivedData(); void EnqueueWrite(std::vector Frame); void FlushWriteQueue(); void DoClose(uint16_t Code, std::string_view Reason); void Disconnect(); void MaybeReleaseSelfRef(); HANDLE m_RequestQueueHandle; HTTP_REQUEST_ID m_RequestId; IWebSocketHandler& m_Handler; PTP_IO m_Iocp; // Tagged OVERLAPPED contexts for concurrent read and write HttpSysIoContext m_ReadIoContext{}; HttpSysIoContext m_WriteIoContext{}; // Read state std::vector m_ReadBuffer; std::vector m_Accumulated; // Write state RwLock m_WriteLock; std::deque> m_WriteQueue; std::vector m_CurrentWriteBuffer; HTTP_DATA_CHUNK m_WriteChunk{}; bool m_IsWriting = false; // Lifetime management std::atomic m_OutstandingOps{0}; Ref m_SelfRef; std::atomic m_ShutdownRequested{false}; std::atomic m_IsOpen{true}; bool m_CloseSent = false; }; } // namespace zen #endif // ZEN_WITH_HTTPSYS