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/build_config.h" 27 #include "perfetto/base/export.h" 28 #include "perfetto/base/logging.h" 29 #include "perfetto/ext/base/scoped_file.h" 30 #include "perfetto/ext/base/utils.h" 31 #include "perfetto/ext/base/weak_ptr.h" 32 33 struct msghdr; 34 35 namespace perfetto { 36 namespace base { 37 38 // Define the SocketHandle and ScopedSocketHandle types. 39 // On POSIX OSes, a SocketHandle is really just an int (a file descriptor). 40 // On Windows, sockets are have their own type (SOCKET) which is neither a 41 // HANDLE nor an int. However Windows SOCKET(s) can have a event HANDLE attached 42 // to them (which in Perfetto is a PlatformHandle), and that can be used in 43 // WaitForMultipleObjects, hence in base::TaskRunner.AddFileDescriptorWatch(). 44 45 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 46 // uintptr_t really reads as SOCKET here (Windows headers typedef to that). 47 // As usual we don't just use SOCKET here to avoid leaking Windows.h includes 48 // in our headers. 49 using SocketHandle = uintptr_t; // SOCKET 50 int CloseSocket(SocketHandle); // A wrapper around ::closesocket(). 51 using ScopedSocketHandle = 52 ScopedResource<SocketHandle, CloseSocket, static_cast<SocketHandle>(-1)>; 53 #else 54 using SocketHandle = int; 55 using ScopedSocketHandle = ScopedFile; 56 #endif 57 58 class TaskRunner; 59 60 // Use arbitrarily high values to avoid that some code accidentally ends up 61 // assuming that these enum values match the sysroot's SOCK_xxx defines rather 62 // than using GetSockType() / GetSockFamily(). 63 enum class SockType { kStream = 100, kDgram, kSeqPacket }; 64 enum class SockFamily { kUnix = 200, kInet, kInet6 }; 65 66 // Controls the getsockopt(SO_PEERCRED) behavior, which allows to obtain the 67 // peer credentials. 68 enum class SockPeerCredMode { 69 // Obtain the peer credentials immediatley after connection and cache them. 70 kReadOnConnect = 0, 71 72 // Don't read peer credentials at all. Calls to peer_uid()/peer_pid() will 73 // hit a DCHECK and return kInvalidUid/Pid in release builds. 74 kIgnore = 1, 75 76 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 77 kDefault = kIgnore, 78 #else 79 kDefault = kReadOnConnect, 80 #endif 81 }; 82 83 // UnixSocketRaw is a basic wrapper around sockets. It exposes wrapper 84 // methods that take care of most common pitfalls (e.g., marking fd as 85 // O_CLOEXEC, avoiding SIGPIPE, properly handling partial writes). It is used as 86 // a building block for the more sophisticated UnixSocket class which depends 87 // on base::TaskRunner. 88 class UnixSocketRaw { 89 public: 90 // Creates a new unconnected unix socket. 91 static UnixSocketRaw CreateMayFail(SockFamily family, SockType type); 92 93 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 94 // Crates a pair of connected sockets. 95 static std::pair<UnixSocketRaw, UnixSocketRaw> CreatePairPosix(SockFamily, 96 SockType); 97 #endif 98 99 // Creates an uninitialized unix socket. 100 UnixSocketRaw(); 101 102 // Creates a unix socket adopting an existing file descriptor. This is 103 // typically used to inherit fds from init via environment variables. 104 UnixSocketRaw(ScopedSocketHandle, SockFamily, SockType); 105 106 ~UnixSocketRaw() = default; 107 UnixSocketRaw(UnixSocketRaw&&) noexcept = default; 108 UnixSocketRaw& operator=(UnixSocketRaw&&) = default; 109 110 bool Bind(const std::string& socket_name); 111 bool Listen(); 112 bool Connect(const std::string& socket_name); 113 bool SetTxTimeout(uint32_t timeout_ms); 114 bool SetRxTimeout(uint32_t timeout_ms); 115 void Shutdown(); 116 void SetBlocking(bool); 117 void DcheckIsBlocking(bool expected) const; // No-op on release and Win. 118 void RetainOnExec(); type()119 SockType type() const { return type_; } family()120 SockFamily family() const { return family_; } fd()121 SocketHandle fd() const { return *fd_; } 122 explicit operator bool() const { return !!fd_; } 123 124 // This is the handle that passed to TaskRunner.AddFileDescriptorWatch(). 125 // On UNIX this is just the socket FD. On Windows, we need to create a 126 // dedicated event object. watch_handle()127 PlatformHandle watch_handle() const { 128 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 129 return *event_handle_; 130 #else 131 return *fd_; 132 #endif 133 } 134 ReleaseFd()135 ScopedSocketHandle ReleaseFd() { return std::move(fd_); } 136 137 // |send_fds| and |num_fds| are ignored on Windows. 138 ssize_t Send(const void* msg, 139 size_t len, 140 const int* send_fds = nullptr, 141 size_t num_fds = 0); 142 143 // |fd_vec| and |max_files| are ignored on Windows. 144 ssize_t Receive(void* msg, 145 size_t len, 146 ScopedFile* fd_vec = nullptr, 147 size_t max_files = 0); 148 149 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 150 // UNIX-specific helpers to deal with SCM_RIGHTS. 151 152 // Re-enter sendmsg until all the data has been sent or an error occurs. 153 // TODO(fmayer): Figure out how to do timeouts here for heapprofd. 154 ssize_t SendMsgAllPosix(struct msghdr* msg); 155 156 // Exposed for testing only. 157 // Update msghdr so subsequent sendmsg will send data that remains after n 158 // bytes have already been sent. 159 static void ShiftMsgHdrPosix(size_t n, struct msghdr* msg); 160 #endif 161 162 private: 163 UnixSocketRaw(SockFamily, SockType); 164 165 UnixSocketRaw(const UnixSocketRaw&) = delete; 166 UnixSocketRaw& operator=(const UnixSocketRaw&) = delete; 167 168 ScopedSocketHandle fd_; 169 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 170 ScopedPlatformHandle event_handle_; 171 #endif 172 SockFamily family_ = SockFamily::kUnix; 173 SockType type_ = SockType::kStream; 174 }; 175 176 // A non-blocking UNIX domain socket. Allows also to transfer file descriptors. 177 // None of the methods in this class are blocking. 178 // The main design goal is making strong guarantees on the EventListener 179 // callbacks, in order to avoid ending in some undefined state. 180 // In case of any error it will aggressively just shut down the socket and 181 // notify the failure with OnConnect(false) or OnDisconnect() depending on the 182 // state of the socket (see below). 183 // EventListener callbacks stop happening as soon as the instance is destroyed. 184 // 185 // Lifecycle of a client socket: 186 // 187 // Connect() 188 // | 189 // +------------------+------------------+ 190 // | (success) | (failure or Shutdown()) 191 // V V 192 // OnConnect(true) OnConnect(false) 193 // | 194 // V 195 // OnDataAvailable() 196 // | 197 // V 198 // OnDisconnect() (failure or shutdown) 199 // 200 // 201 // Lifecycle of a server socket: 202 // 203 // Listen() --> returns false in case of errors. 204 // | 205 // V 206 // OnNewIncomingConnection(new_socket) 207 // 208 // (|new_socket| inherits the same EventListener) 209 // | 210 // V 211 // OnDataAvailable() 212 // | (failure or Shutdown()) 213 // V 214 // OnDisconnect() 215 class PERFETTO_EXPORT UnixSocket { 216 public: 217 class EventListener { 218 public: 219 virtual ~EventListener(); 220 221 // After Listen(). 222 virtual void OnNewIncomingConnection( 223 UnixSocket* self, 224 std::unique_ptr<UnixSocket> new_connection); 225 226 // After Connect(), whether successful or not. 227 virtual void OnConnect(UnixSocket* self, bool connected); 228 229 // After a successful Connect() or OnNewIncomingConnection(). Either the 230 // other endpoint did disconnect or some other error happened. 231 virtual void OnDisconnect(UnixSocket* self); 232 233 // Whenever there is data available to Receive(). Note that spurious FD 234 // watch events are possible, so it is possible that Receive() soon after 235 // OnDataAvailable() returns 0 (just ignore those). 236 virtual void OnDataAvailable(UnixSocket* self); 237 }; 238 239 enum class State { 240 kDisconnected = 0, // Failed connection, peer disconnection or Shutdown(). 241 kConnecting, // Soon after Connect(), before it either succeeds or fails. 242 kConnected, // After a successful Connect(). 243 kListening // After Listen(), until Shutdown(). 244 }; 245 246 // Creates a socket and starts listening. If SockFamily::kUnix and 247 // |socket_name| starts with a '@', an abstract UNIX dmoain socket will be 248 // created instead of a filesystem-linked UNIX socket (Linux/Android only). 249 // If SockFamily::kInet, |socket_name| is host:port (e.g., "1.2.3.4:8000"). 250 // If SockFamily::kInet6, |socket_name| is [host]:port (e.g., "[::1]:8000"). 251 // Returns nullptr if the socket creation or bind fails. If listening fails, 252 // (e.g. if another socket with the same name is already listening) the 253 // returned socket will have is_listening() == false. 254 static std::unique_ptr<UnixSocket> Listen(const std::string& socket_name, 255 EventListener*, 256 TaskRunner*, 257 SockFamily, 258 SockType); 259 260 // Attaches to a pre-existing socket. The socket must have been created in 261 // SOCK_STREAM mode and the caller must have called bind() on it. 262 static std::unique_ptr<UnixSocket> Listen(ScopedSocketHandle, 263 EventListener*, 264 TaskRunner*, 265 SockFamily, 266 SockType); 267 268 // Creates a Unix domain socket and connects to the listening endpoint. 269 // Returns always an instance. EventListener::OnConnect(bool success) will 270 // be called always, whether the connection succeeded or not. 271 static std::unique_ptr<UnixSocket> Connect( 272 const std::string& socket_name, 273 EventListener*, 274 TaskRunner*, 275 SockFamily, 276 SockType, 277 SockPeerCredMode = SockPeerCredMode::kDefault); 278 279 // Constructs a UnixSocket using the given connected socket. 280 static std::unique_ptr<UnixSocket> AdoptConnected( 281 ScopedSocketHandle, 282 EventListener*, 283 TaskRunner*, 284 SockFamily, 285 SockType, 286 SockPeerCredMode = SockPeerCredMode::kDefault); 287 288 UnixSocket(const UnixSocket&) = delete; 289 UnixSocket& operator=(const UnixSocket&) = delete; 290 // Cannot be easily moved because of tasks from the FileDescriptorWatch. 291 UnixSocket(UnixSocket&&) = delete; 292 UnixSocket& operator=(UnixSocket&&) = delete; 293 294 // This class gives the hard guarantee that no callback is called on the 295 // passed EventListener immediately after the object has been destroyed. 296 // Any queued callback will be silently dropped. 297 ~UnixSocket(); 298 299 // Shuts down the current connection, if any. If the socket was Listen()-ing, 300 // stops listening. The socket goes back to kNotInitialized state, so it can 301 // be reused with Listen() or Connect(). 302 void Shutdown(bool notify); 303 SetTxTimeout(uint32_t timeout_ms)304 void SetTxTimeout(uint32_t timeout_ms) { 305 PERFETTO_CHECK(sock_raw_.SetTxTimeout(timeout_ms)); 306 } SetRxTimeout(uint32_t timeout_ms)307 void SetRxTimeout(uint32_t timeout_ms) { 308 PERFETTO_CHECK(sock_raw_.SetRxTimeout(timeout_ms)); 309 } 310 // Returns true is the message was queued, false if there was no space in the 311 // output buffer, in which case the client should retry or give up. 312 // If any other error happens the socket will be shutdown and 313 // EventListener::OnDisconnect() will be called. 314 // If the socket is not connected, Send() will just return false. 315 // Does not append a null string terminator to msg in any case. 316 bool Send(const void* msg, size_t len, const int* send_fds, size_t num_fds); 317 318 inline bool Send(const void* msg, size_t len, int send_fd = -1) { 319 if (send_fd != -1) 320 return Send(msg, len, &send_fd, 1); 321 return Send(msg, len, nullptr, 0); 322 } 323 Send(const std::string & msg)324 inline bool Send(const std::string& msg) { 325 return Send(msg.c_str(), msg.size() + 1, -1); 326 } 327 328 // Returns the number of bytes (<= |len|) written in |msg| or 0 if there 329 // is no data in the buffer to read or an error occurs (in which case a 330 // EventListener::OnDisconnect() will follow). 331 // If the ScopedFile pointer is not null and a FD is received, it moves the 332 // received FD into that. If a FD is received but the ScopedFile pointer is 333 // null, the FD will be automatically closed. 334 size_t Receive(void* msg, size_t len, ScopedFile*, size_t max_files = 1); 335 Receive(void * msg,size_t len)336 inline size_t Receive(void* msg, size_t len) { 337 return Receive(msg, len, nullptr, 0); 338 } 339 340 // Only for tests. This is slower than Receive() as it requires a heap 341 // allocation and a copy for the std::string. Guarantees that the returned 342 // string is null terminated even if the underlying message sent by the peer 343 // is not. 344 std::string ReceiveString(size_t max_length = 1024); 345 is_connected()346 bool is_connected() const { return state_ == State::kConnected; } is_listening()347 bool is_listening() const { return state_ == State::kListening; } fd()348 SocketHandle fd() const { return sock_raw_.fd(); } 349 350 // User ID of the peer, as returned by the kernel. If the client disconnects 351 // and the socket goes into the kDisconnected state, it retains the uid of 352 // the last peer. 353 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 354 uid_t peer_uid_posix(bool skip_check_for_testing = false) const { 355 PERFETTO_DCHECK((!is_listening() && peer_uid_ != kInvalidUid) || 356 skip_check_for_testing); 357 358 return peer_uid_; 359 } 360 #endif 361 362 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ 363 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) 364 // Process ID of the peer, as returned by the kernel. If the client 365 // disconnects and the socket goes into the kDisconnected state, it 366 // retains the pid of the last peer. 367 // 368 // This is only available on Linux / Android. 369 pid_t peer_pid_linux(bool skip_check_for_testing = false) const { 370 PERFETTO_DCHECK((!is_listening() && peer_pid_ != kInvalidPid) || 371 skip_check_for_testing); 372 return peer_pid_; 373 } 374 #endif 375 376 // This makes the UnixSocket unusable. 377 UnixSocketRaw ReleaseSocket(); 378 379 private: 380 UnixSocket(EventListener*, 381 TaskRunner*, 382 SockFamily, 383 SockType, 384 SockPeerCredMode); 385 UnixSocket(EventListener*, 386 TaskRunner*, 387 ScopedSocketHandle, 388 State, 389 SockFamily, 390 SockType, 391 SockPeerCredMode); 392 393 // Called once by the corresponding public static factory methods. 394 void DoConnect(const std::string& socket_name); 395 396 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 397 void ReadPeerCredentialsPosix(); 398 #endif 399 400 void OnEvent(); 401 void NotifyConnectionState(bool success); 402 403 UnixSocketRaw sock_raw_; 404 State state_ = State::kDisconnected; 405 SockPeerCredMode peer_cred_mode_ = SockPeerCredMode::kDefault; 406 407 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 408 uid_t peer_uid_ = kInvalidUid; 409 #endif 410 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ 411 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) 412 pid_t peer_pid_ = kInvalidPid; 413 #endif 414 EventListener* const event_listener_; 415 TaskRunner* const task_runner_; 416 WeakPtrFactory<UnixSocket> weak_ptr_factory_; // Keep last. 417 }; 418 419 } // namespace base 420 } // namespace perfetto 421 422 #endif // INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_ 423