src/corosio/src/local_stream_acceptor.cpp

95.2% Lines (79 / 83) 94.4% Branches (34 / 36) 93.3% Functions (14 / 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 6x 100.0% 100.0% 100.0% boost::corosio::local_stream_acceptor::~local_stream_acceptor() :55 98x 0.0% – 100.0% boost::corosio::local_stream_acceptor::local_stream_acceptor(boost::capy::execution_context&) :60 87x 100.0% 100.0% 100.0% boost::corosio::local_stream_acceptor::local_stream_acceptor(boost::capy::execution_context&, boost::corosio::local_endpoint, int) :70 4x 100.0% 100.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 2x 100.0% 100.0% 100.0% boost::corosio::local_stream_acceptor::open() :88 67x 100.0% 100.0% 100.0% boost::corosio::local_stream_acceptor::assign(unsigned long long) :101 26x 100.0% 100.0% 100.0% boost::corosio::local_stream_acceptor::native_handle() const :113 12x 100.0% 100.0% 100.0% boost::corosio::local_stream_acceptor::bind(boost::corosio::local_endpoint, boost::corosio::bind_option) :127 50x 100.0% 80.0% 100.0% boost::corosio::local_stream_acceptor::listen(int) :154 40x 100.0% 100.0% 100.0% boost::corosio::local_stream_acceptor::close() :166 107x 100.0% 100.0% 100.0% boost::corosio::local_stream_acceptor::release() :174 7x 100.0% 100.0% 100.0% boost::corosio::local_stream_acceptor::cancel() :184 4x 100.0% 100.0% 100.0% boost::corosio::local_stream_acceptor::local_endpoint() const :192 7x 100.0% 100.0% 100.0% boost::corosio::local_stream_acceptor::discard_peer(boost::corosio::local_stream_acceptor&, boost::corosio::io_object::implementation*) :200 0 0.0% – 0.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 6x open_listener_or_throw(
43 local_stream_acceptor& acc, corosio::local_endpoint ep, int backlog)
44 {
45
2/2
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 5 times.
6x if (auto ec = acc.open())
46 1x detail::throw_system_error(ec, "local_stream_acceptor");
47
2/2
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 10 taken 3 times.
5x if (auto ec = acc.bind(ep))
48 2x detail::throw_system_error(ec, "local_stream_acceptor");
49
2/2
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 14 taken 2 times.
3x if (auto ec = acc.listen(backlog))
50 1x detail::throw_system_error(ec, "local_stream_acceptor");
51 2x }
52
53 } // namespace
54
55 98x local_stream_acceptor::~local_stream_acceptor()
56 {
57 98x close();
58 98x }
59
60 87x local_stream_acceptor::local_stream_acceptor(capy::execution_context& ctx)
61 87x : io_object(handle(
62 ctx,
63 detail::use_backend_service<
64 detail::local_stream_acceptor_service_of,
65
1/1
✓ Branch 3 → 4 taken 87 times.
87x detail::local_stream_acceptor_service>(ctx)))
66
1/1
✓ Branch 2 → 3 taken 87 times.
174x , ctx_(ctx)
67 {
68 87x }
69
70 4x local_stream_acceptor::local_stream_acceptor(
71 4x capy::execution_context& ctx, corosio::local_endpoint ep, int backlog)
72 4x : local_stream_acceptor(ctx)
73 {
74
1/1
✓ Branch 3 → 4 taken 1 time.
4x open_listener_or_throw(*this, ep, backlog);
75 4x }
76
77 2x local_stream_acceptor::local_stream_acceptor(
78 handle h,
79 capy::execution_context& ctx,
80 corosio::local_endpoint ep,
81 2x int backlog)
82 2x : local_stream_acceptor(std::move(h), ctx)
83 {
84
1/1
✓ Branch 6 → 7 taken 1 time.
2x open_listener_or_throw(*this, ep, backlog);
85 2x }
86
87 std::error_code
88 67x local_stream_acceptor::open() noexcept
89 {
90
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 66 times.
67x if (is_open())
91 1x return {};
92 auto& svc =
93 66x static_cast<detail::local_stream_acceptor_service&>(h_.service());
94 66x auto ec = svc.open_acceptor_socket(
95 66x static_cast<local_stream_acceptor::implementation&>(*h_.get()), AF_UNIX,
96 SOCK_STREAM, 0);
97 66x return ec;
98 }
99
100 std::error_code
101 26x local_stream_acceptor::assign(native_handle_type fd) noexcept
102 {
103
2/2
✓ Branch 3 → 4 taken 4 times.
✓ Branch 3 → 5 taken 22 times.
26x if (is_open())
104 4x return make_error_code(error::already_open);
105 auto& svc =
106 22x static_cast<detail::local_stream_acceptor_service&>(h_.service());
107 22x auto ec = svc.assign_socket(
108 22x static_cast<local_stream_acceptor::implementation&>(*h_.get()), fd);
109 22x return ec;
110 }
111
112 native_handle_type
113 12x local_stream_acceptor::native_handle() const noexcept
114 {
115
2/2
✓ Branch 3 → 4 taken 3 times.
✓ Branch 3 → 5 taken 9 times.
12x if (!is_open())
116 {
117 #if BOOST_COROSIO_HAS_IOCP
118 3x return static_cast<native_handle_type>(~0ull); // INVALID_SOCKET
119 #else
120 return -1;
121 #endif
122 }
123 9x return get().native_handle();
124 }
125
126 std::error_code
127 50x local_stream_acceptor::bind(
128 corosio::local_endpoint ep, bind_option opt) noexcept
129 {
130
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 49 times.
50x if (!is_open())
131 1x return make_error_code(std::errc::bad_file_descriptor);
132
133
6/8
✓ Branch 5 → 6 taken 7 times.
✓ Branch 5 → 11 taken 42 times.
✓ Branch 7 → 8 taken 7 times.
✗ Branch 7 → 11 not taken.
✓ Branch 9 → 10 taken 7 times.
✗ Branch 9 → 11 not taken.
✓ Branch 12 → 13 taken 7 times.
✓ Branch 12 → 19 taken 42 times.
49x if (opt == bind_option::unlink_existing && !ep.empty() && !ep.is_abstract())
134 {
135 // Best-effort removal; missing file is fine.
136 7x auto p = ep.path();
137 char buf[local_endpoint::max_path_length + 1];
138 7x std::memcpy(buf, p.data(), p.size());
139 7x buf[p.size()] = '\0';
140 #if BOOST_COROSIO_POSIX
141 ::unlink(buf);
142 #else
143 7x ::DeleteFileA(buf);
144 #endif
145 }
146
147 auto& svc =
148 49x static_cast<detail::local_stream_acceptor_service&>(h_.service());
149 49x return svc.bind_acceptor(
150 98x static_cast<local_stream_acceptor::implementation&>(*h_.get()), ep);
151 }
152
153 std::error_code
154 40x local_stream_acceptor::listen(int backlog) noexcept
155 {
156
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 39 times.
40x if (!is_open())
157 1x return make_error_code(std::errc::bad_file_descriptor);
158 auto& svc =
159 39x static_cast<detail::local_stream_acceptor_service&>(h_.service());
160 39x return svc.listen_acceptor(
161 39x static_cast<local_stream_acceptor::implementation&>(*h_.get()),
162 39x backlog);
163 }
164
165 void
166 107x local_stream_acceptor::close() noexcept
167 {
168
2/2
✓ Branch 3 → 4 taken 56 times.
✓ Branch 3 → 5 taken 51 times.
107x if (!is_open())
169 56x return;
170 51x h_.service().close(h_);
171 }
172
173 capy::results<native_handle_type>
174 7x local_stream_acceptor::release() noexcept
175 {
176
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 7 taken 6 times.
7x if (!is_open())
177 return {
178 2x make_error_code(std::errc::bad_file_descriptor),
179 1x detail::invalid_native_handle};
180 6x return {std::error_code{}, get().release_socket()};
181 }
182
183 void
184 4x local_stream_acceptor::cancel() noexcept
185 {
186
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 3 times.
4x if (!is_open())
187 1x return;
188 3x get().cancel();
189 }
190
191 local_endpoint
192 7x local_stream_acceptor::local_endpoint() const noexcept
193 {
194
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 6 times.
7x if (!is_open())
195 1x return corosio::local_endpoint{};
196 6x return get().local_endpoint();
197 }
198
199 void
200 ✗ 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 handle h(
206 acc.ctx_,
207 detail::use_backend_service<
208 detail::local_stream_service_of,
209 ✗ detail::local_stream_service>(acc.ctx_),
210 ✗ impl);
211 ✗ }
212
213 } // namespace boost::corosio
214