Coverage Report

Created: 2025-07-04 06:45

/src/crow/include/crow/socket_adaptors.h
Line
Count
Source (jump to first uncovered line)
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
0
#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
27
namespace 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
39
    struct SocketAdaptor
40
    {
41
        using context = void;
42
        SocketAdaptor(asio::io_context& io_context, context*):
43
          socket_(io_context)
44
0
        {}
45
46
        asio::io_context& get_io_context()
47
0
        {
48
0
            return GET_IO_CONTEXT(socket_);
49
0
        }
Unexecuted instantiation: crow::SocketAdaptor::get_io_context()
Unexecuted instantiation: crow::SocketAdaptor::get_io_context()
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
0
        {
54
0
            return socket_;
55
0
        }
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
0
        {
60
0
            return socket_;
61
0
        }
62
63
        tcp::endpoint remote_endpoint() const
64
0
        {
65
0
            return socket_.remote_endpoint();
66
0
        }
67
68
        std::string address() const
69
0
        {
70
0
            return socket_.remote_endpoint().address().to_string();
71
0
        }
72
73
        bool is_open() const
74
0
        {
75
0
            return socket_.is_open();
76
0
        }
77
78
        void close()
79
0
        {
80
0
            error_code ec;
81
0
            socket_.close(ec);
82
0
        }
83
84
        void shutdown_readwrite()
85
0
        {
86
0
            error_code ec;
87
0
            socket_.shutdown(asio::socket_base::shutdown_type::shutdown_both, ec);
88
0
        }
89
90
        void shutdown_write()
91
0
        {
92
0
            error_code ec;
93
0
            socket_.shutdown(asio::socket_base::shutdown_type::shutdown_send, ec);
94
0
        }
95
96
        void shutdown_read()
97
0
        {
98
0
            error_code ec;
99
0
            socket_.shutdown(asio::socket_base::shutdown_type::shutdown_receive, ec);
100
0
        }
101
102
        template<typename F>
103
        void start(F f)
104
0
        {
105
0
            f(error_code());
106
0
        }
107
108
        tcp::socket socket_;
109
    };
110
111
    struct UnixSocketAdaptor
112
    {
113
        using context = void;
114
        UnixSocketAdaptor(asio::io_context& io_context, context*):
115
          socket_(io_context)
116
0
        {
117
0
        }
118
119
        asio::io_context& get_io_context()
120
0
        {
121
0
            return GET_IO_CONTEXT(socket_);
122
0
        }
Unexecuted instantiation: crow::UnixSocketAdaptor::get_io_context()
Unexecuted instantiation: crow::UnixSocketAdaptor::get_io_context()
123
124
        stream_protocol::socket& raw_socket()
125
0
        {
126
0
            return socket_;
127
0
        }
128
129
        stream_protocol::socket& socket()
130
0
        {
131
0
            return socket_;
132
0
        }
133
134
        stream_protocol::endpoint remote_endpoint()
135
0
        {
136
0
            return socket_.local_endpoint();
137
0
        }
138
139
        std::string address() const
140
0
        {
141
0
            return "";
142
0
        }
143
144
        bool is_open()
145
0
        {
146
0
            return socket_.is_open();
147
0
        }
148
149
        void close()
150
0
        {
151
0
            error_code ec;
152
0
            socket_.close(ec);
153
0
        }
154
155
        void shutdown_readwrite()
156
0
        {
157
0
            error_code ec;
158
0
            socket_.shutdown(asio::socket_base::shutdown_type::shutdown_both, ec);
159
0
        }
160
161
        void shutdown_write()
162
0
        {
163
0
            error_code ec;
164
0
            socket_.shutdown(asio::socket_base::shutdown_type::shutdown_send, ec);
165
0
        }
166
167
        void shutdown_read()
168
0
        {
169
0
            error_code ec;
170
0
            socket_.shutdown(asio::socket_base::shutdown_type::shutdown_receive, ec);
171
0
        }
172
173
        template<typename F>
174
        void start(F f)
175
0
        {
176
0
            f(error_code());
177
0
        }
178
179
        stream_protocol::socket socket_;
180
    };
181
182
#ifdef CROW_ENABLE_SSL
183
    struct SSLAdaptor
184
    {
185
        using context = asio::ssl::context;
186
        using ssl_socket_t = asio::ssl::stream<tcp::socket>;
187
        SSLAdaptor(asio::io_context& io_context, context* ctx):
188
          ssl_socket_(new ssl_socket_t(io_context, *ctx))
189
        {}
190
191
        asio::ssl::stream<tcp::socket>& socket()
192
        {
193
            return *ssl_socket_;
194
        }
195
196
        tcp::socket::lowest_layer_type&
197
          raw_socket()
198
        {
199
            return ssl_socket_->lowest_layer();
200
        }
201
202
        tcp::endpoint remote_endpoint()
203
        {
204
            return raw_socket().remote_endpoint();
205
        }
206
207
        std::string address() const
208
        {
209
            return ssl_socket_->lowest_layer().remote_endpoint().address().to_string();
210
        }
211
212
        bool is_open()
213
        {
214
            return ssl_socket_ ? raw_socket().is_open() : false;
215
        }
216
217
        void close()
218
        {
219
            if (is_open())
220
            {
221
                error_code ec;
222
                raw_socket().close(ec);
223
            }
224
        }
225
226
        void shutdown_readwrite()
227
        {
228
            if (is_open())
229
            {
230
                error_code ec;
231
                raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_both, ec);
232
            }
233
        }
234
235
        void shutdown_write()
236
        {
237
            if (is_open())
238
            {
239
                error_code ec;
240
                raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_send, ec);
241
            }
242
        }
243
244
        void shutdown_read()
245
        {
246
            if (is_open())
247
            {
248
                error_code ec;
249
                raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_receive, ec);
250
            }
251
        }
252
253
        asio::io_context& get_io_context()
254
        {
255
            return GET_IO_CONTEXT(raw_socket());
256
        }
257
258
        template<typename F>
259
        void start(F f)
260
        {
261
            ssl_socket_->async_handshake(asio::ssl::stream_base::server,
262
                                         [f](const error_code& ec) {
263
                                             f(ec);
264
                                         });
265
        }
266
267
        std::unique_ptr<asio::ssl::stream<tcp::socket>> ssl_socket_;
268
    };
269
#endif
270
} // namespace crow