13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
53345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#ifndef NET_SPDY_SPDY_FRAME_BUILDER_H_
63345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#define NET_SPDY_SPDY_FRAME_BUILDER_H_
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/basictypes.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/sys_byteorder.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_protocol.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace spdy {
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This class provides facilities for basic binary value packing and unpacking
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// into Spdy frames.
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The SpdyFrameBuilder supports appending primitive values (int, string, etc)
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to a frame instance.  The SpdyFrameBuilder grows its internal memory buffer
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// dynamically to hold the sequence of primitive values.   The internal memory
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// buffer is exposed as the "data" of the SpdyFrameBuilder.
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// When reading from a SpdyFrameBuilder the consumer must know what value types
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to read and in what order to read them as the SpdyFrameBuilder does not keep
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// track of the type of data written to it.
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SpdyFrameBuilder {
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SpdyFrameBuilder();
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Initializes a SpdyFrameBuilder from a const block of data.  The data is
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // not copied; instead the data is merely referenced by this
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // SpdyFrameBuilder.  Only const methods should be used when initialized
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // this way.
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SpdyFrameBuilder(const char* data, int data_len);
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ~SpdyFrameBuilder();
3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns the size of the SpdyFrameBuilder's data.
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int length() const { return length_; }
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Takes the buffer from the SpdyFrameBuilder.
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SpdyFrame* take() {
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SpdyFrame* rv = new SpdyFrame(buffer_, true);
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    buffer_ = NULL;
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    capacity_ = 0;
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    length_ = 0;
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return rv;
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Methods for reading the payload of the SpdyFrameBuilder.  To read from the
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // start of the SpdyFrameBuilder, initialize *iter to NULL.  If successful,
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // these methods return true.  Otherwise, false is returned to indicate that
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the result could not be extracted.
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool ReadUInt16(void** iter, uint16* result) const;
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool ReadUInt32(void** iter, uint32* result) const;
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool ReadString(void** iter, std::string* result) const;
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool ReadBytes(void** iter, const char** data, uint16 length) const;
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool ReadData(void** iter, const char** data, uint16* length) const;
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Methods for adding to the payload.  These values are appended to the end
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // of the SpdyFrameBuilder payload.  When reading values, you must read them
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // in the order they were added.  Note - binary integers are converted from
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // host to network form.
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool WriteUInt16(uint16 value) {
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    value = htons(value);
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return WriteBytes(&value, sizeof(value));
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool WriteUInt32(uint32 value) {
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    value = htonl(value);
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return WriteBytes(&value, sizeof(value));
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool WriteString(const std::string& value);
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool WriteBytes(const void* data, uint16 data_len);
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Write an integer to a particular offset in the data buffer.
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool WriteUInt32ToOffset(int offset, uint32 value) {
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    value = htonl(value);
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return WriteBytesToOffset(offset, &value, sizeof(value));
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Write to a particular offset in the data buffer.
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool WriteBytesToOffset(int offset, const void* data, uint32 data_len) {
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (offset + data_len > length_)
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    char *ptr = buffer_ + offset;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    memcpy(ptr, data, data_len);
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Allows the caller to write data directly into the SpdyFrameBuilder.
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This saves a copy when the data is not already available in a buffer.
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The caller must not write more than the length it declares it will.
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Use ReadData to get the data.
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns NULL on failure.
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The returned pointer will only be valid until the next write operation
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // on this SpdyFrameBuilder.
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char* BeginWriteData(uint16 length);
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns true if the given iterator could point to data with the given
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // length. If there is no room for the given data before the end of the
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // payload, returns false.
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool IteratorHasRoomFor(const void* iter, int len) const {
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* end_of_region = reinterpret_cast<const char*>(iter) + len;
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (len < 0 ||
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        iter < buffer_ ||
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        iter > end_of_payload() ||
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        iter > end_of_region ||
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        end_of_region > end_of_payload())
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Watch out for overflow in pointer calculation, which wraps.
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return (iter <= end_of_region) && (end_of_region <= end_of_payload());
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected:
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size_t capacity() const {
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return capacity_;
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* end_of_payload() const { return buffer_ + length_; }
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Resizes the buffer for use when writing the specified amount of data. The
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // location that the data should be written at is returned, or NULL if there
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // was an error. Call EndWrite with the returned offset and the given length
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to pad out for the next write.
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char* BeginWrite(size_t length);
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Completes the write operation by padding the data with NULL bytes until it
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // is padded. Should be paired with BeginWrite, but it does not necessarily
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // have to be called after the data is written.
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void EndWrite(char* dest, int length);
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Resize the capacity, note that the input value should include the size of
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the header: new_capacity = sizeof(Header) + desired_payload_capacity.
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // A new failure will cause a Resize failure... and caller should check
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the return result for true (i.e., successful resizing).
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool Resize(size_t new_capacity);
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Moves the iterator by the given number of bytes.
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static void UpdateIter(void** iter, int bytes) {
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *iter = static_cast<char*>(*iter) + bytes;
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Initial size of the payload.
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const int kInitialPayload = 1024;
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char* buffer_;
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size_t capacity_;  // Allocation size of payload (or -1 if buffer is const).
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size_t length_;    // current length of the buffer
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size_t variable_buffer_offset_;  // IF non-zero, then offset to a buffer.
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace spdy
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif  // NET_SPDY_SPDY_FRAME_BUILDER_H_
160