Improve UI by streaming MoQT chat messages to a file. If output_file is an argument, it allows a somewhat friendlier interface where the tail command in a different window allows view of all the messages, while not interfering with typing in the main CLI window. I will integrate the interactive tool for a third mode. PiperOrigin-RevId: 608722885
diff --git a/quiche/quic/moqt/tools/chat_client_bin.cc b/quiche/quic/moqt/tools/chat_client_bin.cc index 282d2d8..8e639d6 100644 --- a/quiche/quic/moqt/tools/chat_client_bin.cc +++ b/quiche/quic/moqt/tools/chat_client_bin.cc
@@ -6,6 +6,7 @@ #include <unistd.h> #include <cstdint> +#include <fstream> #include <iostream> #include <memory> #include <optional> @@ -39,6 +40,10 @@ bool, disable_certificate_verification, false, "If true, don't verify the server certificate."); +DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, output_file, "", + "chat messages will stream to a file instead of stdout"); + class ChatClient { public: ChatClient(quic::QuicServerId& server_id, std::string path, @@ -56,6 +61,11 @@ std::unique_ptr<quic::ProofVerifier> verifier; const bool ignore_certificate = quiche::GetQuicheCommandLineFlag( FLAGS_disable_certificate_verification); + output_filename_ = quiche::GetQuicheCommandLineFlag(FLAGS_output_file); + if (!output_filename_.empty()) { + output_file_.open(output_filename_); + output_file_ << "Chat transcript:\n"; + } if (ignore_certificate) { verifier = std::make_unique<quic::FakeProofVerifier>(); } else { @@ -94,6 +104,13 @@ moqt::FullSequence& next_sequence() { return next_sequence_; } + bool has_output_file() { return !output_filename_.empty(); } + + void WriteToFile(absl::string_view user, absl::string_view message) { + output_file_ << user << ": " << message << "\n\n"; + output_file_.flush(); + } + class QUICHE_EXPORT RemoteTrackVisitor : public moqt::RemoteTrack::Visitor { public: RemoteTrackVisitor(ChatClient* client) : client_(client) {} @@ -138,6 +155,10 @@ std::cout << "Username " << username << "doesn't exist\n"; return; } + if (client_->has_output_file()) { + client_->WriteToFile(username, object); + return; + } std::cout << username << ": " << object << "\n"; } @@ -201,7 +222,6 @@ } while (std::getline(f, line)) { if (!got_version) { - // Chat server currently does not send version if (line != "version=1") { session_->Error(moqt::MoqtError::kProtocolViolation, "Catalog does not begin with version"); @@ -305,6 +325,9 @@ // Handling incoming and outgoing messages moqt::FullSequence next_sequence_ = {0, 0}; + + std::ofstream output_file_; + std::string output_filename_; }; // A client for MoQT over chat, used for interop testing. See @@ -335,8 +358,13 @@ client.RunEventLoop(); } if (client.session_is_open()) { - std::cout << "Fully connected. Press ENTER to begin input of message, " - << "ENTER when done. Exit session if the message is ':exit'\n"; + if (client.has_output_file()) { + std::cout << "Fully connected. Messages are in the output file. Exit the " + << "session by entering :exit\n"; + } else { + std::cout << "Fully connected. Press ENTER to begin input of message, " + << "ENTER when done. Exit session if the message is ':exit'\n"; + } } bool session_is_open = client.session_is_open(); struct pollfd poll_settings = { @@ -349,8 +377,10 @@ while (poll(&poll_settings, 1, 0) <= 0) { client.RunEventLoop(); } - std::cin.ignore(10, '\n'); - std::cout << username << ": "; + if (!client.has_output_file()) { + std::cin.ignore(10, '\n'); + std::cout << username << ": "; + } std::getline(std::cin, message_to_send); if (message_to_send.empty()) { continue; @@ -361,6 +391,9 @@ session_is_open = false; break; } + if (client.has_output_file()) { + client.WriteToFile(username, message_to_send); + } client.session()->PublishObject( client.my_track_name(), client.next_sequence().group++, client.next_sequence().object, /*object_send_order=*/0,