src/corosio/src/tcp_acceptor.cpp

100.0% Lines (88 / 88) 70.8% Branches (34 / 48) 100.0% Functions (15 / 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 33x open_listener_or_throw(tcp_acceptor& acc, endpoint ep, int backlog)
41 {
42
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 8 times.
33x if (auto ec = detail::open_listener(acc, ep, backlog))
43 8x detail::throw_system_error(ec, "tcp_acceptor");
44 25x }
45
46 } // namespace
47
48 7669x tcp_acceptor::~tcp_acceptor()
49 7669x {
50 3862x close();
51 7669x }
52
53 7306x tcp_acceptor::tcp_acceptor(capy::execution_context& ctx)
54 3653x : io_object(handle(
55 3653x ctx,
56 3653x 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 3653x >(ctx)))
64 7306x {
65 7306x }
66
67 25x tcp_acceptor::tcp_acceptor(
68 capy::execution_context& ctx, endpoint ep, int backlog)
69 25x : tcp_acceptor(ctx)
70 {
71
2/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 6 times.
25x open_listener_or_throw(*this, ep, backlog);
72 25x }
73
74 8x tcp_acceptor::tcp_acceptor(handle h, endpoint ep, int backlog)
75 8x : tcp_acceptor(std::move(h))
76 {
77
2/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8x open_listener_or_throw(*this, ep, backlog);
78 8x }
79
80 std::error_code
81 3639x tcp_acceptor::open(family f) noexcept
82 {
83
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3637 times.
3639x if (is_open())
84 2x return {};
85
86 #if BOOST_COROSIO_HAS_IOCP
87 auto& svc = static_cast<detail::win_tcp_acceptor_service&>(h_.service());
88 #else
89 3637x auto& svc = static_cast<detail::tcp_acceptor_service&>(h_.service());
90 #endif
91
2/4
✓ Branch 0 taken 3637 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3637 times.
✗ Branch 3 not taken.
7274x std::error_code ec = svc.open_acceptor_socket(
92 3637x *static_cast<tcp_acceptor::implementation*>(h_.get()),
93 3637x detail::native_family(f), SOCK_STREAM, IPPROTO_TCP);
94 3637x return ec;
95 3639x }
96
97 std::error_code
98 23x tcp_acceptor::assign(native_handle_type fd) noexcept
99 {
100
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 17 times.
23x if (is_open())
101 6x return make_error_code(error::already_open);
102 #if BOOST_COROSIO_HAS_IOCP
103 auto& svc = static_cast<detail::win_tcp_acceptor_service&>(h_.service());
104 #else
105 17x auto& svc = static_cast<detail::tcp_acceptor_service&>(h_.service());
106 #endif
107
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
34x std::error_code ec = svc.assign_socket(
108 17x *static_cast<tcp_acceptor::implementation*>(h_.get()), fd);
109 17x return ec;
110 23x }
111
112 capy::results<native_handle_type>
113 14x tcp_acceptor::release() noexcept
114 {
115
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14x if (!is_open())
116 2x return {
117 2x make_error_code(std::errc::bad_file_descriptor),
118 detail::invalid_native_handle};
119 12x return {std::error_code{}, get().release_socket()};
120 14x }
121
122 native_handle_type
123 34x tcp_acceptor::native_handle() const noexcept
124 {
125
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 30 times.
34x if (!is_open())
126 {
127 #if BOOST_COROSIO_HAS_IOCP
128 return static_cast<native_handle_type>(~0ull); // INVALID_SOCKET
129 #else
130 4x return -1;
131 #endif
132 }
133 30x return get().native_handle();
134 34x }
135
136 std::error_code
137 3602x tcp_acceptor::bind(endpoint ep) noexcept
138 {
139
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3600 times.
3602x if (!is_open())
140 2x return make_error_code(std::errc::bad_file_descriptor);
141 #if BOOST_COROSIO_HAS_IOCP
142 auto& svc = static_cast<detail::win_tcp_acceptor_service&>(h_.service());
143 #else
144 3600x auto& svc = static_cast<detail::tcp_acceptor_service&>(h_.service());
145 #endif
146
2/4
✓ Branch 0 taken 3600 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3600 times.
✗ Branch 3 not taken.
7200x return svc.bind_acceptor(
147 3600x *static_cast<tcp_acceptor::implementation*>(h_.get()), ep);
148 3602x }
149
150 std::error_code
151 3569x tcp_acceptor::listen(int backlog) noexcept
152 {
153
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3567 times.
3569x if (!is_open())
154 2x return make_error_code(std::errc::bad_file_descriptor);
155 #if BOOST_COROSIO_HAS_IOCP
156 auto& svc = static_cast<detail::win_tcp_acceptor_service&>(h_.service());
157 #else
158 3567x auto& svc = static_cast<detail::tcp_acceptor_service&>(h_.service());
159 #endif
160
2/4
✓ Branch 0 taken 3567 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3567 times.
✗ Branch 3 not taken.
7134x return svc.listen_acceptor(
161 3567x *static_cast<tcp_acceptor::implementation*>(h_.get()), backlog);
162 3569x }
163
164 void
165 6477x tcp_acceptor::close() noexcept
166 {
167
2/2
✓ Branch 0 taken 2804 times.
✓ Branch 1 taken 3673 times.
6477x if (!is_open())
168 3673x return;
169
1/2
✓ Branch 0 taken 2804 times.
✗ Branch 1 not taken.
2804x h_.service().close(h_);
170 6477x }
171
172 void
173 23x tcp_acceptor::cancel() noexcept
174 {
175
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 21 times.
23x if (!is_open())
176 2x return;
177 21x get().cancel();
178 23x }
179
180 endpoint
181 2704x tcp_acceptor::local_endpoint() const noexcept
182 {
183
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2702 times.
2704x if (!is_open())
184 2x return endpoint{};
185 2702x return get().local_endpoint();
186 2704x }
187
188 void
189 8x 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 8x auto& ctx = acc.context();
195 8x handle h(
196 8x ctx,
197
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8x detail::use_backend_service<detail::tcp_service_of, tcp_peer_service>(
198 8x ctx),
199 8x impl);
200 8x }
201
202 } // namespace boost::corosio
203