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

100.0% Lines (2/2) 100.0% List of functions (1/1) 50.0% Branches (1/2)
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/ex/executor_ref.hpp>
22 #include <boost/corosio/detail/intrusive.hpp>
23 #include <boost/corosio/native/detail/iocp/win_overlapped_op.hpp>
24 #include <boost/corosio/native/detail/iocp/win_windows.hpp>
25
26 #include <coroutine>
27 #include <memory>
28
29 #include <ws2tcpip.h>
30 #include <mswsock.h>
31
32 namespace boost::corosio::detail {
33
34 class win_tcp_acceptor_service;
35 class win_tcp_service;
36 class win_tcp_socket;
37 class win_tcp_acceptor_internal;
38
39 /** Accept operation state. */
40 struct accept_op : overlapped_op
41 {
42 SOCKET accepted_socket = INVALID_SOCKET;
43 win_tcp_socket* peer_wrapper = nullptr;
44 std::shared_ptr<win_tcp_acceptor_internal> acceptor_ptr;
45 SOCKET listen_socket = INVALID_SOCKET;
46 io_object::implementation** impl_out = nullptr;
47 char addr_buf[2 * (sizeof(sockaddr_in6) + 16)];
48
49 static void do_complete(
50 void* owner,
51 scheduler_op* base,
52 std::uint32_t bytes,
53 std::uint32_t error);
54 static void do_cancel_impl(overlapped_op* op) noexcept;
55
56 accept_op() noexcept;
57 };
58
59 /** Readiness-wait operation state for an acceptor. */
60 struct acceptor_wait_op : overlapped_op
61 {
62 std::shared_ptr<win_tcp_acceptor_internal> acceptor_ptr;
63 SOCKET listen_socket = INVALID_SOCKET;
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 acceptor_wait_op() noexcept;
73 };
74
75 /** Internal acceptor state for IOCP-based I/O.
76
77 This class contains the actual state for a listening socket, including
78 the native socket handle and pending accept operation.
79
80 @note Internal implementation detail. Users interact with acceptor class.
81 */
82 class win_tcp_acceptor_internal
83 : public intrusive_list<win_tcp_acceptor_internal>::node
84 , public std::enable_shared_from_this<win_tcp_acceptor_internal>
85 {
86 friend class win_tcp_service;
87 friend class win_tcp_acceptor;
88
89 public:
90 explicit win_tcp_acceptor_internal(win_tcp_service& svc) noexcept;
91 ~win_tcp_acceptor_internal();
92
93 /// Return the owning socket service.
94 win_tcp_service& socket_service() noexcept;
95
96 std::coroutine_handle<> accept(
97 std::coroutine_handle<>,
98 capy::executor_ref,
99 std::stop_token,
100 std::error_code*,
101 io_object::implementation**);
102
103 std::coroutine_handle<> wait(
104 std::coroutine_handle<>,
105 capy::executor_ref,
106 wait_type,
107 std::stop_token,
108 std::error_code*);
109
110 SOCKET native_handle() const noexcept;
111 endpoint local_endpoint() const noexcept;
112 bool is_open() const noexcept;
113 void cancel() noexcept;
114 void close_socket() noexcept;
115 void set_local_endpoint(endpoint ep) noexcept;
116
117 accept_op acc_;
118 acceptor_wait_op wt_;
119
120 private:
121 win_tcp_service& svc_;
122 SOCKET socket_ = INVALID_SOCKET;
123 int family_ = AF_UNSPEC;
124 endpoint local_endpoint_;
125 };
126
127 /** Acceptor implementation wrapper for IOCP-based I/O.
128
129 This class is the public-facing implementation that holds a shared_ptr
130 to the internal state. The shared_ptr is hidden from the public interface.
131
132 @note Internal implementation detail. Users interact with acceptor class.
133 */
134 class win_tcp_acceptor final
135 : public tcp_acceptor::implementation
136 , public intrusive_list<win_tcp_acceptor>::node
137 {
138 std::shared_ptr<win_tcp_acceptor_internal> internal_;
139
140 public:
141 explicit win_tcp_acceptor(
142 std::shared_ptr<win_tcp_acceptor_internal> internal) noexcept;
143
144 void close_internal() noexcept;
145
146 std::coroutine_handle<> accept(
147 std::coroutine_handle<> h,
148 capy::executor_ref d,
149 std::stop_token token,
150 std::error_code* ec,
151 io_object::implementation** impl_out) override;
152
153 std::coroutine_handle<> wait(
154 std::coroutine_handle<> h,
155 capy::executor_ref d,
156 wait_type w,
157 std::stop_token token,
158 std::error_code* ec) override;
159
160 endpoint local_endpoint() const noexcept override;
161 bool is_open() const noexcept override;
162 void cancel() noexcept override;
163
164 native_handle_type native_handle() const noexcept override;
165
166 1791x corosio::family family() const noexcept override
167 {
168 // getsockname fails with WSAEINVAL on an unbound socket, so
169 // the family recorded at socket creation is authoritative
170
1/2
✓ Branch 3 → 4 taken 1791 times.
✗ Branch 3 → 6 not taken.
1791x return to_family(internal_ ? internal_->family_ : AF_UNSPEC);
171 }
172 native_handle_type release_socket() noexcept override;
173
174 std::error_code set_option(
175 int level,
176 int optname,
177 void const* data,
178 std::size_t size) noexcept override;
179 std::error_code
180 get_option(int level, int optname, void* data, std::size_t* size)
181 const noexcept override;
182
183 win_tcp_acceptor_internal* get_internal() const noexcept;
184 };
185
186 } // namespace boost::corosio::detail
187
188 #endif // BOOST_COROSIO_HAS_IOCP
189
190 #endif // BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_TCP_ACCEPTOR_HPP
191