chat/
chat.rs

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