blob: 5de3135e99dea9160a7cd48d6a0bbb4c1c89fda2 [file] [log] [blame]
// Copyright 2015 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_HTTP_BIDIRECTIONAL_STREAM_H_
#define NET_HTTP_BIDIRECTIONAL_STREAM_H_
#include <stdint.h>
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "net/http/bidirectional_stream_job.h"
#include "net/http/http_stream_factory.h"
#include "net/log/net_log.h"
#include "net/net_features.h"
#if !BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
#error Only include this if ENABLE_BIDIRECTIONAL_STREAM is defined
#endif
class GURL;
namespace net {
class HttpAuthController;
class HttpNetworkSession;
class HttpStream;
class HttpStreamRequest;
class IOBuffer;
class ProxyInfo;
class SpdyHeaderBlock;
struct BidirectionalStreamRequestInfo;
struct SSLConfig;
// A class to do HTTP/2 bidirectional streaming. Note that at most one each of
// ReadData or SendData should be in flight until the operation completes.
// The BidirectionalStream must be torn down before the HttpNetworkSession.
class NET_EXPORT BidirectionalStream
: public NON_EXPORTED_BASE(BidirectionalStreamJob::Delegate),
public NON_EXPORTED_BASE(HttpStreamRequest::Delegate) {
public:
// Delegate interface to get notified of success of failure. Callbacks will be
// invoked asynchronously.
class NET_EXPORT Delegate {
public:
Delegate();
// Called when headers have been sent. This is called at most once for
// the lifetime of a stream.
// The delegate may call BidirectionalStream::ReadData to start reading,
// or call BidirectionalStream::SendData to send data.
// The delegate should not call BidirectionalStream::Cancel
// during this callback.
virtual void OnHeadersSent() = 0;
// Called when headers are received. This is called at most once for the
// lifetime of a stream.
// The delegate may call BidirectionalStream::ReadData to start reading,
// call BidirectionalStream::SendData to send data,
// or call BidirectionalStream::Cancel to cancel the stream.
virtual void OnHeadersReceived(const SpdyHeaderBlock& response_headers) = 0;
// Called when a pending read is completed asynchronously.
// |bytes_read| specifies how much data is read.
// The delegate may call BidirectionalStream::ReadData to continue
// reading, call BidirectionalStream::SendData to send data,
// or call BidirectionalStream::Cancel to cancel the stream.
virtual void OnDataRead(int bytes_read) = 0;
// Called when the entire buffer passed through SendData is sent.
// The delegate may call BidirectionalStream::ReadData to continue
// reading, call BidirectionalStream::SendData to send data,
// The delegate should not call BidirectionalStream::Cancel
// during this callback.
virtual void OnDataSent() = 0;
// Called when trailers are received. This is called as soon as trailers
// are received, which can happen before a read completes.
// The delegate is able to continue reading if there is no pending read and
// EOF has not been received, or to send data if there is no pending send.
virtual void OnTrailersReceived(const SpdyHeaderBlock& trailers) = 0;
// Called when the stream is closed or an error occurred.
// No other delegate functions will be called after this.
virtual void OnFailed(int error) = 0;
protected:
virtual ~Delegate();
private:
DISALLOW_COPY_AND_ASSIGN(Delegate);
};
// Constructs a BidirectionalStream. |request_info| contains information about
// the request, and must be non-NULL. |session| is the http network session
// with which this request will be made. |delegate| must be non-NULL.
// |session| and |delegate| must outlive |this|.
BidirectionalStream(scoped_ptr<BidirectionalStreamRequestInfo> request_info,
HttpNetworkSession* session,
Delegate* delegate);
// Constructor that accepts a Timer, which can be used in tests to control
// the buffering of received data.
BidirectionalStream(scoped_ptr<BidirectionalStreamRequestInfo> request_info,
HttpNetworkSession* session,
Delegate* delegate,
scoped_ptr<base::Timer> timer);
// Cancels |stream_request_| or |stream_job_| if applicable.
// |this| should not be destroyed during Delegate::OnHeadersSent or
// Delegate::OnDataSent.
~BidirectionalStream() override;
// Reads at most |buf_len| bytes into |buf|. Returns the number of bytes read,
// or ERR_IO_PENDING if the read is to be completed asynchronously, or an
// error code if any error occurred. If returns 0, there is no more data to
// read. This should not be called before Delegate::OnHeadersReceived is
// invoked, and should not be called again unless it returns with number
// greater than 0 or until Delegate::OnDataRead is invoked.
int ReadData(IOBuffer* buf, int buf_len);
// Sends data. This should not be called before Delegate::OnHeadersSent is
// invoked, and should not be called again until Delegate::OnDataSent is
// invoked. If |end_stream| is true, the DATA frame will have an END_STREAM
// flag.
void SendData(IOBuffer* data, int length, bool end_stream);
// If |stream_request_| is non-NULL, cancel it. If |stream_job_| is
// established, cancel it. No delegate method will be called after Cancel().
// Any pending operations may or may not succeed.
void Cancel();
// Returns the protocol used by this stream. If stream has not been
// established, return kProtoUnknown.
NextProto GetProtocol() const;
// Total number of bytes received over the network of SPDY data, headers, and
// push_promise frames associated with this stream, including the size of
// frame headers, after SSL decryption and not including proxy overhead.
// If stream has not been established, return 0.
int64_t GetTotalReceivedBytes() const;
// Total number of bytes sent over the network of SPDY frames associated with
// this stream, including the size of frame headers, before SSL encryption and
// not including proxy overhead. Note that some SPDY frames such as pings are
// not associated with any stream, and are not included in this value.
int64_t GetTotalSentBytes() const;
// TODO(xunjieli): Implement a method to do flow control and a method to ping
// remote end point.
private:
// BidirectionalStreamJob::Delegate implementation:
void OnHeadersSent() override;
void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override;
void OnDataRead(int bytes_read) override;
void OnDataSent() override;
void OnTrailersReceived(const SpdyHeaderBlock& trailers) override;
void OnFailed(int error) override;
// HttpStreamRequest::Delegate implementation:
void OnStreamReady(const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
HttpStream* stream) override;
void OnBidirectionalStreamJobReady(const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
BidirectionalStreamJob* stream) override;
void OnWebSocketHandshakeStreamReady(
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
WebSocketHandshakeStreamBase* stream) override;
void OnStreamFailed(int status,
const SSLConfig& used_ssl_config,
SSLFailureState ssl_failure_state) override;
void OnCertificateError(int status,
const SSLConfig& used_ssl_config,
const SSLInfo& ssl_info) override;
void OnNeedsProxyAuth(const HttpResponseInfo& response_info,
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
HttpAuthController* auth_controller) override;
void OnNeedsClientAuth(const SSLConfig& used_ssl_config,
SSLCertRequestInfo* cert_info) override;
void OnHttpsProxyTunnelResponse(const HttpResponseInfo& response_info,
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
HttpStream* stream) override;
void OnQuicBroken() override;
// BidirectionalStreamRequestInfo used when requesting the stream.
scoped_ptr<BidirectionalStreamRequestInfo> request_info_;
const BoundNetLog net_log_;
Delegate* const delegate_;
// Timer used to buffer data received in short time-spans and send a single
// read completion notification.
scoped_ptr<base::Timer> timer_;
// HttpStreamRequest used to request a BidirectionalStreamJob. This is NULL if
// the request has been canceled or completed.
scoped_ptr<HttpStreamRequest> stream_request_;
// The underlying BidirectioanlStreamJob used for this stream. It is non-NULL,
// if the |stream_request_| successfully finishes.
scoped_ptr<BidirectionalStreamJob> stream_job_;
DISALLOW_COPY_AND_ASSIGN(BidirectionalStream);
};
} // namespace net
#endif // NET_HTTP_BIDIRECTIONAL_STREAM_H_