Project import generated by Copybara.

PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/test_tools/server_thread.cc b/quic/test_tools/server_thread.cc
new file mode 100644
index 0000000..ca15913
--- /dev/null
+++ b/quic/test_tools/server_thread.cc
@@ -0,0 +1,121 @@
+// 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.
+
+#include "net/third_party/quiche/src/quic/test_tools/server_thread.h"
+
+#include "net/third_party/quiche/src/quic/core/quic_dispatcher.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_server_peer.h"
+
+namespace quic {
+namespace test {
+
+ServerThread::ServerThread(QuicServer* server, const QuicSocketAddress& address)
+    : QuicThread("server_thread"),
+      server_(server),
+      address_(address),
+      port_(0),
+      initialized_(false) {}
+
+ServerThread::~ServerThread() = default;
+
+void ServerThread::Initialize() {
+  if (initialized_) {
+    return;
+  }
+
+  server_->CreateUDPSocketAndListen(address_);
+
+  QuicWriterMutexLock lock(&port_lock_);
+  port_ = server_->port();
+
+  initialized_ = true;
+}
+
+void ServerThread::Run() {
+  if (!initialized_) {
+    Initialize();
+  }
+
+  while (!quit_.HasBeenNotified()) {
+    if (pause_.HasBeenNotified() && !resume_.HasBeenNotified()) {
+      paused_.Notify();
+      resume_.WaitForNotification();
+    }
+    server_->WaitForEvents();
+    ExecuteScheduledActions();
+    MaybeNotifyOfHandshakeConfirmation();
+  }
+
+  server_->Shutdown();
+}
+
+int ServerThread::GetPort() {
+  QuicReaderMutexLock lock(&port_lock_);
+  int rc = port_;
+  return rc;
+}
+
+void ServerThread::Schedule(std::function<void()> action) {
+  DCHECK(!quit_.HasBeenNotified());
+  QuicWriterMutexLock lock(&scheduled_actions_lock_);
+  scheduled_actions_.push_back(std::move(action));
+}
+
+void ServerThread::WaitForCryptoHandshakeConfirmed() {
+  confirmed_.WaitForNotification();
+}
+
+void ServerThread::Pause() {
+  DCHECK(!pause_.HasBeenNotified());
+  pause_.Notify();
+  paused_.WaitForNotification();
+}
+
+void ServerThread::Resume() {
+  DCHECK(!resume_.HasBeenNotified());
+  DCHECK(pause_.HasBeenNotified());
+  resume_.Notify();
+}
+
+void ServerThread::Quit() {
+  if (pause_.HasBeenNotified() && !resume_.HasBeenNotified()) {
+    resume_.Notify();
+  }
+  if (!quit_.HasBeenNotified()) {
+    quit_.Notify();
+  }
+}
+
+void ServerThread::MaybeNotifyOfHandshakeConfirmation() {
+  if (confirmed_.HasBeenNotified()) {
+    // Only notify once.
+    return;
+  }
+  QuicDispatcher* dispatcher = QuicServerPeer::GetDispatcher(server());
+  if (dispatcher->session_map().empty()) {
+    // Wait for a session to be created.
+    return;
+  }
+  QuicSession* session = dispatcher->session_map().begin()->second.get();
+  if (session->IsCryptoHandshakeConfirmed()) {
+    confirmed_.Notify();
+  }
+}
+
+void ServerThread::ExecuteScheduledActions() {
+  QuicDeque<std::function<void()>> actions;
+  {
+    QuicWriterMutexLock lock(&scheduled_actions_lock_);
+    actions.swap(scheduled_actions_);
+  }
+  while (!actions.empty()) {
+    actions.front()();
+    actions.pop_front();
+  }
+}
+
+}  // namespace test
+}  // namespace quic