src/corosio/src/tcp_acceptor.cpp

93.1% Lines (67 / 72) 100.0% Branches (24 / 24) 93.3% Functions (14 / 15)
tcp_acceptor.cpp
f(x) Functions (15)
Line Branch TLA Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco ([email protected])
3 // Copyright (c) 2026 Steve Gerbino
4 // Copyright (c) 2026 Michael Vandeberg
5 //
6 // Distributed under the Boost Software License, Version 1.0. (See accompanying
7 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // Official repository: https://github.com/cppalliance/corosio
10 //
11
12 #include <boost/corosio/tcp_acceptor.hpp>
13 #include <boost/corosio/error.hpp>
14 #include <boost/corosio/native/detail/endpoint_convert.hpp>
15 #include <boost/corosio/detail/platform.hpp>
16
17 #if BOOST_COROSIO_HAS_IOCP
18 #include <boost/corosio/native/detail/iocp/win_tcp_acceptor_service.hpp>
19 #else
20 #include <boost/corosio/detail/tcp_acceptor_service.hpp>
21 #include <boost/corosio/detail/tcp_service.hpp>
22 #endif
23
24 #include <boost/corosio/detail/except.hpp>
25
26 #include "src/detail/open_listener.hpp"
27 #include "src/detail/use_backend_service.hpp"
28
29 namespace boost::corosio {
30
31 namespace {
32
33 #if BOOST_COROSIO_HAS_IOCP
34 using tcp_peer_service = detail::win_tcp_service;
35 #else
36 using tcp_peer_service = detail::tcp_service;
37 #endif
38
39 void
40 13x open_listener_or_throw(tcp_acceptor& acc, endpoint ep, int backlog)
41 {
42
2/2
✓ Branch 4 → 5 taken 4 times.
✓ Branch 4 → 6 taken 9 times.
13x if (auto ec = detail::open_listener(acc, ep, backlog))
43 4x detail::throw_system_error(ec, "tcp_acceptor");
44 9x }
45
46 } // namespace
47
48 2806x tcp_acceptor::~tcp_acceptor()
49 {
50 2806x close();
51 2806x }
52
53 2719x tcp_acceptor::tcp_acceptor(capy::execution_context& ctx)
54 2719x : io_object(handle(
55 ctx,
56 detail::use_backend_service<
57 detail::tcp_acceptor_service_of,
58 #if BOOST_COROSIO_HAS_IOCP
59 detail::win_tcp_acceptor_service
60 #else
61 detail::tcp_acceptor_service
62 #endif
63
2/2
✓ Branch 2 → 3 taken 2719 times.
✓ Branch 3 → 4 taken 2719 times.
2719x >(ctx)))
64 {
65 2719x }
66
67 9x tcp_acceptor::tcp_acceptor(
68 9x capy::execution_context& ctx, endpoint ep, int backlog)
69 9x : tcp_acceptor(ctx)
70 {
71
1/1
✓ Branch 3 → 4 taken 6 times.
9x open_listener_or_throw(*this, ep, backlog);
72 9x }
73
74 4x tcp_acceptor::tcp_acceptor(handle h, endpoint ep, int backlog)
75 4x : tcp_acceptor(std::move(h))
76 {
77
1/1
✓ Branch 6 → 7 taken 3 times.
4x open_listener_or_throw(*this, ep, backlog);
78 4x }
79
80 std::error_code
81 2706x tcp_acceptor::open(family f) noexcept
82 {
83
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 2705 times.
2706x if (is_open())
84 1x return {};
85
86 #if BOOST_COROSIO_HAS_IOCP
87 2705x auto& svc = static_cast<detail::win_tcp_acceptor_service&>(h_.service());
88 #else
89 auto& svc = static_cast<detail::tcp_acceptor_service&>(h_.service());
90 #endif
91 5410x std::error_code ec = svc.open_acceptor_socket(
92 2705x *static_cast<tcp_acceptor::implementation*>(h_.get()),
93 detail::native_family(f), SOCK_STREAM, IPPROTO_TCP);
94 2705x return ec;
95 }
96
97 std::error_code
98 28x tcp_acceptor::assign(native_handle_type fd) noexcept
99 {
100
2/2
✓ Branch 3 → 4 taken 3 times.
✓ Branch 3 → 5 taken 25 times.
28x if (is_open())
101 3x return make_error_code(error::already_open);
102 #if BOOST_COROSIO_HAS_IOCP
103 25x auto& svc = static_cast<detail::win_tcp_acceptor_service&>(h_.service());
104 #else
105 auto& svc = static_cast<detail::tcp_acceptor_service&>(h_.service());
106 #endif
107 25x std::error_code ec = svc.assign_socket(
108 25x *static_cast<tcp_acceptor::implementation*>(h_.get()), fd);
109 25x return ec;
110 }
111
112 capy::results<native_handle_type>
113 6x tcp_acceptor::release() noexcept
114 {
115
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 7 taken 5 times.
6x if (!is_open())
116 return {
117 2x make_error_code(std::errc::bad_file_descriptor),
118 1x detail::invalid_native_handle};
119 5x return {std::error_code{}, get().release_socket()};
120 }
121
122 native_handle_type
123 16x tcp_acceptor::native_handle() const noexcept
124 {
125
2/2
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 5 taken 14 times.
16x if (!is_open())
126 {
127 #if BOOST_COROSIO_HAS_IOCP
128 2x return static_cast<native_handle_type>(~0ull); // INVALID_SOCKET
129 #else
130 return -1;
131 #endif
132 }
133 14x return get().native_handle();
134 }
135
136 std::error_code
137 2688x tcp_acceptor::bind(endpoint ep) noexcept
138 {
139
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 2687 times.
2688x if (!is_open())
140 1x return make_error_code(std::errc::bad_file_descriptor);
141 #if BOOST_COROSIO_HAS_IOCP
142 2687x auto& svc = static_cast<detail::win_tcp_acceptor_service&>(h_.service());
143 #else
144 auto& svc = static_cast<detail::tcp_acceptor_service&>(h_.service());
145 #endif
146 2687x return svc.bind_acceptor(
147 5374x *static_cast<tcp_acceptor::implementation*>(h_.get()), ep);
148 }
149
150 std::error_code
151 2666x tcp_acceptor::listen(int backlog) noexcept
152 {
153
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 2665 times.
2666x if (!is_open())
154 1x return make_error_code(std::errc::bad_file_descriptor);
155 #if BOOST_COROSIO_HAS_IOCP
156 2665x auto& svc = static_cast<detail::win_tcp_acceptor_service&>(h_.service());
157 #else
158 auto& svc = static_cast<detail::tcp_acceptor_service&>(h_.service());
159 #endif
160 2665x return svc.listen_acceptor(
161 5330x *static_cast<tcp_acceptor::implementation*>(h_.get()), backlog);
162 }
163
164 void
165 5019x tcp_acceptor::close() noexcept
166 {
167
2/2
✓ Branch 3 → 4 taken 2732 times.
✓ Branch 3 → 5 taken 2287 times.
5019x if (!is_open())
168 2732x return;
169 2287x h_.service().close(h_);
170 }
171
172 void
173 7x tcp_acceptor::cancel() noexcept
174 {
175
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 6 times.
7x if (!is_open())
176 1x return;
177 6x get().cancel();
178 }
179
180 endpoint
181 2251x tcp_acceptor::local_endpoint() const noexcept
182 {
183
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 2250 times.
2251x if (!is_open())
184 1x return endpoint{};
185 2250x return get().local_endpoint();
186 }
187
188 void
189 ✗ tcp_acceptor::discard_peer(
190 tcp_acceptor& acc, io_object::implementation* impl) noexcept
191 {
192 // Its own handle closes and releases the peer, as the socket the
193 // awaiter would have received does.
194 ✗ auto& ctx = acc.context();
195 handle h(
196 ctx,
197 ✗ detail::use_backend_service<detail::tcp_service_of, tcp_peer_service>(
198 ctx),
199 ✗ impl);
200 ✗ }
201
202 } // namespace boost::corosio
203