Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions crates/cli/src/commands/relay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,11 +403,25 @@ mod tests {
with_relay_server(
|args| args.p2p.external_host = Some("www.google.com".into()),
async |cfg| {
let response = relay_server_get(cfg, "/enr").await.unwrap();
let body = response.text().await.unwrap();
let enr = pluto_eth2util::enr::Record::try_from(body.as_str()).unwrap();

assert!(enr.ip().unwrap().is_loopback());
// Resolution happens asynchronously on a tick, so poll until the
// ENR reflects a non-loopback IP (mirrors the Go test using
// `assert.Eventually`).
tokio::time::timeout(time::Duration::from_secs(10), async {
loop {
let response = relay_server_get(cfg.clone(), "/enr").await.unwrap();
let body = response.text().await.unwrap();
let enr = pluto_eth2util::enr::Record::try_from(body.as_str()).unwrap();
let ip = enr.ip().unwrap();

if !ip.is_loopback() {
break;
}

tokio::time::sleep(time::Duration::from_millis(200)).await;
}
})
.await
.expect("external host never resolved to non-loopback ip");
},
)
.await
Expand Down
19 changes: 14 additions & 5 deletions crates/relay-server/src/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,13 +329,22 @@ async fn resolve_external_host_periodically(

/// Resolves the external host to an IP address.
async fn resolve_external_host(state: Arc<AppState>, external_host: &str) {
match tokio::net::lookup_host(external_host).await {
Ok(mut addrs) => {
if let Some(addr) = addrs.next()
&& let IpAddr::V4(ipv4) = addr.ip()
{
// `tokio::net::lookup_host` requires a `host:port` input, but we only need
// the IP — use a dummy port of 0 so a bare hostname resolves correctly.
match tokio::net::lookup_host((external_host, 0)).await {
Ok(addrs) => {
let ipv4 = addrs
.filter_map(|a| match a.ip() {
IpAddr::V4(v4) => Some(v4),
IpAddr::V6(_) => None,
})
.next();

if let Some(ipv4) = ipv4 {
debug!("Resolved external host {external_host} to {ipv4}");
state.set_external_host_ip(Some(ipv4)).await;
} else {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we invalidate the cache here state.set_external_host_ip(None).await;? The DNS may no longer return IPv4 for the host, so a later query could fail

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would keep it as it is, since it's the original charon behavior

warn!("External host {external_host} resolved with no IPv4 address");
}
}
Err(e) => {
Expand Down
Loading