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

100.0% Lines (2 / 2) -% Branches (0 / 0) 100.0% Functions (1 / 1)
win_udp_socket.hpp
f(x) Functions (1)
Line Branch TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Steve Gerbino
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/corosio
8 //
9
10 #ifndef BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_UDP_SOCKET_HPP
11 #define BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_UDP_SOCKET_HPP
12
13 #include <boost/corosio/native/detail/endpoint_convert.hpp>
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/corosio/detail/object_ref.hpp>
20 #include <boost/corosio/udp_socket.hpp>
21 #include <boost/corosio/wait_type.hpp>
22 #include <boost/capy/continuation.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
30 namespace boost::corosio::detail {
31
32 class win_udp_service;
33 class win_udp_socket;
34
35 /** Send-to operation state with buffer and destination address. */
36 struct send_to_op : overlapped_op
37 {
38 static constexpr std::size_t max_buffers = 16;
39 WSABUF wsabufs[max_buffers];
40 DWORD wsabuf_count = 0;
41 sockaddr_storage dest_storage{};
42 int dest_len = 0;
43 win_udp_socket& internal;
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 send_to_op(win_udp_socket& internal_) noexcept;
53 };
54
55 /** Recv-from operation state with buffer and source address capture. */
56 struct recv_from_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 sockaddr_storage source_storage{};
63 INT source_len = sizeof(sockaddr_storage);
64 endpoint* source_out = nullptr;
65 win_udp_socket& internal;
66
67 static void do_complete(
68 void* owner,
69 scheduler_op* base,
70 std::uint32_t bytes,
71 std::uint32_t error);
72 static void do_cancel_impl(overlapped_op* op) noexcept;
73
74 explicit recv_from_op(win_udp_socket& internal_) noexcept;
75 };
76
77 /** Connect operation for connected-mode UDP on IOCP. */
78 struct udp_connect_op : overlapped_op
79 {
80 endpoint target_endpoint;
81 win_udp_socket& internal;
82
83 static void do_complete(
84 void* owner,
85 scheduler_op* base,
86 std::uint32_t bytes,
87 std::uint32_t error);
88 static void do_cancel_impl(overlapped_op* op) noexcept;
89
90 explicit udp_connect_op(win_udp_socket& internal_) noexcept;
91 };
92
93 /** Connected send operation (no destination address). */
94 struct udp_send_op : overlapped_op
95 {
96 static constexpr std::size_t max_buffers = 16;
97 WSABUF wsabufs[max_buffers];
98 DWORD wsabuf_count = 0;
99 win_udp_socket& internal;
100
101 static void do_complete(
102 void* owner,
103 scheduler_op* base,
104 std::uint32_t bytes,
105 std::uint32_t error);
106 static void do_cancel_impl(overlapped_op* op) noexcept;
107
108 explicit udp_send_op(win_udp_socket& internal_) noexcept;
109 };
110
111 /** Connected recv operation (no source address). */
112 struct udp_recv_op : overlapped_op
113 {
114 static constexpr std::size_t max_buffers = 16;
115 WSABUF wsabufs[max_buffers];
116 DWORD wsabuf_count = 0;
117 DWORD flags = 0;
118 win_udp_socket& internal;
119
120 static void do_complete(
121 void* owner,
122 scheduler_op* base,
123 std::uint32_t bytes,
124 std::uint32_t error);
125 static void do_cancel_impl(overlapped_op* op) noexcept;
126
127 explicit udp_recv_op(win_udp_socket& internal_) noexcept;
128 };
129
130 /** Readiness-wait operation (datagram socket). */
131 struct udp_wait_op : overlapped_op
132 {
133 win_udp_socket& internal;
134
135 static void do_complete(
136 void* owner,
137 scheduler_op* base,
138 std::uint32_t bytes,
139 std::uint32_t error);
140 static void do_cancel_impl(overlapped_op* op) noexcept;
141
142 explicit udp_wait_op(win_udp_socket& internal_) noexcept;
143 };
144
145 /** Datagram socket implementation for IOCP-based I/O.
146
147 Collapses the historical internal-state/wrapper split into one
148 pooled `io_object::implementation`: it both owns the native socket
149 handle and pending operations, and directly implements
150 `udp_socket::implementation`. `win_udp_service` recycles instances
151 through its pool instead of freeing them on every close.
152
153 @note Internal implementation detail.
154 */
155 class win_udp_socket final
156 : public udp_socket::implementation
157 , public intrusive_list<win_udp_socket>::node
158 {
159 friend class win_udp_service;
160 friend struct send_to_op;
161 friend struct recv_from_op;
162 friend struct udp_connect_op;
163 friend struct udp_send_op;
164 friend struct udp_recv_op;
165 friend struct udp_wait_op;
166
167 win_udp_service& svc_;
168 send_to_op wr_;
169 recv_from_op rd_;
170 udp_connect_op conn_;
171 udp_send_op send_wr_;
172 udp_recv_op recv_rd_;
173 udp_wait_op wt_;
174 SOCKET socket_ = INVALID_SOCKET;
175 int family_ = AF_UNSPEC;
176 endpoint local_endpoint_;
177 endpoint remote_endpoint_;
178
179 public:
180 explicit win_udp_socket(win_udp_service& svc) noexcept;
181
182 /// Recycle into the owning service's pool. Defined out-of-line
183 /// after `win_udp_service` is complete (needs `svc_.pool_`).
184 void retire() noexcept override;
185
186 /** Reset recycled state for reuse.
187
188 Each op's `OVERLAPPED` fields are re-seeded by
189 `overlapped_op::reset()` at its next submit, so they are not
190 zeroed here.
191
192 @pre refs_ == 0, socket closed, no op in flight.
193 */
194 void reuse() noexcept;
195
196 std::coroutine_handle<> send_to(
197 capy::continuation& cont,
198 capy::executor_ref d,
199 buffer_param buf,
200 endpoint dest,
201 int flags,
202 std::stop_token token,
203 std::error_code* ec,
204 std::size_t* bytes) override;
205
206 std::coroutine_handle<> recv_from(
207 capy::continuation& cont,
208 capy::executor_ref d,
209 buffer_param buf,
210 endpoint* source,
211 int flags,
212 std::stop_token token,
213 std::error_code* ec,
214 std::size_t* bytes) override;
215
216 std::coroutine_handle<> connect(
217 capy::continuation& cont,
218 capy::executor_ref d,
219 endpoint ep,
220 std::stop_token token,
221 std::error_code* ec) override;
222
223 std::coroutine_handle<> send(
224 capy::continuation& cont,
225 capy::executor_ref d,
226 buffer_param buf,
227 int flags,
228 std::stop_token token,
229 std::error_code* ec,
230 std::size_t* bytes) override;
231
232 std::coroutine_handle<> recv(
233 capy::continuation& cont,
234 capy::executor_ref d,
235 buffer_param buf,
236 int flags,
237 std::stop_token token,
238 std::error_code* ec,
239 std::size_t* bytes) override;
240
241 std::coroutine_handle<> wait(
242 capy::continuation& cont,
243 capy::executor_ref d,
244 wait_type w,
245 std::stop_token token,
246 std::error_code* ec) override;
247
248 native_handle_type native_handle() const noexcept override;
249
250 80x corosio::family family() const noexcept override
251 {
252 // getsockname fails with WSAEINVAL on an unbound socket, so
253 // the family recorded at socket creation is authoritative
254 80x return to_family(family_);
255 }
256
257 std::error_code shutdown(udp_socket::shutdown_type what) noexcept override;
258
259 native_handle_type release_socket() noexcept override;
260
261 std::error_code set_option(
262 int level,
263 int optname,
264 void const* data,
265 std::size_t size) noexcept override;
266 std::error_code
267 get_option(int level, int optname, void* data, std::size_t* size)
268 const noexcept override;
269
270 endpoint local_endpoint() const noexcept override;
271 endpoint remote_endpoint() const noexcept override;
272 void cancel() noexcept override;
273
274 void close_socket() noexcept;
275 };
276
277 } // namespace boost::corosio::detail
278
279 #endif // BOOST_COROSIO_HAS_IOCP
280
281 #endif // BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_UDP_SOCKET_HPP
282