| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file Copyright.txt or https://cmake.org/licensing for details. */ |
| |
| #pragma once |
| |
| #include "cmConfigure.h" // IWYU pragma: keep |
| |
| #include <cstddef> |
| #include <memory> |
| #include <string> |
| |
| #include <cm3p/uv.h> |
| |
| #include "cmUVHandlePtr.h" |
| |
| class cmServerBase; |
| |
| /*** |
| * Given a sequence of bytes with any kind of buffering, instances of this |
| * class arrange logical chunks according to whatever the use case is for |
| * the connection. |
| */ |
| class cmConnectionBufferStrategy |
| { |
| public: |
| virtual ~cmConnectionBufferStrategy(); |
| |
| /*** |
| * Called whenever with an active raw buffer. If a logical chunk |
| * becomes available, that chunk is returned and that portion is |
| * removed from the rawBuffer |
| * |
| * @param rawBuffer in/out parameter. Receive buffer; the buffer strategy is |
| * free to manipulate this buffer anyway it needs to. |
| * |
| * @return Next chunk from the stream. Returns the empty string if a chunk |
| * isn't ready yet. Users of this interface should repeatedly call this |
| * function until an empty string is returned since its entirely possible |
| * multiple chunks come in a single raw buffer. |
| */ |
| virtual std::string BufferMessage(std::string& rawBuffer) = 0; |
| |
| /*** |
| * Called to properly buffer an outgoing message. |
| * |
| * @param rawBuffer Message to format in the correct way |
| * |
| * @return Formatted message |
| */ |
| virtual std::string BufferOutMessage(const std::string& rawBuffer) const |
| { |
| return rawBuffer; |
| }; |
| /*** |
| * Resets the internal state of the buffering |
| */ |
| virtual void clear(); |
| |
| // TODO: There should be a callback / flag set for errors |
| }; |
| |
| class cmConnection |
| { |
| public: |
| cmConnection() = default; |
| |
| cmConnection(cmConnection const&) = delete; |
| cmConnection& operator=(cmConnection const&) = delete; |
| |
| virtual void WriteData(const std::string& data) = 0; |
| |
| virtual ~cmConnection(); |
| |
| virtual bool OnConnectionShuttingDown(); |
| |
| virtual bool IsOpen() const = 0; |
| |
| virtual void SetServer(cmServerBase* s); |
| |
| virtual void ProcessRequest(const std::string& request); |
| |
| virtual bool OnServeStart(std::string* pString); |
| |
| protected: |
| cmServerBase* Server = nullptr; |
| }; |
| |
| /*** |
| * Abstraction of a connection; ties in event callbacks from libuv and notifies |
| * the server when appropriate |
| */ |
| class cmEventBasedConnection : public cmConnection |
| { |
| |
| public: |
| /*** |
| * @param bufferStrategy If no strategy is given, it will process the raw |
| * chunks as they come in. The connection |
| * owns the pointer given. |
| */ |
| cmEventBasedConnection(cmConnectionBufferStrategy* bufferStrategy = nullptr); |
| |
| virtual void Connect(uv_stream_t* server); |
| |
| virtual void ReadData(const std::string& data); |
| |
| bool IsOpen() const override; |
| |
| void WriteData(const std::string& data) override; |
| bool OnConnectionShuttingDown() override; |
| |
| virtual void OnDisconnect(int errorCode); |
| |
| static void on_close(uv_handle_t* handle); |
| |
| template <typename T> |
| static void on_close_delete(uv_handle_t* handle) |
| { |
| delete reinterpret_cast<T*>(handle); |
| } |
| |
| protected: |
| cm::uv_stream_ptr WriteStream; |
| |
| std::string RawReadBuffer; |
| |
| std::unique_ptr<cmConnectionBufferStrategy> BufferStrategy; |
| |
| static void on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf); |
| |
| static void on_write(uv_write_t* req, int status); |
| |
| static void on_new_connection(uv_stream_t* stream, int status); |
| |
| static void on_alloc_buffer(uv_handle_t* handle, size_t suggested_size, |
| uv_buf_t* buf); |
| }; |