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

100.0% Lines (2 / 2) -% Branches (0 / 0) 100.0% Functions (1 / 1)
win_local_stream_socket.hpp
f(x) Functions (1)
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_SOCKET_HPP
11 #define BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_LOCAL_STREAM_SOCKET_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/object_ref.hpp>
19 #include <boost/corosio/local_stream_socket.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/intrusive.hpp>
24 #include <boost/corosio/native/detail/iocp/win_overlapped_op.hpp>
25 #include <boost/corosio/native/detail/iocp/win_windows.hpp>
26
27 #include <coroutine>
28
29 #include <mswsock.h>
30
31 namespace boost::corosio::detail {
32
33 class win_local_stream_service;
34 class win_local_stream_socket;
35
36 /** Connect operation state for local stream sockets. */
37 struct local_stream_connect_op : overlapped_op
38 {
39 win_local_stream_socket& internal;
40 corosio::local_endpoint target_endpoint;
41
42 static void do_complete(
43 void* owner,
44 scheduler_op* base,
45 std::uint32_t bytes,
46 std::uint32_t error);
47 static void do_cancel_impl(overlapped_op* op) noexcept;
48
49 explicit local_stream_connect_op(
50 win_local_stream_socket& internal_) noexcept;
51 };
52
53 /** Read operation state for local stream sockets. */
54 struct local_stream_read_op : overlapped_op
55 {
56 static constexpr std::size_t max_buffers = 16;
57 WSABUF wsabufs[max_buffers];
58 DWORD wsabuf_count = 0;
59 DWORD flags = 0;
60 win_local_stream_socket& internal;
61
62 static void do_complete(
63 void* owner,
64 scheduler_op* base,
65 std::uint32_t bytes,
66 std::uint32_t error);
67 static void do_cancel_impl(overlapped_op* op) noexcept;
68
69 explicit local_stream_read_op(win_local_stream_socket& internal_) noexcept;
70 };
71
72 /** Write operation state for local stream sockets. */
73 struct local_stream_write_op : overlapped_op
74 {
75 static constexpr std::size_t max_buffers = 16;
76 WSABUF wsabufs[max_buffers];
77 DWORD wsabuf_count = 0;
78 win_local_stream_socket& internal;
79
80 static void do_complete(
81 void* owner,
82 scheduler_op* base,
83 std::uint32_t bytes,
84 std::uint32_t error);
85 static void do_cancel_impl(overlapped_op* op) noexcept;
86
87 explicit local_stream_write_op(win_local_stream_socket& internal_) noexcept;
88 };
89
90 /** Readiness-wait operation state for local stream sockets. */
91 struct local_stream_wait_op : overlapped_op
92 {
93 WSABUF wsabuf{};
94 DWORD flags = 0;
95 wait_type w = wait_type::read;
96 win_local_stream_socket& internal;
97
98 static void do_complete(
99 void* owner,
100 scheduler_op* base,
101 std::uint32_t bytes,
102 std::uint32_t error);
103 static void do_cancel_impl(overlapped_op* op) noexcept;
104
105 explicit local_stream_wait_op(win_local_stream_socket& internal_) noexcept;
106 };
107
108 /** Socket implementation for IOCP local stream I/O.
109
110 Collapses the historical internal-state/wrapper split into one
111 pooled `io_object::implementation`: it both owns the native SOCKET
112 handle and pending operations, and directly implements
113 `local_stream_socket::implementation`. `win_local_stream_service`
114 recycles instances through its pool instead of freeing them on
115 every close.
116 */
117 class win_local_stream_socket final
118 : public local_stream_socket::implementation
119 , public intrusive_list<win_local_stream_socket>::node
120 {
121 friend class win_local_stream_service;
122 friend struct local_stream_read_op;
123 friend struct local_stream_write_op;
124 friend struct local_stream_connect_op;
125 friend struct local_stream_wait_op;
126
127 win_local_stream_service& svc_;
128 local_stream_connect_op conn_;
129 local_stream_read_op rd_;
130 local_stream_write_op wr_;
131 local_stream_wait_op wt_;
132 SOCKET socket_ = INVALID_SOCKET;
133 corosio::local_endpoint local_endpoint_;
134 corosio::local_endpoint remote_endpoint_;
135
136 public:
137 explicit win_local_stream_socket(win_local_stream_service& svc) noexcept;
138
139 /// Recycle into the owning service's pool. Defined out-of-line
140 /// after `win_local_stream_service` is complete (needs
141 /// `svc_.pool_`).
142 void retire() noexcept override;
143
144 /** Reset recycled state for reuse.
145
146 Each op's `OVERLAPPED` fields are re-seeded by
147 `overlapped_op::reset()` at its next submit, so they are not
148 zeroed here.
149
150 @pre refs_ == 0, socket closed, no op in flight.
151 */
152 void reuse() noexcept;
153
154 std::coroutine_handle<> connect(
155 capy::continuation& cont,
156 capy::executor_ref d,
157 corosio::local_endpoint ep,
158 std::stop_token token,
159 std::error_code* ec) override;
160
161 std::coroutine_handle<> read_some(
162 capy::continuation& cont,
163 capy::executor_ref d,
164 buffer_param buf,
165 std::stop_token token,
166 std::error_code* ec,
167 std::size_t* bytes) override;
168
169 std::coroutine_handle<> write_some(
170 capy::continuation& cont,
171 capy::executor_ref d,
172 buffer_param buf,
173 std::stop_token token,
174 std::error_code* ec,
175 std::size_t* bytes) override;
176
177 std::coroutine_handle<> wait(
178 capy::continuation& cont,
179 capy::executor_ref d,
180 wait_type w,
181 std::stop_token token,
182 std::error_code* ec) override;
183
184 std::error_code
185 shutdown(local_stream_socket::shutdown_type what) noexcept override;
186
187 native_handle_type native_handle() const noexcept override;
188
189 5x corosio::family family() const noexcept override
190 {
191 // Local sockets have no IP family; v4 is the inert value
192 5x return corosio::family::v4;
193 }
194
195 native_handle_type release_socket() noexcept override;
196
197 std::error_code set_option(
198 int level,
199 int optname,
200 void const* data,
201 std::size_t size) noexcept override;
202 std::error_code
203 get_option(int level, int optname, void* data, std::size_t* size)
204 const noexcept override;
205
206 corosio::local_endpoint local_endpoint() const noexcept override;
207 corosio::local_endpoint remote_endpoint() const noexcept override;
208 void cancel() noexcept override;
209
210 /// Used by the acceptor's `local_stream_accept_op` to finish
211 /// setting up the peer.
212 void set_socket(SOCKET s) noexcept;
213 void set_endpoints(
214 corosio::local_endpoint local, corosio::local_endpoint remote) noexcept;
215
216 void close_socket() noexcept;
217 };
218
219 } // namespace boost::corosio::detail
220
221 #endif // BOOST_COROSIO_HAS_IOCP
222
223 #endif // BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_LOCAL_STREAM_SOCKET_HPP
224