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 : QuicReliableClientStream(id
, session
),
22 read_buf_(new GrowableIOBuffer()),
23 response_headers_received_(false) {
26 QuicSpdyClientStream::~QuicSpdyClientStream() {
29 uint32
QuicSpdyClientStream::ProcessData(const char* data
, uint32 length
) {
30 uint32 total_bytes_processed
= 0;
32 // Are we still reading the response headers.
33 if (!response_headers_received_
) {
34 // Grow the read buffer if necessary.
35 if (read_buf_
->RemainingCapacity() < (int)length
) {
36 read_buf_
->SetCapacity(read_buf_
->capacity() + kHeaderBufInitialSize
);
38 memcpy(read_buf_
->data(), data
, length
);
39 read_buf_
->set_offset(read_buf_
->offset() + length
);
40 ParseResponseHeaders();
42 mutable_data()->append(data
+ total_bytes_processed
,
43 length
- total_bytes_processed
);
48 void QuicSpdyClientStream::TerminateFromPeer(bool half_close
) {
49 ReliableQuicStream::TerminateFromPeer(half_close
);
50 if (!response_headers_received_
) {
51 Close(QUIC_BAD_APPLICATION_PAYLOAD
);
52 } else if ((headers().content_length_status() ==
53 BalsaHeadersEnums::VALID_CONTENT_LENGTH
) &&
54 mutable_data()->size() != headers().content_length()) {
55 Close(QUIC_BAD_APPLICATION_PAYLOAD
);
59 ssize_t
QuicSpdyClientStream::SendRequest(const BalsaHeaders
& headers
,
62 SpdyHeaderBlock header_block
=
63 SpdyUtils::RequestHeadersToSpdyHeaders(headers
);
65 string headers_string
=
66 session()->compressor()->CompressHeaders(header_block
);
68 bool has_body
= !body
.empty();
70 WriteData(headers_string
, fin
&& !has_body
); // last_data
76 return headers_string
.size() + body
.size();
79 int QuicSpdyClientStream::ParseResponseHeaders() {
80 size_t read_buf_len
= static_cast<size_t>(read_buf_
->offset());
81 SpdyFramer
framer(SPDY3
);
82 SpdyHeaderBlock headers
;
83 char* data
= read_buf_
->StartOfBuffer();
84 size_t len
= framer
.ParseHeaderBlockInBuffer(data
, read_buf_
->offset(),
90 if (!SpdyUtils::FillBalsaResponseHeaders(headers
, mutable_headers())) {
91 Close(QUIC_BAD_APPLICATION_PAYLOAD
);
95 size_t delta
= read_buf_len
- len
;
97 mutable_data()->append(data
+ len
, delta
);