1mod task;
2
3pub use rustp2p;
4use rustp2p::config::LoadBalance;
5use rustp2p::pipe::PeerNodeAddress;
6use rustp2p::protocol::node_id::GroupCode;
7use std::io;
8use std::net::Ipv4Addr;
9pub use tcp_ip;
10#[derive(Clone, Debug, Default)]
13pub struct TransportBuilder {
14 group_code: Option<String>,
15 endpoint: Option<Ipv4Addr>,
16 load_balance: Option<LoadBalance>,
17 listen_port: Option<u16>,
18 peers: Option<Vec<PeerNodeAddress>>,
19}
20impl TransportBuilder {
21 pub fn group_code(mut self, group_code: String) -> Self {
23 self.group_code = Some(group_code);
24 self
25 }
26 pub fn endpoint(mut self, endpoint: Ipv4Addr) -> Self {
28 self.endpoint = Some(endpoint);
29 self
30 }
31 pub fn listen_port(mut self, listen_port: u16) -> Self {
33 self.listen_port = Some(listen_port);
34 self
35 }
36 pub fn peers(mut self, peers: Vec<PeerNodeAddress>) -> Self {
38 self.peers = Some(peers);
39 self
40 }
41 pub fn load_balance(mut self, load_balance: LoadBalance) -> Self {
42 self.load_balance = Some(load_balance);
43 self
44 }
45 fn config(self) -> io::Result<(rustp2p::config::PipeConfig, tcp_ip::IpStackConfig)> {
46 let Some(ip) = self.endpoint else {
47 return Err(io::Error::new(io::ErrorKind::Other, "IP must be set"));
48 };
49 let mut udp_config = rustp2p::config::UdpPipeConfig::default();
50 let mut tcp_config = rustp2p::config::TcpPipeConfig::default();
51 if let Some(port) = self.listen_port {
52 udp_config = udp_config.set_simple_udp_port(port);
53 tcp_config = tcp_config.set_tcp_port(port);
54 }
55 let mut p2p_config = rustp2p::config::PipeConfig::empty()
56 .set_load_balance(self.load_balance.unwrap_or(LoadBalance::RoundRobin))
57 .set_udp_pipe_config(udp_config)
58 .set_tcp_pipe_config(tcp_config)
59 .set_node_id(ip.into());
60 if let Some(peers) = self.peers {
61 p2p_config = p2p_config.set_direct_addrs(peers);
62 }
63 if let Some(group_code) = self.group_code {
64 p2p_config = p2p_config.set_group_code(string_to_group_code(&group_code))
65 }
66
67 let ip_stack_config = tcp_ip::IpStackConfig::default();
68 Ok((p2p_config, ip_stack_config))
69 }
70 #[cfg(feature = "global")]
71 pub async fn build_context(self) -> io::Result<()> {
72 let (p2p_config, ip_stack_config) = self.config()?;
73 transport_from_config(p2p_config, ip_stack_config).await
74 }
75 #[cfg(not(feature = "global"))]
76 pub async fn build(self) -> io::Result<tcp_ip::IpStack> {
77 let (p2p_config, ip_stack_config) = self.config()?;
78 transport_from_config(p2p_config, ip_stack_config).await
79 }
80}
81#[cfg(feature = "global")]
83pub async fn transport_from_config(
84 rustp2p_config: rustp2p::config::PipeConfig,
85 tcp_ip_config: tcp_ip::IpStackConfig,
86) -> io::Result<()> {
87 transport_from_config0(rustp2p_config, tcp_ip_config)
88 .await
89 .map(|_| ())
90}
91#[cfg(not(feature = "global"))]
93pub async fn transport_from_config(
94 rustp2p_config: rustp2p::config::PipeConfig,
95 tcp_ip_config: tcp_ip::IpStackConfig,
96) -> io::Result<tcp_ip::IpStack> {
97 transport_from_config0(rustp2p_config, tcp_ip_config).await
98}
99async fn transport_from_config0(
100 rustp2p_config: rustp2p::config::PipeConfig,
101 tcp_ip_config: tcp_ip::IpStackConfig,
102) -> io::Result<tcp_ip::IpStack> {
103 let mtu = tcp_ip_config.mtu;
104 let pipe = rustp2p::pipe::Pipe::new(rustp2p_config).await?;
105 let Some(node_id) = pipe.writer().pipe_context().load_id() else {
106 return Err(io::Error::new(io::ErrorKind::Other, "Node ID must be set"));
107 };
108 #[cfg(not(feature = "global"))]
109 let (ip_stack, ip_stack_send, ip_stack_recv) = tcp_ip::ip_stack(tcp_ip_config)?;
110 #[cfg(feature = "global")]
111 let (ip_stack_send, ip_stack_recv) = tcp_ip::ip_stack(tcp_ip_config)?;
112 #[cfg(feature = "global")]
113 let ip_stack = tcp_ip::IpStack::get()?;
114 ip_stack.routes().set_default_v4(node_id.into());
115 let mut v6: [u8; 16] = [
116 0xfd, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0, 0, 0, 0,
117 ];
118 v6[12..].copy_from_slice(node_id.as_ref());
119 ip_stack
120 .routes()
121 .set_default_v6(std::net::Ipv6Addr::from(v6));
122 task::start(mtu, pipe, ip_stack_send, ip_stack_recv).await?;
123 Ok(ip_stack)
124}
125fn string_to_group_code(input: &str) -> GroupCode {
126 let mut array = [0u8; 16];
127 let bytes = input.as_bytes();
128 let len = bytes.len().min(16);
129 array[..len].copy_from_slice(&bytes[..len]);
130 array.into()
131}