100.00% Lines (14/14) 100.00% Functions (6/6)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2026 Michael Vandeberg 2   // Copyright (c) 2026 Michael Vandeberg
3   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 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) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/cppalliance/corosio 7   // Official repository: https://github.com/cppalliance/corosio
8   // 8   //
9   9  
10   #ifndef BOOST_COROSIO_LOCAL_ENDPOINT_HPP 10   #ifndef BOOST_COROSIO_LOCAL_ENDPOINT_HPP
11   #define BOOST_COROSIO_LOCAL_ENDPOINT_HPP 11   #define BOOST_COROSIO_LOCAL_ENDPOINT_HPP
12   12  
13   #include <boost/corosio/detail/config.hpp> 13   #include <boost/corosio/detail/config.hpp>
14   14  
15   #include <algorithm> 15   #include <algorithm>
16   #include <compare> 16   #include <compare>
17   #include <cstddef> 17   #include <cstddef>
18   #include <cstdint> 18   #include <cstdint>
19   #include <cstring> 19   #include <cstring>
20   #include <iosfwd> 20   #include <iosfwd>
21   #include <string_view> 21   #include <string_view>
22   #include <system_error> 22   #include <system_error>
23   23  
24   namespace boost::corosio { 24   namespace boost::corosio {
25   25  
26   /** A Unix domain socket endpoint (filesystem path). 26   /** A Unix domain socket endpoint (filesystem path).
27   27  
28   Stores the path in a fixed-size buffer, avoiding heap 28   Stores the path in a fixed-size buffer, avoiding heap
29   allocation. The object is trivially copyable. 29   allocation. The object is trivially copyable.
30   30  
31   Abstract sockets (Linux-only) are represented by paths whose 31   Abstract sockets (Linux-only) are represented by paths whose
32   first character is '\0'. The full path including the leading 32   first character is '\0'. The full path including the leading
33   null byte is stored. 33   null byte is stored.
34   34  
35   The library does NOT automatically unlink the socket path on 35   The library does NOT automatically unlink the socket path on
36   close — callers are responsible for cleanup. 36   close — callers are responsible for cleanup.
37   37  
38   @par Thread Safety 38   @par Thread Safety
39   Distinct objects: Safe.@n 39   Distinct objects: Safe.@n
40   Shared objects: Safe. 40   Shared objects: Safe.
41   */ 41   */
42   class BOOST_COROSIO_DECL local_endpoint 42   class BOOST_COROSIO_DECL local_endpoint
43   { 43   {
44   // sun_path is 108 on Linux, 104 on macOS/FreeBSD. Use the 44   // sun_path is 108 on Linux, 104 on macOS/FreeBSD. Use the
45   // minimum so local_endpoint is portable across all three. 45   // minimum so local_endpoint is portable across all three.
46   char path_[104]{}; 46   char path_[104]{};
47   std::uint8_t len_ = 0; 47   std::uint8_t len_ = 0;
48   48  
49   public: 49   public:
50   /// Maximum path length for a Unix domain socket (excluding null terminator). 50   /// Maximum path length for a Unix domain socket (excluding null terminator).
51   static constexpr std::size_t max_path_length = 103; 51   static constexpr std::size_t max_path_length = 103;
52   52  
53   /// Default constructor. Creates an empty (unbound) endpoint. 53   /// Default constructor. Creates an empty (unbound) endpoint.
HITCBC 54   8214 local_endpoint() noexcept = default; 54   8214 local_endpoint() noexcept = default;
55   55  
56   /** Construct from a path. 56   /** Construct from a path.
57   57  
58   An over-long path is a precondition violation: the limit is 58   An over-long path is a precondition violation: the limit is
59   the public @ref max_path_length constant, so callers with 59   the public @ref max_path_length constant, so callers with
60   runtime-derived paths can check 60   runtime-derived paths can check
61   `path.size() <= max_path_length` before constructing. 61   `path.size() <= max_path_length` before constructing.
62   62  
63   @param path The filesystem path for the socket. 63   @param path The filesystem path for the socket.
64   Must not exceed @ref max_path_length bytes. 64   Must not exceed @ref max_path_length bytes.
65   65  
66   @throws std::system_error `errc::filename_too_long` if the 66   @throws std::system_error `errc::filename_too_long` if the
67   path is too long. 67   path is too long.
68   */ 68   */
69   explicit local_endpoint(std::string_view path); 69   explicit local_endpoint(std::string_view path);
70 -  
71   70  
72   /** Return the socket path. 71   /** Return the socket path.
73   72  
74   For abstract sockets, the returned view includes the 73   For abstract sockets, the returned view includes the
75   leading null byte. 74   leading null byte.
76   75  
77   @return A view over the stored path bytes. 76   @return A view over the stored path bytes.
78   */ 77   */
HITCBC 79   322 std::string_view path() const noexcept 78   322 std::string_view path() const noexcept
80   { 79   {
HITCBC 81   322 return std::string_view(path_, len_); 80   322 return std::string_view(path_, len_);
82   } 81   }
83   82  
84   /** Check if this is an abstract socket (Linux-only). 83   /** Check if this is an abstract socket (Linux-only).
85   84  
86   Abstract sockets live in a kernel namespace rather than 85   Abstract sockets live in a kernel namespace rather than
87   the filesystem. They are identified by a leading null byte 86   the filesystem. They are identified by a leading null byte
88   in the path. 87   in the path.
89   88  
90   @return `true` if the path starts with '\\0'. 89   @return `true` if the path starts with '\\0'.
91   */ 90   */
HITCBC 92   301 bool is_abstract() const noexcept 91   301 bool is_abstract() const noexcept
93   { 92   {
HITCBC 94   301 return len_ > 0 && path_[0] == '\0'; 93   301 return len_ > 0 && path_[0] == '\0';
95   } 94   }
96   95  
97   /// Return true if the endpoint has no path. 96   /// Return true if the endpoint has no path.
HITCBC 98   26 bool empty() const noexcept 97   26 bool empty() const noexcept
99   { 98   {
HITCBC 100   26 return len_ == 0; 99   26 return len_ == 0;
101   } 100   }
102   101  
103   /// Compare endpoints for equality. 102   /// Compare endpoints for equality.
104   friend bool 103   friend bool
HITCBC 105   9 operator==(local_endpoint const& a, local_endpoint const& b) noexcept 104   9 operator==(local_endpoint const& a, local_endpoint const& b) noexcept
106   { 105   {
HITCBC 107 - 16 return a.len_ == b.len_ && 106 + 9 return a.len_ == b.len_ && std::memcmp(a.path_, b.path_, a.len_) == 0;
DCB 108 - 16 std::memcmp(a.path_, b.path_, a.len_) == 0;  
109   } 107   }
110   108  
111   /** Format the endpoint for stream output. 109   /** Format the endpoint for stream output.
112   110  
113   Non-abstract paths are printed as-is. Abstract paths 111   Non-abstract paths are printed as-is. Abstract paths
114   (leading null byte) are printed as `[abstract:name]`. 112   (leading null byte) are printed as `[abstract:name]`.
115   Empty endpoints produce no output. 113   Empty endpoints produce no output.
116   114  
117   @param os The output stream. 115   @param os The output stream.
118   @param ep The endpoint to format. 116   @param ep The endpoint to format.
119   117  
120   @return A reference to @p os. 118   @return A reference to @p os.
121   */ 119   */
122   friend BOOST_COROSIO_DECL std::ostream& 120   friend BOOST_COROSIO_DECL std::ostream&
123   operator<<(std::ostream& os, local_endpoint const& ep); 121   operator<<(std::ostream& os, local_endpoint const& ep);
124   122  
125   /// Lexicographic ordering on stored path bytes. 123   /// Lexicographic ordering on stored path bytes.
126   friend std::strong_ordering 124   friend std::strong_ordering
HITCBC 127   44 operator<=>(local_endpoint const& a, local_endpoint const& b) noexcept 125   44 operator<=>(local_endpoint const& a, local_endpoint const& b) noexcept
128   { 126   {
HITCBC 129   44 auto common = (std::min)(a.len_, b.len_); 127   44 auto common = (std::min)(a.len_, b.len_);
HITCBC 130   44 if (int cmp = std::memcmp(a.path_, b.path_, common); cmp != 0) 128   44 if (int cmp = std::memcmp(a.path_, b.path_, common); cmp != 0)
HITCBC 131   19 return cmp <=> 0; 129   19 return cmp <=> 0;
HITCBC 132   25 return a.len_ <=> b.len_; 130   25 return a.len_ <=> b.len_;
133   } 131   }
134   }; 132   };
135   133  
136   } // namespace boost::corosio 134   } // namespace boost::corosio
137   135  
138   #endif // BOOST_COROSIO_LOCAL_ENDPOINT_HPP 136   #endif // BOOST_COROSIO_LOCAL_ENDPOINT_HPP