Skip to main content

Crate zyris_transfer

Crate zyris_transfer 

Source
Expand description

The reference implementation of node-to-node file transfer for Zyris.

zyris_caps declares two capabilities here and says nothing about how either is served. peer_transfer is the exchange two nodes have with each other; file_transfer is the surface an agent calls to start one and to read what has arrived. This crate is one answer to both.

There is no human confirmation on the receiving side — an agent calls a tool and a file lands on someone else’s machine. The path jail, the size limit and the audit log are the only defenses there are. This crate splits those between its parts.

ModuleWhat it owns
nameProposed name → a single path component. Never touches the filesystem
inboxChoosing the destination and checking the real path. Rejects symlinks
undoMoves the original aside before overwriting
auditWrites one line per transfer
peerWires the above together into peer_transfer
sendThe other direction — the file_transfer surface an agent calls
listenAccepting peer connections, and deciding whose they are
rendezvousThe Attacca client both of those ask where a peer is

name is kept apart from inbox on purpose — sanitizing is a pure decision, so dozens of cases run as one table test in an instant. Merged in, every one of those tests would need a tempfile.

§Features

Everything above the line is unconditional: it touches nothing but the filesystem, so it costs no transport dependencies, and it alone is enough to drive a whole exchange over zyris::testing::duplex.

FeatureWhat it adds
sendfile_transfer.send_to: the rendezvous client and the iroh dial
listenAccepting peer connections: the rendezvous, and iroh to accept at all

Both are off by default and each stands on its own. The two directions are separately useful — a node can take deliveries without carrying the tool surface that makes them, and a node can make them without listening. rendezvous is compiled for either, which is what keeps that claim true: it used to live inside send, so listen reached across into it and did not compile alone, however plainly this said otherwise.

Turning either on reaches iroh, and through it a ring build that needs a C toolchain. See this crate’s Cargo.toml.

use zyris::{Node, NodeKind};
use zyris_caps::PeerTransferServer;
use zyris_transfer::{LocalPeerTransfer, TransferConfig};

let config = TransferConfig {
    inbox: "/srv/inbox".into(),
    undo: "/srv/undo".into(),
    ..TransferConfig::default()
};
// The peer's own name, which decides which subdirectory of the inbox its files land in.
let receiving = LocalPeerTransfer::receiver_pending(config, "laptop".to_string());
let node = Node::builder()
    .name("workstation")
    .kind(NodeKind::Service)
    .capability(PeerTransferServer(receiving))
    .build()?;

Re-exports§

pub use audit::Audit;
pub use audit::AuditLine;
pub use inbox::Inbox;
pub use inbox::InboxError;
pub use listen::serve_peers;
pub use listen::PeerCache;
pub use listen::PeerDirectory;
pub use listen::DEFAULT_DIRECTORY_TTL;
pub use listen::DEFAULT_REFRESH_INTERVAL;
pub use name::safe_name;
pub use peer::InFlight;
pub use peer::LocalPeerTransfer;
pub use peer::TRANSFER_IN_FLIGHT;
pub use peer::TransferConfig;
pub use peer::part_path;
pub use rendezvous::Rendezvous;
pub use send::FileTransferConfig;
pub use send::LocalFileTransfer;
pub use send::PeerSession;
pub use send::DEFAULT_WIRE_DEADLINE;
pub use undo::UndoStore;

Modules§

audit
One line per transfer. In a flow with no human confirmation this is the only way to find out afterwards what happened.
inbox
Where received files land. It is a jail.
listen
Taking incoming peer connections. Not from anyone who asks.
name
Washes the name the sending side proposed into a single path component the receiving side can use.
peer
Reference implementation of peer_transfer. One type plays both roles — the sending side answers pull, the receiving side answers push_offer.
rendezvous
The handle both network halves ask where a peer is.
send
The sending side: what an agent calls to put a file on another node of the same account.
undo
Moves the original aside before it gets overwritten.