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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//! ## RLDP - Reliable Large Datagram Protocol
//!
//! A reliable arbitrary-size datagram protocol built upon the ADNL, called RLDP, is used instead
//! of a TCP-like protocol. This reliable datagram protocol can be employed, for instance,
//! to send RPC queries to remote hosts and receive answers from them.
//!
//! TODO

use std::sync::Arc;

use anyhow::Result;
use frunk_core::hlist::{HCons, HList, IntoTuple2, Selector};
use frunk_core::indices::{Here, There};

pub(crate) use decoder::RaptorQDecoder;
pub(crate) use encoder::RaptorQEncoder;
pub use node::{Node, NodeMetrics, NodeOptions};

use crate::adnl;
use crate::subscriber::QuerySubscriber;
use crate::util::{DeferredInitialization, NetworkBuilder};

pub(crate) mod compression;
mod decoder;
mod encoder;
mod incoming_transfer;
mod node;
mod outgoing_transfer;
mod transfers_cache;

pub(crate) type Deferred = Result<(Arc<adnl::Node>, Vec<Arc<dyn QuerySubscriber>>, NodeOptions)>;

impl DeferredInitialization for Deferred {
    type Initialized = Arc<Node>;

    fn initialize(self) -> Result<Self::Initialized> {
        let (adnl, subscribers, options) = self?;
        Node::new(adnl, subscribers, options)
    }
}

impl<L, A, R> NetworkBuilder<L, (A, R)>
where
    L: HList + Selector<adnl::Deferred, A>,
    HCons<Deferred, L>: IntoTuple2,
{
    /// Creates RLDP network layer
    ///
    /// See [`with_rldp_ext`] if you need an RLDP node with additional subscribers
    ///
    /// [`with_rldp_ext`]: fn@crate::util::NetworkBuilder::with_rldp_ext
    ///
    /// # Examples
    ///
    /// ```
    /// # use anyhow::Result;
    /// # use everscale_network::{adnl, rldp, NetworkBuilder};
    /// #[tokio::main]
    /// async fn main() -> Result<()> {
    ///     let keystore = adnl::Keystore::builder()
    ///         .with_tagged_key([0; 32], 0)?
    ///         .build();
    ///
    ///     let adnl_options = adnl::NodeOptions::default();
    ///     let rldp_options = rldp::NodeOptions::default();
    ///
    ///     let (adnl, rldp) = NetworkBuilder::with_adnl("127.0.0.1:10000", keystore, adnl_options)
    ///         .with_rldp(rldp_options)
    ///         .build()?;
    ///     Ok(())
    /// }
    /// ```
    #[allow(clippy::type_complexity)]
    pub fn with_rldp(
        self,
        options: NodeOptions,
    ) -> NetworkBuilder<HCons<Deferred, L>, (There<A>, Here)> {
        self.with_rldp_ext(options, Vec::new())
    }

    /// Creates RLDP network layer with additional RLDP query subscribers
    ///
    /// # Examples
    ///
    /// ```
    /// # use std::borrow::Cow;
    /// # use std::sync::Arc;
    /// # use anyhow::Result;
    /// # use everscale_network::{
    /// #     adnl, rldp, NetworkBuilder, QueryConsumingResult, QuerySubscriber, SubscriberContext,
    /// # };
    /// struct LoggerSubscriber;
    ///
    /// #[async_trait::async_trait]
    /// impl QuerySubscriber for LoggerSubscriber {
    ///     async fn try_consume_query<'a>(
    ///         &self,
    ///         ctx: SubscriberContext<'a>,
    ///         constructor: u32,
    ///         query: Cow<'a, [u8]>,
    ///     ) -> Result<QueryConsumingResult<'a>> {
    ///         println!("received {constructor}");
    ///         Ok(QueryConsumingResult::Rejected(query))
    ///     }
    /// }
    ///
    /// #[tokio::main]
    /// async fn main() -> Result<()> {
    ///     let keystore = adnl::Keystore::builder()
    ///         .with_tagged_key([0; 32], 0)?
    ///         .build();
    ///
    ///     let adnl_options = adnl::NodeOptions::default();
    ///     let rldp_options = rldp::NodeOptions::default();
    ///
    ///     let subscriber = Arc::new(LoggerSubscriber);
    ///
    ///     let (adnl, rldp) = NetworkBuilder::with_adnl("127.0.0.1:10000", keystore, adnl_options)
    ///         .with_rldp_ext(rldp_options, vec![subscriber])
    ///         .build()?;
    ///     Ok(())
    /// }
    /// ```
    #[allow(clippy::type_complexity)]
    pub fn with_rldp_ext(
        self,
        options: NodeOptions,
        subscribers: Vec<Arc<dyn QuerySubscriber>>,
    ) -> NetworkBuilder<HCons<Deferred, L>, (There<A>, Here)> {
        let deferred = match self.0.get() {
            Ok(adnl) => Ok((adnl.clone(), subscribers, options)),
            Err(_) => Err(anyhow::anyhow!("ADNL was not initialized")),
        };
        NetworkBuilder(self.0.prepend(deferred), Default::default())
    }
}