src/corosio/src/local_stream_acceptor.cpp

100.0% Lines (102 / 102) 71.7% Branches (43 / 60) 100.0% Functions (15 / 15)
local_stream_acceptor.cpp
f(x) Functions (15)
Function Calls Lines Branches Blocks
boost::corosio::(anonymous namespace)::open_listener_or_throw(boost::corosio::local_stream_acceptor&, boost::corosio::local_endpoint, int) :42 18x 100.0% 100.0% 100.0% boost::corosio::local_stream_acceptor::~local_stream_acceptor() :55 348x 100.0% – 100.0% boost::corosio::local_stream_acceptor::local_stream_acceptor(boost::capy::execution_context&) :60 320x 100.0% – 100.0% boost::corosio::local_stream_acceptor::local_stream_acceptor(boost::capy::execution_context&, boost::corosio::local_endpoint, int) :70 14x 100.0% 50.0% 100.0% boost::corosio::local_stream_acceptor::local_stream_acceptor(boost::corosio::io_object::handle, boost::capy::execution_context&, boost::corosio::local_endpoint, int) :77 4x 100.0% 50.0% 100.0% boost::corosio::local_stream_acceptor::open() :88 100x 100.0% 66.7% 83.0% boost::corosio::local_stream_acceptor::assign(int) :101 12x 100.0% 66.7% 83.0% boost::corosio::local_stream_acceptor::native_handle() const :113 20x 100.0% 100.0% 100.0% boost::corosio::local_stream_acceptor::bind(boost::corosio::local_endpoint, boost::corosio::bind_option) :127 88x 100.0% 64.3% 90.0% boost::corosio::local_stream_acceptor::listen(int) :154 71x 100.0% 66.7% 83.0% boost::corosio::local_stream_acceptor::close() :166 203x 100.0% 75.0% 80.0% boost::corosio::local_stream_acceptor::release() :174 10x 100.0% 100.0% 100.0% boost::corosio::local_stream_acceptor::cancel() :184 8x 100.0% 100.0% 100.0% boost::corosio::local_stream_acceptor::local_endpoint() const :192 14x 100.0% 100.0% 100.0% boost::corosio::local_stream_acceptor::discard_peer(boost::corosio::local_stream_acceptor&, boost::corosio::io_object::implementation*) :200 8x 100.0% 50.0% 66.0%
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 #include <boost/corosio/local_stream_acceptor.hpp>
11 #include <boost/corosio/error.hpp>
12 #include <boost/corosio/detail/except.hpp>
13 #include <boost/corosio/detail/platform.hpp>
14 #include <boost/corosio/detail/local_stream_acceptor_service.hpp>
15
16 #include "src/detail/use_backend_service.hpp"
17
18 #include <cstring>
19
20 #if BOOST_COROSIO_POSIX
21 #include <sys/socket.h>
22 #include <unistd.h>
23 #else
24 // Windows: AF_UNIX socket files are reparse points with tag
25 // IO_REPARSE_TAG_AF_UNIX. DeleteFileA reliably removes them;
26 // std::filesystem::remove via libstdc++/MS STL was observed to
27 // silently leave them in place on at least some Windows hosts,
28 // so call the Win32 API directly.
29 #define WIN32_LEAN_AND_MEAN
30 #include <winsock2.h>
31 #include <windows.h>
32 #ifndef AF_UNIX
33 #define AF_UNIX 1
34 #endif
35 #endif
36
37 namespace boost::corosio {
38
39 namespace {
40
41 void
42 18x open_listener_or_throw(
43 local_stream_acceptor& acc, corosio::local_endpoint ep, int backlog)
44 {
45
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18x if (auto ec = acc.open())
46 2x detail::throw_system_error(ec, "local_stream_acceptor");
47
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
16x if (auto ec = acc.bind(ep))
48 4x detail::throw_system_error(ec, "local_stream_acceptor");
49
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12x if (auto ec = acc.listen(backlog))
50 2x detail::throw_system_error(ec, "local_stream_acceptor");
51 10x }
52
53 } // namespace
54
55 348x local_stream_acceptor::~local_stream_acceptor()
56 348x {
57 188x close();
58 348x }
59
60 320x local_stream_acceptor::local_stream_acceptor(capy::execution_context& ctx)
61 160x : io_object(handle(
62 160x ctx,
63 160x detail::use_backend_service<
64 detail::local_stream_acceptor_service_of,
65 160x detail::local_stream_acceptor_service>(ctx)))
66 160x , ctx_(ctx)
67 320x {
68 320x }
69
70 14x local_stream_acceptor::local_stream_acceptor(
71 capy::execution_context& ctx, corosio::local_endpoint ep, int backlog)
72 14x : local_stream_acceptor(ctx)
73 {
74
2/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 6 times.
14x open_listener_or_throw(*this, ep, backlog);
75 14x }
76
77 4x local_stream_acceptor::local_stream_acceptor(
78 handle h,
79 capy::execution_context& ctx,
80 corosio::local_endpoint ep,
81 int backlog)
82 4x : local_stream_acceptor(std::move(h), ctx)
83 {
84
2/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4x open_listener_or_throw(*this, ep, backlog);
85 4x }
86
87 std::error_code
88 100x local_stream_acceptor::open() noexcept
89 {
90
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 98 times.
100x if (is_open())
91 2x return {};
92 98x auto& svc =
93 98x static_cast<detail::local_stream_acceptor_service&>(h_.service());
94
2/4
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 98 times.
✗ Branch 3 not taken.
196x auto ec = svc.open_acceptor_socket(
95 98x static_cast<local_stream_acceptor::implementation&>(*h_.get()), AF_UNIX,
96 SOCK_STREAM, 0);
97 98x return ec;
98 100x }
99
100 std::error_code
101 12x local_stream_acceptor::assign(native_handle_type fd) noexcept
102 {
103
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12x if (is_open())
104 6x return make_error_code(error::already_open);
105 6x auto& svc =
106 6x static_cast<detail::local_stream_acceptor_service&>(h_.service());
107
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
12x auto ec = svc.assign_socket(
108 6x static_cast<local_stream_acceptor::implementation&>(*h_.get()), fd);
109 6x return ec;
110 12x }
111
112 native_handle_type
113 20x local_stream_acceptor::native_handle() const noexcept
114 {
115
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 16 times.
20x if (!is_open())
116 {
117 #if BOOST_COROSIO_HAS_IOCP
118 return static_cast<native_handle_type>(~0ull); // INVALID_SOCKET
119 #else
120 4x return -1;
121 #endif
122 }
123 16x return get().native_handle();
124 20x }
125
126 std::error_code
127 88x local_stream_acceptor::bind(
128 corosio::local_endpoint ep, bind_option opt) noexcept
129 {
130
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 86 times.
88x if (!is_open())
131 2x return make_error_code(std::errc::bad_file_descriptor);
132
133
4/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 82 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
86x if (opt == bind_option::unlink_existing && !ep.empty() && !ep.is_abstract())
134 {
135 // Best-effort removal; missing file is fine.
136 4x auto p = ep.path();
137 char buf[local_endpoint::max_path_length + 1];
138 4x std::memcpy(buf, p.data(), p.size());
139 4x buf[p.size()] = '\0';
140 #if BOOST_COROSIO_POSIX
141
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4x ::unlink(buf);
142 #else
143 ::DeleteFileA(buf);
144 #endif
145 4x }
146
147 86x auto& svc =
148 86x static_cast<detail::local_stream_acceptor_service&>(h_.service());
149
2/4
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 86 times.
✗ Branch 3 not taken.
172x return svc.bind_acceptor(
150 86x static_cast<local_stream_acceptor::implementation&>(*h_.get()), ep);
151 88x }
152
153 std::error_code
154 71x local_stream_acceptor::listen(int backlog) noexcept
155 {
156
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 69 times.
71x if (!is_open())
157 2x return make_error_code(std::errc::bad_file_descriptor);
158 69x auto& svc =
159 69x static_cast<detail::local_stream_acceptor_service&>(h_.service());
160
2/4
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
138x return svc.listen_acceptor(
161 69x static_cast<local_stream_acceptor::implementation&>(*h_.get()),
162 69x backlog);
163 71x }
164
165 void
166 203x local_stream_acceptor::close() noexcept
167 {
168
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 111 times.
203x if (!is_open())
169 111x return;
170
1/2
✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
92x h_.service().close(h_);
171 203x }
172
173 capy::results<native_handle_type>
174 10x local_stream_acceptor::release() noexcept
175 {
176
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10x if (!is_open())
177 2x return {
178 2x make_error_code(std::errc::bad_file_descriptor),
179 detail::invalid_native_handle};
180 8x return {std::error_code{}, get().release_socket()};
181 10x }
182
183 void
184 8x local_stream_acceptor::cancel() noexcept
185 {
186
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8x if (!is_open())
187 2x return;
188 6x get().cancel();
189 8x }
190
191 local_endpoint
192 14x local_stream_acceptor::local_endpoint() const noexcept
193 {
194
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14x if (!is_open())
195 2x return corosio::local_endpoint{};
196 12x return get().local_endpoint();
197 14x }
198
199 void
200 8x local_stream_acceptor::discard_peer(
201 local_stream_acceptor& acc, io_object::implementation* impl) noexcept
202 {
203 // Its own handle closes and releases the peer, as the socket the
204 // awaiter would have received does.
205 8x handle h(
206 8x acc.ctx_,
207
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8x detail::use_backend_service<
208 detail::local_stream_service_of,
209 8x detail::local_stream_service>(acc.ctx_),
210 8x impl);
211 8x }
212
213 } // namespace boost::corosio
214