summaryrefslogtreecommitdiffstats
path: root/net/spdy/spdy_frame_builder.h
diff options
context:
space:
mode:
Diffstat (limited to 'net/spdy/spdy_frame_builder.h')
-rw-r--r--net/spdy/spdy_frame_builder.h163
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_
+