Skip to content

Commit

Permalink
feat: update Iroh and enable local network discovery. (#455)
Browse files Browse the repository at this point in the history
This updates to the latest version of `iroh-net` and enables the local
network discovery feature. I can't remember where we left off on LAN but
I needed this locally to discover a local matchmaker when I don't have
network access to Iroh's pkarr DNS discovery.

Enabling this should completely replace our need for the manual mDNS
discovery module for lan networking I think, but I haven't actually done
any work on that.

---------

Co-authored-by: Max Whitehead <[email protected]>
  • Loading branch information
zicklag and MaxCWhitehead authored Oct 8, 2024
1 parent 4a72715 commit 008a95d
Show file tree
Hide file tree
Showing 15 changed files with 448 additions and 200 deletions.
491 changes: 339 additions & 152 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,9 @@ github = ["gschup"]
name = "ring"
expression = "MIT AND ISC AND OpenSSL"
license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }]


[advisories]
ignore = [
"RUSTSEC-2024-0370", # no upgrade available - https://github.com/fishfolk/bones/issues/479
]
4 changes: 2 additions & 2 deletions framework_crates/bones_framework/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@ postcard = { version = "1.0", features = ["alloc"] }
rcgen = "0.12"
rustls = { version = "0.21", features = ["dangerous_configuration", "quic"] }
smallvec = "1.10"
iroh-quinn = "0.10"
iroh-net = "0.22"
iroh-quinn = { version = "0.11" }
iroh-net = { version = "0.26", features = ["discovery-local-network"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
turborand = { version = "0.10.0", features = ["atomic"] }

Expand Down
8 changes: 7 additions & 1 deletion framework_crates/bones_framework/src/networking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,20 @@ pub async fn get_network_endpoint() -> &'static iroh_net::Endpoint {
.alpns(vec![MATCH_ALPN.to_vec(), PLAY_ALPN.to_vec()])
.discovery(Box::new(
iroh_net::discovery::ConcurrentDiscovery::from_services(vec![
Box::new(
iroh_net::discovery::local_swarm_discovery::LocalSwarmDiscovery::new(
secret_key.public(),
)
.unwrap(),
),
Box::new(iroh_net::discovery::dns::DnsDiscovery::n0_dns()),
Box::new(iroh_net::discovery::pkarr::PkarrPublisher::n0_dns(
secret_key.clone(),
)),
]),
))
.secret_key(secret_key)
.bind(0)
.bind()
.await
.unwrap()
})
Expand Down
14 changes: 8 additions & 6 deletions framework_crates/bones_framework/src/networking/lan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,14 +328,15 @@ async fn lan_start_server(
}

