This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
zhangyang-libzt/pkg/crate/libzt/src/udp.rs

460 lines
14 KiB
Rust
Raw Normal View History

2021-05-24 21:29:57 -07:00
/*
* Copyright (c)2013-2021 ZeroTier, Inc.
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 2026-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2.0 of the Apache License.
*/
/****/
use std::convert::TryInto;
use std::ffi::{c_void, CString};
use std::io::{self, Error, ErrorKind};
use std::net::{/*Ipv4Addr, Ipv6Addr,*/ SocketAddr, ToSocketAddrs};
use std::os::raw::c_int;
use std::time::Duration;
//use std::cmp;
use crate::socket::Socket;
use crate::utils::*;
//----------------------------------------------------------------------------//
// UdpSocketImpl //
//----------------------------------------------------------------------------//
pub struct UdpSocketImpl {
inner: Socket,
}
impl UdpSocketImpl {
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<UdpSocketImpl> {
let addr = addr?;
let socket = Socket::new(addr, ZTS_SOCK_DGRAM as i32)?;
// TODO: Possibly set SO_REUSEADDR
//let (addrp, len) = addr.into_inner();
unsafe {
//zts_bsd_bind(*socket.as_inner(), addrp, len as _);
// TODO: Find a better way to split this address string
let full_str = addr.to_string();
let full_vec = full_str.split(":");
let lvec: Vec<&str> = full_vec.collect();
let addr_str = lvec[0];
let port = addr.port();
// TODO: Handle native error code, consider cvt?
// This is a false-positive by the linter
// See: https://github.com/rust-lang/rust/issues/78691
#[allow(temporary_cstring_as_ptr)]
zts_bind(
*socket.as_inner(),
CString::new(addr_str).unwrap().as_ptr(),
port,
);
}
Ok(UdpSocketImpl { inner: socket })
}
pub fn socket(&self) -> &Socket {
&self.inner
}
pub fn into_socket(self) -> Socket {
self.inner
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
sockname(|buf, len| unsafe { zts_bsd_getpeername(*self.inner.as_inner(), buf, len) })
}
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
sockname(|buf, len| unsafe { zts_bsd_getsockname(*self.inner.as_inner(), buf, len) })
}
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
self.inner.recv_from(buf)
}
pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
self.inner.peek_from(buf)
}
pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
/*
let len = cmp::min(buf.len(), <size_t>::MAX as usize) as size_t;
let (dstp, dstlen) = dst.into_inner();
let ret = cvt(unsafe {
zts_bsd_sendto(
*self.inner.as_inner(),
buf.as_ptr() as *const c_void,
len,
ZTS_MSG_NOSIGNAL,
dstp,
dstlen,
)
})?;
Ok(ret as usize)
*/
Ok(0)
}
pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.inner.set_timeout(dur, ZTS_SO_RCVTIMEO as i32)
}
pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.inner.set_timeout(dur, ZTS_SO_SNDTIMEO as i32)
}
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
self.inner.timeout(ZTS_SO_RCVTIMEO as i32)
}
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
self.inner.timeout(ZTS_SO_SNDTIMEO as i32)
}
pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
setsockopt(
&self.inner,
ZTS_SOL_SOCKET as i32,
ZTS_SO_BROADCAST as i32,
broadcast as c_int,
)
}
pub fn broadcast(&self) -> io::Result<bool> {
let raw: c_int = getsockopt(&self.inner, ZTS_SOL_SOCKET as i32, ZTS_SO_BROADCAST as i32)?;
Ok(raw != 0)
}
/*
pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
setsockopt(
&self.inner,
ZTS_IPPROTO_IP,
ZTS_IP_MULTICAST_LOOP,
multicast_loop_v4 as IpV4MultiCastType,
)
}
pub fn multicast_loop_v4(&self) -> io::Result<bool> {
let raw: IpV4MultiCastType = getsockopt(&self.inner, ZTS_IPPROTO_IP, ZTS_IP_MULTICAST_LOOP)?;
Ok(raw != 0)
}
pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
setsockopt(
&self.inner,
ZTS_IPPROTO_IP,
ZTS_IP_MULTICAST_TTL,
multicast_ttl_v4 as IpV4MultiCastType,
)
}
pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
let raw: IpV4MultiCastType = getsockopt(&self.inner, ZTS_IPPROTO_IP, ZTS_IP_MULTICAST_TTL)?;
Ok(raw as u32)
}
pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
setsockopt(&self.inner, ZTS_IPPROTO_IPV6, ZTS_IPV6_MULTICAST_LOOP, multicast_loop_v6 as c_int)
}
pub fn multicast_loop_v6(&self) -> io::Result<bool> {
let raw: c_int = getsockopt(&self.inner, ZTS_IPPROTO_IPV6, ZTS_IPV6_MULTICAST_LOOP)?;
Ok(raw != 0)
}
pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
let mreq = zts_ip_mreq {
imr_multiaddr: multiaddr.into_inner(),
imr_interface: interface.into_inner(),
};
setsockopt(&self.inner, ZTS_IPPROTO_IP, ZTS_IP_ADD_MEMBERSHIP, mreq)
}
pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
let mreq = zts_ipv6_mreq {
ipv6mr_multiaddr: *multiaddr.as_inner(),
ipv6mr_interface: to_ipv6mr_interface(interface),
};
setsockopt(&self.inner, ZTS_IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq)
}
pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
let mreq = zts_ip_mreq {
imr_multiaddr: multiaddr.into_inner(),
imr_interface: interface.into_inner(),
};
setsockopt(&self.inner, ZTS_IPPROTO_IP, ZTS_IP_DROP_MEMBERSHIP, mreq)
}
pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
let mreq = zts_ipv6_mreq {
ipv6mr_multiaddr: *multiaddr.as_inner(),
ipv6mr_interface: to_ipv6mr_interface(interface),
};
setsockopt(&self.inner, ZTS_IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq)
}
*/
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
setsockopt(
&self.inner,
ZTS_IPPROTO_IP as i32,
ZTS_IP_TTL as i32,
ttl as c_int,
)
}
pub fn ttl(&self) -> io::Result<u32> {
let raw: c_int = getsockopt(&self.inner, ZTS_IPPROTO_IP as i32, ZTS_IP_TTL as i32)?;
Ok(raw as u32)
}
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
self.inner.take_error()
}
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
self.inner.set_nonblocking(nonblocking)
}
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf)
}
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.peek(buf)
}
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
/*
let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
let ret = cvt(unsafe {
zts_bsd_send(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, ZTS_MSG_NOSIGNAL)
})?;
Ok(ret as usize)
*/
unsafe {
let raw = zts_bsd_write(
*self.inner.as_inner(),
buf.as_ptr() as *const c_void,
buf.len().try_into().unwrap(),
);
if raw >= 0 {
Ok(raw.try_into().unwrap())
} else {
Err(io::Error::from_raw_os_error(raw as i32))
}
}
}
pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> {
let addr = addr?;
//let (addrp, len) = addr?.into_inner();
unsafe {
let full_str = addr.to_string();
let full_vec = full_str.split(":");
let lvec: Vec<&str> = full_vec.collect();
let addr_str = lvec[0];
let port = addr.port();
let timeout_ms = 0;
// TODO: Handle native error code, consider cvt?
// This is a false-positive by the linter
// See: https://github.com/rust-lang/rust/issues/78691
#[allow(temporary_cstring_as_ptr)]
cvt(zts_connect(
*self.inner.as_inner(),
CString::new(addr_str).unwrap().as_ptr(),
port,
timeout_ms,
))?;
}
Ok(())
}
}
impl FromInner<Socket> for UdpSocketImpl {
fn from_inner(socket: Socket) -> UdpSocketImpl {
UdpSocketImpl { inner: socket }
}
}
/*
impl fmt::Debug for UdpSocketImpl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut res = f.debug_struct("UdpSocketImpl");
if let Ok(addr) = self.socket_addr() {
res.field("addr", &addr);
}
let name = if cfg!(windows) { "socket" } else { "fd" };
res.field(name, &self.inner.as_inner()).finish()
}
}
*/
//----------------------------------------------------------------------------//
// UdpSocket //
//----------------------------------------------------------------------------//
pub struct UdpSocket(UdpSocketImpl);
impl UdpSocket {
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
each_addr(addr, UdpSocketImpl::bind).map(UdpSocket)
}
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
self.0.recv_from(buf)
}
pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
self.0.peek_from(buf)
}
pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A) -> io::Result<usize> {
match addr.to_socket_addrs()?.next() {
Some(addr) => self.0.send_to(buf, &addr),
None => Err(Error::new(
ErrorKind::InvalidInput,
"No address to send data to",
)),
}
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
self.0.peer_addr()
}
pub fn local_addr(&self) -> io::Result<SocketAddr> {
self.0.socket_addr()
}
pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.0.set_read_timeout(dur)
}
pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.0.set_write_timeout(dur)
}
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
self.0.read_timeout()
}
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
self.0.write_timeout()
}
pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
self.0.set_broadcast(broadcast)
}
pub fn broadcast(&self) -> io::Result<bool> {
self.0.broadcast()
}
/*
pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
self.0.set_multicast_loop_v4(multicast_loop_v4)
}
pub fn multicast_loop_v4(&self) -> io::Result<bool> {
self.0.multicast_loop_v4()
}
pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
self.0.set_multicast_ttl_v4(multicast_ttl_v4)
}
pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
self.0.multicast_ttl_v4()
}
pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
self.0.set_multicast_loop_v6(multicast_loop_v6)
}
pub fn multicast_loop_v6(&self) -> io::Result<bool> {
self.0.multicast_loop_v6()
}
*/
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
self.0.set_ttl(ttl)
}
pub fn ttl(&self) -> io::Result<u32> {
self.0.ttl()
}
/*
pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
self.0.join_multicast_v4(multiaddr, interface)
}
pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
self.0.join_multicast_v6(multiaddr, interface)
}
pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
self.0.leave_multicast_v4(multiaddr, interface)
}
pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
self.0.leave_multicast_v6(multiaddr, interface)
}
*/
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
self.0.take_error()
}
pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
each_addr(addr, |addr| self.0.connect(addr))
}
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
self.0.send(buf)
}
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
self.0.recv(buf)
}
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
self.0.peek(buf)
}
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
self.0.set_nonblocking(nonblocking)
}
}
impl AsInner<UdpSocketImpl> for UdpSocket {
fn as_inner(&self) -> &UdpSocketImpl {
&self.0
}
}
impl FromInner<UdpSocketImpl> for UdpSocket {
fn from_inner(inner: UdpSocketImpl) -> UdpSocket {
UdpSocket(inner)
}
}
impl IntoInner<UdpSocketImpl> for UdpSocket {
fn into_inner(self) -> UdpSocketImpl {
self.0
}
}
/*
impl fmt::Debug for UdpSocket {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
*/