/*
 *  Copyright (c) 2020 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 "test/network/emulated_turn_server.h"

#include <string>
#include <utility>

#include "api/packet_socket_factory.h"
#include "rtc_base/strings/string_builder.h"

namespace {

static const char kTestRealm[] = "example.org";
static const char kTestSoftware[] = "TestTurnServer";

// A wrapper class for copying data between an AsyncPacketSocket and a
// EmulatedEndpoint. This is used by the cricket::TurnServer when
// sending data back into the emulated network.
class AsyncPacketSocketWrapper : public rtc::AsyncPacketSocket {
 public:
  AsyncPacketSocketWrapper(webrtc::test::EmulatedTURNServer* turn_server,
                           webrtc::EmulatedEndpoint* endpoint,
                           uint16_t port)
      : turn_server_(turn_server),
        endpoint_(endpoint),
        local_address_(
            rtc::SocketAddress(endpoint_->GetPeerLocalAddress(), port)) {}
  ~AsyncPacketSocketWrapper() { turn_server_->Unbind(local_address_); }

  rtc::SocketAddress GetLocalAddress() const override { return local_address_; }
  rtc::SocketAddress GetRemoteAddress() const override {
    return rtc::SocketAddress();
  }
  int Send(const void* pv,
           size_t cb,
           const rtc::PacketOptions& options) override {
    RTC_CHECK(false) << "TCP not implemented";
    return -1;
  }
  int SendTo(const void* pv,
             size_t cb,
             const rtc::SocketAddress& addr,
             const rtc::PacketOptions& options) override {
    // Copy from rtc::AsyncPacketSocket to EmulatedEndpoint.
    rtc::CopyOnWriteBuffer buf(reinterpret_cast<const char*>(pv), cb);
    endpoint_->SendPacket(local_address_, addr, buf);
    return cb;
  }
  int Close() override { return 0; }

  rtc::AsyncPacketSocket::State GetState() const override {
    return rtc::AsyncPacketSocket::STATE_BOUND;
  }
  int GetOption(rtc::Socket::Option opt, int* value) override { return 0; }
  int SetOption(rtc::Socket::Option opt, int value) override { return 0; }
  int GetError() const override { return 0; }
  void SetError(int error) override {}

 private:
  webrtc::test::EmulatedTURNServer* const turn_server_;
  webrtc::EmulatedEndpoint* const endpoint_;
  const rtc::SocketAddress local_address_;
};

// A wrapper class for cricket::TurnServer to allocate sockets.
class PacketSocketFactoryWrapper : public rtc::PacketSocketFactory {
 public:
  explicit PacketSocketFactoryWrapper(
      webrtc::test::EmulatedTURNServer* turn_server)
      : turn_server_(turn_server) {}
  ~PacketSocketFactoryWrapper() override {}

  // This method is called from TurnServer when making a TURN ALLOCATION.
  // It will create a socket on the |peer_| endpoint.
  rtc::AsyncPacketSocket* CreateUdpSocket(const rtc::SocketAddress& address,
                                          uint16_t min_port,
                                          uint16_t max_port) override {
    return turn_server_->CreatePeerSocket();
  }

  rtc::AsyncPacketSocket* CreateServerTcpSocket(
      const rtc::SocketAddress& local_address,
      uint16_t min_port,
      uint16_t max_port,
      int opts) override {
    return nullptr;
  }
  rtc::AsyncPacketSocket* CreateClientTcpSocket(
      const rtc::SocketAddress& local_address,
      const rtc::SocketAddress& remote_address,
      const rtc::ProxyInfo& proxy_info,
      const std::string& user_agent,
      const rtc::PacketSocketTcpOptions& tcp_options) override {
    return nullptr;
  }
  rtc::AsyncResolverInterface* CreateAsyncResolver() override {
    return nullptr;
  }

 private:
  webrtc::test::EmulatedTURNServer* turn_server_;
};

}  //  namespace

namespace webrtc {
namespace test {

EmulatedTURNServer::EmulatedTURNServer(std::unique_ptr<rtc::Thread> thread,
                                       EmulatedEndpoint* client,
                                       EmulatedEndpoint* peer)
    : thread_(std::move(thread)), client_(client), peer_(peer) {
  ice_config_.username = "keso";
  ice_config_.password = "keso";
  thread_->Invoke<void>(RTC_FROM_HERE, [=]() {
    RTC_DCHECK_RUN_ON(thread_.get());
    turn_server_ = std::make_unique<cricket::TurnServer>(thread_.get());
    turn_server_->set_realm(kTestRealm);
    turn_server_->set_realm(kTestSoftware);
    turn_server_->set_auth_hook(this);

    auto client_socket = Wrap(client_);
    turn_server_->AddInternalSocket(client_socket, cricket::PROTO_UDP);
    turn_server_->SetExternalSocketFactory(new PacketSocketFactoryWrapper(this),
                                           rtc::SocketAddress());
    client_address_ = client_socket->GetLocalAddress();
    char buf[256];
    rtc::SimpleStringBuilder str(buf);
    str.AppendFormat("turn:%s?transport=udp",
                     client_address_.ToString().c_str());
    ice_config_.url = str.str();
  });
}

void EmulatedTURNServer::Stop() {
  thread_->Invoke<void>(RTC_FROM_HERE, [=]() {
    RTC_DCHECK_RUN_ON(thread_.get());
    sockets_.clear();
  });
}

EmulatedTURNServer::~EmulatedTURNServer() {
  thread_->Invoke<void>(RTC_FROM_HERE, [=]() {
    RTC_DCHECK_RUN_ON(thread_.get());
    turn_server_.reset(nullptr);
  });
}

rtc::AsyncPacketSocket* EmulatedTURNServer::Wrap(EmulatedEndpoint* endpoint) {
  RTC_DCHECK_RUN_ON(thread_.get());
  auto port = endpoint->BindReceiver(0, this).value();
  auto socket = new AsyncPacketSocketWrapper(this, endpoint, port);
  sockets_[rtc::SocketAddress(endpoint->GetPeerLocalAddress(), port)] = socket;
  return socket;
}

void EmulatedTURNServer::OnPacketReceived(webrtc::EmulatedIpPacket packet) {
  // Copy from EmulatedEndpoint to rtc::AsyncPacketSocket.
  thread_->PostTask(RTC_FROM_HERE, [this, packet(std::move(packet))]() {
    RTC_DCHECK_RUN_ON(thread_.get());
    auto it = sockets_.find(packet.to);
    if (it != sockets_.end()) {
      it->second->SignalReadPacket(
          it->second, reinterpret_cast<const char*>(packet.cdata()),
          packet.size(), packet.from, packet.arrival_time.ms());
    }
  });
}

void EmulatedTURNServer::Unbind(rtc::SocketAddress address) {
  RTC_DCHECK_RUN_ON(thread_.get());
  if (GetClientEndpoint()->GetPeerLocalAddress() == address.ipaddr()) {
    GetClientEndpoint()->UnbindReceiver(address.port());
  } else {
    GetPeerEndpoint()->UnbindReceiver(address.port());
  }
  sockets_.erase(address);
}

}  // namespace test
}  // namespace webrtc
