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 SRC_IPC_UNIX_SOCKET_H_ 18 #define SRC_IPC_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/base/scoped_file.h" 28 #include "perfetto/base/weak_ptr.h" 29 #include "perfetto/ipc/basic_types.h" 30 31 namespace perfetto { 32 33 namespace base { 34 class TaskRunner; 35 } // namespace base. 36 37 namespace ipc { 38 39 // A non-blocking UNIX domain socket in SOCK_STREAM mode. Allows also to 40 // transfer file descriptors. None of the methods in this class are blocking. 41 // The main design goal is API simplicity and strong guarantees on the 42 // EventListener callbacks, in order to avoid ending in some undefined state. 43 // In case of any error it will aggressively just shut down the socket and 44 // notify the failure with OnConnect(false) or OnDisconnect() depending on the 45 // state of the socket (see below). 46 // EventListener callbacks stop happening as soon as the instance is destroyed. 47 // 48 // Lifecycle of a client socket: 49 // 50 // Connect() 51 // | 52 // +------------------+------------------+ 53 // | (success) | (failure or Shutdown()) 54 // V V 55 // OnConnect(true) OnConnect(false) 56 // | 57 // V 58 // OnDataAvailable() 59 // | 60 // V 61 // OnDisconnect() (failure or shutdown) 62 // 63 // 64 // Lifecycle of a server socket: 65 // 66 // Listen() --> returns false in case of errors. 67 // | 68 // V 69 // OnNewIncomingConnection(new_socket) 70 // 71 // (|new_socket| inherits the same EventListener) 72 // | 73 // V 74 // OnDataAvailable() 75 // | (failure or Shutdown()) 76 // V 77 // OnDisconnect() 78 class UnixSocket { 79 public: 80 class EventListener { 81 public: 82 virtual ~EventListener(); 83 84 // After Listen(). 85 virtual void OnNewIncomingConnection( 86 UnixSocket* self, 87 std::unique_ptr<UnixSocket> new_connection); 88 89 // After Connect(), whether successful or not. 90 virtual void OnConnect(UnixSocket* self, bool connected); 91 92 // After a successful Connect() or OnNewIncomingConnection(). Either the 93 // other endpoint did disconnect or some other error happened. 94 virtual void OnDisconnect(UnixSocket* self); 95 96 // Whenever there is data available to Receive(). Note that spurious FD 97 // watch events are possible, so it is possible that Receive() soon after 98 // OnDataAvailable() returns 0 (just ignore those). 99 virtual void OnDataAvailable(UnixSocket* self); 100 }; 101 102 enum class State { 103 kDisconnected = 0, // Failed connection, peer disconnection or Shutdown(). 104 kConnecting, // Soon after Connect(), before it either succeeds or fails. 105 kConnected, // After a successful Connect(). 106 kListening // After Listen(), until Shutdown(). 107 }; 108 109 enum class BlockingMode { kNonBlocking, kBlocking }; 110 111 // Creates a Unix domain socket and starts listening. If |socket_name| 112 // starts with a '@', an abstract socket will be created (Linux/Android only). 113 // Returns always an instance. In case of failure (e.g., another socket 114 // with the same name is already listening) the returned socket will have 115 // is_listening() == false and last_error() will contain the failure reason. 116 static std::unique_ptr<UnixSocket> Listen(const std::string& socket_name, 117 EventListener*, 118 base::TaskRunner*); 119 120 // Attaches to a pre-existing socket. The socket must have been created in 121 // SOCK_STREAM mode and the caller must have called bind() on it. 122 static std::unique_ptr<UnixSocket> Listen(base::ScopedFile socket_fd, 123 EventListener*, 124 base::TaskRunner*); 125 126 // Creates a Unix domain socket and connects to the listening endpoint. 127 // Returns always an instance. EventListener::OnConnect(bool success) will 128 // be called always, whether the connection succeeded or not. 129 static std::unique_ptr<UnixSocket> Connect(const std::string& socket_name, 130 EventListener*, 131 base::TaskRunner*); 132 133 // Creates a Unix domain socket and binds it to |socket_name| (see comment 134 // of Listen() above for the format). This file descriptor is suitable to be 135 // passed to Listen(ScopedFile, ...). Returns the file descriptor, or -1 in 136 // case of failure. 137 static base::ScopedFile CreateAndBind(const std::string& socket_name); 138 139 // This class gives the hard guarantee that no callback is called on the 140 // passed EventListener immediately after the object has been destroyed. 141 // Any queued callback will be silently dropped. 142 ~UnixSocket(); 143 144 // Shuts down the current connection, if any. If the socket was Listen()-ing, 145 // stops listening. The socket goes back to kNotInitialized state, so it can 146 // be reused with Listen() or Connect(). 147 void Shutdown(bool notify); 148 149 // Returns true is the message was queued, false if there was no space in the 150 // output buffer, in which case the client should retry or give up. 151 // If any other error happens the socket will be shutdown and 152 // EventListener::OnDisconnect() will be called. 153 // If the socket is not connected, Send() will just return false. 154 // Does not append a null string terminator to msg in any case. 155 bool Send(const void* msg, 156 size_t len, 157 int send_fd = -1, 158 BlockingMode blocking = BlockingMode::kNonBlocking); 159 bool Send(const std::string& msg); 160 161 // Returns the number of bytes (<= |len|) written in |msg| or 0 if there 162 // is no data in the buffer to read or an error occurs (in which case a 163 // EventListener::OnDisconnect() will follow). 164 // If the ScopedFile pointer is not null and a FD is received, it moves the 165 // received FD into that. If a FD is received but the ScopedFile pointer is 166 // null, the FD will be automatically closed. 167 size_t Receive(void* msg, size_t len, base::ScopedFile* = nullptr); 168 169 // Only for tests. This is slower than Receive() as it requires a heap 170 // allocation and a copy for the std::string. Guarantees that the returned 171 // string is null terminated even if the underlying message sent by the peer 172 // is not. 173 std::string ReceiveString(size_t max_length = 1024); 174 is_connected()175 bool is_connected() const { return state_ == State::kConnected; } is_listening()176 bool is_listening() const { return state_ == State::kListening; } fd()177 int fd() const { return fd_.get(); } last_error()178 int last_error() const { return last_error_; } 179 180 // User ID of the peer, as returned by the kernel. If the client disconnects 181 // and the socket goes into the kDisconnected state, it retains the uid of 182 // the last peer. peer_uid()183 uid_t peer_uid() const { 184 PERFETTO_DCHECK(!is_listening() && peer_uid_ != kInvalidUid); 185 return peer_uid_; 186 } 187 188 private: 189 UnixSocket(EventListener*, base::TaskRunner*); 190 UnixSocket(EventListener*, base::TaskRunner*, base::ScopedFile, State); 191 UnixSocket(const UnixSocket&) = delete; 192 UnixSocket& operator=(const UnixSocket&) = delete; 193 194 // Called once by the corresponding public static factory methods. 195 void DoConnect(const std::string& socket_name); 196 void ReadPeerCredentials(); 197 void SetBlockingIO(bool is_blocking); 198 199 void OnEvent(); 200 void NotifyConnectionState(bool success); 201 202 base::ScopedFile fd_; 203 State state_ = State::kDisconnected; 204 int last_error_ = 0; 205 uid_t peer_uid_ = kInvalidUid; 206 EventListener* event_listener_; 207 base::TaskRunner* task_runner_; 208 base::WeakPtrFactory<UnixSocket> weak_ptr_factory_; 209 }; 210 211 } // namespace ipc 212 } // namespace perfetto 213 214 #endif // SRC_IPC_UNIX_SOCKET_H_ 215