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

68.0% Lines (187/275) 80.6% List of functions (29/36) 38.1% Branches (48/126)
win_local_stream_acceptor_service.hpp
f(x) Functions (36)
Function Calls Lines Branches Blocks
boost::corosio::detail::local_stream_accept_op::local_stream_accept_op() :77 16x 100.0% 100.0% boost::corosio::detail::local_stream_accept_op::do_cancel_impl(boost::corosio::detail::overlapped_op*) :84 0 0.0% 0.0% 0.0% boost::corosio::detail::local_stream_acceptor_wait_op::local_stream_acceptor_wait_op() :93 16x 100.0% 100.0% boost::corosio::detail::local_stream_acceptor_wait_op::do_cancel_impl(boost::corosio::detail::overlapped_op*) :100 0 0.0% 0.0% 0.0% boost::corosio::detail::local_stream_accept_op::do_complete(void*, boost::corosio::detail::scheduler_op*, unsigned int, unsigned int) :118 7x 64.2% 40.5% 57.8% boost::corosio::detail::local_stream_acceptor_wait_op::do_complete(void*, boost::corosio::detail::scheduler_op*, unsigned int, unsigned int) :217 1x 66.7% 66.7% 61.5% boost::corosio::detail::win_local_stream_acceptor_internal::win_local_stream_acceptor_internal(boost::corosio::detail::win_local_stream_service&) :240 16x 100.0% 100.0% boost::corosio::detail::win_local_stream_acceptor_internal::~win_local_stream_acceptor_internal() :246 16x 100.0% 100.0% boost::corosio::detail::win_local_stream_acceptor_internal::socket_service() :252 0 0.0% 0.0% boost::corosio::detail::win_local_stream_acceptor_internal::native_handle() const :258 0 0.0% 0.0% boost::corosio::detail::win_local_stream_acceptor_internal::local_endpoint() const :264 1x 100.0% 100.0% boost::corosio::detail::win_local_stream_acceptor_internal::is_open() const :270 68x 100.0% 100.0% boost::corosio::detail::win_local_stream_acceptor_internal::set_local_endpoint(boost::corosio::local_endpoint) :276 10x 100.0% 100.0% boost::corosio::detail::win_local_stream_acceptor_internal::cancel() :283 1x 100.0% 50.0% 100.0% boost::corosio::detail::win_local_stream_acceptor_internal::wait(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::wait_type, std::stop_token, std::error_code*) :293 1x 87.5% 66.7% 81.0% boost::corosio::detail::win_local_stream_acceptor_internal::close_socket() :326 51x 100.0% 100.0% 100.0% boost::corosio::detail::win_local_stream_acceptor_internal::accept(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref, std::stop_token, std::error_code*, boost::corosio::io_object::implementation**) :341 7x 58.9% 43.3% 49.2% boost::corosio::detail::win_local_stream_acceptor::win_local_stream_acceptor(std::shared_ptr<boost::corosio::detail::win_local_stream_acceptor_internal>) :443 16x 100.0% 100.0% boost::corosio::detail::win_local_stream_acceptor::close_internal() :450 16x 100.0% 50.0% 100.0% boost::corosio::detail::win_local_stream_acceptor::accept(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref, std::stop_token, std::error_code*, boost::corosio::io_object::implementation**) :460 7x 100.0% 100.0% 80.0% boost::corosio::detail::win_local_stream_acceptor::wait(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::wait_type, std::stop_token, std::error_code*) :471 1x 100.0% 100.0% 80.0% boost::corosio::detail::win_local_stream_acceptor::local_endpoint() const :482 1x 100.0% 100.0% boost::corosio::detail::win_local_stream_acceptor::is_open() const :488 68x 100.0% 75.0% 100.0% boost::corosio::detail::win_local_stream_acceptor::cancel() :494 0 0.0% 0.0% 0.0% boost::corosio::detail::win_local_stream_acceptor::release_socket() :501 1x 88.9% 50.0% 92.3% boost::corosio::detail::win_local_stream_acceptor::set_option(int, int, void const*, unsigned long long) :516 0 0.0% 0.0% 0.0% boost::corosio::detail::win_local_stream_acceptor::get_option(int, int, void*, unsigned long long*) const :529 0 0.0% 0.0% 0.0% boost::corosio::detail::win_local_stream_acceptor::get_internal() const :544 54x 100.0% 100.0% boost::corosio::detail::win_local_stream_acceptor_service::win_local_stream_acceptor_service(boost::capy::execution_context&, boost::corosio::detail::win_local_stream_service&) :553 594x 100.0% 100.0% boost::corosio::detail::win_local_stream_acceptor_service::construct() :560 16x 100.0% 100.0% 88.2% boost::corosio::detail::win_local_stream_acceptor_service::destroy(boost::corosio::io_object::implementation*) :580 16x 100.0% 50.0% 100.0% boost::corosio::detail::win_local_stream_acceptor_service::close(boost::corosio::io_object::handle&) :591 25x 100.0% 100.0% boost::corosio::detail::win_local_stream_acceptor_service::open_acceptor_socket(boost::corosio::local_stream_acceptor::implementation&, int, int, int) :598 10x 100.0% 100.0% boost::corosio::detail::win_local_stream_acceptor_service::bind_acceptor(boost::corosio::local_stream_acceptor::implementation&, boost::corosio::local_endpoint) :608 10x 100.0% 100.0% boost::corosio::detail::win_local_stream_acceptor_service::listen_acceptor(boost::corosio::local_stream_acceptor::implementation&, int) :618 9x 100.0% 100.0% boost::corosio::detail::win_local_stream_acceptor_service::shutdown() :627 594x 100.0% 100.0%
Line Branch TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Michael Vandeberg
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_LOCAL_STREAM_ACCEPTOR_SERVICE_HPP
11 #define BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_LOCAL_STREAM_ACCEPTOR_SERVICE_HPP
12
13 #include <boost/corosio/detail/platform.hpp>
14
15 #if BOOST_COROSIO_HAS_IOCP
16
17 #include <boost/corosio/detail/config.hpp>
18 #include <boost/corosio/detail/except.hpp>
19 #include <boost/corosio/detail/local_stream_acceptor_service.hpp>
20 #include <boost/capy/ex/execution_context.hpp>
21
22 #include <boost/corosio/native/detail/iocp/win_local_stream_acceptor.hpp>
23 #include <boost/corosio/native/detail/iocp/win_local_stream_service.hpp>
24
25 #include <boost/corosio/native/detail/iocp/win_scheduler.hpp>
26 #include <boost/corosio/native/detail/iocp/win_completion_key.hpp>
27
28 #include <boost/corosio/native/detail/endpoint_convert.hpp>
29 #include <boost/corosio/native/detail/make_err.hpp>
30 #include <boost/corosio/detail/dispatch_coro.hpp>
31
32 #include <Ws2tcpip.h>
33
34 namespace boost::corosio::detail {
35
36 /* IOCP local stream acceptor service.
37
38 Delegates acceptor lifecycle management to win_local_stream_service
39 and provides the local_stream_acceptor_service virtual interface.
40 */
41 class BOOST_COROSIO_DECL win_local_stream_acceptor_service final
42 : public local_stream_acceptor_service
43 {
44 public:
45 win_local_stream_acceptor_service(
46 capy::execution_context& ctx, win_local_stream_service& svc);
47
48 io_object::implementation* construct() override;
49
50 void destroy(io_object::implementation* p) override;
51
52 void close(io_object::handle& h) override;
53
54 std::error_code open_acceptor_socket(
55 local_stream_acceptor::implementation& impl,
56 int family, int type, int protocol) override;
57
58 std::error_code
59 bind_acceptor(
60 local_stream_acceptor::implementation& impl,
61 corosio::local_endpoint ep) override;
62
63 std::error_code
64 listen_acceptor(
65 local_stream_acceptor::implementation& impl, int backlog) override;
66
67 void shutdown() override;
68
69 private:
70 win_local_stream_service& svc_;
71 };
72
73 // ============================================================
74 // local_stream_accept_op
75 // ============================================================
76
77 16x inline local_stream_accept_op::local_stream_accept_op() noexcept
78 16x : overlapped_op(&do_complete)
79 {
80 16x cancel_func_ = &do_cancel_impl;
81 16x }
82
83 inline void
84 local_stream_accept_op::do_cancel_impl(overlapped_op* base) noexcept
85 {
86 auto* op = static_cast<local_stream_accept_op*>(base);
87 if (op->listen_socket != INVALID_SOCKET)
88 {
89 ::CancelIoEx(reinterpret_cast<HANDLE>(op->listen_socket), op);
90 }
91 }
92
93 16x inline local_stream_acceptor_wait_op::local_stream_acceptor_wait_op() noexcept
94 16x : overlapped_op(&do_complete)
95 {
96 16x cancel_func_ = &do_cancel_impl;
97 16x }
98
99 inline void
100 local_stream_acceptor_wait_op::do_cancel_impl(overlapped_op* base) noexcept
101 {
102 auto* op = static_cast<local_stream_acceptor_wait_op*>(base);
103 op->cancelled.store(true, std::memory_order_release);
104 if (op->listen_socket != INVALID_SOCKET)
105 {
106 ::CancelIoEx(reinterpret_cast<HANDLE>(op->listen_socket), op);
107 }
108 if (op->acceptor_ptr)
109 {
110 op->acceptor_ptr->socket_service().scheduler()
111 .cancel_wait_if_constructed(op);
112 }
113 }
114
115 // accept_op completion handler
116
117 inline void
118 7x local_stream_accept_op::do_complete(
119 void* owner,
120 scheduler_op* base,
121 std::uint32_t /*bytes*/,
122 std::uint32_t /*error*/)
123 {
124 7x auto* op = static_cast<local_stream_accept_op*>(base);
125
126
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 12 taken 7 times.
7x if (!owner)
127 {
128 if (op->accepted_socket != INVALID_SOCKET)
129 {
130 ::closesocket(op->accepted_socket);
131 op->accepted_socket = INVALID_SOCKET;
132 }
133
134 if (op->peer_wrapper)
135 {
136 op->peer_wrapper->close_internal();
137 op->peer_wrapper = nullptr;
138 }
139
140 op->cleanup_only();
141 op->acceptor_ptr.reset();
142 return;
143 }
144
145 7x op->stop_cb.reset();
146
147 bool success =
148
2/4
✓ Branch 13 → 14 taken 7 times.
✗ Branch 13 → 17 not taken.
✓ Branch 15 → 16 taken 7 times.
✗ Branch 15 → 17 not taken.
7x (op->dwError == 0 && !op->cancelled.load(std::memory_order_acquire));
149
150
1/2
✓ Branch 18 → 19 taken 7 times.
✗ Branch 18 → 27 not taken.
7x if (op->ec_out)
151 {
152
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 23 taken 7 times.
7x if (op->cancelled.load(std::memory_order_acquire))
153 *op->ec_out = capy::error::canceled;
154
1/2
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 25 taken 7 times.
7x else if (op->dwError != 0)
155 *op->ec_out = make_err(op->dwError);
156 else
157 7x *op->ec_out = {};
158 }
159
160
3/6
✓ Branch 27 → 28 taken 7 times.
✗ Branch 27 → 44 not taken.
✓ Branch 28 → 29 taken 7 times.
✗ Branch 28 → 44 not taken.
✓ Branch 29 → 30 taken 7 times.
✗ Branch 29 → 44 not taken.
7x if (success && op->accepted_socket != INVALID_SOCKET && op->peer_wrapper)
161 {
162 7x ::setsockopt(
163 op->accepted_socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
164
1/1
✓ Branch 30 → 31 taken 7 times.
7x reinterpret_cast<char*>(&op->listen_socket), sizeof(SOCKET));
165
166 7x op->peer_wrapper->get_internal()->set_socket(op->accepted_socket);
167
168 7x sockaddr_storage local_storage{};
169 7x int local_len = sizeof(local_storage);
170 7x sockaddr_storage remote_storage{};
171 7x int remote_len = sizeof(remote_storage);
172
173 7x corosio::local_endpoint local_ep, remote_ep;
174
1/1
✓ Branch 33 → 34 taken 7 times.
7x if (::getsockname(
175 op->accepted_socket,
176
1/2
✓ Branch 34 → 35 taken 7 times.
✗ Branch 34 → 36 not taken.
7x reinterpret_cast<sockaddr*>(&local_storage), &local_len) == 0)
177 7x local_ep = from_sockaddr_local(
178 local_storage, static_cast<socklen_t>(local_len));
179
1/1
✓ Branch 36 → 37 taken 7 times.
7x if (::getpeername(
180 op->accepted_socket,
181
1/2
✓ Branch 37 → 38 taken 7 times.
✗ Branch 37 → 39 not taken.
7x reinterpret_cast<sockaddr*>(&remote_storage), &remote_len) == 0)
182 7x remote_ep = from_sockaddr_local(
183 remote_storage, static_cast<socklen_t>(remote_len));
184
185 7x op->peer_wrapper->get_internal()->set_endpoints(local_ep, remote_ep);
186 7x op->accepted_socket = INVALID_SOCKET;
187
188
1/2
✓ Branch 41 → 42 taken 7 times.
✗ Branch 41 → 43 not taken.
7x if (op->impl_out)
189 7x *op->impl_out = op->peer_wrapper;
190 7x }
191 else
192 {
193 if (op->accepted_socket != INVALID_SOCKET)
194 {
195 ::closesocket(op->accepted_socket);
196 op->accepted_socket = INVALID_SOCKET;
197 }
198
199 if (op->peer_wrapper)
200 {
201 op->acceptor_ptr->socket_service().destroy(op->peer_wrapper);
202 op->peer_wrapper = nullptr;
203 }
204
205 if (op->impl_out)
206 *op->impl_out = nullptr;
207 }
208
209 7x op->cont_op.cont.h = op->h;
210 7x auto saved_ex = op->ex;
211 7x auto prevent_premature_destruction = std::move(op->acceptor_ptr);
212
213
2/2
✓ Branch 56 → 57 taken 7 times.
✓ Branch 57 → 58 taken 7 times.
7x dispatch_coro(saved_ex, op->cont_op.cont).resume();
214 7x }
215
216 inline void
217 1x local_stream_acceptor_wait_op::do_complete(
218 void* owner,
219 scheduler_op* base,
220 std::uint32_t /*bytes*/,
221 std::uint32_t /*error*/)
222 {
223 1x auto* op = static_cast<local_stream_acceptor_wait_op*>(base);
224
225
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 6 taken 1 time.
1x if (!owner)
226 {
227 op->cleanup_only();
228 op->acceptor_ptr.reset();
229 return;
230 }
231
232 1x auto prevent_premature_destruction = std::move(op->acceptor_ptr);
233
1/1
✓ Branch 8 → 9 taken 1 time.
1x op->invoke_handler();
234 1x }
235
236 // ============================================================
237 // win_local_stream_acceptor_internal
238 // ============================================================
239
240 16x inline win_local_stream_acceptor_internal::win_local_stream_acceptor_internal(
241 16x win_local_stream_service& svc) noexcept
242 16x : svc_(svc)
243 {
244 16x }
245
246 16x inline win_local_stream_acceptor_internal::~win_local_stream_acceptor_internal()
247 {
248 16x svc_.unregister_acceptor_impl(*this);
249 16x }
250
251 inline win_local_stream_service&
252 win_local_stream_acceptor_internal::socket_service() noexcept
253 {
254 return svc_;
255 }
256
257 inline SOCKET
258 win_local_stream_acceptor_internal::native_handle() const noexcept
259 {
260 return socket_;
261 }
262
263 inline corosio::local_endpoint
264 1x win_local_stream_acceptor_internal::local_endpoint() const noexcept
265 {
266 1x return local_endpoint_;
267 }
268
269 inline bool
270 68x win_local_stream_acceptor_internal::is_open() const noexcept
271 {
272 68x return socket_ != INVALID_SOCKET;
273 }
274
275 inline void
276 10x win_local_stream_acceptor_internal::set_local_endpoint(
277 corosio::local_endpoint ep) noexcept
278 {
279 10x local_endpoint_ = ep;
280 10x }
281
282 inline void
283 1x win_local_stream_acceptor_internal::cancel() noexcept
284 {
285
1/2
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 4 not taken.
1x if (socket_ != INVALID_SOCKET)
286 1x ::CancelIoEx(reinterpret_cast<HANDLE>(socket_), nullptr);
287 1x acc_.request_cancel();
288 1x wt_.request_cancel();
289 1x svc_.scheduler().cancel_wait_if_constructed(&wt_);
290 1x }
291
292 inline std::coroutine_handle<>
293 1x win_local_stream_acceptor_internal::wait(
294 std::coroutine_handle<> h,
295 capy::executor_ref d,
296 wait_type w,
297 std::stop_token token,
298 std::error_code* ec)
299 {
300
1/1
✓ Branch 2 → 3 taken 1 time.
1x wt_.acceptor_ptr = shared_from_this();
301 1x wt_.listen_socket = socket_;
302
303 1x auto& op = wt_;
304 1x op.reset();
305 1x op.h = h;
306 1x op.ex = d;
307 1x op.ec_out = ec;
308 1x op.bytes_out = nullptr;
309 1x op.start(token);
310
311 1x svc_.work_started();
312
313
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 15 taken 1 time.
1x if (w == wait_type::write)
314 {
315 svc_.on_completion(&op, 0, 0);
316 return std::noop_coroutine();
317 }
318
319 // wait_type::read and wait_type::error route through the auxiliary
320 // select reactor.
321 1x svc_.scheduler().wait_reactor().register_wait(socket_, w, &op);
322 1x return std::noop_coroutine();
323 }
324
325 inline void
326 51x win_local_stream_acceptor_internal::close_socket() noexcept
327 {
328 51x wt_.request_cancel();
329 51x svc_.scheduler().cancel_wait_if_constructed(&wt_);
330
331
2/2
✓ Branch 5 → 6 taken 9 times.
✓ Branch 5 → 9 taken 42 times.
51x if (socket_ != INVALID_SOCKET)
332 {
333 9x ::CancelIoEx(reinterpret_cast<HANDLE>(socket_), nullptr);
334 9x ::closesocket(socket_);
335 9x socket_ = INVALID_SOCKET;
336 }
337 51x local_endpoint_ = corosio::local_endpoint{};
338 51x }
339
340 inline std::coroutine_handle<>
341 7x win_local_stream_acceptor_internal::accept(
342 std::coroutine_handle<> h,
343 capy::executor_ref d,
344 std::stop_token token,
345 std::error_code* ec,
346 io_object::implementation** impl_out)
347 {
348
1/1
✓ Branch 2 → 3 taken 7 times.
7x acc_.acceptor_ptr = shared_from_this();
349
350 7x auto& op = acc_;
351 7x op.reset();
352 7x op.h = h;
353 7x op.ex = d;
354 7x op.ec_out = ec;
355 7x op.impl_out = impl_out;
356 7x op.start(token);
357
358 7x svc_.work_started();
359
360 // Create wrapper for the peer socket
361
1/1
✓ Branch 10 → 11 taken 7 times.
7x auto* peer_ptr = svc_.construct();
362
1/2
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 16 taken 7 times.
7x if (!peer_ptr)
363 {
364 svc_.on_completion(&op, ERROR_OUTOFMEMORY, 0);
365 return std::noop_coroutine();
366 }
367 7x auto& peer_wrapper = static_cast<win_local_stream_socket&>(*peer_ptr);
368
369 // Always AF_UNIX for local sockets
370
1/1
✓ Branch 16 → 17 taken 7 times.
7x SOCKET accepted = ::WSASocketW(
371 AF_UNIX, SOCK_STREAM, 0, nullptr, 0, WSA_FLAG_OVERLAPPED);
372
373
1/2
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 24 taken 7 times.
7x if (accepted == INVALID_SOCKET)
374 {
375 svc_.destroy(&peer_wrapper);
376 svc_.on_completion(&op, ::WSAGetLastError(), 0);
377 return std::noop_coroutine();
378 }
379
380
1/1
✓ Branch 25 → 26 taken 7 times.
7x HANDLE result = ::CreateIoCompletionPort(
381 7x reinterpret_cast<HANDLE>(accepted), svc_.native_handle(), key_io, 0);
382
383
1/2
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 34 taken 7 times.
7x if (result == nullptr)
384 {
385 DWORD err = ::GetLastError();
386 ::closesocket(accepted);
387 svc_.destroy(&peer_wrapper);
388 svc_.on_completion(&op, err, 0);
389 return std::noop_coroutine();
390 }
391
392 7x op.accepted_socket = accepted;
393 7x op.peer_wrapper = &peer_wrapper;
394 7x op.listen_socket = socket_;
395
396 7x auto accept_ex = svc_.accept_ex();
397
1/2
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 42 taken 7 times.
7x if (!accept_ex)
398 {
399 ::closesocket(accepted);
400 svc_.destroy(&peer_wrapper);
401 op.peer_wrapper = nullptr;
402 op.accepted_socket = INVALID_SOCKET;
403 svc_.on_completion(&op, WSAEOPNOTSUPP, 0);
404 return std::noop_coroutine();
405 }
406
407 // AcceptEx address buffer sized for sockaddr_un
408 7x DWORD addr_size =
409 static_cast<DWORD>(sizeof(un_sa_t) + 16);
410 7x DWORD bytes_received = 0;
411
412 14x BOOL ok = accept_ex(
413
1/1
✓ Branch 42 → 43 taken 7 times.
7x socket_, accepted, op.addr_buf, 0, addr_size, addr_size,
414 &bytes_received, &op);
415
416
1/2
✓ Branch 43 → 44 taken 7 times.
✗ Branch 43 → 52 not taken.
7x if (!ok)
417 {
418
1/1
✓ Branch 44 → 45 taken 7 times.
7x DWORD err = ::WSAGetLastError();
419
1/2
✗ Branch 45 → 46 not taken.
✓ Branch 45 → 52 taken 7 times.
7x if (err != ERROR_IO_PENDING)
420 {
421 ::closesocket(accepted);
422 svc_.destroy(&peer_wrapper);
423 op.peer_wrapper = nullptr;
424 op.accepted_socket = INVALID_SOCKET;
425 svc_.on_completion(&op, err, 0);
426 return std::noop_coroutine();
427 }
428 }
429
430 7x svc_.on_pending(&op);
431
432 // Re-check cancellation after I/O is pending
433
1/2
✗ Branch 54 → 55 not taken.
✓ Branch 54 → 56 taken 7 times.
7x if (op.cancelled.load(std::memory_order_acquire))
434 ::CancelIoEx(reinterpret_cast<HANDLE>(socket_), &op);
435
436 7x return std::noop_coroutine();
437 }
438
439 // ============================================================
440 // win_local_stream_acceptor (wrapper)
441 // ============================================================
442
443 16x inline win_local_stream_acceptor::win_local_stream_acceptor(
444 16x std::shared_ptr<win_local_stream_acceptor_internal> internal) noexcept
445 16x : internal_(std::move(internal))
446 {
447 16x }
448
449 inline void
450 16x win_local_stream_acceptor::close_internal() noexcept
451 {
452
1/2
✓ Branch 3 → 4 taken 16 times.
✗ Branch 3 → 7 not taken.
16x if (internal_)
453 {
454 16x internal_->close_socket();
455 16x internal_.reset();
456 }
457 16x }
458
459 inline std::coroutine_handle<>
460 7x win_local_stream_acceptor::accept(
461 std::coroutine_handle<> h,
462 capy::executor_ref d,
463 std::stop_token token,
464 std::error_code* ec,
465 io_object::implementation** impl_out)
466 {
467
1/1
✓ Branch 4 → 5 taken 7 times.
7x return internal_->accept(h, d, token, ec, impl_out);
468 }
469
470 inline std::coroutine_handle<>
471 1x win_local_stream_acceptor::wait(
472 std::coroutine_handle<> h,
473 capy::executor_ref d,
474 wait_type w,
475 std::stop_token token,
476 std::error_code* ec)
477 {
478
1/1
✓ Branch 4 → 5 taken 1 time.
1x return internal_->wait(h, d, w, token, ec);
479 }
480
481 inline corosio::local_endpoint
482 1x win_local_stream_acceptor::local_endpoint() const noexcept
483 {
484 1x return internal_->local_endpoint();
485 }
486
487 inline bool
488 68x win_local_stream_acceptor::is_open() const noexcept
489 {
490
3/4
✓ Branch 3 → 4 taken 68 times.
✗ Branch 3 → 8 not taken.
✓ Branch 6 → 7 taken 38 times.
✓ Branch 6 → 8 taken 30 times.
68x return internal_ && internal_->is_open();
491 }
492
493 inline void
494 win_local_stream_acceptor::cancel() noexcept
495 {
496 if (internal_)
497 internal_->cancel();
498 }
499
500 inline native_handle_type
501 1x win_local_stream_acceptor::release_socket() noexcept
502 {
503
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1 time.
1x if (!internal_)
504 return static_cast<native_handle_type>(INVALID_SOCKET);
505 1x SOCKET s = internal_->socket_;
506
1/2
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 13 not taken.
1x if (s != INVALID_SOCKET)
507 {
508 1x internal_->cancel();
509 1x internal_->socket_ = INVALID_SOCKET;
510 1x internal_->local_endpoint_ = corosio::local_endpoint{};
511 }
512 1x return static_cast<native_handle_type>(s);
513 }
514
515 inline std::error_code
516 win_local_stream_acceptor::set_option(
517 int level, int optname, void const* data, std::size_t size) noexcept
518 {
519 if (!internal_ || !internal_->is_open())
520 return make_err(WSAENOTSOCK);
521 if (::setsockopt(
522 internal_->native_handle(), level, optname,
523 reinterpret_cast<char const*>(data), static_cast<int>(size)) != 0)
524 return make_err(WSAGetLastError());
525 return {};
526 }
527
528 inline std::error_code
529 win_local_stream_acceptor::get_option(
530 int level, int optname, void* data, std::size_t* size) const noexcept
531 {
532 if (!internal_ || !internal_->is_open())
533 return make_err(WSAENOTSOCK);
534 int len = static_cast<int>(*size);
535 if (::getsockopt(
536 internal_->native_handle(), level, optname,
537 reinterpret_cast<char*>(data), &len) != 0)
538 return make_err(WSAGetLastError());
539 *size = static_cast<std::size_t>(len);
540 return {};
541 }
542
543 inline win_local_stream_acceptor_internal*
544 54x win_local_stream_acceptor::get_internal() const noexcept
545 {
546 54x return internal_.get();
547 }
548
549 // ============================================================
550 // win_local_stream_acceptor_service
551 // ============================================================
552
553 594x inline win_local_stream_acceptor_service::win_local_stream_acceptor_service(
554 594x capy::execution_context& /*ctx*/, win_local_stream_service& svc)
555 594x : svc_(svc)
556 {
557 594x }
558
559 inline io_object::implementation*
560 16x win_local_stream_acceptor_service::construct()
561 {
562 auto internal =
563
1/1
✓ Branch 2 → 3 taken 16 times.
16x std::make_shared<win_local_stream_acceptor_internal>(svc_);
564
565 // Allocate wrapper before mutating lists so a throw from
566 // new doesn't leave a dangling pointer in acceptor_list_.
567 16x auto* raw = internal.get();
568
1/1
✓ Branch 4 → 5 taken 16 times.
16x auto* wrapper = new win_local_stream_acceptor(std::move(internal));
569
570 {
571 16x std::lock_guard<win_mutex> lock(svc_.mutex_);
572 16x svc_.acceptor_list_.push_back(raw);
573 16x svc_.acceptor_wrapper_list_.push_back(wrapper);
574 16x }
575
576 16x return wrapper;
577 16x }
578
579 inline void
580 16x win_local_stream_acceptor_service::destroy(io_object::implementation* p)
581 {
582
1/2
✓ Branch 2 → 3 taken 16 times.
✗ Branch 2 → 5 not taken.
16x if (p)
583 {
584 16x auto& wrapper = static_cast<win_local_stream_acceptor&>(*p);
585 16x wrapper.close_internal();
586 16x svc_.destroy_acceptor_impl(wrapper);
587 }
588 16x }
589
590 inline void
591 25x win_local_stream_acceptor_service::close(io_object::handle& h)
592 {
593 25x auto& wrapper = static_cast<win_local_stream_acceptor&>(*h.get());
594 25x wrapper.get_internal()->close_socket();
595 25x }
596
597 inline std::error_code
598 10x win_local_stream_acceptor_service::open_acceptor_socket(
599 local_stream_acceptor::implementation& impl,
600 int family, int type, int protocol)
601 {
602 auto* internal =
603 10x static_cast<win_local_stream_acceptor&>(impl).get_internal();
604 10x return svc_.open_acceptor_socket(*internal, family, type, protocol);
605 }
606
607 inline std::error_code
608 10x win_local_stream_acceptor_service::bind_acceptor(
609 local_stream_acceptor::implementation& impl,
610 corosio::local_endpoint ep)
611 {
612 auto* internal =
613 10x static_cast<win_local_stream_acceptor&>(impl).get_internal();
614 10x return svc_.bind_acceptor(*internal, ep);
615 }
616
617 inline std::error_code
618 9x win_local_stream_acceptor_service::listen_acceptor(
619 local_stream_acceptor::implementation& impl, int backlog)
620 {
621 auto* internal =
622 9x static_cast<win_local_stream_acceptor&>(impl).get_internal();
623 9x return svc_.listen_acceptor(*internal, backlog);
624 }
625
626 inline void
627 594x win_local_stream_acceptor_service::shutdown()
628 {
629 // Socket shutdown is handled by win_local_stream_service::shutdown()
630 594x }
631
632 } // namespace boost::corosio::detail
633
634 #endif // BOOST_COROSIO_HAS_IOCP
635
636 #endif // BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_LOCAL_STREAM_ACCEPTOR_SERVICE_HPP
637