Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / net / tools / quic / quic_spdy_client_stream.cc
blobe89b925ba380c890cb471b5e2c78af860d422e50
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
3 // found in the LICENSE file.
5 #include "net/tools/quic/quic_spdy_client_stream.h"
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "net/quic/spdy_utils.h"
11 #include "net/spdy/spdy_protocol.h"
12 #include "net/tools/quic/quic_client_session.h"
13 #include "net/tools/quic/spdy_balsa_utils.h"
15 using base::StringPiece;
16 using std::string;
17 using base::StringToInt;
19 namespace net {
20 namespace tools {
22 QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id,
23 QuicClientSession* session)
24 : QuicDataStream(id, session),
25 content_length_(-1),
26 response_code_(0),
27 header_bytes_read_(0),
28 header_bytes_written_(0) {
31 QuicSpdyClientStream::~QuicSpdyClientStream() {
34 void QuicSpdyClientStream::OnStreamFrame(const QuicStreamFrame& frame) {
35 if (!write_side_closed()) {
36 DVLOG(1) << "Got a response before the request was complete. "
37 << "Aborting request.";
38 CloseWriteSide();
40 QuicDataStream::OnStreamFrame(frame);
43 void QuicSpdyClientStream::OnStreamHeadersComplete(bool fin,
44 size_t frame_len) {
45 header_bytes_read_ = frame_len;
46 QuicDataStream::OnStreamHeadersComplete(fin, frame_len);
47 if (!ParseResponseHeaders(decompressed_headers().data(),
48 decompressed_headers().length())) {
49 Reset(QUIC_BAD_APPLICATION_PAYLOAD);
50 return;
52 MarkHeadersConsumed(decompressed_headers().length());
55 void QuicSpdyClientStream::OnDataAvailable() {
56 while (HasBytesToRead()) {
57 struct iovec iov;
58 if (GetReadableRegions(&iov, 1) == 0) {
59 // No more data to read.
60 break;
62 DVLOG(1) << "Client processed " << iov.iov_len << " bytes for stream "
63 << id();
64 data_.append(static_cast<char*>(iov.iov_base), iov.iov_len);
66 if (content_length_ >= 0 &&
67 static_cast<int>(data_.size()) > content_length_) {
68 Reset(QUIC_BAD_APPLICATION_PAYLOAD);
69 return;
71 MarkConsumed(iov.iov_len);
73 if (sequencer()->IsClosed()) {
74 OnFinRead();
75 } else {
76 sequencer()->SetUnblocked();
80 bool QuicSpdyClientStream::ParseResponseHeaders(const char* data,
81 uint32 data_len) {
82 DCHECK(headers_decompressed());
83 SpdyFramer framer(HTTP2);
84 size_t len = framer.ParseHeaderBlockInBuffer(data,
85 data_len,
86 &response_headers_);
87 DCHECK_LE(len, data_len);
88 if (len == 0 || response_headers_.empty()) {
89 return false; // Headers were invalid.
92 if (data_len > len) {
93 data_.append(data + len, data_len - len);
95 if (ContainsKey(response_headers_, "content-length") &&
96 !StringToInt(response_headers_["content-length"], &content_length_)) {
97 return false; // Invalid content-length.
99 string status = response_headers_[":status"];
100 size_t end = status.find(" ");
101 if (end != string::npos) {
102 status.erase(end);
104 if (!StringToInt(status, &response_code_)) {
105 return false; // Invalid response code.
107 return true;
110 size_t QuicSpdyClientStream::SendRequest(const SpdyHeaderBlock& headers,
111 StringPiece body,
112 bool fin) {
113 bool send_fin_with_headers = fin && body.empty();
114 size_t bytes_sent = body.size();
115 header_bytes_written_ =
116 WriteHeaders(headers, send_fin_with_headers, nullptr);
117 bytes_sent += header_bytes_written_;
119 if (!body.empty()) {
120 WriteOrBufferData(body, fin, nullptr);
123 return bytes_sent;
126 void QuicSpdyClientStream::SendBody(const string& data, bool fin) {
127 SendBody(data, fin, nullptr);
130 void QuicSpdyClientStream::SendBody(
131 const string& data, bool fin,
132 QuicAckNotifier::DelegateInterface* delegate) {
133 WriteOrBufferData(data, fin, delegate);
136 } // namespace tools
137 } // namespace net