OpenVPN 3 Core Library
Loading...
Searching...
No Matches
asio.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#ifndef OPENVPN_CLIENT_ASYNC_RESOLVE_ASIO_H
13#define OPENVPN_CLIENT_ASYNC_RESOLVE_ASIO_H
14
15#include <openvpn/io/io.hpp>
17
19#include <openvpn/common/rc.hpp>
21
22
23namespace openvpn {
24template <typename RESOLVER_TYPE>
26{
27 private:
29
30 class ResolveThread : public RC<thread_safe_refcount>
31 {
32 friend class AsyncResolvable<RESOLVER_TYPE>;
33
34 private:
36
37 openvpn_io::io_context &io_context;
39 std::atomic<bool> detached{false};
40
41 ResolveThread(openvpn_io::io_context &io_context_arg,
43 const std::string &host,
44 const std::string &port)
45 : io_context(io_context_arg),
46 parent(parent_arg)
47 {
48 std::thread t([self = Ptr(this), host, port]()
49 {
50 openvpn_io::io_context io_context(1);
51 openvpn_io::error_code error;
52 RESOLVER_TYPE resolver(io_context);
53 typename RESOLVER_TYPE::results_type results;
54
55 results = resolver.resolve(host, port, error);
56 if (!self->is_detached())
57 {
58 self->post_callback(results, error);
59 } });
60 // detach the thread so that the client won't need to wait for
61 // it to join.
62 t.detach();
63 }
64
65 void detach()
66 {
67 detached.store(true, std::memory_order_relaxed);
68 parent = nullptr;
69 }
70
71 bool is_detached() const
72 {
73 return detached.load(std::memory_order_relaxed);
74 }
75
76 void post_callback(typename RESOLVER_TYPE::results_type results,
77 openvpn_io::error_code error)
78 {
79 openvpn_io::post(io_context, [self = Ptr(this), results, error]()
80 {
81 auto parent = self->parent;
82 if (!self->is_detached() && parent)
83 {
84 self->detach();
85 OPENVPN_ASYNC_HANDLER;
86 parent->resolve_callback(error, results);
87 } });
88 }
89 };
90
91 openvpn_io::io_context &io_context;
92 std::unique_ptr<AsioWork> asio_work;
94
95 public:
96 using resolver_type = RESOLVER_TYPE;
97 using results_type = typename RESOLVER_TYPE::results_type;
98
99 AsyncResolvable(openvpn_io::io_context &io_context_arg)
100 : io_context(io_context_arg)
101 {
102 }
103
105 {
107 }
108
109 virtual void resolve_callback(const openvpn_io::error_code &error,
110 results_type results) = 0;
111
112 // mimic the asynchronous DNS resolution by performing a
113 // synchronous one in a detached thread.
114 //
115 // This strategy has the advantage of allowing the core to
116 // stop/exit without waiting for the getaddrinfo() (used
117 // internally) to terminate.
118 // Note: getaddrinfo() is non-interruptible by design.
119 //
120 // In other words, we are re-creating exactly what ASIO would
121 // normally do in case of async_resolve(), with the difference
122 // that here we have control over the resolving thread and we
123 // can easily detach it. Deatching the internal thread created
124 // by ASIO would not be feasible as it is not exposed.
125 virtual void async_resolve_name(const std::string &host, const std::string &port)
126 {
128 }
129
130 // there might be nothing else in the main io_context queue
131 // right now, therefore we use AsioWork to prevent the loop
132 // from exiting while we perform the DNS resolution in the
133 // detached thread.
135 {
136 asio_work.reset(new AsioWork(io_context));
137 }
138
139 // to be called by the child class when the core wants to stop
140 // and we don't need to wait for the detached thread any longer.
141 // It simulates a resolve abort
143 {
144 if (resolve_thread)
145 {
148 }
149
150 asio_work.reset();
151 }
152};
153} // namespace openvpn
154
155#endif /* OPENVPN_CLIENT_ASYNC_RESOLVE_ASIO_H */
ResolveThread(openvpn_io::io_context &io_context_arg, AsyncResolvable< RESOLVER_TYPE > *parent_arg, const std::string &host, const std::string &port)
Definition asio.hpp:41
AsyncResolvable< RESOLVER_TYPE > * parent
Definition asio.hpp:38
void post_callback(typename RESOLVER_TYPE::results_type results, openvpn_io::error_code error)
Definition asio.hpp:76
RCPtr< ResolveThread > Ptr
Definition asio.hpp:35
openvpn_io::io_context & io_context
Definition asio.hpp:37
RESOLVER_TYPE resolver_type
Definition asio.hpp:96
virtual ~AsyncResolvable()
Definition asio.hpp:104
AsyncResolvable(openvpn_io::io_context &io_context_arg)
Definition asio.hpp:99
RCPtr< AsyncResolvable > Ptr
Definition asio.hpp:28
openvpn_io::io_context & io_context
Definition asio.hpp:91
typename RESOLVER_TYPE::results_type results_type
Definition asio.hpp:97
virtual void async_resolve_name(const std::string &host, const std::string &port)
Definition asio.hpp:125
virtual void resolve_callback(const openvpn_io::error_code &error, results_type results)=0
ResolveThread::Ptr resolve_thread
Definition asio.hpp:93
RESOLVER_TYPE resolver
Definition generic.hpp:28
std::unique_ptr< AsioWork > asio_work
Definition asio.hpp:92
The smart pointer class.
Definition rc.hpp:119
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
Definition rc.hpp:290
Reference count base class for objects tracked by RCPtr. Disallows copying and assignment.
Definition rc.hpp:912
proxy_host_port port
proxy_host_port host