Skip to main content

dht_rpc/
lib.rs

1//! Rust Implementation of the hyperswarm DHT
2#![warn(
3    //unreachable_pub, // TODO
4    //missing_debug_implementations, // TODO
5    //missing_docs, // TODO
6    redundant_lifetimes,
7    unsafe_code,
8    non_local_definitions,
9    clippy::needless_pass_by_value,
10    clippy::needless_pass_by_ref_mut,
11    clippy::enum_glob_use
12)]
13
14mod cenc;
15mod commit;
16mod constants;
17mod io;
18mod kbucket;
19mod message;
20mod periodic_job;
21mod query;
22mod stateobserver;
23mod stream;
24mod util;
25
26pub use crate::{
27    cenc::generic_hash,
28    commit::Commit,
29    io::{InResponse, OutRequestBuilder},
30    message::{ReplyMsgData, RequestMsgData, RequestMsgDataInner},
31    periodic_job::PeriodicJob,
32    query::{CommandQuery, CommandQueryResponse, QueryId, QueryResult},
33};
34
35#[cfg(test)]
36mod s_test;
37#[cfg(test)]
38pub mod test;
39use constants::ID_BYTES_LENGTH;
40use futures::{Stream, channel::mpsc};
41use std::{
42    array::TryFromSliceError,
43    borrow::Borrow,
44    collections::{BTreeMap, BTreeSet, HashSet, VecDeque},
45    convert::{TryFrom, TryInto},
46    fmt::Display,
47    future::Future,
48    iter::FromIterator,
49    net::{AddrParseError, SocketAddr, SocketAddrV4, ToSocketAddrs},
50    pin::Pin,
51    str::FromStr,
52    sync::{Arc, Mutex, RwLock},
53    task::{Context, Poll, Waker},
54    time::Duration,
55};
56use tracing::{debug, error, instrument, trace, warn};
57use wasm_timer::Instant;
58
59use rand::{
60    RngCore, SeedableRng,
61    rngs::{OsRng, StdRng},
62};
63
64use crate::{
65    cenc::validate_id,
66    commit::{CommitMessage, Progress},
67    kbucket::{
68        Distance, Entry, EntryView, InsertResult, K_VALUE, KBucketsTable, NodeStatus, distance,
69    },
70    util::pretty_bytes,
71};
72use compact_encoding::EncodingError;
73use tokio::sync::oneshot::{self, Receiver, Sender, error::RecvError};
74
75use self::{
76    io::{IoConfig, IoHandler, IoHandlerEvent},
77    query::{
78        Query, QueryConfig, QueryEvent, QueryPool, QueryPoolEvent, QueryStats, table::PeerState,
79    },
80    stateobserver::State,
81    stream::MessageDataStream,
82};
83pub use crate::io::Tid;
84
85const DEFAULT_REQUEST_TIMEOUT: Duration = Duration::from_secs(3);
86
87/// The publicly available hyperswarm DHT addresses
88pub const DEFAULT_BOOTSTRAP: [&str; 3] = [
89    "node1.hyperdht.org:49737",
90    "node2.hyperdht.org:49737",
91    "node3.hyperdht.org:49737",
92];
93
94/// The command identifier for `Mutable` storage
95pub const MUTABLE_STORE_CMD: usize = 1;
96/// The command identifier for immutable storage
97pub const IMMUTABLE_STORE_CMD: usize = 2;
98/// The command identifier to (un)announce/lookup peers
99pub const PEERS_CMD: usize = 3;
100
101#[derive(Debug, thiserror::Error)]
102pub enum Error {
103    #[error("Error from compact_encoding: {0}")]
104    CompactEncodingError(EncodingError),
105    #[error("IO Eror")]
106    IoError(#[from] std::io::Error),
107    #[error("Invalid RPC command in message: {0}")]
108    InvalidRpcCommand(u8),
109    #[error("Incorrect message ID size. Expected 32. Error: {0}")]
110    IncorrectMessageIdSize(TryFromSliceError),
111    #[error("Error in libsodium's genric_hash function. Return value: {0}")]
112    LibSodiumGenericHashError(i32),
113    #[error("RpcDhtBuilderError: {0}")]
114    RpcDhtBuilderError(#[from] RpcInnerBuilderError),
115    #[error("RecvError: {0}")]
116    RecvError(#[from] RecvError),
117    #[error("AddrParseError: {0}")]
118    AddrParseError(#[from] AddrParseError),
119    #[error("Requests must have a 'to' field")]
120    RequestRequiresToField,
121    #[error("Ipv6 not supported")]
122    Ipv6NotSupported,
123    #[error("Error trying to send message to IoHandler")]
124    RequestChannelSendError(),
125    #[error("Error building request. Missing field: {0}")]
126    RequestBuilderError(String),
127    #[error("Request timed out after {0:?}")]
128    Timeout(Duration),
129}
130
131pub type Result<T> = std::result::Result<T, Error>;
132
133/// TODO make EncodingError impl Error trait
134impl From<EncodingError> for Error {
135    fn from(value: EncodingError) -> Self {
136        Error::CompactEncodingError(value)
137    }
138}
139
140/// TODO in js this is de/encoded with c.uint which is for a variable sized unsigned integer.
141// but it is always one byte. We use a u8 instead of a usize here. So there is a limit on 256
142// commands.
143#[derive(Copy, Debug, Clone, PartialEq)]
144#[repr(u8)]
145pub enum InternalCommand {
146    Ping = 0,
147    PingNat,
148    FindNode,
149    DownHint,
150}
151
152/// Query Commands
153pub mod commands {
154    use crate::Command;
155    /// Ping
156    pub const PING: Command = Command::Internal(crate::InternalCommand::Ping);
157    /// Ping NAT
158    pub const PING_NAT: Command = Command::Internal(crate::InternalCommand::PingNat);
159    /// Find node
160    pub const FIND_NODE: Command = Command::Internal(crate::InternalCommand::FindNode);
161    /// Down hint
162    pub const DOWN_HINT: Command = Command::Internal(crate::InternalCommand::DownHint);
163}
164
165impl Display for InternalCommand {
166    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167        use InternalCommand as Ic;
168        write!(f, "COMMAND")?;
169        match self {
170            Ic::Ping => write!(f, "::Ping"),
171            Ic::PingNat => write!(f, "::PingNat"),
172            Ic::FindNode => write!(f, "::FindNode"),
173            Ic::DownHint => write!(f, "::DownHint"),
174        }
175    }
176}
177
178impl From<InternalCommand> for Command {
179    fn from(value: InternalCommand) -> Self {
180        Command::Internal(value)
181    }
182}
183
184#[derive(Copy, Debug, Clone, PartialEq)]
185pub struct ExternalCommand(pub usize);
186
187impl From<ExternalCommand> for Command {
188    fn from(value: ExternalCommand) -> Self {
189        Command::External(value)
190    }
191}
192
193/// TODO This is encoded as u8 which might not always be true
194#[derive(Copy, Debug, Clone, PartialEq)]
195pub enum Command {
196    Internal(InternalCommand),
197    External(ExternalCommand),
198}
199
200impl Display for Command {
201    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
202        match self {
203            Command::Internal(c) => write!(f, "Internal({})", c),
204            Command::External(ExternalCommand(x)) => {
205                // NB: magic numbers & strings here: the names and number values for external command are defined in the hyperdht
206                // crate, which depends on this crate.The numbers & names are just copied here to
207                // avoid doing something more complicated to get a nice Dislpay impl.
208                // Alternatively we could do:
209                // struct ExternalCommand(struct ExternalCommandKind( { number: usize, name:
210                // 'static &str })
211                // Display would do:
212                // write(f, "External({})", ext_command_kind.name)
213                let cmd_name = match x {
214                    0 => "PEER_HANDSHAKE",
215                    1 => "PEER_HOLEPUNCH",
216                    2 => "FIND_PEER",
217                    3 => "LOOKUP",
218                    4 => "ANNOUNCE",
219                    5 => "UNANNOUNCE",
220                    mystery => &format!("??{mystery}??"),
221                };
222                write!(f, "External({cmd_name})")
223            }
224        }
225    }
226}
227
228impl Command {
229    fn encode(&self) -> u8 {
230        match &self {
231            Command::Internal(cmd) => *cmd as u8,
232            Command::External(ExternalCommand(cmd)) => *cmd as u8,
233        }
234    }
235}
236
237impl TryFrom<u8> for InternalCommand {
238    type Error = crate::Error;
239
240    fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
241        use InternalCommand as Ic;
242        Ok(match value {
243            0 => Ic::Ping,
244            1 => Ic::PingNat,
245            2 => Ic::FindNode,
246            3 => Ic::DownHint,
247            x => return Err(crate::Error::InvalidRpcCommand(x)),
248        })
249    }
250}
251
252fn thirty_two_random_bytes() -> [u8; 32] {
253    let mut buff = [0; 32];
254    let mut rng = StdRng::from_rng(OsRng).unwrap();
255    rng.fill_bytes(&mut buff);
256    buff
257}
258
259pub(crate) type QueryAndTid = (Option<QueryId>, Tid);
260
261#[derive(Debug, derive_builder::Builder)]
262#[builder(pattern = "owned")]
263pub struct RpcInner {
264    // TODO use message passing to update id's in IoHandler
265    #[builder(default = "State::new(IdBytes::from(thirty_two_random_bytes()))")]
266    pub id: State<IdBytes>,
267    pub(crate) kbuckets: KBucketsTable<Node>,
268    pub io: IoHandler,
269    bootstrap_job: PeriodicJob,
270    ping_job: PeriodicJob,
271    /// The currently active (i.e. in-progress) queries.
272    queries: QueryPool,
273    /// Custom commands
274    // TODO remove me
275    #[expect(unused)]
276    commands: HashSet<usize>,
277    /// Queued events to return when being polled.
278    queued_events: VecDeque<RpcEvent>,
279    #[builder(field(ty = "Vec<SocketAddr>"))]
280    bootstrap_nodes: Vec<SocketAddr>,
281    bootstrapped: bool,
282    down_hints_in_progress: Vec<(u16, IdBytes, Instant)>,
283    pending_requests: BTreeMap<Tid, Sender<Arc<InResponse>>>,
284    stream_waker: Option<Waker>,
285    pending_queries: BTreeMap<QueryId, Sender<Arc<QueryResult>>>,
286    pending_bootstrap: Option<Sender<Arc<Bootstrapped>>>,
287    pending_query_streams: BTreeMap<QueryId, mpsc::Sender<Arc<InResponse>>>,
288}
289
290#[derive(Clone)]
291pub struct Rpc {
292    inner: Arc<Mutex<RpcInner>>,
293}
294
295impl Rpc {
296    pub fn name(&self) -> String {
297        self.inner.lock().unwrap().io.name().to_string()
298    }
299
300    pub async fn with_config(config: DhtConfig) -> Result<Self> {
301        Ok(Self {
302            inner: Arc::new(Mutex::new(RpcInner::with_config(config).await?)),
303        })
304    }
305
306    pub fn is_ephemeral(&self) -> bool {
307        self.inner.lock().unwrap().is_ephemeral()
308    }
309    /// Returns the local address that this listener is bound to.
310    pub fn local_addr(&self) -> Result<SocketAddr> {
311        self.inner.lock().unwrap().local_addr()
312    }
313    pub fn socket(&self) -> udx::UdxSocket {
314        self.inner.lock().unwrap().socket()
315    }
316    pub fn is_bootstrapped(&self) -> bool {
317        self.inner.lock().unwrap().is_bootstrapped()
318    }
319
320    pub fn new_tid(&self) -> Tid {
321        self.inner.lock().unwrap().new_tid()
322    }
323    /// Returns the id used to identify this node.
324    pub fn id(&self) -> IdBytes {
325        self.inner.lock().unwrap().id()
326    }
327    pub fn reply_command(&self, resp: CommandQueryResponse) {
328        self.inner.lock().unwrap().reply_command(resp)
329    }
330
331    pub fn closer_nodes(&self, key: IdBytes) -> Vec<Peer> {
332        self.inner.lock().unwrap().closer_nodes(key, K_VALUE.into())
333    }
334
335    // TODO Error on timeout
336    pub fn bootstrap(&self) -> BootstrapFuture {
337        let (tx, rx) = oneshot::channel();
338        {
339            let mut inner = self.inner.lock().unwrap();
340            inner.bootstrap();
341            _ = inner.pending_bootstrap.insert(tx);
342        }
343        BootstrapFuture {
344            inner: self.inner.clone(),
345            rx,
346        }
347    }
348
349    pub fn request(
350        &self,
351        command: Command,
352        target: Option<IdBytes>,
353        value: Option<Vec<u8>>,
354        destination: Peer,
355        token: Option<[u8; 32]>,
356    ) -> RpcDhtRequestFuture {
357        let (tx, rx) = oneshot::channel();
358
359        let tid = {
360            let mut inner = self.inner.lock().unwrap();
361            let mut o = OutRequestBuilder::new(destination, command);
362            if let Some(target) = target {
363                o = o.target(target);
364            }
365            if let Some(value) = value {
366                o = o.value(value);
367            }
368            if let Some(token) = token {
369                o = o.token(token);
370            }
371
372            let tid = inner.request(o);
373            inner.store_tid_sender(tid, tx);
374            tid
375        };
376
377        // Create a future that polls RpcDht for events and waits for the response
378        RpcDhtRequestFuture::new(self.inner.clone(), tid, rx)
379    }
380    pub fn request_from_builder(&self, o: OutRequestBuilder) -> RpcDhtRequestFuture {
381        let (tx, rx) = oneshot::channel();
382
383        let tid = {
384            let mut inner = self.inner.lock().unwrap();
385            let tid = inner.request(o);
386            inner.store_tid_sender(tid, tx);
387            tid
388        };
389        // Create a future that polls RpcDht for events and waits for the response
390        RpcDhtRequestFuture::new(self.inner.clone(), tid, rx)
391    }
392    pub fn request2(
393        &self,
394        o: OutRequestBuilder,
395    ) -> crate::Result<tokio::sync::oneshot::Receiver<()>> {
396        self.inner.lock().unwrap().io.request2(o)
397    }
398    pub fn respond(
399        &self,
400        request: &RequestMsgData,
401        value: Option<Vec<u8>>,
402        closer_nodes: Option<Vec<Peer>>,
403        peer: &Peer,
404    ) -> crate::Result<tokio::sync::oneshot::Receiver<()>> {
405        self.inner
406            .lock()
407            .unwrap()
408            .io
409            .response(request, value, closer_nodes, peer)
410    }
411
412    pub async fn ping(&self, peer: Peer) -> Result<Arc<InResponse>> {
413        self.request(
414            Command::Internal(InternalCommand::Ping),
415            None,
416            None,
417            peer,
418            None,
419        )
420        .await
421    }
422
423    pub fn query(&self, args: QueryArgs) -> QueryNext {
424        const QUERY_STREAM_CHANNEL_SIZE: usize = 1024;
425        let (parts_tx, parts_rx) = mpsc::channel(QUERY_STREAM_CHANNEL_SIZE);
426        let (result_tx, result_rx) = oneshot::channel();
427
428        {
429            let mut inner = self.inner.lock().unwrap();
430            let qid = inner.query(args);
431            inner.store_qid_stream_sender(qid, parts_tx);
432            inner.store_qid_sender(qid, result_tx);
433        };
434
435        QueryNext {
436            inner: self.inner.clone(),
437            parts_rx,
438            result_rx,
439        }
440    }
441}
442
443impl Stream for Rpc {
444    type Item = RpcEvent;
445
446    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
447        let mut inner = self.inner.lock().unwrap();
448        Stream::poll_next(Pin::new(&mut *inner), cx)
449    }
450}
451
452#[derive(Debug)]
453pub struct QueryArgs {
454    command: Command,
455    target: IdBytes,
456    value: Option<Vec<u8>>,
457    commit: Option<Commit>,
458    closest_nodes: Option<Vec<Peer>>,
459}
460
461impl QueryArgs {
462    pub fn new(command: Command, target: IdBytes) -> Self {
463        Self {
464            command,
465            target,
466            value: None,
467            commit: None,
468            closest_nodes: None,
469        }
470    }
471    pub fn value(mut self, value: Vec<u8>) -> Self {
472        self.value = Some(value);
473        self
474    }
475    pub fn commit(mut self, value: Commit) -> Self {
476        self.commit = Some(value);
477        self
478    }
479    pub fn closest_nodes(mut self, value: Vec<Peer>) -> Self {
480        self.closest_nodes = Some(value);
481        self
482    }
483}
484
485#[derive(Debug)]
486pub struct QueryNext {
487    inner: Arc<Mutex<RpcInner>>,
488    parts_rx: mpsc::Receiver<Arc<InResponse>>,
489    result_rx: Receiver<Arc<QueryResult>>,
490}
491
492impl Stream for QueryNext {
493    type Item = Arc<InResponse>;
494
495    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
496        {
497            let mut inner = self.inner.lock().unwrap();
498            let _ = Stream::poll_next(Pin::new(&mut *inner), cx);
499        }
500        Pin::new(&mut self.parts_rx).poll_next(cx)
501    }
502}
503impl Future for QueryNext {
504    type Output = Result<Arc<QueryResult>>;
505
506    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
507        {
508            let mut inner = self.inner.lock().unwrap();
509            let _ = Stream::poll_next(Pin::new(&mut *inner), cx);
510        }
511        Pin::new(&mut self.result_rx)
512            .poll(cx)
513            .map_err(Error::RecvError)
514    }
515}
516
517macro_rules! future_poller {
518    ($self:expr, $cx:expr) => {{
519        // First, try to poll the response future
520        {
521            let mut inner = $self.inner.lock().unwrap();
522            let _ = Stream::poll_next(Pin::new(&mut *inner), $cx);
523        }
524        Pin::new(&mut $self.rx).poll($cx).map_err(Error::RecvError)
525    }};
526}
527
528pub struct BootstrapFuture {
529    inner: Arc<Mutex<RpcInner>>,
530    rx: Receiver<Arc<Bootstrapped>>,
531}
532
533impl Future for BootstrapFuture {
534    type Output = Result<Arc<Bootstrapped>>;
535
536    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
537        future_poller!(self, cx)
538    }
539}
540
541/// A future that polls RpcDht for events while waiting for a specific response.
542#[derive(Debug)]
543pub struct RpcDhtRequestFuture {
544    inner: Arc<Mutex<RpcInner>>,
545    tid: Tid,
546    rx: Receiver<Arc<InResponse>>,
547    started_at: Instant,
548    timeout: Duration,
549}
550
551impl Future for RpcDhtRequestFuture {
552    type Output = Result<Arc<InResponse>>;
553
554    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
555        {
556            let mut inner = self.inner.lock().unwrap();
557            let _ = Stream::poll_next(Pin::new(&mut *inner), cx);
558        }
559
560        match Pin::new(&mut self.rx).poll(cx) {
561            Poll::Ready(Ok(response)) => {
562                cx.waker().wake_by_ref();
563                Poll::Ready(Ok(response))
564            }
565            Poll::Ready(Err(e)) => Poll::Ready(Err(Error::RecvError(e))),
566            Poll::Pending => {
567                if Instant::now().duration_since(self.started_at) > self.timeout {
568                    error!(tid = self.tid, "request timed out");
569                    Poll::Ready(Err(Error::Timeout(self.timeout)))
570                } else {
571                    // TODO basically a busy loop. Figure out how to wake at the right time when
572                    // timeout expiers, then remove this.
573                    cx.waker().wake_by_ref();
574                    Poll::Pending
575                }
576            }
577        }
578    }
579}
580
581impl RpcDhtRequestFuture {
582    pub fn new(inner: Arc<Mutex<RpcInner>>, tid: Tid, rx: Receiver<Arc<InResponse>>) -> Self {
583        Self {
584            inner,
585            tid,
586            rx,
587            started_at: Instant::now(),
588            timeout: DEFAULT_REQUEST_TIMEOUT,
589        }
590    }
591    pub fn tid(&self) -> Tid {
592        self.tid
593    }
594}
595
596#[derive(Debug)]
597pub struct DhtConfig {
598    pub kbucket_pending_timeout: Duration,
599    pub local_id: Option<[u8; 32]>,
600    pub commands: HashSet<usize>,
601    pub query_config: QueryConfig,
602    pub io_config: IoConfig,
603    pub bootstrap_interval: Duration,
604    pub ping_interval: Duration,
605    pub connection_idle_timeout: Duration,
606    pub adaptive: bool,
607    pub bootstrap_nodes: Vec<SocketAddr>,
608    pub socket: Option<MessageDataStream>,
609}
610
611impl Default for DhtConfig {
612    fn default() -> Self {
613        DhtConfig {
614            kbucket_pending_timeout: Duration::from_secs(60),
615            local_id: None,
616            commands: Default::default(),
617            query_config: Default::default(),
618            ping_interval: Duration::from_secs(40),
619            bootstrap_interval: Duration::from_secs(320),
620            connection_idle_timeout: Duration::from_secs(10),
621            adaptive: false,
622            bootstrap_nodes: Vec::new(),
623            socket: None,
624            io_config: Default::default(),
625        }
626    }
627}
628
629impl DhtConfig {
630    /// Create a new UDP socket and attempt to bind it to the addr provided.
631    pub fn bind<A: ToSocketAddrs>(mut self, addr: A) -> crate::Result<Self> {
632        self.socket = Some(MessageDataStream::bind(addr)?);
633        Ok(self)
634    }
635    pub fn add_bootstrap_node<A: Into<SocketAddr>>(mut self, addr: A) -> Self {
636        self.bootstrap_nodes.push(addr.into());
637        self
638    }
639    pub fn empty_bootstrap_nodes(mut self) -> Self {
640        self.bootstrap_nodes = vec![];
641        self
642    }
643    /// Set the nodes to bootstrap from
644    pub fn set_bootstrap_nodes<T: ToSocketAddrs>(mut self, addresses: &[T]) -> Self {
645        let mut bootstrap_nodes = vec![];
646
647        for addrs in addresses {
648            if let Ok(addrs) = addrs.to_socket_addrs() {
649                for addr in addrs {
650                    bootstrap_nodes.push(addr)
651                }
652            }
653        }
654        self.bootstrap_nodes = bootstrap_nodes;
655        self
656    }
657
658    /// Register all commands to listen to.
659    pub fn register_commands(mut self, cmds: &[usize]) -> Self {
660        for cmd in cmds {
661            self.commands.insert(*cmd);
662        }
663        self
664    }
665
666    /// Set `ephemeral` value. When `true` this node won't expose its `id` to remote peer, so other peers do not add us to the peer list.
667    pub fn set_ephemeral(mut self, ephemeral: bool) -> Self {
668        self.io_config.ephemeral = ephemeral;
669        self
670    }
671}
672
673impl RpcInner {
674    fn store_tid_sender(&mut self, tid: Tid, tx: Sender<Arc<InResponse>>) {
675        self.pending_requests.insert(tid, tx);
676    }
677    fn store_qid_sender(&mut self, qid: QueryId, tx: Sender<Arc<QueryResult>>) {
678        self.pending_queries.insert(qid, tx);
679    }
680    fn store_qid_stream_sender(&mut self, qid: QueryId, tx: mpsc::Sender<Arc<InResponse>>) {
681        self.pending_query_streams.insert(qid, tx);
682    }
683
684    fn poll_next_inner(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<RpcEvent>> {
685        let pin = self.get_mut();
686        let now = Instant::now();
687        _ = pin.stream_waker.insert(cx.waker().clone());
688
689        if let Poll::Ready(()) = pin.bootstrap_job.poll(cx, now)
690            && pin.kbuckets.iter().count() < 20
691        {
692            debug!("next bootstrap_job running");
693            pin.bootstrap();
694        }
695
696        if let Poll::Ready(()) = pin.ping_job.poll(cx, now) {
697            pin.ping_some();
698        }
699        loop {
700            // Drain queued events first.
701            if let Some(event) = pin.queued_events.pop_front() {
702                cx.waker().wake_by_ref();
703                return Poll::Ready(Some(event));
704            }
705
706            // Look for a sent/received message
707            loop {
708                if let Poll::Ready(Some(event)) = Stream::poll_next(Pin::new(&mut pin.io), cx) {
709                    if let Ok(Some(e)) = pin.inject_event(event) {
710                        cx.waker().wake_by_ref();
711                        return Poll::Ready(Some(e));
712                    }
713                    if let Some(event) = pin.queued_events.pop_front() {
714                        return Poll::Ready(Some(event));
715                    }
716                } else {
717                    match pin.queries.poll(now, cx.waker().clone()) {
718                        QueryPoolEvent::Commit((query, cev)) => {
719                            use commit::{Commit as C, CommitEvent as E, Progress as P};
720                            // TODO add all commit handlers
721                            match cev {
722                                E::AutoStart((_, _)) => {
723                                    let tids = pin.default_commit(&query);
724                                    query.write().unwrap().commit =
725                                        C::Auto(P::AwaitingReplies(BTreeSet::from_iter(tids)))
726                                }
727                                E::CustomStart((tx_commit_messages, _)) => {
728                                    return Poll::Ready(Some(RpcEvent::ReadyToCommit {
729                                        query,
730                                        tx_commit_messages,
731                                    }));
732                                }
733                                E::SendRequests((commits, _)) => {
734                                    for msg in commits {
735                                        match msg {
736                                            CommitMessage::Send(cr) => {
737                                                let (_, tid) = pin.io.request(
738                                                    cr.command,
739                                                    cr.target,
740                                                    cr.value,
741                                                    cr.peer.into(),
742                                                    Some(cr.query_id),
743                                                    Some(cr.token),
744                                                );
745                                                if let C::Custom(prog @ P::Sending(_)) =
746                                                    &mut query.write().unwrap().commit
747                                                {
748                                                    prog.sent_tid(tid);
749                                                }
750                                            }
751                                            CommitMessage::Done => {
752                                                match &mut query.write().unwrap().commit {
753                                                    C::Custom(prog @ P::Sending(_)) => {
754                                                        // Done should only be emitted last. Any
755                                                        // further rquests sent with `Send` are
756                                                        // dropped
757                                                        prog.transition_to_awaiting();
758                                                        if prog.all_replies_recieved() {
759                                                            // if we'd already recieved all replies,
760                                                            // we're done
761                                                            *prog = Progress::Done;
762                                                        }
763                                                    }
764                                                    _ => {
765                                                        // We expect that only `Custom` sends
766                                                        // SendRequests. and only sends Done while
767                                                        // in `Sending`
768                                                        todo!()
769                                                    }
770                                                }
771                                            }
772                                        }
773                                    }
774                                }
775                                E::Done => {
776                                    todo!("Commit Done!")
777                                }
778                            }
779                        }
780                        QueryPoolEvent::Waiting(Some((query, event))) => {
781                            let id = query.read().unwrap().id();
782                            pin.inject_query_event(id, event);
783                        }
784                        QueryPoolEvent::Finished(q) => {
785                            trace!(
786                                "QueryPoolEvent::Finished. Query::id = {:?}",
787                                q.try_read().map(|x| x.id)
788                            );
789                            let event = pin.query_finished(&q);
790                            return Poll::Ready(Some(event));
791                        }
792                        QueryPoolEvent::Timeout(q) => {
793                            let event = pin.query_timeout(&q);
794                            trace!("{event:#?}");
795                            return Poll::Ready(Some(event));
796                        }
797                        QueryPoolEvent::Waiting(None) | QueryPoolEvent::Idle => {
798                            break;
799                        }
800                    }
801                }
802            }
803
804            // No immediate event was produced as a result of a finished query or socket.
805            // If no new events have been queued either, signal `Pending` to
806            // be polled again later.
807            if pin.queued_events.is_empty() {
808                return Poll::Pending;
809            }
810        }
811    }
812
813    fn enque_stream_event(&mut self, event: RpcEvent) {
814        self.queued_events.push_back(event);
815        if let Some(w) = self.stream_waker.take() {
816            w.wake()
817        }
818    }
819    pub async fn with_config(config: DhtConfig) -> crate::Result<Self> {
820        let bites = config.local_id.unwrap_or_else(thirty_two_random_bytes);
821        let id_bytes = IdBytes::from(bites);
822        let local_id = id_bytes;
823        let id = State::new(local_id);
824
825        let socket = config
826            .socket
827            .map(Result::Ok)
828            .unwrap_or_else(MessageDataStream::defualt_bind)?;
829
830        let io = IoHandler::new(id.view(), socket, config.io_config);
831
832        let mut dht = Self {
833            id,
834            kbuckets: KBucketsTable::new(local_id, config.kbucket_pending_timeout),
835            io,
836            bootstrap_job: PeriodicJob::new(config.bootstrap_interval),
837            ping_job: PeriodicJob::new(config.ping_interval),
838            queries: QueryPool::new(local_id, config.query_config),
839            commands: config.commands,
840            queued_events: Default::default(),
841            bootstrap_nodes: config.bootstrap_nodes,
842            bootstrapped: false,
843            down_hints_in_progress: Vec::new(),
844            pending_requests: Default::default(),
845            stream_waker: Default::default(),
846            pending_queries: Default::default(),
847            pending_bootstrap: Default::default(),
848            pending_query_streams: Default::default(),
849        };
850
851        dht.bootstrap();
852        Ok(dht)
853    }
854
855    pub fn is_ephemeral(&self) -> bool {
856        self.io.is_ephemeral()
857    }
858
859    /// Returns the local address that this listener is bound to.
860    pub fn local_addr(&self) -> crate::Result<SocketAddr> {
861        self.io.local_addr()
862    }
863    pub fn socket(&self) -> udx::UdxSocket {
864        self.io.socket()
865    }
866    pub fn bootstrap(&mut self) {
867        if !self.bootstrap_nodes.is_empty() {
868            let target = self.id.get();
869            let peers = self
870                .kbuckets
871                .closest(&target)
872                .take(usize::from(K_VALUE))
873                .map(|e| PeerId::new(e.node.value.addr, e.node.key))
874                .collect::<Vec<_>>();
875            let bootstrap_nodes: Vec<Peer> = self.bootstrap_nodes.iter().map(Peer::from).collect();
876            self.queries.bootstrap(target, peers, bootstrap_nodes);
877        } else if !self.bootstrapped {
878            let e = Arc::new(Bootstrapped {
879                stats: QueryStats::empty(),
880            });
881            if let Some(tx) = self.pending_bootstrap.take() {
882                _ = tx.send(e.clone());
883            }
884
885            self.enque_stream_event(RpcEvent::Bootstrapped(e));
886            self.bootstrapped = true;
887        }
888    }
889
890    pub fn is_bootstrapped(&self) -> bool {
891        self.bootstrapped
892    }
893
894    #[instrument(skip(self, args))]
895    pub fn query(&mut self, args: QueryArgs) -> QueryId {
896        // Use routing table peers for QueryTable (commit tracking)
897        let peers = self
898            .kbuckets
899            .closest(&args.target)
900            .take(usize::from(K_VALUE))
901            .map(|e| PeerId::new(e.node.value.addr, e.node.key))
902            .collect::<Vec<_>>();
903
904        // Use closest_nodes if provided, otherwise fall back to bootstrap_nodes
905        let bootstrap: Vec<Peer> = args
906            .closest_nodes
907            .unwrap_or_else(|| self.bootstrap_nodes.iter().map(Peer::from).collect());
908
909        let commit = args.commit.unwrap_or(Commit::No);
910
911        self.queries.add_stream(
912            args.command,
913            peers,
914            args.target,
915            args.value,
916            bootstrap,
917            commit,
918        )
919    }
920
921    pub fn request(&mut self, req: OutRequestBuilder) -> Tid {
922        self.io.request_from_builder(req).1
923    }
924
925    pub fn ping(&mut self, peer: &Peer) -> QueryAndTid {
926        self.io.request(
927            Command::Internal(InternalCommand::Ping),
928            None,
929            None,
930            peer.clone(),
931            None,
932            None,
933        )
934    }
935
936    fn ping_some(&mut self) -> Vec<QueryAndTid> {
937        let cnt = if self.queries.len() > 2 { 3 } else { 5 };
938        let now = Instant::now();
939        let mut out = vec![];
940        let ping_interval = self.ping_job.interval;
941        for peer in self
942            .kbuckets
943            .iter()
944            .filter_map(|entry| {
945                if now > entry.node.value.last_seen + ping_interval {
946                    Some(Peer::from(entry.node.value.addr))
947                } else {
948                    None
949                }
950            })
951            .take(cnt)
952            .collect::<Vec<_>>()
953        {
954            out.push(self.ping(&peer));
955        }
956        out
957    }
958
959    /// Handle the event generated from the underlying IO
960    fn inject_event(&mut self, event: IoHandlerEvent) -> Result<Option<RpcEvent>> {
961        match event {
962            IoHandlerEvent::OutResponse { .. } => {}
963            IoHandlerEvent::OutSocketErr { .. } => {}
964            IoHandlerEvent::InRequest { message, peer } => {
965                return self.on_request(message, peer);
966            }
967            IoHandlerEvent::InMessageErr { .. } => {}
968            IoHandlerEvent::InSocketErr { .. } => {}
969            IoHandlerEvent::InResponseBadRequestId { message, peer } => {
970                warn!(msg =? message, peer =? peer, "Bad Response ID");
971                // received a response that did not match any issued requests
972                //self.remove_node(&peer);
973                todo!()
974            }
975            IoHandlerEvent::OutRequest { .. } => {
976                // sent a request
977            }
978            IoHandlerEvent::InResponse(resp) => {
979                self.on_response(resp);
980            }
981            IoHandlerEvent::RequestTimeout { .. } => {
982                todo!()
983            }
984            IoHandlerEvent::ChanneledResponse(tid) => {
985                trace!(tid = tid, "Passed io response through channel")
986            }
987        }
988        Ok(None)
989    }
990
991    /// Process a response.
992    #[instrument(skip_all)]
993    fn on_response(&mut self, resp_data: Arc<InResponse>) {
994        if let Some(tx) = self.pending_requests.remove(&resp_data.request.tid) {
995            let _ = tx
996                .send(resp_data.clone())
997                .inspect_err(|e| error!("Failed to send result to pending request: {e:?}"));
998        }
999        if let Some(id) = validate_id(&resp_data.response.id, &resp_data.peer) {
1000            self.add_node(
1001                id,
1002                resp_data.peer.clone(),
1003                None,
1004                Some(SocketAddr::from(&resp_data.response.to)),
1005            );
1006        }
1007        match resp_data.query_id {
1008            Some(query_id) => {
1009                if let Some(query) = self.queries.get(&query_id) {
1010                    if let Some(resp) = query.write().unwrap().inject_response(resp_data) {
1011                        // TODO remove ResponoseResult here and relpace downstream with
1012                        // QueryResponse
1013                        self.enque_stream_event(RpcEvent::ResponseResult(Ok(
1014                            ResponseOk::Response(resp.clone()),
1015                        )));
1016                        self.enque_stream_event(RpcEvent::QueryResponse(resp.clone()));
1017                        if let Some(tx) = self.pending_query_streams.get(&query_id) {
1018                            let _ = tx.clone().try_send(resp.clone()).inspect_err(|e| {
1019                                error!("Failed to send response to query stream: {e:?}")
1020                            });
1021                        }
1022                    }
1023                } else {
1024                    debug!(
1025                        "Recieved response for missing query with id: {:?}. It could have been removed already",
1026                        resp_data.query_id
1027                    );
1028                }
1029            }
1030            None => match resp_data.request.command {
1031                Command::Internal(InternalCommand::Ping) => {
1032                    self.on_pong(&resp_data.response, resp_data.peer.clone());
1033                }
1034                Command::External(_) => {
1035                    self.enque_stream_event(RpcEvent::ResponseResult(Ok(ResponseOk::Response(
1036                        resp_data,
1037                    ))));
1038                }
1039                Command::Internal(_) => {
1040                    todo!("I think this happens whene there is request that should be a query")
1041                }
1042            },
1043        }
1044    }
1045
1046    /// Handle an incoming request.
1047    ///
1048    /// Eventually send a response.
1049    fn on_request(&mut self, request: RequestMsgData, peer: Peer) -> Result<Option<RpcEvent>> {
1050        if let Some(id) = validate_id(&request.id, &peer) {
1051            self.add_node(id, peer.clone(), None, Some(SocketAddr::from(&request.to)));
1052        }
1053
1054        match request.command {
1055            Command::Internal(cmd) => match cmd {
1056                InternalCommand::Ping => self.on_ping(&request, &peer),
1057                InternalCommand::FindNode => self.on_find_node(&request, &peer),
1058                InternalCommand::PingNat => self.on_ping_nat(&request, peer),
1059                InternalCommand::DownHint => self.on_down_hint(&request, peer),
1060            },
1061            Command::External(command) => {
1062                return Ok(Some(RpcEvent::CustomRequest(CustomCommandRequest {
1063                    request: Box::new(request),
1064                    peer,
1065                    command,
1066                })));
1067            }
1068        }
1069        Ok(None)
1070    }
1071
1072    fn add_node(
1073        &mut self,
1074        id: IdBytes,
1075        peer: Peer,
1076        roundtrip_token: Option<Vec<u8>>,
1077        to: Option<SocketAddr>,
1078    ) {
1079        match self.kbuckets.entry(&id) {
1080            Entry::Present(mut entry, _) => {
1081                entry.value().last_seen = Instant::now();
1082            }
1083            Entry::Pending(mut entry, _) => {
1084                let n = entry.value();
1085                n.addr = peer.addr;
1086                n.last_seen = Instant::now();
1087            }
1088            Entry::Absent(entry) => {
1089                let node = Node {
1090                    addr: peer.addr,
1091                    roundtrip_token,
1092                    to,
1093                    last_seen: Instant::now(),
1094                    referrers: vec![],
1095                    down_hint: false,
1096                    last_pinged: None,
1097                };
1098
1099                use InsertResult as Ir;
1100                match entry.insert(node, NodeStatus::Connected) {
1101                    Ir::Inserted => {
1102                        self.enque_stream_event(RpcEvent::RoutingUpdated {
1103                            peer,
1104                            old_peer: None,
1105                        });
1106                    }
1107                    Ir::Full => {
1108                        debug!("Bucket full. Peer not added to routing table: {:?}", peer)
1109                    }
1110                    Ir::Pending { disconnected: _ } => {
1111
1112                        // TODO dial remote
1113                    }
1114                }
1115            }
1116            Entry::SelfEntry => {}
1117        }
1118    }
1119    pub fn reply_command(&mut self, resp: CommandQueryResponse) {
1120        self.io.reply(resp.msg)
1121    }
1122
1123    #[expect(unused)] // TODO FIXME
1124    fn reply(
1125        &mut self,
1126        error: usize,
1127        value: Option<Vec<u8>>,
1128        token: Option<[u8; 32]>,
1129        has_closer_nodes: bool,
1130        request: &RequestMsgData,
1131        peer: &Peer,
1132    ) {
1133        let closer_nodes: Vec<Peer> = match (has_closer_nodes, request.target) {
1134            (true, Some(key)) => self.closer_nodes(IdBytes::from(key), usize::from(K_VALUE)),
1135            _ => vec![],
1136        };
1137        let msg = ReplyMsgData {
1138            tid: request.tid,
1139            to: peer.clone(),
1140            id: None,
1141            token,
1142            closer_nodes,
1143            error,
1144            value,
1145        };
1146        self.io.reply(msg)
1147    }
1148
1149    /// Handle a ping request
1150    fn on_ping(&mut self, msg: &RequestMsgData, peer: &Peer /* peer who sent ping */) {
1151        let msg = ReplyMsgData {
1152            tid: msg.tid,
1153            to: peer.clone(),
1154            id: (!self.is_ephemeral()).then(|| self.id.get().0),
1155            token: self.io.token(peer, 1).ok(),
1156            closer_nodes: vec![],
1157            error: 0,
1158            value: None,
1159        };
1160        self.io.reply(msg)
1161    }
1162
1163    /// Handle an incoming find peers request.
1164    ///
1165    /// Reply only if the remote provided a target to get the closest nodes for.
1166    fn on_find_node(&mut self, request: &RequestMsgData, peer: &Peer) {
1167        // TODO same as 582
1168        let closer_nodes: Vec<Peer> = match request.target {
1169            Some(t) => self.closer_nodes(IdBytes::from(t), usize::from(K_VALUE)),
1170            None => {
1171                // TODO emit an event about this
1172                warn!("Got FIND_NODE without a target. Msg: {request:?}");
1173                return;
1174            }
1175        };
1176        self.io.reply(ReplyMsgData {
1177            tid: request.tid,
1178            to: peer.clone(),
1179            id: (!self.is_ephemeral()).then(|| self.id.get().0),
1180            token: self.io.token(peer, 1).ok(),
1181            closer_nodes,
1182            error: 0,
1183            value: None,
1184        });
1185    }
1186
1187    /// Get the `num` closest nodes in the bucket.
1188    fn closer_nodes(&mut self, key: IdBytes, num: usize) -> Vec<Peer> {
1189        self.kbuckets
1190            .closest(&key)
1191            .take(num)
1192            .map(|p| Peer::from(&p.node.value.addr))
1193            .collect::<Vec<_>>()
1194        //PeersEncoding::encode(&nodes)
1195    }
1196    fn on_down_hint(&mut self, request: &RequestMsgData, peer: Peer) {
1197        match &request.value {
1198            None => {
1199                // TODO emit an event about this
1200                warn!("Got DOWN_HINT with no value. Msg: {request:?}");
1201            }
1202            Some(value) => {
1203                if value.len() < 6 {
1204                    // TODO emit an event about this
1205                    warn!("Got DOWN_HINT with value too small. Msg: {request:?}");
1206                    return;
1207                }
1208                if self.down_hints_in_progress.len() < 10 {
1209                    let key = IdBytes::from(generic_hash(&value[..6]));
1210                    // NB: akwardness follows.
1211                    // We have to mutate some state to track the DownHint progress. but doing this
1212                    // is split up between outside and inside the match statement
1213                    //
1214                    // this happenes bc we take a mutable borrow of `self` entering the
1215                    // match statement. but in Pending/Present we want to mutate self in order
1216                    // track state related to DownHint. In these cases we return node.addr from the
1217                    // match, and use then do our self mutation.
1218                    //
1219                    // we can't return the node from the match because it's a reference.
1220
1221                    // why a macro? we can't use a function because we can't take an immutable
1222                    // borrow of self to pass to the func
1223                    macro_rules! update_node_for_down_hint {
1224                        ($entry:tt) => {{
1225                            let node = $entry.value();
1226                            if node.pinged_within_last(Duration::from_millis(
1227                                crate::constants::TICK_INTERVAL_MS,
1228                            )) || !node.down_hint
1229                            {
1230                                node.down_hint = true;
1231                                node.ping_sent();
1232                                (node.addr, node.last_seen)
1233                            } else {
1234                                warn!(
1235                                    "Got DOWN_HINT for node already DOWN_HINT'd. Msg: {request:?}"
1236                                );
1237                                return;
1238                            }
1239                        }};
1240                    }
1241
1242                    let (node_addr, last_seen) = match self.kbuckets.entry(&key) {
1243                        Entry::Pending(mut entry, _) => {
1244                            update_node_for_down_hint!(entry)
1245                        }
1246                        Entry::Present(mut entry, _) => {
1247                            update_node_for_down_hint!(entry)
1248                        }
1249                        _ => {
1250                            warn!("Got DOWN_HINT for node we don't have. Msg: {request:?}");
1251                            return;
1252                        }
1253                    };
1254                    // update self for down hint
1255                    let (_, tid) = self.ping(&Peer::from(node_addr));
1256                    self.down_hints_in_progress.push((tid, key, last_seen));
1257                }
1258                self.io.reply(ReplyMsgData {
1259                    tid: request.tid,
1260                    token: self.io.token(&peer, 1).ok(),
1261                    to: peer,
1262                    id: (!self.is_ephemeral()).then(|| self.id.get().0),
1263                    closer_nodes: vec![],
1264                    error: 0,
1265                    value: None,
1266                })
1267            }
1268        };
1269    }
1270
1271    fn on_ping_nat(&mut self, request: &RequestMsgData, mut peer: Peer) {
1272        let port = match &request.value {
1273            Some(port_buf) => {
1274                if port_buf.len() < 2 {
1275                    // TODO emit an event about this
1276                    warn!("Got PING_NAT with value too small. Msg: {request:?}");
1277                    return;
1278                }
1279                let port = u16::from_le_bytes([port_buf[0], port_buf[1]]);
1280                if port == 0 {
1281                    warn!("Got PING_NAT with port == 0. Msg: {request:?}");
1282                    return;
1283                }
1284                port
1285            }
1286            None => {
1287                // TODO emit an event about this
1288                warn!("Got PING_NAT without a value. Msg: {request:?}");
1289                return;
1290            }
1291        };
1292        peer.addr.set_port(port);
1293        let token = self.io.token(&peer, 1).ok();
1294        self.io.reply(ReplyMsgData {
1295            tid: request.tid,
1296            to: peer,
1297            id: (!self.is_ephemeral()).then(|| self.id.get().0),
1298            token,
1299            closer_nodes: vec![],
1300            error: 0,
1301            value: None,
1302        });
1303    }
1304    /// Handle a response for our Ping command
1305    fn on_pong(&mut self, msg: &ReplyMsgData, peer: Peer) {
1306        // check if pong was for a downhint ping
1307        if let Some(pos) = self
1308            .down_hints_in_progress
1309            .iter()
1310            .position(|&(tid, _, _)| tid == msg.tid)
1311        {
1312            let (_, key, last_seen) = self.down_hints_in_progress.remove(pos);
1313            if msg.error != 0 {
1314                self.remove_peer(&key);
1315            } else {
1316                // we received a good response from an address than was downhinted.
1317                // the node either isn't down, or it is a new node (with a new id)
1318                // if it isn't down, node.last_seen is already updated because we have
1319                // already called add_node on this message. otherwise last_seen
1320                // is the same as it was we we pinged the node
1321                self.remove_stale_peer(&key, last_seen);
1322            }
1323        }
1324
1325        self.enque_stream_event(RpcEvent::ResponseResult(Ok(ResponseOk::Pong(peer))));
1326    }
1327
1328    fn default_commit(&mut self, query: &Arc<RwLock<Query>>) -> Vec<Tid> {
1329        let q = query.read().unwrap();
1330        q.closest_replies
1331            .iter()
1332            .map(|rep| {
1333                self.io
1334                    .request(
1335                        q.cmd,
1336                        Some(q.peer_iter.target),
1337                        q.value.clone(),
1338                        rep.peer.clone(),
1339                        Some(q.id),
1340                        rep.response.token,
1341                    )
1342                    .1
1343            })
1344            .collect()
1345    }
1346
1347    /// Delegate new query event to the io handler
1348    fn inject_query_event(&mut self, id: QueryId, event: QueryEvent) {
1349        match event {
1350            QueryEvent::Query {
1351                peer,
1352                command,
1353                target,
1354                value,
1355            } => {
1356                self.io
1357                    .request(command, Some(target), value, peer, Some(id), None);
1358            }
1359            QueryEvent::RemoveNode { id } => {
1360                self.remove_peer(&id);
1361            }
1362            QueryEvent::MissingRoundtripToken { .. } => {
1363                // TODO
1364            }
1365            _ => {
1366                todo!()
1367            } /*
1368              QueryEvent::Update {
1369                  peer,
1370                  command,
1371                  target,
1372                  value,
1373                  token,
1374              } => {
1375                  self.io
1376                      .update(command, Some(target), value, peer, token, id);
1377              }
1378              */
1379        }
1380    }
1381
1382    /// Removes a peer from the routing table.
1383    ///
1384    /// Returns `None` if the peer was not in the routing table,
1385    /// not even pending insertion.
1386    fn remove_peer(&mut self, key: &IdBytes) -> Option<EntryView<Node>> {
1387        match self.kbuckets.entry(key) {
1388            Entry::Present(entry, _) => Some(entry.remove()),
1389            Entry::Pending(entry, _) => Some(entry.remove()),
1390            Entry::Absent(..) | Entry::SelfEntry => None,
1391        }
1392    }
1393    fn remove_stale_peer(&mut self, key: &IdBytes, last_seen: Instant) -> Option<EntryView<Node>> {
1394        match self.kbuckets.entry(key) {
1395            Entry::Present(mut entry, _) => {
1396                if entry.value().last_seen <= last_seen {
1397                    return Some(entry.remove());
1398                }
1399                None
1400            }
1401            Entry::Pending(mut entry, _) => {
1402                if entry.value().last_seen <= last_seen {
1403                    return Some(entry.remove());
1404                };
1405                None
1406            }
1407            Entry::Absent(..) | Entry::SelfEntry => None,
1408        }
1409    }
1410
1411    /// Handles a finished query.
1412    #[instrument(skip_all)]
1413    fn query_finished(&mut self, query: &Arc<RwLock<Query>>) -> RpcEvent {
1414        let is_find_node = matches!(
1415            query.read().unwrap().command(),
1416            Command::Internal(InternalCommand::FindNode)
1417        );
1418
1419        let result = query.read().unwrap().get_result();
1420
1421        // add nodes to the table
1422        for (peer, state) in result.peers.iter() {
1423            match state {
1424                PeerState::Failed => {
1425                    debug!("peer.id = [{:?}] Failed - removing", peer.id);
1426                    self.remove_peer(&peer.id);
1427                }
1428                PeerState::Succeeded {
1429                    roundtrip_token,
1430                    to,
1431                } => {
1432                    debug!("peer.id = [{:?}] Succeeded", peer.id);
1433                    self.add_node(
1434                        peer.id,
1435                        Peer::from(peer.addr),
1436                        Some(roundtrip_token.clone()),
1437                        *to,
1438                    );
1439                }
1440                PeerState::NotContacted => {
1441                    trace!("peer.id = [{:?}] NotContacted", peer.id);
1442                }
1443            }
1444        }
1445
1446        // first `find_node` query is issued as bootstrap
1447        if is_find_node && !self.bootstrapped {
1448            debug!("Bootstrap process's FindNode query finished");
1449            self.bootstrapped = true;
1450            let e = Arc::new(Bootstrapped {
1451                stats: result.stats,
1452            });
1453            if let Some(tx) = self.pending_bootstrap.take() {
1454                _ = tx.send(e.clone());
1455            }
1456
1457            RpcEvent::Bootstrapped(e)
1458        } else {
1459            let result = Arc::new(result);
1460            if let Some(tx) = self.pending_queries.remove(&result.query_id) {
1461                if let Some(mut stream_tx) = self.pending_query_streams.remove(&result.query_id) {
1462                    stream_tx.close_channel();
1463                }
1464                let _ = tx
1465                    .send(result.clone())
1466                    .inspect_err(|e| error!("Failed to send result of pending query: {e:?}"));
1467            }
1468
1469            debug!(
1470                cmd = tracing::field::display(result.cmd),
1471                "Query result ready"
1472            );
1473            RpcEvent::QueryResult(result)
1474        }
1475    }
1476    /// Handles a query that timed out.
1477    fn query_timeout(&mut self, query: &Arc<RwLock<Query>>) -> RpcEvent {
1478        self.query_finished(query)
1479    }
1480
1481    pub fn new_tid(&self) -> Tid {
1482        self.io.new_tid()
1483    }
1484    /// Returns the id used to identify this node.
1485    pub fn id(&self) -> IdBytes {
1486        self.io.id()
1487    }
1488}
1489
1490#[derive(Debug)]
1491pub enum RpcEvent {
1492    /// Result wrapping an incomming Request
1493    /// Only emits Ok on custom/external commands. Errs on any request error (custom or non-custom)
1494    CustomRequest(CustomCommandRequest),
1495    /// Result wrapping an incomming Response
1496    /// Emits for any valid response
1497    ResponseResult(ResponseResult),
1498    /// The routing table has been updated.
1499    RoutingUpdated {
1500        /// The ID of the peer that was added or updated.
1501        peer: Peer,
1502        /// The ID of the peer that was evicted from the routing table to make
1503        /// room for the new peer, if any.
1504        old_peer: Option<Peer>,
1505    },
1506    /// Emitted when bootstrapping is complete
1507    Bootstrapped(Arc<Bootstrapped>),
1508
1509    /// Only emitted when Query is made with Commit::Custom
1510    ReadyToCommit {
1511        /// The query we are commiting for
1512        query: Arc<RwLock<Query>>,
1513        tx_commit_messages: mpsc::Sender<CommitMessage>,
1514    },
1515    /// A completed query.
1516    ///
1517    /// No more responses are expected for this query
1518    QueryResult(Arc<QueryResult>),
1519    /// A single response for a request made for a query
1520    QueryResponse(Arc<InResponse>),
1521}
1522
1523#[derive(Debug)]
1524pub struct Bootstrapped {
1525    /// Execution statistics from the bootstrap query.
1526    pub stats: QueryStats,
1527}
1528
1529/// Custom incoming request to a registered command
1530///
1531/// # Note
1532///
1533/// Custom commands are not automatically replied to and need to be answered
1534/// manually
1535/// The query we received and need to respond to
1536#[derive(Debug)]
1537pub struct CustomCommandRequest {
1538    pub request: Box<RequestMsgData>,
1539    /// Peer that sent th erequest
1540    pub peer: Peer, // maybe peerid? or SocketAddr
1541    pub command: ExternalCommand,
1542}
1543
1544#[derive(Debug)]
1545pub enum RequestError {
1546    /// Received a query with a custom command that is not registered
1547    UnsupportedCommand {
1548        /// The unknown command
1549        command: String,
1550        /// The message we received from the peer.
1551        msg: RequestMsgData,
1552        /// The peer the message originated from.
1553        peer: Peer,
1554    },
1555    /// The `target` field of message was required but was empty
1556    MissingTarget { msg: RequestMsgData, peer: Peer },
1557    /// Received a message with an unknown type
1558    InvalidType {
1559        ty: i32,
1560        msg: RequestMsgData,
1561        peer: Peer,
1562    },
1563    /// Received a request with no command attached.
1564    MissingCommand { peer: Peer },
1565    /// Ignored Request due to message's value being this peer's id.
1566    InvalidValue { msg: RequestMsgData, peer: Peer },
1567}
1568
1569pub type ResponseResult = std::result::Result<ResponseOk, ResponseError>;
1570
1571#[derive(Debug)]
1572pub enum ResponseOk {
1573    /// Received a pong response to our ping request.
1574    Pong(Peer),
1575    /// A remote peer successfully responded to our query
1576    Response(Arc<InResponse>),
1577}
1578
1579#[derive(Debug)]
1580pub enum ResponseError {
1581    /// We received a bad pong to our ping request
1582    InvalidPong(Peer),
1583}
1584
1585impl Stream for RpcInner {
1586    type Item = RpcEvent;
1587
1588    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
1589        self.poll_next_inner(cx)
1590    }
1591}
1592
1593#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1594pub struct Peer {
1595    pub id: Option<[u8; 32]>,
1596    pub addr: SocketAddr,
1597    /// Referrer that told us about this node.
1598    pub referrer: Option<SocketAddr>,
1599}
1600
1601impl Peer {
1602    /// Encoded size of a peer: 4 bytes for a Ipv4Addr and 2 bytes for a u16.
1603    const ENCODED_SIZE: usize = 6;
1604
1605    pub fn socketv4(&self) -> Result<&SocketAddrV4> {
1606        socket_into_v4(&self.addr)
1607    }
1608    pub fn new(addr: SocketAddr) -> Self {
1609        Self {
1610            id: None,
1611            addr,
1612            referrer: None,
1613        }
1614    }
1615    pub fn with_id(mut self, id: Option<[u8; 32]>) -> Self {
1616        self.id = id;
1617        self
1618    }
1619    pub fn with_referrer(mut self, referrer: Option<SocketAddr>) -> Self {
1620        self.referrer = referrer;
1621        self
1622    }
1623}
1624
1625impl std::fmt::Debug for Peer {
1626    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1627        let mut debug_struct = f.debug_struct("Peer");
1628        if let Some(bytes) = &self.id {
1629            debug_struct.field("id", &format_args!("Some({})", pretty_bytes(bytes)));
1630        }
1631        if self.referrer.is_some() {
1632            debug_struct.field("referrer", &self.referrer);
1633        }
1634        debug_struct.field("addr", &self.addr).finish()
1635    }
1636}
1637
1638impl FromStr for Peer {
1639    type Err = crate::Error;
1640
1641    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
1642        let addr: SocketAddr = s.parse()?;
1643        Ok(Peer {
1644            addr,
1645            id: None,
1646            referrer: None,
1647        })
1648    }
1649}
1650
1651// TODO DRY
1652impl From<&SocketAddr> for Peer {
1653    fn from(value: &SocketAddr) -> Self {
1654        Peer {
1655            id: None,
1656            addr: *value,
1657            referrer: None,
1658        }
1659    }
1660}
1661impl From<&Peer> for SocketAddr {
1662    fn from(value: &Peer) -> Self {
1663        value.addr
1664    }
1665}
1666
1667impl From<SocketAddr> for Peer {
1668    fn from(value: SocketAddr) -> Self {
1669        Peer {
1670            id: None,
1671            addr: value,
1672            referrer: None,
1673        }
1674    }
1675}
1676
1677#[derive(Debug, Clone)]
1678pub struct Node {
1679    /// Address of the peer.
1680    pub addr: SocketAddr,
1681    /// last roundtrip token in a req/resp exchanged with the peer
1682    pub roundtrip_token: Option<Vec<u8>>,
1683    /// Decoded address of the `to` message field
1684    pub to: Option<SocketAddr>,
1685    /// When a new ping is due
1686    pub last_seen: Instant,
1687    /// Known referrers available for holepunching
1688    pub referrers: Vec<SocketAddr>,
1689    /// If this node recieved a down hint
1690    pub down_hint: bool,
1691    /// Last time a ping was sent to this node
1692    pub last_pinged: Option<Instant>,
1693}
1694
1695impl Node {
1696    fn pinged_within_last(&self, delta: Duration) -> bool {
1697        if let Some(x) = self.last_pinged {
1698            return Instant::now().duration_since(x) > delta;
1699        }
1700        true
1701    }
1702
1703    fn ping_sent(&mut self) {
1704        self.last_pinged = Some(Instant::now())
1705    }
1706}
1707
1708/// A 32 byte identifier for a node participating in the DHT.
1709#[derive(Clone, Hash, PartialOrd, PartialEq, Eq, Copy)]
1710pub struct IdBytes(pub [u8; ID_BYTES_LENGTH]);
1711
1712impl IdBytes {
1713    /// Create new 32 byte array with random bytes.
1714    pub fn random() -> Self {
1715        let mut key = [0u8; 32];
1716        fill_random_bytes(&mut key);
1717        Self(key)
1718    }
1719
1720    pub fn to_vec(&self) -> Vec<u8> {
1721        self.0.to_vec()
1722    }
1723    pub fn distance(&self, other: impl AsRef<[u8]>) -> Distance {
1724        distance(&self.0, other.as_ref())
1725    }
1726}
1727
1728impl std::fmt::Debug for IdBytes {
1729    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1730        write!(f, "IdBytes({})", pretty_bytes(&self.0))
1731    }
1732}
1733
1734impl Borrow<[u8]> for IdBytes {
1735    fn borrow(&self) -> &[u8] {
1736        &self.0
1737    }
1738}
1739
1740impl From<IdBytes> for [u8; ID_BYTES_LENGTH] {
1741    fn from(value: IdBytes) -> Self {
1742        value.0
1743    }
1744}
1745impl From<[u8; ID_BYTES_LENGTH]> for IdBytes {
1746    fn from(value: [u8; ID_BYTES_LENGTH]) -> Self {
1747        Self(value)
1748    }
1749}
1750
1751impl AsRef<[u8]> for IdBytes {
1752    fn as_ref(&self) -> &[u8] {
1753        &self.0
1754    }
1755}
1756
1757impl TryFrom<&[u8]> for IdBytes {
1758    type Error = std::array::TryFromSliceError;
1759
1760    fn try_from(buf: &[u8]) -> std::result::Result<Self, Self::Error> {
1761        Ok(Self(buf.try_into()?))
1762    }
1763}
1764
1765#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1766pub struct PeerId {
1767    pub addr: SocketAddr,
1768    pub id: IdBytes,
1769}
1770
1771impl PeerId {
1772    pub fn new(addr: SocketAddr, id: IdBytes) -> Self {
1773        Self { addr, id }
1774    }
1775}
1776
1777impl Borrow<[u8]> for PeerId {
1778    fn borrow(&self) -> &[u8] {
1779        self.id.borrow()
1780    }
1781}
1782
1783/// Fill the slice with random bytes
1784#[inline]
1785pub fn fill_random_bytes(dest: &mut [u8]) {
1786    use rand::{
1787        RngCore, SeedableRng,
1788        rngs::{OsRng, StdRng},
1789    };
1790    let mut rng = StdRng::from_rng(OsRng).unwrap();
1791    rng.fill_bytes(dest)
1792}
1793
1794fn socket_into_v4(addr: &SocketAddr) -> Result<&SocketAddrV4> {
1795    let SocketAddr::V4(addr) = &addr else {
1796        return Err(Error::Ipv6NotSupported);
1797    };
1798    Ok(addr)
1799}