// Handle new connections
new_connection = ep.accept() => {
let Some(mut new_connection) = new_connection else {
incomming = ep.accept() => {
let Some(incomming) = incomming else {
anyhow::bail!("unable to accept new connections");
};
let result = async move {
let alpn = new_connection.alpn().await?;
let mut connecting = incomming.accept()?;
let alpn = connecting.alpn().await?;
anyhow::ensure!(alpn == PLAY_ALPN, "unexpected ALPN");
let conn = new_connection.await?;
let conn = connecting.await?;
anyhow::Ok(conn)
};

Expand Down Expand Up @@ -383,7 +384,7 @@ async fn lan_start_server(
.for_each(|(i, conn)| {
let id = get_remote_node_id(conn).expect("invalid connection");
let mut addr = NodeAddr::new(id);
if let Some(info) = endpoint.connection_info(id) {
if let Some(info) = endpoint.remote_info(id) {
if let Some(relay_url) = info.relay_url {
addr = addr.with_relay_url(relay_url.relay_url);
}
Expand All @@ -402,7 +403,8 @@ async fn lan_start_server(
player_count,
})?)
.await?;
uni.finish().await?;
uni.finish()?;
uni.stopped().await?;
}

let connections = connections
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ pub(crate) async fn resolve_list_lobbies(
let message = MatchmakerRequest::ListLobbies(game_id);
let message = postcard::to_allocvec(&message)?;
send.write_all(&message).await?;
send.finish().await?;
send.finish()?;
send.stopped().await?;

let response = recv.read_to_end(5 * 1024).await?;
let message: MatchmakerResponse = postcard::from_bytes(&response)?;
Expand All @@ -50,7 +51,8 @@ pub(crate) async fn resolve_create_lobby(
let message = MatchmakerRequest::CreateLobby(lobby_info);
let message = postcard::to_allocvec(&message)?;
send.write_all(&message).await?;
send.finish().await?;
send.finish()?;
send.stopped().await?;

let response = recv.read_to_end(READ_TO_END_BYTE_COUNT).await?;
let message: MatchmakerResponse = postcard::from_bytes(&response)?;
Expand Down Expand Up @@ -81,7 +83,8 @@ pub(crate) async fn resolve_join_lobby(
let message = MatchmakerRequest::JoinLobby(game_id, lobby_id.clone(), password);
let message = postcard::to_allocvec(&message)?;
send.write_all(&message).await?;
send.finish().await?;
send.finish()?;
send.stopped().await?;

let response = recv.read_to_end(READ_TO_END_BYTE_COUNT).await?;
let message: MatchmakerResponse = postcard::from_bytes(&response)?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ pub(crate) async fn resolve_search_for_match(
info!(request=?message, "Resolve: Sending match request");
let message = postcard::to_allocvec(&message)?;
send.write_all(&message).await?;
send.finish().await?;
send.finish()?;
send.stopped().await?;

let res = recv.read_to_end(READ_TO_END_BYTE_COUNT).await?;
let _response: MatchmakerResponse = postcard::from_bytes(&res)?;
Expand Down Expand Up @@ -114,7 +115,8 @@ pub(crate) async fn resolve_stop_search_for_match(

let message = postcard::to_allocvec(&message)?;
send.write_all(&message).await?;
send.finish().await?;
send.finish()?;
send.stopped().await?;

let res = recv.read_to_end(READ_TO_END_BYTE_COUNT).await?;
let response: MatchmakerResponse = postcard::from_bytes(&res)?;
Expand Down
16 changes: 10 additions & 6 deletions framework_crates/bones_framework/src/networking/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ impl NetworkSocket for Socket {
let result = async move {
let mut stream = conn.open_uni().await?;
stream.write_chunk(message).await?;
stream.finish().await?;
stream.finish()?;
stream.stopped().await?;
anyhow::Ok(())
};
if let Err(err) = result.await {
Expand All @@ -168,7 +169,8 @@ impl NetworkSocket for Socket {
let result = async move {
let mut stream = conn.open_uni().await?;
stream.write_chunk(message).await?;
stream.finish().await?;
stream.finish()?;
stream.stopped().await?;
anyhow::Ok(())
};
if let Err(err) = result.await {
Expand Down Expand Up @@ -233,18 +235,19 @@ pub(super) async fn establish_peer_connections(
info!(players=?range, "Waiting for {} peer connections", range.len());
for i in range {
// Wait for connection
let mut conn = ep
let conn = ep
.accept()
.await
.ok_or_else(|| anyhow::anyhow!("no connection for {}", i))?;
let alpn = conn.alpn().await?;
let mut connecting = conn.accept()?;
let alpn = connecting.alpn().await?;
anyhow::ensure!(
alpn == PLAY_ALPN,
"invalid ALPN: {:?}",
std::str::from_utf8(&alpn).unwrap_or("<bytes>")
);

let conn = conn.await?;
let conn = connecting.await?;

// Receive the player index
let idx = {
Expand All @@ -271,7 +274,8 @@ pub(super) async fn establish_peer_connections(
// Send player index
let mut channel = conn.open_uni().await?;
channel.write(&player_idx.to_le_bytes()).await?;
channel.finish().await?;
channel.finish()?;
channel.stopped().await?;

out_connections.push((i, conn));
}
Expand Down
6 changes: 3 additions & 3 deletions other_crates/bones_matchmaker/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ postcard = { version = "1.0", default-features = false, features =
serde = { version = "1.0", features = ["derive"] }
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
iroh-net = { version = "0.22" }
quinn = { version = "0.10", package = "iroh-quinn" }
blake3 = "1.5.3"
iroh-net = { version = "0.26", features = ["discovery-local-network"] }
quinn = { version = "0.11", package = "iroh-quinn" }
blake3 = "1.5.3"
26 changes: 19 additions & 7 deletions other_crates/bones_matchmaker/examples/matchmaker_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use bones_matchmaker_proto::{
MatchInfo, MatchmakerRequest, MatchmakerResponse, PlayerIdxAssignment, MATCH_ALPN, PLAY_ALPN,
};
use serde::{Deserialize, Serialize};
use std::time::Duration;
use std::{
net::{Ipv4Addr, SocketAddrV4},
time::Duration,
};
use tokio::task::JoinSet;

const CLIENT_PORT: u16 = 0;
Expand All @@ -25,14 +28,20 @@ async fn client() -> anyhow::Result<()> {
.alpns(vec![MATCH_ALPN.to_vec(), PLAY_ALPN.to_vec()])
.discovery(Box::new(
iroh_net::discovery::ConcurrentDiscovery::from_services(vec![
Box::new(
iroh_net::discovery::local_swarm_discovery::LocalSwarmDiscovery::new(
secret_key.public(),
)?,
),
Box::new(iroh_net::discovery::dns::DnsDiscovery::n0_dns()),
Box::new(iroh_net::discovery::pkarr::PkarrPublisher::n0_dns(
secret_key.clone(),
)),
]),
))
.secret_key(secret_key)
.bind(CLIENT_PORT)
.bind_addr_v4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, CLIENT_PORT))
.bind()
.await?;

let i_am = std::env::args().nth(2).unwrap();
Expand Down Expand Up @@ -61,7 +70,8 @@ async fn client() -> anyhow::Result<()> {
let message = postcard::to_allocvec(&message)?;

send.write_all(&message).await?;
send.finish().await?;
send.finish()?;
send.stopped().await?;

println!("o Waiting for response");

Expand Down Expand Up @@ -116,7 +126,8 @@ async fn client() -> anyhow::Result<()> {
sender
.write_all(&postcard::to_allocvec(&hello.clone())?)
.await?;
sender.finish().await?;
sender.finish()?;
sender.stopped().await?;

tokio::time::sleep(Duration::from_secs(1)).await;
}
Expand All @@ -133,13 +144,14 @@ async fn client() -> anyhow::Result<()> {

let endpoint = endpoint.clone();
tasks.spawn(async move {
if let Some(mut conn) = endpoint.accept().await {
if let Some(incomming) = endpoint.accept().await {
let result = async {
let alpn = conn.alpn().await?;
let mut connecting = incomming.accept()?;
let alpn = connecting.alpn().await?;
if alpn != PLAY_ALPN {
anyhow::bail!("unexpected ALPN: {:?}", alpn);
}
let conn = conn.await?;
let conn = connecting.await?;

for _ in 0..3 {
let mut recv = conn.accept_uni().await?;
Expand Down
11 changes: 9 additions & 2 deletions other_crates/bones_matchmaker/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#[macro_use]
extern crate tracing;

use std::net::SocketAddr;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};

use bones_matchmaker_proto::MATCH_ALPN;
use iroh_net::key::SecretKey;
Expand Down Expand Up @@ -52,14 +52,20 @@ async fn server(args: Config) -> anyhow::Result<()> {
.alpns(vec![MATCH_ALPN.to_vec()])
.discovery(Box::new(
iroh_net::discovery::ConcurrentDiscovery::from_services(vec![
Box::new(
iroh_net::discovery::local_swarm_discovery::LocalSwarmDiscovery::new(
secret_key.public(),
)?,
),
Box::new(iroh_net::discovery::dns::DnsDiscovery::n0_dns()),
Box::new(iroh_net::discovery::pkarr::PkarrPublisher::n0_dns(
secret_key.clone(),
)),
]),
))
.secret_key(secret_key)
.bind(port)
.bind_addr_v4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, port))
.bind()
.await?;

let my_addr = endpoint.node_addr().await?;
Expand All @@ -76,6 +82,7 @@ async fn server(args: Config) -> anyhow::Result<()> {
Ok(conn) => {
info!(
connection_id = conn.stable_id(),
addr = ?conn.remote_address(),
"Accepted connection from client"
);

Expand Down
24 changes: 16 additions & 8 deletions other_crates/bones_matchmaker/src/lobbies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ pub async fn handle_list_lobbies(game_id: GameID, send: &mut quinn::SendStream)
// Send the lobby list back to the client
let message = postcard::to_allocvec(&MatchmakerResponse::LobbiesList(lobbies))?;
send.write_all(&message).await?;
send.finish().await?;
send.finish()?;
send.stopped().await?;

Ok(())
}
Expand Down Expand Up @@ -77,7 +78,8 @@ pub async fn handle_create_lobby(
// Send confirmation to the client
let message = postcard::to_allocvec(&MatchmakerResponse::LobbyCreated(lobby_id))?;
send.write_all(&message).await?;
send.finish().await?;
send.finish()?;
send.stopped().await?;

Ok(())
}
Expand All @@ -102,7 +104,8 @@ pub async fn handle_join_lobby(
"Incorrect password".to_string(),
))?;
send.write_all(&message).await?;
send.finish().await?;
send.finish()?;
send.stopped().await?;
return Ok(());
}
}
Expand Down Expand Up @@ -130,7 +133,8 @@ pub async fn handle_join_lobby(
let message =
postcard::to_allocvec(&MatchmakerResponse::LobbyJoined(lobby_id.clone()))?;
send.write_all(&message).await?;
send.finish().await?;
send.finish()?;
send.stopped().await?;

// Always notify all players in the lobby about the update
let lobby_update_message =
Expand All @@ -144,7 +148,8 @@ pub async fn handle_join_lobby(
for connection in connections.get().iter() {
let mut send = connection.open_uni().await?;
send.write_all(&lobby_update_message).await?;
send.finish().await?;
send.finish()?;
send.stopped().await?;
}
}

Expand Down Expand Up @@ -176,20 +181,23 @@ pub async fn handle_join_lobby(
"Lobby is full".to_string(),
))?;
send.write_all(&message).await?;
send.finish().await?;
send.finish()?;
send.stopped().await?;
}
}
} else {
let message =
postcard::to_allocvec(&MatchmakerResponse::Error("Lobby not found".to_string()))?;
send.write_all(&message).await?;
send.finish().await?;
send.finish()?;
send.stopped().await?;
}
} else {
let message =
postcard::to_allocvec(&MatchmakerResponse::Error("Game not found".to_string()))?;
send.write_all(&message).await?;
send.finish().await?;
send.finish()?;
send.stopped().await?;
}

Ok(())
Expand Down
Loading

0 comments on commit 008a95d

Please sign in to comment.