blob: 10e545cadcb36a331092e222c39baf6e13187af6 [file] [log] [blame]
// 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 SERVICES_NETWORK_PROXY_RESOLVING_CLIENT_SOCKET_H_
#define SERVICES_NETWORK_PROXY_RESOLVING_CLIENT_SOCKET_H_
#include <stdint.h>
#include <memory>
#include "base/compiler_specific.h"
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
#include "net/log/net_log_with_source.h"
#include "net/proxy_resolution/proxy_info.h"
#include "net/proxy_resolution/proxy_resolution_service.h"
#include "net/socket/connect_job.h"
#include "net/socket/next_proto.h"
#include "net/socket/stream_socket.h"
#include "net/ssl/ssl_config_service.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "url/gurl.h"
namespace net {
struct CommonConnectJobParams;
class HttpAuthController;
class HttpResponseInfo;
class HttpNetworkSession;
} // namespace net
namespace network {
// This class represents a net::StreamSocket implementation that does proxy
// resolution for the provided url before establishing a connection. If there is
// a proxy configured, a connection will be established to the proxy.
class COMPONENT_EXPORT(NETWORK_SERVICE) ProxyResolvingClientSocket
: public net::StreamSocket,
public net::ConnectJob::Delegate {
public:
// Constructs a new ProxyResolvingClientSocket. |url|'s host and port specify
// where a connection will be established to. The full URL will be only used
// for proxy resolution. Caller doesn't need to explicitly sanitize the url,
// any sensitive data (like embedded usernames and passwords), and local data
// (i.e. reference fragment) will be sanitized by
// net::ProxyResolutionService::ResolveProxyHelper() before the url is
// disclosed to the proxy. If |use_tls|, this will try to do a tls connect
// instead of a regular tcp connect. |network_session| and
// |common_connect_job_params| must outlive |this|.
ProxyResolvingClientSocket(
net::HttpNetworkSession* network_session,
const net::CommonConnectJobParams* common_connect_job_params,
const net::SSLConfig& ssl_config,
const GURL& url,
bool use_tls);
~ProxyResolvingClientSocket() override;
// net::StreamSocket implementation.
int Read(net::IOBuffer* buf,
int buf_len,
net::CompletionOnceCallback callback) override;
int ReadIfReady(net::IOBuffer* buf,
int buf_len,
net::CompletionOnceCallback callback) override;
int CancelReadIfReady() override;
int Write(
net::IOBuffer* buf,
int buf_len,
net::CompletionOnceCallback callback,
const net::NetworkTrafficAnnotationTag& traffic_annotation) override;
int SetReceiveBufferSize(int32_t size) override;
int SetSendBufferSize(int32_t size) override;
int Connect(net::CompletionOnceCallback callback) override;
void Disconnect() override;
bool IsConnected() const override;
bool IsConnectedAndIdle() const override;
int GetPeerAddress(net::IPEndPoint* address) const override;
int GetLocalAddress(net::IPEndPoint* address) const override;
const net::NetLogWithSource& NetLog() const override;
bool WasEverUsed() const override;
bool WasAlpnNegotiated() const override;
net::NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(net::SSLInfo* ssl_info) override;
void GetConnectionAttempts(net::ConnectionAttempts* out) const override;
void ClearConnectionAttempts() override {}
void AddConnectionAttempts(const net::ConnectionAttempts& attempts) override {
}
int64_t GetTotalReceivedBytes() const override;
void ApplySocketTag(const net::SocketTag& tag) override;
private:
enum State {
STATE_PROXY_RESOLVE,
STATE_PROXY_RESOLVE_COMPLETE,
STATE_INIT_CONNECTION,
STATE_INIT_CONNECTION_COMPLETE,
STATE_DONE,
STATE_NONE,
};
FRIEND_TEST_ALL_PREFIXES(ProxyResolvingClientSocketTest, ConnectToProxy);
FRIEND_TEST_ALL_PREFIXES(ProxyResolvingClientSocketTest, ReadWriteErrors);
FRIEND_TEST_ALL_PREFIXES(ProxyResolvingClientSocketTest,
ResetSocketAfterTunnelAuth);
void OnIOComplete(int result);
int DoLoop(int result);
int DoProxyResolve();
int DoProxyResolveComplete(int result);
int DoInitConnection();
int DoInitConnectionComplete(int result);
// net::ConnectJob::Delegate implementation:
void OnConnectJobComplete(int result, net::ConnectJob* job) override;
void OnNeedsProxyAuth(const net::HttpResponseInfo& response,
net::HttpAuthController* auth_controller,
base::OnceClosure restart_with_auth_callback,
net::ConnectJob* job) override;
int ReconsiderProxyAfterError(int error);
net::HttpNetworkSession* network_session_;
const net::CommonConnectJobParams* common_connect_job_params_;
std::unique_ptr<net::ConnectJob> connect_job_;
std::unique_ptr<net::StreamSocket> socket_;
const net::SSLConfig ssl_config_;
std::unique_ptr<net::ProxyResolutionService::Request> proxy_resolve_request_;
net::ProxyInfo proxy_info_;
const GURL url_;
const bool use_tls_;
net::NetLogWithSource net_log_;
// The callback passed to Connect().
net::CompletionOnceCallback user_connect_callback_;
State next_state_;
base::WeakPtrFactory<ProxyResolvingClientSocket> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ProxyResolvingClientSocket);
};
} // namespace network
#endif // SERVICES_NETWORK_PROXY_RESOLVING_CLIENT_SOCKET_H_