src/corosio/src/local_stream_acceptor.cpp

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