Skip to content

Commit

Permalink
Retry landing the flip changes. This time with DEPS!
Browse files Browse the repository at this point in the history
BUG=none 
TEST=flip_session_unittest.cc flip_network_transaction_unittest.cc flip_framer_test.cc 

Review URL: http://codereview.chromium.org/210016

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26533 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
mbelshe@google.com committed Sep 18, 2009
1 parent c69157c commit aea8060
Show file tree
Hide file tree
Showing 17 changed files with 3,770 additions and 0 deletions.
1 change: 1 addition & 0 deletions net/DEPS
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
include_rules = [
"+third_party/modp_b64",
"+third_party/libevent",
"+third_party/zlib",
"+sdch/open_vcdiff",
]
16 changes: 16 additions & 0 deletions net/flip/flip_bitmasks.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// 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.

#ifndef NET_FLIP_FLIP_BITMASKS_H_
#define NET_FLIP_FLIP_BITMASKS_H_

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
} // flip

#endif // NET_FLIP_FLIP_BITMASKS_H_

184 changes: 184 additions & 0 deletions net/flip/flip_frame_builder.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
// 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 <limits>

#include "flip_frame_builder.h" // cross-google3 directory naming.
#include "flip_protocol.h"

namespace flip {

// We mark a read only FlipFrameBuilder with a special capacity_.
static const size_t kCapacityReadOnly = std::numeric_limits<size_t>::max();

FlipFrameBuilder::FlipFrameBuilder()
: buffer_(NULL),
capacity_(0),
length_(0),
variable_buffer_offset_(0) {
Resize(kInitialPayload);
}

FlipFrameBuilder::FlipFrameBuilder(const char* data, int data_len)
: buffer_(const_cast<char*>(data)),
capacity_(kCapacityReadOnly),
length_(data_len),
variable_buffer_offset_(0) {
}

FlipFrameBuilder::~FlipFrameBuilder() {
if (capacity_ != kCapacityReadOnly)
delete[] buffer_;
}

bool FlipFrameBuilder::ReadUInt16(void** iter, uint16* result) const {
DCHECK(iter);
if (!*iter)
*iter = const_cast<char*>(buffer_);

if (!IteratorHasRoomFor(*iter, sizeof(*result)))
return false;

*result = ntohs(*(reinterpret_cast<uint16*>(*iter)));

UpdateIter(iter, sizeof(*result));
return true;
}

bool FlipFrameBuilder::ReadUInt32(void** iter, uint32* result) const {
DCHECK(iter);
if (!*iter)
*iter = const_cast<char*>(buffer_);

if (!IteratorHasRoomFor(*iter, sizeof(*result)))
return false;

*result = ntohl(*(reinterpret_cast<uint32*>(*iter)));

UpdateIter(iter, sizeof(*result));
return true;
}

bool FlipFrameBuilder::ReadString(void** iter, std::string* result) const {
DCHECK(iter);

uint16 len;
if (!ReadUInt16(iter, &len)) {
VLOG(1) << "Unable to read length";
return false;
}
if (!IteratorHasRoomFor(*iter, len)) {
VLOG(1) << "!IteratorHasRoomFor";
return false;
}

char* chars = reinterpret_cast<char*>(*iter);
result->assign(chars, len);

UpdateIter(iter, len);
return true;
}

bool FlipFrameBuilder::ReadBytes(void** iter, const char** data,
uint16 length) const {
DCHECK(iter);
DCHECK(data);

if (!IteratorHasRoomFor(*iter, length))
return false;

*data = reinterpret_cast<const char*>(*iter);

UpdateIter(iter, length);
return true;
}

bool FlipFrameBuilder::ReadData(void** iter, const char** data,
uint16* length) const {
DCHECK(iter);
DCHECK(data);
DCHECK(length);

if (!ReadUInt16(iter, length))
return false;

return ReadBytes(iter, data, *length);
}

char* FlipFrameBuilder::BeginWrite(size_t length) {
size_t offset = length_;
size_t needed_size = length_ + length;
if (needed_size > capacity_ && !Resize(std::max(capacity_ * 2, needed_size)))
return NULL;

#ifdef ARCH_CPU_64_BITS
DCHECK_LE(length, std::numeric_limits<uint32>::max());
#endif

return buffer_ + offset;
}

void FlipFrameBuilder::EndWrite(char* dest, int length) {
}

bool FlipFrameBuilder::WriteBytes(const void* data, uint16 data_len) {
DCHECK(capacity_ != kCapacityReadOnly);

char* dest = BeginWrite(data_len);
if (!dest)
return false;

memcpy(dest, data, data_len);

EndWrite(dest, data_len);
length_ += data_len;
return true;
}

bool FlipFrameBuilder::WriteString(const std::string& value) {
if (value.size() > 0xffff)
return false;

if (!WriteUInt16(static_cast<int>(value.size())))
return false;

return WriteBytes(value.data(), static_cast<uint16>(value.size()));
}

char* FlipFrameBuilder::BeginWriteData(uint16 length) {
DCHECK_EQ(variable_buffer_offset_, 0U) <<
"There can only be one variable buffer in a FlipFrameBuilder";

if (!WriteUInt16(length))
return false;

char *data_ptr = BeginWrite(length);
if (!data_ptr)
return NULL;

variable_buffer_offset_ = data_ptr - buffer_ - sizeof(int);

// EndWrite doesn't necessarily have to be called after the write operation,
// so we call it here to pad out what the caller will eventually write.
EndWrite(data_ptr, length);
return data_ptr;
}

bool FlipFrameBuilder::Resize(size_t new_capacity) {
if (new_capacity < capacity_)
return true;

char* p = new char[new_capacity];
if (buffer_) {
memcpy(p, buffer_, capacity_);
delete[] buffer_;
}
if (!p && new_capacity > 0)
return false;
buffer_ = p;
capacity_ = new_capacity;
return true;
}

} // namespace flip
184 changes: 184 additions & 0 deletions net/flip/flip_frame_builder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
// 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.

