146 lines
4.1 KiB
C
146 lines
4.1 KiB
C
|
// 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 <sys/socket.h>
|
||
|
#include <sys/un.h>
|
||
|
|
||
|
#include <string>
|
||
|
#include <vector>
|
||
|
|
||
|
#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<Event> events_;
|
||
|
|
||
|
DISALLOW_COPY_AND_ASSIGN(Socket);
|
||
|
};
|
||
|
|
||
|
} // namespace forwarder
|
||
|
|
||
|
#endif // TOOLS_ANDROID_FORWARDER2_SOCKET_H_
|