Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/cppalliance/beast2
8 : //
9 :
10 : #ifndef BOOST_BEAST2_SERVER_PLAIN_WORKER_HPP
11 : #define BOOST_BEAST2_SERVER_PLAIN_WORKER_HPP
12 :
13 : #include <boost/beast2/server/http_stream.hpp>
14 : #include <boost/beast2/server/call_mf.hpp>
15 : #include <boost/beast2/server/router_asio.hpp>
16 : #include <boost/beast2/server/workers.hpp>
17 : #include <boost/beast2/logger.hpp>
18 : #include <boost/beast2/read.hpp>
19 : #include <boost/capy/application.hpp>
20 : #include <boost/asio/basic_socket_acceptor.hpp>
21 : #include <boost/asio/basic_stream_socket.hpp>
22 : #include <boost/asio/prepend.hpp>
23 : #include <boost/utility/base_from_member.hpp>
24 :
25 : namespace boost {
26 : namespace beast2 {
27 :
28 : template<class Executor, class Protocol>
29 : class plain_worker
30 : : private boost::base_from_member<
31 : asio::basic_stream_socket<Protocol, Executor>>
32 : , public http_stream<
33 : asio::basic_stream_socket<Protocol, Executor>>
34 : {
35 : using base_member = boost::base_from_member<
36 : asio::basic_stream_socket<Protocol, Executor>>;
37 :
38 : public:
39 : using executor_type = Executor;
40 : using protocol_type = Protocol;
41 : using socket_type =
42 : asio::basic_stream_socket<Protocol, Executor>;
43 : using stream_type = socket_type;
44 : using acceptor_config = http::acceptor_config;
45 :
46 : template<class Executor0>
47 : plain_worker(
48 : workers_base& wb,
49 : Executor0 const& ex,
50 : router_asio<stream_type&> rr);
51 :
52 : capy::application& app() noexcept
53 : {
54 : return wb_.app();
55 : }
56 :
57 0 : socket_type& socket() noexcept
58 : {
59 0 : return this->member;
60 : }
61 :
62 : typename Protocol::endpoint&
63 0 : endpoint() noexcept
64 : {
65 0 : return ep_;
66 : }
67 :
68 : /** Cancel all outstanding I/O
69 : */
70 : void cancel();
71 :
72 : // Called when an incoming connection is accepted
73 : void on_accept(acceptor_config const* pconfig);
74 :
75 : void do_fail(
76 : core::string_view s, system::error_code const& ec);
77 :
78 : void reset();
79 :
80 : private:
81 : /** Called when the logical session ends
82 : */
83 : void do_close(system::error_code const& ec);
84 :
85 : workers_base& wb_;
86 : typename Protocol::endpoint ep_;
87 : };
88 :
89 : //------------------------------------------------
90 :
91 : template<class Executor, class Protocol>
92 : template<class Executor0>
93 0 : plain_worker<Executor, Protocol>::
94 : plain_worker(
95 : workers_base& wb,
96 : Executor0 const& ex,
97 : router_asio<stream_type&> rr)
98 0 : : base_member(Executor(ex))
99 : , http_stream<stream_type>(
100 0 : wb.app(),
101 0 : this->member,
102 0 : std::move(rr),
103 0 : [this](system::error_code const& ec)
104 : {
105 0 : this->do_close(ec);
106 : })
107 0 : , wb_(wb)
108 : {
109 0 : }
110 :
111 : template<class Executor, class Protocol>
112 : void
113 0 : plain_worker<Executor, Protocol>::
114 : cancel()
115 : {
116 0 : system::error_code ec;
117 0 : this->member.cancel(ec);
118 0 : }
119 :
120 : //--------------------------------------------
121 :
122 : // Called when an incoming connection is accepted
123 : template<class Executor, class Protocol>
124 : void
125 0 : plain_worker<Executor, Protocol>::
126 : on_accept(acceptor_config const* pconfig)
127 : {
128 0 : BOOST_ASSERT(this->member.get_executor().running_in_this_thread());
129 : // VFALCO TODO timeout
130 0 : this->on_stream_begin(*pconfig);
131 0 : }
132 :
133 : template<class Executor, class Protocol>
134 : void
135 0 : plain_worker<Executor, Protocol>::
136 : do_fail(
137 : core::string_view s, system::error_code const& ec)
138 : {
139 0 : reset();
140 :
141 0 : if(ec == asio::error::operation_aborted)
142 : {
143 0 : LOG_TRC(this->sect_)(
144 : "{} {}: {}",
145 : this->id(), s, ec.message());
146 : // this means the worker was stopped, don't submit new work
147 0 : return;
148 : }
149 :
150 0 : LOG_DBG(this->sect_)(
151 : "{} {}: {}",
152 : this->id(), s, ec.message());
153 0 : wb_.do_idle(this);
154 : }
155 :
156 : template<class Executor, class Protocol>
157 : void
158 0 : plain_worker<Executor, Protocol>::
159 : reset()
160 : {
161 : // Clean up any previous connection.
162 0 : system::error_code ec;
163 0 : this->member.close(ec);
164 0 : }
165 :
166 : /** Close the connection to end the session
167 : */
168 : template<class Executor, class Protocol>
169 : void
170 0 : plain_worker<Executor, Protocol>::
171 : do_close(system::error_code const& ec)
172 : {
173 0 : if(! ec.failed())
174 : {
175 0 : reset();
176 0 : wb_.do_idle(this);
177 0 : return;
178 : }
179 :
180 0 : do_fail("plain_worker::do_close", ec);
181 : }
182 :
183 : } // beast2
184 : } // boost
185 :
186 : #endif
|