Skip to content

Commit fca67bc

Browse files
committed
[lightning-net-tokio] Fix race-y unwrap fetching peer socket address
I recently saw the following panic on one of my test nodes: ``` thread 'tokio-runtime-worker' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 107, kind: NotConnected, message: "Transport endpoint is not connected" }', rust-lightning/lightning-net-tokio/src/lib.rs:250:38 ``` Presumably what happened is somehow the connection was closed in between us accepting it and us going to start processing it. While this is a somewhat surprising race, its clearly reachable. The fix proposed here is quite trivial - simply don't `unwrap` trying to fetch our peer's socket address, instead treat the peer address as `None` and discover the disconnection later when we go to read.
1 parent 637fb88 commit fca67bc

File tree

1 file changed

+18
-23
lines changed

1 file changed

+18
-23
lines changed

lightning-net-tokio/src/lib.rs

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ use lightning::ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, NetAddre
8585
use lightning::util::logger::Logger;
8686

8787
use std::task;
88-
use std::net::IpAddr;
8988
use std::net::SocketAddr;
9089
use std::net::TcpStream as StdTcpStream;
9190
use std::sync::{Arc, Mutex};
@@ -212,6 +211,20 @@ impl Connection {
212211
}
213212
}
214213

214+
fn get_addr_from_stream(stream: &StdTcpStream) -> Option<NetAddress> {
215+
match stream.peer_addr() {
216+
Ok(SocketAddr::V4(sockaddr)) => Some(NetAddress::IPv4 {
217+
addr: sockaddr.ip().octets(),
218+
port: sockaddr.port(),
219+
}),
220+
Ok(SocketAddr::V6(sockaddr)) => Some(NetAddress::IPv6 {
221+
addr: sockaddr.ip().octets(),
222+
port: sockaddr.port(),
223+
}),
224+
Err(_) => None,
225+
}
226+
}
227+
215228
/// Process incoming messages and feed outgoing messages on the provided socket generated by
216229
/// accepting an incoming connection.
217230
///
@@ -223,21 +236,12 @@ pub fn setup_inbound<CMH, RMH, L, UMH>(peer_manager: Arc<peer_handler::PeerManag
223236
RMH: RoutingMessageHandler + 'static + Send + Sync,
224237
L: Logger + 'static + ?Sized + Send + Sync,
225238
UMH: CustomMessageHandler + 'static + Send + Sync {
226-
let ip_addr = stream.peer_addr().unwrap();
239+
let remote_addr = get_addr_from_stream(&stream);
227240
let (reader, write_receiver, read_receiver, us) = Connection::new(stream);
228241
#[cfg(debug_assertions)]
229242
let last_us = Arc::clone(&us);
230243

231-
let handle_opt = if let Ok(_) = peer_manager.new_inbound_connection(SocketDescriptor::new(us.clone()), match ip_addr.ip() {
232-
IpAddr::V4(ip) => Some(NetAddress::IPv4 {
233-
addr: ip.octets(),
234-
port: ip_addr.port(),
235-
}),
236-
IpAddr::V6(ip) => Some(NetAddress::IPv6 {
237-
addr: ip.octets(),
238-
port: ip_addr.port(),
239-
}),
240-
}) {
244+
let handle_opt = if let Ok(_) = peer_manager.new_inbound_connection(SocketDescriptor::new(us.clone()), remote_addr) {
241245
Some(tokio::spawn(Connection::schedule_read(peer_manager, us, reader, read_receiver, write_receiver)))
242246
} else {
243247
// Note that we will skip socket_disconnected here, in accordance with the PeerManager
@@ -274,20 +278,11 @@ pub fn setup_outbound<CMH, RMH, L, UMH>(peer_manager: Arc<peer_handler::PeerMana
274278
RMH: RoutingMessageHandler + 'static + Send + Sync,
275279
L: Logger + 'static + ?Sized + Send + Sync,
276280
UMH: CustomMessageHandler + 'static + Send + Sync {
277-
let ip_addr = stream.peer_addr().unwrap();
281+
let remote_addr = get_addr_from_stream(&stream);
278282
let (reader, mut write_receiver, read_receiver, us) = Connection::new(stream);
279283
#[cfg(debug_assertions)]
280284
let last_us = Arc::clone(&us);
281-
let handle_opt = if let Ok(initial_send) = peer_manager.new_outbound_connection(their_node_id, SocketDescriptor::new(us.clone()), match ip_addr.ip() {
282-
IpAddr::V4(ip) => Some(NetAddress::IPv4 {
283-
addr: ip.octets(),
284-
port: ip_addr.port(),
285-
}),
286-
IpAddr::V6(ip) => Some(NetAddress::IPv6 {
287-
addr: ip.octets(),
288-
port: ip_addr.port(),
289-
}),
290-
}) {
285+
let handle_opt = if let Ok(initial_send) = peer_manager.new_outbound_connection(their_node_id, SocketDescriptor::new(us.clone()), remote_addr) {
291286
Some(tokio::spawn(async move {
292287
// We should essentially always have enough room in a TCP socket buffer to send the
293288
// initial 10s of bytes. However, tokio running in single-threaded mode will always

0 commit comments

Comments
 (0)