• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2009 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_FLIP_FLIP_FRAMER_H_
6 #define NET_FLIP_FLIP_FRAMER_H_
7 
8 #ifdef _WIN32
9 #include <winsock2.h>
10 #else
11 #include <arpa/inet.h>
12 #endif
13 #include <map>
14 #include <string>
15 
16 #include "base/basictypes.h"
17 #include "base/logging.h"
18 #include "base/scoped_ptr.h"
19 #include "testing/gtest/include/gtest/gtest_prod.h"
20 #include "flip_protocol.h"    // cross-google3 directory naming.
21 
22 typedef struct z_stream_s z_stream;  // Forward declaration for zlib.
23 
24 namespace net {
25 class FlipNetworkTransactionTest;
26 class HttpNetworkLayer;
27 }
28 
29 namespace flip {
30 
31 class FlipFramer;
32 class FlipFramerTest;
33 
34 namespace test {
35 class TestFlipVisitor;
36 void FramerSetEnableCompressionHelper(FlipFramer* framer, bool compress);
37 }  // namespace test
38 
39 // A datastructure for holding a set of headers from either a
40 // SYN_STREAM or SYN_REPLY frame.
41 typedef std::map<std::string, std::string> FlipHeaderBlock;
42 
43 // FlipFramerVisitorInterface is a set of callbacks for the FlipFramer.
44 // Implement this interface to receive event callbacks as frames are
45 // decoded from the framer.
46 class FlipFramerVisitorInterface {
47  public:
~FlipFramerVisitorInterface()48   virtual ~FlipFramerVisitorInterface() {}
49 
50   // Called if an error is detected in the FlipFrame protocol.
51   virtual void OnError(FlipFramer* framer) = 0;
52 
53   // Called when a Control Frame is received.
54   virtual void OnControl(const FlipControlFrame* frame) = 0;
55 
56   // Called when data is received.
57   // |stream_id| The stream receiving data.
58   // |data| A buffer containing the data received.
59   // |len| The length of the data buffer.
60   // When the other side has finished sending data on this stream,
61   // this method will be called with a zero-length buffer.
62   virtual void OnStreamFrameData(flip::FlipStreamId stream_id,
63                                  const char* data,
64                                  size_t len) = 0;
65 };
66 
67 class FlipFramer {
68  public:
69   // Flip states.
70   // TODO(mbelshe): Can we move these into the implementation
71   //                and avoid exposing through the header.  (Needed for test)
72   enum FlipState {
73     FLIP_ERROR,
74     FLIP_DONE,
75     FLIP_RESET,
76     FLIP_AUTO_RESET,
77     FLIP_READING_COMMON_HEADER,
78     FLIP_INTERPRET_CONTROL_FRAME_COMMON_HEADER,
79     FLIP_CONTROL_FRAME_PAYLOAD,
80     FLIP_IGNORE_REMAINING_PAYLOAD,
81     FLIP_FORWARD_STREAM_FRAME
82   };
83 
84   // Flip error codes.
85   enum FlipError {
86     FLIP_NO_ERROR,
87     FLIP_UNKNOWN_CONTROL_TYPE,       // Control frame is an unknown type.
88     FLIP_INVALID_CONTROL_FRAME,      // Control frame is mal-formatted.
89     FLIP_CONTROL_PAYLOAD_TOO_LARGE,  // Control frame payload was too large.
90     FLIP_ZLIB_INIT_FAILURE,          // The Zlib library could not initialize.
91     FLIP_UNSUPPORTED_VERSION,        // Control frame has unsupported version.
92     FLIP_DECOMPRESS_FAILURE,         // There was an error decompressing.
93   };
94 
95   // Create a new Framer.
96   FlipFramer();
97   virtual ~FlipFramer();
98 
99   // Set callbacks to be called from the framer.  A visitor must be set, or
100   // else the framer will likely crash.  It is acceptable for the visitor
101   // to do nothing.  If this is called multiple times, only the last visitor
102   // will be used.
set_visitor(FlipFramerVisitorInterface * visitor)103   void set_visitor(FlipFramerVisitorInterface* visitor) {
104     visitor_ = visitor;
105   }
106 
107   // Pass data into the framer for parsing.
108   // Returns the number of bytes consumed. It is safe to pass more bytes in
109   // than may be consumed.
110   size_t ProcessInput(const char* data, size_t len);
111 
112   // Resets the framer state after a frame has been successfully decoded.
113   // TODO(mbelshe): can we make this private?
114   void Reset();
115 
116   // Check the state of the framer.
error_code()117   FlipError error_code() const { return error_code_; }
state()118   FlipState state() const { return state_; }
119 
MessageFullyRead()120   bool MessageFullyRead() {
121     return state_ == FLIP_DONE || state_ == FLIP_AUTO_RESET;
122   }
HasError()123   bool HasError() { return state_ == FLIP_ERROR; }
124 
125   // Further parsing utilities.
126   // Given a control frame, parse out a FlipHeaderBlock.  Only
127   // valid for SYN_STREAM and SYN_REPLY frames.
128   // Returns true if successfully parsed, false otherwise.
129   bool ParseHeaderBlock(const FlipFrame* frame, FlipHeaderBlock* block);
130 
131   // Create a FlipSynStreamControlFrame.
132   // |stream_id| is the stream for this frame.
133   // |priority| is the priority (0-3) for this frame.
134   // |flags| is the flags to use with the data.
135   //    To mark this frame as the last frame, enable CONTROL_FLAG_FIN.
136   // |compressed| specifies whether the frame should be compressed.
137   // |headers| is the header block to include in the frame.
138   FlipSynStreamControlFrame* CreateSynStream(FlipStreamId stream_id,
139                                              int priority,
140                                              FlipControlFlags flags,
141                                              bool compressed,
142                                              FlipHeaderBlock* headers);
143 
144   static FlipFinStreamControlFrame* CreateFinStream(FlipStreamId stream_id,
145                                                     int status);
146 
147   // Create a FlipSynReplyControlFrame.
148   // |stream_id| is the stream for this frame.
149   // |flags| is the flags to use with the data.
150   //    To mark this frame as the last frame, enable CONTROL_FLAG_FIN.
151   // |compressed| specifies whether the frame should be compressed.
152   // |headers| is the header block to include in the frame.
153   FlipSynReplyControlFrame* CreateSynReply(FlipStreamId stream_id,
154                                            FlipControlFlags flags,
155                                            bool compressed,
156                                            FlipHeaderBlock* headers);
157 
158   // Create a data frame.
159   // |stream_id| is the stream  for this frame
160   // |data| is the data to be included in the frame.
161   // |len| is the length of the data
162   // |flags| is the flags to use with the data.
163   //    To create a compressed frame, enable DATA_FLAG_COMPRESSED.
164   //    To mark this frame as the last data frame, enable DATA_FLAG_FIN.
165   FlipDataFrame* CreateDataFrame(FlipStreamId stream_id, const char* data,
166                                  uint32 len, FlipDataFlags flags);
167 
168   static FlipControlFrame* CreateNopFrame();
169 
170   // NOTES about frame compression.
171   // We want flip to compress headers across the entire session.  As long as
172   // the session is over TCP, frames are sent serially.  The client & server
173   // can each compress frames in the same order and then compress them in that
174   // order, and the remote can do the reverse.  However, we ultimately want
175   // the creation of frames to be less sensitive to order so that they can be
176   // placed over a UDP based protocol and yet still benefit from some
177   // compression.  We don't know of any good compression protocol which does
178   // not build its state in a serial (stream based) manner....  For now, we're
179   // using zlib anyway.
180 
181   // Compresses a FlipFrame.
182   // On success, returns a new FlipFrame with the payload compressed.
183   // Compression state is maintained as part of the FlipFramer.
184   // Returned frame must be freed with free().
185   // On failure, returns NULL.
186   FlipFrame* CompressFrame(const FlipFrame* frame);
187 
188   // Decompresses a FlipFrame.
189   // On success, returns a new FlipFrame with the payload decompressed.
190   // Compression state is maintained as part of the FlipFramer.
191   // Returned frame must be freed with free().
192   // On failure, returns NULL.
193   FlipFrame* DecompressFrame(const FlipFrame* frame);
194 
195   // Create a copy of a frame.
196   FlipFrame* DuplicateFrame(const FlipFrame* frame);
197 
198   // For debugging.
199   static const char* StateToString(int state);
200   static const char* ErrorCodeToString(int error_code);
201 
202  protected:
203   FRIEND_TEST(FlipFramerTest, HeaderBlockBarfsOnOutOfOrderHeaders);
204   friend class net::FlipNetworkTransactionTest;
205   friend class net::HttpNetworkLayer;  // This is temporary for the server.
206   friend class test::TestFlipVisitor;
207   friend void test::FramerSetEnableCompressionHelper(FlipFramer* framer,
208                                                      bool compress);
209 
210   // For ease of testing we can tweak compression on/off.
211   void set_enable_compression(bool value);
212   static void set_enable_compression_default(bool value);
213 
214  private:
215   // Internal breakout from ProcessInput.  Returns the number of bytes
216   // consumed from the data.
217   size_t ProcessCommonHeader(const char* data, size_t len);
218   void ProcessControlFrameHeader();
219   size_t ProcessControlFramePayload(const char* data, size_t len);
220   size_t ProcessDataFramePayload(const char* data, size_t len);
221 
222   // Initialize the ZLib state.
223   bool InitializeCompressor();
224   bool InitializeDecompressor();
225 
226   // Not used (yet)
227   size_t BytesSafeToRead() const;
228 
229   // Set the error code.
230   void set_error(FlipError error);
231 
232   // Expands the control frame buffer to accomodate a particular payload size.
233   void ExpandControlFrameBuffer(size_t size);
234 
235   // Given a frame, breakdown the variable payload length, the static header
236   // header length, and variable payload pointer.
237   bool GetFrameBoundaries(const FlipFrame* frame, int* payload_length,
238                           int* header_length, const char** payload) const;
239 
240   FlipState state_;
241   FlipError error_code_;
242   size_t remaining_payload_;
243   size_t remaining_control_payload_;
244 
245   char* current_frame_buffer_;
246   size_t current_frame_len_;  // Number of bytes read into the current_frame_.
247   size_t current_frame_capacity_;
248 
249   bool enable_compression_;
250   scoped_ptr<z_stream> compressor_;
251   scoped_ptr<z_stream> decompressor_;
252   FlipFramerVisitorInterface* visitor_;
253 
254   static bool compression_default_;
255 };
256 
257 }  // namespace flip
258 
259 #endif  // NET_FLIP_FLIP_FRAMER_H_
260 
261