Move QboneTunnelSilo to third_party.

PiperOrigin-RevId: 344249287
Change-Id: I7dfea6bc00b03db049fdf3a3f4cc4bf18456e49d
diff --git a/quic/qbone/bonnet/qbone_tunnel_silo.cc b/quic/qbone/bonnet/qbone_tunnel_silo.cc
new file mode 100644
index 0000000..418e71f
--- /dev/null
+++ b/quic/qbone/bonnet/qbone_tunnel_silo.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2020 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/qbone/bonnet/qbone_tunnel_silo.h"
+
+namespace quic {
+
+void QboneTunnelSilo::Run() {
+  while (ShouldRun()) {
+    tunnel_->WaitForEvents();
+  }
+
+  QUIC_LOG(INFO) << "Tunnel has disconnected in state: "
+                 << tunnel_->StateToString(tunnel_->Disconnect());
+}
+
+void QboneTunnelSilo::Quit() {
+  QUIC_LOG(INFO) << "Quit called on QboneTunnelSilo";
+  quitting_.Notify();
+  tunnel_->Wake();
+}
+
+bool QboneTunnelSilo::ShouldRun() {
+  bool post_init_shutdown_ready =
+      only_setup_tun_ &&
+      tunnel_->state() == quic::QboneTunnelInterface::STARTED;
+  return !quitting_.HasBeenNotified() && !post_init_shutdown_ready;
+}
+
+}  // namespace quic
diff --git a/quic/qbone/bonnet/qbone_tunnel_silo.h b/quic/qbone/bonnet/qbone_tunnel_silo.h
new file mode 100644
index 0000000..8aad899
--- /dev/null
+++ b/quic/qbone/bonnet/qbone_tunnel_silo.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2020 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_QBONE_BONNET_QBONE_TUNNEL_SILO_H_
+#define QUICHE_QUIC_QBONE_BONNET_QBONE_TUNNEL_SILO_H_
+
+#include "absl/synchronization/notification.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_thread.h"
+#include "net/third_party/quiche/src/quic/qbone/bonnet/qbone_tunnel_interface.h"
+
+namespace quic {
+
+// QboneTunnelSilo is a thread that initializes and evaluates a QboneTunnel's
+// event loop.
+class QboneTunnelSilo : public QuicThread {
+ public:
+  // Does not take ownership of |tunnel|
+  explicit QboneTunnelSilo(QboneTunnelInterface* tunnel, bool only_setup_tun)
+      : QuicThread("QboneTunnelSilo"),
+        tunnel_(tunnel),
+        only_setup_tun_(only_setup_tun) {}
+
+  QboneTunnelSilo(const QboneTunnelSilo&) = delete;
+  QboneTunnelSilo& operator=(const QboneTunnelSilo&) = delete;
+
+  QboneTunnelSilo(QboneTunnelSilo&&) = delete;
+  QboneTunnelSilo& operator=(QboneTunnelSilo&&) = delete;
+
+  // Terminates the tunnel's event loop. This silo must still be joined.
+  void Quit();
+
+ protected:
+  void Run() override;
+
+ private:
+  bool ShouldRun();
+
+  QboneTunnelInterface* tunnel_;
+
+  absl::Notification quitting_;
+
+  const bool only_setup_tun_;
+};
+
+}  // namespace quic
+
+#endif  // QUICHE_QUIC_QBONE_BONNET_QBONE_TUNNEL_SILO_H_
diff --git a/quic/qbone/bonnet/qbone_tunnel_silo_test.cc b/quic/qbone/bonnet/qbone_tunnel_silo_test.cc
new file mode 100644
index 0000000..c2ff8ac
--- /dev/null
+++ b/quic/qbone/bonnet/qbone_tunnel_silo_test.cc
@@ -0,0 +1,78 @@
+// Copyright (c) 2020 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/qbone/bonnet/qbone_tunnel_silo.h"
+
+#include "absl/synchronization/notification.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/qbone/bonnet/mock_qbone_tunnel.h"
+
+namespace quic {
+namespace {
+
+using ::testing::Eq;
+using ::testing::Invoke;
+using ::testing::Return;
+
+TEST(QboneTunnelSiloTest, SiloRunsEventLoop) {
+  MockQboneTunnel mock_tunnel;
+
+  absl::Notification event_loop_run;
+  EXPECT_CALL(mock_tunnel, WaitForEvents)
+      .WillRepeatedly(Invoke([&event_loop_run]() {
+        if (!event_loop_run.HasBeenNotified()) {
+          event_loop_run.Notify();
+        }
+        return false;
+      }));
+
+  QboneTunnelSilo silo(&mock_tunnel, false);
+  silo.Start();
+
+  event_loop_run.WaitForNotification();
+
+  absl::Notification client_disconnected;
+  EXPECT_CALL(mock_tunnel, Disconnect)
+      .WillOnce(Invoke([&client_disconnected]() {
+        client_disconnected.Notify();
+        return QboneTunnelInterface::ENDED;
+      }));
+
+  silo.Quit();
+  client_disconnected.WaitForNotification();
+
+  silo.Join();
+}
+
+TEST(QboneTunnelSiloTest, SiloCanShutDownAfterInit) {
+  MockQboneTunnel mock_tunnel;
+
+  int iteration_count = 0;
+  EXPECT_CALL(mock_tunnel, WaitForEvents)
+      .WillRepeatedly(Invoke([&iteration_count]() {
+        iteration_count++;
+        return false;
+      }));
+
+  EXPECT_CALL(mock_tunnel, state)
+      .WillOnce(Return(QboneTunnelInterface::START_REQUESTED))
+      .WillOnce(Return(QboneTunnelInterface::STARTED));
+
+  absl::Notification client_disconnected;
+  EXPECT_CALL(mock_tunnel, Disconnect)
+      .WillOnce(Invoke([&client_disconnected]() {
+        client_disconnected.Notify();
+        return QboneTunnelInterface::ENDED;
+      }));
+
+  QboneTunnelSilo silo(&mock_tunnel, true);
+  silo.Start();
+
+  client_disconnected.WaitForNotification();
+  silo.Join();
+  EXPECT_THAT(iteration_count, Eq(1));
+}
+
+}  // namespace
+}  // namespace quic