// 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/test_tools/simple_quic_framer.h"

#include "base/stl_util.h"
#include "net/quic/crypto/crypto_framer.h"
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"

using base::StringPiece;
using std::string;
using std::vector;

namespace net {
namespace test {

class SimpleFramerVisitor : public QuicFramerVisitorInterface {
 public:
  SimpleFramerVisitor()
      : error_(QUIC_NO_ERROR) {
  }

  ~SimpleFramerVisitor() override { STLDeleteElements(&stream_data_); }

  void OnError(QuicFramer* framer) override { error_ = framer->error(); }

  bool OnProtocolVersionMismatch(QuicVersion version) override { return false; }

  void OnPacket() override {}
  void OnPublicResetPacket(const QuicPublicResetPacket& packet) override {
    public_reset_packet_.reset(new QuicPublicResetPacket(packet));
  }
  void OnVersionNegotiationPacket(
      const QuicVersionNegotiationPacket& packet) override {
    version_negotiation_packet_.reset(
        new QuicVersionNegotiationPacket(packet));
  }
  void OnRevivedPacket() override {}

  bool OnUnauthenticatedPublicHeader(
      const QuicPacketPublicHeader& header) override {
    return true;
  }
  bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override {
    return true;
  }
  void OnDecryptedPacket(EncryptionLevel level) override {}
  bool OnPacketHeader(const QuicPacketHeader& header) override {
    has_header_ = true;
    header_ = header;
    return true;
  }

  void OnFecProtectedPayload(StringPiece payload) override {}

  bool OnStreamFrame(const QuicStreamFrame& frame) override {
    // Save a copy of the data so it is valid after the packet is processed.
    stream_data_.push_back(frame.GetDataAsString());
    QuicStreamFrame stream_frame(frame);
    // Make sure that the stream frame points to this data.
    stream_frame.data.Clear();
    stream_frame.data.Append(const_cast<char*>(stream_data_.back()->data()),
                             stream_data_.back()->size());
    stream_frames_.push_back(stream_frame);
    return true;
  }

  bool OnAckFrame(const QuicAckFrame& frame) override {
    ack_frames_.push_back(frame);
    return true;
  }

  bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override {
    stop_waiting_frames_.push_back(frame);
    return true;
  }

  bool OnPingFrame(const QuicPingFrame& frame) override {
    ping_frames_.push_back(frame);
    return true;
  }

  void OnFecData(const QuicFecData& fec) override {
    fec_data_ = fec;
    fec_redundancy_ = fec_data_.redundancy.as_string();
    fec_data_.redundancy = fec_redundancy_;
  }

  bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override {
    rst_stream_frames_.push_back(frame);
    return true;
  }

  bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override {
    connection_close_frames_.push_back(frame);
    return true;
  }

  bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override {
    goaway_frames_.push_back(frame);
    return true;
  }

  bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override {
    window_update_frames_.push_back(frame);
    return true;
  }

  bool OnBlockedFrame(const QuicBlockedFrame& frame) override {
    blocked_frames_.push_back(frame);
    return true;
  }

  void OnPacketComplete() override {}

  const QuicPacketHeader& header() const { return header_; }
  const vector<QuicAckFrame>& ack_frames() const { return ack_frames_; }
  const vector<QuicConnectionCloseFrame>& connection_close_frames() const {
    return connection_close_frames_;
  }
  const vector<QuicGoAwayFrame>& goaway_frames() const {
    return goaway_frames_;
  }
  const vector<QuicRstStreamFrame>& rst_stream_frames() const {
    return rst_stream_frames_;
  }
  const vector<QuicStreamFrame>& stream_frames() const {
    return stream_frames_;
  }
  const vector<QuicStopWaitingFrame>& stop_waiting_frames() const {
    return stop_waiting_frames_;
  }
  const vector<QuicPingFrame>& ping_frames() const {
    return ping_frames_;
  }
  const QuicFecData& fec_data() const {
    return fec_data_;
  }
  const QuicVersionNegotiationPacket* version_negotiation_packet() const {
    return version_negotiation_packet_.get();
  }
  const QuicPublicResetPacket* public_reset_packet() const {
    return public_reset_packet_.get();
  }

