bones_matchmaker/
lib.rs

1#![doc = include_str!("../README.md")]
2// This cfg_attr is needed because `rustdoc::all` includes lints not supported on stable
3#![cfg_attr(doc, allow(unknown_lints))]
4#![deny(rustdoc::all)]
5#[macro_use]
6extern crate tracing;
7
8use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
9use std::sync::Arc;
10
11use bones_matchmaker_proto::MATCH_ALPN;
12use iroh::key::SecretKey;
13use matchmaker::Matchmaker;
14
15pub mod cli;
16mod helpers;
17mod lobbies;
18mod matchmaker;
19mod matchmaking;
20
21#[derive(clap::Parser, Debug)]
22#[command(author, version, about, long_about = None)]
23struct Config {
24    /// The server address to listen on
25    #[clap(short, long = "listen", default_value = "0.0.0.0:8943")]
26    listen_addr: SocketAddr,
27    /// If enabled, prints the current secret key. Use with caution.
28    #[clap(long)]
29    print_secret_key: bool,
30    /// Use this secret key for the node
31    #[clap(short, long, env = "BONES_MATCHMAKER_SECRET_KEY")]
32    secret_key: Option<iroh::key::SecretKey>,
33}
34
35async fn server(args: Config) -> anyhow::Result<()> {
36    let port = args.listen_addr.port();
37
38    match args.secret_key {
39        Some(ref key) => {
40            info!("Using existing key: {}", key.public());
41        }
42        None => {
43            info!("Generating new key");
44        }
45    }
46
47    let secret_key = args.secret_key.unwrap_or_else(SecretKey::generate);
48
49    if args.print_secret_key {
50        println!("Secret Key: {}", secret_key);
51    }
52
53    let endpoint = iroh::Endpoint::builder()
54        .alpns(vec![MATCH_ALPN.to_vec()])
55        .discovery(Box::new(
56            iroh::discovery::ConcurrentDiscovery::from_services(vec![
57                Box::new(
58                    iroh::discovery::local_swarm_discovery::LocalSwarmDiscovery::new(
59                        secret_key.public(),
60                    )?,
61                ),
62                Box::new(iroh::discovery::dns::DnsDiscovery::n0_dns()),
63                Box::new(iroh::discovery::pkarr::PkarrPublisher::n0_dns(
64                    secret_key.clone(),
65                )),
66            ]),
67        ))
68        .secret_key(secret_key)
69        .bind_addr_v4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, port))
70        .bind()
71        .await?;
72
73    let my_addr = endpoint.node_addr().await?;
74
75    info!(address=?my_addr, "Started server");
76
77    println!("Node ID: {}", my_addr.node_id);
78
79    let matchmaker = Matchmaker::new(endpoint.clone());
80    let router = iroh::protocol::Router::builder(endpoint)
81        .accept(MATCH_ALPN, Arc::new(matchmaker))
82        .spawn()
83        .await?;
84
85    // wait for shutdown
86    tokio::signal::ctrl_c().await?;
87
88    router.shutdown().await?;
89
90    info!("Server shutdown");
91
92    Ok(())
93}