blob: fc4b47ccfd7bf48edcb0dd29a11c2449cba6825b [file] [log] [blame]
// Copyright 2012 The Goma 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 DEVTOOLS_GOMA_CLIENT_SOCKET_POOL_H_
#define DEVTOOLS_GOMA_CLIENT_SOCKET_POOL_H_
#ifndef _WIN32
#include <sys/socket.h>
#include <sys/types.h>
#endif
#include <deque>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "absl/time/time.h"
#include "absl/types/optional.h"
#include "basictypes.h"
#include "lockhelper.h"
#include "scoped_fd.h"
#include "simple_timer.h"
#include "socket_factory.h"
using std::string;
struct addrinfo;
namespace devtools_goma {
class SimpleTimer;
// TODO: template for ScopedSocket and ScopedNamedPipe.
class SocketPool : public SocketFactory {
public:
SocketPool(const string& host_name, int port);
~SocketPool() override;
bool IsInitialized() const override;
ScopedSocket NewSocket() override;
// Releases the socket. The socket will be reused if NewSocket is called
// within some period of time.
void ReleaseSocket(ScopedSocket&& sock) override;
// Closes the socket.
// Marks the current address had error if err is true, so
// it won't use the current address for some period of time when
// it needs to open new connection.
void CloseSocket(ScopedSocket&& sock, bool err) override;
string DestName() const override;
string host_name() const override { return host_name_; }
int port() const override { return port_; }
size_t NumAddresses() const;
string DebugString() const override;
private:
struct AddrData {
AddrData();
struct sockaddr_storage storage;
size_t len;
int ai_socktype;
int ai_protocol;
string name;
absl::optional<absl::Time> error_timestamp;
const struct sockaddr* addr_ptr() const;
void Invalidate();
bool IsValid() const;
bool InitFromIPv4Addr(const string& ipv4, int port);
void InitFromAddrInfo(const struct addrinfo* ai);
};
class ScopedSocketList;
// Resolves hostname:port and stores in addrs.
static void ResolveAddress(const string& hostname, int port,
std::vector<AddrData>* addrs);
// Initializes socket_pool.
// Returns OK if at least one address could be available, and put
// connected socket into socket_pool_.
// Returns FAIL if no address is available.
// Returns ERR_TIMEOUT if timeout.
Errno InitializeUnlocked() EXCLUSIVE_LOCKS_REQUIRED(mu_);
// Sets error_timetamp in AddrData for sock to |time|.
void SetErrorTimestampUnlocked(int sock, absl::optional<absl::Time> time);
// This host:port is for means the address we will connect directly.
// So, this can be either a destination address or a proxy address.
string host_name_;
int port_;
mutable Lock mu_;
std::vector<AddrData> addrs_;
AddrData* current_addr_; // point in addrs_, or NULL.
std::unordered_map<int, string> fd_addrs_;
// TODO: use ScopedSocket. std::pair doesn't support movable yet?
std::deque<std::pair<int, SimpleTimer>> socket_pool_;
DISALLOW_COPY_AND_ASSIGN(SocketPool);
};
} // namespace devtools_goma
#endif // DEVTOOLS_GOMA_CLIENT_SOCKET_POOL_H_