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
#![warn(missing_docs)]
//! This module provider [SwarmBuilder] and it's interface for
//! [Swarm]

use std::sync::Arc;
use std::sync::RwLock;

use crate::dht::PeerRing;
use crate::dht::VNodeStorage;
use crate::measure::MeasureImpl;
use crate::session::SessionSk;
use crate::swarm::callback::SharedSwarmCallback;
use crate::swarm::callback::SwarmCallback;
use crate::swarm::transport::SwarmTransport;
use crate::swarm::Swarm;

struct DefaultCallback;
impl SwarmCallback for DefaultCallback {}

/// Creates a SwarmBuilder to configure a Swarm.
pub struct SwarmBuilder {
    network_id: u32,
    ice_servers: String,
    external_address: Option<String>,
    dht_succ_max: u8,
    dht_storage: VNodeStorage,
    session_sk: SessionSk,
    session_ttl: Option<usize>,
    measure: Option<MeasureImpl>,
    callback: Option<SharedSwarmCallback>,
}

impl SwarmBuilder {
    /// Creates new instance of [SwarmBuilder]
    pub fn new(
        network_id: u32,
        ice_servers: &str,
        dht_storage: VNodeStorage,
        session_sk: SessionSk,
    ) -> Self {
        SwarmBuilder {
            network_id,
            ice_servers: ice_servers.to_string(),
            external_address: None,
            dht_succ_max: 3,
            dht_storage,
            session_sk,
            session_ttl: None,
            measure: None,
            callback: 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 callback for Swarm.
    pub fn callback(mut self, callback: SharedSwarmCallback) -> Self {
        self.callback = Some(callback);
        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 callback = RwLock::new(
            self.callback
                .unwrap_or_else(|| Arc::new(DefaultCallback {})),
        );

        let transport = Arc::new(SwarmTransport::new(
            self.network_id,
            &self.ice_servers,
            self.external_address,
            self.session_sk,
            dht.clone(),
            self.measure,
        ));

        Swarm {
            dht,
            transport,
            callback,
        }
    }
}