Home | History | Annotate | Download | only in ipc
      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 
    175   bool is_connected() const { return state_ == State::kConnected; }
    176   bool is_listening() const { return state_ == State::kListening; }
    177   int fd() const { return fd_.get(); }
    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.
    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