Skip to content

Commit 1e9a001

Browse files
authored
io: Make peer_addr fallible (#755)
The `io::PeerAddr` trait assumes that the peer addr lookup is infallible, panicking the process when the call fails. In practice, however, this call can fail when a system is under load. This change modifies the `io::PeerAddr` trait to allow this lookup to fail. When it fails, we propagate this failure to the connection's task.
1 parent 8cb51ec commit 1e9a001

File tree

5 files changed

+37
-40
lines changed

5 files changed

+37
-40
lines changed

linkerd/io/src/boxed.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{internal::Io, AsyncRead, AsyncWrite, PeerAddr, Poll};
1+
use super::{internal::Io, AsyncRead, AsyncWrite, PeerAddr, Poll, Result};
22
use bytes::{Buf, BufMut};
33
use std::{mem::MaybeUninit, pin::Pin, task::Context};
44

@@ -15,7 +15,7 @@ impl BoxedIo {
1515
}
1616

1717
impl PeerAddr for BoxedIo {
18-
fn peer_addr(&self) -> std::net::SocketAddr {
18+
fn peer_addr(&self) -> Result<std::net::SocketAddr> {
1919
self.0.peer_addr()
2020
}
2121
}
@@ -106,8 +106,8 @@ mod tests {
106106
struct WriteBufDetector;
107107

108108
impl PeerAddr for WriteBufDetector {
109-
fn peer_addr(&self) -> std::net::SocketAddr {
110-
([0, 0, 0, 0], 0).into()
109+
fn peer_addr(&self) -> Result<std::net::SocketAddr> {
110+
Ok(([0, 0, 0, 0], 0).into())
111111
}
112112
}
113113

linkerd/io/src/lib.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,38 +16,38 @@ pub use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
1616
pub type Poll<T> = std::task::Poll<Result<T>>;
1717

1818
pub trait PeerAddr {
19-
fn peer_addr(&self) -> SocketAddr;
19+
fn peer_addr(&self) -> Result<SocketAddr>;
2020
}
2121

2222
impl PeerAddr for tokio::net::TcpStream {
23-
fn peer_addr(&self) -> SocketAddr {
24-
tokio::net::TcpStream::peer_addr(self).expect("TcpStream must have a peer address")
23+
fn peer_addr(&self) -> Result<SocketAddr> {
24+
tokio::net::TcpStream::peer_addr(self)
2525
}
2626
}
2727

2828
impl<T: PeerAddr> PeerAddr for tokio_rustls::client::TlsStream<T> {
29-
fn peer_addr(&self) -> SocketAddr {
29+
fn peer_addr(&self) -> Result<SocketAddr> {
3030
self.get_ref().0.peer_addr()
3131
}
3232
}
3333

3434
impl<T: PeerAddr> PeerAddr for tokio_rustls::server::TlsStream<T> {
35-
fn peer_addr(&self) -> SocketAddr {
35+
fn peer_addr(&self) -> Result<SocketAddr> {
3636
self.get_ref().0.peer_addr()
3737
}
3838
}
3939

4040
#[cfg(feature = "tokio-test")]
4141
impl PeerAddr for tokio_test::io::Mock {
42-
fn peer_addr(&self) -> SocketAddr {
43-
([0, 0, 0, 0], 0).into()
42+
fn peer_addr(&self) -> Result<SocketAddr> {
43+
Ok(([0, 0, 0, 0], 0).into())
4444
}
4545
}
4646

4747
#[cfg(feature = "tokio-test")]
4848
impl PeerAddr for tokio::io::DuplexStream {
49-
fn peer_addr(&self) -> SocketAddr {
50-
([0, 0, 0, 0], 0).into()
49+
fn peer_addr(&self) -> Result<SocketAddr> {
50+
Ok(([0, 0, 0, 0], 0).into())
5151
}
5252
}
5353
mod internal {

linkerd/io/src/prefixed.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
use crate::{internal::Io, PeerAddr, Poll};
22
use bytes::{Buf, BufMut, Bytes};
3+
use pin_project::pin_project;
34
use std::{cmp, io};
45
use std::{mem::MaybeUninit, pin::Pin, task::Context};
5-
use tokio::io::{AsyncRead, AsyncWrite};
6-
7-
use pin_project::pin_project;
6+
use tokio::io::{AsyncRead, AsyncWrite, Result};
87

98
/// A TcpStream where the initial reads will be served from `prefix`.
109
#[pin_project]
@@ -28,7 +27,7 @@ impl<S: AsyncRead + AsyncWrite> PrefixedIo<S> {
2827
}
2928

3029
impl<S: PeerAddr> PeerAddr for PrefixedIo<S> {
31-
fn peer_addr(&self) -> std::net::SocketAddr {
30+
fn peer_addr(&self) -> Result<std::net::SocketAddr> {
3231
self.io.peer_addr()
3332
}
3433
}

linkerd/io/src/sensor.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use pin_project::pin_project;
66
use std::mem::MaybeUninit;
77
use std::pin::Pin;
88
use std::task::Context;
9-
use tokio::io::{AsyncRead, AsyncWrite};
9+
use tokio::io::{AsyncRead, AsyncWrite, Result};
1010

1111
pub trait Sensor {
1212
fn record_read(&mut self, sz: usize);
@@ -106,7 +106,7 @@ impl<T: Io, S: Sensor + Send> Io for SensorIo<T, S> {
106106
}
107107

108108
impl<T: PeerAddr, S> PeerAddr for SensorIo<T, S> {
109-
fn peer_addr(&self) -> std::net::SocketAddr {
109+
fn peer_addr(&self) -> Result<std::net::SocketAddr> {
110110
self.io.peer_addr()
111111
}
112112
}

linkerd/proxy/http/src/detect.rs

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -158,21 +158,20 @@ where
158158
svc
159159
};
160160

161-
let (svc, closed) = SetClientHandle::new(io.peer_addr(), http1);
162-
163-
let mut conn = self
164-
.server
165-
.clone()
166-
.http1_only(true)
167-
.serve_connection(
168-
io,
169-
// Enable support for HTTP upgrades (CONNECT and websockets).
170-
HyperServerSvc::new(upgrade::Service::new(svc, self.drain.clone())),
171-
)
172-
.with_upgrades();
173-
161+
let mut server = self.server.clone();
174162
let drain = self.drain.clone();
175163
Box::pin(async move {
164+
let (svc, closed) = SetClientHandle::new(io.peer_addr()?, http1);
165+
166+
let mut conn = server
167+
.http1_only(true)
168+
.serve_connection(
169+
io,
170+
// Enable support for HTTP upgrades (CONNECT and websockets).
171+
HyperServerSvc::new(upgrade::Service::new(svc, drain.clone())),
172+
)
173+
.with_upgrades();
174+
176175
tokio::select! {
177176
res = &mut conn => {
178177
debug!(?res, "The client is shutting down the connection");
@@ -208,16 +207,15 @@ where
208207
svc
209208
};
210209

211-
let (svc, closed) = SetClientHandle::new(io.peer_addr(), h2);
212-
213-
let mut conn = self
214-
.server
215-
.clone()
216-
.http2_only(true)
217-
.serve_connection(io, HyperServerSvc::new(svc));
218-
210+
let mut server = self.server.clone();
219211
let drain = self.drain.clone();
220212
Box::pin(async move {
213+
let (svc, closed) = SetClientHandle::new(io.peer_addr()?, h2);
214+
215+
let mut conn = server
216+
.http2_only(true)
217+
.serve_connection(io, HyperServerSvc::new(svc));
218+
221219
tokio::select! {
222220
res = &mut conn => {
223221
debug!(?res, "The client is shutting down the connection");

0 commit comments

Comments
 (0)