// 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 #include #include #include #include #include #include "base/basictypes.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; } bool Accept(Socket* new_socket); // Returns the port allocated to this socket or zero on error. int GetPort(); bool IsFdInSet(const fd_set& fds) const; bool AddFdToSet(fd_set* fds) const; // Just a wrapper around unix read() function. // Reads up to buffer_size, but may read less then buffer_size. // Returns the number of bytes read. int Read(void* buffer, size_t buffer_size); // Same as Read(), just a wrapper around write(). int Write(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); // 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 int GetHighestFileDescriptor(const Socket& s1, const Socket& s2); 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; }; // 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 either the Socket or the |exit_notifier_fd_| has received an // event. bool WaitForEvent(EventType type, int timeout_secs); int socket_; int port_; bool socket_error_; // Family of the socket (PF_INET, PF_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 events_; DISALLOW_COPY_AND_ASSIGN(Socket); }; } // namespace forwarder #endif // TOOLS_ANDROID_FORWARDER2_SOCKET_H_