summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/flip/flip_bitmasks.h2
-rw-r--r--net/flip/flip_framer.cc5
-rw-r--r--net/flip/flip_framer_test.cc57
-rw-r--r--net/flip/flip_protocol.h79
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) +