TLA Line data 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 : #ifndef BOOST_COROSIO_LOCAL_ENDPOINT_HPP
11 : #define BOOST_COROSIO_LOCAL_ENDPOINT_HPP
12 :
13 : #include <boost/corosio/detail/config.hpp>
14 :
15 : #include <algorithm>
16 : #include <compare>
17 : #include <cstddef>
18 : #include <cstdint>
19 : #include <cstring>
20 : #include <iosfwd>
21 : #include <string_view>
22 : #include <system_error>
23 :
24 : namespace boost::corosio {
25 :
26 : /* A Unix domain socket endpoint (filesystem path).
27 :
28 : Stores the path in a fixed-size buffer, avoiding heap
29 : allocation. The object is trivially copyable.
30 :
31 : Abstract sockets (Linux-only) are represented by paths whose
32 : first character is '\0'. The full path including the leading
33 : null byte is stored.
34 :
35 : The library does NOT automatically unlink the socket path on
36 : close — callers are responsible for cleanup.
37 :
38 : Thread Safety:
39 : Distinct objects: Safe.
40 : Shared objects: Safe.
41 : */
42 : class BOOST_COROSIO_DECL local_endpoint
43 : {
44 : // sun_path is 108 on Linux, 104 on macOS/FreeBSD. Use the
45 : // minimum so local_endpoint is portable across all three.
46 : char path_[104]{};
47 : std::uint8_t len_ = 0;
48 :
49 : public:
50 : /// Maximum path length for a Unix domain socket (excluding null terminator).
51 : static constexpr std::size_t max_path_length = 103;
52 :
53 : /// Default constructor. Creates an empty (unbound) endpoint.
54 HIT 828 : local_endpoint() noexcept = default;
55 :
56 : /** Construct from a path.
57 :
58 : @param path The filesystem path for the socket.
59 : Must not exceed @ref max_path_length bytes.
60 :
61 : @throws std::system_error if the path is too long.
62 : */
63 : explicit local_endpoint(std::string_view path);
64 :
65 : /** Construct from a path (no-throw).
66 :
67 : @param path The filesystem path for the socket.
68 : @param ec Set to an error if the path is too long.
69 : */
70 : local_endpoint(std::string_view path, std::error_code& ec) noexcept;
71 :
72 : /// Return the socket path.
73 52 : std::string_view path() const noexcept
74 : {
75 52 : return std::string_view(path_, len_);
76 : }
77 :
78 : /** Check if this is an abstract socket (Linux-only).
79 :
80 : Abstract sockets live in a kernel namespace rather than
81 : the filesystem. They are identified by a leading null byte
82 : in the path.
83 :
84 : @return `true` if the path starts with '\\0'.
85 : */
86 48 : bool is_abstract() const noexcept
87 : {
88 48 : return len_ > 0 && path_[0] == '\0';
89 : }
90 :
91 : /// Return true if the endpoint has no path.
92 10 : bool empty() const noexcept
93 : {
94 10 : return len_ == 0;
95 : }
96 :
97 : /// Compare endpoints for equality.
98 : friend bool
99 4 : operator==(local_endpoint const& a, local_endpoint const& b) noexcept
100 : {
101 8 : return a.len_ == b.len_ &&
102 8 : std::memcmp(a.path_, b.path_, a.len_) == 0;
103 : }
104 :
105 : /** Format the endpoint for stream output.
106 :
107 : Non-abstract paths are printed as-is. Abstract paths
108 : (leading null byte) are printed as `[abstract:name]`.
109 : Empty endpoints produce no output.
110 : */
111 : friend BOOST_COROSIO_DECL std::ostream&
112 : operator<<(std::ostream& os, local_endpoint const& ep);
113 :
114 : /// Lexicographic ordering on stored path bytes.
115 : friend std::strong_ordering
116 18 : operator<=>(local_endpoint const& a, local_endpoint const& b) noexcept
117 : {
118 18 : auto common = (std::min)(a.len_, b.len_);
119 18 : if (int cmp = std::memcmp(a.path_, b.path_, common); cmp != 0)
120 6 : return cmp <=> 0;
121 12 : return a.len_ <=> b.len_;
122 : }
123 : };
124 :
125 : } // namespace boost::corosio
126 :
127 : #endif // BOOST_COROSIO_LOCAL_ENDPOINT_HPP
|