mirror of https://github.com/rapiz1/rathole.git
fix: support IPv6 `local_address` for UDP
This commit is contained in:
parent
edbb5ce5c9
commit
7a7eef11bc
|
@ -5,9 +5,9 @@ use std::{
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use socket2::{SockRef, TcpKeepalive};
|
use socket2::{SockRef, TcpKeepalive};
|
||||||
use tokio::net::{TcpStream, ToSocketAddrs, UdpSocket};
|
use tokio::net::{lookup_host, TcpStream, ToSocketAddrs, UdpSocket};
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
// Tokio hesitates to expose this option...So we have to do it on our own :(
|
// Tokio hesitates to expose this option...So we have to do it on our own :(
|
||||||
|
@ -39,8 +39,17 @@ pub fn feature_not_compile(feature: &str) -> ! {
|
||||||
|
|
||||||
/// Create a UDP socket and connect to `addr`
|
/// Create a UDP socket and connect to `addr`
|
||||||
pub async fn udp_connect<A: ToSocketAddrs>(addr: A) -> Result<UdpSocket> {
|
pub async fn udp_connect<A: ToSocketAddrs>(addr: A) -> Result<UdpSocket> {
|
||||||
// FIXME: This only works for IPv4
|
let addr = lookup_host(addr)
|
||||||
let s = UdpSocket::bind("0.0.0.0:0").await?;
|
.await?
|
||||||
|
.next()
|
||||||
|
.ok_or(anyhow!("Failed to lookup the host"))?;
|
||||||
|
|
||||||
|
let bind_addr = match addr {
|
||||||
|
SocketAddr::V4(_) => "0.0.0.0:0",
|
||||||
|
SocketAddr::V6(_) => ":::0",
|
||||||
|
};
|
||||||
|
|
||||||
|
let s = UdpSocket::bind(bind_addr).await?;
|
||||||
s.connect(addr).await?;
|
s.connect(addr).await?;
|
||||||
Ok(s)
|
Ok(s)
|
||||||
}
|
}
|
||||||
|
@ -70,8 +79,12 @@ pub fn floor_to_pow_of_2(x: usize) -> usize {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use tokio::net::UdpSocket;
|
||||||
|
|
||||||
use crate::helper::{floor_to_pow_of_2, log2_floor};
|
use crate::helper::{floor_to_pow_of_2, log2_floor};
|
||||||
|
|
||||||
|
use super::udp_connect;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_log2_floor() {
|
fn test_log2_floor() {
|
||||||
let t = [
|
let t = [
|
||||||
|
@ -111,4 +124,29 @@ mod test {
|
||||||
assert_eq!(floor_to_pow_of_2(t.0), t.1);
|
assert_eq!(floor_to_pow_of_2(t.0), t.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_udp_connect() {
|
||||||
|
let hello = "HELLO";
|
||||||
|
|
||||||
|
let t = [("0.0.0.0:2333", "127.0.0.1:2333"), (":::2333", "::1:2333")];
|
||||||
|
for t in t {
|
||||||
|
let listener = UdpSocket::bind(t.0).await.unwrap();
|
||||||
|
|
||||||
|
let handle = tokio::spawn(async move {
|
||||||
|
let s = udp_connect(t.1).await.unwrap();
|
||||||
|
s.send(hello.as_bytes()).await.unwrap();
|
||||||
|
let mut buf = [0u8; 16];
|
||||||
|
let n = s.recv(&mut buf).await.unwrap();
|
||||||
|
assert_eq!(&buf[..n], hello.as_bytes());
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut buf = [0u8; 16];
|
||||||
|
let (n, addr) = listener.recv_from(&mut buf).await.unwrap();
|
||||||
|
assert_eq!(&buf[..n], hello.as_bytes());
|
||||||
|
listener.send_to(&buf[..n], addr).await.unwrap();
|
||||||
|
|
||||||
|
handle.await.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue