/* 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 #include #include #include #include #include #include #include #include #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 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(suggested_size)); }, // read_cb [](uv_stream_t* readStream, ssize_t nread, const uv_buf_t* buf) { auto conn = static_cast(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 { public: cmDebuggerPipeConnection(std::string name); ~cmDebuggerPipeConnection() override; void WaitForConnection() override { cmDebuggerPipeBase::WaitForConnection(); } bool StartListening(std::string& errorMessage) override; std::shared_ptr GetReader() override; std::shared_ptr GetWriter() override; // dap::ReaderWriter implementation bool isOpen() override; // Used for unit test synchronization std::promise 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