chat/
chat.rs

1use anyhow::Result;
2use iroh::{Endpoint, SecretKey};
3use iroh_gossip::{api::Event, net::Gossip};
4
5use ed25519_dalek::SigningKey;
6
7// Imports from distrubuted-topic-tracker
8use distributed_topic_tracker::{AutoDiscoveryGossip, RecordPublisher, TopicId};
9
10#[tokio::main]
11async fn main() -> Result<()> {
12    // tracing init - only show distributed_topic_tracker logs
13    use tracing_subscriber::filter::EnvFilter;
14
15    tracing_subscriber::fmt()
16        .with_thread_ids(true)
17        .with_ansi(true)
18        .with_env_filter(
19            EnvFilter::try_from_default_env()
20                .unwrap_or_else(|_| EnvFilter::new("distributed_topic_tracker=debug")),
21        )
22        .init();
23
24    // Generate a new random secret key
25    let secret_key = SecretKey::generate(&mut rand::rng());
26    let signing_key = SigningKey::from_bytes(&secret_key.to_bytes());
27
28    // Set up endpoint with discovery enabled
29    let endpoint = Endpoint::builder()
30        .secret_key(secret_key.clone())
31        .bind()
32        .await?;
33
34    // Initialize gossip with auto-discovery
35    let gossip = Gossip::builder().spawn(endpoint.clone());
36
37    // Set up protocol router
38    let _router = iroh::protocol::Router::builder(endpoint.clone())
39        .accept(iroh_gossip::ALPN, gossip.clone())
40        .spawn();
41
42    let topic_id = TopicId::new("my-iroh-gossip-topic".to_string());
43    let initial_secret = b"my-initial-secret".to_vec();
44
45    let record_publisher = RecordPublisher::new(
46        topic_id.clone(),
47        signing_key.verifying_key(),
48        signing_key.clone(),
49        None,
50        initial_secret,
51    );
52
53    // Split into sink (sending) and stream (receiving)
54    let (gossip_sender, gossip_receiver) = gossip
55        .subscribe_and_join_with_auto_discovery(record_publisher)
56        .await?
57        .split()
58        .await?;
59
60    println!("Joined topic");
61
62    // Spawn listener for incoming messages
63    tokio::spawn(async move {
64        while let Some(Ok(event)) = gossip_receiver.next().await {
65            if let Event::Received(msg) = event {
66                println!(
67                    "\nMessage from {}: {}",
68                    &msg.delivered_from.to_string()[0..8],
69                    String::from_utf8(msg.content.to_vec()).unwrap()
70                );
71            } else if let Event::NeighborUp(peer) = event {
72                println!("\nJoined by {}", &peer.to_string()[0..8]);
73            }
74        }
75    });
76
77    // Main input loop for sending messages
78    let mut buffer = String::new();
79    let stdin = std::io::stdin();
80    loop {
81        print!("\n> ");
82        stdin.read_line(&mut buffer).unwrap();
83        gossip_sender
84            .broadcast(buffer.clone().replace("\n", "").into())
85            .await
86            .unwrap();
87        println!(" - (sent)");
88        buffer.clear();
89    }
90}