src/corosio/src/local_stream_acceptor.cpp

100.0% Lines (83 / 83) 100.0% Functions (15 / 15)
local_stream_acceptor.cpp
f(x) Functions (15)
Function Calls Lines Blocks
boost::corosio::(anonymous namespace)::open_listener_or_throw(boost::corosio::local_stream_acceptor&, boost::corosio::local_endpoint, int) :42 24x 100.0% 100.0% boost::corosio::local_stream_acceptor::~local_stream_acceptor() :55 194x 100.0% 100.0% boost::corosio::local_stream_acceptor::local_stream_acceptor(boost::capy::execution_context&) :60 166x 100.0% 100.0% boost::corosio::local_stream_acceptor::local_stream_acceptor(boost::capy::execution_context&, boost::corosio::local_endpoint, int) :70 20x 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 4x 100.0% 100.0% boost::corosio::local_stream_acceptor::open() :88 106x 100.0% 100.0% boost::corosio::local_stream_acceptor::assign(int) :101 12x 100.0% 100.0% boost::corosio::local_stream_acceptor::native_handle() const :113 20x 100.0% 100.0% boost::corosio::local_stream_acceptor::bind(boost::corosio::local_endpoint, boost::corosio::bind_option) :127 91x 100.0% 100.0% boost::corosio::local_stream_acceptor::listen(int) :154 74x 100.0% 100.0% boost::corosio::local_stream_acceptor::close() :166 209x 100.0% 100.0% boost::corosio::local_stream_acceptor::release() :174 10x 100.0% 100.0% boost::corosio::local_stream_acceptor::cancel() :184 8x 100.0% 100.0% boost::corosio::local_stream_acceptor::local_endpoint() const :192 14x 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% 100.0%
Line 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 24x open_listener_or_throw(
43 local_stream_acceptor& acc, corosio::local_endpoint ep, int backlog)
44 {
45 24x if (auto ec = acc.open())
46 5x detail::throw_system_error(ec, "local_stream_acceptor");
47 19x if (auto ec = acc.bind(ep))
48 4x detail::throw_system_error(ec, "local_stream_acceptor");
49 15x if (auto ec = acc.listen(backlog))
50 5x detail::throw_system_error(ec, "local_stream_acceptor");
51 10x }
52
53 } // namespace
54
55 194x local_stream_acceptor::~local_stream_acceptor()
56 {
57 194x close();
58 194x }
59
60 166x local_stream_acceptor::local_stream_acceptor(capy::execution_context& ctx)
61 166x : io_object(handle(
62 ctx,
63 detail::use_backend_service<
64 detail::local_stream_acceptor_service_of,
65 166x detail::local_stream_acceptor_service>(ctx)))
66 332x , ctx_(ctx)
67 {
68 166x }
69
70 20x local_stream_acceptor::local_stream_acceptor(
71 20x capy::execution_context& ctx, corosio::local_endpoint ep, int backlog)
72 20x : local_stream_acceptor(ctx)
73 {
74 20x open_listener_or_throw(*this, ep, backlog);
75 20x }
76
77 4x local_stream_acceptor::local_stream_acceptor(
78 handle h,
79 capy::execution_context& ctx,
80 corosio::local_endpoint ep,
81 4x int backlog)
82 4x : local_stream_acceptor(std::move(h), ctx)
83 {
84 4x open_listener_or_throw(*this, ep, backlog);
85 4x }
86
87 std::error_code
88 106x local_stream_acceptor::open() noexcept
89 {
90 106x if (is_open())
91 2x return {};
92 auto& svc =
93 104x static_cast<detail::local_stream_acceptor_service&>(h_.service());
94 104x auto ec = svc.open_acceptor_socket(
95 104x static_cast<local_stream_acceptor::implementation&>(*h_.get()), AF_UNIX,
96 SOCK_STREAM, 0);
97 104x return ec;
98 }
99
100 std::error_code
101 12x local_stream_acceptor::assign(native_handle_type fd) noexcept
102 {
103 12x if (is_open())
104 6x return make_error_code(error::already_open);
105 auto& svc =
106 6x static_cast<detail::local_stream_acceptor_service&>(h_.service());
107 6x auto ec = svc.assign_socket(
108 6x static_cast<local_stream_acceptor::implementation&>(*h_.get()), fd);
109 6x return ec;
110 }
111
112 native_handle_type
113 20x local_stream_acceptor::native_handle() const noexcept
114 {
115 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 }
125
126 std::error_code
127 91x local_stream_acceptor::bind(
128 corosio::local_endpoint ep, bind_option opt) noexcept
129 {
130 91x if (!is_open())
131 2x return make_error_code(std::errc::bad_file_descriptor);
132
133 89x 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 4x ::unlink(buf);
142 #else
143 ::DeleteFileA(buf);
144 #endif
145 }
146
147 auto& svc =
148 89x static_cast<detail::local_stream_acceptor_service&>(h_.service());
149 89x return svc.bind_acceptor(
150 178x static_cast<local_stream_acceptor::implementation&>(*h_.get()), ep);
151 }
152
153 std::error_code
154 74x local_stream_acceptor::listen(int backlog) noexcept
155 {
156 74x if (!is_open())
157 2x return make_error_code(std::errc::bad_file_descriptor);
158 auto& svc =
159 72x static_cast<detail::local_stream_acceptor_service&>(h_.service());
160 72x return svc.listen_acceptor(
161 72x static_cast<local_stream_acceptor::implementation&>(*h_.get()),
162 72x backlog);
163 }
164
165 void
166 209x local_stream_acceptor::close() noexcept
167 {
168 209x if (!is_open())
169 114x return;
170 95x h_.service().close(h_);
171 }
172
173 capy::results<native_handle_type>
174 10x local_stream_acceptor::release() noexcept
175 {
176 10x if (!is_open())
177 return {
178 4x make_error_code(std::errc::bad_file_descriptor),
179 2x detail::invalid_native_handle};
180 8x return {std::error_code{}, get().release_socket()};
181 }
182
183 void
184 8x local_stream_acceptor::cancel() noexcept
185 {
186 8x if (!is_open())
187 2x return;
188 6x get().cancel();
189 }
190
191 local_endpoint
192 14x local_stream_acceptor::local_endpoint() const noexcept
193 {
194 14x if (!is_open())
195 2x return corosio::local_endpoint{};
196 12x return get().local_endpoint();
197 }
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 handle h(
206 acc.ctx_,
207 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