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,