CanMan/examples/can-sync/src/protocol.rs
Jason Tudisco a28fac6c9a Rewrite can-sync v2: simplified P2P full-mirror replication
Replace the over-engineered iroh-docs/libraries/filters architecture
with a simple peer-to-peer sync using:
- iroh 0.96 Endpoint for QUIC transport + NAT traversal
- iroh-gossip for peer discovery via shared passphrase
- Protobuf messages over QUIC streams for asset transfer
- CAN service's private /sync/* API for local data access

Deleted: announcer, fetcher, library, manifest, node, routes (2860 lines)
Added: discovery, peer, protocol (simplified ~600 lines)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 12:30:12 -06:00

124 lines
3.3 KiB
Rust

//! Protobuf message types for CAN sync API + peer-to-peer protocol.
//!
//! These match the types in CAN service's routes/sync.rs exactly.
use prost::Message;
// ── CAN Sync API messages (protobuf, same as CAN service) ───────────────
#[derive(Clone, PartialEq, Message)]
pub struct HashListRequest {}
#[derive(Clone, PartialEq, Message)]
pub struct HashListResponse {
#[prost(message, repeated, tag = "1")]
pub assets: Vec<AssetDigest>,
}
#[derive(Clone, PartialEq, Message)]
pub struct AssetDigest {
#[prost(string, tag = "1")]
pub hash: String,
#[prost(int64, tag = "2")]
pub timestamp: i64,
#[prost(int64, tag = "3")]
pub size: i64,
#[prost(bool, tag = "4")]
pub is_trashed: bool,
}
#[derive(Clone, PartialEq, Message)]
pub struct PullRequest {
#[prost(string, repeated, tag = "1")]
pub hashes: Vec<String>,
}
#[derive(Clone, PartialEq, Message)]
pub struct PullResponse {
#[prost(message, repeated, tag = "1")]
pub bundles: Vec<AssetBundle>,
}
#[derive(Clone, PartialEq, Message)]
pub struct AssetBundle {
#[prost(string, tag = "1")]
pub hash: String,
#[prost(int64, tag = "2")]
pub timestamp: i64,
#[prost(string, tag = "3")]
pub mime_type: String,
#[prost(string, optional, tag = "4")]
pub application: Option<String>,
#[prost(string, optional, tag = "5")]
pub user_identity: Option<String>,
#[prost(string, optional, tag = "6")]
pub description: Option<String>,
#[prost(string, optional, tag = "7")]
pub human_filename: Option<String>,
#[prost(string, optional, tag = "8")]
pub human_path: Option<String>,
#[prost(bool, tag = "9")]
pub is_trashed: bool,
#[prost(int64, tag = "10")]
pub size: i64,
#[prost(string, repeated, tag = "11")]
pub tags: Vec<String>,
#[prost(bytes = "vec", tag = "12")]
pub content: Vec<u8>,
}
#[derive(Clone, PartialEq, Message)]
pub struct PushRequest {
#[prost(message, optional, tag = "1")]
pub bundle: Option<AssetBundle>,
}
#[derive(Clone, PartialEq, Message)]
pub struct PushResponse {
#[prost(string, tag = "1")]
pub hash: String,
#[prost(bool, tag = "2")]
pub already_existed: bool,
}
#[derive(Clone, PartialEq, Message)]
pub struct MetaUpdateRequest {
#[prost(string, tag = "1")]
pub hash: String,
#[prost(string, optional, tag = "2")]
pub description: Option<String>,
#[prost(string, repeated, tag = "3")]
pub tags: Vec<String>,
#[prost(bool, tag = "4")]
pub is_trashed: bool,
}
#[derive(Clone, PartialEq, Message)]
pub struct MetaUpdateResponse {
#[prost(bool, tag = "1")]
pub success: bool,
}
// ── Peer-to-peer messages (sent over QUIC streams between sync agents) ──
/// Sent between peers during reconciliation: "here are all the hashes I have"
#[derive(Clone, PartialEq, Message)]
pub struct PeerHashSet {
#[prost(message, repeated, tag = "1")]
pub assets: Vec<AssetDigest>,
}
/// Request from peer: "please send me these assets"
#[derive(Clone, PartialEq, Message)]
pub struct PeerPullRequest {
#[prost(string, repeated, tag = "1")]
pub hashes: Vec<String>,
}
/// A single asset being sent from one peer to another
#[derive(Clone, PartialEq, Message)]
pub struct PeerAssetTransfer {
#[prost(message, optional, tag = "1")]
pub bundle: Option<AssetBundle>,
}