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 std::string address() const
69 {
70 return socket_.remote_endpoint().address().to_string();
71 }
72
73 /// Get the TCP port of the remote endpoint, 0 when unavailable (socket already closed).
74 uint16_t remote_port() const
75 {
76 error_code ec;
77 const auto endpoint = socket_.remote_endpoint(ec);
78 return ec ? 0 : endpoint.port();
79 }
80
81 bool is_open() const
82 {
83 return socket_.is_open();
84 }
85
86 void close()
87 {
88 error_code ec;
89 socket_.close(ec);
90 }
91
92 void shutdown_readwrite()
93 {
94 error_code ec;
95 socket_.shutdown(asio::socket_base::shutdown_type::shutdown_both, ec);
96 }
97
98 void shutdown_write()
99 {
100 error_code ec;
101 socket_.shutdown(asio::socket_base::shutdown_type::shutdown_send, ec);
102 }
103
104 void shutdown_read()
105 {
106 error_code ec;
107 socket_.shutdown(asio::socket_base::shutdown_type::shutdown_receive, ec);
108 }
109
110 template<typename F>
111 void start(F f)
112 {
113 f(error_code());
114 }
115
116 tcp::socket socket_;
117 };
118
120 {
121 using context = void;
122 UnixSocketAdaptor(asio::io_context& io_context, context*):
123 socket_(io_context)
124 {
125 }
126
127 asio::io_context& get_io_context()
128 {
129 return GET_IO_CONTEXT(socket_);
130 }
131
132 stream_protocol::socket& raw_socket()
133 {
134 return socket_;
135 }
136
137 stream_protocol::socket& socket()
138 {
139 return socket_;
140 }
141
142 stream_protocol::endpoint remote_endpoint()
143 {
144 return socket_.local_endpoint();
145 }
146
147 std::string address() const
148 {
149 return "";
150 }
151
152 /// Unix domain sockets have no port: always 0.
153 uint16_t remote_port() const
154 {
155 return 0;
156 }
157
158 bool is_open()
159 {
160 return socket_.is_open();
161 }
162
163 void close()
164 {
165 error_code ec;
166 socket_.close(ec);
167 }
168
169 void shutdown_readwrite()
170 {
171 error_code ec;
172 socket_.shutdown(asio::socket_base::shutdown_type::shutdown_both, ec);
173 }
174
175 void shutdown_write()
176 {
177 error_code ec;
178 socket_.shutdown(asio::socket_base::shutdown_type::shutdown_send, ec);
179 }
180
181 void shutdown_read()
182 {
183 error_code ec;
184 socket_.shutdown(asio::socket_base::shutdown_type::shutdown_receive, ec);
185 }
186
187 template<typename F>
188 void start(F f)
189 {
190 f(error_code());
191 }
192
193 stream_protocol::socket socket_;
194 };
195
196#ifdef CROW_ENABLE_SSL
198 {
199 using context = asio::ssl::context;
200 using ssl_socket_t = asio::ssl::stream<tcp::socket>;
201 SSLAdaptor(asio::io_context& io_context, context* ctx):
202 ssl_socket_(new ssl_socket_t(io_context, *ctx))
203 {}
204
205 asio::ssl::stream<tcp::socket>& socket()
206 {
207 return *ssl_socket_;
208 }
209
210 tcp::socket::lowest_layer_type&
211 raw_socket()
212 {
213 return ssl_socket_->lowest_layer();
214 }
215
216 tcp::endpoint remote_endpoint()
217 {
218 return raw_socket().remote_endpoint();
219 }
220
221 std::string address() const
222 {
223 return ssl_socket_->lowest_layer().remote_endpoint().address().to_string();
224 }
225
226 /// Get the TCP port of the remote endpoint, 0 when unavailable (socket already closed).
227 uint16_t remote_port() const
228 {
229 error_code ec;
230 const auto endpoint = ssl_socket_->lowest_layer().remote_endpoint(ec);
231 return ec ? 0 : endpoint.port();
232 }
233
234 bool is_open()
235 {
236 return ssl_socket_ ? raw_socket().is_open() : false;
237 }
238
239 void close()
240 {
241 if (is_open())
242 {
243 error_code ec;
244 raw_socket().close(ec);
245 }
246 }
247
248 void shutdown_readwrite()
249 {
250 if (is_open())
251 {
252 error_code ec;
253 raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_both, ec);
254 }
255 }
256
257 void shutdown_write()
258 {
259 if (is_open())
260 {
261 error_code ec;
262 raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_send, ec);
263 }
264 }
265
266 void shutdown_read()
267 {
268 if (is_open())
269 {
270 error_code ec;
271 raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_receive, ec);
272 }
273 }
274
275 asio::io_context& get_io_context()
276 {
277 return GET_IO_CONTEXT(raw_socket());
278 }
279
280 template<typename F>
281 void start(F f)
282 {
283 ssl_socket_->async_handshake(asio::ssl::stream_base::server,
284 [f](const error_code& ec) {
285 f(ec);
286 });
287 }
288
289 std::unique_ptr<asio::ssl::stream<tcp::socket>> ssl_socket_;
290 };
291#endif
292} // namespace crow
The main namespace of the library. In this namespace is defined the most important classes and functi...
Definition socket_adaptors.h:198
uint16_t remote_port() const
Get the TCP port of the remote endpoint, 0 when unavailable (socket already closed).
Definition socket_adaptors.h:227
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
uint16_t remote_port() const
Get the TCP port of the remote endpoint, 0 when unavailable (socket already closed).
Definition socket_adaptors.h:74
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:120
uint16_t remote_port() const
Unix domain sockets have no port: always 0.
Definition socket_adaptors.h:153