1mod addr_filter;
2mod choke;
3mod client;
4mod connection;
5mod connection_monitor;
6mod constants;
7mod crypto;
8mod debug_payload;
9mod dht;
10mod event;
11mod gateway;
12mod ip;
13mod local_discovery;
14mod message;
15mod message_broker;
16mod message_dispatcher;
17mod peer_addr;
18mod peer_exchange;
19mod peer_info;
20mod peer_source;
21mod peer_state;
22mod protocol;
23mod request_tracker;
24mod runtime_id;
25mod seen_peers;
26mod server;
27mod stats;
28mod stun;
29mod stun_server_list;
30#[cfg(test)]
31mod tests;
32mod upnp;
33
34pub use self::{
35 addr_filter::AddrFilter,
36 connection::PeerInfoCollector,
37 dht::{DEFAULT_DHT_ROUTERS, DhtContactsStoreTrait, DhtLookupStream, DhtPin},
38 event::{NetworkEvent, NetworkEventReceiver, NetworkEventStream},
39 peer_addr::PeerAddr,
40 peer_info::PeerInfo,
41 peer_source::PeerSource,
42 peer_state::PeerState,
43 runtime_id::{PublicRuntimeId, SecretRuntimeId},
44 stats::Stats,
45};
46use dht::DhtEvent;
47pub use net::{
48 bus::{BusRecvStream as RecvStream, BusSendStream as SendStream, TopicId},
49 stun::NatBehavior,
50};
51
52use self::{
53 choke::Choker,
54 connection::{ConnectionPermit, ConnectionSet, ReserveResult},
55 connection_monitor::ConnectionMonitor,
56 constants::REQUEST_TIMEOUT,
57 dht::DhtDiscovery,
58 event::ProtocolVersions,
59 gateway::{Connectivity, Gateway, StackAddresses},
60 local_discovery::LocalDiscovery,
61 message_broker::MessageBroker,
62 peer_addr::PeerPort,
63 peer_exchange::{PexDiscovery, PexRepository},
64 peer_source::ConnectionDirection,
65 protocol::{MAGIC, VERSION, Version},
66 request_tracker::RequestTracker,
67 seen_peers::{SeenPeer, SeenPeers},
68 stats::{ByteCounters, StatsTracker},
69 stun::StunClients,
70};
71use crate::{
72 protocol::RepositoryId,
73 repository::{RepositoryHandle, Vault},
74};
75use backoff::{ExponentialBackoffBuilder, backoff::Backoff};
76use btdht::{self, INFO_HASH_LEN, InfoHash};
77use deadlock::BlockingMutex;
78use futures_util::future;
79use net::{
80 quic,
81 unified::{Connection, ConnectionError},
82};
83use scoped_task::ScopedAbortHandle;
84use slab::Slab;
85use state_monitor::StateMonitor;
86use std::{
87 collections::HashSet,
88 io, mem,
89 net::{SocketAddr, SocketAddrV4, SocketAddrV6},
90 sync::{
91 Arc, Weak,
92 atomic::{AtomicBool, Ordering},
93 },
94};
95use thiserror::Error;
96use tokio::{
97 io::{AsyncReadExt, AsyncWriteExt},
98 sync::{mpsc, watch},
99 task::{AbortHandle, JoinSet},
100 time::Duration,
101};
102use tracing::{Instrument, Span};
103
104#[derive(Default)]
105pub struct NetworkBuilder {
106 dht_contacts: Option<Arc<dyn DhtContactsStoreTrait>>,
107 monitor: Option<StateMonitor>,
108 runtime_id: Option<SecretRuntimeId>,
109 addr_filter: AddrFilter,
110}
111
112impl NetworkBuilder {
113 pub fn dht_contacts(self, contacts: Arc<dyn DhtContactsStoreTrait>) -> Self {
114 Self {
115 dht_contacts: Some(contacts),
116 ..self
117 }
118 }
119
120 pub fn monitor(self, monitor: StateMonitor) -> Self {
121 Self {
122 monitor: Some(monitor),
123 ..self
124 }
125 }
126
127 pub fn runtime_id(self, runtime_id: SecretRuntimeId) -> Self {
128 Self {
129 runtime_id: Some(runtime_id),
130 ..self
131 }
132 }
133
134 pub fn addr_filter(self, addr_filter: AddrFilter) -> Self {
135 Self {
136 addr_filter,
137 ..self
138 }
139 }
140
141 pub fn build(self) -> Network {
142 let (incoming_tx, incoming_rx) = mpsc::channel(1);
143 let gateway = Gateway::new(incoming_tx);
144 let monitor = self.monitor.unwrap_or_else(StateMonitor::make_root);
145
146 let dht_discovery =
153 DhtDiscovery::new(None, None, self.dht_contacts, monitor.make_child("DHT"));
154 let (dht_discovery_tx, dht_discovery_rx) = mpsc::unbounded_channel();
156
157 let port_forwarder = upnp::PortForwarder::new(monitor.make_child("UPnP"));
158
159 let (pex_discovery_tx, pex_discovery_rx) = mpsc::channel(1);
160 let pex_discovery = PexDiscovery::new(pex_discovery_tx);
161
162 let user_provided_peers = SeenPeers::new();
163
164 let this_runtime_id = self.runtime_id.unwrap_or_else(SecretRuntimeId::random);
165 let this_runtime_id_public = this_runtime_id.public();
166
167 let connections_monitor = monitor.make_child("Connections");
168 let peers_monitor = monitor.make_child("Peers");
169
170 let tasks = Arc::new(BlockingMutex::new(JoinSet::new()));
171
172 let inner = Arc::new(Inner {
173 main_monitor: monitor,
174 connections_monitor,
175 peers_monitor,
176 span: Span::current(),
177 gateway,
178 this_runtime_id,
179 registry: BlockingMutex::new(Registry {
180 peers: Some(Slab::new()),
181 repos: Slab::new(),
182 }),
183 port_forwarder,
184 port_forwarder_state: BlockingMutex::new(ComponentState::disabled(
185 DisableReason::Explicit,
186 )),
187 local_discovery_state: BlockingMutex::new(ComponentState::disabled(
188 DisableReason::Explicit,
189 )),
190 dht_discovery,
191 dht_discovery_tx,
192 local_dht_enabled: AtomicBool::new(false),
193 pex_discovery,
194 stun_clients: StunClients::new(),
195 connections: ConnectionSet::new(),
196 user_provided_peers,
197 tasks: Arc::downgrade(&tasks),
198 protocol_versions: watch::Sender::new(ProtocolVersions::new()),
199 our_addresses: BlockingMutex::new(HashSet::default()),
200 stats_tracker: StatsTracker::default(),
201 addr_filter: self.addr_filter,
202 });
203
204 inner.spawn(inner.clone().handle_incoming_connections(incoming_rx));
205 inner.spawn(inner.clone().run_dht(dht_discovery_rx));
206 inner.spawn(inner.clone().run_peer_exchange(pex_discovery_rx));
207
208 tracing::debug!(this_runtime_id = ?this_runtime_id_public.as_public_key(), "Network created");
209
210 Network {
211 inner,
212 _tasks: tasks,
213 }
214 }
215}
216
217pub struct Network {
218 inner: Arc<Inner>,
219 _tasks: Arc<BlockingMutex<JoinSet<()>>>,
222}
223
224impl Network {
225 pub fn builder() -> NetworkBuilder {
227 NetworkBuilder::default()
228 }
229
230 pub fn new() -> Self {
232 Self::builder().build()
233 }
234
235 pub async fn bind(&self, addrs: &[PeerAddr]) {
241 self.inner.bind(addrs).await
242 }
243
244 pub fn listener_local_addrs(&self) -> Vec<PeerAddr> {
245 self.inner.gateway.listener_local_addrs()
246 }
247
248 pub fn set_port_forwarding_enabled(&self, enabled: bool) {
249 let mut state = self.inner.port_forwarder_state.lock().unwrap();
250
251 if enabled {
252 if state.is_enabled() {
253 return;
254 }
255
256 state.enable(PortMappings::new(
257 &self.inner.port_forwarder,
258 &self.inner.gateway,
259 ));
260 } else {
261 state.disable(DisableReason::Explicit);
262 }
263 }
264
265 pub fn is_port_forwarding_enabled(&self) -> bool {
266 self.inner.port_forwarder_state.lock().unwrap().is_enabled()
267 }
268
269 pub fn set_local_discovery_enabled(&self, enabled: bool) {
270 let mut state = self.inner.local_discovery_state.lock().unwrap();
271
272 if enabled {
273 if state.is_enabled() {
274 return;
275 }
276
277 if let Some(handle) = self.inner.spawn_local_discovery() {
278 state.enable(handle.into());
279 } else {
280 state.disable(DisableReason::Implicit);
281 }
282 } else {
283 state.disable(DisableReason::Explicit);
284 }
285 }
286
287 pub fn is_local_discovery_enabled(&self) -> bool {
288 self.inner
289 .local_discovery_state
290 .lock()
291 .unwrap()
292 .is_enabled()
293 }
294
295 pub fn set_pex_send_enabled(&self, enabled: bool) {
300 self.inner.pex_discovery.set_send_enabled(enabled)
301 }
302
303 pub fn is_pex_send_enabled(&self) -> bool {
304 self.inner.pex_discovery.is_send_enabled()
305 }
306
307 pub fn set_pex_recv_enabled(&self, enabled: bool) {
312 self.inner.pex_discovery.set_recv_enabled(enabled)
313 }
314
315 pub fn is_pex_recv_enabled(&self) -> bool {
316 self.inner.pex_discovery.is_recv_enabled()
317 }
318 pub async fn external_addr_v4(&self) -> Option<SocketAddrV4> {
321 self.inner.stun_clients.external_addr_v4().await
322 }
323
324 pub async fn external_addr_v6(&self) -> Option<SocketAddrV6> {
327 self.inner.stun_clients.external_addr_v6().await
328 }
329
330 pub async fn nat_behavior(&self) -> Option<NatBehavior> {
333 self.inner.stun_clients.nat_behavior().await
334 }
335
336 pub fn stats(&self) -> Stats {
338 self.inner.stats_tracker.read()
339 }
340
341 pub fn add_user_provided_peer(&self, peer: &PeerAddr) {
342 self.inner.clone().establish_user_provided_connection(peer);
343 }
344
345 pub fn remove_user_provided_peer(&self, peer: &PeerAddr) {
346 self.inner.user_provided_peers.remove(peer)
347 }
348
349 pub fn this_runtime_id(&self) -> PublicRuntimeId {
350 self.inner.this_runtime_id.public()
351 }
352
353 pub fn peer_info_collector(&self) -> PeerInfoCollector {
354 self.inner.connections.peer_info_collector()
355 }
356
357 pub fn peer_info(&self, addr: PeerAddr) -> Option<PeerInfo> {
358 self.inner.connections.get_peer_info(addr)
359 }
360
361 pub fn current_protocol_version(&self) -> u64 {
362 self.inner.protocol_versions.borrow().our.into()
363 }
364
365 pub fn highest_seen_protocol_version(&self) -> u64 {
366 self.inner.protocol_versions.borrow().highest_seen.into()
367 }
368
369 pub fn subscribe(&self) -> NetworkEventReceiver {
371 NetworkEventReceiver::new(
372 self.inner.protocol_versions.subscribe(),
373 self.inner.connections.subscribe(),
374 )
375 }
376
377 pub fn register(&self, handle: RepositoryHandle) -> Registration {
386 *handle.vault.monitor.info_hash.get() =
387 Some(repository_info_hash(handle.vault.repository_id()));
388
389 let pex = self.inner.pex_discovery.new_repository();
390
391 let request_tracker = RequestTracker::new(handle.vault.monitor.traffic.clone());
392 request_tracker.set_timeout(REQUEST_TIMEOUT);
393
394 let choker = Choker::new();
396
397 let stats_tracker = StatsTracker::default();
398
399 let mut registry = self.inner.registry.lock().unwrap();
400
401 registry.create_link(
402 handle.vault.clone(),
403 &pex,
404 &request_tracker,
405 &choker,
406 stats_tracker.bytes.clone(),
407 );
408
409 let key = registry.repos.insert(RegistrationHolder {
410 vault: handle.vault,
411 dht: None,
412 pex,
413 request_tracker,
414 choker,
415 stats_tracker,
416 });
417
418 Registration {
419 inner: self.inner.clone(),
420 key,
421 }
422 }
423
424 pub async fn shutdown(&self) {
430 let Some(peers) = self.inner.registry.lock().unwrap().peers.take() else {
433 tracing::warn!("Network already shut down");
434 return;
435 };
436
437 shutdown_peers(peers).await;
438 }
439
440 pub fn set_request_timeout(&self, timeout: Duration) {
443 for (_, holder) in &self.inner.registry.lock().unwrap().repos {
444 holder.request_tracker.set_timeout(timeout);
445 }
446 }
447
448 pub fn open_udp_side_channel_v4(&self) -> Option<quic::SideChannel> {
454 self.inner
455 .gateway
456 .udp_side_channel_maker_v4()
457 .as_ref()
458 .map(|m| m.make())
459 }
460
461 pub fn open_udp_side_channel_v6(&self) -> Option<quic::SideChannel> {
467 self.inner
468 .gateway
469 .udp_side_channel_maker_v4()
470 .as_ref()
471 .map(|m| m.make())
472 }
473
474 pub fn open_stream(
479 &self,
480 addr: PeerAddr,
481 topic_id: TopicId,
482 ) -> Option<(SendStream, RecvStream)> {
483 let key = self.inner.connections.get_peer_key(addr)?;
484 Some(
485 self.inner
486 .registry
487 .lock()
488 .unwrap()
489 .peers
490 .as_ref()?
491 .get(key)?
492 .open_stream(topic_id),
493 )
494 }
495
496 pub fn set_dht_routers(&self, routers: HashSet<String>) {
499 self.inner.dht_discovery.set_routers(routers);
500 }
501
502 pub fn dht_routers(&self) -> HashSet<String> {
504 self.inner.dht_discovery.routers()
505 }
506
507 pub fn dht_lookup(&self, info_hash: InfoHash, announce: bool) -> DhtLookupStream {
510 DhtLookupStream::start(
511 &self.inner.dht_discovery,
512 info_hash,
513 announce,
514 self.is_local_dht_enabled(),
515 )
516 }
517
518 pub fn set_local_dht_enabled(&self, enabled: bool) {
526 let prev = self
527 .inner
528 .local_dht_enabled
529 .swap(enabled, Ordering::Release);
530
531 if prev != enabled {
532 self.inner.rebind_dht(self.inner.gateway.connectivity());
533 }
534 }
535
536 pub fn is_local_dht_enabled(&self) -> bool {
537 self.inner.local_dht_enabled.load(Ordering::Acquire)
538 }
539
540 pub async fn pin_dht(&self) -> DhtPin {
548 self.inner.dht_discovery.pin().await
549 }
550}
551
552impl Default for Network {
553 fn default() -> Self {
554 Self::new()
555 }
556}
557
558pub struct Registration {
559 inner: Arc<Inner>,
560 key: usize,
561}
562
563impl Registration {
564 pub fn set_dht_enabled(&self, enabled: bool) {
565 let mut registry = self.inner.registry.lock().unwrap();
566 let holder = &mut registry.repos[self.key];
567
568 if enabled {
569 holder.dht = Some(
570 self.inner
571 .start_dht_lookup(repository_info_hash(holder.vault.repository_id())),
572 );
573 } else {
574 holder.dht = None;
575 }
576 }
577
578 pub fn is_dht_enabled(&self) -> bool {
583 self.inner.registry.lock().unwrap().repos[self.key]
584 .dht
585 .is_some()
586 }
587
588 pub fn set_pex_enabled(&self, enabled: bool) {
594 let registry = self.inner.registry.lock().unwrap();
595 registry.repos[self.key].pex.set_enabled(enabled);
596 }
597
598 pub fn is_pex_enabled(&self) -> bool {
599 self.inner.registry.lock().unwrap().repos[self.key]
600 .pex
601 .is_enabled()
602 }
603
604 pub fn stats(&self) -> Stats {
606 self.inner.registry.lock().unwrap().repos[self.key]
607 .stats_tracker
608 .read()
609 }
610}
611
612impl Drop for Registration {
613 fn drop(&mut self) {
614 let mut registry = self
615 .inner
616 .registry
617 .lock()
618 .unwrap_or_else(|error| error.into_inner());
619
620 if let Some(holder) = registry.repos.try_remove(self.key) {
621 for (_, peer) in registry.peers.as_mut().into_iter().flatten() {
622 peer.destroy_link(holder.vault.repository_id());
623 }
624 }
625 }
626}
627
628struct RegistrationHolder {
629 vault: Vault,
630 dht: Option<dht::LookupRequest>,
631 pex: PexRepository,
632 request_tracker: RequestTracker,
633 choker: Choker,
634 stats_tracker: StatsTracker,
635}
636
637struct Inner {
638 main_monitor: StateMonitor,
639 connections_monitor: StateMonitor,
640 peers_monitor: StateMonitor,
641 span: Span,
642 gateway: Gateway,
643 this_runtime_id: SecretRuntimeId,
644 registry: BlockingMutex<Registry>,
645 port_forwarder: upnp::PortForwarder,
646 port_forwarder_state: BlockingMutex<ComponentState<PortMappings>>,
647 local_discovery_state: BlockingMutex<ComponentState<ScopedAbortHandle>>,
648 dht_discovery: DhtDiscovery,
649 dht_discovery_tx: mpsc::UnboundedSender<DhtEvent>,
650 local_dht_enabled: AtomicBool,
651 pex_discovery: PexDiscovery,
652 stun_clients: StunClients,
653 connections: ConnectionSet,
654 protocol_versions: watch::Sender<ProtocolVersions>,
655 user_provided_peers: SeenPeers,
656 tasks: Weak<BlockingMutex<JoinSet<()>>>,
659 our_addresses: BlockingMutex<HashSet<PeerAddr>>,
661 stats_tracker: StatsTracker,
662 addr_filter: AddrFilter,
663}
664
665struct Registry {
666 peers: Option<Slab<MessageBroker>>,
668 repos: Slab<RegistrationHolder>,
669}
670
671impl Registry {
672 fn create_link(
673 &mut self,
674 repo: Vault,
675 pex: &PexRepository,
676 request_tracker: &RequestTracker,
677 choker: &Choker,
678 byte_counters: Arc<ByteCounters>,
679 ) {
680 if let Some(peers) = &mut self.peers {
681 for (_, peer) in peers {
682 peer.create_link(
683 repo.clone(),
684 pex,
685 request_tracker.clone(),
686 choker.clone(),
687 byte_counters.clone(),
688 )
689 }
690 }
691 }
692}
693
694impl Inner {
695 fn is_shutdown(&self) -> bool {
696 self.registry.lock().unwrap().peers.is_none()
697 }
698
699 async fn bind(self: &Arc<Self>, bind: &[PeerAddr]) {
700 let bind = StackAddresses::from(bind);
701
702 if !self.gateway.addresses().any_stack_needs_rebind(&bind) {
704 return;
705 }
706
707 self.span.in_scope(|| self.gateway.bind(&bind));
709
710 let conn = self.gateway.connectivity();
711
712 match conn {
714 Connectivity::Full => self.stun_clients.rebind(
715 self.gateway.udp_side_channel_maker_v4().map(|m| m.make()),
716 self.gateway.udp_side_channel_maker_v6().map(|m| m.make()),
717 ),
718 Connectivity::LocalOnly | Connectivity::Disabled => (),
719 }
720
721 self.rebind_dht(conn);
723
724 match conn {
726 Connectivity::Full => {
727 let mut state = self.port_forwarder_state.lock().unwrap();
728 if !state.is_disabled(DisableReason::Explicit) {
729 state.enable(PortMappings::new(&self.port_forwarder, &self.gateway));
730 }
731 }
732 Connectivity::LocalOnly | Connectivity::Disabled => {
733 self.port_forwarder_state
734 .lock()
735 .unwrap()
736 .disable_if_enabled(DisableReason::Implicit);
737 }
738 }
739
740 {
745 let mut state = self.local_discovery_state.lock().unwrap();
746 if !state.is_disabled(DisableReason::Explicit) {
747 if let Some(handle) = self.spawn_local_discovery() {
748 state.enable(handle.into());
749 } else {
750 state.disable(DisableReason::Implicit);
751 }
752 }
753 }
754
755 if matches!(conn, Connectivity::LocalOnly | Connectivity::Disabled) {
762 self.disconnect_all().await;
763 }
764 }
765
766 async fn disconnect_all(&self) {
768 let Some(peers) = self.registry.lock().unwrap().peers.replace(Slab::default()) else {
769 return;
770 };
771
772 shutdown_peers(peers).await;
773 }
774
775 fn spawn_local_discovery(self: &Arc<Self>) -> Option<AbortHandle> {
776 let ports: Vec<_> = self
777 .gateway
778 .listener_local_addrs()
779 .into_iter()
780 .filter_map(|addr| match addr {
781 PeerAddr::Tcp(SocketAddr::V4(addr)) => Some(PeerPort::Tcp(addr.port())),
782 PeerAddr::Quic(SocketAddr::V4(addr)) => Some(PeerPort::Quic(addr.port())),
783 _ => None,
784 })
785 .collect();
786
787 if !ports.is_empty() {
788 Some(
789 self.spawn(
790 self.clone()
791 .run_local_discovery(ports)
792 .instrument(self.span.clone()),
793 ),
794 )
795 } else {
796 tracing::error!("Not enabling local discovery because there is no IPv4 listener");
797 None
798 }
799 }
800
801 async fn run_local_discovery(self: Arc<Self>, listener_ports: Vec<PeerPort>) {
802 let mut discovery = LocalDiscovery::new(
803 listener_ports,
804 self.main_monitor.make_child("LocalDiscovery"),
805 );
806
807 loop {
808 let peer = discovery.recv().await;
809
810 if self.is_shutdown() {
811 break;
812 }
813
814 self.spawn(
815 self.clone()
816 .handle_peer_found(peer, PeerSource::LocalDiscovery),
817 );
818 }
819 }
820
821 fn start_dht_lookup(&self, info_hash: InfoHash) -> dht::LookupRequest {
822 self.dht_discovery
823 .start_lookup(info_hash, true, self.dht_discovery_tx.clone())
824 }
825
826 fn rebind_dht(&self, conn: Connectivity) {
827 match (conn, self.local_dht_enabled.load(Ordering::Acquire)) {
828 (Connectivity::Full, _) | (Connectivity::LocalOnly, true) => self.dht_discovery.rebind(
829 self.gateway.udp_side_channel_maker_v4(),
830 self.gateway.udp_side_channel_maker_v6(),
831 ),
832 (Connectivity::LocalOnly, false) | (Connectivity::Disabled, _) => {
833 self.dht_discovery.rebind(None, None)
834 }
835 }
836 }
837
838 async fn run_dht(self: Arc<Self>, mut discovery_rx: mpsc::UnboundedReceiver<DhtEvent>) {
839 while let Some(event) = discovery_rx.recv().await {
840 if self.is_shutdown() {
841 break;
842 }
843
844 let peer = match event {
845 DhtEvent::PeerFound(peer) => peer,
846 DhtEvent::RoundEnded => continue,
847 };
848
849 if !self.local_dht_enabled.load(Ordering::Acquire) && peer.initial_addr().is_local() {
850 continue;
851 }
852
853 self.spawn(self.clone().handle_peer_found(peer, PeerSource::Dht));
854 }
855 }
856
857 async fn run_peer_exchange(self: Arc<Self>, mut discovery_rx: mpsc::Receiver<SeenPeer>) {
858 while let Some(peer) = discovery_rx.recv().await {
859 if self.is_shutdown() {
860 break;
861 }
862
863 self.spawn(
864 self.clone()
865 .handle_peer_found(peer, PeerSource::PeerExchange),
866 );
867 }
868 }
869
870 fn establish_user_provided_connection(self: Arc<Self>, peer: &PeerAddr) {
871 let peer = match self.user_provided_peers.insert(*peer) {
872 Some(peer) => peer,
873 None => return,
875 };
876
877 self.spawn(
878 self.clone()
879 .handle_peer_found(peer, PeerSource::UserProvided),
880 );
881 }
882
883 async fn handle_incoming_connections(
884 self: Arc<Self>,
885 mut rx: mpsc::Receiver<(Connection, PeerAddr)>,
886 ) {
887 while let Some((connection, addr)) = rx.recv().await {
888 match self.connections.reserve(addr, PeerSource::Listener) {
889 ReserveResult::Permit(permit) => {
890 if self.is_shutdown() {
891 break;
892 }
893
894 let this = self.clone();
895
896 let monitor = self.span.in_scope(|| {
897 ConnectionMonitor::new(
898 &self.connections_monitor,
899 &permit.addr(),
900 permit.source(),
901 )
902 });
903 monitor.mark_as_connecting(permit.id());
904
905 self.spawn(async move {
906 this.handle_connection(connection, permit, &monitor).await;
907 });
908 }
909 ReserveResult::Occupied(_, _their_source, permit_id) => {
910 tracing::debug!(?addr, ?permit_id, "dropping accepted duplicate connection");
911 }
912 }
913 }
914 }
915
916 async fn handle_peer_found(self: Arc<Self>, peer: SeenPeer, source: PeerSource) {
917 let create_backoff = || {
918 ExponentialBackoffBuilder::new()
919 .with_initial_interval(Duration::from_millis(100))
920 .with_max_interval(Duration::from_secs(8))
921 .with_max_elapsed_time(None)
922 .build()
923 };
924
925 let mut backoff = create_backoff();
926
927 let mut next_sleep = None;
928
929 loop {
930 let monitor = self.span.in_scope(|| {
931 ConnectionMonitor::new(&self.connections_monitor, peer.initial_addr(), source)
932 });
933
934 if self.is_shutdown() {
938 return;
939 }
940
941 let addr = match peer.addr_if_seen() {
942 Some(addr) => *addr,
943 None => return,
944 };
945
946 if self.our_addresses.lock().unwrap().contains(&addr) {
947 return;
949 }
950
951 let permit = match self.connections.reserve(addr, source) {
952 ReserveResult::Permit(permit) => permit,
953 ReserveResult::Occupied(on_release, their_source, connection_id) => {
954 if source == their_source {
955 return;
957 }
958
959 monitor.mark_as_awaiting_permit();
962 tracing::debug!(
963 parent: monitor.span(),
964 %connection_id,
965 "Duplicate from different source - awaiting permit"
966 );
967
968 on_release.await;
969
970 next_sleep = None;
971 backoff = create_backoff();
972
973 continue;
974 }
975 };
976
977 if let Some(sleep) = next_sleep {
978 tracing::debug!(parent: monitor.span(), "Next connection attempt in {:?}", sleep);
979 tokio::time::sleep(sleep).await;
980 }
981
982 next_sleep = backoff.next_backoff();
983
984 permit.mark_as_connecting();
985 monitor.mark_as_connecting(permit.id());
986 tracing::trace!(parent: monitor.span(), "Connecting");
987
988 let Some(addr) = peer.addr_if_seen() else {
989 break;
990 };
991
992 if !self.addr_filter.apply(addr.socket_addr()) {
993 tracing::debug!("Invalid peer address - discarding");
994 break;
995 }
996
997 let socket = match self
998 .gateway
999 .connect_with_retries(&peer)
1000 .instrument(monitor.span().clone())
1001 .await
1002 {
1003 Some(socket) => socket,
1004 None => break,
1005 };
1006
1007 if !self.handle_connection(socket, permit, &monitor).await {
1008 break;
1009 }
1010 }
1011 }
1012
1013 async fn handle_connection(
1015 &self,
1016 connection: Connection,
1017 permit: ConnectionPermit,
1018 monitor: &ConnectionMonitor,
1019 ) -> bool {
1020 tracing::trace!(parent: monitor.span(), "Handshaking");
1021
1022 permit.mark_as_handshaking();
1023 monitor.mark_as_handshaking();
1024
1025 let handshake_result = perform_handshake(
1026 &connection,
1027 VERSION,
1028 &self.this_runtime_id,
1029 permit.source().direction(),
1030 )
1031 .await;
1032
1033 if let Err(error) = &handshake_result {
1034 tracing::debug!(parent: monitor.span(), ?error, "Handshake failed");
1035 }
1036
1037 let that_runtime_id = match handshake_result {
1038 Ok(writer_id) => writer_id,
1039 Err(HandshakeError::ProtocolVersionMismatch(their_version)) => {
1040 self.on_protocol_mismatch(their_version);
1041 return false;
1042 }
1043 Err(
1044 HandshakeError::Timeout
1045 | HandshakeError::BadMagic
1046 | HandshakeError::Io(_)
1047 | HandshakeError::Connection(_),
1048 ) => return false,
1049 };
1050
1051 if that_runtime_id == self.this_runtime_id.public() {
1053 tracing::debug!(parent: monitor.span(), "Connection from self, discarding");
1054 self.our_addresses.lock().unwrap().insert(permit.addr());
1055 return false;
1056 }
1057
1058 let closed = connection.closed();
1059
1060 let key = {
1061 let mut registry = self.registry.lock().unwrap();
1062 let registry = &mut *registry;
1063
1064 let Some(peers) = &mut registry.peers else {
1065 return false;
1067 };
1068
1069 let pex_peer = self.pex_discovery.new_peer();
1070 pex_peer.handle_connection(permit.addr(), permit.source(), permit.released());
1071
1072 let mut peer = monitor.span().in_scope(|| {
1073 MessageBroker::new(
1074 self.this_runtime_id.public(),
1075 that_runtime_id,
1076 connection,
1077 pex_peer,
1078 self.peers_monitor.make_child(format!(
1079 "{} {}",
1080 permit.source().direction().glyph(),
1081 permit.addr()
1082 )),
1083 self.stats_tracker.bytes.clone(),
1084 permit.byte_counters(),
1085 )
1086 });
1087
1088 for (_, holder) in ®istry.repos {
1092 peer.create_link(
1093 holder.vault.clone(),
1094 &holder.pex,
1095 holder.request_tracker.clone(),
1096 holder.choker.clone(),
1097 holder.stats_tracker.bytes.clone(),
1098 );
1099 }
1100
1101 peers.insert(peer)
1102 };
1103
1104 permit.mark_as_active(that_runtime_id, key);
1105 monitor.mark_as_active(that_runtime_id);
1106
1107 let _guard = PeerGuard {
1110 registry: &self.registry,
1111 key,
1112 };
1113
1114 closed.await;
1115
1116 true
1117 }
1118
1119 fn on_protocol_mismatch(&self, their_version: Version) {
1120 self.protocol_versions.send_if_modified(|versions| {
1121 if versions.highest_seen < their_version {
1122 versions.highest_seen = their_version;
1123 true
1124 } else {
1125 false
1126 }
1127 });
1128 }
1129
1130 fn spawn<Fut>(&self, f: Fut) -> AbortHandle
1131 where
1132 Fut: Future<Output = ()> + Send + 'static,
1133 {
1134 let tasks = self.tasks.upgrade().unwrap();
1137 let mut tasks = tasks.lock().unwrap();
1138
1139 while tasks.try_join_next().is_some() {}
1143
1144 tasks.spawn(f.instrument(Span::current()))
1145 }
1146}
1147
1148async fn perform_handshake(
1152 connection: &Connection,
1153 this_version: Version,
1154 this_runtime_id: &SecretRuntimeId,
1155 dir: ConnectionDirection,
1156) -> Result<PublicRuntimeId, HandshakeError> {
1157 let result = tokio::time::timeout(std::time::Duration::from_secs(5), async move {
1158 let (mut writer, mut reader) = match dir {
1159 ConnectionDirection::Incoming => connection.incoming().await?,
1160 ConnectionDirection::Outgoing => connection.outgoing().await?,
1161 };
1162
1163 writer.write_all(MAGIC).await?;
1164
1165 {
1167 tokio::time::sleep(std::time::Duration::from_millis(700)).await;
1173 }
1174
1175 this_version.write_into(&mut writer).await?;
1176
1177 let mut that_magic = [0; MAGIC.len()];
1178 reader.read_exact(&mut that_magic).await?;
1179
1180 if MAGIC != &that_magic {
1181 return Err(HandshakeError::BadMagic);
1182 }
1183
1184 let that_version = Version::read_from(&mut reader).await?;
1185 if that_version > this_version {
1186 return Err(HandshakeError::ProtocolVersionMismatch(that_version));
1187 }
1188
1189 let that_runtime_id =
1190 runtime_id::exchange(this_runtime_id, &mut writer, &mut reader).await?;
1191
1192 writer.shutdown().await?;
1193
1194 Ok(that_runtime_id)
1195 })
1196 .await;
1197
1198 match result {
1199 Ok(subresult) => subresult,
1200 Err(_) => Err(HandshakeError::Timeout),
1201 }
1202}
1203
1204#[derive(Debug, Error)]
1205enum HandshakeError {
1206 #[error("protocol version mismatch")]
1207 ProtocolVersionMismatch(Version),
1208 #[error("bad magic")]
1209 BadMagic,
1210 #[error("timeout")]
1211 Timeout,
1212 #[error("IO error")]
1213 Io(#[from] io::Error),
1214 #[error("connection error")]
1215 Connection(#[from] ConnectionError),
1216}
1217
1218struct PeerGuard<'a> {
1220 registry: &'a BlockingMutex<Registry>,
1221 key: usize,
1222}
1223
1224impl Drop for PeerGuard<'_> {
1225 fn drop(&mut self) {
1226 if let Some(peers) = &mut self
1227 .registry
1228 .lock()
1229 .unwrap_or_else(|error| error.into_inner())
1230 .peers
1231 {
1232 peers.try_remove(self.key);
1233 }
1234 }
1235}
1236
1237struct PortMappings {
1238 _mappings: Vec<upnp::Mapping>,
1239}
1240
1241impl PortMappings {
1242 fn new(forwarder: &upnp::PortForwarder, gateway: &Gateway) -> Self {
1243 let mappings = gateway
1244 .listener_local_addrs()
1245 .into_iter()
1246 .filter_map(|addr| {
1247 match addr {
1248 PeerAddr::Quic(SocketAddr::V4(addr)) => {
1249 Some(forwarder.add_mapping(
1250 addr.port(), addr.port(), ip::Protocol::Udp,
1253 ))
1254 }
1255 PeerAddr::Tcp(SocketAddr::V4(addr)) => {
1256 Some(forwarder.add_mapping(
1257 addr.port(), addr.port(), ip::Protocol::Tcp,
1260 ))
1261 }
1262 PeerAddr::Quic(SocketAddr::V6(_)) | PeerAddr::Tcp(SocketAddr::V6(_)) => {
1263 None
1267 }
1268 }
1269 })
1270 .collect();
1271
1272 Self {
1273 _mappings: mappings,
1274 }
1275 }
1276}
1277
1278enum ComponentState<T> {
1279 Enabled(T),
1280 Disabled(DisableReason),
1281}
1282
1283impl<T> ComponentState<T> {
1284 fn disabled(reason: DisableReason) -> Self {
1285 Self::Disabled(reason)
1286 }
1287
1288 fn is_enabled(&self) -> bool {
1289 matches!(self, Self::Enabled(_))
1290 }
1291
1292 fn is_disabled(&self, reason: DisableReason) -> bool {
1293 match self {
1294 Self::Disabled(current_reason) if *current_reason == reason => true,
1295 Self::Disabled(_) | Self::Enabled(_) => false,
1296 }
1297 }
1298
1299 fn disable(&mut self, reason: DisableReason) -> Option<T> {
1300 match mem::replace(self, Self::Disabled(reason)) {
1301 Self::Enabled(payload) => Some(payload),
1302 Self::Disabled(_) => None,
1303 }
1304 }
1305
1306 fn disable_if_enabled(&mut self, reason: DisableReason) -> Option<T> {
1307 match self {
1308 Self::Enabled(_) => match mem::replace(self, Self::Disabled(reason)) {
1309 Self::Enabled(payload) => Some(payload),
1310 Self::Disabled(_) => unreachable!(),
1311 },
1312 Self::Disabled(_) => None,
1313 }
1314 }
1315
1316 fn enable(&mut self, payload: T) -> Option<T> {
1317 match mem::replace(self, Self::Enabled(payload)) {
1318 Self::Enabled(payload) => Some(payload),
1319 Self::Disabled(_) => None,
1320 }
1321 }
1322}
1323
1324#[derive(Eq, PartialEq)]
1325enum DisableReason {
1326 Implicit,
1328 Explicit,
1330}
1331
1332pub fn repository_info_hash(id: &RepositoryId) -> InfoHash {
1333 InfoHash::try_from(&id.salted_hash(b"ouisync repository info-hash").as_ref()[..INFO_HASH_LEN])
1337 .unwrap()
1338}
1339
1340async fn shutdown_peers(peers: Slab<MessageBroker>) {
1341 future::join_all(peers.into_iter().map(|(_, peer)| peer.shutdown())).await;
1342}