blob: 403e819540e71ecbee70417985a0ba2065d6fb73 [file] [log] [blame]
[email protected]66a4b6d2011-05-19 23:36:161// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]aea80602009-09-18 00:55:082// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]1407b6e2010-08-27 21:39:485#ifndef NET_SPDY_SPDY_FRAME_BUILDER_H_
6#define NET_SPDY_SPDY_FRAME_BUILDER_H_
[email protected]32b76ef2010-07-26 23:08:247#pragma once
[email protected]aea80602009-09-18 00:55:088
[email protected]aea80602009-09-18 00:55:089#include <string>
10
[email protected]1407b6e2010-08-27 21:39:4811#include "base/basictypes.h"
[email protected]0e6f6192011-12-28 23:18:2112#include "base/sys_byteorder.h"
[email protected]172da1b2011-08-12 15:52:2613#include "net/base/net_export.h"
[email protected]dab9c7d2010-02-06 21:44:3214#include "net/spdy/spdy_protocol.h"
[email protected]aea80602009-09-18 00:55:0815
[email protected]955fc2e72010-02-08 20:37:3016namespace spdy {
[email protected]aea80602009-09-18 00:55:0817
18// This class provides facilities for basic binary value packing and unpacking
[email protected]955fc2e72010-02-08 20:37:3019// into Spdy frames.
[email protected]aea80602009-09-18 00:55:0820//
[email protected]955fc2e72010-02-08 20:37:3021// The SpdyFrameBuilder supports appending primitive values (int, string, etc)
22// to a frame instance. The SpdyFrameBuilder grows its internal memory buffer
[email protected]aea80602009-09-18 00:55:0823// dynamically to hold the sequence of primitive values. The internal memory
[email protected]955fc2e72010-02-08 20:37:3024// buffer is exposed as the "data" of the SpdyFrameBuilder.
[email protected]aea80602009-09-18 00:55:0825//
[email protected]955fc2e72010-02-08 20:37:3026// When reading from a SpdyFrameBuilder the consumer must know what value types
27// to read and in what order to read them as the SpdyFrameBuilder does not keep
[email protected]aea80602009-09-18 00:55:0828// track of the type of data written to it.
[email protected]172da1b2011-08-12 15:52:2629class NET_EXPORT_PRIVATE SpdyFrameBuilder {
[email protected]aea80602009-09-18 00:55:0830 public:
[email protected]fb2323d72011-11-29 03:13:0331 ~SpdyFrameBuilder();
32
[email protected]955fc2e72010-02-08 20:37:3033 SpdyFrameBuilder();
[email protected]aea80602009-09-18 00:55:0834
[email protected]8ac2a022011-11-04 00:01:5735 // Initiailizes a SpdyFrameBuilder with a buffer of given size.
36 // The buffer will still be resized as necessary.
37 explicit SpdyFrameBuilder(size_t size);
38
[email protected]955fc2e72010-02-08 20:37:3039 // Initializes a SpdyFrameBuilder from a const block of data. The data is
[email protected]aea80602009-09-18 00:55:0840 // not copied; instead the data is merely referenced by this
[email protected]955fc2e72010-02-08 20:37:3041 // SpdyFrameBuilder. Only const methods should be used when initialized
[email protected]aea80602009-09-18 00:55:0842 // this way.
[email protected]955fc2e72010-02-08 20:37:3043 SpdyFrameBuilder(const char* data, int data_len);
[email protected]aea80602009-09-18 00:55:0844
[email protected]955fc2e72010-02-08 20:37:3045 // Returns the size of the SpdyFrameBuilder's data.
[email protected]aea80602009-09-18 00:55:0846 int length() const { return length_; }
47
[email protected]955fc2e72010-02-08 20:37:3048 // Takes the buffer from the SpdyFrameBuilder.
49 SpdyFrame* take() {
50 SpdyFrame* rv = new SpdyFrame(buffer_, true);
[email protected]aea80602009-09-18 00:55:0851 buffer_ = NULL;
52 capacity_ = 0;
53 length_ = 0;
54 return rv;
55 }
56
[email protected]955fc2e72010-02-08 20:37:3057 // Methods for reading the payload of the SpdyFrameBuilder. To read from the
58 // start of the SpdyFrameBuilder, initialize *iter to NULL. If successful,
[email protected]aea80602009-09-18 00:55:0859 // these methods return true. Otherwise, false is returned to indicate that
60 // the result could not be extracted.
61 bool ReadUInt16(void** iter, uint16* result) const;
62 bool ReadUInt32(void** iter, uint32* result) const;
63 bool ReadString(void** iter, std::string* result) const;
[email protected]d27ea08b2011-12-27 18:43:0664 bool ReadBytes(void** iter, const char** data, uint32 length) const;
[email protected]aea80602009-09-18 00:55:0865 bool ReadData(void** iter, const char** data, uint16* length) const;
[email protected]d27ea08b2011-12-27 18:43:0666 bool ReadReadLen32PrefixedData(void** iter,
67 const char** data,
68 uint32* length) const;
[email protected]aea80602009-09-18 00:55:0869
70 // Methods for adding to the payload. These values are appended to the end
[email protected]955fc2e72010-02-08 20:37:3071 // of the SpdyFrameBuilder payload. When reading values, you must read them
[email protected]aea80602009-09-18 00:55:0872 // in the order they were added. Note - binary integers are converted from
73 // host to network form.
74 bool WriteUInt16(uint16 value) {
75 value = htons(value);
76 return WriteBytes(&value, sizeof(value));
77 }
78 bool WriteUInt32(uint32 value) {
79 value = htonl(value);
80 return WriteBytes(&value, sizeof(value));
81 }
82 bool WriteString(const std::string& value);
[email protected]fb2323d72011-11-29 03:13:0383 bool WriteBytes(const void* data, uint32 data_len);
[email protected]aea80602009-09-18 00:55:0884
85 // Write an integer to a particular offset in the data buffer.
86 bool WriteUInt32ToOffset(int offset, uint32 value) {
[email protected]aea80602009-09-18 00:55:0887 value = htonl(value);
[email protected]289b93d72009-10-20 15:32:3288 return WriteBytesToOffset(offset, &value, sizeof(value));
89 }
90
91 // Write to a particular offset in the data buffer.
92 bool WriteBytesToOffset(int offset, const void* data, uint32 data_len) {
93 if (offset + data_len > length_)
94 return false;
[email protected]aea80602009-09-18 00:55:0895 char *ptr = buffer_ + offset;
[email protected]289b93d72009-10-20 15:32:3296 memcpy(ptr, data, data_len);
[email protected]aea80602009-09-18 00:55:0897 return true;
98 }
99
[email protected]955fc2e72010-02-08 20:37:30100 // Allows the caller to write data directly into the SpdyFrameBuilder.
[email protected]aea80602009-09-18 00:55:08101 // This saves a copy when the data is not already available in a buffer.
102 // The caller must not write more than the length it declares it will.
103 // Use ReadData to get the data.
104 // Returns NULL on failure.
105 //
106 // The returned pointer will only be valid until the next write operation
[email protected]955fc2e72010-02-08 20:37:30107 // on this SpdyFrameBuilder.
[email protected]aea80602009-09-18 00:55:08108 char* BeginWriteData(uint16 length);
109
110 // Returns true if the given iterator could point to data with the given
111 // length. If there is no room for the given data before the end of the
112 // payload, returns false.
113 bool IteratorHasRoomFor(const void* iter, int len) const {
114 const char* end_of_region = reinterpret_cast<const char*>(iter) + len;
[email protected]d8c21a52009-10-07 01:55:21115 if (len < 0 ||
116 iter < buffer_ ||
117 iter > end_of_payload() ||
118 iter > end_of_region ||
119 end_of_region > end_of_payload())
[email protected]aea80602009-09-18 00:55:08120 return false;
[email protected]aea80602009-09-18 00:55:08121
122 // Watch out for overflow in pointer calculation, which wraps.
123 return (iter <= end_of_region) && (end_of_region <= end_of_payload());
124 }
125
126 protected:
127 size_t capacity() const {
128 return capacity_;
129 }
130
131 const char* end_of_payload() const { return buffer_ + length_; }
132
133 // Resizes the buffer for use when writing the specified amount of data. The
134 // location that the data should be written at is returned, or NULL if there
135 // was an error. Call EndWrite with the returned offset and the given length
136 // to pad out for the next write.
137 char* BeginWrite(size_t length);
138
139 // Completes the write operation by padding the data with NULL bytes until it
140 // is padded. Should be paired with BeginWrite, but it does not necessarily
141 // have to be called after the data is written.
142 void EndWrite(char* dest, int length);
143
144 // Resize the capacity, note that the input value should include the size of
145 // the header: new_capacity = sizeof(Header) + desired_payload_capacity.
146 // A new failure will cause a Resize failure... and caller should check
147 // the return result for true (i.e., successful resizing).
148 bool Resize(size_t new_capacity);
149
150 // Moves the iterator by the given number of bytes.
151 static void UpdateIter(void** iter, int bytes) {
152 *iter = static_cast<char*>(*iter) + bytes;
153 }
154
155 // Initial size of the payload.
156 static const int kInitialPayload = 1024;
157
158 private:
159 char* buffer_;
160 size_t capacity_; // Allocation size of payload (or -1 if buffer is const).
161 size_t length_; // current length of the buffer
162 size_t variable_buffer_offset_; // IF non-zero, then offset to a buffer.
163};
164
[email protected]955fc2e72010-02-08 20:37:30165} // namespace spdy
[email protected]aea80602009-09-18 00:55:08166
[email protected]1407b6e2010-08-27 21:39:48167#endif // NET_SPDY_SPDY_FRAME_BUILDER_H_