Skip to content

Commit

Permalink
transports/quic: remove mutex in InAddr
Browse files Browse the repository at this point in the history
  • Loading branch information
elenaf9 committed Jul 10, 2022
1 parent 0e797cf commit ef7b823
Showing 1 changed file with 16 additions and 37 deletions.
53 changes: 16 additions & 37 deletions transports/quic/src/in_addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,42 @@ use if_watch::{IfEvent, IfWatcher};

use futures::{
future::{BoxFuture, FutureExt},
lock::Mutex,
stream::{Stream, StreamExt},
stream::Stream,
};

use std::{
io::Result,
net::IpAddr,
ops::DerefMut,
pin::Pin,
sync::Arc,
task::{Context, Poll},
};

/// Watches for interface changes.
#[derive(Clone, Debug)]
pub(crate) struct InAddr(Arc<Mutex<InAddrInner>>);
#[derive(Debug)]
pub enum InAddr {
/// The socket accepts connections on a single interface.
One { ip: Option<IpAddr> },
/// The socket accepts connections on all interfaces.
Any { if_watch: Box<IfWatch> },
}

impl InAddr {
/// If ip is specified then only one `IfEvent::Up` with IpNet(ip)/32 will be generated.
/// If ip is unspecified then `IfEvent::Up/Down` events will be generated for all interfaces.
pub(crate) fn new(ip: IpAddr) -> Self {
let inner = if ip.is_unspecified() {
pub fn new(ip: IpAddr) -> Self {
if ip.is_unspecified() {
let watcher = IfWatch::Pending(IfWatcher::new().boxed());
InAddrInner::Any {
InAddr::Any {
if_watch: Box::new(watcher),
}
} else {
InAddrInner::One { ip: Some(ip) }
};
Self(Arc::new(Mutex::new(inner)))
InAddr::One { ip: Some(ip) }
}
}
}

/// The listening addresses of a `UdpSocket`.
#[derive(Debug)]
enum InAddrInner {
/// The socket accepts connections on a single interface.
One { ip: Option<IpAddr> },
/// The socket accepts connections on all interfaces.
Any { if_watch: Box<IfWatch> },
}

enum IfWatch {
pub enum IfWatch {
Pending(BoxFuture<'static, std::io::Result<IfWatcher>>),
Ready(Box<IfWatcher>),
}
Expand All @@ -57,35 +50,21 @@ impl std::fmt::Debug for IfWatch {
}
}
}

impl Stream for InAddr {
type Item = Result<IfEvent>;

fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
let me = Pin::into_inner(self);
let mut lock = me.0.lock();
let mut guard = futures::ready!(lock.poll_unpin(cx));
let inner = &mut *guard;

inner.poll_next_unpin(cx)
}
}

impl Stream for InAddrInner {
type Item = Result<IfEvent>;

fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
let me = Pin::into_inner(self);
loop {
match me {
// If the listener is bound to a single interface, make sure the
// address is reported once.
InAddrInner::One { ip } => {
InAddr::One { ip } => {
if let Some(ip) = ip.take() {
return Poll::Ready(Some(Ok(IfEvent::Up(ip.into()))));
}
}
InAddrInner::Any { if_watch } => {
InAddr::Any { if_watch } => {
match if_watch.deref_mut() {
// If we listen on all interfaces, wait for `if-watch` to be ready.
IfWatch::Pending(f) => match futures::ready!(f.poll_unpin(cx)) {
Expand Down

0 comments on commit ef7b823

Please sign in to comment.