summaryrefslogtreecommitdiffstats
path: root/net/flip
diff options
context:
space:
mode:
Diffstat (limited to 'net/flip')
-rw-r--r--net/flip/flip_frame_builder.h7
-rw-r--r--net/flip/flip_framer.cc353
-rw-r--r--net/flip/flip_framer.h16
-rw-r--r--net/flip/flip_framer_test.cc164
-rw-r--r--net/flip/flip_protocol.h262
-rw-r--r--net/flip/flip_protocol_test.cc182
-rw-r--r--net/flip/flip_session.cc31
-rw-r--r--net/flip/flip_session.h1
8 files changed, 362 insertions, 654 deletions
diff --git a/net/flip/flip_frame_builder.h b/net/flip/flip_frame_builder.h
index 32b6035..fa59c45 100644
--- a/net/flip/flip_frame_builder.h
+++ b/net/flip/flip_frame_builder.h
@@ -43,9 +43,14 @@ class FlipFrameBuilder {
// Returns the size of the FlipFrameBuilder's data.
int length() const { return length_; }
+ // Returns the data for this FlipFrameBuilder.
+ const FlipFrame* data() const {
+ return reinterpret_cast<FlipFrame*>(buffer_);
+ }
+
// Takes the buffer from the FlipFrameBuilder.
FlipFrame* take() {
- FlipFrame* rv = new FlipFrame(buffer_, true);
+ FlipFrame* rv = reinterpret_cast<FlipFrame*>(buffer_);
buffer_ = NULL;
capacity_ = 0;
length_ = 0;
diff --git a/net/flip/flip_framer.cc b/net/flip/flip_framer.cc
index 31d1234..c0136d0 100644
--- a/net/flip/flip_framer.cc
+++ b/net/flip/flip_framer.cc
@@ -105,8 +105,8 @@ size_t FlipFramer::BytesSafeToRead() const {
case FLIP_RESET:
return 0;
case FLIP_READING_COMMON_HEADER:
- DCHECK(current_frame_len_ < FlipFrame::size());
- return FlipFrame::size() - current_frame_len_;
+ DCHECK(current_frame_len_ < sizeof(FlipFrame));
+ return sizeof(FlipFrame) - current_frame_len_;
case FLIP_INTERPRET_CONTROL_FRAME_COMMON_HEADER:
return 0;
case FLIP_CONTROL_FRAME_PAYLOAD:
@@ -151,6 +151,11 @@ size_t FlipFramer::ProcessInput(const char* data, size_t len) {
size_t original_len = len;
while (len != 0) {
+ FlipControlFrame* current_control_frame =
+ reinterpret_cast<FlipControlFrame*>(current_frame_buffer_);
+ FlipDataFrame* current_data_frame =
+ reinterpret_cast<FlipDataFrame*>(current_frame_buffer_);
+
switch (state_) {
case FLIP_ERROR:
case FLIP_DONE:
@@ -173,7 +178,52 @@ size_t FlipFramer::ProcessInput(const char* data, size_t len) {
// I felt it was a nice partitioning, however (which probably indicates
// that it should be refactored into its own function!)
case FLIP_INTERPRET_CONTROL_FRAME_COMMON_HEADER:
- ProcessControlFrameHeader();
+ DCHECK(error_code_ == 0);
+ DCHECK(current_frame_len_ >= sizeof(FlipFrame));
+ // Do some sanity checking on the control frame sizes.
+ switch (current_control_frame->type()) {
+ case SYN_STREAM:
+ // NOTE: sizeof(FlipSynStreamControlFrame) is not accurate.
+ if (current_control_frame->length() <
+ sizeof(FlipSynStreamControlFrame) - sizeof(FlipControlFrame))
+ set_error(FLIP_INVALID_CONTROL_FRAME);
+ break;
+ case SYN_REPLY:
+ if (current_control_frame->length() <
+ sizeof(FlipSynReplyControlFrame) - sizeof(FlipControlFrame))
+ set_error(FLIP_INVALID_CONTROL_FRAME);
+ break;
+ case FIN_STREAM:
+ if (current_control_frame->length() !=
+ sizeof(FlipFinStreamControlFrame) - sizeof(FlipFrame))
+ set_error(FLIP_INVALID_CONTROL_FRAME);
+ break;
+ case NOOP:
+ // NOP. Swallow it.
+ CHANGE_STATE(FLIP_AUTO_RESET);
+ continue;
+ default:
+ set_error(FLIP_UNKNOWN_CONTROL_TYPE);
+ break;
+ }
+
+ // We only support version 1 of this protocol.
+ if (current_control_frame->version() != kFlipProtocolVersion)
+ set_error(FLIP_UNSUPPORTED_VERSION);
+
+ if (error_code_) {
+ CHANGE_STATE(FLIP_ERROR);
+ goto bottom;
+ }
+
+ remaining_control_payload_ = current_control_frame->length();
+ if (remaining_control_payload_ > kControlFrameBufferMaxSize) {
+ set_error(FLIP_CONTROL_PAYLOAD_TOO_LARGE);
+ CHANGE_STATE(FLIP_ERROR);
+ goto bottom;
+ }
+ ExpandControlFrameBuffer(remaining_control_payload_);
+ CHANGE_STATE(FLIP_CONTROL_FRAME_PAYLOAD);
continue;
case FLIP_CONTROL_FRAME_PAYLOAD: {
@@ -185,12 +235,60 @@ size_t FlipFramer::ProcessInput(const char* data, size_t len) {
case FLIP_IGNORE_REMAINING_PAYLOAD:
// control frame has too-large payload
// intentional fallthrough
- case FLIP_FORWARD_STREAM_FRAME: {
- int bytes_read = ProcessDataFramePayload(data, len);
- len -= bytes_read;
- data += bytes_read;
+ case FLIP_FORWARD_STREAM_FRAME:
+ if (remaining_payload_) {
+ size_t amount_to_forward = std::min(remaining_payload_, len);
+ if (amount_to_forward && state_ != FLIP_IGNORE_REMAINING_PAYLOAD) {
+ const FlipDataFrame* data_frame =
+ reinterpret_cast<const FlipDataFrame*>(current_data_frame);
+ if (data_frame->flags() & DATA_FLAG_COMPRESSED) {
+ // TODO(mbelshe): Assert that the decompressor is init'ed.
+ if (!InitializeDecompressor())
+ return NULL;
+
+ size_t decompressed_max_size = amount_to_forward * 100;
+ scoped_array<char> decompressed(new char[decompressed_max_size]);
+ decompressor_->next_in = reinterpret_cast<Bytef*>(
+ const_cast<char*>(data));
+ decompressor_->avail_in = amount_to_forward;
+ decompressor_->next_out =
+ reinterpret_cast<Bytef*>(decompressed.get());
+ decompressor_->avail_out = decompressed_max_size;
+
+ int rv = inflate(decompressor_.get(), Z_SYNC_FLUSH);
+ if (rv != Z_OK) {
+ set_error(FLIP_DECOMPRESS_FAILURE);
+ goto bottom;
+ }
+ size_t decompressed_size = decompressed_max_size -
+ decompressor_->avail_out;
+ // Only inform the visitor if there is data.
+ if (decompressed_size)
+ visitor_->OnStreamFrameData(current_data_frame->stream_id(),
+ decompressed.get(),
+ decompressed_size);
+ amount_to_forward -= decompressor_->avail_in;
+ } else {
+ // The data frame was not compressed.
+ // Only inform the visitor if there is data.
+ if (amount_to_forward)
+ visitor_->OnStreamFrameData(current_data_frame->stream_id(),
+ data, amount_to_forward);
+ }
+ }
+ data += amount_to_forward;
+ len -= amount_to_forward;
+ remaining_payload_ -= amount_to_forward;
+ // If the FIN flag is set, and there is no more data in this data
+ // frame, inform the visitor of EOF via a 0-length data frame.
+ if (!remaining_payload_ &&
+ current_data_frame->flags() & DATA_FLAG_FIN)
+ visitor_->OnStreamFrameData(current_data_frame->stream_id(), NULL,
+ 0);
+ } else {
+ CHANGE_STATE(FLIP_AUTO_RESET);
+ }
continue;
- }
default:
break;
}
@@ -205,11 +303,12 @@ size_t FlipFramer::ProcessCommonHeader(const char* data, size_t len) {
DCHECK(state_ == FLIP_READING_COMMON_HEADER);
int original_len = len;
- FlipFrame current_frame(current_frame_buffer_, false);
+ FlipDataFrame* current_frame =
+ reinterpret_cast<FlipDataFrame*>(current_frame_buffer_);
do {
- if (current_frame_len_ < FlipFrame::size()) {
- size_t bytes_desired = FlipFrame::size() - current_frame_len_;
+ if (current_frame_len_ < sizeof(FlipFrame)) {
+ size_t bytes_desired = sizeof(FlipFrame) - current_frame_len_;
size_t bytes_to_append = std::min(bytes_desired, len);
char* header_buffer = current_frame_buffer_;
memcpy(&header_buffer[current_frame_len_], data, bytes_to_append);
@@ -217,20 +316,18 @@ size_t FlipFramer::ProcessCommonHeader(const char* data, size_t len) {
data += bytes_to_append;
len -= bytes_to_append;
// Check for an empty data frame.
- if (current_frame_len_ == FlipFrame::size() &&
- !current_frame.is_control_frame() &&
- current_frame.length() == 0) {
- if (current_frame.flags() & CONTROL_FLAG_FIN) {
- FlipDataFrame data_frame(current_frame_buffer_, false);
- visitor_->OnStreamFrameData(data_frame.stream_id(), NULL, 0);
- }
+ if (current_frame_len_ == sizeof(FlipFrame) &&
+ !current_frame->is_control_frame() &&
+ current_frame->length() == 0) {
+ if (current_frame->flags() & CONTROL_FLAG_FIN)
+ visitor_->OnStreamFrameData(current_frame->stream_id(), NULL, 0);
CHANGE_STATE(FLIP_RESET);
}
break;
}
- remaining_payload_ = current_frame.length();
+ remaining_payload_ = current_frame->length();
// if we're here, then we have the common header all received.
- if (!current_frame.is_control_frame())
+ if (!current_frame->is_control_frame())
CHANGE_STATE(FLIP_FORWARD_STREAM_FRAME);
else
CHANGE_STATE(FLIP_INTERPRET_CONTROL_FRAME_COMMON_HEADER);
@@ -239,55 +336,6 @@ size_t FlipFramer::ProcessCommonHeader(const char* data, size_t len) {
return original_len - len;
}
-void FlipFramer::ProcessControlFrameHeader() {
- FlipControlFrame current_control_frame(current_frame_buffer_, false);
- DCHECK_EQ(FLIP_NO_ERROR, error_code_);
- DCHECK_LE(FlipFrame::size(), current_frame_len_);
- // Do some sanity checking on the control frame sizes.
- switch (current_control_frame.type()) {
- case SYN_STREAM:
- if (current_control_frame.length() <
- FlipSynStreamControlFrame::size() - FlipControlFrame::size())
- set_error(FLIP_INVALID_CONTROL_FRAME);
- break;
- case SYN_REPLY:
- if (current_control_frame.length() <
- FlipSynReplyControlFrame::size() - FlipControlFrame::size())
- set_error(FLIP_INVALID_CONTROL_FRAME);
- break;
- case FIN_STREAM:
- if (current_control_frame.length() !=
- FlipFinStreamControlFrame::size() - FlipFrame::size())
- set_error(FLIP_INVALID_CONTROL_FRAME);
- break;
- case NOOP:
- // NOP. Swallow it.
- CHANGE_STATE(FLIP_AUTO_RESET);
- return;
- default:
- set_error(FLIP_UNKNOWN_CONTROL_TYPE);
- break;
- }
-
- // We only support version 1 of this protocol.
- if (current_control_frame.version() != kFlipProtocolVersion)
- set_error(FLIP_UNSUPPORTED_VERSION);
-
- if (error_code_) {
- CHANGE_STATE(FLIP_ERROR);
- return;
- }
-
- remaining_control_payload_ = current_control_frame.length();
- if (remaining_control_payload_ > kControlFrameBufferMaxSize) {
- set_error(FLIP_CONTROL_PAYLOAD_TOO_LARGE);
- CHANGE_STATE(FLIP_ERROR);
- return;
- }
- ExpandControlFrameBuffer(remaining_control_payload_);
- CHANGE_STATE(FLIP_CONTROL_FRAME_PAYLOAD);
-}
-
size_t FlipFramer::ProcessControlFramePayload(const char* data, size_t len) {
size_t original_len = len;
do {
@@ -303,85 +351,26 @@ size_t FlipFramer::ProcessControlFramePayload(const char* data, size_t len) {
if (remaining_control_payload_)
break;
}
- FlipControlFrame control_frame(current_frame_buffer_, false);
- visitor_->OnControl(&control_frame);
+ FlipControlFrame* control_frame =
+ reinterpret_cast<FlipControlFrame*>(current_frame_buffer_);
+ visitor_->OnControl(control_frame);
// If this is a FIN, tell the caller.
- if (control_frame.type() == SYN_REPLY &&
- control_frame.flags() & CONTROL_FLAG_FIN)
- visitor_->OnStreamFrameData(control_frame.stream_id(), NULL, 0);
+ if (control_frame->type() == SYN_REPLY &&
+ control_frame->flags() & CONTROL_FLAG_FIN)
+ visitor_->OnStreamFrameData(control_frame->stream_id(), NULL, 0);
CHANGE_STATE(FLIP_IGNORE_REMAINING_PAYLOAD);
} while (false);
return original_len - len;
}
-size_t FlipFramer::ProcessDataFramePayload(const char* data, size_t len) {
- size_t original_len = len;
-
- FlipDataFrame current_data_frame(current_frame_buffer_, false);
- if (remaining_payload_) {
- size_t amount_to_forward = std::min(remaining_payload_, len);
- if (amount_to_forward && state_ != FLIP_IGNORE_REMAINING_PAYLOAD) {
- if (current_data_frame.flags() & DATA_FLAG_COMPRESSED) {
- // TODO(mbelshe): Assert that the decompressor is init'ed.
- if (!InitializeDecompressor())
- return NULL;
-
- size_t decompressed_max_size = amount_to_forward * 100;
- scoped_ptr<char> decompressed(new char[decompressed_max_size]);
- decompressor_->next_in = reinterpret_cast<Bytef*>(
- const_cast<char*>(data));
- decompressor_->avail_in = amount_to_forward;
- decompressor_->next_out =
- reinterpret_cast<Bytef*>(decompressed.get());
- decompressor_->avail_out = decompressed_max_size;
-
- int rv = inflate(decompressor_.get(), Z_SYNC_FLUSH);
- if (rv != Z_OK) {
- set_error(FLIP_DECOMPRESS_FAILURE);
- goto bottom;
- }
- size_t decompressed_size = decompressed_max_size -
- decompressor_->avail_out;
- // Only inform the visitor if there is data.
- if (decompressed_size)
- visitor_->OnStreamFrameData(current_data_frame.stream_id(),
- decompressed.get(),
- decompressed_size);
- amount_to_forward -= decompressor_->avail_in;
- } else {
- // The data frame was not compressed.
- // Only inform the visitor if there is data.
- if (amount_to_forward)
- visitor_->OnStreamFrameData(current_data_frame.stream_id(),
- data, amount_to_forward);
- }
- }
- data += amount_to_forward;
- len -= amount_to_forward;
- remaining_payload_ -= amount_to_forward;
-
- // If the FIN flag is set, and there is no more data in this data
- // frame, inform the visitor of EOF via a 0-length data frame.
- if (!remaining_payload_ &&
- current_data_frame.flags() & DATA_FLAG_FIN)
- visitor_->OnStreamFrameData(current_data_frame.stream_id(), NULL,
- 0);
- } else {
- CHANGE_STATE(FLIP_AUTO_RESET);
- }
-
- bottom:
- return original_len - len;
-}
-
void FlipFramer::ExpandControlFrameBuffer(size_t size) {
DCHECK(size < kControlFrameBufferMaxSize);
if (size < current_frame_capacity_)
return;
- int alloc_size = size + FlipFrame::size();
+ int alloc_size = size + sizeof(FlipFrame);
char* new_buffer = new char[alloc_size];
memcpy(new_buffer, current_frame_buffer_, current_frame_len_);
current_frame_capacity_ = alloc_size;
@@ -390,18 +379,17 @@ void FlipFramer::ExpandControlFrameBuffer(size_t size) {
bool FlipFramer::ParseHeaderBlock(const FlipFrame* frame,
FlipHeaderBlock* block) {
- FlipControlFrame control_frame(frame->data(), false);
- uint32 type = control_frame.type();
+ uint32 type = reinterpret_cast<const FlipControlFrame*>(frame)->type();
if (type != SYN_STREAM && type != SYN_REPLY)
return false;
// Find the header data within the control frame.
- scoped_ptr<FlipFrame> decompressed_frame(DecompressFrame(frame));
- if (!decompressed_frame.get())
+ scoped_array<FlipSynStreamControlFrame> control_frame(
+ reinterpret_cast<FlipSynStreamControlFrame*>(DecompressFrame(frame)));
+ if (!control_frame.get())
return false;
- FlipSynStreamControlFrame syn_frame(decompressed_frame->data(), false);
- const char *header_data = syn_frame.header_block();
- int header_length = syn_frame.header_block_len();
+ const char *header_data = control_frame.get()->header_block();
+ int header_length = control_frame.get()->header_block_len();
FlipFrameBuilder builder(header_data, header_length);
void* iter = NULL;
@@ -450,18 +438,21 @@ FlipSynStreamControlFrame* FlipFramer::CreateSynStream(
}
// Write the length and flags.
- size_t length = frame.length() - FlipFrame::size();
+ size_t length = frame.length() - sizeof(FlipFrame);
DCHECK(length < static_cast<size_t>(kLengthMask));
FlagsAndLength flags_length;
flags_length.length_ = htonl(static_cast<uint32>(length));
flags_length.flags_[0] = flags;
frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length));
- scoped_ptr<FlipFrame> syn_frame(frame.take());
- if (compressed)
- return reinterpret_cast<FlipSynStreamControlFrame*>(
- CompressFrame(syn_frame.get()));
- return reinterpret_cast<FlipSynStreamControlFrame*>(syn_frame.release());
+ if (compressed) {
+ FlipSynStreamControlFrame* new_frame =
+ reinterpret_cast<FlipSynStreamControlFrame*>(
+ CompressFrame(frame.data()));
+ return new_frame;
+ }
+
+ return reinterpret_cast<FlipSynStreamControlFrame*>(frame.take());
}
/* static */
@@ -496,18 +487,17 @@ FlipSynReplyControlFrame* FlipFramer::CreateSynReply(FlipStreamId stream_id,
}
// Write the length
- size_t length = frame.length() - FlipFrame::size();
+ size_t length = frame.length() - sizeof(FlipFrame);
DCHECK(length < static_cast<size_t>(kLengthMask));
FlagsAndLength flags_length;
flags_length.length_ = htonl(static_cast<uint32>(length));
flags_length.flags_[0] = flags;
frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length));
- scoped_ptr<FlipFrame> reply_frame(frame.take());
if (compressed)
return reinterpret_cast<FlipSynReplyControlFrame*>(
- CompressFrame(reply_frame.get()));
- return reinterpret_cast<FlipSynReplyControlFrame*>(reply_frame.release());
+ CompressFrame(frame.data()));
+ return reinterpret_cast<FlipSynReplyControlFrame*>(frame.take());
}
FlipDataFrame* FlipFramer::CreateDataFrame(FlipStreamId stream_id,
@@ -524,10 +514,9 @@ FlipDataFrame* FlipFramer::CreateDataFrame(FlipStreamId stream_id,
frame.WriteBytes(&flags_length, sizeof(flags_length));
frame.WriteBytes(data, len);
- scoped_ptr<FlipFrame> data_frame(frame.take());
if (flags & DATA_FLAG_COMPRESSED)
- return reinterpret_cast<FlipDataFrame*>(CompressFrame(data_frame.get()));
- return reinterpret_cast<FlipDataFrame*>(data_frame.release());
+ return reinterpret_cast<FlipDataFrame*>(CompressFrame(frame.data()));
+ return reinterpret_cast<FlipDataFrame*>(frame.take());
}
/* static */
@@ -600,7 +589,7 @@ bool FlipFramer::InitializeDecompressor() {
bool FlipFramer::GetFrameBoundaries(const FlipFrame* frame,
int* payload_length,
int* header_length,
- const char** payload) const {
+ const unsigned char** payload) const {
if (frame->is_control_frame()) {
const FlipControlFrame* control_frame =
reinterpret_cast<const FlipControlFrame*>(frame);
@@ -611,8 +600,10 @@ bool FlipFramer::GetFrameBoundaries(const FlipFrame* frame,
const FlipSynStreamControlFrame *syn_frame =
reinterpret_cast<const FlipSynStreamControlFrame*>(frame);
*payload_length = syn_frame->header_block_len();
- *header_length = syn_frame->size();
- *payload = frame->data() + *header_length;
+ *header_length = sizeof(FlipFrame) + syn_frame->length() -
+ syn_frame->header_block_len();
+ *payload = reinterpret_cast<const unsigned char*>(frame) +
+ *header_length;
}
break;
default:
@@ -620,12 +611,13 @@ bool FlipFramer::GetFrameBoundaries(const FlipFrame* frame,
return false; // We can't compress this frame!
}
} else {
- *header_length = FlipFrame::size();
+ *header_length = sizeof(FlipFrame);
*payload_length = frame->length();
- *payload = frame->data() + FlipFrame::size();
+ *payload = reinterpret_cast<const unsigned char*>(frame) +
+ sizeof(FlipFrame);
}
DCHECK(static_cast<size_t>(*header_length) <=
- FlipFrame::size() + *payload_length);
+ sizeof(FlipFrame) + *payload_length);
return true;
}
@@ -633,7 +625,7 @@ bool FlipFramer::GetFrameBoundaries(const FlipFrame* frame,
FlipFrame* FlipFramer::CompressFrame(const FlipFrame* frame) {
int payload_length;
int header_length;
- const char* payload;
+ const unsigned char* payload;
static StatsCounter pre_compress_bytes("flip.PreCompressSize");
static StatsCounter post_compress_bytes("flip.PostCompressSize");
@@ -652,13 +644,13 @@ FlipFrame* FlipFramer::CompressFrame(const FlipFrame* frame) {
// Create an output frame.
int compressed_max_size = deflateBound(compressor_.get(), payload_length);
int new_frame_size = header_length + compressed_max_size;
- FlipFrame* new_frame = new FlipFrame(new_frame_size);
- memcpy(new_frame->data(), frame->data(), frame->length() + FlipFrame::size());
+ FlipFrame* new_frame =
+ reinterpret_cast<FlipFrame*>(new char[new_frame_size]);
+ memcpy(new_frame, frame, header_length);
- compressor_->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload));
+ compressor_->next_in = const_cast<Bytef*>(payload);
compressor_->avail_in = payload_length;
- compressor_->next_out = reinterpret_cast<Bytef*>(new_frame->data()) +
- header_length;
+ compressor_->next_out = reinterpret_cast<Bytef*>(new_frame) + header_length;
compressor_->avail_out = compressed_max_size;
// Data packets have a 'compressed flag
@@ -670,12 +662,12 @@ FlipFrame* FlipFramer::CompressFrame(const FlipFrame* frame) {
int rv = deflate(compressor_.get(), Z_SYNC_FLUSH);
if (rv != Z_OK) { // How can we know that it compressed everything?
// This shouldn't happen, right?
- delete [] new_frame;
+ free(new_frame);
return NULL;
}
int compressed_size = compressed_max_size - compressor_->avail_out;
- new_frame->set_length(header_length + compressed_size - FlipFrame::size());
+ new_frame->set_length(header_length + compressed_size - sizeof(FlipFrame));
pre_compress_bytes.Add(payload_length);
post_compress_bytes.Add(new_frame->length());
@@ -686,7 +678,7 @@ FlipFrame* FlipFramer::CompressFrame(const FlipFrame* frame) {
FlipFrame* FlipFramer::DecompressFrame(const FlipFrame* frame) {
int payload_length;
int header_length;
- const char* payload;
+ const unsigned char* payload;
static StatsCounter pre_decompress_bytes("flip.PreDeCompressSize");
static StatsCounter post_decompress_bytes("flip.PostDeCompressSize");
@@ -713,12 +705,13 @@ FlipFrame* FlipFramer::DecompressFrame(const FlipFrame* frame) {
// the input data.
int decompressed_max_size = kControlFrameBufferInitialSize;
int new_frame_size = header_length + decompressed_max_size;
- FlipFrame* new_frame = new FlipFrame(new_frame_size);
- memcpy(new_frame->data(), frame->data(), frame->length() + FlipFrame::size());
+ FlipFrame* new_frame =
+ reinterpret_cast<FlipFrame*>(new char[new_frame_size]);
+ memcpy(new_frame, frame, header_length);
- decompressor_->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload));
+ decompressor_->next_in = const_cast<Bytef*>(payload);
decompressor_->avail_in = payload_length;
- decompressor_->next_out = reinterpret_cast<Bytef*>(new_frame->data()) +
+ decompressor_->next_out = reinterpret_cast<Bytef*>(new_frame) +
header_length;
decompressor_->avail_out = decompressed_max_size;
@@ -733,7 +726,7 @@ FlipFrame* FlipFramer::DecompressFrame(const FlipFrame* frame) {
}
}
if (rv != Z_OK) { // How can we know that it decompressed everything?
- delete [] new_frame;
+ free(new_frame);
return NULL;
}
@@ -744,7 +737,7 @@ FlipFrame* FlipFramer::DecompressFrame(const FlipFrame* frame) {
}
int decompressed_size = decompressed_max_size - decompressor_->avail_out;
- new_frame->set_length(header_length + decompressed_size - FlipFrame::size());
+ new_frame->set_length(header_length + decompressed_size - sizeof(FlipFrame));
pre_decompress_bytes.Add(frame->length());
post_decompress_bytes.Add(new_frame->length());
@@ -753,10 +746,10 @@ FlipFrame* FlipFramer::DecompressFrame(const FlipFrame* frame) {
}
FlipFrame* FlipFramer::DuplicateFrame(const FlipFrame* frame) {
- int size = FlipFrame::size() + frame->length();
- FlipFrame* new_frame = new FlipFrame(size);
- memcpy(new_frame->data(), frame->data(), size);
- return new_frame;
+ int size = sizeof(FlipFrame) + frame->length();
+ char* new_frame = new char[size];
+ memcpy(new_frame, frame, size);
+ return reinterpret_cast<FlipFrame*>(new_frame);
}
void FlipFramer::set_enable_compression(bool value) {
diff --git a/net/flip/flip_framer.h b/net/flip/flip_framer.h
index b333176..d3cae28 100644
--- a/net/flip/flip_framer.h
+++ b/net/flip/flip_framer.h
@@ -30,11 +30,7 @@ namespace flip {
class FlipFramer;
class FlipFramerTest;
-
-namespace test {
class TestFlipVisitor;
-void FramerSetEnableCompressionHelper(FlipFramer* framer, bool compress);
-} // namespace test
// A datastructure for holding a set of headers from either a
// SYN_STREAM or SYN_REPLY frame.
@@ -62,6 +58,9 @@ class FlipFramerVisitorInterface {
virtual void OnStreamFrameData(flip::FlipStreamId stream_id,
const char* data,
size_t len) = 0;
+
+ // TODO(fenix): Implement me!
+ virtual void OnLameDuck() = 0;
};
class FlipFramer {
@@ -201,11 +200,9 @@ class FlipFramer {
protected:
FRIEND_TEST(FlipFramerTest, HeaderBlockBarfsOnOutOfOrderHeaders);
+ friend class flip::TestFlipVisitor;
friend class net::FlipNetworkTransactionTest;
friend class net::HttpNetworkLayer; // This is temporary for the server.
- friend class test::TestFlipVisitor;
- friend void test::FramerSetEnableCompressionHelper(FlipFramer* framer,
- bool compress);
// For ease of testing we can tweak compression on/off.
void set_enable_compression(bool value);
@@ -215,9 +212,7 @@ class FlipFramer {
// Internal breakout from ProcessInput. Returns the number of bytes
// consumed from the data.
size_t ProcessCommonHeader(const char* data, size_t len);
- void ProcessControlFrameHeader();
size_t ProcessControlFramePayload(const char* data, size_t len);
- size_t ProcessDataFramePayload(const char* data, size_t len);
// Initialize the ZLib state.
bool InitializeCompressor();
@@ -235,7 +230,8 @@ class FlipFramer {
// Given a frame, breakdown the variable payload length, the static header
// header length, and variable payload pointer.
bool GetFrameBoundaries(const FlipFrame* frame, int* payload_length,
- int* header_length, const char** payload) const;
+ int* header_length,
+ const unsigned char** payload) const;
FlipState state_;
FlipError error_code_;
diff --git a/net/flip/flip_framer_test.cc b/net/flip/flip_framer_test.cc
index 921e052..bee0432 100644
--- a/net/flip/flip_framer_test.cc
+++ b/net/flip/flip_framer_test.cc
@@ -2,10 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <algorithm>
#include <iostream>
-
#include "base/scoped_ptr.h"
+
#include "flip_framer.h" // cross-google3 directory naming.
#include "flip_protocol.h"
#include "flip_frame_builder.h"
@@ -13,15 +12,14 @@
namespace flip {
-namespace test {
-
-void FramerSetEnableCompressionHelper(FlipFramer* framer, bool compress) {
- framer->set_enable_compression(compress);
-}
+class FlipFramerTest : public PlatformTest {
+ public:
+ virtual void TearDown() {}
+};
class TestFlipVisitor : public FlipFramerVisitorInterface {
public:
- TestFlipVisitor()
+ explicit TestFlipVisitor()
: error_count_(0),
syn_frame_count_(0),
syn_reply_frame_count_(0),
@@ -39,9 +37,10 @@ class TestFlipVisitor : public FlipFramerVisitorInterface {
const char* data,
size_t len) {
if (len == 0)
- ++zero_length_data_frame_count_;
+ zero_length_data_frame_count_++;
data_bytes_ += len;
+#ifdef TEST_LOGGING
std::cerr << "OnStreamFrameData(" << stream_id << ", \"";
if (len > 0) {
for (size_t i = 0 ; i < len; ++i) {
@@ -49,6 +48,7 @@ class TestFlipVisitor : public FlipFramerVisitorInterface {
}
}
std::cerr << "\", " << len << ")\n";
+#endif // TEST_LOGGING
}
void OnControl(const FlipControlFrame* frame) {
@@ -56,12 +56,14 @@ class TestFlipVisitor : public FlipFramerVisitorInterface {
bool parsed_headers = false;
switch (frame->type()) {
case SYN_STREAM:
- parsed_headers = framer_.ParseHeaderBlock(frame, &headers);
+ parsed_headers = framer_.ParseHeaderBlock(
+ reinterpret_cast<const FlipFrame*>(frame), &headers);
DCHECK(parsed_headers);
syn_frame_count_++;
break;
case SYN_REPLY:
- parsed_headers = framer_.ParseHeaderBlock(frame, &headers);
+ parsed_headers = framer_.ParseHeaderBlock(
+ reinterpret_cast<const FlipFrame*>(frame), &headers);
DCHECK(parsed_headers);
syn_reply_frame_count_++;
break;
@@ -72,7 +74,10 @@ class TestFlipVisitor : public FlipFramerVisitorInterface {
DCHECK(false); // Error!
}
if (frame->flags() & CONTROL_FLAG_FIN)
- ++fin_flag_count_;
+ fin_flag_count_++;
+ }
+
+ void OnLameDuck() {
}
// Convenience function which runs a framer simulation with particular input.
@@ -108,27 +113,75 @@ class TestFlipVisitor : public FlipFramerVisitorInterface {
int zero_length_data_frame_count_; // The count of zero-length data frames.
};
-} // namespace test
+// Test our protocol constants
+TEST_F(FlipFramerTest, ProtocolConstants) {
+ EXPECT_EQ(8u, sizeof(FlipFrame));
+ EXPECT_EQ(8u, sizeof(FlipDataFrame));
+ EXPECT_EQ(12u, sizeof(FlipControlFrame));
+ EXPECT_EQ(16u, sizeof(FlipSynStreamControlFrame));
+ EXPECT_EQ(16u, sizeof(FlipSynReplyControlFrame));
+ EXPECT_EQ(16u, sizeof(FlipFinStreamControlFrame));
+ EXPECT_EQ(1, SYN_STREAM);
+ EXPECT_EQ(2, SYN_REPLY);
+ EXPECT_EQ(3, FIN_STREAM);
+}
-} // namespace flip
+// 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());
+}
-using flip::FlipFrame;
-using flip::FlipFrameBuilder;
-using flip::FlipFramer;
-using flip::FlipHeaderBlock;
-using flip::FlipSynStreamControlFrame;
-using flip::kControlFlagMask;
-using flip::CONTROL_FLAG_NONE;
-using flip::SYN_STREAM;
-using flip::test::FramerSetEnableCompressionHelper;
-using flip::test::TestFlipVisitor;
+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());
+}
-namespace {
+TEST_F(FlipFramerTest, ControlFrameStructs) {
+ FlipFramer framer;
+ FlipHeaderBlock headers;
-class FlipFramerTest : public PlatformTest {
- public:
- virtual void TearDown() {}
-};
+ scoped_array<FlipSynStreamControlFrame> syn_frame(
+ framer.CreateSynStream(123, 2, CONTROL_FLAG_NONE, 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, CONTROL_FLAG_NONE, 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) {
@@ -138,12 +191,13 @@ TEST_F(FlipFramerTest, HeaderBlock) {
FlipFramer framer;
// Encode the header block into a SynStream frame.
- scoped_ptr<FlipSynStreamControlFrame> frame(
+ scoped_array<FlipSynStreamControlFrame> frame(
framer.CreateSynStream(1, 1, CONTROL_FLAG_NONE, true, &headers));
EXPECT_TRUE(frame.get() != NULL);
FlipHeaderBlock new_headers;
- framer.ParseHeaderBlock(frame.get(), &new_headers);
+ FlipFrame* control_frame = reinterpret_cast<FlipFrame*>(frame.get());
+ framer.ParseHeaderBlock(control_frame, &new_headers);
EXPECT_EQ(headers.size(), new_headers.size());
EXPECT_EQ(headers["alpha"], new_headers["alpha"]);
@@ -166,13 +220,13 @@ TEST_F(FlipFramerTest, HeaderBlockBarfsOnOutOfOrderHeaders) {
frame.WriteString("alpha");
frame.WriteString("alpha");
// write the length
- frame.WriteUInt32ToOffset(4, frame.length() - FlipFrame::size());
+ frame.WriteUInt32ToOffset(4, frame.length() - sizeof(FlipFrame));
FlipHeaderBlock new_headers;
- scoped_ptr<FlipFrame> control_frame(frame.take());
+ const FlipFrame* control_frame = frame.data();
FlipFramer framer;
- FramerSetEnableCompressionHelper(&framer, false);
- EXPECT_FALSE(framer.ParseHeaderBlock(control_frame.get(), &new_headers));
+ framer.set_enable_compression(false);
+ EXPECT_FALSE(framer.ParseHeaderBlock(control_frame, &new_headers));
}
TEST_F(FlipFramerTest, BasicCompression) {
@@ -185,45 +239,26 @@ TEST_F(FlipFramerTest, BasicCompression) {
headers["content-length"] = "12";
FlipFramer framer;
- FramerSetEnableCompressionHelper(&framer, true);
- scoped_ptr<FlipSynStreamControlFrame>
+ scoped_array<FlipSynStreamControlFrame>
frame1(framer.CreateSynStream(1, 1, CONTROL_FLAG_NONE, true, &headers));
- scoped_ptr<FlipSynStreamControlFrame>
+ scoped_array<FlipSynStreamControlFrame>
frame2(framer.CreateSynStream(1, 1, CONTROL_FLAG_NONE, true, &headers));
// Expect the second frame to be more compact than the first.
- EXPECT_LE(frame2->length(), frame1->length());
+ EXPECT_LE(frame2.get()->length(), frame1.get()->length());
// Decompress the first frame
- scoped_ptr<FlipFrame> frame3(framer.DecompressFrame(frame1.get()));
+ scoped_array<FlipFrame> frame3(
+ framer.DecompressFrame(reinterpret_cast<FlipFrame*>(frame1.get())));
// Decompress the second frame
- scoped_ptr<FlipFrame> frame4(framer.DecompressFrame(frame2.get()));
+ scoped_array<FlipFrame> frame4(
+ framer.DecompressFrame(reinterpret_cast<FlipFrame*>(frame2.get())));
// Expect frames 3 & 4 to be the same.
EXPECT_EQ(0,
- memcmp(frame3->data(), frame4->data(),
- FlipFrame::size() + frame3->length()));
-}
-
-TEST_F(FlipFramerTest, DecompressUncompressedFrame) {
- FlipHeaderBlock headers;
- headers["server"] = "FlipServer 1.0";
- headers["date"] = "Mon 12 Jan 2009 12:12:12 PST";
- headers["status"] = "200";
- headers["version"] = "HTTP/1.1";
- headers["content-type"] = "text/html";
- headers["content-length"] = "12";
-
- FlipFramer framer;
- FramerSetEnableCompressionHelper(&framer, true);
- scoped_ptr<FlipSynStreamControlFrame>
- frame1(framer.CreateSynStream(1, 1, CONTROL_FLAG_NONE, false, &headers));
-
- // Decompress the frame
- scoped_ptr<FlipFrame> frame2(framer.DecompressFrame(frame1.get()));
-
- EXPECT_EQ(NULL, frame2.get());
+ memcmp(frame3.get(), frame4.get(),
+ sizeof(FlipFrame) + frame3.get()->length()));
}
TEST_F(FlipFramerTest, Basic) {
@@ -351,5 +386,6 @@ TEST_F(FlipFramerTest, FinOnSynReplyFrame) {
EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
}
-} // namespace
+} // namespace flip
+
diff --git a/net/flip/flip_protocol.h b/net/flip/flip_protocol.h
index 7c0c659..8a585bc 100644
--- a/net/flip/flip_protocol.h
+++ b/net/flip/flip_protocol.h
@@ -12,11 +12,11 @@
#else
#include <arpa/inet.h>
#endif
-
#include "base/basictypes.h"
#include "base/logging.h"
#include "flip_bitmasks.h" // cross-google3 directory naming.
+
// Data Frame Format
// +----------------------------------+
// |0| Stream-ID (31bits) |
@@ -116,22 +116,29 @@ typedef uint32 FlipStreamId;
#define FLIP_PRIORITY_LOWEST 3
#define FLIP_PRIORITY_HIGHEST 0
-// -------------------------------------------------------------------------
-// These structures mirror the protocol structure definitions.
-
-// For the control data structures, we pack so that sizes match the
-// protocol over-the-wire sizes.
-#pragma pack(push)
-#pragma pack(1)
-
// A special structure for the 8 bit flags and 24 bit length fields.
union FlagsAndLength {
- uint8 flags_[4]; // 8 bits
- uint32 length_; // 24 bits
+ uint8 flags_[4]; // 8 bits
+ uint32 length_; // 24 bits
};
-// The basic FLIP Frame.
-struct FlipFrameBlock {
+// All Flip Frame types derive from the FlipFrame struct.
+typedef struct {
+ 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;
+ }
+
+ protected:
union {
struct {
uint16 version_;
@@ -142,229 +149,74 @@ struct FlipFrameBlock {
} data_;
};
FlagsAndLength flags_length_;
-};
-
-// A Control Frame.
-struct FlipControlFrameBlock : FlipFrameBlock {
- FlipStreamId stream_id_;
-};
-
-// A SYN_STREAM Control Frame.
-struct FlipSynStreamControlFrameBlock : FlipControlFrameBlock {
- uint8 priority_;
- uint8 unused_;
-};
-
-// A SYN_REPLY Control Frame.
-struct FlipSynReplyControlFrameBlock : FlipControlFrameBlock {
- uint16 unused_;
-};
-
-// A FNI_STREAM Control Frame.
-struct FlipFinStreamControlFrameBlock : FlipControlFrameBlock {
- uint32 status_;
-};
-
-#pragma pack(pop)
-
-// -------------------------------------------------------------------------
-// Wrapper classes for various FLIP frames.
-
-// All Flip Frame types derive from this FlipFrame class.
-class FlipFrame {
- public:
- // Create a FlipFrame for a given sized buffer.
- explicit FlipFrame(size_t size) : frame_(NULL), needs_delete_(true) {
- DCHECK_GE(size, sizeof(struct FlipFrameBlock));
- char* buffer = new char[size];
- memset(buffer, 0, size);
- frame_ = reinterpret_cast<struct FlipFrameBlock*>(buffer);
- }
-
- // Create a FlipFrame using a pre-created buffer.
- // If |needs_delete| is true, this class takes ownership of the buffer
- // and will delete it on cleanup. The buffer must have been created using
- // new char[].
- // If |needs_delete| is false, the caller retains ownership
- // of the buffer and will keep the buffer alive longer than |this|. In other
- // words, this class does NOT create a copy of the buffer.
- FlipFrame(char* data, bool needs_delete)
- : frame_(reinterpret_cast<struct FlipFrameBlock*>(data)),
- needs_delete_(needs_delete) {
- DCHECK(frame_);
- }
-
- virtual ~FlipFrame() {
- if (needs_delete_) {
- char* buffer = reinterpret_cast<char*>(frame_);
- delete [] buffer;
- }
- frame_ = NULL;
- }
-
- // Provide access to the frame bytes
- char* data() const { return reinterpret_cast<char*>(frame_); }
-
- uint8 flags() const { return frame_->flags_length_.flags_[0]; }
- void set_flags(uint8 flags) { frame_->flags_length_.flags_[0] = flags; }
-
- uint32 length() const {
- return ntohl(frame_->flags_length_.length_) & kLengthMask;
- }
-
- void set_length(uint32 length) {
- DCHECK_EQ(0u, (length & ~kLengthMask));
- length = htonl(length & kLengthMask);
- frame_->flags_length_.length_ = flags() | length;
- }
-
- bool is_control_frame() const {
- return (ntohs(frame_->control_.version_) & kControlFlagMask) ==
- kControlFlagMask;
- }
-
- static size_t size() { return sizeof(struct FlipFrameBlock); }
-
- protected:
- FlipFrameBlock* frame_;
-
- private:
- bool needs_delete_;
- DISALLOW_COPY_AND_ASSIGN(FlipFrame);
-};
+} FlipFrame;
// A Data Frame.
-class FlipDataFrame : public FlipFrame {
- public:
- FlipDataFrame() : FlipFrame(size()) {}
- FlipDataFrame(char* data, bool needs_delete)
- : FlipFrame(data, needs_delete) {}
- virtual ~FlipDataFrame() {}
-
+typedef struct : public FlipFrame {
FlipStreamId stream_id() const {
- return ntohl(frame_->data_.stream_id_) & kStreamIdMask;
- }
-
- // Note that setting the stream id sets the control bit to false.
- // As stream id should always be set, this means the control bit
- // should always be set correctly.
- void set_stream_id(FlipStreamId id) {
- DCHECK_EQ(0u, (id & ~kStreamIdMask));
- frame_->data_.stream_id_ = htonl(id & kStreamIdMask);
+ return ntohl(data_.stream_id_) & kStreamIdMask;
}
-
- static size_t size() { return FlipFrame::size(); }
- private:
- DISALLOW_COPY_AND_ASSIGN(FlipDataFrame);
-};
+ void set_stream_id(FlipStreamId id) { data_.stream_id_ = htonl(id); }
+} FlipDataFrame;
// A Control Frame.
-class FlipControlFrame : public FlipFrame {
- public:
- explicit FlipControlFrame(size_t size) : FlipFrame(size) {}
- FlipControlFrame(char* data, bool needs_delete)
- : FlipFrame(data, needs_delete) {}
- virtual ~FlipControlFrame() {}
-
+typedef struct : public FlipFrame {
uint16 version() const {
const int kVersionMask = 0x7fff;
- return ntohs(block()->control_.version_) & kVersionMask;
+ return ntohs(control_.version_) & kVersionMask;
}
FlipControlType type() const {
- uint16 type = ntohs(block()->control_.type_);
+ uint16 type = ntohs(control_.type_);
DCHECK(type >= SYN_STREAM && type <= NOOP);
return static_cast<FlipControlType>(type);
}
- FlipStreamId stream_id() const {
- return ntohl(block()->stream_id_) & kStreamIdMask;
- }
-
- void set_stream_id(FlipStreamId id) {
- block()->stream_id_ = htonl(id & kStreamIdMask);
- }
-
- static size_t size() { return sizeof(FlipControlFrameBlock); }
+ FlipStreamId stream_id() const { return ntohl(stream_id_) & kStreamIdMask; }
private:
- struct FlipControlFrameBlock* block() const {
- return static_cast<FlipControlFrameBlock*>(frame_);
- }
- DISALLOW_COPY_AND_ASSIGN(FlipControlFrame);
-};
+ FlipStreamId stream_id_;
+} FlipControlFrame;
// A SYN_STREAM frame.
-class FlipSynStreamControlFrame : public FlipControlFrame {
- public:
- FlipSynStreamControlFrame() : FlipControlFrame(size()) {}
- FlipSynStreamControlFrame(char* data, bool needs_delete)
- : FlipControlFrame(data, needs_delete) {}
- virtual ~FlipSynStreamControlFrame() {}
-
- uint8 priority() const { return (block()->priority_ & kPriorityMask) >> 6; }
-
+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() - (size() - FlipFrame::size());
- }
-
+ int header_block_len() const { return length() - kHeaderBlockOffset; }
const char* header_block() const {
- return reinterpret_cast<const char*>(block()) + size();
+ return reinterpret_cast<const char*>(this) +
+ sizeof(FlipFrame) + kHeaderBlockOffset;
}
-
- static size_t size() { return sizeof(FlipSynStreamControlFrameBlock); }
-
private:
- struct FlipSynStreamControlFrameBlock* block() const {
- return static_cast<FlipSynStreamControlFrameBlock*>(frame_);
- }
- DISALLOW_COPY_AND_ASSIGN(FlipSynStreamControlFrame);
-};
+ // Offset from the end of the FlipControlFrame to the FlipHeaderBlock.
+ static const int kHeaderBlockOffset = 6;
+ uint8 priority_;
+ uint8 unused_;
+ // Variable FlipHeaderBlock here.
+} FlipSynStreamControlFrame;
// A SYN_REPLY frame.
-class FlipSynReplyControlFrame : public FlipControlFrame {
- public:
- FlipSynReplyControlFrame() : FlipControlFrame(size()) {}
- FlipSynReplyControlFrame(char* data, bool needs_delete)
- : FlipControlFrame(data, needs_delete) {}
- virtual ~FlipSynReplyControlFrame() {}
-
- int header_block_len() const {
- return length() - (size() - FlipFrame::size());
- }
-
+typedef struct FlipSynReplyControlFrame : public FlipControlFrame {
+ int header_block_len() const { return length() - kHeaderBlockOffset; }
const char* header_block() const {
- return reinterpret_cast<const char*>(block()) + size();
+ return reinterpret_cast<const char*>(this) +
+ sizeof(FlipFrame) + kHeaderBlockOffset;
}
- static size_t size() { return sizeof(FlipSynReplyControlFrameBlock); }
-
private:
- struct FlipSynReplyControlFrameBlock* block() const {
- return static_cast<FlipSynReplyControlFrameBlock*>(frame_);
- }
- DISALLOW_COPY_AND_ASSIGN(FlipSynReplyControlFrame);
-};
+ // Offset from the end of the FlipControlFrame to the FlipHeaderBlock.
+ static const int kHeaderBlockOffset = 6;
+ uint16 unused_;
+ // Variable FlipHeaderBlock here.
+} FlipSynReplyControlFrame;
// A FIN_STREAM frame.
-class FlipFinStreamControlFrame : public FlipControlFrame {
- public:
- FlipFinStreamControlFrame() : FlipControlFrame(size()) {}
- FlipFinStreamControlFrame(char* data, bool needs_delete)
- : FlipControlFrame(data, needs_delete) {}
- virtual ~FlipFinStreamControlFrame() {}
-
- uint32 status() const { return ntohl(block()->status_); }
- void set_status(uint32 status) { block()->status_ = htonl(status); }
-
- static size_t size() { return sizeof(FlipFinStreamControlFrameBlock); }
-
+typedef struct FlipFinStreamControlFrame : public FlipControlFrame {
+ uint32 status() const { return ntohl(status_); }
+ void set_status(int id) { status_ = htonl(id); }
private:
- struct FlipFinStreamControlFrameBlock* block() const {
- return static_cast<FlipFinStreamControlFrameBlock*>(frame_);
- }
- DISALLOW_COPY_AND_ASSIGN(FlipFinStreamControlFrame);
-};
+ uint32 status_;
+} FlipFinStreamControlFrame;
} // namespace flip
#endif // NET_FLIP_FLIP_PROTOCOL_H_
+
diff --git a/net/flip/flip_protocol_test.cc b/net/flip/flip_protocol_test.cc
deleted file mode 100644
index fb78b63..0000000
--- a/net/flip/flip_protocol_test.cc
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "flip_protocol.h"
-
-#include "base/scoped_ptr.h"
-#include "flip_bitmasks.h" // shared with server.
-#include "flip_framer.h"
-#ifdef _WIN32
-#include "testing/platform_test.h"
-#else
-#include "testing/base/public/gunit.h"
-#endif
-
-using flip::FlipDataFrame;
-using flip::FlipFrame;
-using flip::FlipControlFrame;
-using flip::FlipSynStreamControlFrame;
-using flip::FlipSynReplyControlFrame;
-using flip::FlipFinStreamControlFrame;
-using flip::FlipFramer;
-using flip::FlipHeaderBlock;
-using flip::FlagsAndLength;
-using flip::kLengthMask;
-using flip::kStreamIdMask;
-using flip::kFlipProtocolVersion;
-using flip::SYN_STREAM;
-using flip::SYN_REPLY;
-using flip::FIN_STREAM;
-using flip::CONTROL_FLAG_FIN;
-using flip::CONTROL_FLAG_NONE;
-
-namespace {
-
-// Test our protocol constants
-TEST(FlipProtocolTest, ProtocolConstants) {
- EXPECT_EQ(8u, FlipFrame::size());
- EXPECT_EQ(8u, FlipDataFrame::size());
- EXPECT_EQ(12u, FlipControlFrame::size());
- EXPECT_EQ(14u, FlipSynStreamControlFrame::size());
- EXPECT_EQ(14u, FlipSynReplyControlFrame::size());
- EXPECT_EQ(16u, FlipFinStreamControlFrame::size());
- EXPECT_EQ(4u, sizeof(FlagsAndLength));
- EXPECT_EQ(1, SYN_STREAM);
- EXPECT_EQ(2, SYN_REPLY);
- EXPECT_EQ(3, FIN_STREAM);
-}
-
-// Test some of the protocol helper functions
-TEST(FlipProtocolTest, FrameStructs) {
- FlipFrame frame(FlipFrame::size());
- 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());
-
- 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(FlipProtocolTest, DataFrameStructs) {
- FlipDataFrame data_frame;
- data_frame.set_stream_id(12345);
- EXPECT_EQ(12345u, data_frame.stream_id());
-}
-
-TEST(FlipProtocolTest, ControlFrameStructs) {
- FlipFramer framer;
- FlipHeaderBlock headers;
-
- scoped_ptr<FlipSynStreamControlFrame> syn_frame(
- framer.CreateSynStream(123, 2, CONTROL_FLAG_FIN, false, &headers));
- EXPECT_EQ(kFlipProtocolVersion, syn_frame->version());
- EXPECT_EQ(true, syn_frame->is_control_frame());
- EXPECT_EQ(SYN_STREAM, syn_frame->type());
- EXPECT_EQ(123u, syn_frame->stream_id());
- EXPECT_EQ(2u, syn_frame->priority());
- EXPECT_EQ(2, syn_frame->header_block_len());
- EXPECT_EQ(1u, syn_frame->flags());
-
- scoped_ptr<FlipSynReplyControlFrame> syn_reply(
- framer.CreateSynReply(123, CONTROL_FLAG_NONE, false, &headers));
- EXPECT_EQ(kFlipProtocolVersion, syn_reply->version());
- EXPECT_EQ(true, syn_reply->is_control_frame());
- EXPECT_EQ(SYN_REPLY, syn_reply->type());
- EXPECT_EQ(123u, syn_reply->stream_id());
- EXPECT_EQ(2, syn_reply->header_block_len());
- EXPECT_EQ(0, syn_reply->flags());
-
- scoped_ptr<FlipFinStreamControlFrame> fin_frame(
- framer.CreateFinStream(123, 444));
- EXPECT_EQ(kFlipProtocolVersion, fin_frame->version());
- EXPECT_EQ(true, fin_frame->is_control_frame());
- EXPECT_EQ(FIN_STREAM, fin_frame->type());
- EXPECT_EQ(123u, fin_frame->stream_id());
- EXPECT_EQ(444u, fin_frame->status());
- fin_frame->set_status(555);
- EXPECT_EQ(555u, fin_frame->status());
- EXPECT_EQ(0, fin_frame->flags());
-}
-
-TEST(FlipProtocolTest, TestDataFrame) {
- FlipDataFrame frame;
-
- // Set the stream ID to various values.
- frame.set_stream_id(0);
- EXPECT_EQ(0, frame.stream_id());
- EXPECT_FALSE(frame.is_control_frame());
- frame.set_stream_id(~0 & kStreamIdMask);
- EXPECT_EQ(~0 & kStreamIdMask, frame.stream_id());
- EXPECT_FALSE(frame.is_control_frame());
-
- // Set length to various values. Make sure that when you set_length(x),
- // length() == x. Also make sure the flags are unaltered.
- memset(frame.data(), '1', FlipDataFrame::size());
- int8 flags = frame.flags();
- frame.set_length(0);
- EXPECT_EQ(0, frame.length());
- EXPECT_EQ(flags, frame.flags());
- frame.set_length(kLengthMask);
- EXPECT_EQ(kLengthMask, frame.length());
- EXPECT_EQ(flags, frame.flags());
- frame.set_length(5);
- EXPECT_EQ(5, frame.length());
- EXPECT_EQ(flags, frame.flags());
-
- // Set flags to various values. Make sure that when you set_flags(x),
- // flags() == x. Also make sure the length is unaltered.
- memset(frame.data(), '1', FlipDataFrame::size());
- uint32 length = frame.length();
- frame.set_flags(0);
- EXPECT_EQ(0, frame.flags());
- EXPECT_EQ(length, frame.length());
- int8 all_flags = ~0;
- frame.set_flags(all_flags);
- flags = frame.flags();
- EXPECT_EQ(all_flags, flags);
- EXPECT_EQ(length, frame.length());
- frame.set_flags(5);
- EXPECT_EQ(5, frame.flags());
- EXPECT_EQ(length, frame.length());
-}
-
-// Make sure that overflows both die in debug mode, and do not cause problems
-// in opt mode. Note: Chrome doesn't die on DCHECK failures, so the
-// EXPECT_DEBUG_DEATH doesn't work.
-TEST(FlipProtocolDeathTest, TestDataFrame) {
- FlipDataFrame frame;
-
- frame.set_stream_id(0);
-#ifndef WIN32
- EXPECT_DEBUG_DEATH(frame.set_stream_id(~0), "");
-#endif
- EXPECT_FALSE(frame.is_control_frame());
-
- frame.set_flags(0);
-#ifndef WIN32
- EXPECT_DEBUG_DEATH(frame.set_length(~0), "");
-#endif
- EXPECT_EQ(0, frame.flags());
-}
-
-TEST(FlipProtocolDeathTest, TestFlipControlFrame) {
- FlipControlFrame frame(FlipControlFrame::size());
- memset(frame.data(), '1', FlipControlFrame::size());
-
- // Set the stream ID to various values.
- frame.set_stream_id(0);
- EXPECT_EQ(0, frame.stream_id());
- EXPECT_FALSE(frame.is_control_frame());
- frame.set_stream_id(~0 & kStreamIdMask);
- EXPECT_EQ(~0 & kStreamIdMask, frame.stream_id());
- EXPECT_FALSE(frame.is_control_frame());
-}
-
-} // namespace
-
diff --git a/net/flip/flip_session.cc b/net/flip/flip_session.cc
index 1f594eb..72bd387 100644
--- a/net/flip/flip_session.cc
+++ b/net/flip/flip_session.cc
@@ -188,12 +188,13 @@ int FlipSession::CreateStream(FlipDelegate* delegate) {
flags = flip::CONTROL_FLAG_FIN;
// Create a SYN_STREAM packet and add to the output queue.
- scoped_ptr<flip::FlipSynStreamControlFrame> syn_frame(
- flip_framer_.CreateSynStream(stream_id, priority, flags, false,
- &headers));
- int length = flip::FlipFrame::size() + syn_frame->length();
- IOBufferWithSize* buffer = new IOBufferWithSize(length);
- memcpy(buffer->data(), syn_frame->data(), length);
+ flip::FlipSynStreamControlFrame* syn_frame =
+ flip_framer_.CreateSynStream(stream_id, priority, flags, false, &headers);
+ int length = sizeof(flip::FlipFrame) + syn_frame->length();
+ IOBufferWithSize* buffer =
+ new IOBufferWithSize(length);
+ memcpy(buffer->data(), syn_frame, length);
+ delete[] syn_frame;
queue_.push(FlipIOBuffer(buffer, priority, stream));
static StatsCounter flip_requests("flip.requests");
@@ -410,16 +411,17 @@ void FlipSession::WriteSocket() {
// We've deferred compression until just before we write it to the socket,
// which is now.
- flip::FlipFrame uncompressed_frame(next_buffer.buffer()->data(), false);
- scoped_ptr<flip::FlipFrame> compressed_frame(
- flip_framer_.CompressFrame(&uncompressed_frame));
- size_t size = compressed_frame.get()->length() + flip::FlipFrame::size();
+ flip::FlipFrame* uncompressed_frame =
+ reinterpret_cast<flip::FlipFrame*>(next_buffer.buffer()->data());
+ scoped_array<flip::FlipFrame> compressed_frame(
+ flip_framer_.CompressFrame(uncompressed_frame));
+ size_t size = compressed_frame.get()->length() + sizeof(flip::FlipFrame);
DCHECK(size > 0);
// TODO(mbelshe): We have too much copying of data here.
IOBufferWithSize* buffer = new IOBufferWithSize(size);
- memcpy(buffer->data(), compressed_frame->data(), size);
+ memcpy(buffer->data(), compressed_frame.get(), size);
// Attempt to send the frame.
in_flight_write_ = FlipIOBuffer(buffer, 0, next_buffer.stream());
@@ -643,7 +645,8 @@ void FlipSession::OnControl(const flip::FlipControlFrame* frame) {
flip::FlipHeaderBlock headers;
uint32 type = frame->type();
if (type == flip::SYN_STREAM || type == flip::SYN_REPLY) {
- if (!flip_framer_.ParseHeaderBlock(frame, &headers)) {
+ if (!flip_framer_.ParseHeaderBlock(
+ reinterpret_cast<const flip::FlipFrame*>(frame), &headers)) {
LOG(WARNING) << "Could not parse Flip Control Frame Header";
return;
}
@@ -695,4 +698,8 @@ void FlipSession::OnFin(const flip::FlipFinStreamControlFrame* frame) {
}
}
+void FlipSession::OnLameDuck() {
+ NOTIMPLEMENTED();
+}
+
} // namespace net
diff --git a/net/flip/flip_session.h b/net/flip/flip_session.h
index 7c7ad78..a76630d 100644
--- a/net/flip/flip_session.h
+++ b/net/flip/flip_session.h
@@ -143,6 +143,7 @@ class FlipSession : public base::RefCounted<FlipSession>,
const char* data,
size_t len);
virtual void OnControl(const flip::FlipControlFrame* frame);
+ virtual void OnLameDuck();
// Control frame handlers.
void OnSyn(const flip::FlipSynStreamControlFrame* frame,