1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_ 18 #define INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_ 19 20 #include <stdint.h> 21 #include <sys/types.h> 22 23 #include <memory> 24 #include <string> 25 26 #include "perfetto/base/logging.h" 27 #include "perfetto/ext/base/scoped_file.h" 28 #include "perfetto/ext/base/utils.h" 29 #include "perfetto/ext/base/weak_ptr.h" 30 31 struct msghdr; 32 33 namespace perfetto { 34 namespace base { 35 36 class TaskRunner; 37 38 // Use arbitrarily high values to avoid that some code accidentally ends up 39 // assuming that these enum values match the sysroot's SOCK_xxx defines rather 40 // than using GetSockType() / GetSockFamily(). 41 enum class SockType { kStream = 100, kDgram, kSeqPacket }; 42 enum class SockFamily { kUnix = 200, kInet }; 43 44 // UnixSocketRaw is a basic wrapper around UNIX sockets. It exposes wrapper 45 // methods that take care of most common pitfalls (e.g., marking fd as 46 // O_CLOEXEC, avoiding SIGPIPE, properly handling partial writes). It is used as 47 // a building block for the more sophisticated UnixSocket class. 48 class UnixSocketRaw { 49 public: 50 // Creates a new unconnected unix socket. 51 static UnixSocketRaw CreateMayFail(SockFamily family, SockType type); 52 53 // Crates a pair of connected sockets. 54 static std::pair<UnixSocketRaw, UnixSocketRaw> CreatePair(SockFamily, 55 SockType); 56 57 // Creates an uninitialized unix socket. 58 UnixSocketRaw(); 59 60 // Creates a unix socket adopting an existing file descriptor. This is 61 // typically used to inherit fds from init via environment variables. 62 UnixSocketRaw(ScopedFile, SockFamily, SockType); 63 64 ~UnixSocketRaw() = default; 65 UnixSocketRaw(UnixSocketRaw&&) noexcept = default; 66 UnixSocketRaw& operator=(UnixSocketRaw&&) = default; 67 68 bool Bind(const std::string& socket_name); 69 bool Listen(); 70 bool Connect(const std::string& socket_name); 71 bool SetTxTimeout(uint32_t timeout_ms); 72 bool SetRxTimeout(uint32_t timeout_ms); 73 void Shutdown(); 74 void SetBlocking(bool); 75 bool IsBlocking() const; 76 void RetainOnExec(); type()77 SockType type() const { return type_; } family()78 SockFamily family() const { return family_; } fd()79 int fd() const { return *fd_; } 80 explicit operator bool() const { return !!fd_; } 81 ReleaseFd()82 ScopedFile ReleaseFd() { return std::move(fd_); } 83 84 ssize_t Send(const void* msg, 85 size_t len, 86 const int* send_fds = nullptr, 87 size_t num_fds = 0); 88 89 // Re-enter sendmsg until all the data has been sent or an error occurs. 90 // TODO(fmayer): Figure out how to do timeouts here for heapprofd. 91 ssize_t SendMsgAll(struct msghdr* msg); 92 93 ssize_t Receive(void* msg, 94 size_t len, 95 ScopedFile* fd_vec = nullptr, 96 size_t max_files = 0); 97 98 // Exposed for testing only. 99 // Update msghdr so subsequent sendmsg will send data that remains after n 100 // bytes have already been sent. 101 static void ShiftMsgHdr(size_t n, struct msghdr* msg); 102 103 private: 104 UnixSocketRaw(SockFamily, SockType); 105 106 UnixSocketRaw(const UnixSocketRaw&) = delete; 107 UnixSocketRaw& operator=(const UnixSocketRaw&) = delete; 108 109 ScopedFile fd_; 110 SockFamily family_ = SockFamily::kUnix; 111 SockType type_ = SockType::kStream; 112 }; 113 114 // A non-blocking UNIX domain socket. Allows also to transfer file descriptors. 115 // None of the methods in this class are blocking. 116 // The main design goal is making strong guarantees on the EventListener 117 // callbacks, in order to avoid ending in some undefined state. 118 // In case of any error it will aggressively just shut down the socket and 119 // notify the failure with OnConnect(false) or OnDisconnect() depending on the 120 // state of the socket (see below). 121 // EventListener callbacks stop happening as soon as the instance is destroyed. 122 // 123 // Lifecycle of a client socket: 124 // 125 // Connect() 126 // | 127 // +------------------+------------------+ 128 // | (success) | (failure or Shutdown()) 129 // V V 130 // OnConnect(true) OnConnect(false) 131 // | 132 // V 133 // OnDataAvailable() 134 // | 135 // V 136 // OnDisconnect() (failure or shutdown) 137 // 138 // 139 // Lifecycle of a server socket: 140 // 141 // Listen() --> returns false in case of errors. 142 // | 143 // V 144 // OnNewIncomingConnection(new_socket) 145 // 146 // (|new_socket| inherits the same EventListener) 147 // | 148 // V 149 // OnDataAvailable() 150 // | (failure or Shutdown()) 151 // V 152 // OnDisconnect() 153 class UnixSocket { 154 public: 155 class EventListener { 156 public: 157 virtual ~EventListener(); 158 159 // After Listen(). 160 virtual void OnNewIncomingConnection( 161 UnixSocket* self, 162 std::unique_ptr<UnixSocket> new_connection); 163 164 // After Connect(), whether successful or not. 165 virtual void OnConnect(UnixSocket* self, bool connected); 166 167 // After a successful Connect() or OnNewIncomingConnection(). Either the 168 // other endpoint did disconnect or some other error happened. 169 virtual void OnDisconnect(UnixSocket* self); 170 171 // Whenever there is data available to Receive(). Note that spurious FD 172 // watch events are possible, so it is possible that Receive() soon after 173 // OnDataAvailable() returns 0 (just ignore those). 174 virtual void OnDataAvailable(UnixSocket* self); 175 }; 176 177 enum class State { 178 kDisconnected = 0, // Failed connection, peer disconnection or Shutdown(). 179 kConnecting, // Soon after Connect(), before it either succeeds or fails. 180 kConnected, // After a successful Connect(). 181 kListening // After Listen(), until Shutdown(). 182 }; 183 184 // Creates a socket and starts listening. If SockFamily::kUnix and 185 // |socket_name| starts with a '@', an abstract UNIX dmoain socket will be 186 // created instead of a filesystem-linked UNIX socket (Linux/Android only). 187 // If SockFamily::kInet, |socket_name| is host:port (e.g., "1.2.3.4:8000"). 188 // Returns always an instance. In case of failure (e.g., another socket 189 // with the same name is already listening) the returned socket will have 190 // is_listening() == false and last_error() will contain the failure reason. 191 static std::unique_ptr<UnixSocket> Listen(const std::string& socket_name, 192 EventListener*, 193 TaskRunner*, 194 SockFamily, 195 SockType); 196 197 // Attaches to a pre-existing socket. The socket must have been created in 198 // SOCK_STREAM mode and the caller must have called bind() on it. 199 static std::unique_ptr<UnixSocket> Listen(ScopedFile, 200 EventListener*, 201 TaskRunner*, 202 SockFamily, 203 SockType); 204 205 // Creates a Unix domain socket and connects to the listening endpoint. 206 // Returns always an instance. EventListener::OnConnect(bool success) will 207 // be called always, whether the connection succeeded or not. 208 static std::unique_ptr<UnixSocket> Connect(const std::string& socket_name, 209 EventListener*, 210 TaskRunner*, 211 SockFamily, 212 SockType); 213 214 // Constructs a UnixSocket using the given connected socket. 215 static std::unique_ptr<UnixSocket> AdoptConnected(ScopedFile, 216 EventListener*, 217 TaskRunner*, 218 SockFamily, 219 SockType); 220 221 UnixSocket(const UnixSocket&) = delete; 222 UnixSocket& operator=(const UnixSocket&) = delete; 223 // Cannot be easily moved because of tasks from the FileDescriptorWatch. 224 UnixSocket(UnixSocket&&) = delete; 225 UnixSocket& operator=(UnixSocket&&) = delete; 226 227 // This class gives the hard guarantee that no callback is called on the 228 // passed EventListener immediately after the object has been destroyed. 229 // Any queued callback will be silently dropped. 230 ~UnixSocket(); 231 232 // Shuts down the current connection, if any. If the socket was Listen()-ing, 233 // stops listening. The socket goes back to kNotInitialized state, so it can 234 // be reused with Listen() or Connect(). 235 void Shutdown(bool notify); 236 237 // Returns true is the message was queued, false if there was no space in the 238 // output buffer, in which case the client should retry or give up. 239 // If any other error happens the socket will be shutdown and 240 // EventListener::OnDisconnect() will be called. 241 // If the socket is not connected, Send() will just return false. 242 // Does not append a null string terminator to msg in any case. 243 bool Send(const void* msg, size_t len, const int* send_fds, size_t num_fds); 244 245 inline bool Send(const void* msg, size_t len, int send_fd = -1) { 246 if (send_fd != -1) 247 return Send(msg, len, &send_fd, 1); 248 return Send(msg, len, nullptr, 0); 249 } 250 Send(const std::string & msg)251 inline bool Send(const std::string& msg) { 252 return Send(msg.c_str(), msg.size() + 1, -1); 253 } 254 255 // Returns the number of bytes (<= |len|) written in |msg| or 0 if there 256 // is no data in the buffer to read or an error occurs (in which case a 257 // EventListener::OnDisconnect() will follow). 258 // If the ScopedFile pointer is not null and a FD is received, it moves the 259 // received FD into that. If a FD is received but the ScopedFile pointer is 260 // null, the FD will be automatically closed. 261 size_t Receive(void* msg, size_t len, ScopedFile*, size_t max_files = 1); 262 Receive(void * msg,size_t len)263 inline size_t Receive(void* msg, size_t len) { 264 return Receive(msg, len, nullptr, 0); 265 } 266 267 // Only for tests. This is slower than Receive() as it requires a heap 268 // allocation and a copy for the std::string. Guarantees that the returned 269 // string is null terminated even if the underlying message sent by the peer 270 // is not. 271 std::string ReceiveString(size_t max_length = 1024); 272 is_connected()273 bool is_connected() const { return state_ == State::kConnected; } is_listening()274 bool is_listening() const { return state_ == State::kListening; } fd()275 int fd() const { return sock_raw_.fd(); } last_error()276 int last_error() const { return last_error_; } 277 278 // User ID of the peer, as returned by the kernel. If the client disconnects 279 // and the socket goes into the kDisconnected state, it retains the uid of 280 // the last peer. peer_uid()281 uid_t peer_uid() const { 282 PERFETTO_DCHECK(!is_listening() && peer_uid_ != kInvalidUid); 283 ignore_result(kInvalidPid); // Silence warnings in amalgamated builds. 284 return peer_uid_; 285 } 286 287 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ 288 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) 289 // Process ID of the peer, as returned by the kernel. If the client 290 // disconnects and the socket goes into the kDisconnected state, it 291 // retains the pid of the last peer. 292 // 293 // This is only available on Linux / Android. peer_pid()294 pid_t peer_pid() const { 295 PERFETTO_DCHECK(!is_listening() && peer_pid_ != kInvalidPid); 296 return peer_pid_; 297 } 298 #endif 299 300 // This makes the UnixSocket unusable. 301 UnixSocketRaw ReleaseSocket(); 302 303 private: 304 UnixSocket(EventListener*, TaskRunner*, SockFamily, SockType); 305 UnixSocket(EventListener*, 306 TaskRunner*, 307 ScopedFile, 308 State, 309 SockFamily, 310 SockType); 311 312 // Called once by the corresponding public static factory methods. 313 void DoConnect(const std::string& socket_name); 314 void ReadPeerCredentials(); 315 316 void OnEvent(); 317 void NotifyConnectionState(bool success); 318 319 UnixSocketRaw sock_raw_; 320 State state_ = State::kDisconnected; 321 int last_error_ = 0; 322 uid_t peer_uid_ = kInvalidUid; 323 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ 324 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) 325 pid_t peer_pid_ = kInvalidPid; 326 #endif 327 EventListener* const event_listener_; 328 TaskRunner* const task_runner_; 329 WeakPtrFactory<UnixSocket> weak_ptr_factory_; // Keep last. 330 }; 331 332 } // namespace base 333 } // namespace perfetto 334 335 #endif // INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_ 336