1#![warn(
3 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
87pub const DEFAULT_BOOTSTRAP: [&str; 3] = [
89 "node1.hyperdht.org:49737",
90 "node2.hyperdht.org:49737",
91 "node3.hyperdht.org:49737",
92];
93
94pub const MUTABLE_STORE_CMD: usize = 1;
96pub const IMMUTABLE_STORE_CMD: usize = 2;
98pub 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
133impl From<EncodingError> for Error {
135 fn from(value: EncodingError) -> Self {
136 Error::CompactEncodingError(value)
137 }
138}
139
140#[derive(Copy, Debug, Clone, PartialEq)]
144#[repr(u8)]
145pub enum InternalCommand {
146 Ping = 0,
147 PingNat,
148 FindNode,
149 DownHint,
150}
151
152pub mod commands {
154 use crate::Command;
155 pub const PING: Command = Command::Internal(crate::InternalCommand::Ping);
157 pub const PING_NAT: Command = Command::Internal(crate::InternalCommand::PingNat);
159 pub const FIND_NODE: Command = Command::Internal(crate::InternalCommand::FindNode);
161 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#[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 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 #[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 queries: QueryPool,
273 #[expect(unused)]
276 commands: HashSet<usize>,
277 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 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 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 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 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 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 {
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#[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 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 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 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 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 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 if let Some(event) = pin.queued_events.pop_front() {
702 cx.waker().wake_by_ref();
703 return Poll::Ready(Some(event));
704 }
705
706 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 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 prog.transition_to_awaiting();
758 if prog.all_replies_recieved() {
759 *prog = Progress::Done;
762 }
763 }
764 _ => {
765 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 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 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 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 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 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 todo!()
974 }
975 IoHandlerEvent::OutRequest { .. } => {
976 }
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 #[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 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 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 }
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)] 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 fn on_ping(&mut self, msg: &RequestMsgData, peer: &Peer ) {
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 fn on_find_node(&mut self, request: &RequestMsgData, peer: &Peer) {
1167 let closer_nodes: Vec<Peer> = match request.target {
1169 Some(t) => self.closer_nodes(IdBytes::from(t), usize::from(K_VALUE)),
1170 None => {
1171 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 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 }
1196 fn on_down_hint(&mut self, request: &RequestMsgData, peer: Peer) {
1197 match &request.value {
1198 None => {
1199 warn!("Got DOWN_HINT with no value. Msg: {request:?}");
1201 }
1202 Some(value) => {
1203 if value.len() < 6 {
1204 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 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 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 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 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 fn on_pong(&mut self, msg: &ReplyMsgData, peer: Peer) {
1306 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 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 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 }
1365 _ => {
1366 todo!()
1367 } }
1380 }
1381
1382 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 #[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 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 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 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 pub fn id(&self) -> IdBytes {
1486 self.io.id()
1487 }
1488}
1489
1490#[derive(Debug)]
1491pub enum RpcEvent {
1492 CustomRequest(CustomCommandRequest),
1495 ResponseResult(ResponseResult),
1498 RoutingUpdated {
1500 peer: Peer,
1502 old_peer: Option<Peer>,
1505 },
1506 Bootstrapped(Arc<Bootstrapped>),
1508
1509 ReadyToCommit {
1511 query: Arc<RwLock<Query>>,
1513 tx_commit_messages: mpsc::Sender<CommitMessage>,
1514 },
1515 QueryResult(Arc<QueryResult>),
1519 QueryResponse(Arc<InResponse>),
1521}
1522
1523#[derive(Debug)]
1524pub struct Bootstrapped {
1525 pub stats: QueryStats,
1527}
1528
1529#[derive(Debug)]
1537pub struct CustomCommandRequest {
1538 pub request: Box<RequestMsgData>,
1539 pub peer: Peer, pub command: ExternalCommand,
1542}
1543
1544#[derive(Debug)]
1545pub enum RequestError {
1546 UnsupportedCommand {
1548 command: String,
1550 msg: RequestMsgData,
1552 peer: Peer,
1554 },
1555 MissingTarget { msg: RequestMsgData, peer: Peer },
1557 InvalidType {
1559 ty: i32,
1560 msg: RequestMsgData,
1561 peer: Peer,
1562 },
1563 MissingCommand { peer: Peer },
1565 InvalidValue { msg: RequestMsgData, peer: Peer },
1567}
1568
1569pub type ResponseResult = std::result::Result<ResponseOk, ResponseError>;
1570
1571#[derive(Debug)]
1572pub enum ResponseOk {
1573 Pong(Peer),
1575 Response(Arc<InResponse>),
1577}
1578
1579#[derive(Debug)]
1580pub enum ResponseError {
1581 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 pub referrer: Option<SocketAddr>,
1599}
1600
1601impl Peer {
1602 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
1651impl 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 pub addr: SocketAddr,
1681 pub roundtrip_token: Option<Vec<u8>>,
1683 pub to: Option<SocketAddr>,
1685 pub last_seen: Instant,
1687 pub referrers: Vec<SocketAddr>,
1689 pub down_hint: bool,
1691 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#[derive(Clone, Hash, PartialOrd, PartialEq, Eq, Copy)]
1710pub struct IdBytes(pub [u8; ID_BYTES_LENGTH]);
1711
1712impl IdBytes {
1713 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#[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}