From 022b8542361518cab469136f9e6571cf2b63fc6b Mon Sep 17 00:00:00 2001 From: frehberg Date: Thu, 16 Feb 2023 13:52:11 +0100 Subject: [PATCH] #68617: prototype UdpSocket::send_to_vectored() --- library/std/Cargo.toml | 1 + library/std/src/net/udp.rs | 20 +++++++++++++++++++- library/std/src/sys/unix/l4re.rs | 4 ++++ library/std/src/sys_common/net.rs | 20 ++++++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 349cd91c89e69..b1fd67a20cc25 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -56,6 +56,7 @@ backtrace = [ 'miniz_oxide/rustc-dep-of-std', ] gimli-symbolize = [] +udp_sendmsg = [] panic-unwind = ["panic_unwind"] profiler = ["profiler_builtins"] diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs index 864e1b0f3450a..0ea174e209fbd 100644 --- a/library/std/src/net/udp.rs +++ b/library/std/src/net/udp.rs @@ -2,12 +2,13 @@ mod tests; use crate::fmt; -use crate::io::{self, ErrorKind}; +use crate::io::{self, ErrorKind, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs}; use crate::sys_common::net as net_imp; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::Duration; + /// A UDP socket. /// /// After creating a `UdpSocket` by [`bind`]ing it to a socket address, data can be @@ -181,6 +182,20 @@ impl UdpSocket { } } + /// Sends data on the socket to the given address. On success, returns the + /// number of bytes written. + /// + /// + #[stable(feature = "udp_sendmsg", since = "1.70.0")] + pub fn send_to_vectored(&self, bufs: &mut [IoSliceMut<'_>], addr: A) -> io::Result { + match addr.to_socket_addrs()?.next() { + Some(addr) => self.0.send_to_vectored(bufs, &addr), + None => { + Err(io::const_io_error!(ErrorKind::InvalidInput, "no addresses to send data to")) + } + } + } + /// Returns the socket address of the remote peer this socket was connected to. /// /// # Examples @@ -667,6 +682,9 @@ impl UdpSocket { self.0.send(buf) } + /// + /// + /// Receives a single datagram message on the socket from the remote address to /// which it is connected. On success, returns the number of bytes read. /// diff --git a/library/std/src/sys/unix/l4re.rs b/library/std/src/sys/unix/l4re.rs index 9967588939ac9..a96d4632e9770 100644 --- a/library/std/src/sys/unix/l4re.rs +++ b/library/std/src/sys/unix/l4re.rs @@ -399,6 +399,10 @@ pub mod net { unimpl!(); } + // pub fn send_to_vectored(&self, _: &mut [IoSliceMut<'_>], _: &SocketAddr) -> io::Result { + // unimpl!(); + // } + pub fn duplicate(&self) -> io::Result { unimpl!(); } diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index 2c38dfecf9734..2eed015b91ca7 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -14,6 +14,10 @@ use crate::sys::net::{cvt, cvt_gai, cvt_r, init, wrlen_t, Socket}; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::Duration; +use libc; + +type IovLen = usize; + use crate::ffi::{c_int, c_void}; cfg_if::cfg_if! { @@ -553,6 +557,22 @@ impl UdpSocket { Ok(ret as usize) } + pub fn send_to_vectored(&self, bufs: &mut [IoSliceMut<'_>], dst: &SocketAddr) -> io::Result { + let (dst, dstlen) = dst.into_inner(); + let mut msg: libc::msghdr = unsafe { mem::zeroed() }; + // Safety: we're creating a `*mut` pointer from a reference, which is UB + // once actually used. However the OS should not write to it in the + // `sendmsg` system call. + msg.msg_name = dst.as_ptr() as *mut _; + msg.msg_namelen = dstlen; + // Safety: Same as above about `*const` -> `*mut`. + msg.msg_iov = bufs.as_ptr() as *mut _; + msg.msg_iovlen = cmp::min(bufs.len(), IovLen::MAX as usize) as IovLen; + // TODO(fr) set flags + let ret = self.inner.send_msg(&mut msg)?; + Ok(ret as usize) + } + pub fn duplicate(&self) -> io::Result { self.inner.duplicate().map(|s| UdpSocket { inner: s }) }