• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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