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::SocketAddr;
9
10use bones_matchmaker_proto::MATCH_ALPN;
11use iroh_net::key::SecretKey;
12
13pub mod cli;
14
15mod matchmaker;
16
17#[derive(clap::Parser, Debug)]
18#[command(author, version, about, long_about = None)]
19struct Config {
20    /// The server address to listen on
21    #[clap(short, long = "listen", default_value = "0.0.0.0:8943")]
22    listen_addr: SocketAddr,
23    /// If enabled, prints the current secret key. Use with caution.
24    #[clap(long)]
25    print_secret_key: bool,
26    /// Use this secret key for the node
27    #[clap(short, long, env = "BONES_MATCHMAKER_SECRET_KEY")]
28    secret_key: Option<iroh_net::key::SecretKey>,
29}
30
31async fn server(args: Config) -> anyhow::Result<()> {
32    let port = args.listen_addr.port();
33
34    match args.secret_key {
35        Some(ref key) => {
36            info!("Using existing key: {}", key.public());
37        }
38        None => {
39            info!("Generating new key");
40        }
41    }
42
43    let secret_key = args.secret_key.unwrap_or_else(SecretKey::generate);
44
45    if args.print_secret_key {
46        println!("Secret Key: {}", secret_key);
47    }
48
49    let endpoint = iroh_net::Endpoint::builder()
50        .alpns(vec![MATCH_ALPN.to_vec()])
51        .discovery(Box::new(
52            iroh_net::discovery::ConcurrentDiscovery::from_services(vec![
53                Box::new(iroh_net::discovery::dns::DnsDiscovery::n0_dns()),
54                Box::new(iroh_net::discovery::pkarr::PkarrPublisher::n0_dns(
55                    secret_key.clone(),
56                )),
57            ]),
58        ))
59        .secret_key(secret_key)
60        .bind(port)
61        .await?;
62
63    let my_addr = endpoint.node_addr().await?;
64
65    info!(address=?my_addr, "Started server");
66
67    println!("Node ID: {}", my_addr.node_id);
68
69    // Listen for incomming connections
70    while let Some(connecting) = endpoint.accept().await {
71        let connection = connecting.await;
72
73        match connection {
74            Ok(conn) => {
75                info!(
76                    connection_id = conn.stable_id(),
77                    "Accepted connection from client"
78                );
79
80                // Spawn a task to handle the new connection
81                tokio::task::spawn(matchmaker::handle_connection(endpoint.clone(), conn));
82            }
83            Err(e) => error!("Error opening client connection: {e:?}"),
84        }
85    }
86
87    info!("Server shutdown");
88
89    Ok(())
90}