12 releases
0.1.12 | Dec 5, 2024 |
---|---|
0.1.11 | Nov 27, 2024 |
0.1.9 | Oct 31, 2024 |
0.1.2 | Sep 23, 2024 |
#1424 in Network programming
512 downloads per month
Used in 2 crates
(via rustp2p)
170KB
4.5K
SLoC
rust-p2p
NAT traversal for p2p communication, this is implemented in terms of a hole-punching technique.
This crate provides a convenient way to create a pipe between multiple remote peers that may be behind Nats, these pipelines that are spawned from the pipe can be used to read/write bytes from/to a peer to another.
The underlying transport protocols are TCP
, UDP
in the pipelines, users can even extend the protocol for the pipeline by using the powerful trait.
This crate is built on the async ecosystem tokio
Supported Platforms
It's a cross-platform crate
Usage
Add this dependency to your cargo.toml
rust-p2p-core = {version = "0.1"}
Example
#[tokio::main]
async fn main() {
let udp_config = UdpPipeConfig::default();
let tcp_config = TcpPipeConfig::default();
let config = PipeConfig::empty()
.set_udp_pipe_config(udp_config)
.set_tcp_pipe_config(tcp_config)
.set_main_pipeline_num(2);
let (mut pipe, puncher, idle_route_manager) = pipe(config).unwrap();
// Handle the idle route
tokio::spawn(async move {
loop {
let (peer_id, route, time) = idle_route_manager.next_idle().await;
log::info!(
"route timeout peer_id={peer_id},route={route:?},time={:?}",
time.elapsed()
);
// delete the mapping associated with the route and peer_id
idle_route_manager.remove_route(&peer_id, &route.route_key());
}
});
let pipe_writer = pipe.writer_ref().to_owned();
let peer_id = "peer_id".to_owned(); // The remote peer is said to be named "peer_id"
// The Nat information of the peer for which we prepare to punch the hole between local and it
let peer_nat_info = NatInfo {
nat_type: NatType::Cone, //Nat type
public_ips: vec![Ipv4Addr::new(1, 1, 1, 1)], // The public IP mapped by Nat
public_ports: vec![8080], // The public port mapped by Nat
mapping_tcp_addr: vec![],
mapping_udp_addr: vec![],
public_port_range: 0,
local_ipv4: Ipv4Addr::new(1, 1, 1, 1),
ipv6: None,
local_udp_ports: vec![0],
local_tcp_port: 0,
public_tcp_port: 0,
};
tokio::spawn(async move {
// We may need to keep calling this method until the peer receives "hello"
let rs = puncher
.punch(
peer_id,
b"hello",
PunchInfo::new(PunchModelBoxes::all(), peer_nat_info),
)
.await;
});
loop {
let pipe_line = pipe.accept().await.unwrap();
let pipe_writer_ = pipe_writer.clone();
tokio::spawn(async move {
let mut buf = [0; 65536];
loop {
let (len, route_key) = match pipe_line.recv_from(&mut buf).await {
Ok(rs) => rs,
Err(e) => break,
};
// route_key denotes the source from which the buf is sent from in the pipeline
// pipe_writer_.send_to(b"hello", &route_key).await.unwrap();
}
});
}
}
Dependencies
~4–35MB
~545K SLoC