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 66x local_stream_acceptor::~local_stream_acceptor()
32 {
33 66x close();
34 66x }
35
36 48x local_stream_acceptor::local_stream_acceptor(capy::execution_context& ctx)
37 48x : io_object(create_handle<detail::local_stream_acceptor_service>(ctx))
38 48x , ctx_(ctx)
39 {
40 48x }
41
42 void
43 48x local_stream_acceptor::open(local_stream proto)
44 {
45 48x if (is_open())
46 return;
47 auto& svc =
48 48x static_cast<detail::local_stream_acceptor_service&>(h_.service());
49 96x auto ec = svc.open_acceptor_socket(
50 48x static_cast<local_stream_acceptor::implementation&>(*h_.get()),
51 proto.family(), proto.type(), proto.protocol());
52 48x if (ec)
53 detail::throw_system_error(ec, "local_stream_acceptor::open");
54 }
55
56 std::error_code
57 51x local_stream_acceptor::bind(corosio::local_endpoint ep, bind_option opt)
58 {
59 51x if (!is_open())
60 3x detail::throw_logic_error("bind: acceptor not open");
61
62 54x if (opt == bind_option::unlink_existing &&
63 48x !ep.empty() && !ep.is_abstract())
64 {
65 // Best-effort removal; missing file is fine.
66 6x auto p = ep.path();
67 char buf[local_endpoint::max_path_length + 1];
68 6x std::memcpy(buf, p.data(), p.size());
69 6x buf[p.size()] = '\0';
70 #if BOOST_COROSIO_POSIX
71 6x ::unlink(buf);
72 #else
73 ::DeleteFileA(buf);
74 #endif
75 }
76
77 auto& svc =
78 48x static_cast<detail::local_stream_acceptor_service&>(h_.service());
79 48x return svc.bind_acceptor(
80 48x static_cast<local_stream_acceptor::implementation&>(*h_.get()),
81 48x ep);
82 }
83
84 std::error_code
85 36x local_stream_acceptor::listen(int backlog)
86 {
87 36x if (!is_open())
88 3x detail::throw_logic_error("listen: acceptor not open");
89 auto& svc =
90 33x static_cast<detail::local_stream_acceptor_service&>(h_.service());
91 33x return svc.listen_acceptor(
92 33x static_cast<local_stream_acceptor::implementation&>(*h_.get()),
93 33x backlog);
94 }
95
96 void
97 69x local_stream_acceptor::close()
98 {
99 69x if (!is_open())
100 24x return;
101 45x h_.service().close(h_);
102 }
103
104 native_handle_type
105 6x local_stream_acceptor::release()
106 {
107 6x if (!is_open())
108 3x detail::throw_logic_error("release: acceptor not open");
109 3x return get().release_socket();
110 }
111
112 void
113 6x local_stream_acceptor::cancel()
114 {
115 6x if (!is_open())
116 3x return;
117 3x get().cancel();
118 }
119
120 local_endpoint
121 6x local_stream_acceptor::local_endpoint() const noexcept
122 {
123 6x if (!is_open())
124 3x return corosio::local_endpoint{};
125 3x return get().local_endpoint();
126 }
127
128 } // namespace boost::corosio
129