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)
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdyFrameBuilder::SpdyFrameBuilder(size_t size, SpdyMajorVersion version)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : buffer_(new char[size]),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      capacity_(size),
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      length_(0),
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      offset_(0),
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      version_(version) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyFrameBuilder::~SpdyFrameBuilder() {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* SpdyFrameBuilder::GetWritableBuffer(size_t length) {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!CanWrite(length)) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return buffer_.get() + offset_ + length_;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SpdyFrameBuilder::Seek(size_t length) {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!CanWrite(length)) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  length_ += length;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SpdyFrameBuilder::WriteControlFrameHeader(const SpdyFramer& framer,
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                               SpdyFrameType type,
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                               uint8 flags) {
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK_GE(SPDY3, version_);
664ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  DCHECK_NE(-1,
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            SpdyConstants::SerializeFrameType(version_, type));
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool success = true;
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  FlagsAndLength flags_length = CreateFlagsAndLength(
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      flags, capacity_ - framer.GetControlFrameHeaderSize());
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  success &= WriteUInt16(kControlFlagMask |
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                         SpdyConstants::SerializeMajorVersion(version_));
734ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  success &= WriteUInt16(
744ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      SpdyConstants::SerializeFrameType(framer.protocol_version(), type));
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  success &= WriteBytes(&flags_length, sizeof(flags_length));
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(framer.GetControlFrameHeaderSize(), length());
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return success;
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SpdyFrameBuilder::WriteDataFrameHeader(const SpdyFramer& framer,
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            SpdyStreamId stream_id,
824ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                                            uint8 flags) {
835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (version_ > SPDY3) {
845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return BeginNewFrame(framer, DATA, flags, stream_id);
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool success = true;
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  success &= WriteUInt32(stream_id);
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t length_field = capacity_ - framer.GetDataFrameMinimumSize();
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_EQ(0u, length_field & ~static_cast<size_t>(kLengthMask));
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  FlagsAndLength flags_length;
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  flags_length.length_ = htonl(length_field);
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_EQ(0, flags & ~kDataFlagsMask);
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  flags_length.flags_[0] = flags;
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  success &= WriteBytes(&flags_length, sizeof(flags_length));
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_EQ(framer.GetDataFrameMinimumSize(), length());
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return success;
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool SpdyFrameBuilder::BeginNewFrame(const SpdyFramer& framer,
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     SpdyFrameType type,
1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     uint8 flags,
1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     SpdyStreamId stream_id) {
1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(SpdyConstants::IsValidFrameType(version_,
1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      SpdyConstants::SerializeFrameType(version_, type)));
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK_LT(SPDY3, framer.protocol_version());
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool success = true;
1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (length_ > 0) {
1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // Update length field for previous frame.
1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    OverwriteLength(framer, length_ - framer.GetPrefixLength(type));
1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DLOG_IF(DFATAL, SpdyConstants::GetFrameMaximumSize(version_) < length_)
1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        << "Frame length  " << length_
1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        << " is longer than the maximum allowed length.";
1154ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  }
1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  offset_ += length_;
1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  length_ = 0;
1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Assume all remaining capacity will be used for this frame. If not,
1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // the length will get overwritten when we begin the next frame.
1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Don't check for length limits here because this may be larger than the
1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // actual frame length.
1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  success &= WriteUInt16(capacity_ - offset_ - framer.GetPrefixLength(type));
1254ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  success &= WriteUInt8(
1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      SpdyConstants::SerializeFrameType(version_, type));
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  success &= WriteUInt8(flags);
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  success &= WriteUInt32(stream_id);
1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK_EQ(framer.GetDataFrameMinimumSize(), length_);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return success;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFrameBuilder::WriteString(const std::string& value) {
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (value.size() > 0xffff) {
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(false) << "Tried to write string with length > 16bit.";
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!WriteUInt16(static_cast<int>(value.size())))
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return WriteBytes(value.data(), static_cast<uint16>(value.size()));
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFrameBuilder::WriteStringPiece32(const base::StringPiece& value) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!WriteUInt32(value.size())) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return WriteBytes(value.data(), value.size());
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SpdyFrameBuilder::WriteBytes(const void* data, uint32 data_len) {
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!CanWrite(data_len)) {
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char* dest = GetWritableBuffer(data_len);
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memcpy(dest, data, data_len);
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Seek(data_len);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SpdyFrameBuilder::RewriteLength(const SpdyFramer& framer) {
1654ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  return OverwriteLength(framer,
1664ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                         length_ - framer.GetControlFrameHeaderSize());
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SpdyFrameBuilder::OverwriteLength(const SpdyFramer& framer,
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       size_t length) {
1715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (version_ <= SPDY3) {
1725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK_GE(SpdyConstants::GetFrameMaximumSize(version_) -
1735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              framer.GetFrameMinimumSize(),
17423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)              length);
17523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  } else {
1765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK_GE(SpdyConstants::GetFrameMaximumSize(version_), length);
17723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool success = false;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t old_length = length_;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (version_ <= SPDY3) {
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FlagsAndLength flags_length = CreateFlagsAndLength(
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        0,  // We're not writing over the flags value anyway.
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        length);
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Write into the correct location by temporarily faking the offset.
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    length_ = 5;  // Offset at which the length field occurs.
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    success = WriteBytes(reinterpret_cast<char*>(&flags_length) + 1,
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         sizeof(flags_length) - 1);
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    length_ = 0;
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    success = WriteUInt16(length);
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  length_ = old_length;
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return success;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1994ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochbool SpdyFrameBuilder::OverwriteFlags(const SpdyFramer& framer,
2004ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                                      uint8 flags) {
2015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK_LT(SPDY3, framer.protocol_version());
2024ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  bool success = false;
2034ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  const size_t old_length = length_;
2044ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // Flags are the fourth octet in the frame prefix.
2054ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  length_ = 3;
2064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  success = WriteUInt8(flags);
2074ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  length_ = old_length;
2084ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  return success;
2094ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch}
2104ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SpdyFrameBuilder::CanWrite(size_t length) const {
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (length > kLengthMask) {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(false);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (offset_ + length_ + length > capacity_) {
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(false);
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
226