#ifndef NET_FLIP_FRAME_BUILDER_H_
#define NET_FLIP_FRAME_BUILDER_H_

#ifdef WIN32
#include <winsock2.h> // for htonl() functions
#else
#include <arpa/inet.h>
#endif

#include <string>

#include "base/logging.h"
#include "flip_protocol.h" // cross-google3 directory naming.

#ifdef WIN32
#undef VLOG
#define VLOG(x) LOG_IF(INFO, false)
#endif // WIN32

namespace flip {

// This class provides facilities for basic binary value packing and unpacking
// into Flip frames. Note: this is similar to Chrome's pickle class, but is
// simplified to work in both the client and server, and without excess
// padding.
//
// The FlipFrameBuilder supports appending primitive values (int, string, etc)
// to a frame instance. The FlipFrameBuilder grows its internal memory buffer
// dynamically to hold the sequence of primitive values. The internal memory
// buffer is exposed as the "data" of the FlipFrameBuilder.
//
// When reading from a FlipFrameBuilder the consumer must know what value types
// to read and in what order to read them as the FlipFrameBuilder does not keep
// track of the type of data written to it.
class FlipFrameBuilder {
public:
FlipFrameBuilder();
~FlipFrameBuilder();

// Initializes a FlipFrameBuilder from a const block of data. The data is
// not copied; instead the data is merely referenced by this
// FlipFrameBuilder. Only const methods should be used when initialized
// this way.
FlipFrameBuilder(const char* data, int data_len);

// 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 = reinterpret_cast<FlipFrame*>(buffer_);
buffer_ = NULL;
capacity_ = 0;
length_ = 0;
return rv;
}

// Methods for reading the payload of the FlipFrameBuilder. To read from the
// start of the FlipFrameBuilder, initialize *iter to NULL. If successful,
// these methods return true. Otherwise, false is returned to indicate that
// the result could not be extracted.
bool ReadUInt16(void** iter, uint16* result) const;
bool ReadUInt32(void** iter, uint32* result) const;
bool ReadString(void** iter, std::string* result) const;
bool ReadBytes(void** iter, const char** data, uint16 length) const;
bool ReadData(void** iter, const char** data, uint16* length) const;

// Methods for adding to the payload. These values are appended to the end
// of the FlipFrameBuilder payload. When reading values, you must read them
// in the order they were added. Note - binary integers are converted from
// host to network form.
bool WriteUInt16(uint16 value) {
value = htons(value);
return WriteBytes(&value, sizeof(value));
}
bool WriteUInt32(uint32 value) {
value = htonl(value);
return WriteBytes(&value, sizeof(value));
}
bool WriteString(const std::string& value);
bool WriteBytes(const void* data, uint16 data_len);

// Write an integer to a particular offset in the data buffer.
bool WriteUInt32ToOffset(int offset, uint32 value) {
if (offset + sizeof(value) > length_)
return false;
value = htonl(value);
char *ptr = buffer_ + offset;
memcpy(ptr, &value, sizeof(value));
return true;
}

// Allows the caller to write data directly into the FlipFrameBuilder.
// This saves a copy when the data is not already available in a buffer.
// The caller must not write more than the length it declares it will.
// Use ReadData to get the data.
// Returns NULL on failure.
//
// The returned pointer will only be valid until the next write operation
// on this FlipFrameBuilder.
char* BeginWriteData(uint16 length);

// Returns true if the given iterator could point to data with the given
// length. If there is no room for the given data before the end of the
// payload, returns false.
bool IteratorHasRoomFor(const void* iter, int len) const {
const char* end_of_region = reinterpret_cast<const char*>(iter) + len;
VLOG(1) << "len: " << len;
if (len < 0) {
VLOG(1) << "Len < 0";
return false;
} else if (iter < buffer_) {
VLOG(1) << "iter < buffer_";
return false;
} else if (iter > end_of_payload()) {
VLOG(1) << "iter > end_of_payload())";
return false;
} else if (iter > end_of_region) {
VLOG(1) << "iter > end_of_region)";
return false;
} else if (end_of_region > end_of_payload()) {
VLOG(1) << "end_of_region > end_of_payload()";
VLOG(1) << "end_of_region - end_of_payload(): "
<< (end_of_region - end_of_payload());

return false;
}

// Watch out for overflow in pointer calculation, which wraps.
return (iter <= end_of_region) && (end_of_region <= end_of_payload());
}

protected:
size_t capacity() const {
return capacity_;
}

const char* end_of_payload() const { return buffer_ + length_; }

// Resizes the buffer for use when writing the specified amount of data. The
// location that the data should be written at is returned, or NULL if there
// was an error. Call EndWrite with the returned offset and the given length
// to pad out for the next write.
char* BeginWrite(size_t length);

// Completes the write operation by padding the data with NULL bytes until it
// is padded. Should be paired with BeginWrite, but it does not necessarily
// have to be called after the data is written.
void EndWrite(char* dest, int length);

// Resize the capacity, note that the input value should include the size of
// the header: new_capacity = sizeof(Header) + desired_payload_capacity.
// A new failure will cause a Resize failure... and caller should check
// the return result for true (i.e., successful resizing).
bool Resize(size_t new_capacity);

// Moves the iterator by the given number of bytes.
static void UpdateIter(void** iter, int bytes) {
*iter = static_cast<char*>(*iter) + bytes;
}

// Initial size of the payload.
static const int kInitialPayload = 1024;

private:
char* buffer_;
size_t capacity_; // Allocation size of payload (or -1 if buffer is const).
size_t length_; // current length of the buffer
size_t variable_buffer_offset_; // IF non-zero, then offset to a buffer.
};

} // namespace flip

#endif // NET_FLIP_FRAME_BUILDER_H_

Loading

0 comments on commit aea8060

Please sign in to comment.