• 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 
SendStr(const std::string & str)143   ssize_t SendStr(const std::string& str) {
144     return Send(str.data(), str.size());
145   }
146 
147   // |fd_vec| and |max_files| are ignored on Windows.
148   ssize_t Receive(void* msg,
149                   size_t len,
150                   ScopedFile* fd_vec = nullptr,
151                   size_t max_files = 0);
152 
153 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
154   // UNIX-specific helpers to deal with SCM_RIGHTS.
155 
156   // Re-enter sendmsg until all the data has been sent or an error occurs.
157   // TODO(fmayer): Figure out how to do timeouts here for heapprofd.
158   ssize_t SendMsgAllPosix(struct msghdr* msg);
159 
160   // Exposed for testing only.
161   // Update msghdr so subsequent sendmsg will send data that remains after n
162   // bytes have already been sent.
163   static void ShiftMsgHdrPosix(size_t n, struct msghdr* msg);
164 #endif
165 
166  private:
167   UnixSocketRaw(SockFamily, SockType);
168 
169   UnixSocketRaw(const UnixSocketRaw&) = delete;
170   UnixSocketRaw& operator=(const UnixSocketRaw&) = delete;
171 
172   ScopedSocketHandle fd_;
173 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
174   ScopedPlatformHandle event_handle_;
175 #endif
176   SockFamily family_ = SockFamily::kUnix;
177   SockType type_ = SockType::kStream;
178   uint32_t tx_timeout_ms_ = 0;
179 };
180 
181 // A non-blocking UNIX domain socket. Allows also to transfer file descriptors.
182 // None of the methods in this class are blocking.
183 // The main design goal is making strong guarantees on the EventListener
184 // callbacks, in order to avoid ending in some undefined state.
185 // In case of any error it will aggressively just shut down the socket and
186 // notify the failure with OnConnect(false) or OnDisconnect() depending on the
187 // state of the socket (see below).
188 // EventListener callbacks stop happening as soon as the instance is destroyed.
189 //
190 // Lifecycle of a client socket:
191 //
192 //                           Connect()
193 //                               |
194 //            +------------------+------------------+
195 //            | (success)                           | (failure or Shutdown())
196 //            V                                     V
197 //     OnConnect(true)                         OnConnect(false)
198 //            |
199 //            V
200 //    OnDataAvailable()
201 //            |
202 //            V
203 //     OnDisconnect()  (failure or shutdown)
204 //
205 //
206 // Lifecycle of a server socket:
207 //
208 //                          Listen()  --> returns false in case of errors.
209 //                             |
210 //                             V
211 //              OnNewIncomingConnection(new_socket)
212 //
213 //          (|new_socket| inherits the same EventListener)
214 //                             |
215 //                             V
216 //                     OnDataAvailable()
217 //                             | (failure or Shutdown())
218 //                             V
219 //                       OnDisconnect()
220 class PERFETTO_EXPORT UnixSocket {
221  public:
222   class EventListener {
223    public:
224     virtual ~EventListener();
225 
226     // After Listen().
227     virtual void OnNewIncomingConnection(
228         UnixSocket* self,
229         std::unique_ptr<UnixSocket> new_connection);
230 
231     // After Connect(), whether successful or not.
232     virtual void OnConnect(UnixSocket* self, bool connected);
233 
234     // After a successful Connect() or OnNewIncomingConnection(). Either the
235     // other endpoint did disconnect or some other error happened.
236     virtual void OnDisconnect(UnixSocket* self);
237 
238     // Whenever there is data available to Receive(). Note that spurious FD
239     // watch events are possible, so it is possible that Receive() soon after
240     // OnDataAvailable() returns 0 (just ignore those).
241     virtual void OnDataAvailable(UnixSocket* self);
242   };
243 
244   enum class State {
245     kDisconnected = 0,  // Failed connection, peer disconnection or Shutdown().
246     kConnecting,  // Soon after Connect(), before it either succeeds or fails.
247     kConnected,   // After a successful Connect().
248     kListening    // After Listen(), until Shutdown().
249   };
250 
251   // Creates a socket and starts listening. If SockFamily::kUnix and
252   // |socket_name| starts with a '@', an abstract UNIX dmoain socket will be
253   // created instead of a filesystem-linked UNIX socket (Linux/Android only).
254   // If SockFamily::kInet, |socket_name| is host:port (e.g., "1.2.3.4:8000").
255   // If SockFamily::kInet6, |socket_name| is [host]:port (e.g., "[::1]:8000").
256   // Returns nullptr if the socket creation or bind fails. If listening fails,
257   // (e.g. if another socket with the same name is already listening) the
258   // returned socket will have is_listening() == false.
259   static std::unique_ptr<UnixSocket> Listen(const std::string& socket_name,
260                                             EventListener*,
261                                             TaskRunner*,
262                                             SockFamily,
263                                             SockType);
264 
265   // Attaches to a pre-existing socket. The socket must have been created in
266   // SOCK_STREAM mode and the caller must have called bind() on it.
267   static std::unique_ptr<UnixSocket> Listen(ScopedSocketHandle,
268                                             EventListener*,
269                                             TaskRunner*,
270                                             SockFamily,
271                                             SockType);
272 
273   // Creates a Unix domain socket and connects to the listening endpoint.
274   // Returns always an instance. EventListener::OnConnect(bool success) will
275   // be called always, whether the connection succeeded or not.
276   static std::unique_ptr<UnixSocket> Connect(
277       const std::string& socket_name,
278       EventListener*,
279       TaskRunner*,
280       SockFamily,
281       SockType,
282       SockPeerCredMode = SockPeerCredMode::kDefault);
283 
284   // Constructs a UnixSocket using the given connected socket.
285   static std::unique_ptr<UnixSocket> AdoptConnected(
286       ScopedSocketHandle,
287       EventListener*,
288       TaskRunner*,
289       SockFamily,
290       SockType,
291       SockPeerCredMode = SockPeerCredMode::kDefault);
292 
293   UnixSocket(const UnixSocket&) = delete;
294   UnixSocket& operator=(const UnixSocket&) = delete;
295   // Cannot be easily moved because of tasks from the FileDescriptorWatch.
296   UnixSocket(UnixSocket&&) = delete;
297   UnixSocket& operator=(UnixSocket&&) = delete;
298 
299   // This class gives the hard guarantee that no callback is called on the
300   // passed EventListener immediately after the object has been destroyed.
301   // Any queued callback will be silently dropped.
302   ~UnixSocket();
303 
304   // Shuts down the current connection, if any. If the socket was Listen()-ing,
305   // stops listening. The socket goes back to kNotInitialized state, so it can
306   // be reused with Listen() or Connect().
307   void Shutdown(bool notify);
308 
SetTxTimeout(uint32_t timeout_ms)309   void SetTxTimeout(uint32_t timeout_ms) {
310     PERFETTO_CHECK(sock_raw_.SetTxTimeout(timeout_ms));
311   }
SetRxTimeout(uint32_t timeout_ms)312   void SetRxTimeout(uint32_t timeout_ms) {
313     PERFETTO_CHECK(sock_raw_.SetRxTimeout(timeout_ms));
314   }
315   // Returns true is the message was queued, false if there was no space in the
316   // output buffer, in which case the client should retry or give up.
317   // If any other error happens the socket will be shutdown and
318   // EventListener::OnDisconnect() will be called.
319   // If the socket is not connected, Send() will just return false.
320   // Does not append a null string terminator to msg in any case.
321   bool Send(const void* msg, size_t len, const int* send_fds, size_t num_fds);
322 
323   inline bool Send(const void* msg, size_t len, int send_fd = -1) {
324     if (send_fd != -1)
325       return Send(msg, len, &send_fd, 1);
326     return Send(msg, len, nullptr, 0);
327   }
328 
SendStr(const std::string & msg)329   inline bool SendStr(const std::string& msg) {
330     return Send(msg.data(), msg.size(), -1);
331   }
332 
333   // Returns the number of bytes (<= |len|) written in |msg| or 0 if there
334   // is no data in the buffer to read or an error occurs (in which case a
335   // EventListener::OnDisconnect() will follow).
336   // If the ScopedFile pointer is not null and a FD is received, it moves the
337   // received FD into that. If a FD is received but the ScopedFile pointer is
338   // null, the FD will be automatically closed.
339   size_t Receive(void* msg, size_t len, ScopedFile*, size_t max_files = 1);
340 
Receive(void * msg,size_t len)341   inline size_t Receive(void* msg, size_t len) {
342     return Receive(msg, len, nullptr, 0);
343   }
344 
345   // Only for tests. This is slower than Receive() as it requires a heap
346   // allocation and a copy for the std::string. Guarantees that the returned
347   // string is null terminated even if the underlying message sent by the peer
348   // is not.
349   std::string ReceiveString(size_t max_length = 1024);
350 
is_connected()351   bool is_connected() const { return state_ == State::kConnected; }
is_listening()352   bool is_listening() const { return state_ == State::kListening; }
fd()353   SocketHandle fd() const { return sock_raw_.fd(); }
354 
355   // User ID of the peer, as returned by the kernel. If the client disconnects
356   // and the socket goes into the kDisconnected state, it retains the uid of
357   // the last peer.
358 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
359   uid_t peer_uid_posix(bool skip_check_for_testing = false) const {
360     PERFETTO_DCHECK((!is_listening() && peer_uid_ != kInvalidUid) ||
361                     skip_check_for_testing);
362 
363     return peer_uid_;
364   }
365 #endif
366 
367 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
368     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
369   // Process ID of the peer, as returned by the kernel. If the client
370   // disconnects and the socket goes into the kDisconnected state, it
371   // retains the pid of the last peer.
372   //
373   // This is only available on Linux / Android.
374   pid_t peer_pid_linux(bool skip_check_for_testing = false) const {
375     PERFETTO_DCHECK((!is_listening() && peer_pid_ != kInvalidPid) ||
376                     skip_check_for_testing);
377     return peer_pid_;
378   }
379 #endif
380 
381   // This makes the UnixSocket unusable.
382   UnixSocketRaw ReleaseSocket();
383 
384  private:
385   UnixSocket(EventListener*,
386              TaskRunner*,
387              SockFamily,
388              SockType,
389              SockPeerCredMode);
390   UnixSocket(EventListener*,
391              TaskRunner*,
392              ScopedSocketHandle,
393              State,
394              SockFamily,
395              SockType,
396              SockPeerCredMode);
397 
398   // Called once by the corresponding public static factory methods.
399   void DoConnect(const std::string& socket_name);
400 
401 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
402   void ReadPeerCredentialsPosix();
403 #endif
404 
405   void OnEvent();
406   void NotifyConnectionState(bool success);
407 
408   UnixSocketRaw sock_raw_;
409   State state_ = State::kDisconnected;
410   SockPeerCredMode peer_cred_mode_ = SockPeerCredMode::kDefault;
411 
412 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
413   uid_t peer_uid_ = kInvalidUid;
414 #endif
415 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
416     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
417   pid_t peer_pid_ = kInvalidPid;
418 #endif
419   EventListener* const event_listener_;
420   TaskRunner* const task_runner_;
421   WeakPtrFactory<UnixSocket> weak_ptr_factory_;  // Keep last.
422 };
423 
424 }  // namespace base
425 }  // namespace perfetto
426 
427 #endif  // INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_
428