OpenVPN 3 Core Library
Loading...
Searching...
No Matches
asiopolysock.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12// Asio polymorphic socket for handling TCP
13// and unix domain sockets.
14
15#ifndef OPENVPN_ASIO_ASIOPOLYSOCK_H
16#define OPENVPN_ASIO_ASIOPOLYSOCK_H
17
18#include <openvpn/io/io.hpp>
19
23#include <openvpn/common/rc.hpp>
27#include <openvpn/addr/ip.hpp>
28
29#if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING)
30#include <openvpn/asio/alt_routing.hpp>
31#elif defined(OPENVPN_POLYSOCK_SUPPORTS_BIND)
33#endif
34
35#ifdef ASIO_HAS_LOCAL_SOCKETS
37#endif
38
40// for shutdown()
42{
43 SHUTDOWN_SEND = (1 << 0),
44 SHUTDOWN_RECV = (1 << 1),
45};
46
47class Base : public RC<thread_unsafe_refcount>
48{
49 public:
51
52 virtual void async_send(const openvpn_io::const_buffer &buf,
53 Function<void(const openvpn_io::error_code &, const size_t)> &&callback) = 0;
54
55 virtual void async_receive(const openvpn_io::mutable_buffer &buf,
56 Function<void(const openvpn_io::error_code &, const size_t)> &&callback) = 0;
57
58 virtual std::string remote_endpoint_str() const = 0;
59 virtual bool remote_ip_port(IP::Addr &addr, unsigned int &port) const = 0;
60
61 virtual void non_blocking(const bool state) = 0;
62
63 virtual void close() = 0;
64
65 virtual void shutdown(const unsigned int flags)
66 {
67 }
68
69 virtual void tcp_nodelay()
70 {
71 }
72 virtual void set_cloexec()
73 {
74 }
75
76 virtual openvpn_io::detail::socket_type native_handle()
77 {
78 return -1;
79 }
80
81#ifdef ASIO_HAS_LOCAL_SOCKETS
82 virtual bool peercreds(SockOpt::Creds &cr)
83 {
84 return false;
85 }
86#endif
87
88#if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING)
89 virtual bool alt_routing_enabled() const
90 {
91 return false;
92 }
93#endif
94
95 virtual bool is_open() const = 0;
96 virtual bool is_local() const = 0;
97
98 size_t index() const
99 {
100 return index_;
101 }
102
103 protected:
104 Base(const size_t index)
105 : index_(index)
106 {
107 }
108
109 private:
110 size_t index_;
111};
112
113struct TCP : public Base
114{
116
117 TCP(openvpn_io::io_context &io_context,
118 const size_t index)
119 : Base(index),
120 socket(io_context)
121 {
122 }
123
124 void async_send(const openvpn_io::const_buffer &buf,
125 Function<void(const openvpn_io::error_code &, const size_t)> &&callback) override
126 {
127 socket.async_send(buf, std::move(callback));
128 }
129
130 void async_receive(const openvpn_io::mutable_buffer &buf,
131 Function<void(const openvpn_io::error_code &, const size_t)> &&callback) override
132 {
133 socket.async_receive(buf, std::move(callback));
134 }
135
136#if !defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING)
137 std::string remote_endpoint_str() const override
138 {
139 try
140 {
141 return "TCP " + openvpn::to_string(socket.remote_endpoint());
142 }
143 catch (const std::exception &)
144 {
145 return "TCP";
146 }
147 }
148#endif
149
150 bool remote_ip_port(IP::Addr &addr, unsigned int &port) const override
151 {
152 try
153 {
154 addr = IP::Addr::from_asio(socket.remote_endpoint().address());
155 port = socket.remote_endpoint().port();
156 return true;
157 }
158 catch (const std::exception &)
159 {
160 return false;
161 }
162 }
163
164 void non_blocking(const bool state) override
165 {
166 socket.non_blocking(state);
167 }
168
169 void tcp_nodelay() override
170 {
171 socket.set_option(openvpn_io::ip::tcp::no_delay(true));
172 }
173
174#if !defined(OPENVPN_PLATFORM_WIN)
175 void set_cloexec() override
176 {
177 const int fd = socket.native_handle();
178 if (fd >= 0)
180 }
181#endif
182
183 void shutdown(const unsigned int flags) override
184 {
185 if (flags & SHUTDOWN_SEND)
186 socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_send);
187 else if (flags & SHUTDOWN_RECV)
188 socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_receive);
189 }
190
191 void close() override
192 {
193 socket.close();
194 }
195
196 bool is_open() const override
197 {
198 return socket.is_open();
199 }
200
201 bool is_local() const override
202 {
203 return false;
204 }
205
206 openvpn_io::detail::socket_type native_handle() override
207 {
208 return socket.native_handle();
209 }
210
211#if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING)
212 std::string remote_endpoint_str() const override
213 {
214 const char *proto = (socket.alt_routing_enabled() ? "TCP ALT " : "TCP ");
215 return proto + socket.to_string();
216 }
217
218 bool alt_routing_enabled() const override
219 {
220 return socket.alt_routing_enabled();
221 }
222
223 AltRouting::Socket socket;
224#elif defined(OPENVPN_POLYSOCK_SUPPORTS_BIND)
225 AsioBoundSocket::Socket socket;
226#else
227 openvpn_io::ip::tcp::socket socket;
228#endif
229};
230
231#ifdef ASIO_HAS_LOCAL_SOCKETS
232struct Unix : public Base
233{
234 typedef RCPtr<Unix> Ptr;
235
236 Unix(openvpn_io::io_context &io_context,
237 const size_t index)
238 : Base(index),
239 socket(io_context)
240 {
241 }
242
243 void async_send(const openvpn_io::const_buffer &buf,
244 Function<void(const openvpn_io::error_code &, const size_t)> &&callback) override
245 {
246 socket.async_send(buf, std::move(callback));
247 }
248
249 void async_receive(const openvpn_io::mutable_buffer &buf,
250 Function<void(const openvpn_io::error_code &, const size_t)> &&callback) override
251 {
252 socket.async_receive(buf, std::move(callback));
253 }
254
255 std::string remote_endpoint_str() const override
256 {
257 return "LOCAL";
258 }
259
260 bool remote_ip_port(IP::Addr &, unsigned int &) const override
261 {
262 return false;
263 }
264
265 void non_blocking(const bool state) override
266 {
267 socket.non_blocking(state);
268 }
269
270 bool peercreds(SockOpt::Creds &cr) override
271 {
272 return SockOpt::peercreds(socket.native_handle(), cr);
273 }
274
275 void set_cloexec() override
276 {
277 const int fd = socket.native_handle();
278 if (fd >= 0)
279 SockOpt::set_cloexec(fd);
280 }
281
282#if !defined(OPENVPN_PLATFORM_MAC)
283 // shutdown() throws "socket is not connected" exception
284 // on macos if another side has called close() - this behavior
285 // breaks communication with agent, and hence disabled
286 void shutdown(const unsigned int flags) override
287 {
288 if (flags & SHUTDOWN_SEND)
289 socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_send);
290 else if (flags & SHUTDOWN_RECV)
291 socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_receive);
292 }
293#endif
294
295 void close() override
296 {
297 socket.close();
298 }
299
300 bool is_open() const override
301 {
302 return socket.is_open();
303 }
304
305 bool is_local() const override
306 {
307 return true;
308 }
309
310 openvpn_io::detail::socket_type native_handle() override
311 {
312 return socket.native_handle();
313 }
314
315 openvpn_io::local::stream_protocol::socket socket;
316};
317#endif
318
319#if defined(OPENVPN_PLATFORM_WIN)
320struct NamedPipe : public Base
321{
322 typedef RCPtr<NamedPipe> Ptr;
323
324 NamedPipe(openvpn_io::windows::stream_handle &&handle_arg,
325 const size_t index)
326 : Base(index),
327 handle(std::move(handle_arg))
328 {
329 }
330
331 void async_send(const openvpn_io::const_buffer &buf,
332 Function<void(const openvpn_io::error_code &, const size_t)> &&callback) override
333 {
334 handle.async_write_some(buf, std::move(callback));
335 }
336
337 void async_receive(const openvpn_io::mutable_buffer &buf,
338 Function<void(const openvpn_io::error_code &, const size_t)> &&callback) override
339 {
340 handle.async_read_some(buf, std::move(callback));
341 }
342
343 std::string remote_endpoint_str() const override
344 {
345 return "NAMED_PIPE";
346 }
347
348 bool remote_ip_port(IP::Addr &, unsigned int &) const override
349 {
350 return false;
351 }
352
353 void non_blocking(const bool state) override
354 {
355 }
356
357 void close() override
358 {
359 handle.close();
360 }
361
362 bool is_open() const override
363 {
364 return handle.is_open();
365 }
366
367 bool is_local() const override
368 {
369 return true;
370 }
371
372 openvpn_io::windows::stream_handle handle;
373};
374#endif
375} // namespace openvpn::AsioPolySock
376
377#endif
virtual bool remote_ip_port(IP::Addr &addr, unsigned int &port) const =0
virtual void async_receive(const openvpn_io::mutable_buffer &buf, Function< void(const openvpn_io::error_code &, const size_t)> &&callback)=0
virtual std::string remote_endpoint_str() const =0
virtual void async_send(const openvpn_io::const_buffer &buf, Function< void(const openvpn_io::error_code &, const size_t)> &&callback)=0
virtual bool is_local() const =0
virtual void shutdown(const unsigned int flags)
virtual void non_blocking(const bool state)=0
virtual openvpn_io::detail::socket_type native_handle()
virtual bool is_open() const =0
static Addr from_asio(const openvpn_io::ip::address &addr)
Definition ip.hpp:576
The smart pointer class.
Definition rc.hpp:119
Reference count base class for objects tracked by RCPtr. Disallows copying and assignment.
Definition rc.hpp:912
void set_cloexec(const int fd)
Definition sockopt.hpp:57
bool peercreds(const int fd, Creds &cr)
Definition peercred.hpp:58
HTTPBase< HTTPCore, Config, Status, HTTP::ReplyType, ContentInfo, olong, RC< thread_unsafe_refcount > > Base
Definition httpcli.hpp:347
std::string to_string(const T &t)
Convert a value to a string.
Definition to_string.hpp:45
bool is_local() const override
openvpn_io::detail::socket_type native_handle() override
bool remote_ip_port(IP::Addr &addr, unsigned int &port) const override
void async_receive(const openvpn_io::mutable_buffer &buf, Function< void(const openvpn_io::error_code &, const size_t)> &&callback) override
void shutdown(const unsigned int flags) override
bool is_open() const override
openvpn_io::ip::tcp::socket socket
void async_send(const openvpn_io::const_buffer &buf, Function< void(const openvpn_io::error_code &, const size_t)> &&callback) override
TCP(openvpn_io::io_context &io_context, const size_t index)
std::string remote_endpoint_str() const override
void non_blocking(const bool state) override
reroute_gw flags
proxy_host_port port