Merge branch 'release-3.29'
[kiteware-cmake.git] / Source / cmDebuggerPosixPipeConnection.cxx
blob05874501546f910dc49626feda145ff135c9e91d
1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #include "cmDebuggerPosixPipeConnection.h"
5 #include <cerrno>
6 #include <cstring>
7 #include <stdexcept>
8 #include <utility>
10 #include <unistd.h>
12 #include <sys/socket.h>
14 namespace cmDebugger {
16 #ifndef _WIN32
18 cmDebuggerPipeConnection_POSIX::cmDebuggerPipeConnection_POSIX(
19 std::string name)
20 : PipeName(std::move(name))
22 addr.sun_path[0] = '\0';
25 cmDebuggerPipeConnection_POSIX::~cmDebuggerPipeConnection_POSIX()
27 if (isOpen()) {
28 close();
32 bool cmDebuggerPipeConnection_POSIX::StartListening(std::string& errorMessage)
34 listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
35 if (listen_fd < 0) {
36 errorMessage = "Failed to create socket: ";
37 errorMessage += strerror(errno);
38 return false;
41 addr.sun_family = AF_UNIX;
42 strncpy(addr.sun_path, PipeName.c_str(), sizeof(addr.sun_path));
43 addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
44 if (bind(listen_fd, (sockaddr*)&addr, sizeof(addr)) == -1) {
45 errorMessage = "Failed to bind name '";
46 errorMessage += addr.sun_path;
47 errorMessage += "' to socket: ";
48 errorMessage += strerror(errno);
49 close_listen();
50 return false;
53 if (listen(listen_fd, 1) == -1) {
54 errorMessage = "Failed to listen on socket: ";
55 errorMessage += strerror(errno);
56 close_listen();
57 return false;
60 StartedListening.set_value();
61 return true;
64 std::shared_ptr<dap::Reader> cmDebuggerPipeConnection_POSIX::GetReader()
66 return std::static_pointer_cast<dap::Reader>(shared_from_this());
69 std::shared_ptr<dap::Writer> cmDebuggerPipeConnection_POSIX::GetWriter()
71 return std::static_pointer_cast<dap::Writer>(shared_from_this());
74 bool cmDebuggerPipeConnection_POSIX::isOpen()
76 return rw_pipe >= 0;
79 void cmDebuggerPipeConnection_POSIX::close()
81 close_listen();
82 ::close(rw_pipe);
83 rw_pipe = -1;
86 void cmDebuggerPipeConnection_POSIX::close_listen()
88 if (strlen(addr.sun_path) > 0) {
89 unlink(addr.sun_path);
90 addr.sun_path[0] = '\0';
92 ::close(listen_fd);
93 listen_fd = -1;
96 void cmDebuggerPipeConnection_POSIX::WaitForConnection()
98 sockaddr_un laddr;
99 socklen_t len = sizeof(laddr);
100 rw_pipe = accept(listen_fd, (sockaddr*)&laddr, &len);
101 if (rw_pipe < 0) {
102 close();
103 return;
106 close_listen(); // no longer need the listen resources
109 size_t cmDebuggerPipeConnection_POSIX::read(void* buffer, size_t n)
111 size_t result = 0;
112 if (rw_pipe >= 0) {
113 result = ::read(rw_pipe, buffer, n);
114 if (result == 0) {
115 close();
119 return result;
122 bool cmDebuggerPipeConnection_POSIX::write(void const* buffer, size_t n)
124 bool result = false;
125 if (rw_pipe >= 0) {
126 result = ::write(rw_pipe, buffer, n) >= 0;
127 if (!result) {
128 close();
132 return result;
135 cmDebuggerPipeClient_POSIX::cmDebuggerPipeClient_POSIX(std::string name)
136 : PipeName(std::move(name))
140 cmDebuggerPipeClient_POSIX::~cmDebuggerPipeClient_POSIX()
142 close();
145 void cmDebuggerPipeClient_POSIX::WaitForConnection()
147 rw_pipe = socket(AF_UNIX, SOCK_STREAM, 0);
148 if (rw_pipe < 0) {
149 throw std::runtime_error(std::string("Failed to create socket: ") +
150 strerror(errno));
153 sockaddr_un addr;
154 addr.sun_family = AF_UNIX;
155 strncpy(addr.sun_path, PipeName.c_str(), sizeof(addr.sun_path));
156 addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
157 if (connect(rw_pipe, (sockaddr*)&addr, sizeof(addr)) == -1) {
158 close();
159 throw std::runtime_error(
160 std::string("Failed to connect path to socket: ") + strerror(errno));
164 bool cmDebuggerPipeClient_POSIX::isOpen()
166 return rw_pipe >= 0;
169 void cmDebuggerPipeClient_POSIX::close()
171 if (isOpen()) {
172 ::close(rw_pipe);
173 rw_pipe = -1;
177 size_t cmDebuggerPipeClient_POSIX::read(void* buffer, size_t n)
179 int count = 0;
180 if (isOpen()) {
181 count = static_cast<int>(::read(rw_pipe, buffer, n));
182 if (count == 0) {
183 close();
187 return count;
190 bool cmDebuggerPipeClient_POSIX::write(void const* buffer, size_t n)
192 int count = 0;
193 if (isOpen()) {
194 count = static_cast<int>(::write(rw_pipe, buffer, n));
195 if (count < 0) {
196 close();
200 return count > 0;
203 #endif // !_WIN32
205 } // namespace cmDebugger