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