// Copyright 2013 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.

#ifndef QUICHE_QUIC_TEST_TOOLS_SERVER_THREAD_H_
#define QUICHE_QUIC_TEST_TOOLS_SERVER_THREAD_H_

#include <memory>

#include "quic/core/quic_config.h"
#include "quic/platform/api/quic_containers.h"
#include "quic/platform/api/quic_mutex.h"
#include "quic/platform/api/quic_socket_address.h"
#include "quic/platform/api/quic_thread.h"
#include "quic/tools/quic_server.h"

namespace quic {
namespace test {

// Simple wrapper class to run QuicServer in a dedicated thread.
class ServerThread : public QuicThread {
 public:
  ServerThread(QuicServer* server, const QuicSocketAddress& address);
  ServerThread(const ServerThread&) = delete;
  ServerThread& operator=(const ServerThread&) = delete;

  ~ServerThread() override;

  // Prepares the server, but does not start accepting connections. Useful for
  // injecting mocks.
  void Initialize();

  // Runs the event loop. Will initialize if necessary.
  void Run() override;

  // Schedules the given action for execution in the event loop.
  void Schedule(std::function<void()> action);

  // Waits for the handshake to be confirmed for the first session created.
  void WaitForCryptoHandshakeConfirmed();

  // Wait until |termination_predicate| returns true in server thread, or
  // reached |timeout|. Must be called from an external thread.
  // Return whether the function returned after |termination_predicate| become
  // true.
  bool WaitUntil(std::function<bool()> termination_predicate,
                 QuicTime::Delta timeout);

  // Pauses execution of the server until Resume() is called.  May only be
  // called once.
  void Pause();

  // Resumes execution of the server after Pause() has been called.  May only
  // be called once.
  void Resume();

  // Stops the server from executing and shuts it down, destroying all
  // server objects.
  void Quit();

  // Returns the underlying server.  Care must be taken to avoid data races
  // when accessing the server.  It is always safe to access the server
  // after calling Pause() and before calling Resume().
  QuicServer* server() { return server_.get(); }

  // Returns the port that the server is listening on.
  int GetPort();

 private:
  void MaybeNotifyOfHandshakeConfirmation();
  void ExecuteScheduledActions();

  QuicNotification
      confirmed_;            // Notified when the first handshake is confirmed.
  QuicNotification pause_;   // Notified when the server should pause.
  QuicNotification paused_;  // Notitied when the server has paused
  QuicNotification resume_;  // Notified when the server should resume.
  QuicNotification quit_;    // Notified when the server should quit.

  std::unique_ptr<QuicServer> server_;
  QuicEpollClock clock_;
  QuicSocketAddress address_;
  mutable QuicMutex port_lock_;
  int port_ QUIC_GUARDED_BY(port_lock_);

  bool initialized_;

  QuicMutex scheduled_actions_lock_;
  quiche::QuicheCircularDeque<std::function<void()>> scheduled_actions_
      QUIC_GUARDED_BY(scheduled_actions_lock_);
};

}  // namespace test
}  // namespace quic

#endif  // QUICHE_QUIC_TEST_TOOLS_SERVER_THREAD_H_
