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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
|
// 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.
#ifndef NET_SPDY_BUFFERED_SPDY_FRAMER_H_
#define NET_SPDY_BUFFERED_SPDY_FRAMER_H_
#include <string>
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/net_export.h"
#include "net/spdy/spdy_framer.h"
#include "net/spdy/spdy_header_block.h"
#include "net/spdy/spdy_protocol.h"
namespace net {
class NET_EXPORT_PRIVATE BufferedSpdyFramerVisitorInterface {
public:
BufferedSpdyFramerVisitorInterface() {}
// Called if an error is detected in the SpdyFrame protocol.
virtual void OnError(SpdyFramer::SpdyError error_code) = 0;
// Called if an error is detected in a SPDY stream.
virtual void OnStreamError(SpdyStreamId stream_id,
const std::string& description) = 0;
// Called after all the header data for SYN_STREAM control frame is received.
virtual void OnSynStream(SpdyStreamId stream_id,
SpdyStreamId associated_stream_id,
SpdyPriority priority,
uint8 credential_slot,
bool fin,
bool unidirectional,
const SpdyHeaderBlock& headers) = 0;
// Called after all the header data for SYN_REPLY control frame is received.
virtual void OnSynReply(SpdyStreamId stream_id,
bool fin,
const SpdyHeaderBlock& headers) = 0;
// Called after all the header data for HEADERS control frame is received.
virtual void OnHeaders(SpdyStreamId stream_id,
bool fin,
const SpdyHeaderBlock& headers) = 0;
// Called when data is received.
// |stream_id| The stream receiving data.
// |data| A buffer containing the data received.
// |len| The length of the data buffer.
// When the other side has finished sending data on this stream,
// this method will be called with a zero-length buffer.
virtual void OnStreamFrameData(SpdyStreamId stream_id,
const char* data,
size_t len,
SpdyDataFlags flags) = 0;
// Called when an individual setting within a SETTINGS frame has been parsed
// and validated.
virtual void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) = 0;
// Called when a PING frame has been parsed.
virtual void OnPing(uint32 unique_id) = 0;
// Called when a RST_STREAM frame has been parsed.
virtual void OnRstStream(SpdyStreamId stream_id, SpdyStatusCodes status) = 0;
// Called when a GOAWAY frame has been parsed.
virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
SpdyGoAwayStatus status) = 0;
// Called when a WINDOW_UPDATE frame has been parsed.
virtual void OnWindowUpdate(SpdyStreamId stream_id,
int delta_window_size) = 0;
// Called after a control frame has been compressed to allow the visitor
// to record compression statistics.
virtual void OnControlFrameCompressed(
const SpdyControlFrame& uncompressed_frame,
const SpdyControlFrame& compressed_frame) = 0;
protected:
virtual ~BufferedSpdyFramerVisitorInterface() {}
private:
DISALLOW_COPY_AND_ASSIGN(BufferedSpdyFramerVisitorInterface);
};
class NET_EXPORT_PRIVATE BufferedSpdyFramer
: public SpdyFramerVisitorInterface {
public:
BufferedSpdyFramer(int version,
bool enable_compression);
virtual ~BufferedSpdyFramer();
// Sets callbacks to be called from the buffered spdy framer. A visitor must
// be set, or else the framer will likely crash. It is acceptable for the
// visitor to do nothing. If this is called multiple times, only the last
// visitor will be used.
void set_visitor(BufferedSpdyFramerVisitorInterface* visitor);
// SpdyFramerVisitorInterface
virtual void OnError(SpdyFramer* spdy_framer) OVERRIDE;
virtual void OnSynStream(SpdyStreamId stream_id,
SpdyStreamId associated_stream_id,
SpdyPriority priority,
uint8 credential_slot,
bool fin,
bool unidirectional) OVERRIDE;
virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE;
virtual void OnHeaders(SpdyStreamId stream_id, bool fin) OVERRIDE;
virtual bool OnCredentialFrameData(const char* frame_data,
size_t len) OVERRIDE;
virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
const char* header_data,
size_t len) OVERRIDE;
virtual void OnStreamFrameData(SpdyStreamId stream_id,
const char* data,
size_t len,
SpdyDataFlags flags) OVERRIDE;
virtual void OnSetting(
SpdySettingsIds id, uint8 flags, uint32 value) OVERRIDE;
virtual void OnPing(uint32 unique_id) OVERRIDE;
virtual void OnRstStream(SpdyStreamId stream_id,
SpdyStatusCodes status) OVERRIDE;
virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
SpdyGoAwayStatus status) OVERRIDE;
virtual void OnWindowUpdate(SpdyStreamId stream_id,
int delta_window_size) OVERRIDE;
virtual void OnDataFrameHeader(const SpdyDataFrame* frame) OVERRIDE;
// Called after a control frame has been compressed to allow the visitor
// to record compression statistics.
virtual void OnControlFrameCompressed(
const SpdyControlFrame& uncompressed_frame,
const SpdyControlFrame& compressed_frame) OVERRIDE;
// SpdyFramer methods.
size_t ProcessInput(const char* data, size_t len);
int protocol_version();
void Reset();
SpdyFramer::SpdyError error_code() const;
SpdyFramer::SpdyState state() const;
bool MessageFullyRead();
bool HasError();
SpdySynStreamControlFrame* CreateSynStream(SpdyStreamId stream_id,
SpdyStreamId associated_stream_id,
SpdyPriority priority,
uint8 credential_slot,
SpdyControlFlags flags,
bool compressed,
const SpdyHeaderBlock* headers);
SpdySynReplyControlFrame* CreateSynReply(SpdyStreamId stream_id,
SpdyControlFlags flags,
bool compressed,
const SpdyHeaderBlock* headers);
SpdyRstStreamControlFrame* CreateRstStream(SpdyStreamId stream_id,
SpdyStatusCodes status) const;
SpdySettingsControlFrame* CreateSettings(const SettingsMap& values) const;
SpdyPingControlFrame* CreatePingFrame(uint32 unique_id) const;
SpdyGoAwayControlFrame* CreateGoAway(
SpdyStreamId last_accepted_stream_id,
SpdyGoAwayStatus status) const;
SpdyHeadersControlFrame* CreateHeaders(SpdyStreamId stream_id,
SpdyControlFlags flags,
bool compressed,
const SpdyHeaderBlock* headers);
SpdyWindowUpdateControlFrame* CreateWindowUpdate(
SpdyStreamId stream_id,
uint32 delta_window_size) const;
SpdyCredentialControlFrame* CreateCredentialFrame(
const SpdyCredential& credential) const;
SpdyDataFrame* CreateDataFrame(SpdyStreamId stream_id,
const char* data,
uint32 len,
SpdyDataFlags flags);
SpdyPriority GetHighestPriority() const;
bool IsCompressible(const SpdyFrame& frame) const;
int frames_received() const { return frames_received_; }
private:
// The size of the header_buffer_.
enum { kHeaderBufferSize = 32 * 1024 };
void InitHeaderStreaming(SpdyStreamId stream_id);
SpdyFramer spdy_framer_;
BufferedSpdyFramerVisitorInterface* visitor_;
// Header block streaming state:
char header_buffer_[kHeaderBufferSize];
size_t header_buffer_used_;
bool header_buffer_valid_;
SpdyStreamId header_stream_id_;
int frames_received_;
// Collection of fields from control frames that we need to
// buffer up from the spdy framer.
struct ControlFrameFields {
SpdyControlType type;
SpdyStreamId stream_id;
SpdyStreamId associated_stream_id;
SpdyPriority priority;
uint8 credential_slot;
bool fin;
bool unidirectional;
};
scoped_ptr<ControlFrameFields> control_frame_fields_;
DISALLOW_COPY_AND_ASSIGN(BufferedSpdyFramer);
};
} // namespace net
#endif // NET_SPDY_BUFFERED_SPDY_FRAMER_H_
|