diff options
-rw-r--r-- | net/flip/flip_bitmasks.h | 2 | ||||
-rw-r--r-- | net/flip/flip_framer.cc | 5 | ||||
-rw-r--r-- | net/flip/flip_framer_test.cc | 57 | ||||
-rw-r--r-- | net/flip/flip_protocol.h | 79 |
4 files changed, 108 insertions, 35 deletions
diff --git a/net/flip/flip_bitmasks.h b/net/flip/flip_bitmasks.h index 8f139e0..3123da7 100644 --- a/net/flip/flip_bitmasks.h +++ b/net/flip/flip_bitmasks.h @@ -10,6 +10,8 @@ namespace flip { const int kStreamIdMask = 0x7fffffff; // StreamId mask from the FlipHeader const int kControlFlagMask = 0x8000; // Control flag mask from the FlipHeader const int kPriorityMask = 0xc0; // Priority mask from the SYN_FRAME +const int kLengthMask = 0xffffff; // Mask the lower 24 bits. + } // flip #endif // NET_FLIP_FLIP_BITMASKS_H_ diff --git a/net/flip/flip_framer.cc b/net/flip/flip_framer.cc index 9793c3b..b5b611f 100644 --- a/net/flip/flip_framer.cc +++ b/net/flip/flip_framer.cc @@ -20,9 +20,6 @@ static const size_t kControlFrameBufferInitialSize = 32 * 1024; // TODO(mbelshe): We should make this stream-based so there are no limits. static const size_t kControlFrameBufferMaxSize = 64 * 1024; -// This implementation of Flip is version 1. -static const int kFlipProtocolVersion = 1; - // By default is compression on or off. bool FlipFramer::compression_default_ = true; @@ -652,7 +649,7 @@ FlipFrame* FlipFramer::DecompressFrame(const FlipFrame* frame) { if (!frame->is_control_frame()) { const FlipDataFrame* data_frame = reinterpret_cast<const FlipDataFrame*>(frame); - if (!data_frame->flags() & DATA_FLAG_COMPRESSED) + if ((data_frame->flags() & DATA_FLAG_COMPRESSED) == 0) return DuplicateFrame(frame); } diff --git a/net/flip/flip_framer_test.cc b/net/flip/flip_framer_test.cc index e37d54f..979c541 100644 --- a/net/flip/flip_framer_test.cc +++ b/net/flip/flip_framer_test.cc @@ -95,6 +95,63 @@ TEST_F(FlipFramerTest, ProtocolConstants) { EXPECT_EQ(3, FIN_STREAM); } +// Test some of the protocol helper functions +TEST_F(FlipFramerTest, FrameStructs) { + FlipFrame frame; + memset(&frame, 0, sizeof(frame)); + frame.set_length(12345); + frame.set_flags(10); + EXPECT_EQ(12345u, frame.length()); + EXPECT_EQ(10u, frame.flags()); + EXPECT_EQ(false, frame.is_control_frame()); + + memset(&frame, 0, sizeof(frame)); + frame.set_length(0); + frame.set_flags(10); + EXPECT_EQ(0u, frame.length()); + EXPECT_EQ(10u, frame.flags()); + EXPECT_EQ(false, frame.is_control_frame()); +} + +TEST_F(FlipFramerTest, DataFrameStructs) { + FlipDataFrame data_frame; + memset(&data_frame, 0, sizeof(data_frame)); + data_frame.set_stream_id(12345); + EXPECT_EQ(12345u, data_frame.stream_id()); +} + +TEST_F(FlipFramerTest, ControlFrameStructs) { + FlipFramer framer; + FlipHeaderBlock headers; + + scoped_array<FlipSynStreamControlFrame> syn_frame( + framer.CreateSynStream(123, 2, false, &headers)); + EXPECT_EQ(kFlipProtocolVersion, syn_frame.get()->version()); + EXPECT_EQ(true, syn_frame.get()->is_control_frame()); + EXPECT_EQ(SYN_STREAM, syn_frame.get()->type()); + EXPECT_EQ(123u, syn_frame.get()->stream_id()); + EXPECT_EQ(2u, syn_frame.get()->priority()); + EXPECT_EQ(2, syn_frame.get()->header_block_len()); + + scoped_array<FlipSynReplyControlFrame> syn_reply( + framer.CreateSynReply(123, false, &headers)); + EXPECT_EQ(kFlipProtocolVersion, syn_reply.get()->version()); + EXPECT_EQ(true, syn_reply.get()->is_control_frame()); + EXPECT_EQ(SYN_REPLY, syn_reply.get()->type()); + EXPECT_EQ(123u, syn_reply.get()->stream_id()); + EXPECT_EQ(2, syn_reply.get()->header_block_len()); + + scoped_array<FlipFinStreamControlFrame> fin_frame( + framer.CreateFinStream(123, 444)); + EXPECT_EQ(kFlipProtocolVersion, fin_frame.get()->version()); + EXPECT_EQ(true, fin_frame.get()->is_control_frame()); + EXPECT_EQ(FIN_STREAM, fin_frame.get()->type()); + EXPECT_EQ(123u, fin_frame.get()->stream_id()); + EXPECT_EQ(444u, fin_frame.get()->status()); + fin_frame.get()->set_status(555); + EXPECT_EQ(555u, fin_frame.get()->status()); +} + // Test that we can encode and decode a FlipHeaderBlock. TEST_F(FlipFramerTest, HeaderBlock) { FlipHeaderBlock headers; diff --git a/net/flip/flip_protocol.h b/net/flip/flip_protocol.h index 93c8a5a..c737473 100644 --- a/net/flip/flip_protocol.h +++ b/net/flip/flip_protocol.h @@ -17,32 +17,29 @@ #include "flip_bitmasks.h" // cross-google3 directory naming. -// Stream Frame Format -// +-------------------------------+ -// |0| Stream-ID (31bits) | -// +-------------------------------+ -// |flags (16)| Length (16bits) | -// +-------------------------------+ -// | Data | -// +-------------------------------+ +// Data Frame Format +// +----------------------------------+ +// |0| Stream-ID (31bits) | +// +----------------------------------+ +// | flags (8) | Length (24 bits) | +// +----------------------------------+ +// | Data | +// +----------------------------------+ // - -// Control Frame Format -// +-------------------------------+ -// |1| Version(15bits)|Type(16bits)| -// +-------------------------------+ -// | Length (32bits) | -// +-------------------------------+ -// | Data | -// +-------------------------------+ +// Control Frame Format +// +----------------------------------+ +// |1| Version(15bits) | Type(16bits) | +// +----------------------------------+ +// | flags (8) | Length (24 bits) | +// +----------------------------------+ +// | Data | +// +----------------------------------+ // - - // Control Frame: SYN_STREAM // +----------------------------------+ // |1|000000000000001|0000000000000001| // +----------------------------------+ -// | Length (32bits) | >= 8 +// | flags (8) | Length (24 bits) | >= 8 // +----------------------------------+ // |X| Stream-ID(31bits) | // +----------------------------------+ @@ -53,7 +50,7 @@ // +----------------------------------+ // |1|000000000000001|0000000000000010| // +----------------------------------+ -// | Length (32bits) | >= 8 +// | flags (8) | Length (24 bits) | >= 8 // +----------------------------------+ // |X| Stream-ID(31bits) | // +----------------------------------+ @@ -64,7 +61,7 @@ // +----------------------------------+ // |1|000000000000001|0000000000000011| // +----------------------------------+ -// | Length (32bits) | >= 4 +// | flags (8) | Length (24 bits) | >= 4 // +----------------------------------+ // |X| Stream-ID(31bits) | // +----------------------------------+ @@ -75,7 +72,7 @@ // +----------------------------------+ // |1|000000000000001|0000000000000100| // +----------------------------------+ -// | Length (32bits) | >= 4 +// | flags (8) | Length (24 bits) | >= 4 // +----------------------------------+ // |X| Stream-ID(31bits) | // +----------------------------------+ @@ -84,6 +81,9 @@ namespace flip { +// This implementation of Flip is version 1. +const int kFlipProtocolVersion = 1; + // Note: all protocol data structures are on-the-wire format. That means that // data is stored in network-normalized order. Readers must use the // accessors provided or call ntohX() functions. @@ -98,9 +98,15 @@ typedef enum { // Flags on data packets typedef enum { - DATA_FLAG_COMPRESSED = 1 + DATA_FLAG_FIN = 1, + DATA_FLAG_COMPRESSED = 2 // TODO(mbelshe): remove me. } FlipDataFlags; +// Flags on control packets +typedef enum { + CONTROL_FLAG_FIN = 1 +} FlipControlFlags; + // A FLIP stream id is a 31 bit entity. typedef uint32 FlipStreamId; @@ -108,10 +114,24 @@ typedef uint32 FlipStreamId; #define FLIP_PRIORITY_LOWEST 3 #define FLIP_PRIORITY_HIGHEST 0 +// A special structure for the 8 bit flags and 24 bit length fields. +typedef union { + uint8 flags_[4]; // 8 bits + uint32 length_; // 24 bits +} FlagsLength; + // All Flip Frame types derive from the FlipFrame struct. typedef struct { - uint32 length() const { return ntohs(data_.length_); } - void set_length(uint16 length) { data_.length_ = htons(length); } + uint8 flags() const { return flags_length_.flags_[0]; } + void set_flags(uint8 flags) { flags_length_.flags_[0] = flags; } + + uint32 length() const { return ntohl(flags_length_.length_) & kLengthMask; } + void set_length(uint32 length) { + DCHECK((length & ~kLengthMask) == 0); + length = htonl(length & kLengthMask); + flags_length_.length_ = (flags() << 6) | length; + } + bool is_control_frame() const { return (ntohs(control_.version_) & kControlFlagMask) == kControlFlagMask; } @@ -121,14 +141,12 @@ typedef struct { struct { uint16 version_; uint16 type_; - uint32 length_; } control_; struct { FlipStreamId stream_id_; - uint16 flags_; - uint16 length_; } data_; }; + FlagsLength flags_length_; } FlipFrame; // A Data Frame. @@ -137,8 +155,6 @@ typedef struct : public FlipFrame { return ntohl(data_.stream_id_) & kStreamIdMask; } void set_stream_id(FlipStreamId id) { data_.stream_id_ = htonl(id); } - uint16 flags() const { return ntohs(data_.flags_); } - void set_flags(uint16 flags) { data_.flags_ = htons(flags); } } FlipDataFrame; // A Control Frame. @@ -161,6 +177,7 @@ typedef struct : public FlipFrame { // A SYN_STREAM frame. typedef struct FlipSynStreamControlFrame : public FlipControlFrame { uint8 priority() const { return (priority_ & kPriorityMask) >> 6; } + // The number of bytes in the header block beyond the frame header length. int header_block_len() const { return length() - kHeaderBlockOffset; } const char* header_block() const { return reinterpret_cast<const char*>(this) + |