 private:
  QuicErrorCode error_;
  bool has_header_;
  QuicPacketHeader header_;
  QuicFecData fec_data_;
  scoped_ptr<QuicVersionNegotiationPacket> version_negotiation_packet_;
  scoped_ptr<QuicPublicResetPacket> public_reset_packet_;
  string fec_redundancy_;
  vector<QuicAckFrame> ack_frames_;
  vector<QuicStopWaitingFrame> stop_waiting_frames_;
  vector<QuicPingFrame> ping_frames_;
  vector<QuicStreamFrame> stream_frames_;
  vector<QuicRstStreamFrame> rst_stream_frames_;
  vector<QuicGoAwayFrame> goaway_frames_;
  vector<QuicConnectionCloseFrame> connection_close_frames_;
  vector<QuicWindowUpdateFrame> window_update_frames_;
  vector<QuicBlockedFrame> blocked_frames_;
  vector<string*> stream_data_;

  DISALLOW_COPY_AND_ASSIGN(SimpleFramerVisitor);
};

SimpleQuicFramer::SimpleQuicFramer()
    : framer_(QuicSupportedVersions(), QuicTime::Zero(), true) {
}

SimpleQuicFramer::SimpleQuicFramer(const QuicVersionVector& supported_versions)
    : framer_(supported_versions, QuicTime::Zero(), true) {
}

SimpleQuicFramer::~SimpleQuicFramer() {
}

bool SimpleQuicFramer::ProcessPacket(const QuicPacket& packet) {
  scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(
      ENCRYPTION_NONE, 0, packet));
  return ProcessPacket(*encrypted);
}

bool SimpleQuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) {
  visitor_.reset(new SimpleFramerVisitor);
  framer_.set_visitor(visitor_.get());
  return framer_.ProcessPacket(packet);
}

void SimpleQuicFramer::Reset() {
  visitor_.reset(new SimpleFramerVisitor);
}


const QuicPacketHeader& SimpleQuicFramer::header() const {
  return visitor_->header();
}

const QuicFecData& SimpleQuicFramer::fec_data() const {
  return visitor_->fec_data();
}

const QuicVersionNegotiationPacket*
SimpleQuicFramer::version_negotiation_packet() const {
  return visitor_->version_negotiation_packet();
}

const QuicPublicResetPacket* SimpleQuicFramer::public_reset_packet() const {
  return visitor_->public_reset_packet();
}

QuicFramer* SimpleQuicFramer::framer() {
  return &framer_;
}

size_t SimpleQuicFramer::num_frames() const {
  return ack_frames().size() +
      goaway_frames().size() +
      rst_stream_frames().size() +
      stop_waiting_frames().size() +
      stream_frames().size() +
      ping_frames().size() +
      connection_close_frames().size();
}

const vector<QuicAckFrame>& SimpleQuicFramer::ack_frames() const {
  return visitor_->ack_frames();
}

const vector<QuicStopWaitingFrame>&
SimpleQuicFramer::stop_waiting_frames() const {
  return visitor_->stop_waiting_frames();
}

const vector<QuicPingFrame>& SimpleQuicFramer::ping_frames() const {
  return visitor_->ping_frames();
}

const vector<QuicStreamFrame>& SimpleQuicFramer::stream_frames() const {
  return visitor_->stream_frames();
}

const vector<QuicRstStreamFrame>& SimpleQuicFramer::rst_stream_frames() const {
  return visitor_->rst_stream_frames();
}

const vector<QuicGoAwayFrame>&
SimpleQuicFramer::goaway_frames() const {
  return visitor_->goaway_frames();
}

const vector<QuicConnectionCloseFrame>&
SimpleQuicFramer::connection_close_frames() const {
  return visitor_->connection_close_frames();
}

}  // namespace test
}  // namespace net
