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

100.0% Lines (2/2) 100.0% List of functions (1/1) 50.0% Branches (1/2)
win_tcp_socket.hpp
f(x) Functions (1)
Line Branch TLA Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco ([email protected])
3 // Copyright (c) 2026 Steve Gerbino
4 // Copyright (c) 2026 Michael Vandeberg
5 //
6 // Distributed under the Boost Software License, Version 1.0. (See accompanying
7 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // Official repository: https://github.com/cppalliance/corosio
10 //
11
12 #ifndef BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_TCP_SOCKET_HPP
13 #define BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_TCP_SOCKET_HPP
14
15 #include <boost/corosio/native/detail/endpoint_convert.hpp>
16 #include <boost/corosio/detail/platform.hpp>
17
18 #if BOOST_COROSIO_HAS_IOCP
19
20 #include <boost/corosio/detail/config.hpp>
21 #include <boost/corosio/tcp_socket.hpp>
22 #include <boost/corosio/wait_type.hpp>
23 #include <boost/capy/ex/executor_ref.hpp>
24 #include <boost/corosio/detail/intrusive.hpp>
25 #include <boost/corosio/native/detail/iocp/win_overlapped_op.hpp>
26 #include <boost/corosio/native/detail/iocp/win_windows.hpp>
27
28 #include <coroutine>
29 #include <memory>
30
31 #include <mswsock.h>
32
33 namespace boost::corosio::detail {
34
35 class win_tcp_service;
36 class win_tcp_socket_internal;
37
38 /** Connect operation state. */
39 struct connect_op : overlapped_op
40 {
41 win_tcp_socket_internal& internal;
42 std::shared_ptr<win_tcp_socket_internal> internal_ptr;
43 endpoint target_endpoint;
44
45 static void do_complete(
46 void* owner,
47 scheduler_op* base,
48 std::uint32_t bytes,
49 std::uint32_t error);
50 static void do_cancel_impl(overlapped_op* op) noexcept;
51
52 explicit connect_op(win_tcp_socket_internal& internal_) noexcept;
53 };
54
55 /** Read operation state with buffer descriptors. */
56 struct read_op : overlapped_op
57 {
58 static constexpr std::size_t max_buffers = 16;
59 WSABUF wsabufs[max_buffers];
60 DWORD wsabuf_count = 0;
61 DWORD flags = 0;
62 win_tcp_socket_internal& internal;
63 std::shared_ptr<win_tcp_socket_internal> internal_ptr;
64
65 static void do_complete(
66 void* owner,
67 scheduler_op* base,
68 std::uint32_t bytes,
69 std::uint32_t error);
70 static void do_cancel_impl(overlapped_op* op) noexcept;
71
72 explicit read_op(win_tcp_socket_internal& internal_) noexcept;
73 };
74
75 /** Write operation state with buffer descriptors. */
76 struct write_op : overlapped_op
77 {
78 static constexpr std::size_t max_buffers = 16;
79 WSABUF wsabufs[max_buffers];
80 DWORD wsabuf_count = 0;
81 win_tcp_socket_internal& internal;
82 std::shared_ptr<win_tcp_socket_internal> internal_ptr;
83
84 static void do_complete(
85 void* owner,
86 scheduler_op* base,
87 std::uint32_t bytes,
88 std::uint32_t error);
89 static void do_cancel_impl(overlapped_op* op) noexcept;
90
91 explicit write_op(win_tcp_socket_internal& internal_) noexcept;
92 };
93
94 /** Readiness-wait operation state.
95
96 Completion conveys an error_code only (no bytes_transferred).
97 wait_type::read posts a zero-byte WSARecv: the kernel signals
98 completion when data arrives without consuming it.
99 wait_type::write and wait_type::error park the op in the
100 auxiliary poll reactor until the socket becomes writable or the
101 kernel reports an error condition.
102 */
103 struct wait_op : overlapped_op
104 {
105 WSABUF wsabuf{};
106 DWORD flags = 0;
107 wait_type w = wait_type::read;
108 win_tcp_socket_internal& internal;
109 std::shared_ptr<win_tcp_socket_internal> internal_ptr;
110
111 static void do_complete(
112 void* owner,
113 scheduler_op* base,
114 std::uint32_t bytes,
115 std::uint32_t error);
116 static void do_cancel_impl(overlapped_op* op) noexcept;
117
118 explicit wait_op(win_tcp_socket_internal& internal_) noexcept;
119 };
120
121 /** Internal socket state for IOCP-based I/O.
122
123 This class contains the actual state for a single socket, including
124 the native socket handle and pending operations. It derives from
125 enable_shared_from_this so operations can extend its lifetime.
126
127 @note Internal implementation detail. Users interact with socket class.
128 */
129 class win_tcp_socket_internal
130 : public intrusive_list<win_tcp_socket_internal>::node
131 , public std::enable_shared_from_this<win_tcp_socket_internal>
132 {
133 friend class win_tcp_service;
134 friend class win_tcp_socket;
135 friend struct read_op;
136 friend struct write_op;
137 friend struct connect_op;
138 friend struct wait_op;
139
140 win_tcp_service& svc_;
141 connect_op conn_;
142 read_op rd_;
143 write_op wr_;
144 wait_op wt_;
145 SOCKET socket_ = INVALID_SOCKET;
146 int family_ = AF_UNSPEC;
147
148 public:
149 explicit win_tcp_socket_internal(win_tcp_service& svc) noexcept;
150 ~win_tcp_socket_internal();
151
152 std::coroutine_handle<> connect(
153 std::coroutine_handle<>,
154 capy::executor_ref,
155 endpoint,
156 std::stop_token,
157 std::error_code*);
158
159 std::coroutine_handle<> read_some(
160 std::coroutine_handle<>,
161 capy::executor_ref,
162 buffer_param,
163 std::stop_token,
164 std::error_code*,
165 std::size_t*);
166
167 std::coroutine_handle<> write_some(
168 std::coroutine_handle<>,
169 capy::executor_ref,
170 buffer_param,
171 std::stop_token,
172 std::error_code*,
173 std::size_t*);
174
175 std::coroutine_handle<> wait(
176 std::coroutine_handle<>,
177 capy::executor_ref,
178 wait_type,
179 std::stop_token,
180 std::error_code*);
181
182 SOCKET native_handle() const noexcept;
183 endpoint local_endpoint() const noexcept;
184 endpoint remote_endpoint() const noexcept;
185 bool is_open() const noexcept;
186 void cancel() noexcept;
187 void close_socket() noexcept;
188 void set_socket(SOCKET s) noexcept;
189 void set_endpoints(endpoint local, endpoint remote) noexcept;
190
191 private:
192 endpoint local_endpoint_;
193 endpoint remote_endpoint_;
194 };
195
196 /** Socket implementation wrapper for IOCP-based I/O.
197
198 This class is the public-facing implementation that holds a shared_ptr
199 to the internal state. The shared_ptr is hidden from the public interface.
200
201 @note Internal implementation detail. Users interact with socket class.
202 */
203 class win_tcp_socket final
204 : public tcp_socket::implementation
205 , public intrusive_list<win_tcp_socket>::node
206 {
207 std::shared_ptr<win_tcp_socket_internal> internal_;
208
209 public:
210 explicit win_tcp_socket(
211 std::shared_ptr<win_tcp_socket_internal> internal) noexcept;
212
213 void close_internal() noexcept;
214
215 std::coroutine_handle<> connect(
216 std::coroutine_handle<> h,
217 capy::executor_ref d,
218 endpoint ep,
219 std::stop_token token,
220 std::error_code* ec) override;
221
222 std::coroutine_handle<> read_some(
223 std::coroutine_handle<> h,
224 capy::executor_ref d,
225 buffer_param buf,
226 std::stop_token token,
227 std::error_code* ec,
228 std::size_t* bytes) override;
229
230 std::coroutine_handle<> write_some(
231 std::coroutine_handle<> h,
232 capy::executor_ref d,
233 buffer_param buf,
234 std::stop_token token,
235 std::error_code* ec,
236 std::size_t* bytes) override;
237
238 std::coroutine_handle<> wait(
239 std::coroutine_handle<> h,
240 capy::executor_ref d,
241 wait_type w,
242 std::stop_token token,
243 std::error_code* ec) override;
244
245 std::error_code shutdown(tcp_socket::shutdown_type what) noexcept override;
246
247 native_handle_type native_handle() const noexcept override;
248
249 2669x corosio::family family() const noexcept override
250 {
251 // getsockname fails with WSAEINVAL on an unbound socket, so
252 // the family recorded at socket creation is authoritative
253
1/2
✓ Branch 3 → 4 taken 2669 times.
✗ Branch 3 → 6 not taken.
2669x return to_family(internal_ ? internal_->family_ : AF_UNSPEC);
254 }
255
256 native_handle_type release_socket() noexcept override;
257
258 std::error_code set_option(
259 int level,
260 int optname,
261 void const* data,
262 std::size_t size) noexcept override;
263 std::error_code
264 get_option(int level, int optname, void* data, std::size_t* size)
265 const noexcept override;
266
267 endpoint local_endpoint() const noexcept override;
268 endpoint remote_endpoint() const noexcept override;
269 void cancel() noexcept override;
270
271 win_tcp_socket_internal* get_internal() const noexcept;
272 };
273
274 } // namespace boost::corosio::detail
275
276 #endif // BOOST_COROSIO_HAS_IOCP
277
278 #endif // BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_TCP_SOCKET_HPP
279