15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_frame_builder.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_framer.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_protocol.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A special structure for the 8 bit flags and 24 bit length fields. 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)union FlagsAndLength { 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 flags_[4]; // 8 bits 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 length_; // 24 bits 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a FlagsAndLength. 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FlagsAndLength CreateFlagsAndLength(uint8 flags, size_t length) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask)); 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FlagsAndLength flags_length; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags_length.length_ = htonl(static_cast<uint32>(length)); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0, flags & ~kControlFlagsMask); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags_length.flags_[0] = flags; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return flags_length; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrameBuilder::SpdyFrameBuilder(size_t size) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : buffer_(new char[size]), 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) capacity_(size), 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length_(0) { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyFrameBuilder::~SpdyFrameBuilder() { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* SpdyFrameBuilder::GetWritableBuffer(size_t length) { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!CanWrite(length)) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return buffer_.get() + length_; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SpdyFrameBuilder::Seek(size_t length) { 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!CanWrite(length)) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) length_ += length; 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SpdyFrameBuilder::WriteControlFrameHeader(const SpdyFramer& framer, 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpdyFrameType type, 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 flags) { 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GE(type, FIRST_CONTROL_TYPE); 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_LE(type, LAST_CONTROL_TYPE); 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_GT(4, framer.protocol_version()); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool success = true; 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FlagsAndLength flags_length = CreateFlagsAndLength( 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) flags, capacity_ - framer.GetControlFrameHeaderSize()); 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) success &= WriteUInt16(kControlFlagMask | framer.protocol_version()); 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) success &= WriteUInt16(type); 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) success &= WriteBytes(&flags_length, sizeof(flags_length)); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(framer.GetControlFrameHeaderSize(), length()); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return success; 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SpdyFrameBuilder::WriteDataFrameHeader(const SpdyFramer& framer, 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyStreamId stream_id, 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyDataFlags flags) { 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (framer.protocol_version() >= 4) { 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return WriteFramePrefix(framer, DATA, flags, stream_id); 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(0u, stream_id & ~kStreamIdMask); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool success = true; 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) success &= WriteUInt32(stream_id); 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size_t length_field = capacity_ - framer.GetDataFrameMinimumSize(); 8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_EQ(0u, length_field & ~static_cast<size_t>(kLengthMask)); 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FlagsAndLength flags_length; 8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) flags_length.length_ = htonl(length_field); 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_EQ(0, flags & ~kDataFlagsMask); 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) flags_length.flags_[0] = flags; 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) success &= WriteBytes(&flags_length, sizeof(flags_length)); 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_EQ(framer.GetDataFrameMinimumSize(), length()); 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return success; 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool SpdyFrameBuilder::WriteFramePrefix(const SpdyFramer& framer, 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SpdyFrameType type, 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) uint8 flags, 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SpdyStreamId stream_id) { 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_LE(DATA, type); 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_GE(LAST_CONTROL_TYPE, type); 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_EQ(0u, stream_id & ~kStreamIdMask); 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_LE(4, framer.protocol_version()); 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool success = true; 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_GT(1u<<16, capacity_); // Make sure length fits in 2B. 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) success &= WriteUInt16(capacity_); 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) success &= WriteUInt8(type); 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) success &= WriteUInt8(flags); 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) success &= WriteUInt32(stream_id); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(framer.GetDataFrameMinimumSize(), length()); 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return success; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFrameBuilder::WriteString(const std::string& value) { 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (value.size() > 0xffff) { 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(false) << "Tried to write string with length > 16bit."; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!WriteUInt16(static_cast<int>(value.size()))) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WriteBytes(value.data(), static_cast<uint16>(value.size())); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFrameBuilder::WriteStringPiece32(const base::StringPiece& value) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!WriteUInt32(value.size())) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WriteBytes(value.data(), value.size()); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SpdyFrameBuilder::WriteBytes(const void* data, uint32 data_len) { 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!CanWrite(data_len)) { 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) char* dest = GetWritableBuffer(data_len); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(dest, data, data_len); 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Seek(data_len); 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SpdyFrameBuilder::RewriteLength(const SpdyFramer& framer) { 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (framer.protocol_version() < 4) { 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OverwriteLength(framer, 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) length_ - framer.GetControlFrameHeaderSize()); 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OverwriteLength(framer, length_); 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SpdyFrameBuilder::OverwriteLength(const SpdyFramer& framer, 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t length) { 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool success = false; 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const size_t old_length = length_; 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (framer.protocol_version() < 4) { 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FlagsAndLength flags_length = CreateFlagsAndLength( 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0, // We're not writing over the flags value anyway. 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) length); 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Write into the correct location by temporarily faking the offset. 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) length_ = 5; // Offset at which the length field occurs. 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) success = WriteBytes(reinterpret_cast<char*>(&flags_length) + 1, 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sizeof(flags_length) - 1); 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) length_ = 0; 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) success = WriteUInt16(length); 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) length_ = old_length; 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return success; 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SpdyFrameBuilder::CanWrite(size_t length) const { 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (length > kLengthMask) { 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(false); 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (length_ + length > capacity_) { 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(false); 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 192