Milestone 5

This commit is contained in:
Joey Yakimowich-Payne 2026-01-29 21:13:18 -07:00
commit 4e21039222
9 changed files with 877 additions and 22 deletions

View file

@ -1,3 +1,4 @@
#include <csignal>
#include <cstdint>
#include <cstdlib>
#include <iostream>
@ -7,6 +8,12 @@
namespace {
volatile sig_atomic_t g_running = 1;
void SignalHandler(int) {
g_running = 0;
}
uint32_t ParseId(const char* value) {
if (!value) {
return 0;
@ -19,11 +26,29 @@ uint32_t ParseId(const char* value) {
return static_cast<uint32_t>(parsed);
}
std::string ArgValue(int argc, char* argv[], int i, const char* flag) {
if (i + 1 < argc) {
return argv[i + 1];
}
std::cerr << "warppipe: missing value for " << flag << "\n";
return "";
}
int Usage() {
std::cerr << "Usage:\n"
<< " warppipe_cli list-nodes\n"
<< " warppipe_cli list-ports <node-id>\n"
<< " warppipe_cli list-links\n";
<< " warppipe_cli list-links\n"
<< " warppipe_cli list-rules\n"
<< " warppipe_cli create-sink <name> [--rate N] [--channels N]\n"
<< " warppipe_cli create-source <name> [--rate N] [--channels N]\n"
<< " warppipe_cli link <out-node> <out-port> <in-node> <in-port> [--passive] [--linger]\n"
<< " warppipe_cli unlink <link-id>\n"
<< " warppipe_cli add-rule --app <name> --target <node> [--process <bin>] [--role <role>]\n"
<< " warppipe_cli remove-rule <rule-id>\n"
<< " warppipe_cli save-config <path>\n"
<< " warppipe_cli load-config <path>\n"
<< " warppipe_cli defaults\n";
return 2;
}
@ -91,5 +116,189 @@ int main(int argc, char* argv[]) {
return 0;
}
if (command == "list-rules") {
auto rules = client_result.value->ListRouteRules();
if (!rules.ok()) {
std::cerr << "warppipe: list-rules failed: " << rules.status.message << "\n";
return 1;
}
for (const auto& rule : rules.value) {
std::cout << rule.id.value << "\t"
<< "app=" << rule.match.application_name << "\t"
<< "proc=" << rule.match.process_binary << "\t"
<< "role=" << rule.match.media_role << "\t"
<< "-> " << rule.target_node << "\n";
}
return 0;
}
if (command == "create-sink" || command == "create-source") {
if (argc < 3) {
return Usage();
}
std::string name = argv[2];
warppipe::VirtualNodeOptions node_options;
for (int i = 3; i < argc; ++i) {
std::string arg = argv[i];
if (arg == "--rate" && i + 1 < argc) {
node_options.format.rate = ParseId(argv[++i]);
} else if (arg == "--channels" && i + 1 < argc) {
node_options.format.channels = ParseId(argv[++i]);
}
}
if (command == "create-sink") {
auto result = client_result.value->CreateVirtualSink(name, node_options);
if (!result.ok()) {
std::cerr << "warppipe: create-sink failed: " << result.status.message << "\n";
return 1;
}
std::cout << "created sink " << result.value.name
<< " (node " << result.value.node.value << ")\n";
} else {
auto result = client_result.value->CreateVirtualSource(name, node_options);
if (!result.ok()) {
std::cerr << "warppipe: create-source failed: " << result.status.message << "\n";
return 1;
}
std::cout << "created source " << result.value.name
<< " (node " << result.value.node.value << ")\n";
}
std::cout << "press Ctrl+C to stop\n";
std::signal(SIGINT, SignalHandler);
std::signal(SIGTERM, SignalHandler);
while (g_running) {
usleep(100000);
}
std::cout << "\nshutting down\n";
return 0;
}
if (command == "link") {
if (argc < 6) {
std::cerr << "warppipe: link requires <out-node> <out-port> <in-node> <in-port>\n";
return Usage();
}
std::string out_node = argv[2];
std::string out_port = argv[3];
std::string in_node = argv[4];
std::string in_port = argv[5];
warppipe::LinkOptions link_opts;
for (int i = 6; i < argc; ++i) {
std::string arg = argv[i];
if (arg == "--passive") {
link_opts.passive = true;
} else if (arg == "--linger") {
link_opts.linger = true;
}
}
auto result = client_result.value->CreateLinkByName(out_node, out_port, in_node, in_port, link_opts);
if (!result.ok()) {
std::cerr << "warppipe: link failed: " << result.status.message << "\n";
return 1;
}
std::cout << "created link " << result.value.id.value << "\n";
return 0;
}
if (command == "unlink") {
if (argc < 3) {
return Usage();
}
uint32_t link_id = ParseId(argv[2]);
if (link_id == 0) {
std::cerr << "warppipe: invalid link id\n";
return 1;
}
auto status = client_result.value->RemoveLink(warppipe::LinkId{link_id});
if (!status.ok()) {
std::cerr << "warppipe: unlink failed: " << status.message << "\n";
return 1;
}
std::cout << "removed link " << link_id << "\n";
return 0;
}
if (command == "add-rule") {
warppipe::RouteRule rule;
for (int i = 2; i < argc; ++i) {
std::string arg = argv[i];
if (arg == "--app" && i + 1 < argc) {
rule.match.application_name = argv[++i];
} else if (arg == "--process" && i + 1 < argc) {
rule.match.process_binary = argv[++i];
} else if (arg == "--role" && i + 1 < argc) {
rule.match.media_role = argv[++i];
} else if (arg == "--target" && i + 1 < argc) {
rule.target_node = argv[++i];
}
}
auto result = client_result.value->AddRouteRule(rule);
if (!result.ok()) {
std::cerr << "warppipe: add-rule failed: " << result.status.message << "\n";
return 1;
}
std::cout << "added rule " << result.value.value << "\n";
return 0;
}
if (command == "remove-rule") {
if (argc < 3) {
return Usage();
}
uint32_t rule_id = ParseId(argv[2]);
if (rule_id == 0) {
std::cerr << "warppipe: invalid rule id\n";
return 1;
}
auto status = client_result.value->RemoveRouteRule(warppipe::RuleId{rule_id});
if (!status.ok()) {
std::cerr << "warppipe: remove-rule failed: " << status.message << "\n";
return 1;
}
std::cout << "removed rule " << rule_id << "\n";
return 0;
}
if (command == "save-config") {
if (argc < 3) {
return Usage();
}
auto status = client_result.value->SaveConfig(argv[2]);
if (!status.ok()) {
std::cerr << "warppipe: save-config failed: " << status.message << "\n";
return 1;
}
std::cout << "saved config to " << argv[2] << "\n";
return 0;
}
if (command == "load-config") {
if (argc < 3) {
return Usage();
}
auto status = client_result.value->LoadConfig(argv[2]);
if (!status.ok()) {
std::cerr << "warppipe: load-config failed: " << status.message << "\n";
return 1;
}
std::cout << "loaded config from " << argv[2] << "\n";
return 0;
}
if (command == "defaults") {
auto defaults = client_result.value->GetDefaults();
if (!defaults.ok()) {
std::cerr << "warppipe: defaults failed: " << defaults.status.message << "\n";
return 1;
}
std::cout << "default_sink\t" << defaults.value.default_sink_name << "\n"
<< "default_source\t" << defaults.value.default_source_name << "\n"
<< "configured_sink\t" << defaults.value.configured_sink_name << "\n"
<< "configured_source\t" << defaults.value.configured_source_name << "\n";
return 0;
}
return Usage();
}