Land Recent QUIC Changes until 04/30/2015.
[chromium-blink-merge.git] / net / tools / quic / quic_spdy_client_stream.cc
blobe7c234255c034fee9f07144356cfe35dde41f946
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);
49 uint32 QuicSpdyClientStream::ProcessData(const char* data, uint32 data_len) {
50 if (!headers_decompressed()) {
51 // Let the headers data accumulate in the underlying QuicDataStream.
52 return 0;
54 if (response_headers_.empty()) {
55 if (!ParseResponseHeaders(data, data_len)) {
56 // Headers were invalid.
57 Reset(QUIC_BAD_APPLICATION_PAYLOAD);
58 return 0;
60 } else {
61 data_.append(data, data_len);
63 DCHECK(!response_headers_.empty());
64 if (content_length_ >= 0 &&
65 static_cast<int>(data_.size()) > content_length_) {
66 Reset(QUIC_BAD_APPLICATION_PAYLOAD);
67 return 0;
69 DVLOG(1) << "Client processed " << data_len << " bytes for stream " << id();
70 return data_len;
73 bool QuicSpdyClientStream::ParseResponseHeaders(const char* data,
74 uint32 data_len) {
75 DCHECK(headers_decompressed());
76 SpdyFramer framer(SPDY3);
77 size_t len = framer.ParseHeaderBlockInBuffer(data,
78 data_len,
79 &response_headers_);
80 DCHECK_LE(len, data_len);
81 if (len == 0 || response_headers_.empty()) {
82 return false; // Headers were invalid.
85 if (data_len > len) {
86 data_.append(data + len, data_len - len);
88 if (ContainsKey(response_headers_, "content-length") &&
89 !StringToInt(response_headers_["content-length"], &content_length_)) {
90 return false; // Invalid content-length.
92 string status = response_headers_[":status"];
93 size_t end = status.find(" ");
94 if (end != string::npos) {
95 status.erase(end);
97 if (!StringToInt(status, &response_code_)) {
98 return false; // Invalid response code.
100 return true;
103 size_t QuicSpdyClientStream::SendRequest(const SpdyHeaderBlock& headers,
104 StringPiece body,
105 bool fin) {
106 bool send_fin_with_headers = fin && body.empty();
107 size_t bytes_sent = body.size();
108 header_bytes_written_ =
109 WriteHeaders(headers, send_fin_with_headers, nullptr);
110 bytes_sent += header_bytes_written_;
112 if (!body.empty()) {
113 WriteOrBufferData(body, fin, nullptr);
116 return bytes_sent;
119 void QuicSpdyClientStream::SendBody(const string& data, bool fin) {
120 SendBody(data, fin, nullptr);
123 void QuicSpdyClientStream::SendBody(
124 const string& data, bool fin,
125 QuicAckNotifier::DelegateInterface* delegate) {
126 WriteOrBufferData(data, fin, delegate);
129 } // namespace tools
130 } // namespace net