Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(134)

Side by Side Diff: net/http/http_stream_parser.cc

Issue 1884943003: HttpStreamParser: Don't reuse sockets which receive unparsed data. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removed a bit too much, fix case with body Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_stream_parser.h" 5 #include "net/http/http_stream_parser.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 request_(request), 207 request_(request),
208 request_headers_(nullptr), 208 request_headers_(nullptr),
209 request_headers_length_(0), 209 request_headers_length_(0),
210 read_buf_(read_buffer), 210 read_buf_(read_buffer),
211 read_buf_unused_offset_(0), 211 read_buf_unused_offset_(0),
212 response_header_start_offset_(-1), 212 response_header_start_offset_(-1),
213 received_bytes_(0), 213 received_bytes_(0),
214 sent_bytes_(0), 214 sent_bytes_(0),
215 response_(nullptr), 215 response_(nullptr),
216 response_body_length_(-1), 216 response_body_length_(-1),
217 response_is_keep_alive_(false),
217 response_body_read_(0), 218 response_body_read_(0),
218 user_read_buf_(nullptr), 219 user_read_buf_(nullptr),
219 user_read_buf_len_(0), 220 user_read_buf_len_(0),
220 connection_(connection), 221 connection_(connection),
221 net_log_(net_log), 222 net_log_(net_log),
222 sent_last_chunk_(false), 223 sent_last_chunk_(false),
223 upload_error_(OK), 224 upload_error_(OK),
224 weak_ptr_factory_(this) { 225 weak_ptr_factory_(this) {
225 io_callback_ = base::Bind(&HttpStreamParser::OnIOComplete, 226 io_callback_ = base::Bind(&HttpStreamParser::OnIOComplete,
226 weak_ptr_factory_.GetWeakPtr()); 227 weak_ptr_factory_.GetWeakPtr());
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after
587 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); 588 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize);
588 589
589 // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL. 590 // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL.
590 // See if the user is passing in an IOBuffer with a NULL |data_|. 591 // See if the user is passing in an IOBuffer with a NULL |data_|.
591 CHECK(read_buf_->data()); 592 CHECK(read_buf_->data());
592 593
593 return connection_->socket() 594 return connection_->socket()
594 ->Read(read_buf_.get(), read_buf_->RemainingCapacity(), io_callback_); 595 ->Read(read_buf_.get(), read_buf_->RemainingCapacity(), io_callback_);
595 } 596 }
596 597
597 int HttpStreamParser::DoReadHeadersComplete(int result) { 598 int HttpStreamParser::DoReadHeadersComplete(int result) {
mmenke 2016/05/20 21:50:02 We could probably null out response_ now, whenever
598 // DoReadHeadersComplete is called with the result of Socket::Read, which is a 599 // DoReadHeadersComplete is called with the result of Socket::Read, which is a
599 // (byte_count | error), and returns (error | OK). 600 // (byte_count | error), and returns (error | OK).
600 601
601 result = HandleReadHeaderResult(result); 602 result = HandleReadHeaderResult(result);
602 603
603 // TODO(mmenke): The code below is ugly and hacky. A much better and more 604 // TODO(mmenke): The code below is ugly and hacky. A much better and more
604 // flexible long term solution would be to separate out the read and write 605 // flexible long term solution would be to separate out the read and write
605 // loops, though this would involve significant changes, both here and 606 // loops, though this would involve significant changes, both here and
606 // elsewhere (WebSockets, for instance). 607 // elsewhere (WebSockets, for instance).
607 608
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 863
863 if (end_of_header_offset == -1) { 864 if (end_of_header_offset == -1) {
864 io_state_ = STATE_READ_HEADERS; 865 io_state_ = STATE_READ_HEADERS;
865 // Prevent growing the headers buffer indefinitely. 866 // Prevent growing the headers buffer indefinitely.
866 if (read_buf_->offset() >= kMaxHeaderBufSize) { 867 if (read_buf_->offset() >= kMaxHeaderBufSize) {
867 io_state_ = STATE_DONE; 868 io_state_ = STATE_DONE;
868 return ERR_RESPONSE_HEADERS_TOO_BIG; 869 return ERR_RESPONSE_HEADERS_TOO_BIG;
869 } 870 }
870 } else { 871 } else {
871 CalculateResponseBodySize(); 872 CalculateResponseBodySize();
873
872 // If the body is zero length, the caller may not call ReadResponseBody, 874 // If the body is zero length, the caller may not call ReadResponseBody,
873 // which is where any extra data is copied to read_buf_, so we move the 875 // which is where any extra data is copied to read_buf_, so we move the
874 // data here. 876 // data here.
875 if (response_body_length_ == 0) { 877 if (response_body_length_ == 0) {
876 int extra_bytes = read_buf_->offset() - end_of_header_offset; 878 int extra_bytes = read_buf_->offset() - end_of_header_offset;
877 if (extra_bytes) { 879 if (extra_bytes) {
878 CHECK_GT(extra_bytes, 0); 880 CHECK_GT(extra_bytes, 0);
879 memmove(read_buf_->StartOfBuffer(), 881 memmove(read_buf_->StartOfBuffer(),
880 read_buf_->StartOfBuffer() + end_of_header_offset, 882 read_buf_->StartOfBuffer() + end_of_header_offset,
881 extra_bytes); 883 extra_bytes);
882 } 884 }
883 read_buf_->SetCapacity(extra_bytes); 885 read_buf_->SetCapacity(extra_bytes);
884 if (response_->headers->response_code() / 100 == 1) { 886 if (response_->headers->response_code() / 100 == 1) {
885 // After processing a 1xx response, the caller will ask for the next 887 // After processing a 1xx response, the caller will ask for the next
886 // header, so reset state to support that. We don't completely ignore a 888 // header, so reset state to support that. We don't completely ignore a
887 // 1xx response because it cannot be returned in reply to a CONNECT 889 // 1xx response because it cannot be returned in reply to a CONNECT
888 // request so we return OK here, which lets the caller inspect the 890 // request so we return OK here, which lets the caller inspect the
889 // response and reject it in the event that we're setting up a CONNECT 891 // response and reject it in the event that we're setting up a CONNECT
890 // tunnel. 892 // tunnel.
891 response_header_start_offset_ = -1; 893 response_header_start_offset_ = -1;
892 response_body_length_ = -1; 894 response_body_length_ = -1;
893 // Now waiting for the second set of headers to be read. 895 // Now waiting for the second set of headers to be read.
894 } else { 896 } else {
897 // Only set keep-alive based on final set of headers.
898 response_is_keep_alive_ = response_->headers->IsKeepAlive();
899
895 io_state_ = STATE_DONE; 900 io_state_ = STATE_DONE;
896 } 901 }
897 return OK; 902 return OK;
898 } 903 }
899 904
905 // Only set keep-alive based on final set of headers.
906 response_is_keep_alive_ = response_->headers->IsKeepAlive();
907
900 // Note where the headers stop. 908 // Note where the headers stop.
901 read_buf_unused_offset_ = end_of_header_offset; 909 read_buf_unused_offset_ = end_of_header_offset;
902 // Now waiting for the body to be read. 910 // Now waiting for the body to be read.
903 } 911 }
904 return OK; 912 return OK;
905 } 913 }
906 914
907 int HttpStreamParser::FindAndParseResponseHeaders() { 915 int HttpStreamParser::FindAndParseResponseHeaders() {
908 int end_offset = -1; 916 int end_offset = -1;
909 DCHECK_EQ(0, read_buf_unused_offset_); 917 DCHECK_EQ(0, read_buf_unused_offset_);
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
1080 reuse_type == ClientSocketHandle::UNUSED_IDLE; 1088 reuse_type == ClientSocketHandle::UNUSED_IDLE;
1081 } 1089 }
1082 1090
1083 void HttpStreamParser::SetConnectionReused() { 1091 void HttpStreamParser::SetConnectionReused() {
1084 connection_->set_reuse_type(ClientSocketHandle::REUSED_IDLE); 1092 connection_->set_reuse_type(ClientSocketHandle::REUSED_IDLE);
1085 } 1093 }
1086 1094
1087 bool HttpStreamParser::CanReuseConnection() const { 1095 bool HttpStreamParser::CanReuseConnection() const {
1088 if (!CanFindEndOfResponse()) 1096 if (!CanFindEndOfResponse())
1089 return false; 1097 return false;
1090 if (!response_->headers || !response_->headers->IsKeepAlive()) 1098
1099 if (!response_is_keep_alive_)
1091 return false; 1100 return false;
1101
1102 // Check if extra data was received after reading the entire response body. If
1103 // extra data was received reusing the socket is not a great idea. This does
1104 // have the down side of papering over certain server bugs, but seems to be
1105 // the best option here.
1106 //
1107 // TODO(mmenke): Consider logging this - hard to decipher socket reuse
1108 // behavior makes NetLogs harder to read.
1109 if (IsResponseBodyComplete() && read_buf_->offset() > 0)
asanka 2016/06/01 19:43:35 Is it possible for (read_buf_->offset() > 0) to be
mmenke 2016/06/02 15:56:23 Done. Good suggestion - it's much clearer.
1110 return false;
1111
1092 return connection_->socket() && connection_->socket()->IsConnected(); 1112 return connection_->socket() && connection_->socket()->IsConnected();
1093 } 1113 }
1094 1114
1095 void HttpStreamParser::GetSSLInfo(SSLInfo* ssl_info) { 1115 void HttpStreamParser::GetSSLInfo(SSLInfo* ssl_info) {
1096 if (request_->url.SchemeIsCryptographic() && connection_->socket()) { 1116 if (request_->url.SchemeIsCryptographic() && connection_->socket()) {
1097 SSLClientSocket* ssl_socket = 1117 SSLClientSocket* ssl_socket =
1098 static_cast<SSLClientSocket*>(connection_->socket()); 1118 static_cast<SSLClientSocket*>(connection_->socket());
1099 ssl_socket->GetSSLInfo(ssl_info); 1119 ssl_socket->GetSSLInfo(ssl_info);
1100 } 1120 }
1101 } 1121 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1160 } 1180 }
1161 1181
1162 void HttpStreamParser::ValidateStatusLine(const std::string& status_line) { 1182 void HttpStreamParser::ValidateStatusLine(const std::string& status_line) {
1163 HttpStatusLineValidator::StatusLineStatus status = 1183 HttpStatusLineValidator::StatusLineStatus status =
1164 HttpStatusLineValidator::ValidateStatusLine(status_line); 1184 HttpStatusLineValidator::ValidateStatusLine(status_line);
1165 UMA_HISTOGRAM_ENUMERATION("Net.HttpStatusLineStatus", status, 1185 UMA_HISTOGRAM_ENUMERATION("Net.HttpStatusLineStatus", status,
1166 HttpStatusLineValidator::STATUS_LINE_MAX); 1186 HttpStatusLineValidator::STATUS_LINE_MAX);
1167 } 1187 }
1168 1188
1169 } // namespace net 1189 } // namespace net
OLDNEW
« net/http/http_network_transaction_unittest.cc ('K') | « net/http/http_stream_parser.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698