summaryrefslogtreecommitdiffstats
path: root/Source/cmDebuggerPipeConnection.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmDebuggerPipeConnection.h')
-rw-r--r--Source/cmDebuggerPipeConnection.h139
1 files changed, 139 insertions, 0 deletions
diff --git a/Source/cmDebuggerPipeConnection.h b/Source/cmDebuggerPipeConnection.h
new file mode 100644
index 0000000..0991ff7
--- /dev/null
+++ b/Source/cmDebuggerPipeConnection.h
@@ -0,0 +1,139 @@
+/* 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 <condition_variable>
+#include <cstddef>
+#include <future>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <thread>
+
+#include <cm3p/cppdap/io.h>
+#include <cm3p/uv.h>
+
+#include "cmDebuggerAdapter.h"
+#include "cmUVHandlePtr.h"
+
+namespace cmDebugger {
+
+class cmDebuggerPipeBase : public dap::ReaderWriter
+{
+public:
+ cmDebuggerPipeBase(std::string name);
+
+ void WaitForConnection();
+
+ // dap::ReaderWriter implementation
+
+ void close() final;
+ size_t read(void* buffer, size_t n) final;
+ bool write(const void* buffer, size_t n) final;
+
+protected:
+ virtual void CloseConnection(){};
+ template <typename T>
+ void StartReading(uv_stream_t* stream)
+ {
+ uv_read_start(
+ stream,
+ // alloc_cb
+ [](uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
+ (void)handle;
+ char* rawBuffer = new char[suggested_size];
+ *buf =
+ uv_buf_init(rawBuffer, static_cast<unsigned int>(suggested_size));
+ },
+ // read_cb
+ [](uv_stream_t* readStream, ssize_t nread, const uv_buf_t* buf) {
+ auto conn = static_cast<T*>(readStream->data);
+ if (conn) {
+ if (nread >= 0) {
+ conn->BufferData(std::string(buf->base, buf->base + nread));
+ } else {
+ conn->close();
+ }
+ }
+ delete[] (buf->base);
+ });
+ }
+ void StopLoop();
+
+ const std::string PipeName;
+ std::thread LoopThread;
+ cm::uv_loop_ptr Loop;
+ cm::uv_pipe_ptr Pipe;
+ std::mutex Mutex;
+ std::condition_variable Connected;
+ bool FailedToOpen = false;
+
+private:
+ void BufferData(const std::string& data);
+ void WriteInternal();
+
+ cm::uv_async_ptr LoopExit;
+ cm::uv_async_ptr WriteEvent;
+ cm::uv_async_ptr PipeClose;
+ std::string WriteBuffer;
+ std::string ReadBuffer;
+ std::condition_variable ReadReady;
+ std::condition_variable WriteComplete;
+};
+
+class cmDebuggerPipeConnection
+ : public cmDebuggerPipeBase
+ , public cmDebuggerConnection
+ , public std::enable_shared_from_this<cmDebuggerPipeConnection>
+{
+public:
+ cmDebuggerPipeConnection(std::string name);
+ ~cmDebuggerPipeConnection() override;
+
+ void WaitForConnection() override
+ {
+ cmDebuggerPipeBase::WaitForConnection();
+ }
+
+ bool StartListening(std::string& errorMessage) override;
+ std::shared_ptr<dap::Reader> GetReader() override;
+ std::shared_ptr<dap::Writer> GetWriter() override;
+
+ // dap::ReaderWriter implementation
+
+ bool isOpen() override;
+
+ // Used for unit test synchronization
+ std::promise<void> StartedListening;
+
+private:
+ void CloseConnection() override;
+ void Connect(uv_stream_t* server);
+
+ cm::uv_pipe_ptr ServerPipe;
+ cm::uv_async_ptr ServerPipeClose;
+};
+
+class cmDebuggerPipeClient : public cmDebuggerPipeBase
+{
+public:
+ using cmDebuggerPipeBase::cmDebuggerPipeBase;
+ ~cmDebuggerPipeClient() override;
+
+ void Start();
+
+ // dap::ReaderWriter implementation
+
+ bool isOpen() override;
+
+private:
+ void CloseConnection() override;
+ void Connect();
+ void FailConnection();
+
+ bool IsConnected = false;
+};
+
+} // namespace cmDebugger