cuprate_p2p_core/network_zones/
clear.rs

1use std::{
2    net::{IpAddr, SocketAddr},
3    pin::Pin,
4    task::{Context, Poll},
5};
6
7use futures::Stream;
8use tokio::net::{
9    tcp::{OwnedReadHalf, OwnedWriteHalf},
10    TcpListener, TcpStream,
11};
12use tokio_util::codec::{FramedRead, FramedWrite};
13
14use cuprate_wire::MoneroWireCodec;
15
16use crate::{NetZoneAddress, NetworkZone};
17
18impl NetZoneAddress for SocketAddr {
19    type BanID = IpAddr;
20
21    fn set_port(&mut self, port: u16) {
22        Self::set_port(self, port);
23    }
24
25    fn ban_id(&self) -> Self::BanID {
26        self.ip()
27    }
28
29    fn make_canonical(&mut self) {
30        let ip = self.ip().to_canonical();
31        self.set_ip(ip);
32    }
33
34    fn should_add_to_peer_list(&self) -> bool {
35        // TODO
36        true
37    }
38}
39
40#[derive(Debug, Clone)]
41pub struct ClearNetServerCfg {
42    pub ip: IpAddr,
43}
44
45#[derive(Clone, Copy)]
46pub enum ClearNet {}
47
48#[async_trait::async_trait]
49impl NetworkZone for ClearNet {
50    const NAME: &'static str = "ClearNet";
51
52    const CHECK_NODE_ID: bool = true;
53
54    type Addr = SocketAddr;
55    type Stream = FramedRead<OwnedReadHalf, MoneroWireCodec>;
56    type Sink = FramedWrite<OwnedWriteHalf, MoneroWireCodec>;
57    type Listener = InBoundStream;
58
59    type ServerCfg = ClearNetServerCfg;
60
61    async fn connect_to_peer(
62        addr: Self::Addr,
63    ) -> Result<(Self::Stream, Self::Sink), std::io::Error> {
64        let (read, write) = TcpStream::connect(addr).await?.into_split();
65        Ok((
66            FramedRead::new(read, MoneroWireCodec::default()),
67            FramedWrite::new(write, MoneroWireCodec::default()),
68        ))
69    }
70
71    async fn incoming_connection_listener(
72        config: Self::ServerCfg,
73        port: u16,
74    ) -> Result<Self::Listener, std::io::Error> {
75        let listener = TcpListener::bind(SocketAddr::new(config.ip, port)).await?;
76        Ok(InBoundStream { listener })
77    }
78}
79
80pub struct InBoundStream {
81    listener: TcpListener,
82}
83
84impl Stream for InBoundStream {
85    type Item = Result<
86        (
87            Option<SocketAddr>,
88            FramedRead<OwnedReadHalf, MoneroWireCodec>,
89            FramedWrite<OwnedWriteHalf, MoneroWireCodec>,
90        ),
91        std::io::Error,
92    >;
93
94    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
95        self.listener
96            .poll_accept(cx)
97            .map_ok(|(stream, mut addr)| {
98                let ip = addr.ip().to_canonical();
99                addr.set_ip(ip);
100
101                let (read, write) = stream.into_split();
102                (
103                    Some(addr),
104                    FramedRead::new(read, MoneroWireCodec::default()),
105                    FramedWrite::new(write, MoneroWireCodec::default()),
106                )
107            })
108            .map(Some)
109    }
110}