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

100.0% Lines (2 / 2) -% Branches (0 / 0) 100.0% Functions (1 / 1)
win_tcp_acceptor.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 //
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_ACCEPTOR_HPP
12 #define BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_TCP_ACCEPTOR_HPP
13
14 #include <boost/corosio/native/detail/endpoint_convert.hpp>
15 #include <boost/corosio/detail/platform.hpp>
16
17 #if BOOST_COROSIO_HAS_IOCP
18
19 #include <boost/corosio/tcp_acceptor.hpp>
20 #include <boost/corosio/wait_type.hpp>
21 #include <boost/capy/continuation.hpp>
22 #include <boost/capy/ex/executor_ref.hpp>
23 #include <boost/corosio/detail/object_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 #include <ws2tcpip.h>
31 #include <mswsock.h>
32
33 namespace boost::corosio::detail {
34
35 class win_tcp_acceptor_service;
36 class win_tcp_service;
37 class win_tcp_socket;
38 class win_tcp_acceptor;
39
40 /** Accept operation state. */
41 struct accept_op : overlapped_op
42 {
43 SOCKET accepted_socket = INVALID_SOCKET;
44 win_tcp_socket* peer_wrapper = nullptr;
45 win_tcp_acceptor& acceptor;
46 SOCKET listen_socket = INVALID_SOCKET;
47 io_object::implementation** impl_out = nullptr;
48 char addr_buf[2 * (sizeof(sockaddr_in6) + 16)];
49
50 static void do_complete(
51 void* owner,
52 scheduler_op* base,
53 std::uint32_t bytes,
54 std::uint32_t error);
55 static void do_cancel_impl(overlapped_op* op) noexcept;
56
57 explicit accept_op(win_tcp_acceptor& acceptor_) noexcept;
58 };
59
60 /** Readiness-wait operation state for an acceptor. */
61 struct acceptor_wait_op : overlapped_op
62 {
63 win_tcp_acceptor& acceptor;
64 SOCKET listen_socket = INVALID_SOCKET;
65
66 static void do_complete(
67 void* owner,
68 scheduler_op* base,
69 std::uint32_t bytes,
70 std::uint32_t error);
71 static void do_cancel_impl(overlapped_op* op) noexcept;
72
73 explicit acceptor_wait_op(win_tcp_acceptor& acceptor_) noexcept;
74 };
75
76 /** Acceptor implementation for IOCP-based I/O.
77
78 Collapses the historical internal-state/wrapper split into one
79 pooled `io_object::implementation`: it both owns the listening
80 socket and pending operations, and directly implements
81 `tcp_acceptor::implementation`. `win_tcp_service` recycles
82 instances through its acceptor pool instead of freeing them on
83 every close.
84
85 @note Internal implementation detail. Users interact with acceptor class.
86 */
87 class win_tcp_acceptor final
88 : public tcp_acceptor::implementation
89 , public intrusive_list<win_tcp_acceptor>::node
90 {
91 friend class win_tcp_service;
92 friend struct accept_op;
93 friend struct acceptor_wait_op;
94
95 win_tcp_service& svc_;
96 accept_op acc_;
97 acceptor_wait_op wt_;
98 SOCKET socket_ = INVALID_SOCKET;
99 int family_ = AF_UNSPEC;
100 endpoint local_endpoint_;
101
102 public:
103 explicit win_tcp_acceptor(win_tcp_service& svc) noexcept;
104
105 /// Recycle into the owning service's pool. Defined out-of-line
106 /// after `win_tcp_service` is complete (needs `svc_.acceptor_pool_`).
107 void retire() noexcept override;
108
109 /** Reset recycled state for reuse.
110
111 `close_socket()` already drives the socket handle, family,
112 and cached endpoint to their closed values, and each op's
113 completion drops its `object_ref_` before `refs_` can reach
114 zero, so this only asserts. Each op's `OVERLAPPED` fields are
115 re-seeded by `overlapped_op::reset()` at its next submit, so
116 they are not zeroed here.
117
118 @pre refs_ == 0, socket closed, no op in flight.
119 */
120 void reuse() noexcept;
121
122 /// Return the owning socket service.
123 win_tcp_service& socket_service() noexcept;
124
125 std::coroutine_handle<> accept(
126 capy::continuation& cont,
127 capy::executor_ref d,
128 std::stop_token token,
129 std::error_code* ec,
130 io_object::implementation** impl_out) override;
131
132 std::coroutine_handle<> wait(
133 capy::continuation& cont,
134 capy::executor_ref d,
135 wait_type w,
136 std::stop_token token,
137 std::error_code* ec) override;
138
139 endpoint local_endpoint() const noexcept override;
140 bool is_open() const noexcept override;
141 void cancel() noexcept override;
142
143 native_handle_type native_handle() const noexcept override;
144
145 2269x corosio::family family() const noexcept override
146 {
147 // getsockname fails with WSAEINVAL on an unbound socket, so
148 // the family recorded at socket creation is authoritative
149 2269x return to_family(family_);
150 }
151 native_handle_type release_socket() noexcept override;
152
153 std::error_code set_option(
154 int level,
155 int optname,
156 void const* data,
157 std::size_t size) noexcept override;
158 std::error_code
159 get_option(int level, int optname, void* data, std::size_t* size)
160 const noexcept override;
161
162 void set_local_endpoint(endpoint ep) noexcept;
163 void close_socket() noexcept;
164 };
165
166 } // namespace boost::corosio::detail
167
168 #endif // BOOST_COROSIO_HAS_IOCP
169
170 #endif // BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_TCP_ACCEPTOR_HPP
171