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