udpflow/lib.rs
1//! Stream API for tokio-udp.
2//!
3//! ## TCP-like UDP stream
4//!
5//! ```
6//! use tokio::net::UdpSocket;
7//! use tokio::io::{AsyncReadExt, AsyncWriteExt};
8//! use udpflow::{UdpListener, UdpStreamLocal, UdpStreamRemote};
9//! async fn server() {
10//! let addr = "127.0.0.1:5000".parse().unwrap();
11//! let listener = UdpListener::new(addr).unwrap();
12//! loop {
13//! let mut buf = vec![0u8; 0x2000];
14//! let (n, stream, addr) = listener.accept(&mut buf).await.unwrap();
15//! buf.truncate(n);
16//! tokio::spawn(handle(stream, buf));
17//! }
18//! }
19//!
20//! async fn handle(mut stream1: UdpStreamLocal, first_packet: Vec<u8>) {
21//! let local = "127.0.0.1:0".parse().unwrap();
22//! let remote = "127.0.0.1:10000".parse().unwrap();
23//! let mut stream2 = UdpStreamRemote::new(local, remote).await.unwrap();
24//! stream2.write_all(&first_packet).await.unwrap();
25//! let mut buf = vec![0u8; 256];
26//! stream1.read(&mut buf).await; stream2.write(&buf).await;
27//! stream2.read(&mut buf).await; stream1.write(&buf).await;
28//! }
29//! ```
30//!
31//! ## Send/Recv framed data
32//!
33//! ```
34//! use tokio::net::TcpStream;
35//! use udpflow::UotStream;
36//! use tokio::io::{AsyncReadExt, AsyncWriteExt};
37//! async {
38//! let stream = TcpStream::connect("127.0.0.1:8080").await.unwrap();
39//! let mut stream = UotStream::new(stream);
40//! let mut buf = vec![0u8; 256];
41//! // read a frame
42//! let n = stream.read(&mut buf).await.unwrap();
43//! // write a frame
44//! stream.write_all(&buf[..n]).await;
45//! };
46//! ```
47//!
48
49mod streaml;
50mod streamr;
51mod listener;
52
53pub mod frame;
54
55pub use listener::UdpListener;
56pub use streaml::UdpStreamLocal;
57pub use streamr::UdpStreamRemote;
58pub use frame::UotStream;
59
60/// Re-export from tokio-udp.
61pub use tokio::net::UdpSocket;
62
63mod statics {
64 use std::time::Duration;
65
66 static mut TIMEOUT: Duration = Duration::from_secs(20);
67
68 /// Get read timeout.
69 pub fn get_timeout() -> Duration { unsafe { TIMEOUT } }
70
71 /// Set read timeout.
72 pub fn set_timeout(timeout: Duration) {
73 unsafe {
74 TIMEOUT = timeout;
75 }
76 }
77}
78
79pub use statics::{set_timeout, get_timeout};
80
81pub(crate) fn new_udp_socket(local_addr: std::net::SocketAddr) -> std::io::Result<UdpSocket> {
82 let udp_sock = socket2::Socket::new(
83 if local_addr.is_ipv4() {
84 socket2::Domain::IPV4
85 } else {
86 socket2::Domain::IPV6
87 },
88 socket2::Type::DGRAM,
89 Some(socket2::Protocol::UDP),
90 )?;
91 udp_sock.set_reuse_address(true)?;
92 #[cfg(not(windows))]
93 udp_sock.set_reuse_port(true)?;
94 udp_sock.set_nonblocking(true)?;
95 udp_sock.bind(&socket2::SockAddr::from(local_addr))?;
96 let udp_sock: std::net::UdpSocket = udp_sock.into();
97 udp_sock.try_into()
98}