Skip to content

Commit 68ce91e

Browse files
committed
Make some things infallible
1 parent 4741be8 commit 68ce91e

File tree

8 files changed

+77
-57
lines changed

8 files changed

+77
-57
lines changed

iroh-relay/src/server/clients.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl Clients {
7171
/// peer is gone from the network.
7272
///
7373
/// Must be passed a matching connection_id.
74-
pub(super) async fn unregister<'a>(&self, connection_id: u64, node_id: NodeId) {
74+
pub(super) async fn unregister(&self, connection_id: u64, node_id: NodeId) {
7575
trace!(
7676
node_id = node_id.fmt_short(),
7777
connection_id,

iroh/examples/dht_discovery.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ async fn chat_server(args: Args) -> anyhow::Result<()> {
8888
};
8989
tokio::spawn(async move {
9090
let connection = connecting.await?;
91-
let remote_node_id = connection.remote_node_id()?;
91+
let remote_node_id = connection.remote_node_id();
9292
println!("got connection from {}", remote_node_id);
9393
// just leave the tasks hanging. this is just an example.
9494
let (mut writer, mut reader) = connection.accept_bi().await?;

iroh/examples/echo.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl ProtocolHandler for Echo {
7777
// Wait for the connection to be fully established.
7878
let connection = connecting.await?;
7979
// We can get the remote's node id from the connection.
80-
let node_id = connection.remote_node_id()?;
80+
let node_id = connection.remote_node_id();
8181
println!("accepted connection from {node_id}");
8282

8383
// Our protocol is a simple request-response protocol, so we expect the

iroh/examples/listen-unreliable.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ async fn main() -> anyhow::Result<()> {
5858
// accept incoming connections, returns a normal QUIC connection
5959

6060
while let Some(incoming) = endpoint.accept().await {
61-
let mut connecting = match incoming.accept() {
61+
let connecting = match incoming.accept() {
6262
Ok(connecting) => connecting,
6363
Err(err) => {
6464
warn!("incoming connection failed: {err:#}");
@@ -67,9 +67,9 @@ async fn main() -> anyhow::Result<()> {
6767
continue;
6868
}
6969
};
70-
let alpn = connecting.alpn().await?;
7170
let conn = connecting.await?;
72-
let node_id = conn.remote_node_id()?;
71+
let alpn = conn.alpn();
72+
let node_id = conn.remote_node_id();
7373
info!(
7474
"new (unreliable) connection from {node_id} with ALPN {} (coming from {})",
7575
String::from_utf8_lossy(&alpn),

iroh/examples/listen.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ async fn main() -> anyhow::Result<()> {
5959
);
6060
// accept incoming connections, returns a normal QUIC connection
6161
while let Some(incoming) = endpoint.accept().await {
62-
let mut connecting = match incoming.accept() {
62+
let connecting = match incoming.accept() {
6363
Ok(connecting) => connecting,
6464
Err(err) => {
6565
warn!("incoming connection failed: {err:#}");
@@ -68,9 +68,9 @@ async fn main() -> anyhow::Result<()> {
6868
continue;
6969
}
7070
};
71-
let alpn = connecting.alpn().await?;
7271
let conn = connecting.await?;
73-
let node_id = conn.remote_node_id()?;
72+
let alpn = conn.alpn();
73+
let node_id = conn.remote_node_id();
7474
info!(
7575
"new connection from {node_id} with ALPN {} (coming from {})",
7676
String::from_utf8_lossy(&alpn),

iroh/examples/search.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ impl ProtocolHandler for BlobSearch {
134134
// Wait for the connection to be fully established.
135135
let connection = connecting.await?;
136136
// We can get the remote's node id from the connection.
137-
let node_id = connection.remote_node_id()?;
137+
let node_id = connection.remote_node_id();
138138
println!("accepted connection from {node_id}");
139139

140140
// Our protocol is a simple request-response protocol, so we expect the

iroh/examples/transfer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ async fn provide(size: u64, relay_url: Option<String>, relay_only: bool) -> anyh
121121
}
122122
};
123123
let conn = connecting.await?;
124-
let node_id = conn.remote_node_id()?;
124+
let node_id = conn.remote_node_id();
125125
info!(
126126
"new connection from {node_id} with ALPN {} (coming from {})",
127127
String::from_utf8_lossy(TRANSFER_ALPN),

iroh/src/endpoint.rs

Lines changed: 66 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,16 +1257,24 @@ impl Connecting {
12571257
}
12581258

12591259
/// Extracts the ALPN protocol from the peer's handshake data.
1260-
// Note, we could totally provide this method to be on a Connection as well. But we'd
1261-
// need to wrap Connection too.
1262-
pub async fn alpn(&mut self) -> Result<Vec<u8>> {
1260+
pub async fn alpn(&mut self) -> Result<Vec<u8>, ConnectionError> {
12631261
let data = self.handshake_data().await?;
1264-
match data.downcast::<quinn::crypto::rustls::HandshakeData>() {
1265-
Ok(data) => match data.protocol {
1266-
Some(protocol) => Ok(protocol),
1267-
None => bail!("no ALPN protocol available"),
1268-
},
1269-
Err(_) => bail!("unknown handshake type"),
1262+
let data = data
1263+
.downcast::<quinn::crypto::rustls::HandshakeData>()
1264+
.expect("fixed crypto setup for iroh");
1265+
match data.protocol {
1266+
Some(proto) => Ok(proto),
1267+
None => {
1268+
// Using QUIC's CONNECTION_REFUSED error on the server-side is a bit odd,
1269+
// but perhaps not a total crime. Strictly speaking for QUIC this is an
1270+
// application error, but if we surfaced this as an application error it
1271+
// would be even more confusing for the user.
1272+
Err(ConnectionError::TransportError(TransportError {
1273+
code: TransportErrorCode::CONNECTION_REFUSED,
1274+
frame: None,
1275+
reason: String::from("iroh connections must use an ALPN"),
1276+
}))
1277+
}
12701278
}
12711279
}
12721280
}
@@ -1281,6 +1289,27 @@ impl Future for Connecting {
12811289
Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
12821290
Poll::Ready(Ok(inner)) => {
12831291
let conn = Connection { inner };
1292+
1293+
// An iroh connection MUST always have an ALPN. Note that this check is
1294+
// only valid for accepting connections, but we **currently** do not use
1295+
// this `Connecting` struct when establishing connections. Once we do we'll
1296+
// have to make this check conditional.
1297+
let handshake_data = conn.handshake_data();
1298+
let handshake_data = handshake_data
1299+
.downcast::<quinn::crypto::rustls::HandshakeData>()
1300+
.expect("fixed crypto setup for iroh");
1301+
if handshake_data.protocol.is_none() {
1302+
// Using QUIC's CONNECTION_REFUSED error on the server-side is a bit odd,
1303+
// but perhaps not a total crime. Strictly speaking for QUIC this is an
1304+
// application error, but if we surfaced this as an application error it
1305+
// would be even more confusing for the user.
1306+
return Poll::Ready(Err(ConnectionError::TransportError(TransportError {
1307+
code: TransportErrorCode::CONNECTION_REFUSED,
1308+
frame: None,
1309+
reason: String::from("iroh connections must use an ALPN"),
1310+
})));
1311+
}
1312+
12841313
try_send_rtt_msg(&conn, this.ep);
12851314
Poll::Ready(Ok(conn))
12861315
}
@@ -1511,17 +1540,20 @@ impl Connection {
15111540
///
15121541
/// [`Connection::handshake_data()`]: crate::Connecting::handshake_data
15131542
#[inline]
1514-
pub fn handshake_data(&self) -> Option<Box<dyn Any>> {
1515-
self.inner.handshake_data()
1543+
pub fn handshake_data(&self) -> Box<dyn Any> {
1544+
self.inner
1545+
.handshake_data()
1546+
.expect("we always have handshake data")
15161547
}
15171548

15181549
/// Extracts the ALPN protocol from the peer's handshake data.
1519-
pub fn alpn(&self) -> Option<Vec<u8>> {
1520-
let data = self.handshake_data()?;
1521-
match data.downcast::<quinn::crypto::rustls::HandshakeData>() {
1522-
Ok(data) => data.protocol,
1523-
Err(_) => None,
1524-
}
1550+
pub fn alpn(&self) -> Vec<u8> {
1551+
let data = self.handshake_data();
1552+
let data = data
1553+
.downcast::<quinn::crypto::rustls::HandshakeData>()
1554+
.expect("fixed crypto setup for iroh");
1555+
data.protocol
1556+
.expect("checked in <Connecting as Future>::poll")
15251557
}
15261558

15271559
/// Cryptographic identity of the peer.
@@ -1533,8 +1565,10 @@ impl Connection {
15331565
/// [`Session`]: quinn_proto::crypto::Session
15341566
/// [`downcast`]: Box::downcast
15351567
#[inline]
1536-
pub fn peer_identity(&self) -> Option<Box<dyn Any>> {
1537-
self.inner.peer_identity()
1568+
pub fn peer_identity(&self) -> Box<dyn Any> {
1569+
self.inner
1570+
.peer_identity()
1571+
.expect("we always have a peer identity")
15381572
}
15391573

15401574
/// Returns the [`NodeId`] from the peer's TLS certificate.
@@ -1545,25 +1579,14 @@ impl Connection {
15451579
/// connection.
15461580
///
15471581
/// [`PublicKey`]: iroh_base::PublicKey
1548-
// TODO: Would be nice if this could be infallible.
1549-
pub fn remote_node_id(&self) -> Result<NodeId> {
1582+
pub fn remote_node_id(&self) -> NodeId {
15501583
let data = self.peer_identity();
1551-
match data {
1552-
None => bail!("no peer certificate found"),
1553-
Some(data) => match data.downcast::<Vec<rustls::pki_types::CertificateDer>>() {
1554-
Ok(certs) => {
1555-
if certs.len() != 1 {
1556-
bail!(
1557-
"expected a single peer certificate, but {} found",
1558-
certs.len()
1559-
);
1560-
}
1561-
let cert = tls::certificate::parse(&certs[0])?;
1562-
Ok(cert.peer_id())
1563-
}
1564-
Err(_) => bail!("invalid peer certificate"),
1565-
},
1566-
}
1584+
let certs = data
1585+
.downcast::<Vec<rustls::pki_types::CertificateDer>>()
1586+
.expect("we always have a cert");
1587+
debug_assert_eq!(certs.len(), 1);
1588+
let cert = tls::certificate::parse(&certs[0]).expect("valid cert");
1589+
cert.peer_id()
15671590
}
15681591

15691592
/// A stable identifier for this connection.
@@ -1624,10 +1647,7 @@ impl Connection {
16241647
/// function.
16251648
fn try_send_rtt_msg(conn: &Connection, magic_ep: &Endpoint) {
16261649
// If we can't notify the rtt-actor that's not great but not critical.
1627-
let Ok(node_id) = conn.remote_node_id() else {
1628-
warn!(?conn, "failed to get remote node id");
1629-
return;
1630-
};
1650+
let node_id = conn.remote_node_id();
16311651
let Ok(conn_type_changes) = magic_ep.conn_type(node_id) else {
16321652
warn!(?conn, "failed to create conn_type stream");
16331653
return;
@@ -1953,7 +1973,7 @@ mod tests {
19531973
info!("[server] round {i}");
19541974
let incoming = ep.accept().await.unwrap();
19551975
let conn = incoming.await.unwrap();
1956-
let node_id = conn.remote_node_id().unwrap();
1976+
let node_id = conn.remote_node_id();
19571977
info!(%i, peer = %node_id.fmt_short(), "accepted connection");
19581978
let (mut send, mut recv) = conn.accept_bi().await.unwrap();
19591979
let mut buf = vec![0u8; chunk_size];
@@ -2066,10 +2086,10 @@ mod tests {
20662086

20672087
async fn accept_world(ep: Endpoint, src: NodeId) {
20682088
let incoming = ep.accept().await.unwrap();
2069-
let mut iconn = incoming.accept().unwrap();
2070-
let alpn = iconn.alpn().await.unwrap();
2089+
let iconn = incoming.accept().unwrap();
20712090
let conn = iconn.await.unwrap();
2072-
let node_id = conn.remote_node_id().unwrap();
2091+
let alpn = conn.alpn();
2092+
let node_id = conn.remote_node_id();
20732093
assert_eq!(node_id, src);
20742094
assert_eq!(alpn, TEST_ALPN);
20752095
let (mut send, mut recv) = conn.accept_bi().await.unwrap();
@@ -2159,7 +2179,7 @@ mod tests {
21592179
async fn accept(ep: &Endpoint) -> NodeId {
21602180
let incoming = ep.accept().await.unwrap();
21612181
let conn = incoming.await.unwrap();
2162-
let node_id = conn.remote_node_id().unwrap();
2182+
let node_id = conn.remote_node_id();
21632183
tracing::info!(node_id=%node_id.fmt_short(), "accepted connection");
21642184
node_id
21652185
}

0 commit comments

Comments
 (0)