Crow  1.1
A C++ microframework for the web
 
Loading...
Searching...
No Matches
socket_adaptors.h
1#pragma once
2
3#ifdef CROW_USE_BOOST
4#include <boost/asio.hpp>
5#include <boost/asio/version.hpp>
6#ifdef CROW_ENABLE_SSL
7#include <boost/asio/ssl.hpp>
8#endif
9#else
10#ifndef ASIO_STANDALONE
11#define ASIO_STANDALONE
12#endif
13#include <asio.hpp>
14#include <asio/version.hpp>
15#ifdef CROW_ENABLE_SSL
16#include <asio/ssl.hpp>
17#endif
18#endif
19#include "crow/settings.h"
20
21#if (defined(CROW_USE_BOOST) && BOOST_VERSION >= 107000) || (ASIO_VERSION >= 101008)
22#define GET_IO_CONTEXT(s) ((asio::io_context&)(s).get_executor().context())
23#else
24#define GET_IO_CONTEXT(s) ((s).get_io_service())
25#endif
26
27namespace crow
28{
29#ifdef CROW_USE_BOOST
30 namespace asio = boost::asio;
31 using error_code = boost::system::error_code;
32#else
33 using error_code = asio::error_code;
34#endif
35 using tcp = asio::ip::tcp;
36 using stream_protocol = asio::local::stream_protocol;
37
38 /// A wrapper for the asio::ip::tcp::socket and asio::ssl::stream
40 {
41 using context = void;
42 SocketAdaptor(asio::io_context& io_context, context*):
43 socket_(io_context)
44 {}
45
46 asio::io_context& get_io_context()
47 {
48 return GET_IO_CONTEXT(socket_);
49 }
50
51 /// Get the TCP socket handling data transfers, regardless of what layer is handling transfers on top of the socket.
52 tcp::socket& raw_socket()
53 {
54 return socket_;
55 }
56
57 /// Get the object handling data transfers, this can be either a TCP socket or an SSL stream (if SSL is enabled).
58 tcp::socket& socket()
59 {
60 return socket_;
61 }
62
63 tcp::endpoint remote_endpoint() const
64 {
65 return socket_.remote_endpoint();
66 }
67
68 /// Get the IP address of the remote endpoint, empty when unavailable (socket already closed).
69 std::string address() const
70 {
71 error_code ec;
72 const auto endpoint = socket_.remote_endpoint(ec);
73 return ec ? std::string() : endpoint.address().to_string();
74 }
75
76 /// Get the TCP port of the remote endpoint, 0 when unavailable (socket already closed).
77 uint16_t remote_port() const
78 {
79 error_code ec;
80 const auto endpoint = socket_.remote_endpoint(ec);
81 return ec ? 0 : endpoint.port();
82 }
83
84 bool is_open() const
85 {
86 return socket_.is_open();
87 }
88
89 void close()
90 {
91 error_code ec;
92 socket_.close(ec);
93 }
94
95 void shutdown_readwrite()
96 {
97 error_code ec;
98 socket_.shutdown(asio::socket_base::shutdown_type::shutdown_both, ec);
99 }
100
101 void shutdown_write()
102 {
103 error_code ec;
104 socket_.shutdown(asio::socket_base::shutdown_type::shutdown_send, ec);
105 }
106
107 void shutdown_read()
108 {
109 error_code ec;
110 socket_.shutdown(asio::socket_base::shutdown_type::shutdown_receive, ec);
111 }
112
113 template<typename F>
114 void start(F f)
115 {
116 f(error_code());
117 }
118
119 tcp::socket socket_;
120 };
121
123 {
124 using context = void;
125 UnixSocketAdaptor(asio::io_context& io_context, context*):
126 socket_(io_context)
127 {
128 }
129
130 asio::io_context& get_io_context()
131 {
132 return GET_IO_CONTEXT(socket_);
133 }
134
135 stream_protocol::socket& raw_socket()
136 {
137 return socket_;
138 }
139
140 stream_protocol::socket& socket()
141 {
142 return socket_;
143 }
144
145 stream_protocol::endpoint remote_endpoint()
146 {
147 return socket_.local_endpoint();
148 }
149
150 std::string address() const
151 {
152 return "";
153 }
154
155 /// Unix domain sockets have no port: always 0.
156 uint16_t remote_port() const
157 {
158 return 0;
159 }
160
161 bool is_open()
162 {
163 return socket_.is_open();
164 }
165
166 void close()
167 {
168 error_code ec;
169 socket_.close(ec);
170 }
171
172 void shutdown_readwrite()
173 {
174 error_code ec;
175 socket_.shutdown(asio::socket_base::shutdown_type::shutdown_both, ec);
176 }
177
178 void shutdown_write()
179 {
180 error_code ec;
181 socket_.shutdown(asio::socket_base::shutdown_type::shutdown_send, ec);
182 }
183
184 void shutdown_read()
185 {
186 error_code ec;
187 socket_.shutdown(asio::socket_base::shutdown_type::shutdown_receive, ec);
188 }
189
190 template<typename F>
191 void start(F f)
192 {
193 f(error_code());
194 }
195
196 stream_protocol::socket socket_;
197 };
198
199#ifdef CROW_ENABLE_SSL
201 {
202 using context = asio::ssl::context;
203 using ssl_socket_t = asio::ssl::stream<tcp::socket>;
204 SSLAdaptor(asio::io_context& io_context, context* ctx):
205 ssl_socket_(new ssl_socket_t(io_context, *ctx))
206 {}
207
208 asio::ssl::stream<tcp::socket>& socket()
209 {
210 return *ssl_socket_;
211 }
212
213 tcp::socket::lowest_layer_type&
214 raw_socket()
215 {
216 return ssl_socket_->lowest_layer();
217 }
218
219 tcp::endpoint remote_endpoint()
220 {
221 return raw_socket().remote_endpoint();
222 }
223
224 /// Get the IP address of the remote endpoint, empty when unavailable (socket already closed).
225 std::string address() const
226 {
227 error_code ec;
228 const auto endpoint = ssl_socket_->lowest_layer().remote_endpoint(ec);
229 return ec ? std::string() : endpoint.address().to_string();
230 }
231
232 /// Get the TCP port of the remote endpoint, 0 when unavailable (socket already closed).
233 uint16_t remote_port() const
234 {
235 error_code ec;
236 const auto endpoint = ssl_socket_->lowest_layer().remote_endpoint(ec);
237 return ec ? 0 : endpoint.port();
238 }
239
240 bool is_open()
241 {
242 return ssl_socket_ ? raw_socket().is_open() : false;
243 }
244
245 void close()
246 {
247 if (is_open())
248 {
249 error_code ec;
250 raw_socket().close(ec);
251 }
252 }
253
254 void shutdown_readwrite()
255 {
256 if (is_open())
257 {
258 error_code ec;
259 raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_both, ec);
260 }
261 }
262
263 void shutdown_write()
264 {
265 if (is_open())
266 {
267 error_code ec;
268 raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_send, ec);
269 }
270 }
271
272 void shutdown_read()
273 {
274 if (is_open())
275 {
276 error_code ec;
277 raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_receive, ec);
278 }
279 }
280
281 asio::io_context& get_io_context()
282 {
283 return GET_IO_CONTEXT(raw_socket());
284 }
285
286 template<typename F>
287 void start(F f)
288 {
289 ssl_socket_->async_handshake(asio::ssl::stream_base::server,
290 [f](const error_code& ec) {
291 f(ec);
292 });
293 }
294
295 std::unique_ptr<asio::ssl::stream<tcp::socket>> ssl_socket_;
296 };
297#endif
298} // namespace crow
The main namespace of the library. In this namespace is defined the most important classes and functi...
Definition socket_adaptors.h:201
std::string address() const
Get the IP address of the remote endpoint, empty when unavailable (socket already closed).
Definition socket_adaptors.h:225
uint16_t remote_port() const
Get the TCP port of the remote endpoint, 0 when unavailable (socket already closed).
Definition socket_adaptors.h:233
A wrapper for the asio::ip::tcp::socket and asio::ssl::stream.
Definition socket_adaptors.h:40
tcp::socket & socket()
Get the object handling data transfers, this can be either a TCP socket or an SSL stream (if SSL is e...
Definition socket_adaptors.h:58
std::string address() const
Get the IP address of the remote endpoint, empty when unavailable (socket already closed).
Definition socket_adaptors.h:69
uint16_t remote_port() const
Get the TCP port of the remote endpoint, 0 when unavailable (socket already closed).
Definition socket_adaptors.h:77
tcp::socket & raw_socket()
Get the TCP socket handling data transfers, regardless of what layer is handling transfers on top of ...
Definition socket_adaptors.h:52
Definition socket_adaptors.h:123
uint16_t remote_port() const
Unix domain sockets have no port: always 0.
Definition socket_adaptors.h:156