Home | History | Annotate | Download | only in forwarder2
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef TOOLS_ANDROID_FORWARDER2_SOCKET_H_
      6 #define TOOLS_ANDROID_FORWARDER2_SOCKET_H_
      7 
      8 #include <fcntl.h>
      9 #include <netinet/in.h>
     10 #include <sys/socket.h>
     11 #include <sys/un.h>
     12 
     13 #include <string>
     14 #include <vector>
     15 
     16 #include "base/basictypes.h"
     17 
     18 namespace forwarder2 {
     19 
     20 // Wrapper class around unix socket api.  Can be used to create, bind or
     21 // connect to both Unix domain sockets and TCP sockets.
     22 // TODO(pliard): Split this class into TCPSocket and UnixDomainSocket.
     23 class Socket {
     24  public:
     25   Socket();
     26   ~Socket();
     27 
     28   bool BindUnix(const std::string& path);
     29   bool BindTcp(const std::string& host, int port);
     30   bool ConnectUnix(const std::string& path);
     31   bool ConnectTcp(const std::string& host, int port);
     32 
     33   // Just a wrapper around unix socket shutdown(), see man 2 shutdown.
     34   void Shutdown();
     35 
     36   // Just a wrapper around unix socket close(), see man 2 close.
     37   void Close();
     38   bool IsClosed() const { return socket_ < 0; }
     39 
     40   bool Accept(Socket* new_socket);
     41 
     42   // Returns the port allocated to this socket or zero on error.
     43   int GetPort();
     44 
     45   bool IsFdInSet(const fd_set& fds) const;
     46   bool AddFdToSet(fd_set* fds) const;
     47 
     48   // Just a wrapper around unix read() function.
     49   // Reads up to buffer_size, but may read less then buffer_size.
     50   // Returns the number of bytes read.
     51   int Read(void* buffer, size_t buffer_size);
     52 
     53   // Non-blocking version of Read() above. This must be called after a
     54   // successful call to select(). The socket must also be in non-blocking mode
     55   // before calling this method.
     56   int NonBlockingRead(void* buffer, size_t buffer_size);
     57 
     58   // Wrapper around send().
     59   int Write(const void* buffer, size_t count);
     60 
     61   // Same as NonBlockingRead() but for writing.
     62   int NonBlockingWrite(const void* buffer, size_t count);
     63 
     64   // Calls Read() multiple times until num_bytes is written to the provided
     65   // buffer. No bounds checking is performed.
     66   // Returns number of bytes read, which can be different from num_bytes in case
     67   // of errror.
     68   int ReadNumBytes(void* buffer, size_t num_bytes);
     69 
     70   // Calls Write() multiple times until num_bytes is written. No bounds checking
     71   // is performed. Returns number of bytes written, which can be different from
     72   // num_bytes in case of errror.
     73   int WriteNumBytes(const void* buffer, size_t num_bytes);
     74 
     75   // Calls WriteNumBytes for the given std::string. Note that the null
     76   // terminator is not written to the socket.
     77   int WriteString(const std::string& buffer);
     78 
     79   bool has_error() const { return socket_error_; }
     80 
     81   // |event_fd| must be a valid pipe file descriptor created from the
     82   // PipeNotifier and must live (not be closed) at least as long as this socket
     83   // is alive.
     84   void AddEventFd(int event_fd);
     85 
     86   // Returns whether Accept() or Connect() was interrupted because the socket
     87   // received an external event fired through the provided fd.
     88   bool DidReceiveEventOnFd(int fd) const;
     89 
     90   bool DidReceiveEvent() const;
     91 
     92   static int GetHighestFileDescriptor(const Socket& s1, const Socket& s2);
     93 
     94   static pid_t GetUnixDomainSocketProcessOwner(const std::string& path);
     95 
     96  private:
     97   enum EventType {
     98     READ,
     99     WRITE
    100   };
    101 
    102   union SockAddr {
    103     // IPv4 sockaddr
    104     sockaddr_in addr4;
    105     // IPv6 sockaddr
    106     sockaddr_in6 addr6;
    107     // Unix Domain sockaddr
    108     sockaddr_un addr_un;
    109   };
    110 
    111   struct Event {
    112     int fd;
    113     bool was_fired;
    114   };
    115 
    116   bool SetNonBlocking();
    117 
    118   // If |host| is empty, use localhost.
    119   bool InitTcpSocket(const std::string& host, int port);
    120   bool InitUnixSocket(const std::string& path);
    121   bool BindAndListen();
    122   bool Connect();
    123 
    124   bool Resolve(const std::string& host);
    125   bool InitSocketInternal();
    126   void SetSocketError();
    127 
    128   // Waits until either the Socket or the |exit_notifier_fd_| has received an
    129   // event.
    130   bool WaitForEvent(EventType type, int timeout_secs);
    131 
    132   int socket_;
    133   int port_;
    134   bool socket_error_;
    135 
    136   // Family of the socket (PF_INET, PF_INET6 or PF_UNIX).
    137   int family_;
    138 
    139   SockAddr addr_;
    140 
    141   // Points to one of the members of the above union depending on the family.
    142   sockaddr* addr_ptr_;
    143   // Length of one of the members of the above union depending on the family.
    144   socklen_t addr_len_;
    145 
    146   // Used to listen for external events (e.g. process received a SIGTERM) while
    147   // blocking on I/O operations.
    148   std::vector<Event> events_;
    149 
    150   DISALLOW_COPY_AND_ASSIGN(Socket);
    151 };
    152 
    153 }  // namespace forwarder
    154 
    155 #endif  // TOOLS_ANDROID_FORWARDER2_SOCKET_H_
    156