Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / spdy / buffered_spdy_framer.cc
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.
4
5 #include "net/spdy/buffered_spdy_framer.h"
6
7 #include "base/logging.h"
8
9 namespace net {
10
11 SpdyMajorVersion NextProtoToSpdyMajorVersion(NextProto next_proto) {
12   switch (next_proto) {
13     case kProtoDeprecatedSPDY2:
14       return SPDY2;
15     case kProtoSPDY3:
16     case kProtoSPDY31:
17       return SPDY3;
18     case kProtoSPDY4:
19       return SPDY4;
20     case kProtoUnknown:
21     case kProtoHTTP11:
22     case kProtoQUIC1SPDY3:
23       break;
24   }
25   NOTREACHED();
26   return SPDY2;
27 }
28
29 BufferedSpdyFramer::BufferedSpdyFramer(SpdyMajorVersion version,
30                                        bool enable_compression)
31     : spdy_framer_(version),
32       visitor_(NULL),
33       header_buffer_used_(0),
34       header_buffer_valid_(false),
35       header_stream_id_(SpdyFramer::kInvalidStream),
36       frames_received_(0) {
37   spdy_framer_.set_enable_compression(enable_compression);
38   memset(header_buffer_, 0, sizeof(header_buffer_));
39 }
40
41 BufferedSpdyFramer::~BufferedSpdyFramer() {
42 }
43
44 void BufferedSpdyFramer::set_visitor(
45     BufferedSpdyFramerVisitorInterface* visitor) {
46   visitor_ = visitor;
47   spdy_framer_.set_visitor(this);
48 }
49
50 void BufferedSpdyFramer::set_debug_visitor(
51     SpdyFramerDebugVisitorInterface* debug_visitor) {
52   spdy_framer_.set_debug_visitor(debug_visitor);
53 }
54
55 void BufferedSpdyFramer::OnError(SpdyFramer* spdy_framer) {
56   DCHECK(spdy_framer);
57   visitor_->OnError(spdy_framer->error_code());
58 }
59
60 void BufferedSpdyFramer::OnSynStream(SpdyStreamId stream_id,
61                                      SpdyStreamId associated_stream_id,
62                                      SpdyPriority priority,
63                                      bool fin,
64                                      bool unidirectional) {
65   frames_received_++;
66   DCHECK(!control_frame_fields_.get());
67   control_frame_fields_.reset(new ControlFrameFields());
68   control_frame_fields_->type = SYN_STREAM;
69   control_frame_fields_->stream_id = stream_id;
70   control_frame_fields_->associated_stream_id = associated_stream_id;
71   control_frame_fields_->priority = priority;
72   control_frame_fields_->fin = fin;
73   control_frame_fields_->unidirectional = unidirectional;
74
75   InitHeaderStreaming(stream_id);
76 }
77
78 void BufferedSpdyFramer::OnHeaders(SpdyStreamId stream_id,
79                                    bool has_priority,
80                                    SpdyPriority priority,
81                                    bool fin,
82                                    bool end) {
83   frames_received_++;
84   DCHECK(!control_frame_fields_.get());
85   control_frame_fields_.reset(new ControlFrameFields());
86   control_frame_fields_->type = HEADERS;
87   control_frame_fields_->stream_id = stream_id;
88   control_frame_fields_->has_priority = has_priority;
89   if (control_frame_fields_->has_priority) {
90     control_frame_fields_->priority = priority;
91   }
92   control_frame_fields_->fin = fin;
93
94   InitHeaderStreaming(stream_id);
95 }
96
97 void BufferedSpdyFramer::OnSynReply(SpdyStreamId stream_id,
98                                     bool fin) {
99   frames_received_++;
100   DCHECK(!control_frame_fields_.get());
101   control_frame_fields_.reset(new ControlFrameFields());
102   control_frame_fields_->type = SYN_REPLY;
103   control_frame_fields_->stream_id = stream_id;
104   control_frame_fields_->fin = fin;
105
106   InitHeaderStreaming(stream_id);
107 }
108
109 bool BufferedSpdyFramer::OnControlFrameHeaderData(SpdyStreamId stream_id,
110                                                   const char* header_data,
111                                                   size_t len) {
112   CHECK_EQ(header_stream_id_, stream_id);
113
114   if (len == 0) {
115     // Indicates end-of-header-block.
116     CHECK(header_buffer_valid_);
117
118     SpdyHeaderBlock headers;
119     size_t parsed_len = spdy_framer_.ParseHeaderBlockInBuffer(
120         header_buffer_, header_buffer_used_, &headers);
121     // TODO(rch): this really should be checking parsed_len != len,
122     // but a bunch of tests fail.  Need to figure out why.
123     if (parsed_len == 0) {
124       visitor_->OnStreamError(
125           stream_id, "Could not parse Spdy Control Frame Header.");
126       return false;
127     }
128     DCHECK(control_frame_fields_.get());
129     switch (control_frame_fields_->type) {
130       case SYN_STREAM:
131         visitor_->OnSynStream(control_frame_fields_->stream_id,
132                               control_frame_fields_->associated_stream_id,
133                               control_frame_fields_->priority,
134                               control_frame_fields_->fin,
135                               control_frame_fields_->unidirectional,
136                               headers);
137         break;
138       case SYN_REPLY:
139         visitor_->OnSynReply(control_frame_fields_->stream_id,
140                              control_frame_fields_->fin,
141                              headers);
142         break;
143       case HEADERS:
144         visitor_->OnHeaders(control_frame_fields_->stream_id,
145                             control_frame_fields_->has_priority,
146                             control_frame_fields_->priority,
147                             control_frame_fields_->fin,
148                             headers);
149         break;
150       case PUSH_PROMISE:
151         DCHECK_LT(SPDY3, protocol_version());
152         visitor_->OnPushPromise(control_frame_fields_->stream_id,
153                                 control_frame_fields_->promised_stream_id,
154                                 headers);
155         break;
156       default:
157         DCHECK(false) << "Unexpect control frame type: "
158                       << control_frame_fields_->type;
159         break;
160     }
161     control_frame_fields_.reset(NULL);
162     return true;
163   }
164
165   const size_t available = kHeaderBufferSize - header_buffer_used_;
166   if (len > available) {
167     header_buffer_valid_ = false;
168     visitor_->OnStreamError(
169         stream_id, "Received more data than the allocated size.");
170     return false;
171   }
172   memcpy(header_buffer_ + header_buffer_used_, header_data, len);
173   header_buffer_used_ += len;
174   return true;
175 }
176
177 void BufferedSpdyFramer::OnDataFrameHeader(SpdyStreamId stream_id,
178                                            size_t length,
179                                            bool fin) {
180   frames_received_++;
181   header_stream_id_ = stream_id;
182   visitor_->OnDataFrameHeader(stream_id, length, fin);
183 }
184
185 void BufferedSpdyFramer::OnStreamFrameData(SpdyStreamId stream_id,
186                                            const char* data,
187                                            size_t len,
188                                            bool fin) {
189   visitor_->OnStreamFrameData(stream_id, data, len, fin);
190 }
191
192 void BufferedSpdyFramer::OnSettings(bool clear_persisted) {
193   visitor_->OnSettings(clear_persisted);
194 }
195
196 void BufferedSpdyFramer::OnSetting(SpdySettingsIds id,
197                                    uint8 flags,
198                                    uint32 value) {
199   visitor_->OnSetting(id, flags, value);
200 }
201
202 void BufferedSpdyFramer::OnSettingsAck() {
203   visitor_->OnSettingsAck();
204 }
205
206 void BufferedSpdyFramer::OnSettingsEnd() {
207   visitor_->OnSettingsEnd();
208 }
209
210 void BufferedSpdyFramer::OnPing(SpdyPingId unique_id, bool is_ack) {
211   visitor_->OnPing(unique_id, is_ack);
212 }
213
214 void BufferedSpdyFramer::OnRstStream(SpdyStreamId stream_id,
215                                      SpdyRstStreamStatus status) {
216   visitor_->OnRstStream(stream_id, status);
217 }
218 void BufferedSpdyFramer::OnGoAway(SpdyStreamId last_accepted_stream_id,
219                                   SpdyGoAwayStatus status) {
220   visitor_->OnGoAway(last_accepted_stream_id, status);
221 }
222
223 void BufferedSpdyFramer::OnWindowUpdate(SpdyStreamId stream_id,
224                                         uint32 delta_window_size) {
225   visitor_->OnWindowUpdate(stream_id, delta_window_size);
226 }
227
228 void BufferedSpdyFramer::OnPushPromise(SpdyStreamId stream_id,
229                                        SpdyStreamId promised_stream_id,
230                                        bool end) {
231   DCHECK_LT(SPDY3, protocol_version());
232   frames_received_++;
233   DCHECK(!control_frame_fields_.get());
234   control_frame_fields_.reset(new ControlFrameFields());
235   control_frame_fields_->type = PUSH_PROMISE;
236   control_frame_fields_->stream_id = stream_id;
237   control_frame_fields_->promised_stream_id = promised_stream_id;
238
239   InitHeaderStreaming(stream_id);
240 }
241
242 void BufferedSpdyFramer::OnContinuation(SpdyStreamId stream_id, bool end) {
243 }
244
245 bool BufferedSpdyFramer::OnUnknownFrame(SpdyStreamId stream_id,
246                                         int frame_type) {
247   return visitor_->OnUnknownFrame(stream_id, frame_type);
248 }
249
250 SpdyMajorVersion BufferedSpdyFramer::protocol_version() {
251   return spdy_framer_.protocol_version();
252 }
253
254 size_t BufferedSpdyFramer::ProcessInput(const char* data, size_t len) {
255   return spdy_framer_.ProcessInput(data, len);
256 }
257
258 void BufferedSpdyFramer::Reset() {
259   spdy_framer_.Reset();
260 }
261
262 SpdyFramer::SpdyError BufferedSpdyFramer::error_code() const {
263   return spdy_framer_.error_code();
264 }
265
266 SpdyFramer::SpdyState BufferedSpdyFramer::state() const {
267   return spdy_framer_.state();
268 }
269
270 bool BufferedSpdyFramer::MessageFullyRead() {
271   return state() == SpdyFramer::SPDY_AUTO_RESET;
272 }
273
274 bool BufferedSpdyFramer::HasError() {
275   return spdy_framer_.HasError();
276 }
277
278 // TODO(jgraettinger): Eliminate uses of this method (prefer
279 // SpdySynStreamIR).
280 SpdyFrame* BufferedSpdyFramer::CreateSynStream(
281     SpdyStreamId stream_id,
282     SpdyStreamId associated_stream_id,
283     SpdyPriority priority,
284     SpdyControlFlags flags,
285     const SpdyHeaderBlock* headers) {
286   SpdySynStreamIR syn_stream(stream_id);
287   syn_stream.set_associated_to_stream_id(associated_stream_id);
288   syn_stream.set_priority(priority);
289   syn_stream.set_fin((flags & CONTROL_FLAG_FIN) != 0);
290   syn_stream.set_unidirectional((flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
291   // TODO(hkhalil): Avoid copy here.
292   syn_stream.set_name_value_block(*headers);
293   return spdy_framer_.SerializeSynStream(syn_stream);
294 }
295
296 // TODO(jgraettinger): Eliminate uses of this method (prefer
297 // SpdySynReplyIR).
298 SpdyFrame* BufferedSpdyFramer::CreateSynReply(
299     SpdyStreamId stream_id,
300     SpdyControlFlags flags,
301     const SpdyHeaderBlock* headers) {
302   SpdySynReplyIR syn_reply(stream_id);
303   syn_reply.set_fin(flags & CONTROL_FLAG_FIN);
304   // TODO(hkhalil): Avoid copy here.
305   syn_reply.set_name_value_block(*headers);
306   return spdy_framer_.SerializeSynReply(syn_reply);
307 }
308
309 // TODO(jgraettinger): Eliminate uses of this method (prefer
310 // SpdyRstStreamIR).
311 SpdyFrame* BufferedSpdyFramer::CreateRstStream(
312     SpdyStreamId stream_id,
313     SpdyRstStreamStatus status) const {
314   // RST_STREAM payloads are not part of any SPDY spec.
315   // SpdyFramer will accept them, but don't create them.
316   SpdyRstStreamIR rst_ir(stream_id, status, "");
317   return spdy_framer_.SerializeRstStream(rst_ir);
318 }
319
320 // TODO(jgraettinger): Eliminate uses of this method (prefer
321 // SpdySettingsIR).
322 SpdyFrame* BufferedSpdyFramer::CreateSettings(
323     const SettingsMap& values) const {
324   SpdySettingsIR settings_ir;
325   for (SettingsMap::const_iterator it = values.begin();
326        it != values.end();
327        ++it) {
328     settings_ir.AddSetting(
329         it->first,
330         (it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0,
331         (it->second.first & SETTINGS_FLAG_PERSISTED) != 0,
332         it->second.second);
333   }
334   return spdy_framer_.SerializeSettings(settings_ir);
335 }
336
337 // TODO(jgraettinger): Eliminate uses of this method (prefer SpdyPingIR).
338 SpdyFrame* BufferedSpdyFramer::CreatePingFrame(uint32 unique_id,
339                                                bool is_ack) const {
340   SpdyPingIR ping_ir(unique_id);
341   ping_ir.set_is_ack(is_ack);
342   return spdy_framer_.SerializePing(ping_ir);
343 }
344
345 // TODO(jgraettinger): Eliminate uses of this method (prefer SpdyGoAwayIR).
346 SpdyFrame* BufferedSpdyFramer::CreateGoAway(
347     SpdyStreamId last_accepted_stream_id,
348     SpdyGoAwayStatus status) const {
349   SpdyGoAwayIR go_ir(last_accepted_stream_id, status, "");
350   return spdy_framer_.SerializeGoAway(go_ir);
351 }
352
353 // TODO(jgraettinger): Eliminate uses of this method (prefer SpdyHeadersIR).
354 SpdyFrame* BufferedSpdyFramer::CreateHeaders(
355     SpdyStreamId stream_id,
356     SpdyControlFlags flags,
357     SpdyPriority priority,
358     const SpdyHeaderBlock* headers) {
359   SpdyHeadersIR headers_ir(stream_id);
360   headers_ir.set_fin((flags & CONTROL_FLAG_FIN) != 0);
361   if (flags & HEADERS_FLAG_PRIORITY) {
362     headers_ir.set_has_priority(true);
363     headers_ir.set_priority(priority);
364   }
365   headers_ir.set_name_value_block(*headers);
366   return spdy_framer_.SerializeHeaders(headers_ir);
367 }
368
369 // TODO(jgraettinger): Eliminate uses of this method (prefer
370 // SpdyWindowUpdateIR).
371 SpdyFrame* BufferedSpdyFramer::CreateWindowUpdate(
372     SpdyStreamId stream_id,
373     uint32 delta_window_size) const {
374   SpdyWindowUpdateIR update_ir(stream_id, delta_window_size);
375   return spdy_framer_.SerializeWindowUpdate(update_ir);
376 }
377
378 // TODO(jgraettinger): Eliminate uses of this method (prefer SpdyDataIR).
379 SpdyFrame* BufferedSpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
380                                                const char* data,
381                                                uint32 len,
382                                                SpdyDataFlags flags) {
383   SpdyDataIR data_ir(stream_id,
384                      base::StringPiece(data, len));
385   data_ir.set_fin((flags & DATA_FLAG_FIN) != 0);
386   return spdy_framer_.SerializeData(data_ir);
387 }
388
389 // TODO(jgraettinger): Eliminate uses of this method (prefer SpdyPushPromiseIR).
390 SpdyFrame* BufferedSpdyFramer::CreatePushPromise(
391     SpdyStreamId stream_id,
392     SpdyStreamId promised_stream_id,
393     const SpdyHeaderBlock* headers) {
394   SpdyPushPromiseIR push_promise_ir(stream_id, promised_stream_id);
395   push_promise_ir.set_name_value_block(*headers);
396   return spdy_framer_.SerializePushPromise(push_promise_ir);
397 }
398
399 SpdyPriority BufferedSpdyFramer::GetHighestPriority() const {
400   return spdy_framer_.GetHighestPriority();
401 }
402
403 void BufferedSpdyFramer::InitHeaderStreaming(SpdyStreamId stream_id) {
404   memset(header_buffer_, 0, kHeaderBufferSize);
405   header_buffer_used_ = 0;
406   header_buffer_valid_ = true;
407   header_stream_id_ = stream_id;
408   DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
409 }
410
411 }  // namespace net