|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef TOOLS_ANDROID_FORWARDER2_SOCKET_H_ | 
|  | #define TOOLS_ANDROID_FORWARDER2_SOCKET_H_ | 
|  |  | 
|  | #include <fcntl.h> | 
|  | #include <netinet/in.h> | 
|  | #include <stddef.h> | 
|  | #include <sys/socket.h> | 
|  | #include <sys/un.h> | 
|  |  | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/macros.h" | 
|  |  | 
|  | namespace forwarder2 { | 
|  |  | 
|  | // Wrapper class around unix socket api.  Can be used to create, bind or | 
|  | // connect to both Unix domain sockets and TCP sockets. | 
|  | // TODO(pliard): Split this class into TCPSocket and UnixDomainSocket. | 
|  | class Socket { | 
|  | public: | 
|  | Socket(); | 
|  | ~Socket(); | 
|  |  | 
|  | bool BindUnix(const std::string& path); | 
|  | bool BindTcp(const std::string& host, int port); | 
|  | bool ConnectUnix(const std::string& path); | 
|  | bool ConnectTcp(const std::string& host, int port); | 
|  |  | 
|  | // Just a wrapper around unix socket shutdown(), see man 2 shutdown. | 
|  | void Shutdown(); | 
|  |  | 
|  | // Just a wrapper around unix socket close(), see man 2 close. | 
|  | void Close(); | 
|  | bool IsClosed() const { return socket_ < 0; } | 
|  |  | 
|  | int fd() const { return socket_; } | 
|  |  | 
|  | bool Accept(Socket* new_socket); | 
|  |  | 
|  | // Returns the port allocated to this socket or zero on error. | 
|  | int GetPort(); | 
|  |  | 
|  | // Just a wrapper around unix read() function. | 
|  | // Reads up to buffer_size, but may read less than buffer_size. | 
|  | // Returns the number of bytes read. | 
|  | int Read(void* buffer, size_t buffer_size); | 
|  |  | 
|  | // Same as Read() but with a timeout. | 
|  | int ReadWithTimeout(void* buffer, size_t buffer_size, int timeout_secs); | 
|  |  | 
|  | // Non-blocking version of Read() above. This must be called after a | 
|  | // successful call to select(). The socket must also be in non-blocking mode | 
|  | // before calling this method. | 
|  | int NonBlockingRead(void* buffer, size_t buffer_size); | 
|  |  | 
|  | // Wrapper around send(). | 
|  | int Write(const void* buffer, size_t count); | 
|  |  | 
|  | // Same as NonBlockingRead() but for writing. | 
|  | int NonBlockingWrite(const void* buffer, size_t count); | 
|  |  | 
|  | // Calls Read() multiple times until num_bytes is written to the provided | 
|  | // buffer. No bounds checking is performed. | 
|  | // Returns number of bytes read, which can be different from num_bytes in case | 
|  | // of errror. | 
|  | int ReadNumBytes(void* buffer, size_t num_bytes); | 
|  |  | 
|  | // Same as ReadNumBytes() but with a timeout. | 
|  | int ReadNumBytesWithTimeout(void* buffer, size_t num_bytes, int timeout_secs); | 
|  |  | 
|  | // Calls Write() multiple times until num_bytes is written. No bounds checking | 
|  | // is performed. Returns number of bytes written, which can be different from | 
|  | // num_bytes in case of errror. | 
|  | int WriteNumBytes(const void* buffer, size_t num_bytes); | 
|  |  | 
|  | // Calls WriteNumBytes for the given std::string. Note that the null | 
|  | // terminator is not written to the socket. | 
|  | int WriteString(const std::string& buffer); | 
|  |  | 
|  | bool has_error() const { return socket_error_; } | 
|  |  | 
|  | // |event_fd| must be a valid pipe file descriptor created from the | 
|  | // PipeNotifier and must live (not be closed) at least as long as this socket | 
|  | // is alive. | 
|  | void AddEventFd(int event_fd); | 
|  |  | 
|  | // Returns whether Accept() or Connect() was interrupted because the socket | 
|  | // received an external event fired through the provided fd. | 
|  | bool DidReceiveEventOnFd(int fd) const; | 
|  |  | 
|  | bool DidReceiveEvent() const; | 
|  |  | 
|  | static pid_t GetUnixDomainSocketProcessOwner(const std::string& path); | 
|  |  | 
|  | private: | 
|  | enum EventType { | 
|  | READ, | 
|  | WRITE | 
|  | }; | 
|  |  | 
|  | union SockAddr { | 
|  | // IPv4 sockaddr | 
|  | sockaddr_in addr4; | 
|  | // IPv6 sockaddr | 
|  | sockaddr_in6 addr6; | 
|  | // Unix Domain sockaddr | 
|  | sockaddr_un addr_un; | 
|  | }; | 
|  |  | 
|  | struct Event { | 
|  | int fd; | 
|  | bool was_fired; | 
|  | }; | 
|  |  | 
|  | bool SetNonBlocking(); | 
|  |  | 
|  | // If |host| is empty, use localhost. | 
|  | bool InitTcpSocket(const std::string& host, int port); | 
|  | bool InitUnixSocket(const std::string& path); | 
|  | bool BindAndListen(); | 
|  | bool Connect(); | 
|  |  | 
|  | bool Resolve(const std::string& host); | 
|  | bool InitSocketInternal(); | 
|  | void SetSocketError(); | 
|  |  | 
|  | // Waits until a read or write i/o event has happened. | 
|  | bool WaitForEvent(EventType type, int timeout_secs); | 
|  |  | 
|  | int socket_; | 
|  | int port_; | 
|  | bool socket_error_; | 
|  |  | 
|  | // Family of the socket (AF_INET, AF_INET6 or PF_UNIX). | 
|  | int family_; | 
|  |  | 
|  | SockAddr addr_; | 
|  |  | 
|  | // Points to one of the members of the above union depending on the family. | 
|  | sockaddr* addr_ptr_; | 
|  | // Length of one of the members of the above union depending on the family. | 
|  | socklen_t addr_len_; | 
|  |  | 
|  | // Used to listen for external events (e.g. process received a SIGTERM) while | 
|  | // blocking on I/O operations. | 
|  | std::vector<Event> events_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(Socket); | 
|  | }; | 
|  |  | 
|  | }  // namespace forwarder | 
|  |  | 
|  | #endif  // TOOLS_ANDROID_FORWARDER2_SOCKET_H_ |