1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2009 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 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <limits> 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_frame_builder.h" 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_protocol.h" 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace spdy { 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We mark a read only SpdyFrameBuilder with a special capacity_. 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const size_t kCapacityReadOnly = std::numeric_limits<size_t>::max(); 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSpdyFrameBuilder::SpdyFrameBuilder() 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : buffer_(NULL), 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch capacity_(0), 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch length_(0), 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch variable_buffer_offset_(0) { 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Resize(kInitialPayload); 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSpdyFrameBuilder::SpdyFrameBuilder(const char* data, int data_len) 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : buffer_(const_cast<char*>(data)), 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch capacity_(kCapacityReadOnly), 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch length_(data_len), 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch variable_buffer_offset_(0) { 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSpdyFrameBuilder::~SpdyFrameBuilder() { 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (capacity_ != kCapacityReadOnly) 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete[] buffer_; 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SpdyFrameBuilder::ReadUInt16(void** iter, uint16* result) const { 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(iter); 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!*iter) 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *iter = const_cast<char*>(buffer_); 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!IteratorHasRoomFor(*iter, sizeof(*result))) 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *result = ntohs(*(reinterpret_cast<uint16*>(*iter))); 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateIter(iter, sizeof(*result)); 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SpdyFrameBuilder::ReadUInt32(void** iter, uint32* result) const { 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(iter); 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!*iter) 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *iter = const_cast<char*>(buffer_); 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!IteratorHasRoomFor(*iter, sizeof(*result))) 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *result = ntohl(*(reinterpret_cast<uint32*>(*iter))); 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateIter(iter, sizeof(*result)); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SpdyFrameBuilder::ReadString(void** iter, std::string* result) const { 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(iter); 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uint16 len; 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ReadUInt16(iter, &len)) 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!IteratorHasRoomFor(*iter, len)) 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch char* chars = reinterpret_cast<char*>(*iter); 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->assign(chars, len); 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateIter(iter, len); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SpdyFrameBuilder::ReadBytes(void** iter, const char** data, 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uint16 length) const { 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(iter); 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(data); 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!IteratorHasRoomFor(*iter, length)) 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *data = reinterpret_cast<const char*>(*iter); 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateIter(iter, length); 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SpdyFrameBuilder::ReadData(void** iter, const char** data, 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uint16* length) const { 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(iter); 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(data); 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(length); 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ReadUInt16(iter, length)) 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ReadBytes(iter, data, *length); 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SpdyFrameBuilder::WriteString(const std::string& value) { 10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (value.size() > 0xffff) 10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!WriteUInt16(static_cast<int>(value.size()))) 11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return WriteBytes(value.data(), static_cast<uint16>(value.size())); 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SpdyFrameBuilder::WriteBytes(const void* data, uint16 data_len) { 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(capacity_ != kCapacityReadOnly); 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch char* dest = BeginWrite(data_len); 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!dest) 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(dest, data, data_len); 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EndWrite(dest, data_len); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch length_ += data_len; 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochchar* SpdyFrameBuilder::BeginWriteData(uint16 length) { 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(variable_buffer_offset_, 0U) << 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "There can only be one variable buffer in a SpdyFrameBuilder"; 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!WriteUInt16(length)) 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch char *data_ptr = BeginWrite(length); 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!data_ptr) 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch variable_buffer_offset_ = data_ptr - buffer_ - sizeof(int); 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // EndWrite doesn't necessarily have to be called after the write operation, 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so we call it here to pad out what the caller will eventually write. 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EndWrite(data_ptr, length); 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return data_ptr; 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenchar* SpdyFrameBuilder::BeginWrite(size_t length) { 15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen size_t needed_size = length_ + length; 15172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (needed_size > capacity_ && !Resize(std::max(capacity_ * 2, needed_size))) 15272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return NULL; 15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#ifdef ARCH_CPU_64_BITS 15572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_LE(length, std::numeric_limits<uint32>::max()); 15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif 15772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return buffer_ + length_; 15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 16072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 16172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SpdyFrameBuilder::EndWrite(char* dest, int length) { 16272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 16372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SpdyFrameBuilder::Resize(size_t new_capacity) { 1653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (new_capacity <= capacity_) 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch char* p = new char[new_capacity]; 1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!p) 1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (buffer_) { 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(p, buffer_, capacity_); 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete[] buffer_; 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch buffer_ = p; 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch capacity_ = new_capacity; 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace spdy 181