summaryrefslogtreecommitdiff
path: root/Source/cmConnection.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmConnection.h')
-rw-r--r--Source/cmConnection.h136
1 files changed, 136 insertions, 0 deletions
diff --git a/Source/cmConnection.h b/Source/cmConnection.h
new file mode 100644
index 000000000..092b91302
--- /dev/null
+++ b/Source/cmConnection.h
@@ -0,0 +1,136 @@
+/* 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 "cmUVHandlePtr.h"
+#include "cm_uv.h"
+
+#include <cstddef>
+#include <memory>
+#include <string>
+
+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);
+};