blob: a5da28164f9364490630cd6bdba364535180be5f [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 NET_SPDY_SPDY_PROXY_CLIENT_SOCKET_H_
#define NET_SPDY_SPDY_PROXY_CLIENT_SOCKET_H_
#include <string>
#include <list>
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "net/base/completion_callback.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_log.h"
#include "net/http/http_auth_controller.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_info.h"
#include "net/http/proxy_client_socket.h"
#include "net/spdy/spdy_http_stream.h"
#include "net/spdy/spdy_protocol.h"
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_stream.h"
class GURL;
namespace net {
class AddressList;
class HttpStream;
class IOBuffer;
class SpdyStream;
class NET_EXPORT_PRIVATE SpdyProxyClientSocket : public ProxyClientSocket,
public SpdyStream::Delegate {
public:
// Create a socket on top of the |spdy_stream| by sending a SYN_STREAM
// CONNECT frame for |endpoint|. After the SYN_REPLY is received,
// any data read/written to the socket will be transferred in data
// frames.
SpdyProxyClientSocket(SpdyStream* spdy_stream,
const std::string& user_agent,
const HostPortPair& endpoint,
const GURL& url,
const HostPortPair& proxy_server,
HttpAuthCache* auth_cache,
HttpAuthHandlerFactory* auth_handler_factory);
// On destruction Disconnect() is called.
virtual ~SpdyProxyClientSocket();
// ProxyClientSocket methods:
virtual const HttpResponseInfo* GetConnectResponseInfo() const OVERRIDE;
virtual HttpStream* CreateConnectResponseStream() OVERRIDE;
virtual const scoped_refptr<HttpAuthController>& GetAuthController() const
OVERRIDE;
virtual int RestartWithAuth(const CompletionCallback& callback) OVERRIDE;
virtual bool IsUsingSpdy() const OVERRIDE;
virtual NextProto GetProtocolNegotiated() const OVERRIDE;
// StreamSocket implementation.
virtual int Connect(const CompletionCallback& callback) OVERRIDE;
virtual void Disconnect() OVERRIDE;
virtual bool IsConnected() const OVERRIDE;
virtual bool IsConnectedAndIdle() const OVERRIDE;
virtual const BoundNetLog& NetLog() const OVERRIDE;
virtual void SetSubresourceSpeculation() OVERRIDE;
virtual void SetOmniboxSpeculation() OVERRIDE;
virtual bool WasEverUsed() const OVERRIDE;
virtual bool UsingTCPFastOpen() const OVERRIDE;
virtual int64 NumBytesRead() const OVERRIDE;
virtual base::TimeDelta GetConnectTimeMicros() const OVERRIDE;
virtual bool WasNpnNegotiated() const OVERRIDE;
virtual NextProto GetNegotiatedProtocol() const OVERRIDE;
virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE;
// Socket implementation.
virtual int Read(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) OVERRIDE;
virtual int Write(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) OVERRIDE;
virtual bool SetReceiveBufferSize(int32 size) OVERRIDE;
virtual bool SetSendBufferSize(int32 size) OVERRIDE;
virtual int GetPeerAddress(IPEndPoint* address) const OVERRIDE;
virtual int GetLocalAddress(IPEndPoint* address) const OVERRIDE;
// SpdyStream::Delegate implementation.
virtual bool OnSendHeadersComplete(int status) OVERRIDE;
virtual int OnSendBody() OVERRIDE;
virtual int OnSendBodyComplete(int status, bool* eof) OVERRIDE;
virtual int OnResponseReceived(const SpdyHeaderBlock& response,
base::Time response_time,
int status) OVERRIDE;
virtual void OnHeadersSent() OVERRIDE;
virtual int OnDataReceived(const char* data, int length) OVERRIDE;
virtual void OnDataSent(int length) OVERRIDE;
virtual void OnClose(int status) OVERRIDE;
private:
enum State {
STATE_DISCONNECTED,
STATE_GENERATE_AUTH_TOKEN,
STATE_GENERATE_AUTH_TOKEN_COMPLETE,
STATE_SEND_REQUEST,
STATE_SEND_REQUEST_COMPLETE,
STATE_READ_REPLY_COMPLETE,
STATE_OPEN,
STATE_CLOSED
};
void LogBlockedTunnelResponse() const;
void OnIOComplete(int result);
int DoLoop(int last_io_result);
int DoGenerateAuthToken();
int DoGenerateAuthTokenComplete(int result);
int DoSendRequest();
int DoSendRequestComplete(int result);
int DoReadReplyComplete(int result);
// Populates |user_buffer_| with as much read data as possible
// and returns the number of bytes read.
int PopulateUserReadBuffer();
State next_state_;
// Pointer to the SPDY Stream that this sits on top of.
scoped_refptr<SpdyStream> spdy_stream_;
// Stores the callback to the layer above, called on completing Read() or
// Connect().
CompletionCallback read_callback_;
// Stores the callback to the layer above, called on completing Write().
CompletionCallback write_callback_;
// CONNECT request and response.
HttpRequestInfo request_;
HttpResponseInfo response_;
// The hostname and port of the endpoint. This is not necessarily the one
// specified by the URL, due to Alternate-Protocol or fixed testing ports.
const HostPortPair endpoint_;
scoped_refptr<HttpAuthController> auth_;
// We buffer the response body as it arrives asynchronously from the stream.
std::list<scoped_refptr<DrainableIOBuffer> > read_buffer_;
// User provided buffer for the Read() response.
scoped_refptr<DrainableIOBuffer> user_buffer_;
// User specified number of bytes to be written.
int write_buffer_len_;
// Number of bytes written which have not been confirmed
int write_bytes_outstanding_;
// True if the transport socket has ever sent data.
bool was_ever_used_;
scoped_ptr<SpdyHttpStream> response_stream_;
base::WeakPtrFactory<SpdyProxyClientSocket> weak_factory_;
const BoundNetLog net_log_;
DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocket);
};
} // namespace net
#endif // NET_SPDY_SPDY_PROXY_CLIENT_SOCKET_H_