1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/tools/quic/quic_spdy_client_stream.h"
#include "net/spdy/spdy_framer.h"
#include "net/tools/quic/quic_client_session.h"
#include "net/tools/quic/spdy_utils.h"
using base::StringPiece;
using std::string;
namespace net {
namespace tools {
static const size_t kHeaderBufInitialSize = 4096;
QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id,
QuicClientSession* session)
: QuicDataStream(id, session),
read_buf_(new GrowableIOBuffer()),
response_headers_received_(false),
header_bytes_read_(0),
header_bytes_written_(0) {
}
QuicSpdyClientStream::~QuicSpdyClientStream() {
}
bool QuicSpdyClientStream::OnStreamFrame(const QuicStreamFrame& frame) {
if (!write_side_closed()) {
DVLOG(1) << "Got a response before the request was complete. "
<< "Aborting request.";
CloseWriteSide();
}
return QuicDataStream::OnStreamFrame(frame);
}
void QuicSpdyClientStream::OnStreamHeadersComplete(bool fin,
size_t frame_len) {
header_bytes_read_ = frame_len;
QuicDataStream::OnStreamHeadersComplete(fin, frame_len);
}
uint32 QuicSpdyClientStream::ProcessData(const char* data,
uint32 data_len) {
int total_bytes_processed = 0;
// Are we still reading the response headers.
if (!response_headers_received_) {
// Grow the read buffer if necessary.
if (read_buf_->RemainingCapacity() < (int)data_len) {
read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize);
}
memcpy(read_buf_->data(), data, data_len);
read_buf_->set_offset(read_buf_->offset() + data_len);
ParseResponseHeaders();
} else {
data_.append(data + total_bytes_processed,
data_len - total_bytes_processed);
}
return data_len;
}
void QuicSpdyClientStream::OnFinRead() {
ReliableQuicStream::OnFinRead();
if (!response_headers_received_) {
Reset(QUIC_BAD_APPLICATION_PAYLOAD);
} else if ((headers().content_length_status() ==
BalsaHeadersEnums::VALID_CONTENT_LENGTH) &&
data_.size() != headers().content_length()) {
Reset(QUIC_BAD_APPLICATION_PAYLOAD);
}
}
ssize_t QuicSpdyClientStream::SendRequest(const BalsaHeaders& headers,
StringPiece body,
bool fin) {
SpdyHeaderBlock header_block =
SpdyUtils::RequestHeadersToSpdyHeaders(headers);
bool send_fin_with_headers = fin && body.empty();
size_t bytes_sent = body.size();
header_bytes_written_ = WriteHeaders(header_block, send_fin_with_headers);
bytes_sent += header_bytes_written_;
if (!body.empty()) {
WriteOrBufferData(body, fin);
}
return bytes_sent;
}
int QuicSpdyClientStream::ParseResponseHeaders() {
size_t read_buf_len = static_cast<size_t>(read_buf_->offset());
SpdyFramer framer(SPDY3);
SpdyHeaderBlock headers;
char* data = read_buf_->StartOfBuffer();
size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(),
&headers);
if (len == 0) {
return -1;
}
if (!SpdyUtils::FillBalsaResponseHeaders(headers, &headers_)) {
Reset(QUIC_BAD_APPLICATION_PAYLOAD);
return -1;
}
response_headers_received_ = true;
size_t delta = read_buf_len - len;
if (delta > 0) {
data_.append(data + len, delta);
}
return len;
}
// Sends body data to the server and returns the number of bytes sent.
void QuicSpdyClientStream::SendBody(const string& data, bool fin) {
WriteOrBufferData(data, fin);
}
} // namespace tools
} // namespace net
|