// Copyright 2012 The Chromium Authors
// 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>
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(const Socket&) = delete;
Socket& operator=(const Socket&) = delete;
~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_;
};
} // namespace forwarder
#endif // TOOLS_ANDROID_FORWARDER2_SOCKET_H_