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 "net/spdy/spdy_framer.h"
8 #include "net/tools/quic/quic_client_session.h"
9 #include "net/tools/quic/spdy_utils.h"
11 using base::StringPiece
;
17 static const size_t kHeaderBufInitialSize
= 4096;
19 QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id
,
20 QuicClientSession
* session
)
21 : QuicDataStream(id
, session
),
22 read_buf_(new GrowableIOBuffer()),
23 response_headers_received_(false),
24 header_bytes_read_(0),
25 header_bytes_written_(0) {
28 QuicSpdyClientStream::~QuicSpdyClientStream() {
31 void QuicSpdyClientStream::OnStreamFrame(const QuicStreamFrame
& frame
) {
32 if (!write_side_closed()) {
33 DVLOG(1) << "Got a response before the request was complete. "
34 << "Aborting request.";
37 QuicDataStream::OnStreamFrame(frame
);
40 void QuicSpdyClientStream::OnStreamHeadersComplete(bool fin
,
42 header_bytes_read_
= frame_len
;
43 QuicDataStream::OnStreamHeadersComplete(fin
, frame_len
);
46 uint32
QuicSpdyClientStream::ProcessData(const char* data
,
48 int total_bytes_processed
= 0;
50 // Are we still reading the response headers.
51 if (!response_headers_received_
) {
52 // Grow the read buffer if necessary.
53 if (read_buf_
->RemainingCapacity() < (int)data_len
) {
54 read_buf_
->SetCapacity(read_buf_
->capacity() + kHeaderBufInitialSize
);
56 memcpy(read_buf_
->data(), data
, data_len
);
57 read_buf_
->set_offset(read_buf_
->offset() + data_len
);
58 ParseResponseHeaders();
60 data_
.append(data
+ total_bytes_processed
,
61 data_len
- total_bytes_processed
);
66 void QuicSpdyClientStream::OnFinRead() {
67 ReliableQuicStream::OnFinRead();
68 if (!response_headers_received_
) {
69 Reset(QUIC_BAD_APPLICATION_PAYLOAD
);
70 } else if ((headers().content_length_status() ==
71 BalsaHeadersEnums::VALID_CONTENT_LENGTH
) &&
72 data_
.size() != headers().content_length()) {
73 Reset(QUIC_BAD_APPLICATION_PAYLOAD
);
77 ssize_t
QuicSpdyClientStream::SendRequest(const BalsaHeaders
& headers
,
80 SpdyHeaderBlock header_block
=
81 SpdyUtils::RequestHeadersToSpdyHeaders(headers
);
83 bool send_fin_with_headers
= fin
&& body
.empty();
84 size_t bytes_sent
= body
.size();
85 header_bytes_written_
= WriteHeaders(
86 header_block
, send_fin_with_headers
, NULL
);
87 bytes_sent
+= header_bytes_written_
;
90 WriteOrBufferData(body
, fin
, NULL
);
96 int QuicSpdyClientStream::ParseResponseHeaders() {
97 size_t read_buf_len
= static_cast<size_t>(read_buf_
->offset());
98 SpdyFramer
framer(SPDY3
);
99 SpdyHeaderBlock headers
;
100 char* data
= read_buf_
->StartOfBuffer();
101 size_t len
= framer
.ParseHeaderBlockInBuffer(data
, read_buf_
->offset(),
107 if (!SpdyUtils::FillBalsaResponseHeaders(headers
, &headers_
)) {
108 Reset(QUIC_BAD_APPLICATION_PAYLOAD
);
111 response_headers_received_
= true;
113 size_t delta
= read_buf_len
- len
;
115 data_
.append(data
+ len
, delta
);
121 // Sends body data to the server and returns the number of bytes sent.
122 void QuicSpdyClientStream::SendBody(const string
& data
, bool fin
) {
123 WriteOrBufferData(data
, fin
, NULL
);