/src/CMake/Source/cmDebuggerPosixPipeConnection.cxx
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file LICENSE.rst or https://cmake.org/licensing for details. */ |
3 | | #include "cmDebuggerPosixPipeConnection.h" |
4 | | |
5 | | #include <cerrno> |
6 | | #include <cstring> |
7 | | #include <stdexcept> |
8 | | #include <utility> |
9 | | |
10 | | #include <unistd.h> |
11 | | |
12 | | #include <sys/socket.h> |
13 | | |
14 | | namespace cmDebugger { |
15 | | |
16 | | #ifndef _WIN32 |
17 | | |
18 | | cmDebuggerPipeConnection_POSIX::cmDebuggerPipeConnection_POSIX( |
19 | | std::string name) |
20 | 0 | : PipeName(std::move(name)) |
21 | 0 | { |
22 | 0 | addr.sun_path[0] = '\0'; |
23 | 0 | } Unexecuted instantiation: cmDebugger::cmDebuggerPipeConnection_POSIX::cmDebuggerPipeConnection_POSIX(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) Unexecuted instantiation: cmDebugger::cmDebuggerPipeConnection_POSIX::cmDebuggerPipeConnection_POSIX(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) |
24 | | |
25 | | cmDebuggerPipeConnection_POSIX::~cmDebuggerPipeConnection_POSIX() |
26 | 0 | { |
27 | 0 | if (isOpen()) { |
28 | 0 | close(); |
29 | 0 | } |
30 | 0 | } |
31 | | |
32 | | bool cmDebuggerPipeConnection_POSIX::StartListening(std::string& errorMessage) |
33 | 0 | { |
34 | 0 | listen_fd = socket(AF_UNIX, SOCK_STREAM, 0); |
35 | 0 | if (listen_fd < 0) { |
36 | 0 | errorMessage = "Failed to create socket: "; |
37 | 0 | errorMessage += strerror(errno); |
38 | 0 | return false; |
39 | 0 | } |
40 | | |
41 | 0 | addr.sun_family = AF_UNIX; |
42 | 0 | strncpy(addr.sun_path, PipeName.c_str(), sizeof(addr.sun_path)); |
43 | 0 | addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; |
44 | 0 | if (bind(listen_fd, (sockaddr*)&addr, sizeof(addr)) == -1) { |
45 | 0 | errorMessage = "Failed to bind name '"; |
46 | 0 | errorMessage += addr.sun_path; |
47 | 0 | errorMessage += "' to socket: "; |
48 | 0 | errorMessage += strerror(errno); |
49 | 0 | close_listen(); |
50 | 0 | return false; |
51 | 0 | } |
52 | | |
53 | 0 | if (listen(listen_fd, 1) == -1) { |
54 | 0 | errorMessage = "Failed to listen on socket: "; |
55 | 0 | errorMessage += strerror(errno); |
56 | 0 | close_listen(); |
57 | 0 | return false; |
58 | 0 | } |
59 | | |
60 | 0 | StartedListening.set_value(); |
61 | 0 | return true; |
62 | 0 | } |
63 | | |
64 | | std::shared_ptr<dap::Reader> cmDebuggerPipeConnection_POSIX::GetReader() |
65 | 0 | { |
66 | 0 | return std::static_pointer_cast<dap::Reader>(shared_from_this()); |
67 | 0 | } |
68 | | |
69 | | std::shared_ptr<dap::Writer> cmDebuggerPipeConnection_POSIX::GetWriter() |
70 | 0 | { |
71 | 0 | return std::static_pointer_cast<dap::Writer>(shared_from_this()); |
72 | 0 | } |
73 | | |
74 | | bool cmDebuggerPipeConnection_POSIX::isOpen() |
75 | 0 | { |
76 | 0 | return rw_pipe >= 0; |
77 | 0 | } |
78 | | |
79 | | void cmDebuggerPipeConnection_POSIX::close() |
80 | 0 | { |
81 | 0 | close_listen(); |
82 | 0 | ::close(rw_pipe); |
83 | 0 | rw_pipe = -1; |
84 | 0 | } |
85 | | |
86 | | void cmDebuggerPipeConnection_POSIX::close_listen() |
87 | 0 | { |
88 | 0 | if (strlen(addr.sun_path) > 0) { |
89 | 0 | unlink(addr.sun_path); |
90 | 0 | addr.sun_path[0] = '\0'; |
91 | 0 | } |
92 | 0 | ::close(listen_fd); |
93 | 0 | listen_fd = -1; |
94 | 0 | } |
95 | | |
96 | | void cmDebuggerPipeConnection_POSIX::WaitForConnection() |
97 | 0 | { |
98 | 0 | sockaddr_un laddr; |
99 | 0 | socklen_t len = sizeof(laddr); |
100 | 0 | rw_pipe = accept(listen_fd, (sockaddr*)&laddr, &len); |
101 | 0 | if (rw_pipe < 0) { |
102 | 0 | close(); |
103 | 0 | return; |
104 | 0 | } |
105 | | |
106 | 0 | close_listen(); // no longer need the listen resources |
107 | 0 | } |
108 | | |
109 | | size_t cmDebuggerPipeConnection_POSIX::read(void* buffer, size_t n) |
110 | 0 | { |
111 | 0 | size_t result = 0; |
112 | 0 | if (rw_pipe >= 0) { |
113 | 0 | result = ::read(rw_pipe, buffer, n); |
114 | 0 | if (result == 0) { |
115 | 0 | close(); |
116 | 0 | } |
117 | 0 | } |
118 | |
|
119 | 0 | return result; |
120 | 0 | } |
121 | | |
122 | | bool cmDebuggerPipeConnection_POSIX::write(void const* buffer, size_t n) |
123 | 0 | { |
124 | 0 | bool result = false; |
125 | 0 | if (rw_pipe >= 0) { |
126 | 0 | result = ::write(rw_pipe, buffer, n) >= 0; |
127 | 0 | if (!result) { |
128 | 0 | close(); |
129 | 0 | } |
130 | 0 | } |
131 | |
|
132 | 0 | return result; |
133 | 0 | } |
134 | | |
135 | | cmDebuggerPipeClient_POSIX::cmDebuggerPipeClient_POSIX(std::string name) |
136 | 0 | : PipeName(std::move(name)) |
137 | 0 | { |
138 | 0 | } Unexecuted instantiation: cmDebugger::cmDebuggerPipeClient_POSIX::cmDebuggerPipeClient_POSIX(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) Unexecuted instantiation: cmDebugger::cmDebuggerPipeClient_POSIX::cmDebuggerPipeClient_POSIX(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) |
139 | | |
140 | | cmDebuggerPipeClient_POSIX::~cmDebuggerPipeClient_POSIX() |
141 | 0 | { |
142 | 0 | close(); |
143 | 0 | } |
144 | | |
145 | | void cmDebuggerPipeClient_POSIX::WaitForConnection() |
146 | 0 | { |
147 | 0 | rw_pipe = socket(AF_UNIX, SOCK_STREAM, 0); |
148 | 0 | if (rw_pipe < 0) { |
149 | 0 | throw std::runtime_error(std::string("Failed to create socket: ") + |
150 | 0 | strerror(errno)); |
151 | 0 | } |
152 | | |
153 | 0 | sockaddr_un addr; |
154 | 0 | addr.sun_family = AF_UNIX; |
155 | 0 | strncpy(addr.sun_path, PipeName.c_str(), sizeof(addr.sun_path)); |
156 | 0 | addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; |
157 | 0 | if (connect(rw_pipe, (sockaddr*)&addr, sizeof(addr)) == -1) { |
158 | 0 | close(); |
159 | 0 | throw std::runtime_error( |
160 | 0 | std::string("Failed to connect path to socket: ") + strerror(errno)); |
161 | 0 | } |
162 | 0 | } |
163 | | |
164 | | bool cmDebuggerPipeClient_POSIX::isOpen() |
165 | 0 | { |
166 | 0 | return rw_pipe >= 0; |
167 | 0 | } |
168 | | |
169 | | void cmDebuggerPipeClient_POSIX::close() |
170 | 0 | { |
171 | 0 | if (isOpen()) { |
172 | 0 | ::close(rw_pipe); |
173 | 0 | rw_pipe = -1; |
174 | 0 | } |
175 | 0 | } |
176 | | |
177 | | size_t cmDebuggerPipeClient_POSIX::read(void* buffer, size_t n) |
178 | 0 | { |
179 | 0 | int count = 0; |
180 | 0 | if (isOpen()) { |
181 | 0 | count = static_cast<int>(::read(rw_pipe, buffer, n)); |
182 | 0 | if (count == 0) { |
183 | 0 | close(); |
184 | 0 | } |
185 | 0 | } |
186 | |
|
187 | 0 | return count; |
188 | 0 | } |
189 | | |
190 | | bool cmDebuggerPipeClient_POSIX::write(void const* buffer, size_t n) |
191 | 0 | { |
192 | 0 | int count = 0; |
193 | 0 | if (isOpen()) { |
194 | 0 | count = static_cast<int>(::write(rw_pipe, buffer, n)); |
195 | 0 | if (count < 0) { |
196 | 0 | close(); |
197 | 0 | } |
198 | 0 | } |
199 | |
|
200 | 0 | return count > 0; |
201 | 0 | } |
202 | | |
203 | | #endif // !_WIN32 |
204 | | |
205 | | } // namespace cmDebugger |