blob: e264192a5d9705f3329bae1ddebf7b137d2eef83 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_SPDY_SPDY_HTTP_STREAM_H_
#define NET_SPDY_SPDY_HTTP_STREAM_H_
#include <stdint.h>
#include <memory>
#include <set>
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece.h"
#include "base/timer/timer.h"
#include "net/base/completion_once_callback.h"
#include "net/base/load_timing_info.h"
#include "net/base/net_export.h"
#include "net/log/net_log_source.h"
#include "net/spdy/multiplexed_http_stream.h"
#include "net/spdy/spdy_read_queue.h"
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_stream.h"
namespace net {
struct HttpRequestInfo;
class HttpResponseInfo;
class IOBuffer;
class SpdySession;
class UploadDataStream;
// The SpdyHttpStream is a HTTP-specific type of stream known to a SpdySession.
class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
public MultiplexedHttpStream {
public:
static const size_t kRequestBodyBufferSize;
// |spdy_session| must not be NULL.
SpdyHttpStream(const base::WeakPtr<SpdySession>& spdy_session,
spdy::SpdyStreamId pushed_stream_id,
NetLogSource source_dependency,
std::set<std::string> dns_aliases);
SpdyHttpStream(const SpdyHttpStream&) = delete;
SpdyHttpStream& operator=(const SpdyHttpStream&) = delete;
~SpdyHttpStream() override;
SpdyStream* stream() { return stream_; }
// Cancels any callbacks from being invoked and deletes the stream.
void Cancel();
// HttpStream implementation.
void RegisterRequest(const HttpRequestInfo* request_info) override;
int InitializeStream(bool can_send_early,
RequestPriority priority,
const NetLogWithSource& net_log,
CompletionOnceCallback callback) override;
int SendRequest(const HttpRequestHeaders& headers,
HttpResponseInfo* response,
CompletionOnceCallback callback) override;
int ReadResponseHeaders(CompletionOnceCallback callback) override;
int ReadResponseBody(IOBuffer* buf,
int buf_len,
CompletionOnceCallback callback) override;
void Close(bool not_reusable) override;
bool IsResponseBodyComplete() const override;
// Must not be called if a NULL SpdySession was pssed into the
// constructor.
bool IsConnectionReused() const override;
// 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.
int64_t GetTotalReceivedBytes() const override;
// 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 override;
bool GetAlternativeService(
AlternativeService* alternative_service) const override;
bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override;
int GetRemoteEndpoint(IPEndPoint* endpoint) override;
void PopulateNetErrorDetails(NetErrorDetails* details) override;
void SetPriority(RequestPriority priority) override;
const std::set<std::string>& GetDnsAliases() const override;
base::StringPiece GetAcceptChViaAlps() const override;
// SpdyStream::Delegate implementation.
void OnHeadersSent() override;
void OnEarlyHintsReceived(const spdy::Http2HeaderBlock& headers) override;
void OnHeadersReceived(
const spdy::Http2HeaderBlock& response_headers,
const spdy::Http2HeaderBlock* pushed_request_headers) override;
void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) override;
void OnDataSent() override;
void OnTrailers(const spdy::Http2HeaderBlock& trailers) override;
void OnClose(int status) override;
bool CanGreaseFrameType() const override;
NetLogSource source_dependency() const override;
private:
// Helper function used to initialize private members and to set delegate on
// stream when stream is created.
void InitializeStreamHelper();
// Helper function used for resetting stream from inside the stream.
void ResetStream(int error);
// Must be called only when |request_info_| is non-NULL.
bool HasUploadData() const;
void OnStreamCreated(CompletionOnceCallback callback, int rv);
// Reads the remaining data (whether chunked or not) from the
// request body stream and sends it if there's any. The read and
// subsequent sending may happen asynchronously. Must be called only
// when HasUploadData() is true.
void ReadAndSendRequestBodyData();
// Send an empty body. Must only be called if there is no upload data and
// sending greased HTTP/2 frames is enabled. This allows SpdyStream to
// prepend a greased HTTP/2 frame to the empty DATA frame that closes the
// stream.
void SendEmptyBody();
// Called when data has just been read from the request body stream;
// does the actual sending of data.
void OnRequestBodyReadCompleted(int status);
// Call the user callback associated with sending the request.
void DoRequestCallback(int rv);
// Method to PostTask for calling request callback asynchronously.
void MaybeDoRequestCallback(int rv);
// Post the request callback if not null.
// This is necessary because the request callback might destroy |stream_|,
// which does not support that.
void MaybePostRequestCallback(int rv);
// Call the user callback associated with reading the response.
void DoResponseCallback(int rv);
void MaybeScheduleBufferedReadCallback();
void DoBufferedReadCallback();
const base::WeakPtr<SpdySession> spdy_session_;
// The ID of the pushed stream if one is claimed by this request.
// In this case, the request fails if it cannot use that pushed stream.
// Otherwise set to kNoPushedStreamFound.
const spdy::SpdyStreamId pushed_stream_id_;
bool is_reused_;
SpdyStreamRequest stream_request_;
const NetLogSource source_dependency_;
// |stream_| is owned by SpdySession.
// Before InitializeStream() is called, stream_ == nullptr.
// After InitializeStream() is called but before OnClose() is called,
// |*stream_| is guaranteed to be valid.
// After OnClose() is called, stream_ == nullptr.
raw_ptr<SpdyStream> stream_ = nullptr;
// False before OnClose() is called, true after.
bool stream_closed_ = false;
// Set only when |stream_closed_| is true.
int closed_stream_status_ = ERR_FAILED;
spdy::SpdyStreamId closed_stream_id_ = 0;
bool closed_stream_has_load_timing_info_;
LoadTimingInfo closed_stream_load_timing_info_;
// After |stream_| has been closed, this keeps track of the total number of
// bytes received over the network for |stream_| while it was open.
int64_t closed_stream_received_bytes_ = 0;
// After |stream_| has been closed, this keeps track of the total number of
// bytes sent over the network for |stream_| while it was open.
int64_t closed_stream_sent_bytes_ = 0;
// The request to send.
// Set to null before response body is starting to be read. This is to allow
// |this| to be shared for reading and to possibly outlive request_info_'s
// owner. Setting to null happens after headers are completely read or upload
// data stream is uploaded, whichever is later.
raw_ptr<const HttpRequestInfo> request_info_ = nullptr;
// |response_info_| is the HTTP response data object which is filled in
// when a response HEADERS comes in for the stream.
// It is not owned by this stream object, or point to |push_response_info_|.
raw_ptr<HttpResponseInfo> response_info_ = nullptr;
std::unique_ptr<HttpResponseInfo> push_response_info_;
bool response_headers_complete_ = false;
bool upload_stream_in_progress_ = false;
// We buffer the response body as it arrives asynchronously from the stream.
SpdyReadQueue response_body_queue_;
CompletionOnceCallback request_callback_;
CompletionOnceCallback response_callback_;
// User provided buffer for the ReadResponseBody() response.
scoped_refptr<IOBuffer> user_buffer_;
int user_buffer_len_ = 0;
// Temporary buffer used to read the request body from UploadDataStream.
scoped_refptr<IOBufferWithSize> request_body_buf_;
int request_body_buf_size_ = 0;
// Timer to execute DoBufferedReadCallback() with a delay.
base::OneShotTimer buffered_read_timer_;
bool was_alpn_negotiated_ = false;
// Stores any DNS aliases for the remote endpoint. Includes all known aliases,
// e.g. from A, AAAA, or HTTPS, not just from the address used for the
// connection, in no particular order. These are stored in the stream instead
// of the session due to complications related to IP-pooling.
std::set<std::string> dns_aliases_;
base::WeakPtrFactory<SpdyHttpStream> weak_factory_{this};
};
} // namespace net
#endif // NET_SPDY_SPDY_HTTP_STREAM_H_