src/corosio/src/local_stream_acceptor.cpp

100.0% Lines (69 / 69) 100.0% Functions (12 / 12)
local_stream_acceptor.cpp
f(x) Functions (12)
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/detail/except.hpp>
12 #include <boost/corosio/detail/platform.hpp>
13 #include <boost/corosio/detail/local_stream_acceptor_service.hpp>
14
15 #include "src/detail/use_backend_service.hpp"
16
17 #include <cstring>
18
19 #if BOOST_COROSIO_POSIX
20 #include <sys/socket.h>
21 #include <unistd.h>
22 #else
23 // Windows: AF_UNIX socket files are reparse points with tag
24 // IO_REPARSE_TAG_AF_UNIX. DeleteFileA reliably removes them;
25 // std::filesystem::remove via libstdc++/MS STL was observed to
26 // silently leave them in place on at least some Windows hosts,
27 // so call the Win32 API directly.
28 #define WIN32_LEAN_AND_MEAN
29 #include <winsock2.h>
30 #include <windows.h>
31 #ifndef AF_UNIX
32 #define AF_UNIX 1
33 #endif
34 #endif
35
36 namespace boost::corosio {
37
38 114x local_stream_acceptor::~local_stream_acceptor()
39 {
40 114x close();
41 114x }
42
43 94x local_stream_acceptor::local_stream_acceptor(capy::execution_context& ctx)
44 94x : io_object(handle(
45 ctx,
46 detail::use_backend_service<
47 detail::local_stream_acceptor_service_of,
48 94x detail::local_stream_acceptor_service>(ctx)))
49 188x , ctx_(ctx)
50 {
51 94x }
52
53 14x local_stream_acceptor::local_stream_acceptor(
54 14x capy::execution_context& ctx, corosio::local_endpoint ep, int backlog)
55 14x : local_stream_acceptor(ctx)
56 {
57 14x if (auto ec = open())
58 5x detail::throw_system_error(ec, "local_stream_acceptor");
59 9x if (auto ec = bind(ep))
60 2x detail::throw_system_error(ec, "local_stream_acceptor");
61 7x if (auto ec = listen(backlog))
62 5x detail::throw_system_error(ec, "local_stream_acceptor");
63 14x }
64
65 std::error_code
66 90x local_stream_acceptor::open() noexcept
67 {
68 90x if (is_open())
69 2x return {};
70 auto& svc =
71 88x static_cast<detail::local_stream_acceptor_service&>(h_.service());
72 88x auto ec = svc.open_acceptor_socket(
73 88x static_cast<local_stream_acceptor::implementation&>(*h_.get()), AF_UNIX,
74 SOCK_STREAM, 0);
75 88x return ec;
76 }
77
78 std::error_code
79 10x local_stream_acceptor::assign(native_handle_type fd) noexcept
80 {
81 auto& svc =
82 10x static_cast<detail::local_stream_acceptor_service&>(h_.service());
83 10x auto ec = svc.assign_socket(
84 10x static_cast<local_stream_acceptor::implementation&>(*h_.get()), fd);
85 10x return ec;
86 }
87
88 native_handle_type
89 12x local_stream_acceptor::native_handle() const noexcept
90 {
91 12x if (!is_open())
92 {
93 #if BOOST_COROSIO_HAS_IOCP
94 return static_cast<native_handle_type>(~0ull); // INVALID_SOCKET
95 #else
96 4x return -1;
97 #endif
98 }
99 8x return get().native_handle();
100 }
101
102 std::error_code
103 77x local_stream_acceptor::bind(
104 corosio::local_endpoint ep, bind_option opt) noexcept
105 {
106 77x if (!is_open())
107 2x return make_error_code(std::errc::bad_file_descriptor);
108
109 75x if (opt == bind_option::unlink_existing && !ep.empty() && !ep.is_abstract())
110 {
111 // Best-effort removal; missing file is fine.
112 4x auto p = ep.path();
113 char buf[local_endpoint::max_path_length + 1];
114 4x std::memcpy(buf, p.data(), p.size());
115 4x buf[p.size()] = '\0';
116 #if BOOST_COROSIO_POSIX
117 4x ::unlink(buf);
118 #else
119 ::DeleteFileA(buf);
120 #endif
121 }
122
123 auto& svc =
124 75x static_cast<detail::local_stream_acceptor_service&>(h_.service());
125 75x return svc.bind_acceptor(
126 150x static_cast<local_stream_acceptor::implementation&>(*h_.get()), ep);
127 }
128
129 std::error_code
130 62x local_stream_acceptor::listen(int backlog) noexcept
131 {
132 62x if (!is_open())
133 2x return make_error_code(std::errc::bad_file_descriptor);
134 auto& svc =
135 60x static_cast<detail::local_stream_acceptor_service&>(h_.service());
136 60x return svc.listen_acceptor(
137 60x static_cast<local_stream_acceptor::implementation&>(*h_.get()),
138 60x backlog);
139 }
140
141 void
142 125x local_stream_acceptor::close() noexcept
143 {
144 125x if (!is_open())
145 48x return;
146 77x h_.service().close(h_);
147 }
148
149 native_handle_type
150 12x local_stream_acceptor::release()
151 {
152 12x if (!is_open())
153 2x detail::throw_system_error(
154 2x make_error_code(std::errc::bad_file_descriptor),
155 "local_stream_acceptor::release");
156 10x return get().release_socket();
157 }
158
159 void
160 8x local_stream_acceptor::cancel() noexcept
161 {
162 8x if (!is_open())
163 2x return;
164 6x get().cancel();
165 }
166
167 local_endpoint
168 12x local_stream_acceptor::local_endpoint() const noexcept
169 {
170 12x if (!is_open())
171 2x return corosio::local_endpoint{};
172 10x return get().local_endpoint();
173 }
174
175 } // namespace boost::corosio
176