feat: add SSH transport, rsync-style CLI, and --stdio server mode

- Replace send()/recv() with read()/write() + io_set_fds() for fd abstraction
- Add client_connect_ssh() via socketpair + fork/exec; reap child in client_disconnect()
- Add server --stdio flag for SSH invocation
- Replace handle_arg() with rsync-style positional args (fastsync <src> <dest>)
- Add SSH vs TCP auto-detection via is_remote_dest()
- Add TransportType and ssh_destination to Config, fix uninitialized fields in
  config_receive() (pre-existing multithreaded crash)
- Sender threads now wait for server STATUS_OK before disconnecting
- Add --help, error handling for sendfile+SSH combos
- Add pre-flight checks and Posix Args test case to test.py
- Add test_config_ssh_dest() unit test
This commit is contained in:
2026-07-06 18:42:33 +02:00
parent e4ab2a414c
commit fbd7ccf4dd
8 changed files with 347 additions and 40 deletions
+15
View File
@@ -18,6 +18,20 @@ static void test_config_lifecycle() {
EXPECT_FALSE(cfg->use_chunk_serialization);
EXPECT_FALSE(cfg->use_compression);
EXPECT_EQ_INT(cfg->num_connections, 4);
EXPECT_EQ_INT(cfg->transport, TRANSPORT_TCP);
EXPECT_NULL(cfg->ssh_destination);
config_delete(cfg);
}
static void test_config_ssh_dest() {
Config *cfg = config_create(str_dup("1.0"), str_dup("/src"), str_dup("user@host:/dst"),
true, false, false, false, false, 1, 4, false);
cfg->transport = TRANSPORT_SSH;
cfg->ssh_destination = str_dup("user@host:/dst");
EXPECT_NOT_NULL(cfg);
EXPECT_EQ_INT(cfg->transport, TRANSPORT_SSH);
EXPECT_EQ_STR(cfg->ssh_destination, "user@host:/dst");
EXPECT_EQ_STR(cfg->receive_root_directory, "user@host:/dst");
config_delete(cfg);
}
@@ -55,6 +69,7 @@ static void test_pipeline_receiver_lifecycle() {
void test_config() {
test_config_lifecycle();
test_config_ssh_dest();
test_pipeline_sender_lifecycle();
test_pipeline_receiver_lifecycle();
}