mirror of
https://github.com/tokio-rs/tokio.git
synced 2025-09-28 12:10:37 +00:00
net: add UdpSocket::peek_sender()
(#5520)
This commit is contained in:
parent
f177aad6e4
commit
d459a93453
@ -109,7 +109,7 @@ num_cpus = { version = "1.8.0", optional = true }
|
|||||||
parking_lot = { version = "0.12.0", optional = true }
|
parking_lot = { version = "0.12.0", optional = true }
|
||||||
|
|
||||||
[target.'cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))'.dependencies]
|
[target.'cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))'.dependencies]
|
||||||
socket2 = { version = "0.4.4", optional = true, features = [ "all" ] }
|
socket2 = { version = "0.4.9", optional = true, features = [ "all" ] }
|
||||||
|
|
||||||
# Currently unstable. The API exposed by these features may be broken at any time.
|
# Currently unstable. The API exposed by these features may be broken at any time.
|
||||||
# Requires `--cfg tokio_unstable` to enable.
|
# Requires `--cfg tokio_unstable` to enable.
|
||||||
@ -146,7 +146,7 @@ mockall = "0.11.1"
|
|||||||
async-stream = "0.3"
|
async-stream = "0.3"
|
||||||
|
|
||||||
[target.'cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))'.dev-dependencies]
|
[target.'cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))'.dev-dependencies]
|
||||||
socket2 = "0.4"
|
socket2 = "0.4.9"
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
|
|
||||||
[target.'cfg(not(all(any(target_arch = "wasm32", target_arch = "wasm64"), target_os = "unknown")))'.dev-dependencies]
|
[target.'cfg(not(all(any(target_arch = "wasm32", target_arch = "wasm64"), target_os = "unknown")))'.dev-dependencies]
|
||||||
|
@ -954,6 +954,15 @@ impl UdpSocket {
|
|||||||
/// When there is no pending data, `Err(io::ErrorKind::WouldBlock)` is
|
/// When there is no pending data, `Err(io::ErrorKind::WouldBlock)` is
|
||||||
/// returned. This function is usually paired with `readable()`.
|
/// returned. This function is usually paired with `readable()`.
|
||||||
///
|
///
|
||||||
|
/// # Notes
|
||||||
|
/// Note that the socket address **cannot** be implicitly trusted, because it is relatively
|
||||||
|
/// trivial to send a UDP datagram with a spoofed origin in a [packet injection attack].
|
||||||
|
/// Because UDP is stateless and does not validate the origin of a packet,
|
||||||
|
/// the attacker does not need to be able to intercept traffic in order to interfere.
|
||||||
|
/// It is important to be aware of this when designing your application-level protocol.
|
||||||
|
///
|
||||||
|
/// [packet injection attack]: https://en.wikipedia.org/wiki/Packet_injection
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
@ -1177,6 +1186,15 @@ impl UdpSocket {
|
|||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
/// Note that the socket address **cannot** be implicitly trusted, because it is relatively
|
||||||
|
/// trivial to send a UDP datagram with a spoofed origin in a [packet injection attack].
|
||||||
|
/// Because UDP is stateless and does not validate the origin of a packet,
|
||||||
|
/// the attacker does not need to be able to intercept traffic in order to interfere.
|
||||||
|
/// It is important to be aware of this when designing your application-level protocol.
|
||||||
|
///
|
||||||
|
/// [packet injection attack]: https://en.wikipedia.org/wiki/Packet_injection
|
||||||
pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||||
self.io
|
self.io
|
||||||
.registration()
|
.registration()
|
||||||
@ -1201,6 +1219,15 @@ impl UdpSocket {
|
|||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// This function may encounter any standard I/O error except `WouldBlock`.
|
/// This function may encounter any standard I/O error except `WouldBlock`.
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
/// Note that the socket address **cannot** be implicitly trusted, because it is relatively
|
||||||
|
/// trivial to send a UDP datagram with a spoofed origin in a [packet injection attack].
|
||||||
|
/// Because UDP is stateless and does not validate the origin of a packet,
|
||||||
|
/// the attacker does not need to be able to intercept traffic in order to interfere.
|
||||||
|
/// It is important to be aware of this when designing your application-level protocol.
|
||||||
|
///
|
||||||
|
/// [packet injection attack]: https://en.wikipedia.org/wiki/Packet_injection
|
||||||
pub fn poll_recv_from(
|
pub fn poll_recv_from(
|
||||||
&self,
|
&self,
|
||||||
cx: &mut Context<'_>,
|
cx: &mut Context<'_>,
|
||||||
@ -1233,6 +1260,16 @@ impl UdpSocket {
|
|||||||
/// When there is no pending data, `Err(io::ErrorKind::WouldBlock)` is
|
/// When there is no pending data, `Err(io::ErrorKind::WouldBlock)` is
|
||||||
/// returned. This function is usually paired with `readable()`.
|
/// returned. This function is usually paired with `readable()`.
|
||||||
///
|
///
|
||||||
|
/// # Notes
|
||||||
|
///
|
||||||
|
/// Note that the socket address **cannot** be implicitly trusted, because it is relatively
|
||||||
|
/// trivial to send a UDP datagram with a spoofed origin in a [packet injection attack].
|
||||||
|
/// Because UDP is stateless and does not validate the origin of a packet,
|
||||||
|
/// the attacker does not need to be able to intercept traffic in order to interfere.
|
||||||
|
/// It is important to be aware of this when designing your application-level protocol.
|
||||||
|
///
|
||||||
|
/// [packet injection attack]: https://en.wikipedia.org/wiki/Packet_injection
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
@ -1367,6 +1404,17 @@ impl UdpSocket {
|
|||||||
/// Make sure to always use a sufficiently large buffer to hold the
|
/// Make sure to always use a sufficiently large buffer to hold the
|
||||||
/// maximum UDP packet size, which can be up to 65536 bytes in size.
|
/// maximum UDP packet size, which can be up to 65536 bytes in size.
|
||||||
///
|
///
|
||||||
|
/// MacOS will return an error if you pass a zero-sized buffer.
|
||||||
|
///
|
||||||
|
/// If you're merely interested in learning the sender of the data at the head of the queue,
|
||||||
|
/// try [`peek_sender`].
|
||||||
|
///
|
||||||
|
/// Note that the socket address **cannot** be implicitly trusted, because it is relatively
|
||||||
|
/// trivial to send a UDP datagram with a spoofed origin in a [packet injection attack].
|
||||||
|
/// Because UDP is stateless and does not validate the origin of a packet,
|
||||||
|
/// the attacker does not need to be able to intercept traffic in order to interfere.
|
||||||
|
/// It is important to be aware of this when designing your application-level protocol.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
@ -1385,6 +1433,9 @@ impl UdpSocket {
|
|||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// [`peek_sender`]: method@Self::peek_sender
|
||||||
|
/// [packet injection attack]: https://en.wikipedia.org/wiki/Packet_injection
|
||||||
pub async fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
pub async fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||||
self.io
|
self.io
|
||||||
.registration()
|
.registration()
|
||||||
@ -1393,7 +1444,7 @@ impl UdpSocket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Receives data from the socket, without removing it from the input queue.
|
/// Receives data from the socket, without removing it from the input queue.
|
||||||
/// On success, returns the number of bytes read.
|
/// On success, returns the sending address of the datagram.
|
||||||
///
|
///
|
||||||
/// # Notes
|
/// # Notes
|
||||||
///
|
///
|
||||||
@ -1407,6 +1458,17 @@ impl UdpSocket {
|
|||||||
/// Make sure to always use a sufficiently large buffer to hold the
|
/// Make sure to always use a sufficiently large buffer to hold the
|
||||||
/// maximum UDP packet size, which can be up to 65536 bytes in size.
|
/// maximum UDP packet size, which can be up to 65536 bytes in size.
|
||||||
///
|
///
|
||||||
|
/// MacOS will return an error if you pass a zero-sized buffer.
|
||||||
|
///
|
||||||
|
/// If you're merely interested in learning the sender of the data at the head of the queue,
|
||||||
|
/// try [`poll_peek_sender`].
|
||||||
|
///
|
||||||
|
/// Note that the socket address **cannot** be implicitly trusted, because it is relatively
|
||||||
|
/// trivial to send a UDP datagram with a spoofed origin in a [packet injection attack].
|
||||||
|
/// Because UDP is stateless and does not validate the origin of a packet,
|
||||||
|
/// the attacker does not need to be able to intercept traffic in order to interfere.
|
||||||
|
/// It is important to be aware of this when designing your application-level protocol.
|
||||||
|
///
|
||||||
/// # Return value
|
/// # Return value
|
||||||
///
|
///
|
||||||
/// The function returns:
|
/// The function returns:
|
||||||
@ -1418,6 +1480,9 @@ impl UdpSocket {
|
|||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// This function may encounter any standard I/O error except `WouldBlock`.
|
/// This function may encounter any standard I/O error except `WouldBlock`.
|
||||||
|
///
|
||||||
|
/// [`poll_peek_sender`]: method@Self::poll_peek_sender
|
||||||
|
/// [packet injection attack]: https://en.wikipedia.org/wiki/Packet_injection
|
||||||
pub fn poll_peek_from(
|
pub fn poll_peek_from(
|
||||||
&self,
|
&self,
|
||||||
cx: &mut Context<'_>,
|
cx: &mut Context<'_>,
|
||||||
@ -1440,6 +1505,117 @@ impl UdpSocket {
|
|||||||
Poll::Ready(Ok(addr))
|
Poll::Ready(Ok(addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tries to receive data on the socket without removing it from the input queue.
|
||||||
|
/// On success, returns the number of bytes read and the sending address of the
|
||||||
|
/// datagram.
|
||||||
|
///
|
||||||
|
/// When there is no pending data, `Err(io::ErrorKind::WouldBlock)` is
|
||||||
|
/// returned. This function is usually paired with `readable()`.
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
///
|
||||||
|
/// On Windows, if the data is larger than the buffer specified, the buffer
|
||||||
|
/// is filled with the first part of the data, and peek returns the error
|
||||||
|
/// WSAEMSGSIZE(10040). The excess data is lost.
|
||||||
|
/// Make sure to always use a sufficiently large buffer to hold the
|
||||||
|
/// maximum UDP packet size, which can be up to 65536 bytes in size.
|
||||||
|
///
|
||||||
|
/// MacOS will return an error if you pass a zero-sized buffer.
|
||||||
|
///
|
||||||
|
/// If you're merely interested in learning the sender of the data at the head of the queue,
|
||||||
|
/// try [`try_peek_sender`].
|
||||||
|
///
|
||||||
|
/// Note that the socket address **cannot** be implicitly trusted, because it is relatively
|
||||||
|
/// trivial to send a UDP datagram with a spoofed origin in a [packet injection attack].
|
||||||
|
/// Because UDP is stateless and does not validate the origin of a packet,
|
||||||
|
/// the attacker does not need to be able to intercept traffic in order to interfere.
|
||||||
|
/// It is important to be aware of this when designing your application-level protocol.
|
||||||
|
///
|
||||||
|
/// [`try_peek_sender`]: method@Self::try_peek_sender
|
||||||
|
/// [packet injection attack]: https://en.wikipedia.org/wiki/Packet_injection
|
||||||
|
pub fn try_peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||||
|
self.io
|
||||||
|
.registration()
|
||||||
|
.try_io(Interest::READABLE, || self.io.peek_from(buf))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve the sender of the data at the head of the input queue, waiting if empty.
|
||||||
|
///
|
||||||
|
/// This is equivalent to calling [`peek_from`] with a zero-sized buffer,
|
||||||
|
/// but suppresses the `WSAEMSGSIZE` error on Windows and the "invalid argument" error on macOS.
|
||||||
|
///
|
||||||
|
/// Note that the socket address **cannot** be implicitly trusted, because it is relatively
|
||||||
|
/// trivial to send a UDP datagram with a spoofed origin in a [packet injection attack].
|
||||||
|
/// Because UDP is stateless and does not validate the origin of a packet,
|
||||||
|
/// the attacker does not need to be able to intercept traffic in order to interfere.
|
||||||
|
/// It is important to be aware of this when designing your application-level protocol.
|
||||||
|
///
|
||||||
|
/// [`peek_from`]: method@Self::peek_from
|
||||||
|
/// [packet injection attack]: https://en.wikipedia.org/wiki/Packet_injection
|
||||||
|
pub async fn peek_sender(&self) -> io::Result<SocketAddr> {
|
||||||
|
self.io
|
||||||
|
.registration()
|
||||||
|
.async_io(Interest::READABLE, || self.peek_sender_inner())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve the sender of the data at the head of the input queue,
|
||||||
|
/// scheduling a wakeup if empty.
|
||||||
|
///
|
||||||
|
/// This is equivalent to calling [`poll_peek_from`] with a zero-sized buffer,
|
||||||
|
/// but suppresses the `WSAEMSGSIZE` error on Windows and the "invalid argument" error on macOS.
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
///
|
||||||
|
/// Note that on multiple calls to a `poll_*` method in the recv direction, only the
|
||||||
|
/// `Waker` from the `Context` passed to the most recent call will be scheduled to
|
||||||
|
/// receive a wakeup.
|
||||||
|
///
|
||||||
|
/// Note that the socket address **cannot** be implicitly trusted, because it is relatively
|
||||||
|
/// trivial to send a UDP datagram with a spoofed origin in a [packet injection attack].
|
||||||
|
/// Because UDP is stateless and does not validate the origin of a packet,
|
||||||
|
/// the attacker does not need to be able to intercept traffic in order to interfere.
|
||||||
|
/// It is important to be aware of this when designing your application-level protocol.
|
||||||
|
///
|
||||||
|
/// [`poll_peek_from`]: method@Self::poll_peek_from
|
||||||
|
/// [packet injection attack]: https://en.wikipedia.org/wiki/Packet_injection
|
||||||
|
pub fn poll_peek_sender(&self, cx: &mut Context<'_>) -> Poll<io::Result<SocketAddr>> {
|
||||||
|
self.io
|
||||||
|
.registration()
|
||||||
|
.poll_read_io(cx, || self.peek_sender_inner())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Try to retrieve the sender of the data at the head of the input queue.
|
||||||
|
///
|
||||||
|
/// When there is no pending data, `Err(io::ErrorKind::WouldBlock)` is
|
||||||
|
/// returned. This function is usually paired with `readable()`.
|
||||||
|
///
|
||||||
|
/// Note that the socket address **cannot** be implicitly trusted, because it is relatively
|
||||||
|
/// trivial to send a UDP datagram with a spoofed origin in a [packet injection attack].
|
||||||
|
/// Because UDP is stateless and does not validate the origin of a packet,
|
||||||
|
/// the attacker does not need to be able to intercept traffic in order to interfere.
|
||||||
|
/// It is important to be aware of this when designing your application-level protocol.
|
||||||
|
///
|
||||||
|
/// [packet injection attack]: https://en.wikipedia.org/wiki/Packet_injection
|
||||||
|
pub fn try_peek_sender(&self) -> io::Result<SocketAddr> {
|
||||||
|
self.io
|
||||||
|
.registration()
|
||||||
|
.try_io(Interest::READABLE, || self.peek_sender_inner())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn peek_sender_inner(&self) -> io::Result<SocketAddr> {
|
||||||
|
self.io.try_io(|| {
|
||||||
|
self.as_socket()
|
||||||
|
.peek_sender()?
|
||||||
|
// May be `None` if the platform doesn't populate the sender for some reason.
|
||||||
|
// In testing, that only occurred on macOS if you pass a zero-sized buffer,
|
||||||
|
// but the implementation of `Socket::peek_sender()` covers that.
|
||||||
|
.as_socket()
|
||||||
|
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "sender not available"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the value of the `SO_BROADCAST` option for this socket.
|
/// Gets the value of the `SO_BROADCAST` option for this socket.
|
||||||
///
|
///
|
||||||
/// For more information about this option, see [`set_broadcast`].
|
/// For more information about this option, see [`set_broadcast`].
|
||||||
|
@ -106,6 +106,45 @@ async fn send_to_peek_from() -> std::io::Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn send_to_try_peek_from() -> std::io::Result<()> {
|
||||||
|
let sender = UdpSocket::bind("127.0.0.1:0").await?;
|
||||||
|
let receiver = UdpSocket::bind("127.0.0.1:0").await?;
|
||||||
|
|
||||||
|
let receiver_addr = receiver.local_addr()?;
|
||||||
|
poll_fn(|cx| sender.poll_send_to(cx, MSG, receiver_addr)).await?;
|
||||||
|
|
||||||
|
// peek
|
||||||
|
let mut recv_buf = [0u8; 32];
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match receiver.try_peek_from(&mut recv_buf) {
|
||||||
|
Ok((n, addr)) => {
|
||||||
|
assert_eq!(&recv_buf[..n], MSG);
|
||||||
|
assert_eq!(addr, sender.local_addr()?);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
|
||||||
|
receiver.readable().await?;
|
||||||
|
}
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// peek
|
||||||
|
let mut recv_buf = [0u8; 32];
|
||||||
|
let (n, addr) = receiver.peek_from(&mut recv_buf).await?;
|
||||||
|
assert_eq!(&recv_buf[..n], MSG);
|
||||||
|
assert_eq!(addr, sender.local_addr()?);
|
||||||
|
|
||||||
|
let mut recv_buf = [0u8; 32];
|
||||||
|
let (n, addr) = receiver.recv_from(&mut recv_buf).await?;
|
||||||
|
assert_eq!(&recv_buf[..n], MSG);
|
||||||
|
assert_eq!(addr, sender.local_addr()?);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_to_peek_from_poll() -> std::io::Result<()> {
|
async fn send_to_peek_from_poll() -> std::io::Result<()> {
|
||||||
let sender = UdpSocket::bind("127.0.0.1:0").await?;
|
let sender = UdpSocket::bind("127.0.0.1:0").await?;
|
||||||
@ -134,6 +173,92 @@ async fn send_to_peek_from_poll() -> std::io::Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn peek_sender() -> std::io::Result<()> {
|
||||||
|
let sender = UdpSocket::bind("127.0.0.1:0").await?;
|
||||||
|
let receiver = UdpSocket::bind("127.0.0.1:0").await?;
|
||||||
|
|
||||||
|
let sender_addr = sender.local_addr()?;
|
||||||
|
let receiver_addr = receiver.local_addr()?;
|
||||||
|
|
||||||
|
let msg = b"Hello, world!";
|
||||||
|
sender.send_to(msg, receiver_addr).await?;
|
||||||
|
|
||||||
|
let peeked_sender = receiver.peek_sender().await?;
|
||||||
|
assert_eq!(peeked_sender, sender_addr);
|
||||||
|
|
||||||
|
// Assert that `peek_sender()` returns the right sender but
|
||||||
|
// doesn't remove from the receive queue.
|
||||||
|
let mut recv_buf = [0u8; 32];
|
||||||
|
let (read, received_sender) = receiver.recv_from(&mut recv_buf).await?;
|
||||||
|
|
||||||
|
assert_eq!(&recv_buf[..read], msg);
|
||||||
|
assert_eq!(received_sender, peeked_sender);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn poll_peek_sender() -> std::io::Result<()> {
|
||||||
|
let sender = UdpSocket::bind("127.0.0.1:0").await?;
|
||||||
|
let receiver = UdpSocket::bind("127.0.0.1:0").await?;
|
||||||
|
|
||||||
|
let sender_addr = sender.local_addr()?;
|
||||||
|
let receiver_addr = receiver.local_addr()?;
|
||||||
|
|
||||||
|
let msg = b"Hello, world!";
|
||||||
|
poll_fn(|cx| sender.poll_send_to(cx, msg, receiver_addr)).await?;
|
||||||
|
|
||||||
|
let peeked_sender = poll_fn(|cx| receiver.poll_peek_sender(cx)).await?;
|
||||||
|
assert_eq!(peeked_sender, sender_addr);
|
||||||
|
|
||||||
|
// Assert that `poll_peek_sender()` returns the right sender but
|
||||||
|
// doesn't remove from the receive queue.
|
||||||
|
let mut recv_buf = [0u8; 32];
|
||||||
|
let mut read = ReadBuf::new(&mut recv_buf);
|
||||||
|
let received_sender = poll_fn(|cx| receiver.poll_recv_from(cx, &mut read)).await?;
|
||||||
|
|
||||||
|
assert_eq!(read.filled(), msg);
|
||||||
|
assert_eq!(received_sender, peeked_sender);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn try_peek_sender() -> std::io::Result<()> {
|
||||||
|
let sender = UdpSocket::bind("127.0.0.1:0").await?;
|
||||||
|
let receiver = UdpSocket::bind("127.0.0.1:0").await?;
|
||||||
|
|
||||||
|
let sender_addr = sender.local_addr()?;
|
||||||
|
let receiver_addr = receiver.local_addr()?;
|
||||||
|
|
||||||
|
let msg = b"Hello, world!";
|
||||||
|
sender.send_to(msg, receiver_addr).await?;
|
||||||
|
|
||||||
|
let peeked_sender = loop {
|
||||||
|
match receiver.try_peek_sender() {
|
||||||
|
Ok(peeked_sender) => break peeked_sender,
|
||||||
|
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
|
||||||
|
receiver.readable().await?;
|
||||||
|
}
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(peeked_sender, sender_addr);
|
||||||
|
|
||||||
|
// Assert that `try_peek_sender()` returns the right sender but
|
||||||
|
// didn't remove from the receive queue.
|
||||||
|
let mut recv_buf = [0u8; 32];
|
||||||
|
// We already peeked the sender so there must be data in the receive queue.
|
||||||
|
let (read, received_sender) = receiver.try_recv_from(&mut recv_buf).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(&recv_buf[..read], msg);
|
||||||
|
assert_eq!(received_sender, peeked_sender);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn split() -> std::io::Result<()> {
|
async fn split() -> std::io::Result<()> {
|
||||||
let socket = UdpSocket::bind("127.0.0.1:0").await?;
|
let socket = UdpSocket::bind("127.0.0.1:0").await?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user