// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/spdy/spdy_frame_builder.h"

#include <limits>

#include "base/logging.h"
#include "net/spdy/spdy_framer.h"
#include "net/spdy/spdy_protocol.h"

namespace net {

namespace {

// A special structure for the 8 bit flags and 24 bit length fields.
union FlagsAndLength {
  uint8 flags[4];  // 8 bits
  uint32 length;   // 24 bits
};

// Creates a FlagsAndLength.
FlagsAndLength CreateFlagsAndLength(uint8 flags, size_t length) {
  DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask));
  FlagsAndLength flags_length;
  flags_length.length = htonl(static_cast<uint32>(length));
  DCHECK_EQ(0, flags & ~kControlFlagsMask);
  flags_length.flags[0] = flags;
  return flags_length;
}

}  // namespace

SpdyFrameBuilder::SpdyFrameBuilder(size_t size, SpdyMajorVersion version)
    : buffer_(new char[size]),
      capacity_(size),
      length_(0),
      offset_(0),
      version_(version) {
}

SpdyFrameBuilder::~SpdyFrameBuilder() {
}

char* SpdyFrameBuilder::GetWritableBuffer(size_t length) {
  if (!CanWrite(length)) {
    return NULL;
  }
  return buffer_.get() + offset_ + length_;
}

bool SpdyFrameBuilder::Seek(size_t length) {
  if (!CanWrite(length)) {
    return false;
  }

  length_ += length;
  return true;
}

bool SpdyFrameBuilder::WriteControlFrameHeader(const SpdyFramer& framer,
                                               SpdyFrameType type,
                                               uint8 flags) {
  DCHECK_GE(SPDY3, version_);
  DCHECK(SpdyConstants::IsValidFrameType(
      version_, SpdyConstants::SerializeFrameType(version_, type)));
  bool success = true;
  FlagsAndLength flags_length = CreateFlagsAndLength(
      flags, capacity_ - framer.GetControlFrameHeaderSize());
  success &= WriteUInt16(kControlFlagMask |
                         SpdyConstants::SerializeMajorVersion(version_));
  success &= WriteUInt16(
      SpdyConstants::SerializeFrameType(framer.protocol_version(), type));
  success &= WriteBytes(&flags_length, sizeof(flags_length));
  DCHECK_EQ(framer.GetControlFrameHeaderSize(), length());
  return success;
}

bool SpdyFrameBuilder::WriteDataFrameHeader(const SpdyFramer& framer,
                                            SpdyStreamId stream_id,
                                            uint8 flags) {
  if (version_ > SPDY3) {
    return BeginNewFrame(framer, DATA, flags, stream_id);
  }
  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
  bool success = true;
  success &= WriteUInt32(stream_id);
  size_t length_field = capacity_ - framer.GetDataFrameMinimumSize();
  DCHECK_EQ(0u, length_field & ~static_cast<size_t>(kLengthMask));
  FlagsAndLength flags_length;
  flags_length.length = htonl(length_field);
  DCHECK_EQ(0, flags & ~kDataFlagsMask);
  flags_length.flags[0] = flags;
  success &= WriteBytes(&flags_length, sizeof(flags_length));
  DCHECK_EQ(framer.GetDataFrameMinimumSize(), length());
  return success;
}

bool SpdyFrameBuilder::BeginNewFrame(const SpdyFramer& framer,
                                     SpdyFrameType type,
                                     uint8 flags,
                                     SpdyStreamId stream_id) {
  DCHECK(SpdyConstants::IsValidFrameType(
      version_, SpdyConstants::SerializeFrameType(version_, type)));
  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
  DCHECK_GT(framer.protocol_version(), SPDY3);
  bool success = true;
  if (length_ > 0) {
    // Update length field for previous frame.
    OverwriteLength(framer, length_ - framer.GetPrefixLength(type));
    DLOG_IF(DFATAL, SpdyConstants::GetFrameMaximumSize(version_) < length_)
        << "Frame length  " << length_
        << " is longer than the maximum allowed length.";
  }

  offset_ += length_;
  length_ = 0;

  // Assume all remaining capacity will be used for this frame. If not,
  // the length will get overwritten when we begin the next frame.
  // Don't check for length limits here because this may be larger than the
  // actual frame length.
  success &= WriteUInt24(capacity_ - offset_ - framer.GetPrefixLength(type));
  success &= WriteUInt8(
      SpdyConstants::SerializeFrameType(version_, type));
  success &= WriteUInt8(flags);
  success &= WriteUInt32(stream_id);
  DCHECK_EQ(framer.GetDataFrameMinimumSize(), length_);
  return success;
}

bool SpdyFrameBuilder::WriteStringPiece16(const base::StringPiece& value) {
  if (value.size() > 0xffff) {
    DCHECK(false) << "Tried to write string with length > 16bit.";
    return false;
  }

  if (!WriteUInt16(static_cast<uint16>(value.size())))
    return false;

  return WriteBytes(value.data(), static_cast<uint16>(value.size()));
}

bool SpdyFrameBuilder::WriteStringPiece32(const base::StringPiece& value) {
  if (!WriteUInt32(value.size())) {
    return false;
  }

  return WriteBytes(value.data(), value.size());
}

bool SpdyFrameBuilder::WriteBytes(const void* data, uint32 data_len) {
  if (!CanWrite(data_len)) {
    return false;
  }

  char* dest = GetWritableBuffer(data_len);
  memcpy(dest, data, data_len);
  Seek(data_len);
  return true;
}

bool SpdyFrameBuilder::RewriteLength(const SpdyFramer& framer) {
  return OverwriteLength(framer,
                         length_ - framer.GetControlFrameHeaderSize());
}

bool SpdyFrameBuilder::OverwriteLength(const SpdyFramer& framer,
                                       size_t length) {
  if (version_ < SPDY4) {
    DCHECK_LE(length,
              SpdyConstants::GetFrameMaximumSize(version_) -
                  framer.GetFrameMinimumSize());
  } else {
    DCHECK_LE(length, SpdyConstants::GetFrameMaximumSize(version_));
  }
  bool success = false;
  const size_t old_length = length_;

  if (version_ < SPDY4) {
    FlagsAndLength flags_length = CreateFlagsAndLength(
        0,  // We're not writing over the flags value anyway.
        length);

    // Write into the correct location by temporarily faking the offset.
    length_ = 5;  // Offset at which the length field occurs.
    success = WriteBytes(reinterpret_cast<char*>(&flags_length) + 1,
                         sizeof(flags_length) - 1);
  } else {
    length_ = 0;
    success = WriteUInt24(length);
  }

  length_ = old_length;
  return success;
}

bool SpdyFrameBuilder::OverwriteFlags(const SpdyFramer& framer,
                                      uint8 flags) {
  DCHECK_GT(framer.protocol_version(), SPDY3);
  bool success = false;
  const size_t old_length = length_;
  // Flags are the fifth octet in the frame prefix.
  length_ = 4;
  success = WriteUInt8(flags);
  length_ = old_length;
  return success;
}

bool SpdyFrameBuilder::CanWrite(size_t length) const {
  if (length > kLengthMask) {
    DCHECK(false);
    return false;
  }

  if (offset_ + length_ + length > capacity_) {
    DCHECK(false);
    return false;
  }

  return true;
}

}  // namespace net
