| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
- #include "cmDebuggerWindowsPipeConnection.h"
- #include <algorithm>
- #include <cassert>
- #include <cstring>
- #include <stdexcept>
- #include <utility>
- namespace cmDebugger {
- #ifdef _WIN32
- DuplexPipe_WIN32::DuplexPipe_WIN32(HANDLE pipe)
- : hPipe(pipe)
- {
- readOp.Offset = readOp.OffsetHigh = 0;
- readOp.hEvent = CreateEvent(NULL, true, false, NULL);
- writeOp.Offset = readOp.OffsetHigh = 0;
- writeOp.hEvent = CreateEvent(NULL, true, false, NULL);
- }
- DuplexPipe_WIN32::~DuplexPipe_WIN32()
- {
- close();
- }
- size_t DuplexPipe_WIN32::read(void* buffer, size_t n)
- {
- if (hPipe != INVALID_HANDLE_VALUE) {
- readOp.Offset = readOp.OffsetHigh = 0;
- ResetEvent(readOp.hEvent);
- auto r = ReadFile(hPipe, buffer, n, NULL, &readOp);
- auto err = GetLastError();
- if (r || err == ERROR_IO_PENDING) {
- DWORD nRead = 0;
- if (GetOverlappedResult(hPipe, &readOp, &nRead, true)) {
- return nRead;
- }
- }
- }
- return 0;
- }
- bool DuplexPipe_WIN32::write(void const* buffer, size_t n)
- {
- if (hPipe != INVALID_HANDLE_VALUE) {
- writeOp.Offset = writeOp.OffsetHigh = 0;
- ResetEvent(writeOp.hEvent);
- auto w = WriteFile(hPipe, buffer, n, NULL, &writeOp);
- auto err = GetLastError();
- if (w || err == ERROR_IO_PENDING) {
- DWORD nWrite = 0;
- if (GetOverlappedResult(hPipe, &writeOp, &nWrite, true)) {
- return n == nWrite;
- }
- }
- }
- return false;
- }
- void DuplexPipe_WIN32::close()
- {
- CloseHandle(hPipe);
- hPipe = INVALID_HANDLE_VALUE;
- CloseHandle(readOp.hEvent);
- CloseHandle(writeOp.hEvent);
- readOp.hEvent = writeOp.hEvent = INVALID_HANDLE_VALUE;
- }
- bool DuplexPipe_WIN32::WaitForConnection()
- {
- auto connect = ConnectNamedPipe(hPipe, &readOp);
- auto err = GetLastError();
- if (!connect && err == ERROR_IO_PENDING) {
- DWORD ignored;
- if (GetOverlappedResult(hPipe, &readOp, &ignored, true)) {
- return true;
- }
- }
- return connect || err == ERROR_PIPE_CONNECTED;
- }
- cmDebuggerPipeConnection_WIN32::cmDebuggerPipeConnection_WIN32(
- std::string name)
- : PipeName(std::move(name))
- , pipes(nullptr)
- {
- }
- cmDebuggerPipeConnection_WIN32::~cmDebuggerPipeConnection_WIN32()
- {
- if (isOpen()) {
- pipes = nullptr;
- }
- }
- bool cmDebuggerPipeConnection_WIN32::StartListening(std::string& errorMessage)
- {
- bool result = true;
- auto hPipe = CreateNamedPipeA(
- PipeName.c_str(),
- PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
- PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_REJECT_REMOTE_CLIENTS, 1,
- 1024 * 16, 1024 * 16, NMPWAIT_USE_DEFAULT_WAIT, NULL);
- if (hPipe == INVALID_HANDLE_VALUE) {
- auto err = GetLastError();
- errorMessage = GetErrorMessage(err);
- result = false;
- }
- if (result) {
- pipes = std::make_unique<DuplexPipe_WIN32>(hPipe);
- }
- StartedListening.set_value();
- return result;
- }
- std::string cmDebuggerPipeConnection_WIN32::GetErrorMessage(DWORD errorCode)
- {
- LPSTR message = nullptr;
- DWORD size = FormatMessageA(
- FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- nullptr, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPSTR)&message, 0, nullptr);
- std::string errorMessage = "Internal Error with " + this->PipeName + ": " +
- std::string(message, size);
- LocalFree(message);
- return errorMessage;
- }
- std::shared_ptr<dap::Reader> cmDebuggerPipeConnection_WIN32::GetReader()
- {
- return std::static_pointer_cast<dap::Reader>(shared_from_this());
- }
- std::shared_ptr<dap::Writer> cmDebuggerPipeConnection_WIN32::GetWriter()
- {
- return std::static_pointer_cast<dap::Writer>(shared_from_this());
- }
- bool cmDebuggerPipeConnection_WIN32::isOpen()
- {
- return pipes != nullptr;
- }
- void cmDebuggerPipeConnection_WIN32::close()
- {
- CloseConnection();
- }
- void cmDebuggerPipeConnection_WIN32::CloseConnection()
- {
- if (isOpen()) {
- pipes->close();
- pipes = nullptr;
- }
- }
- void cmDebuggerPipeConnection_WIN32::WaitForConnection()
- {
- if (!isOpen()) {
- return;
- }
- if (pipes->WaitForConnection()) {
- return;
- }
- CloseConnection();
- }
- size_t cmDebuggerPipeConnection_WIN32::read(void* buffer, size_t n)
- {
- size_t result = 0;
- if (isOpen()) {
- result = pipes->read(buffer, n);
- if (result == 0) {
- CloseConnection();
- }
- }
- return result;
- }
- bool cmDebuggerPipeConnection_WIN32::write(void const* buffer, size_t n)
- {
- bool result = false;
- if (isOpen()) {
- result = pipes->write(buffer, n);
- if (!result) {
- CloseConnection();
- }
- }
- return result;
- }
- cmDebuggerPipeClient_WIN32::cmDebuggerPipeClient_WIN32(std::string name)
- : PipeName(std::move(name))
- {
- }
- cmDebuggerPipeClient_WIN32::~cmDebuggerPipeClient_WIN32()
- {
- close();
- }
- void cmDebuggerPipeClient_WIN32::WaitForConnection()
- {
- if (!isOpen()) {
- auto hPipe = CreateFileA(PipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0,
- NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
- if (hPipe == INVALID_HANDLE_VALUE) {
- auto err = GetLastError();
- throw std::runtime_error(std::string("CreateFile failed for pipe ") +
- GetErrorMessage(err));
- }
- pipes = std::make_unique<DuplexPipe_WIN32>(hPipe);
- }
- }
- std::string cmDebuggerPipeClient_WIN32::GetErrorMessage(DWORD errorCode)
- {
- LPSTR message = nullptr;
- DWORD size = FormatMessageA(
- FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- nullptr, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPSTR)&message, 0, nullptr);
- std::string errorMessage =
- this->PipeName + ": " + std::string(message, size);
- LocalFree(message);
- return errorMessage;
- }
- bool cmDebuggerPipeClient_WIN32::isOpen()
- {
- return pipes != nullptr;
- }
- void cmDebuggerPipeClient_WIN32::close()
- {
- if (isOpen()) {
- pipes->close();
- pipes = nullptr;
- }
- }
- size_t cmDebuggerPipeClient_WIN32::read(void* buffer, size_t n)
- {
- size_t result = 0;
- if (isOpen()) {
- result = pipes->read(buffer, n);
- if (result == 0) {
- close();
- }
- }
- return result;
- }
- bool cmDebuggerPipeClient_WIN32::write(void const* buffer, size_t n)
- {
- bool result = false;
- if (isOpen()) {
- result = pipes->write(buffer, n);
- if (!result) {
- close();
- }
- }
- return result;
- }
- #endif // _WIN32
- } // namespace cmDebugger
|