OLD | NEW |
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/tools/quic/quic_spdy_client_stream.h" | 5 #include "net/tools/quic/quic_spdy_client_stream.h" |
6 | 6 |
7 #include "net/spdy/spdy_framer.h" | 7 #include "net/spdy/spdy_framer.h" |
8 #include "net/tools/quic/quic_client_session.h" | 8 #include "net/tools/quic/quic_client_session.h" |
9 #include "net/tools/quic/spdy_utils.h" | 9 #include "net/tools/quic/spdy_utils.h" |
10 | 10 |
11 using base::StringPiece; | 11 using base::StringPiece; |
12 using std::string; | 12 using std::string; |
13 | 13 |
14 namespace net { | 14 namespace net { |
15 namespace tools { | 15 namespace tools { |
16 | 16 |
17 static const size_t kHeaderBufInitialSize = 4096; | 17 static const size_t kHeaderBufInitialSize = 4096; |
18 | 18 |
19 QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id, | 19 QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id, |
20 QuicClientSession* session) | 20 QuicClientSession* session) |
21 : QuicReliableClientStream(id, session), | 21 : QuicDataStream(id, session), |
22 read_buf_(new GrowableIOBuffer()), | 22 read_buf_(new GrowableIOBuffer()), |
23 response_headers_received_(false) { | 23 response_headers_received_(false) { |
24 } | 24 } |
25 | 25 |
26 QuicSpdyClientStream::~QuicSpdyClientStream() { | 26 QuicSpdyClientStream::~QuicSpdyClientStream() { |
27 } | 27 } |
28 | 28 |
| 29 bool QuicSpdyClientStream::OnStreamFrame(const QuicStreamFrame& frame) { |
| 30 if (!write_side_closed()) { |
| 31 DLOG(INFO) << "Got a response before the request was complete. " |
| 32 << "Aborting request."; |
| 33 CloseWriteSide(); |
| 34 } |
| 35 return QuicDataStream::OnStreamFrame(frame); |
| 36 } |
| 37 |
29 uint32 QuicSpdyClientStream::ProcessData(const char* data, uint32 length) { | 38 uint32 QuicSpdyClientStream::ProcessData(const char* data, uint32 length) { |
30 uint32 total_bytes_processed = 0; | 39 uint32 total_bytes_processed = 0; |
31 | 40 |
32 // Are we still reading the response headers. | 41 // Are we still reading the response headers. |
33 if (!response_headers_received_) { | 42 if (!response_headers_received_) { |
34 // Grow the read buffer if necessary. | 43 // Grow the read buffer if necessary. |
35 if (read_buf_->RemainingCapacity() < (int)length) { | 44 if (read_buf_->RemainingCapacity() < (int)length) { |
36 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); | 45 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); |
37 } | 46 } |
38 memcpy(read_buf_->data(), data, length); | 47 memcpy(read_buf_->data(), data, length); |
39 read_buf_->set_offset(read_buf_->offset() + length); | 48 read_buf_->set_offset(read_buf_->offset() + length); |
40 ParseResponseHeaders(); | 49 ParseResponseHeaders(); |
41 } else { | 50 } else { |
42 mutable_data()->append(data + total_bytes_processed, | 51 data_.append(data + total_bytes_processed, length - total_bytes_processed); |
43 length - total_bytes_processed); | |
44 } | 52 } |
45 return length; | 53 return length; |
46 } | 54 } |
47 | 55 |
48 void QuicSpdyClientStream::OnFinRead() { | 56 void QuicSpdyClientStream::OnFinRead() { |
49 ReliableQuicStream::OnFinRead(); | 57 ReliableQuicStream::OnFinRead(); |
50 if (!response_headers_received_) { | 58 if (!response_headers_received_) { |
51 Reset(QUIC_BAD_APPLICATION_PAYLOAD); | 59 Reset(QUIC_BAD_APPLICATION_PAYLOAD); |
52 } else if ((headers().content_length_status() == | 60 } else if ((headers().content_length_status() == |
53 BalsaHeadersEnums::VALID_CONTENT_LENGTH) && | 61 BalsaHeadersEnums::VALID_CONTENT_LENGTH) && |
54 mutable_data()->size() != headers().content_length()) { | 62 data_.size() != headers().content_length()) { |
55 Reset(QUIC_BAD_APPLICATION_PAYLOAD); | 63 Reset(QUIC_BAD_APPLICATION_PAYLOAD); |
56 } | 64 } |
57 } | 65 } |
58 | 66 |
59 ssize_t QuicSpdyClientStream::SendRequest(const BalsaHeaders& headers, | 67 ssize_t QuicSpdyClientStream::SendRequest(const BalsaHeaders& headers, |
60 StringPiece body, | 68 StringPiece body, |
61 bool fin) { | 69 bool fin) { |
62 SpdyHeaderBlock header_block = | 70 SpdyHeaderBlock header_block = |
63 SpdyUtils::RequestHeadersToSpdyHeaders(headers); | 71 SpdyUtils::RequestHeadersToSpdyHeaders(headers); |
64 | 72 |
| 73 bool send_fin_with_headers = fin && body.empty(); |
65 string headers_string = session()->compressor()->CompressHeadersWithPriority( | 74 string headers_string = session()->compressor()->CompressHeadersWithPriority( |
66 priority(), header_block); | 75 priority(), header_block); |
| 76 WriteOrBufferData(headers_string, send_fin_with_headers); |
67 | 77 |
68 bool has_body = !body.empty(); | 78 if (!body.empty()) { |
69 | 79 WriteOrBufferData(body, fin); |
70 WriteData(headers_string, fin && !has_body); // last_data | |
71 | |
72 if (has_body) { | |
73 WriteData(body, fin); | |
74 } | 80 } |
75 | 81 |
76 return headers_string.size() + body.size(); | 82 return headers_string.size() + body.size(); |
77 } | 83 } |
78 | 84 |
79 int QuicSpdyClientStream::ParseResponseHeaders() { | 85 int QuicSpdyClientStream::ParseResponseHeaders() { |
80 size_t read_buf_len = static_cast<size_t>(read_buf_->offset()); | 86 size_t read_buf_len = static_cast<size_t>(read_buf_->offset()); |
81 SpdyFramer framer(SPDY3); | 87 SpdyFramer framer(SPDY3); |
82 SpdyHeaderBlock headers; | 88 SpdyHeaderBlock headers; |
83 char* data = read_buf_->StartOfBuffer(); | 89 char* data = read_buf_->StartOfBuffer(); |
84 size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(), | 90 size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(), |
85 &headers); | 91 &headers); |
86 if (len == 0) { | 92 if (len == 0) { |
87 return -1; | 93 return -1; |
88 } | 94 } |
89 | 95 |
90 if (!SpdyUtils::FillBalsaResponseHeaders(headers, mutable_headers())) { | 96 if (!SpdyUtils::FillBalsaResponseHeaders(headers, &headers_)) { |
91 Reset(QUIC_BAD_APPLICATION_PAYLOAD); | 97 Reset(QUIC_BAD_APPLICATION_PAYLOAD); |
92 return -1; | 98 return -1; |
93 } | 99 } |
94 response_headers_received_ = true; | 100 response_headers_received_ = true; |
95 | 101 |
96 size_t delta = read_buf_len - len; | 102 size_t delta = read_buf_len - len; |
97 if (delta > 0) { | 103 if (delta > 0) { |
98 mutable_data()->append(data + len, delta); | 104 data_.append(data + len, delta); |
99 } | 105 } |
100 | 106 |
101 return len; | 107 return len; |
102 } | 108 } |
103 | 109 |
| 110 // Sends body data to the server and returns the number of bytes sent. |
| 111 void QuicSpdyClientStream::SendBody(const string& data, bool fin) { |
| 112 return WriteOrBufferData(data, fin); |
| 113 } |
| 114 |
104 } // namespace tools | 115 } // namespace tools |
105 } // namespace net | 116 } // namespace net |
OLD | NEW |