/*
 *  Copyright 2004 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.
 */

#ifndef RTC_BASE_TEST_ECHO_SERVER_H_
#define RTC_BASE_TEST_ECHO_SERVER_H_

#include <stddef.h>
#include <stdint.h>

#include <memory>
#include <set>
#include <utility>

#include "absl/memory/memory.h"
#include "api/environment/environment.h"
#include "rtc_base/async_packet_socket.h"
#include "rtc_base/async_tcp_socket.h"
#include "rtc_base/checks.h"
#include "rtc_base/memory/less_unique_ptr.h"
#include "rtc_base/network/received_packet.h"
#include "rtc_base/socket.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"

namespace webrtc {

// A test echo server, echoes back any packets sent to it.
// Useful for unit tests.
class TestEchoServer : public sigslot::has_slots<> {
 public:
  TestEchoServer(const Environment& env,
                 Thread* thread,
                 const SocketAddress& addr);
  ~TestEchoServer() override;

  TestEchoServer(const TestEchoServer&) = delete;
  TestEchoServer& operator=(const TestEchoServer&) = delete;

  SocketAddress address() const { return server_socket_->GetLocalAddress(); }

 private:
  void OnAccept(Socket* socket) {
    std::unique_ptr<Socket> raw_socket =
        absl::WrapUnique(socket->Accept(nullptr));
    if (raw_socket) {
      auto packet_socket =
          std::make_unique<AsyncTCPSocket>(env_, std::move(raw_socket));
      packet_socket->RegisterReceivedPacketCallback(
          [&](AsyncPacketSocket* socket, const ReceivedIpPacket& packet) {
            OnPacket(socket, packet);
          });
      packet_socket->SubscribeCloseEvent(
          this, [this](AsyncPacketSocket* s, int err) { OnClose(s, err); });
      client_sockets_.insert(std::move(packet_socket));
    }
  }
  void OnPacket(AsyncPacketSocket* socket, const ReceivedIpPacket& packet) {
    AsyncSocketPacketOptions options;
    socket->Send(packet.payload().data(), packet.payload().size(), options);
  }
  void OnClose(AsyncPacketSocket* socket, int err) {
    // Use `find` instead of `extract` directly because `find` allows
    // heterogeneous lookup while `extract` requires key (i.e., unique_ptr) as
    // the input parameter until c++23.
    auto iter = client_sockets_.find(socket);
    RTC_CHECK(iter != client_sockets_.end());
    // `OnClose` is triggered by socket Close callback, deleting `socket` while
    // processing that callback might be unsafe.
    auto node = client_sockets_.extract(iter);
    Thread::Current()->PostTask([node = std::move(node)] {});
  }

  const Environment env_;
  std::unique_ptr<Socket> server_socket_;
  std::set<std::unique_ptr<AsyncTCPSocket>, less_unique_ptr> client_sockets_;
};

}  //  namespace webrtc


#endif  // RTC_BASE_TEST_ECHO_SERVER_H_
