/*
 *  Copyright 2016 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/p2p/quic/quicsession.h"

#include <string>
#include <utility>

#include "webrtc/rtc_base/checks.h"
#include "webrtc/rtc_base/logging.h"
#include "webrtc/rtc_base/messagehandler.h"
#include "webrtc/rtc_base/messagequeue.h"

namespace cricket {

// Default priority for incoming QUIC streams.
// TODO(mikescarlett): Determine if this value is correct.
static const net::SpdyPriority kDefaultPriority = 3;

QuicSession::QuicSession(std::unique_ptr<net::QuicConnection> connection,
                         const net::QuicConfig& config)
    : net::QuicSession(connection.release(), config) {}

QuicSession::~QuicSession() {}

void QuicSession::StartClientHandshake(
    net::QuicCryptoClientStream* crypto_stream) {
  SetCryptoStream(crypto_stream);
  net::QuicSession::Initialize();
  crypto_stream->CryptoConnect();
}

void QuicSession::StartServerHandshake(
    net::QuicCryptoServerStream* crypto_stream) {
  SetCryptoStream(crypto_stream);
  net::QuicSession::Initialize();
}

void QuicSession::SetCryptoStream(net::QuicCryptoStream* crypto_stream) {
  crypto_stream_.reset(crypto_stream);
}

bool QuicSession::ExportKeyingMaterial(base::StringPiece label,
                                       base::StringPiece context,
                                       size_t result_len,
                                       std::string* result) {
  return crypto_stream_->ExportKeyingMaterial(label, context, result_len,
                                              result);
}

void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
  net::QuicSession::OnCryptoHandshakeEvent(event);
  if (event == HANDSHAKE_CONFIRMED) {
    LOG(LS_INFO) << "QuicSession handshake complete";
    RTC_DCHECK(IsEncryptionEstablished());
    RTC_DCHECK(IsCryptoHandshakeConfirmed());

    SignalHandshakeComplete();
  }
}

void QuicSession::CloseStream(net::QuicStreamId stream_id) {
  if (IsClosedStream(stream_id)) {
    // When CloseStream has been called recursively (via
    // ReliableQuicStream::OnClose), the stream is already closed so return.
    return;
  }
  write_blocked_streams()->UnregisterStream(stream_id);
  net::QuicSession::CloseStream(stream_id);
}

ReliableQuicStream* QuicSession::CreateIncomingDynamicStream(
    net::QuicStreamId id) {
  ReliableQuicStream* stream = CreateDataStream(id, kDefaultPriority);
  if (stream) {
    SignalIncomingStream(stream);
  }
  return stream;
}

ReliableQuicStream* QuicSession::CreateOutgoingDynamicStream(
    net::SpdyPriority priority) {
  return CreateDataStream(GetNextOutgoingStreamId(), priority);
}

ReliableQuicStream* QuicSession::CreateDataStream(net::QuicStreamId id,
                                                  net::SpdyPriority priority) {
  if (crypto_stream_ == nullptr || !crypto_stream_->encryption_established()) {
    // Encryption not active so no stream created
    return nullptr;
  }
  ReliableQuicStream* stream = new ReliableQuicStream(id, this);
  if (stream) {
    // Make QuicSession take ownership of the stream.
    ActivateStream(stream);
    // Register the stream to the QuicWriteBlockedList. |priority| is clamped
    // between 0 and 7, with 0 being the highest priority and 7 the lowest
    // priority.
    write_blocked_streams()->RegisterStream(stream->id(), priority);
  }
  return stream;
}

void QuicSession::OnConnectionClosed(net::QuicErrorCode error,
                                     const std::string& error_details,
                                     net::ConnectionCloseSource source) {
  net::QuicSession::OnConnectionClosed(error, error_details, source);
  SignalConnectionClosed(error,
                         source == net::ConnectionCloseSource::FROM_PEER);
}

bool QuicSession::OnReadPacket(const char* data, size_t data_len) {
  net::QuicReceivedPacket packet(data, data_len, clock_.Now());
  ProcessUdpPacket(connection()->self_address(), connection()->peer_address(),
                   packet);
  return true;
}

}  // namespace cricket
