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}