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#ifndef NET_SPDY_BUFFERED_SPDY_FRAMER_H_
6#define NET_SPDY_BUFFERED_SPDY_FRAMER_H_
7
8#include <string>
9
10#include "base/basictypes.h"
11#include "base/gtest_prod_util.h"
12#include "base/memory/scoped_ptr.h"
13#include "net/base/net_export.h"
14#include "net/socket/next_proto.h"
15#include "net/spdy/spdy_framer.h"
16#include "net/spdy/spdy_header_block.h"
17#include "net/spdy/spdy_protocol.h"
18
19namespace net {
20
21// Returns the SPDY major version corresponding to the given NextProto
22// value, which must represent a SPDY-like protocol.
23NET_EXPORT_PRIVATE SpdyMajorVersion NextProtoToSpdyMajorVersion(
24    NextProto next_proto);
25
26class NET_EXPORT_PRIVATE BufferedSpdyFramerVisitorInterface {
27 public:
28  BufferedSpdyFramerVisitorInterface() {}
29
30  // Called if an error is detected in the SpdyFrame protocol.
31  virtual void OnError(SpdyFramer::SpdyError error_code) = 0;
32
33  // Called if an error is detected in a SPDY stream.
34  virtual void OnStreamError(SpdyStreamId stream_id,
35                             const std::string& description) = 0;
36
37  // Called after all the header data for SYN_STREAM control frame is received.
38  virtual void OnSynStream(SpdyStreamId stream_id,
39                           SpdyStreamId associated_stream_id,
40                           SpdyPriority priority,
41                           bool fin,
42                           bool unidirectional,
43                           const SpdyHeaderBlock& headers) = 0;
44
45  // Called after all the header data for SYN_REPLY control frame is received.
46  virtual void OnSynReply(SpdyStreamId stream_id,
47                          bool fin,
48                          const SpdyHeaderBlock& headers) = 0;
49
50  // Called after all the header data for HEADERS control frame is received.
51  virtual void OnHeaders(SpdyStreamId stream_id,
52                         bool fin,
53                         const SpdyHeaderBlock& headers) = 0;
54
55  // Called when a data frame header is received.
56  virtual void OnDataFrameHeader(SpdyStreamId stream_id,
57                                 size_t length,
58                                 bool fin) = 0;
59
60  // Called when data is received.
61  // |stream_id| The stream receiving data.
62  // |data| A buffer containing the data received.
63  // |len| The length of the data buffer (at most 2^24 - 1 for SPDY/3,
64  // but 2^16 - 1 - 8 for SPDY/4).
65  // When the other side has finished sending data on this stream,
66  // this method will be called with a zero-length buffer.
67  virtual void OnStreamFrameData(SpdyStreamId stream_id,
68                                 const char* data,
69                                 size_t len,
70                                 bool fin) = 0;
71
72  // Called when a SETTINGS frame is received.
73  // |clear_persisted| True if the respective flag is set on the SETTINGS frame.
74  virtual void OnSettings(bool clear_persisted) = 0;
75
76  // Called when an individual setting within a SETTINGS frame has been parsed
77  // and validated.
78  virtual void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) = 0;
79
80  // Called when a SETTINGS frame is received with the ACK flag set.
81  virtual void OnSettingsAck() {}
82
83  // Called at the completion of parsing SETTINGS id and value tuples.
84  virtual void OnSettingsEnd() {}
85
86  // Called when a PING frame has been parsed.
87  virtual void OnPing(SpdyPingId unique_id, bool is_ack) = 0;
88
89  // Called when a RST_STREAM frame has been parsed.
90  virtual void OnRstStream(SpdyStreamId stream_id,
91                           SpdyRstStreamStatus status) = 0;
92
93  // Called when a GOAWAY frame has been parsed.
94  virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
95                        SpdyGoAwayStatus status) = 0;
96
97  // Called when a WINDOW_UPDATE frame has been parsed.
98  virtual void OnWindowUpdate(SpdyStreamId stream_id,
99                              uint32 delta_window_size) = 0;
100
101  // Called when a PUSH_PROMISE frame has been parsed.
102  virtual void OnPushPromise(SpdyStreamId stream_id,
103                             SpdyStreamId promised_stream_id,
104                             const SpdyHeaderBlock& headers) = 0;
105
106  // Called when a frame type we don't recognize is received.
107  // Return true if this appears to be a valid extension frame, false otherwise.
108  // We distinguish between extension frames and nonsense by checking
109  // whether the stream id is valid.
110  virtual bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) = 0;
111
112 protected:
113  virtual ~BufferedSpdyFramerVisitorInterface() {}
114
115 private:
116  DISALLOW_COPY_AND_ASSIGN(BufferedSpdyFramerVisitorInterface);
117};
118
119class NET_EXPORT_PRIVATE BufferedSpdyFramer
120    : public SpdyFramerVisitorInterface {
121 public:
122  BufferedSpdyFramer(SpdyMajorVersion version,
123                     bool enable_compression);
124  virtual ~BufferedSpdyFramer();
125
126  // Sets callbacks to be called from the buffered spdy framer.  A visitor must
127  // be set, or else the framer will likely crash.  It is acceptable for the
128  // visitor to do nothing.  If this is called multiple times, only the last
129  // visitor will be used.
130  void set_visitor(BufferedSpdyFramerVisitorInterface* visitor);
131
132  // Set debug callbacks to be called from the framer. The debug visitor is
133  // completely optional and need not be set in order for normal operation.
134  // If this is called multiple times, only the last visitor will be used.
135  void set_debug_visitor(SpdyFramerDebugVisitorInterface* debug_visitor);
136
137  // SpdyFramerVisitorInterface
138  virtual void OnError(SpdyFramer* spdy_framer) OVERRIDE;
139  virtual void OnSynStream(SpdyStreamId stream_id,
140                           SpdyStreamId associated_stream_id,
141                           SpdyPriority priority,
142                           bool fin,
143                           bool unidirectional) OVERRIDE;
144  virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE;
145  virtual void OnHeaders(SpdyStreamId stream_id, bool fin, bool end) OVERRIDE;
146  virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
147                                        const char* header_data,
148                                        size_t len) OVERRIDE;
149  virtual void OnStreamFrameData(SpdyStreamId stream_id,
150                                 const char* data,
151                                 size_t len,
152                                 bool fin) OVERRIDE;
153  virtual void OnSettings(bool clear_persisted) OVERRIDE;
154  virtual void OnSetting(
155      SpdySettingsIds id, uint8 flags, uint32 value) OVERRIDE;
156  virtual void OnSettingsAck() OVERRIDE;
157  virtual void OnSettingsEnd() OVERRIDE;
158  virtual void OnPing(SpdyPingId unique_id, bool is_ack) OVERRIDE;
159  virtual void OnRstStream(SpdyStreamId stream_id,
160                           SpdyRstStreamStatus status) OVERRIDE;
161  virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
162                        SpdyGoAwayStatus status) OVERRIDE;
163  virtual void OnWindowUpdate(SpdyStreamId stream_id,
164                              uint32 delta_window_size) OVERRIDE;
165  virtual void OnPushPromise(SpdyStreamId stream_id,
166                             SpdyStreamId promised_stream_id,
167                             bool end) OVERRIDE;
168  virtual void OnDataFrameHeader(SpdyStreamId stream_id,
169                                 size_t length,
170                                 bool fin) OVERRIDE;
171  virtual void OnContinuation(SpdyStreamId stream_id, bool end) OVERRIDE;
172  virtual bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) OVERRIDE;
173
174  // SpdyFramer methods.
175  size_t ProcessInput(const char* data, size_t len);
176  SpdyMajorVersion protocol_version();
177  void Reset();
178  SpdyFramer::SpdyError error_code() const;
179  SpdyFramer::SpdyState state() const;
180  bool MessageFullyRead();
181  bool HasError();
182  SpdyFrame* CreateSynStream(SpdyStreamId stream_id,
183                             SpdyStreamId associated_stream_id,
184                             SpdyPriority priority,
185                             SpdyControlFlags flags,
186                             const SpdyHeaderBlock* headers);
187  SpdyFrame* CreateSynReply(SpdyStreamId stream_id,
188                            SpdyControlFlags flags,
189                            const SpdyHeaderBlock* headers);
190  SpdyFrame* CreateRstStream(SpdyStreamId stream_id,
191                             SpdyRstStreamStatus status) const;
192  SpdyFrame* CreateSettings(const SettingsMap& values) const;
193  SpdyFrame* CreatePingFrame(uint32 unique_id, bool is_ack) const;
194  SpdyFrame* CreateGoAway(
195      SpdyStreamId last_accepted_stream_id,
196      SpdyGoAwayStatus status) const;
197  SpdyFrame* CreateHeaders(SpdyStreamId stream_id,
198                           SpdyControlFlags flags,
199                           const SpdyHeaderBlock* headers);
200  SpdyFrame* CreateWindowUpdate(
201      SpdyStreamId stream_id,
202      uint32 delta_window_size) const;
203  SpdyFrame* CreateDataFrame(SpdyStreamId stream_id,
204                             const char* data,
205                             uint32 len,
206                             SpdyDataFlags flags);
207  SpdyFrame* CreatePushPromise(SpdyStreamId stream_id,
208                               SpdyStreamId promised_stream_id,
209                               const SpdyHeaderBlock* headers);
210
211  // Serialize a frame of unknown type.
212  SpdySerializedFrame* SerializeFrame(const SpdyFrameIR& frame) {
213    return spdy_framer_.SerializeFrame(frame);
214  }
215
216  SpdyPriority GetHighestPriority() const;
217
218  size_t GetDataFrameMinimumSize() const {
219    return spdy_framer_.GetDataFrameMinimumSize();
220  }
221
222  size_t GetControlFrameHeaderSize() const {
223    return spdy_framer_.GetControlFrameHeaderSize();
224  }
225
226  size_t GetSynStreamMinimumSize() const {
227    return spdy_framer_.GetSynStreamMinimumSize();
228  }
229
230  size_t GetFrameMinimumSize() const {
231    return spdy_framer_.GetFrameMinimumSize();
232  }
233
234  size_t GetFrameMaximumSize() const {
235    return spdy_framer_.GetFrameMaximumSize();
236  }
237
238  size_t GetDataFrameMaximumPayload() const {
239    return spdy_framer_.GetDataFrameMaximumPayload();
240  }
241
242  int frames_received() const { return frames_received_; }
243
244 private:
245  // The size of the header_buffer_.
246  enum { kHeaderBufferSize = 32 * 1024 };
247
248  void InitHeaderStreaming(SpdyStreamId stream_id);
249
250  SpdyFramer spdy_framer_;
251  BufferedSpdyFramerVisitorInterface* visitor_;
252
253  // Header block streaming state:
254  char header_buffer_[kHeaderBufferSize];
255  size_t header_buffer_used_;
256  bool header_buffer_valid_;
257  SpdyStreamId header_stream_id_;
258  int frames_received_;
259
260  // Collection of fields from control frames that we need to
261  // buffer up from the spdy framer.
262  struct ControlFrameFields {
263    SpdyFrameType type;
264    SpdyStreamId stream_id;
265    SpdyStreamId associated_stream_id;
266    SpdyStreamId promised_stream_id;
267    SpdyPriority priority;
268    uint8 credential_slot;
269    bool fin;
270    bool unidirectional;
271  };
272  scoped_ptr<ControlFrameFields> control_frame_fields_;
273
274  DISALLOW_COPY_AND_ASSIGN(BufferedSpdyFramer);
275};
276
277}  // namespace net
278
279#endif  // NET_SPDY_BUFFERED_SPDY_FRAMER_H_
280