Add a simple QuicTransport server for testing and demo purposes.

The server currently has two modes, echo and discard.  I've changed the integration test to use the simple server instead of a session with a mock visitor.

This CL also adds some of the missing APIs and fixes some of the bugs I've found while doing this.

gfe-relnote: n/a (code not used)
PiperOrigin-RevId: 278456752
Change-Id: Idf9aa654aa0d66673f300f2f5425f0716d6c3e14
diff --git a/quic/tools/quic_transport_simple_server_session.cc b/quic/tools/quic_transport_simple_server_session.cc
new file mode 100644
index 0000000..273a9ae
--- /dev/null
+++ b/quic/tools/quic_transport_simple_server_session.cc
@@ -0,0 +1,228 @@
+// Copyright (c) 2019 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/tools/quic_transport_simple_server_session.h"
+
+#include <memory>
+
+#include "url/gurl.h"
+#include "url/origin.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
+
+namespace quic {
+
+namespace {
+
+// Discards any incoming data.
+class DiscardVisitor : public QuicTransportStream::Visitor {
+ public:
+  DiscardVisitor(QuicTransportStream* stream) : stream_(stream) {}
+
+  void OnCanRead() override {
+    std::string buffer;
+    size_t bytes_read = stream_->Read(&buffer);
+    QUIC_DVLOG(2) << "Read " << bytes_read << " bytes from stream "
+                  << stream_->id();
+  }
+
+  void OnFinRead() override {}
+  void OnCanWrite() override {}
+
+ private:
+  QuicTransportStream* stream_;
+};
+
+// Echoes any incoming data back on the same stream.
+class BidirectionalEchoVisitor : public QuicTransportStream::Visitor {
+ public:
+  BidirectionalEchoVisitor(QuicTransportStream* stream) : stream_(stream) {}
+
+  void OnCanRead() override {
+    stream_->Read(&buffer_);
+    OnCanWrite();
+  }
+
+  void OnFinRead() override {
+    bool success = stream_->SendFin();
+    DCHECK(success);
+  }
+
+  void OnCanWrite() override {
+    if (buffer_.empty()) {
+      return;
+    }
+
+    bool success = stream_->Write(buffer_);
+    if (success) {
+      buffer_ = "";
+    }
+  }
+
+ private:
+  QuicTransportStream* stream_;
+  std::string buffer_;
+};
+
+// Buffers all of the data and calls EchoStreamBack() on the parent session.
+class UnidirectionalEchoReadVisitor : public QuicTransportStream::Visitor {
+ public:
+  UnidirectionalEchoReadVisitor(QuicTransportSimpleServerSession* session,
+                                QuicTransportStream* stream)
+      : session_(session), stream_(stream) {}
+
+  void OnCanRead() override {
+    bool success = stream_->Read(&buffer_);
+    DCHECK(success);
+  }
+
+  void OnFinRead() override {
+    QUIC_DVLOG(1) << "Finished receiving data on stream " << stream_->id()
+                  << ", queueing up the echo";
+    session_->EchoStreamBack(buffer_);
+  }
+
+  void OnCanWrite() override { QUIC_NOTREACHED(); }
+
+ private:
+  QuicTransportSimpleServerSession* session_;
+  QuicTransportStream* stream_;
+  std::string buffer_;
+};
+
+// Sends supplied data.
+class UnidirectionalEchoWriteVisitor : public QuicTransportStream::Visitor {
+ public:
+  UnidirectionalEchoWriteVisitor(QuicTransportStream* stream,
+                                 const std::string& data)
+      : stream_(stream), data_(data) {}
+
+  void OnCanRead() override { QUIC_NOTREACHED(); }
+  void OnFinRead() override { QUIC_NOTREACHED(); }
+  void OnCanWrite() override {
+    if (data_.empty()) {
+      return;
+    }
+    if (!stream_->Write(data_)) {
+      return;
+    }
+    data_ = "";
+    bool fin_sent = stream_->SendFin();
+    DCHECK(fin_sent);
+  }
+
+ private:
+  QuicTransportStream* stream_;
+  std::string data_;
+};
+
+}  // namespace
+
+QuicTransportSimpleServerSession::QuicTransportSimpleServerSession(
+    QuicConnection* connection,
+    bool owns_connection,
+    Visitor* owner,
+    const QuicConfig& config,
+    const ParsedQuicVersionVector& supported_versions,
+    const QuicCryptoServerConfig* crypto_config,
+    QuicCompressedCertsCache* compressed_certs_cache,
+    Mode mode,
+    std::vector<url::Origin> accepted_origins)
+    : QuicTransportServerSession(connection,
+                                 owner,
+                                 config,
+                                 supported_versions,
+                                 crypto_config,
+                                 compressed_certs_cache,
+                                 this),
+      connection_(connection),
+      owns_connection_(owns_connection),
+      mode_(mode),
+      accepted_origins_(accepted_origins) {
+  Initialize();
+}
+
+QuicTransportSimpleServerSession::~QuicTransportSimpleServerSession() {
+  if (owns_connection_) {
+    delete connection_;
+  }
+}
+
+void QuicTransportSimpleServerSession::OnIncomingDataStream(
+    QuicTransportStream* stream) {
+  switch (mode_) {
+    case DISCARD:
+      stream->set_visitor(std::make_unique<DiscardVisitor>(stream));
+      break;
+
+    case ECHO:
+      switch (stream->type()) {
+        case BIDIRECTIONAL:
+          QUIC_DVLOG(1) << "Opening bidirectional echo stream " << stream->id();
+          stream->set_visitor(
+              std::make_unique<BidirectionalEchoVisitor>(stream));
+          break;
+        case READ_UNIDIRECTIONAL:
+          QUIC_DVLOG(1)
+              << "Started receiving data on unidirectional echo stream "
+              << stream->id();
+          stream->set_visitor(
+              std::make_unique<UnidirectionalEchoReadVisitor>(this, stream));
+          break;
+        default:
+          QUIC_NOTREACHED();
+          break;
+      }
+      break;
+  }
+}
+
+void QuicTransportSimpleServerSession::OnCanCreateNewOutgoingStream(
+    bool unidirectional) {
+  if (mode_ == ECHO && unidirectional) {
+    MaybeEchoStreamsBack();
+  }
+}
+
+bool QuicTransportSimpleServerSession::CheckOrigin(url::Origin origin) {
+  if (accepted_origins_.empty()) {
+    return true;
+  }
+
+  for (const url::Origin& accepted_origin : accepted_origins_) {
+    if (origin.IsSameOriginWith(accepted_origin)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void QuicTransportSimpleServerSession::MaybeEchoStreamsBack() {
+  while (!streams_to_echo_back_.empty() &&
+         CanOpenNextOutgoingUnidirectionalStream()) {
+    // Remove the stream from the queue first, in order to avoid accidentally
+    // entering an infinite loop in case any of the following code calls
+    // OnCanCreateNewOutgoingStream().
+    std::string data = std::move(streams_to_echo_back_.front());
+    streams_to_echo_back_.pop_front();
+
+    auto stream_owned = std::make_unique<QuicTransportStream>(
+        GetNextOutgoingUnidirectionalStreamId(), this, this);
+    QuicTransportStream* stream = stream_owned.get();
+    ActivateStream(std::move(stream_owned));
+    QUIC_DVLOG(1) << "Opened echo response stream " << stream->id();
+
+    stream->set_visitor(
+        std::make_unique<UnidirectionalEchoWriteVisitor>(stream, data));
+    stream->visitor()->OnCanWrite();
+  }
+}
+
+}  // namespace quic