1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/http/http_basic_state.h"
6
7 #include <set>
8 #include <utility>
9
10 #include "base/check_op.h"
11 #include "base/no_destructor.h"
12 #include "net/base/io_buffer.h"
13 #include "net/base/ip_endpoint.h"
14 #include "net/base/load_timing_info.h"
15 #include "net/base/net_errors.h"
16 #include "net/http/http_request_info.h"
17 #include "net/http/http_response_body_drainer.h"
18 #include "net/http/http_stream_parser.h"
19 #include "net/http/http_util.h"
20 #include "net/socket/stream_socket.h"
21 #include "net/socket/stream_socket_handle.h"
22 #include "net/ssl/ssl_info.h"
23 #include "url/gurl.h"
24
25 namespace net {
26
HttpBasicState(std::unique_ptr<StreamSocketHandle> connection,bool is_for_get_to_http_proxy)27 HttpBasicState::HttpBasicState(std::unique_ptr<StreamSocketHandle> connection,
28 bool is_for_get_to_http_proxy)
29 : read_buf_(base::MakeRefCounted<GrowableIOBuffer>()),
30 connection_(std::move(connection)),
31 is_for_get_to_http_proxy_(is_for_get_to_http_proxy) {
32 CHECK(connection_) << "StreamSocketHandle passed to HttpBasicState must "
33 "not be NULL. See crbug.com/790776";
34 }
35
36 HttpBasicState::~HttpBasicState() = default;
37
Initialize(const HttpRequestInfo * request_info,RequestPriority priority,const NetLogWithSource & net_log)38 void HttpBasicState::Initialize(const HttpRequestInfo* request_info,
39 RequestPriority priority,
40 const NetLogWithSource& net_log) {
41 DCHECK(!parser_.get());
42 traffic_annotation_ = request_info->traffic_annotation;
43 parser_ = std::make_unique<HttpStreamParser>(
44 connection_->socket(),
45 connection_->reuse_type() ==
46 StreamSocketHandle::SocketReuseType::kReusedIdle,
47 request_info->url, request_info->method, request_info->upload_data_stream,
48 read_buf_.get(), net_log);
49 }
50
Close(bool not_reusable)51 void HttpBasicState::Close(bool not_reusable) {
52 // `parser_` is null if the owner of `this` is created by an orphaned
53 // HttpStreamFactory::Job in which case InitializeStream() will not have been
54 // called. This also protects against null dereference in the case where
55 // ReleaseConnection() has been called.
56 //
57 // TODO(mmenke): Can these cases be handled a bit more cleanly?
58 if (!parser_) {
59 return;
60 }
61 StreamSocket* socket = connection_->socket();
62 if (not_reusable && socket) {
63 socket->Disconnect();
64 }
65 parser()->OnConnectionClose();
66 connection_->Reset();
67 }
68
ReleaseConnection()69 std::unique_ptr<StreamSocketHandle> HttpBasicState::ReleaseConnection() {
70 // The HttpStreamParser object still has a pointer to the connection. Just to
71 // be extra-sure it doesn't touch the connection again, delete it here rather
72 // than leaving it until the destructor is called.
73 parser_.reset();
74 return std::move(connection_);
75 }
76
read_buf() const77 scoped_refptr<GrowableIOBuffer> HttpBasicState::read_buf() const {
78 return read_buf_;
79 }
80
GenerateRequestLine() const81 std::string HttpBasicState::GenerateRequestLine() const {
82 return HttpUtil::GenerateRequestLine(parser_->method(), parser_->url(),
83 is_for_get_to_http_proxy_);
84 }
85
IsConnectionReused() const86 bool HttpBasicState::IsConnectionReused() const {
87 return connection_->reuse_type() ==
88 StreamSocketHandle::SocketReuseType::kReusedIdle ||
89 connection_->reuse_type() ==
90 StreamSocketHandle::SocketReuseType::kUnusedIdle;
91 }
92
SetConnectionReused()93 void HttpBasicState::SetConnectionReused() {
94 connection_->set_reuse_type(StreamSocketHandle::SocketReuseType::kReusedIdle);
95 }
96
CanReuseConnection() const97 bool HttpBasicState::CanReuseConnection() const {
98 return parser_ && connection_->socket() && parser_->CanReuseConnection();
99 }
100
GetLoadTimingInfo(LoadTimingInfo * load_timing_info) const101 bool HttpBasicState::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const {
102 return connection_->GetLoadTimingInfo(IsConnectionReused(), load_timing_info);
103 }
104
GetSSLInfo(SSLInfo * ssl_info)105 void HttpBasicState::GetSSLInfo(SSLInfo* ssl_info) {
106 CHECK(connection_);
107 if (!connection_->socket() || !connection_->socket()->GetSSLInfo(ssl_info)) {
108 *ssl_info = SSLInfo();
109 }
110 }
111
GetRemoteEndpoint(IPEndPoint * endpoint)112 int HttpBasicState::GetRemoteEndpoint(IPEndPoint* endpoint) {
113 if (!connection_ || !connection_->socket()) {
114 return ERR_SOCKET_NOT_CONNECTED;
115 }
116 return connection_->socket()->GetPeerAddress(endpoint);
117 }
118
GetDnsAliases() const119 const std::set<std::string>& HttpBasicState::GetDnsAliases() const {
120 static const base::NoDestructor<std::set<std::string>> emptyset_result;
121 return (connection_ && connection_->socket())
122 ? connection_->socket()->GetDnsAliases()
123 : *emptyset_result;
124 }
125
126 } // namespace net
127