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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#![warn(missing_docs)]
//! This module provider [SwarmBuilder] and it's interface for
//! [Swarm]

use std::sync::Arc;

use rings_transport::core::callback::Callback;
use rings_transport::Transport;

use crate::channels::Channel;
use crate::dht::PeerRing;
use crate::message::CallbackFn;
use crate::message::MessageHandler;
use crate::message::ValidatorFn;
use crate::session::SessionSk;
use crate::storage::PersistenceStorage;
use crate::swarm::callback::SwarmCallback;
use crate::swarm::MeasureImpl;
use crate::swarm::Swarm;
use crate::types::channel::Channel as ChannelTrait;

/// Creates a SwarmBuilder to configure a Swarm.
pub struct SwarmBuilder {
    ice_servers: String,
    external_address: Option<String>,
    dht_succ_max: u8,
    dht_storage: PersistenceStorage,
    session_sk: SessionSk,
    session_ttl: Option<usize>,
    measure: Option<MeasureImpl>,
    message_callback: Option<CallbackFn>,
    message_validator: Option<ValidatorFn>,
}

impl SwarmBuilder {
    /// Creates new instance of [SwarmBuilder]
    pub fn new(ice_servers: &str, dht_storage: PersistenceStorage, session_sk: SessionSk) -> Self {
        SwarmBuilder {
            ice_servers: ice_servers.to_string(),
            external_address: None,
            dht_succ_max: 3,
            dht_storage,
            session_sk,
            session_ttl: None,
            measure: None,
            message_callback: None,
            message_validator: None,
        }
    }

    /// Sets up the maximum length of successors in the DHT.
    pub fn dht_succ_max(mut self, succ_max: u8) -> Self {
        self.dht_succ_max = succ_max;
        self
    }

    /// Sets up the external address for swarm transport.
    /// This will be used to configure the transport to listen for WebRTC connections in "HOST" mode.
    pub fn external_address(mut self, external_address: String) -> Self {
        self.external_address = Some(external_address);
        self
    }

    /// Setup timeout for session.
    pub fn session_ttl(mut self, ttl: usize) -> Self {
        self.session_ttl = Some(ttl);
        self
    }

    /// Bind measurement function for Swarm.
    pub fn measure(mut self, implement: MeasureImpl) -> Self {
        self.measure = Some(implement);
        self
    }

    /// Bind message callback function for Swarm.
    pub fn message_callback(mut self, callback: CallbackFn) -> Self {
        self.message_callback = Some(callback);
        self
    }

    /// Bind message vilidator function implementation for Swarm.
    pub fn message_validator(mut self, validator: ValidatorFn) -> Self {
        self.message_validator = Some(validator);
        self
    }

    /// Try build for `Swarm`.
    pub fn build(self) -> Swarm {
        let dht_did = self.session_sk.account_did();

        let dht = Arc::new(PeerRing::new_with_storage(
            dht_did,
            self.dht_succ_max,
            self.dht_storage,
        ));

        let message_handler =
            MessageHandler::new(dht.clone(), self.message_callback, self.message_validator);

        let transport_event_channel = Channel::new();

        let transport = Transport::new(&self.ice_servers, self.external_address);
        let callback = Arc::new(SwarmCallback::new(transport_event_channel.sender()).boxed());

        Swarm {
            transport_event_channel,
            dht,
            measure: self.measure,
            session_sk: self.session_sk,
            message_handler,
            transport,
            callback,
        }
    }
}