src/corosio/src/local_stream_acceptor.cpp

96.1% Lines (49/51) 100.0% List of functions (9/9)
local_stream_acceptor.cpp
f(x) Functions (9)
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 <cstring>
16
17 #if BOOST_COROSIO_POSIX
18 #include <unistd.h>
19 #else
20 // Windows: AF_UNIX socket files are reparse points with tag
21 // IO_REPARSE_TAG_AF_UNIX. DeleteFileA reliably removes them;
22 // std::filesystem::remove via libstdc++/MS STL was observed to
23 // silently leave them in place on at least some Windows hosts,
24 // so call the Win32 API directly.
25 #define WIN32_LEAN_AND_MEAN
26 #include <windows.h>
27 #endif
28
29 namespace boost::corosio {
30
31 44x local_stream_acceptor::~local_stream_acceptor()
32 {
33 44x close();
34 44x }
35
36 32x local_stream_acceptor::local_stream_acceptor(capy::execution_context& ctx)
37 32x : io_object(create_handle<detail::local_stream_acceptor_service>(ctx))
38 32x , ctx_(ctx)
39 {
40 32x }
41
42 void
43 32x local_stream_acceptor::open(local_stream proto)
44 {
45 32x if (is_open())
46 return;
47 auto& svc =
48 32x static_cast<detail::local_stream_acceptor_service&>(h_.service());
49 64x auto ec = svc.open_acceptor_socket(
50 32x static_cast<local_stream_acceptor::implementation&>(*h_.get()),
51 proto.family(), proto.type(), proto.protocol());
52 32x if (ec)
53 detail::throw_system_error(ec, "local_stream_acceptor::open");
54 }
55
56 std::error_code
57 34x local_stream_acceptor::bind(corosio::local_endpoint ep, bind_option opt)
58 {
59 34x if (!is_open())
60 2x detail::throw_logic_error("bind: acceptor not open");
61
62 36x if (opt == bind_option::unlink_existing &&
63 32x !ep.empty() && !ep.is_abstract())
64 {
65 // Best-effort removal; missing file is fine.
66 4x auto p = ep.path();
67 char buf[local_endpoint::max_path_length + 1];
68 4x std::memcpy(buf, p.data(), p.size());
69 4x buf[p.size()] = '\0';
70 #if BOOST_COROSIO_POSIX
71 4x ::unlink(buf);
72 #else
73 ::DeleteFileA(buf);
74 #endif
75 }
76
77 auto& svc =
78 32x static_cast<detail::local_stream_acceptor_service&>(h_.service());
79 32x return svc.bind_acceptor(
80 32x static_cast<local_stream_acceptor::implementation&>(*h_.get()),
81 32x ep);
82 }
83
84 std::error_code
85 24x local_stream_acceptor::listen(int backlog)
86 {
87 24x if (!is_open())
88 2x detail::throw_logic_error("listen: acceptor not open");
89 auto& svc =
90 22x static_cast<detail::local_stream_acceptor_service&>(h_.service());
91 22x return svc.listen_acceptor(
92 22x static_cast<local_stream_acceptor::implementation&>(*h_.get()),
93 22x backlog);
94 }
95
96 void
97 46x local_stream_acceptor::close()
98 {
99 46x if (!is_open())
100 16x return;
101 30x h_.service().close(h_);
102 }
103
104 native_handle_type
105 4x local_stream_acceptor::release()
106 {
107 4x if (!is_open())
108 2x detail::throw_logic_error("release: acceptor not open");
109 2x return get().release_socket();
110 }
111
112 void
113 4x local_stream_acceptor::cancel()
114 {
115 4x if (!is_open())
116 2x return;
117 2x get().cancel();
118 }
119
120 local_endpoint
121 4x local_stream_acceptor::local_endpoint() const noexcept
122 {
123 4x if (!is_open())
124 2x return corosio::local_endpoint{};
125 2x return get().local_endpoint();
126 }
127
128 } // namespace boost::corosio
129