// 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/quic/crypto/crypto_framer.h"

#include "net/quic/crypto/crypto_protocol.h"
#include "net/quic/quic_data_reader.h"
#include "net/quic/quic_data_writer.h"

using base::StringPiece;
using std::make_pair;
using std::pair;
using std::vector;

namespace net {

namespace {

const size_t kQuicTagSize = sizeof(uint32);
const size_t kCryptoEndOffsetSize = sizeof(uint32);
const size_t kNumEntriesSize = sizeof(uint16);

// OneShotVisitor is a framer visitor that records a single handshake message.
class OneShotVisitor : public CryptoFramerVisitorInterface {
 public:
  OneShotVisitor() : error_(false) {}

  void OnError(CryptoFramer* framer) override { error_ = true; }

  void OnHandshakeMessage(const CryptoHandshakeMessage& message) override {
    out_.reset(new CryptoHandshakeMessage(message));
  }

  bool error() const { return error_; }

  CryptoHandshakeMessage* release() { return out_.release(); }

 private:
  scoped_ptr<CryptoHandshakeMessage> out_;
  bool error_;
};

}  // namespace

CryptoFramer::CryptoFramer()
    : visitor_(nullptr),
      num_entries_(0),
      values_len_(0) {
  Clear();
}

CryptoFramer::~CryptoFramer() {}

// static
CryptoHandshakeMessage* CryptoFramer::ParseMessage(StringPiece in) {
  OneShotVisitor visitor;
  CryptoFramer framer;

  framer.set_visitor(&visitor);
  if (!framer.ProcessInput(in) || visitor.error() ||
      framer.InputBytesRemaining()) {
    return nullptr;
  }

  return visitor.release();
}

bool CryptoFramer::ProcessInput(StringPiece input) {
  DCHECK_EQ(QUIC_NO_ERROR, error_);
  if (error_ != QUIC_NO_ERROR) {
    return false;
  }
  error_ = Process(input);
  if (error_ != QUIC_NO_ERROR) {
    visitor_->OnError(this);
    return false;
  }

  return true;
}

// static
QuicData* CryptoFramer::ConstructHandshakeMessage(
    const CryptoHandshakeMessage& message) {
  size_t num_entries = message.tag_value_map().size();
  size_t pad_length = 0;
  bool need_pad_tag = false;
  bool need_pad_value = false;

  size_t len = message.size();
  if (len < message.minimum_size()) {
    need_pad_tag = true;
    need_pad_value = true;
    num_entries++;

    size_t delta = message.minimum_size() - len;
    const size_t overhead = kQuicTagSize + kCryptoEndOffsetSize;
    if (delta > overhead) {
      pad_length = delta - overhead;
    }
    len += overhead + pad_length;
  }

  if (num_entries > kMaxEntries) {
    return nullptr;
  }


  QuicDataWriter writer(len);
  if (!writer.WriteUInt32(message.tag())) {
    DCHECK(false) << "Failed to write message tag.";
    return nullptr;
  }
  if (!writer.WriteUInt16(num_entries)) {
    DCHECK(false) << "Failed to write size.";
    return nullptr;
  }
  if (!writer.WriteUInt16(0)) {
    DCHECK(false) << "Failed to write padding.";
    return nullptr;
  }

  uint32 end_offset = 0;
  // Tags and offsets
  for (QuicTagValueMap::const_iterator it = message.tag_value_map().begin();
       it != message.tag_value_map().end(); ++it) {
    if (it->first == kPAD && need_pad_tag) {
      // Existing PAD tags are only checked when padding needs to be added
      // because parts of the code may need to reserialize received messages
      // and those messages may, legitimately include padding.
      DCHECK(false) << "Message needed padding but already contained a PAD tag";
      return nullptr;
    }

    if (it->first > kPAD && need_pad_tag) {
      need_pad_tag = false;
      if (!WritePadTag(&writer, pad_length, &end_offset)) {
        return nullptr;
      }
    }

    if (!writer.WriteUInt32(it->first)) {
      DCHECK(false) << "Failed to write tag.";
      return nullptr;
    }
    end_offset += it->second.length();
    if (!writer.WriteUInt32(end_offset)) {
      DCHECK(false) << "Failed to write end offset.";
      return nullptr;
    }
  }

  if (need_pad_tag) {
    if (!WritePadTag(&writer, pad_length, &end_offset)) {
      return nullptr;
    }
  }

  // Values
  for (QuicTagValueMap::const_iterator it = message.tag_value_map().begin();
       it != message.tag_value_map().end(); ++it) {
    if (it->first > kPAD && need_pad_value) {
      need_pad_value = false;
      if (!writer.WriteRepeatedByte('-', pad_length)) {
        DCHECK(false) << "Failed to write padding.";
        return nullptr;
      }
    }

    if (!writer.WriteBytes(it->second.data(), it->second.length())) {
      DCHECK(false) << "Failed to write value.";
      return nullptr;
    }
  }

  if (need_pad_value) {
    if (!writer.WriteRepeatedByte('-', pad_length)) {
      DCHECK(false) << "Failed to write padding.";
      return nullptr;
    }
  }

  return new QuicData(writer.take(), len, true);
}

void CryptoFramer::Clear() {
  message_.Clear();
  tags_and_lengths_.clear();
  error_ = QUIC_NO_ERROR;
  state_ = STATE_READING_TAG;
}

QuicErrorCode CryptoFramer::Process(StringPiece input) {
  // Add this data to the buffer.
  buffer_.append(input.data(), input.length());
  QuicDataReader reader(buffer_.data(), buffer_.length());

  switch (state_) {
    case STATE_READING_TAG:
      if (reader.BytesRemaining() < kQuicTagSize) {
        break;
      }
      QuicTag message_tag;
      reader.ReadUInt32(&message_tag);
      message_.set_tag(message_tag);
      state_ = STATE_READING_NUM_ENTRIES;
    case STATE_READING_NUM_ENTRIES:
      if (reader.BytesRemaining() < kNumEntriesSize + sizeof(uint16)) {
        break;
      }
      reader.ReadUInt16(&num_entries_);
      if (num_entries_ > kMaxEntries) {
        return QUIC_CRYPTO_TOO_MANY_ENTRIES;
      }
      uint16 padding;
      reader.ReadUInt16(&padding);

      tags_and_lengths_.reserve(num_entries_);
      state_ = STATE_READING_TAGS_AND_LENGTHS;
      values_len_ = 0;
    case STATE_READING_TAGS_AND_LENGTHS: {
      if (reader.BytesRemaining() <
              num_entries_ * (kQuicTagSize + kCryptoEndOffsetSize)) {
        break;
      }

      uint32 last_end_offset = 0;
      for (unsigned i = 0; i < num_entries_; ++i) {
        QuicTag tag;
        reader.ReadUInt32(&tag);
        if (i > 0 && tag <= tags_and_lengths_[i-1].first) {
          if (tag == tags_and_lengths_[i-1].first) {
            return QUIC_CRYPTO_DUPLICATE_TAG;
          }
          return QUIC_CRYPTO_TAGS_OUT_OF_ORDER;
        }

        uint32 end_offset;
        reader.ReadUInt32(&end_offset);

        if (end_offset < last_end_offset) {
          return QUIC_CRYPTO_TAGS_OUT_OF_ORDER;
        }
        tags_and_lengths_.push_back(
            make_pair(tag, static_cast<size_t>(end_offset - last_end_offset)));
        last_end_offset = end_offset;
      }
      values_len_ = last_end_offset;
      state_ = STATE_READING_VALUES;
    }
    case STATE_READING_VALUES:
      if (reader.BytesRemaining() < values_len_) {
        break;
      }
      for (vector<pair<QuicTag, size_t> >::const_iterator
           it = tags_and_lengths_.begin(); it != tags_and_lengths_.end();
           it++) {
        StringPiece value;
        reader.ReadStringPiece(&value, it->second);
        message_.SetStringPiece(it->first, value);
      }
      visitor_->OnHandshakeMessage(message_);
      Clear();
      state_ = STATE_READING_TAG;
      break;
  }
  // Save any remaining data.
  buffer_ = reader.PeekRemainingPayload().as_string();
  return QUIC_NO_ERROR;
}

// static
bool CryptoFramer::WritePadTag(QuicDataWriter* writer,
                               size_t pad_length,
                               uint32* end_offset) {
  if (!writer->WriteUInt32(kPAD)) {
    DCHECK(false) << "Failed to write tag.";
    return false;
  }
  *end_offset += pad_length;
  if (!writer->WriteUInt32(*end_offset)) {
    DCHECK(false) << "Failed to write end offset.";
    return false;
  }
  return true;
}

}  // namespace net
