diff options
Diffstat (limited to 'net/spdy/spdy_frame_builder.h')
-rw-r--r-- | net/spdy/spdy_frame_builder.h | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/net/spdy/spdy_frame_builder.h b/net/spdy/spdy_frame_builder.h new file mode 100644 index 0000000..240aae1f --- /dev/null +++ b/net/spdy/spdy_frame_builder.h @@ -0,0 +1,163 @@ +// 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 "net/spdy/spdy_protocol.h" + +namespace flip { + +// This class provides facilities for basic binary value packing and unpacking +// into Flip frames. +// +// 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_; } + + // Takes the buffer from the FlipFrameBuilder. + FlipFrame* take() { + FlipFrame* rv = new FlipFrame(buffer_, true); + 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) { + value = htonl(value); + return WriteBytesToOffset(offset, &value, sizeof(value)); + } + + // Write to a particular offset in the data buffer. + bool WriteBytesToOffset(int offset, const void* data, uint32 data_len) { + if (offset + data_len > length_) + return false; + char *ptr = buffer_ + offset; + memcpy(ptr, data, data_len); + 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; + if (len < 0 || + iter < buffer_ || + iter > end_of_payload() || + iter > end_of_region || + 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_ + |