src/corosio/src/tcp_acceptor.cpp

100.0% Lines (73/73) 100.0% List of functions (16/16) 100.0% Branches (27/27)
tcp_acceptor.cpp
f(x) Functions (16)
Function Calls Lines Branches Blocks
boost::corosio::(anonymous namespace)::exclusive_address_use::level(boost::corosio::family) :41 26x 100.0% – 100.0% boost::corosio::(anonymous namespace)::exclusive_address_use::name(boost::corosio::family) :45 26x 100.0% – 100.0% boost::corosio::(anonymous namespace)::exclusive_address_use::data(boost::corosio::family) const :49 26x 100.0% – 100.0% boost::corosio::(anonymous namespace)::exclusive_address_use::size(boost::corosio::family) const :53 26x 100.0% – 100.0% boost::corosio::tcp_acceptor::~tcp_acceptor() :62 1856x 0.0% – 100.0% boost::corosio::tcp_acceptor::tcp_acceptor(boost::capy::execution_context&) :67 1838x 100.0% 100.0% 100.0% boost::corosio::tcp_acceptor::tcp_acceptor(boost::capy::execution_context&, boost::corosio::endpoint, int) :81 27x 100.0% 100.0% 95.7% boost::corosio::tcp_acceptor::open(boost::corosio::family) :99 1823x 100.0% 100.0% 100.0% boost::corosio::tcp_acceptor::assign(unsigned long long) :116 27x 100.0% 100.0% 100.0% boost::corosio::tcp_acceptor::release() :131 5x 100.0% 100.0% 100.0% boost::corosio::tcp_acceptor::native_handle() const :141 16x 100.0% 100.0% 100.0% boost::corosio::tcp_acceptor::bind(boost::corosio::endpoint) :155 1805x 100.0% 100.0% 100.0% boost::corosio::tcp_acceptor::listen(int) :169 1786x 100.0% 100.0% 100.0% boost::corosio::tcp_acceptor::close() :183 3589x 100.0% 100.0% 100.0% boost::corosio::tcp_acceptor::cancel() :191 6x 100.0% 100.0% 100.0% boost::corosio::tcp_acceptor::local_endpoint() const :199 1776x 100.0% 100.0% 100.0%
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/socket_option.hpp>
16 #include <boost/corosio/detail/platform.hpp>
17
18 #if BOOST_COROSIO_HAS_IOCP
19 #include <boost/corosio/native/detail/iocp/win_tcp_acceptor_service.hpp>
20 #else
21 #include <boost/corosio/detail/tcp_acceptor_service.hpp>
22 #endif
23
24 #include <boost/corosio/detail/except.hpp>
25
26 #include "src/detail/use_backend_service.hpp"
27
28 namespace boost::corosio {
29
30 #if BOOST_COROSIO_HAS_IOCP
31 namespace {
32
33 // On Windows SO_REUSEADDR grants bind-over ("hijack") rights instead
34 // of TIME_WAIT reuse, so a second listener would share the port
35 // silently. SO_EXCLUSIVEADDRUSE restores the POSIX contract: the
36 // collision surfaces as WSAEADDRINUSE (errc::address_in_use).
37 struct exclusive_address_use
38 {
39 int value_ = 1;
40
41 26x static int level(family) noexcept
42 {
43 26x return SOL_SOCKET;
44 }
45 26x static int name(family) noexcept
46 {
47 26x return SO_EXCLUSIVEADDRUSE;
48 }
49 26x void const* data(family) const noexcept
50 {
51 26x return &value_;
52 }
53 26x std::size_t size(family) const noexcept
54 {
55 26x return sizeof(value_);
56 }
57 };
58
59 } // namespace
60 #endif
61
62 1856x tcp_acceptor::~tcp_acceptor()
63 {
64 1856x close();
65 1856x }
66
67 1838x tcp_acceptor::tcp_acceptor(capy::execution_context& ctx)
68 1838x : io_object(handle(
69 ctx,
70 detail::use_backend_service<
71 detail::tcp_acceptor_service_of,
72 #if BOOST_COROSIO_HAS_IOCP
73 detail::win_tcp_acceptor_service
74 #else
75 detail::tcp_acceptor_service
76 #endif
77
2/2
✓ Branch 2 → 3 taken 1838 times.
✓ Branch 3 → 4 taken 1838 times.
1838x >(ctx)))
78 {
79 1838x }
80
81 27x tcp_acceptor::tcp_acceptor(
82 27x capy::execution_context& ctx, endpoint ep, int backlog)
83 27x : tcp_acceptor(ctx)
84 {
85
2/2
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 9 taken 26 times.
27x if (auto ec = open(ep.address().family()))
86 1x detail::throw_system_error(ec, "tcp_acceptor");
87 #if BOOST_COROSIO_HAS_IOCP
88
1/1
✓ Branch 9 → 10 taken 26 times.
26x set_option(exclusive_address_use{});
89 #else
90 set_option(socket_option::reuse_address(true));
91 #endif
92
2/2
✓ Branch 12 → 13 taken 2 times.
✓ Branch 12 → 14 taken 24 times.
26x if (auto ec = bind(ep))
93 2x detail::throw_system_error(ec, "tcp_acceptor");
94
2/2
✓ Branch 16 → 17 taken 1 time.
✓ Branch 16 → 18 taken 23 times.
24x if (auto ec = listen(backlog))
95 1x detail::throw_system_error(ec, "tcp_acceptor");
96 27x }
97
98 std::error_code
99 1823x tcp_acceptor::open(family f) noexcept
100 {
101
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 1822 times.
1823x if (is_open())
102 1x return {};
103
104 #if BOOST_COROSIO_HAS_IOCP
105 1822x auto& svc = static_cast<detail::win_tcp_acceptor_service&>(h_.service());
106 #else
107 auto& svc = static_cast<detail::tcp_acceptor_service&>(h_.service());
108 #endif
109 3644x std::error_code ec = svc.open_acceptor_socket(
110 1822x *static_cast<tcp_acceptor::implementation*>(h_.get()),
111 detail::native_family(f), SOCK_STREAM, IPPROTO_TCP);
112 1822x return ec;
113 }
114
115 std::error_code
116 27x tcp_acceptor::assign(native_handle_type fd) noexcept
117 {
118
2/2
✓ Branch 3 → 4 taken 3 times.
✓ Branch 3 → 5 taken 24 times.
27x if (is_open())
119 3x return make_error_code(error::already_open);
120 #if BOOST_COROSIO_HAS_IOCP
121 24x auto& svc = static_cast<detail::win_tcp_acceptor_service&>(h_.service());
122 #else
123 auto& svc = static_cast<detail::tcp_acceptor_service&>(h_.service());
124 #endif
125 24x std::error_code ec = svc.assign_socket(
126 24x *static_cast<tcp_acceptor::implementation*>(h_.get()), fd);
127 24x return ec;
128 }
129
130 native_handle_type
131 5x tcp_acceptor::release()
132 {
133
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 6 taken 4 times.
5x if (!is_open())
134 1x detail::throw_system_error(
135 1x make_error_code(std::errc::bad_file_descriptor),
136 "tcp_acceptor::release");
137 4x return get().release_socket();
138 }
139
140 native_handle_type
141 16x tcp_acceptor::native_handle() const noexcept
142 {
143
2/2
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 5 taken 14 times.
16x if (!is_open())
144 {
145 #if BOOST_COROSIO_HAS_IOCP
146 2x return static_cast<native_handle_type>(~0ull); // INVALID_SOCKET
147 #else
148 return -1;
149 #endif
150 }
151 14x return get().native_handle();
152 }
153
154 std::error_code
155 1805x tcp_acceptor::bind(endpoint ep) noexcept
156 {
157
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 1804 times.
1805x if (!is_open())
158 1x return make_error_code(std::errc::bad_file_descriptor);
159 #if BOOST_COROSIO_HAS_IOCP
160 1804x auto& svc = static_cast<detail::win_tcp_acceptor_service&>(h_.service());
161 #else
162 auto& svc = static_cast<detail::tcp_acceptor_service&>(h_.service());
163 #endif
164 1804x return svc.bind_acceptor(
165 3608x *static_cast<tcp_acceptor::implementation*>(h_.get()), ep);
166 }
167
168 std::error_code
169 1786x tcp_acceptor::listen(int backlog) noexcept
170 {
171
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 1785 times.
1786x if (!is_open())
172 1x return make_error_code(std::errc::bad_file_descriptor);
173 #if BOOST_COROSIO_HAS_IOCP
174 1785x auto& svc = static_cast<detail::win_tcp_acceptor_service&>(h_.service());
175 #else
176 auto& svc = static_cast<detail::tcp_acceptor_service&>(h_.service());
177 #endif
178 1785x return svc.listen_acceptor(
179 3570x *static_cast<tcp_acceptor::implementation*>(h_.get()), backlog);
180 }
181
182 void
183 3589x tcp_acceptor::close() noexcept
184 {
185
2/2
✓ Branch 3 → 4 taken 1781 times.
✓ Branch 3 → 5 taken 1808 times.
3589x if (!is_open())
186 1781x return;
187 1808x h_.service().close(h_);
188 }
189
190 void
191 6x tcp_acceptor::cancel() noexcept
192 {
193
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 5 times.
6x if (!is_open())
194 1x return;
195 5x get().cancel();
196 }
197
198 endpoint
199 1776x tcp_acceptor::local_endpoint() const noexcept
200 {
201
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 1775 times.
1776x if (!is_open())
202 1x return endpoint{};
203 1775x return get().local_endpoint();
204 }
205
206 } // namespace boost::corosio
207