blob: 548cfda6f57a3e4eec242cea7cd37e238136c8dc [file] [log] [blame]
[email protected]1407b6e2010-08-27 21:39:481// Copyright (c) 2010 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
9#ifdef WIN32
10#include <winsock2.h> // for htonl() functions
11#else
12#include <arpa/inet.h>
13#endif
14
15#include <string>
16
[email protected]1407b6e2010-08-27 21:39:4817#include "base/basictypes.h"
[email protected]dab9c7d2010-02-06 21:44:3218#include "net/spdy/spdy_protocol.h"
[email protected]aea80602009-09-18 00:55:0819
[email protected]955fc2e72010-02-08 20:37:3020namespace spdy {
[email protected]aea80602009-09-18 00:55:0821
22// This class provides facilities for basic binary value packing and unpacking
[email protected]955fc2e72010-02-08 20:37:3023// into Spdy frames.
[email protected]aea80602009-09-18 00:55:0824//
[email protected]955fc2e72010-02-08 20:37:3025// The SpdyFrameBuilder supports appending primitive values (int, string, etc)
26// to a frame instance. The SpdyFrameBuilder grows its internal memory buffer
[email protected]aea80602009-09-18 00:55:0827// dynamically to hold the sequence of primitive values. The internal memory
[email protected]955fc2e72010-02-08 20:37:3028// buffer is exposed as the "data" of the SpdyFrameBuilder.
[email protected]aea80602009-09-18 00:55:0829//
[email protected]955fc2e72010-02-08 20:37:3030// When reading from a SpdyFrameBuilder the consumer must know what value types
31// to read and in what order to read them as the SpdyFrameBuilder does not keep
[email protected]aea80602009-09-18 00:55:0832// track of the type of data written to it.
[email protected]955fc2e72010-02-08 20:37:3033class SpdyFrameBuilder {
[email protected]aea80602009-09-18 00:55:0834 public:
[email protected]955fc2e72010-02-08 20:37:3035 SpdyFrameBuilder();
36 ~SpdyFrameBuilder();
[email protected]aea80602009-09-18 00:55:0837
[email protected]955fc2e72010-02-08 20:37:3038 // Initializes a SpdyFrameBuilder from a const block of data. The data is
[email protected]aea80602009-09-18 00:55:0839 // not copied; instead the data is merely referenced by this
[email protected]955fc2e72010-02-08 20:37:3040 // SpdyFrameBuilder. Only const methods should be used when initialized
[email protected]aea80602009-09-18 00:55:0841 // this way.
[email protected]955fc2e72010-02-08 20:37:3042 SpdyFrameBuilder(const char* data, int data_len);
[email protected]aea80602009-09-18 00:55:0843
[email protected]955fc2e72010-02-08 20:37:3044 // Returns the size of the SpdyFrameBuilder's data.
[email protected]aea80602009-09-18 00:55:0845 int length() const { return length_; }
46
[email protected]955fc2e72010-02-08 20:37:3047 // Takes the buffer from the SpdyFrameBuilder.
48 SpdyFrame* take() {
49 SpdyFrame* rv = new SpdyFrame(buffer_, true);
[email protected]aea80602009-09-18 00:55:0850 buffer_ = NULL;
51 capacity_ = 0;
52 length_ = 0;
53 return rv;
54 }
55
[email protected]955fc2e72010-02-08 20:37:3056 // Methods for reading the payload of the SpdyFrameBuilder. To read from the
57 // start of the SpdyFrameBuilder, initialize *iter to NULL. If successful,
[email protected]aea80602009-09-18 00:55:0858 // these methods return true. Otherwise, false is returned to indicate that
59 // the result could not be extracted.
60 bool ReadUInt16(void** iter, uint16* result) const;
61 bool ReadUInt32(void** iter, uint32* result) const;
62 bool ReadString(void** iter, std::string* result) const;
63 bool ReadBytes(void** iter, const char** data, uint16 length) const;
64 bool ReadData(void** iter, const char** data, uint16* length) const;
65
66 // Methods for adding to the payload. These values are appended to the end
[email protected]955fc2e72010-02-08 20:37:3067 // of the SpdyFrameBuilder payload. When reading values, you must read them
[email protected]aea80602009-09-18 00:55:0868 // in the order they were added. Note - binary integers are converted from
69 // host to network form.
70 bool WriteUInt16(uint16 value) {
71 value = htons(value);
72 return WriteBytes(&value, sizeof(value));
73 }
74 bool WriteUInt32(uint32 value) {
75 value = htonl(value);
76 return WriteBytes(&value, sizeof(value));
77 }
78 bool WriteString(const std::string& value);
79 bool WriteBytes(const void* data, uint16 data_len);
80
81 // Write an integer to a particular offset in the data buffer.
82 bool WriteUInt32ToOffset(int offset, uint32 value) {
[email protected]aea80602009-09-18 00:55:0883 value = htonl(value);
[email protected]289b93d72009-10-20 15:32:3284 return WriteBytesToOffset(offset, &value, sizeof(value));
85 }
86
87 // Write to a particular offset in the data buffer.
88 bool WriteBytesToOffset(int offset, const void* data, uint32 data_len) {
89 if (offset + data_len > length_)
90 return false;
[email protected]aea80602009-09-18 00:55:0891 char *ptr = buffer_ + offset;
[email protected]289b93d72009-10-20 15:32:3292 memcpy(ptr, data, data_len);
[email protected]aea80602009-09-18 00:55:0893 return true;
94 }
95
[email protected]955fc2e72010-02-08 20:37:3096 // Allows the caller to write data directly into the SpdyFrameBuilder.
[email protected]aea80602009-09-18 00:55:0897 // This saves a copy when the data is not already available in a buffer.
98 // The caller must not write more than the length it declares it will.
99 // Use ReadData to get the data.
100 // Returns NULL on failure.
101 //
102 // The returned pointer will only be valid until the next write operation
[email protected]955fc2e72010-02-08 20:37:30103 // on this SpdyFrameBuilder.
[email protected]aea80602009-09-18 00:55:08104 char* BeginWriteData(uint16 length);
105
106 // Returns true if the given iterator could point to data with the given
107 // length. If there is no room for the given data before the end of the
108 // payload, returns false.
109 bool IteratorHasRoomFor(const void* iter, int len) const {
110 const char* end_of_region = reinterpret_cast<const char*>(iter) + len;
[email protected]d8c21a52009-10-07 01:55:21111 if (len < 0 ||
112 iter < buffer_ ||
113 iter > end_of_payload() ||
114 iter > end_of_region ||
115 end_of_region > end_of_payload())
[email protected]aea80602009-09-18 00:55:08116 return false;
[email protected]aea80602009-09-18 00:55:08117
118 // Watch out for overflow in pointer calculation, which wraps.
119 return (iter <= end_of_region) && (end_of_region <= end_of_payload());
120 }
121
122 protected:
123 size_t capacity() const {
124 return capacity_;
125 }
126
127 const char* end_of_payload() const { return buffer_ + length_; }
128
129 // Resizes the buffer for use when writing the specified amount of data. The
130 // location that the data should be written at is returned, or NULL if there
131 // was an error. Call EndWrite with the returned offset and the given length
132 // to pad out for the next write.
133 char* BeginWrite(size_t length);
134
135 // Completes the write operation by padding the data with NULL bytes until it
136 // is padded. Should be paired with BeginWrite, but it does not necessarily
137 // have to be called after the data is written.
138 void EndWrite(char* dest, int length);
139
140 // Resize the capacity, note that the input value should include the size of
141 // the header: new_capacity = sizeof(Header) + desired_payload_capacity.
142 // A new failure will cause a Resize failure... and caller should check
143 // the return result for true (i.e., successful resizing).
144 bool Resize(size_t new_capacity);
145
146 // Moves the iterator by the given number of bytes.
147 static void UpdateIter(void** iter, int bytes) {
148 *iter = static_cast<char*>(*iter) + bytes;
149 }
150
151 // Initial size of the payload.
152 static const int kInitialPayload = 1024;
153
154 private:
155 char* buffer_;
156 size_t capacity_; // Allocation size of payload (or -1 if buffer is const).
157 size_t length_; // current length of the buffer
158 size_t variable_buffer_offset_; // IF non-zero, then offset to a buffer.
159};
160
[email protected]955fc2e72010-02-08 20:37:30161} // namespace spdy
[email protected]aea80602009-09-18 00:55:08162
[email protected]1407b6e2010-08-27 21:39:48163#endif // NET_SPDY_SPDY_FRAME_BUILDER_H_