include/boost/corosio/native/detail/iocp/win_tcp_service.hpp

100.0% Lines (6/6) 100.0% List of functions (3/3) -% Branches (0/0)
win_tcp_service.hpp
f(x) Functions (3)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco ([email protected])
3 // Copyright (c) 2026 Steve Gerbino
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/cppalliance/corosio
9 //
10
11 #ifndef BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_TCP_SERVICE_HPP
12 #define BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_TCP_SERVICE_HPP
13
14 #include <boost/corosio/detail/platform.hpp>
15
16 #if BOOST_COROSIO_HAS_IOCP
17
18 #include <boost/corosio/detail/config.hpp>
19 #include <boost/capy/ex/execution_context.hpp>
20 #include <boost/corosio/detail/intrusive.hpp>
21 #include <boost/corosio/native/detail/iocp/win_mutex.hpp>
22 #include <boost/corosio/native/detail/iocp/win_wsa_init.hpp>
23 #include <boost/corosio/native/detail/iocp/win_windows.hpp>
24
25 #include <boost/corosio/native/detail/iocp/win_tcp_socket.hpp>
26
27 #include <MSWSock.h>
28
29 namespace boost::corosio::detail {
30
31 class win_scheduler;
32 class win_tcp_acceptor;
33 class win_tcp_acceptor_internal;
34 class win_tcp_acceptor_service;
35
36 /** Windows IOCP socket management service.
37
38 This service owns all socket implementations and coordinates their
39 lifecycle with the IOCP. It provides:
40
41 - Socket implementation allocation and deallocation
42 - IOCP handle association for sockets
43 - Function pointer loading for ConnectEx/AcceptEx
44 - Graceful shutdown - destroys all implementations when io_context stops
45
46 @par Thread Safety
47 All public member functions are thread-safe.
48
49 @note Only available on Windows platforms.
50 */
51 class BOOST_COROSIO_DECL win_tcp_service final
52 : private win_wsa_init
53 , public capy::execution_context::service
54 , public io_object::io_service
55 {
56 public:
57 using key_type = win_tcp_service;
58
59 io_object::implementation* construct() override;
60
61 void destroy(io_object::implementation* p) override;
62
63 void close(io_object::handle& h) override;
64
65 /** Construct the socket service.
66
67 Obtains the IOCP handle from the scheduler service and
68 loads extension function pointers.
69
70 @param ctx Reference to the owning execution_context.
71 */
72 explicit win_tcp_service(capy::execution_context& ctx);
73
74 /** Destroy the socket service. */
75 ~win_tcp_service();
76
77 win_tcp_service(win_tcp_service const&) = delete;
78 win_tcp_service& operator=(win_tcp_service const&) = delete;
79
80 /** Shut down the service. */
81 void shutdown() override;
82
83 /** Destroy a socket implementation wrapper.
84 Removes from tracking list and deletes.
85 */
86 void destroy_impl(win_tcp_socket& impl);
87
88 /** Unregister a socket implementation from the service list.
89 Called by the internal impl destructor.
90 */
91 void unregister_impl(win_tcp_socket_internal& impl);
92
93 /** Create and register a socket with the IOCP.
94
95 @param impl The socket implementation internal to initialize.
96 @return Error code, or success.
97 */
98 std::error_code
99 open_socket(win_tcp_socket_internal& impl, int family, int type, int protocol);
100
101 /** Adopt an existing socket handle into an implementation.
102
103 Validates family and type before touching the held socket,
104 then associates the new socket with the IOCP. On success the
105 impl takes ownership and will close the handle; on failure
106 the caller retains ownership.
107
108 @param impl The socket implementation internal to assign to.
109 @param fd The native socket handle to adopt.
110 @return Error code, or success.
111 */
112 std::error_code
113 assign_socket(win_tcp_socket_internal& impl, native_handle_type fd);
114
115 /** Bind a stream socket to a local endpoint.
116
117 @param impl The socket implementation internal to bind.
118 @param ep The local endpoint to bind to.
119 @return Error code, or success.
120 */
121 std::error_code
122 bind_socket(win_tcp_socket_internal& impl, endpoint ep);
123
124 /** Destroy an acceptor implementation wrapper.
125 Removes from tracking list and deletes.
126 */
127 void destroy_acceptor_impl(win_tcp_acceptor& impl);
128
129 /** Unregister an acceptor implementation from the service list.
130 Called by the internal impl destructor.
131 */
132 void unregister_acceptor_impl(win_tcp_acceptor_internal& impl);
133
134 /** Create an acceptor socket without binding or listening.
135
136 Creates a socket and associates it with the IOCP.
137 For IPv6, dual-stack is enabled by default.
138 Does not set SO_REUSEADDR.
139
140 @param impl The acceptor implementation internal to initialize.
141 @param family Address family (e.g. `AF_INET`, `AF_INET6`).
142 @param type Socket type (e.g. `SOCK_STREAM`).
143 @param protocol Protocol number (e.g. `IPPROTO_TCP`).
144 @return Error code, or success.
145 */
146 std::error_code open_acceptor_socket(
147 win_tcp_acceptor_internal& impl, int family, int type, int protocol);
148
149 /** Adopt an existing listening socket into an acceptor.
150
151 Validates the socket, associates it with the IOCP, and only
152 then releases the socket the acceptor already held. Listen
153 state is not verified.
154
155 @param impl The acceptor implementation internal.
156 @param fd The native socket to adopt. Ownership transfers only
157 on success.
158 @return Error code, or success.
159 */
160 std::error_code assign_acceptor_socket(
161 win_tcp_acceptor_internal& impl, native_handle_type fd);
162
163 /** Bind an open acceptor to a local endpoint.
164
165 @param impl The acceptor implementation internal.
166 @param ep The local endpoint to bind to.
167 @return Error code, or success.
168 */
169 std::error_code bind_acceptor(win_tcp_acceptor_internal& impl, endpoint ep);
170
171 /** Start listening for incoming connections.
172
173 @param impl The acceptor implementation internal.
174 @param backlog The listen backlog.
175 @return Error code, or success.
176 */
177 std::error_code listen_acceptor(win_tcp_acceptor_internal& impl, int backlog);
178
179 /** Return the IOCP handle. */
180 void* native_handle() const noexcept;
181
182 /** Return the ConnectEx function pointer. */
183 2358x LPFN_CONNECTEX connect_ex() const noexcept
184 {
185 2358x return connect_ex_;
186 }
187
188 /** Return the AcceptEx function pointer. */
189 2366x LPFN_ACCEPTEX accept_ex() const noexcept
190 {
191 2366x return accept_ex_;
192 }
193
194 /** Post an overlapped operation for completion. */
195 void post(overlapped_op* op);
196
197 /** Signal that an overlapped I/O is now pending (CAS protocol). */
198 void on_pending(overlapped_op* op) noexcept;
199
200 /** Post an immediate completion with pre-stored results. */
201 void on_completion(overlapped_op* op, DWORD error, DWORD bytes) noexcept;
202
203 /** Notify scheduler of pending I/O work. */
204 void work_started() noexcept;
205
206 /** Notify scheduler that I/O work completed. */
207 void work_finished() noexcept;
208
209 /** Return the owning IOCP scheduler. */
210 33519x win_scheduler& scheduler() noexcept
211 {
212 33519x return sched_;
213 }
214
215 private:
216 friend class win_tcp_acceptor_service;
217
218 void load_extension_functions();
219
220 win_scheduler& sched_;
221 BOOST_COROSIO_MSVC_WARNING_PUSH
222 BOOST_COROSIO_MSVC_WARNING_DISABLE(4251) // detail:: members, dll-interface
223 win_mutex mutex_;
224 intrusive_list<win_tcp_socket_internal> socket_list_;
225 intrusive_list<win_tcp_acceptor_internal> acceptor_list_;
226 intrusive_list<win_tcp_socket> socket_wrapper_list_;
227 intrusive_list<win_tcp_acceptor> acceptor_wrapper_list_;
228 BOOST_COROSIO_MSVC_WARNING_POP
229 void* iocp_;
230 LPFN_CONNECTEX connect_ex_ = nullptr;
231 LPFN_ACCEPTEX accept_ex_ = nullptr;
232 };
233
234 } // namespace boost::corosio::detail
235
236 #endif // BOOST_COROSIO_HAS_IOCP
237
238 #endif // BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_TCP_SERVICE_HPP
239