summaryrefslogtreecommitdiffstats
path: root/src/transport.rs
blob: 95d304661972e1575481180645654fe96ca47422 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use anyhow::Result;
use async_trait::async_trait;
use automerge::sync::Message;
use std::boxed::Box;
use std::future::Future;
use std::pin::Pin;

pub type HeadsDigest = [u8; 32];

#[derive(Debug, Clone)]
pub struct Keepalive {
    pub heads_digest: HeadsDigest,
}

#[derive(Debug)]
pub enum ParsedMessage {
    Hello(HelloRequest),
    HelloReply(HelloReply),
    Sync(SyncEnvelope),
    Ping(Keepalive),
    Pong(Keepalive),
}

#[derive(Debug)]
pub struct HelloRequest {}

#[derive(Debug, Clone)]
pub struct HelloReply {
    pub cluster_id: String,
    pub peers: Vec<String>,
}

#[derive(Debug, Clone)]
pub struct SyncEnvelope {
    pub cluster_id: String,
    pub message: Message,
}

/// A message serialized for the wire. Cloning is cheap (shared buffer).
#[derive(Clone, Debug)]
pub struct EncodedMessage {
    pub peer: String,
    pub body: bytes::Bytes,
}

pub type HandlerFn = dyn Fn(String, ParsedMessage) -> Pin<Box<dyn Future<Output = Result<()>> + Send>>
    + Send
    + Sync
    + 'static;
pub type MessageHandler = Box<HandlerFn>;

#[async_trait]
pub trait Transport: Send + Sync {
    /// This node's identity on the transport (for Mycelium: its public key).
    fn local_id(&self) -> &str;

    /// Resolves a user-supplied peer hint (e.g. a seed) to a peer identity.
    async fn resolve_peer(&self, hint: &str) -> Result<String>;

    fn encode(&self, peer: &str, message: &ParsedMessage) -> Result<EncodedMessage>;
    async fn send_encoded(&self, message: &EncodedMessage) -> Result<()>;

    /// Sends an outbound message payload to a targeted peer on a specific topic.
    async fn send_message(&self, peer: &str, message: &ParsedMessage) -> Result<()> {
        let encoded = self.encode(peer, message)?;
        self.send_encoded(&encoded).await
    }

    /// Starts the long-polling inbound event loops, driving messages to the provided handler closure.
    async fn start_consumer(&self, handler: MessageHandler) -> Result<()>;

    /// Asynchronously monitors for fatal network client or sub-process failures.
    async fn wait_for_exit(&self) -> std::io::Result<std::process::ExitStatus>;
}