diff options
| author | hozan23 <hozan23@proton.me> | 2023-11-09 11:38:19 +0300 | 
|---|---|---|
| committer | hozan23 <hozan23@proton.me> | 2023-11-09 11:38:19 +0300 | 
| commit | 849d827486c75b2ab223d7b0e638dbb5b74d4d1d (patch) | |
| tree | 41cd3babc37147ec4a40cab8ce8ae31c91cce33b /p2p/examples | |
| parent | de1354525895ffbad18f90a5246fd65157f7449e (diff) | |
rename crates
Diffstat (limited to 'p2p/examples')
| -rw-r--r-- | p2p/examples/chat.rs | 141 | ||||
| -rwxr-xr-x | p2p/examples/chat_simulation.sh | 25 | ||||
| -rw-r--r-- | p2p/examples/monitor.rs | 93 | ||||
| -rwxr-xr-x | p2p/examples/net_simulation.sh | 73 | ||||
| -rw-r--r-- | p2p/examples/peer.rs | 82 | 
5 files changed, 414 insertions, 0 deletions
| diff --git a/p2p/examples/chat.rs b/p2p/examples/chat.rs new file mode 100644 index 0000000..4358362 --- /dev/null +++ b/p2p/examples/chat.rs @@ -0,0 +1,141 @@ +use std::sync::Arc; + +use async_std::io; +use async_trait::async_trait; +use clap::Parser; +use smol::{channel, future, Executor}; + +use karyons_net::{Endpoint, Port}; + +use karyons_p2p::{ +    protocol::{ArcProtocol, Protocol, ProtocolEvent, ProtocolID}, +    ArcPeer, Backend, Config, P2pError, PeerID, Version, +}; + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +struct Cli { +    /// Optional list of bootstrap peers to start the seeding process. +    #[arg(short)] +    bootstrap_peers: Vec<Endpoint>, + +    /// Optional list of peer endpoints for manual connections. +    #[arg(short)] +    peer_endpoints: Vec<Endpoint>, + +    /// Optional endpoint for accepting incoming connections. +    #[arg(short)] +    listen_endpoint: Option<Endpoint>, + +    /// Optional TCP/UDP port for the discovery service. +    #[arg(short)] +    discovery_port: Option<Port>, + +    /// Username +    #[arg(long)] +    username: String, +} + +pub struct ChatProtocol { +    username: String, +    peer: ArcPeer, +} + +impl ChatProtocol { +    fn new(username: &str, peer: ArcPeer) -> ArcProtocol { +        Arc::new(Self { +            peer, +            username: username.to_string(), +        }) +    } +} + +#[async_trait] +impl Protocol for ChatProtocol { +    async fn start(self: Arc<Self>, ex: Arc<Executor<'_>>) -> Result<(), P2pError> { +        let selfc = self.clone(); +        let stdin = io::stdin(); +        let task = ex.spawn(async move { +            loop { +                let mut input = String::new(); +                stdin.read_line(&mut input).await.unwrap(); +                let msg = format!("> {}: {}", selfc.username, input.trim()); +                selfc.peer.broadcast(&Self::id(), &msg).await; +            } +        }); + +        let listener = self.peer.register_listener::<Self>().await; +        loop { +            let event = listener.recv().await.unwrap(); + +            match event { +                ProtocolEvent::Message(msg) => { +                    let msg = String::from_utf8(msg).unwrap(); +                    println!("{msg}"); +                } +                ProtocolEvent::Shutdown => { +                    break; +                } +            } +        } + +        task.cancel().await; +        listener.cancel().await; +        Ok(()) +    } + +    fn version() -> Result<Version, P2pError> { +        "0.1.0, 0.1.0".parse() +    } + +    fn id() -> ProtocolID { +        "CHAT".into() +    } +} + +fn main() { +    env_logger::init(); +    let cli = Cli::parse(); + +    // Create a PeerID based on the username. +    let peer_id = PeerID::new(cli.username.as_bytes()); + +    // Create the configuration for the backend. +    let config = Config { +        listen_endpoint: cli.listen_endpoint, +        peer_endpoints: cli.peer_endpoints, +        bootstrap_peers: cli.bootstrap_peers, +        discovery_port: cli.discovery_port.unwrap_or(0), +        ..Default::default() +    }; + +    // Create a new Backend +    let backend = Backend::new(peer_id, config); + +    let (ctrlc_s, ctrlc_r) = channel::unbounded(); +    let handle = move || ctrlc_s.try_send(()).unwrap(); +    ctrlc::set_handler(handle).unwrap(); + +    // Create a new Executor +    let ex = Arc::new(Executor::new()); + +    let ex_cloned = ex.clone(); +    let task = ex.spawn(async { +        let username = cli.username; + +        // Attach the ChatProtocol +        let c = move |peer| ChatProtocol::new(&username, peer); +        backend.attach_protocol::<ChatProtocol>(c).await.unwrap(); + +        // Run the backend +        backend.run(ex_cloned).await.unwrap(); + +        // Wait for ctrlc signal +        ctrlc_r.recv().await.unwrap(); + +        // Shutdown the backend +        backend.shutdown().await; +    }); + +    future::block_on(ex.run(task)); +} diff --git a/p2p/examples/chat_simulation.sh b/p2p/examples/chat_simulation.sh new file mode 100755 index 0000000..82bbe96 --- /dev/null +++ b/p2p/examples/chat_simulation.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# build +cargo build --release --example chat  + +tmux new-session -d -s karyons_chat  + +tmux send-keys -t karyons_chat "../../target/release/examples/chat --username 'user1'\ +    -l 'tcp://127.0.0.1:40000' -d  '40010'" Enter + +tmux split-window -h -t karyons_chat +tmux send-keys -t karyons_chat "../../target/release/examples/chat --username 'user2'\ +    -l 'tcp://127.0.0.1:40001' -d  '40011' -b 'tcp://127.0.0.1:40010 ' " Enter + +tmux split-window -h -t karyons_chat +tmux send-keys -t karyons_chat "../../target/release/examples/chat --username 'user3'\ +    -l 'tcp://127.0.0.1:40002' -d  '40012' -b 'tcp://127.0.0.1:40010'" Enter + +tmux split-window -h -t karyons_chat +tmux send-keys -t karyons_chat "../../target/release/examples/chat --username 'user4'\ +    -b 'tcp://127.0.0.1:40010'" Enter + +tmux select-layout tiled  + +tmux attach -t karyons_chat diff --git a/p2p/examples/monitor.rs b/p2p/examples/monitor.rs new file mode 100644 index 0000000..cd4defc --- /dev/null +++ b/p2p/examples/monitor.rs @@ -0,0 +1,93 @@ +use std::sync::Arc; + +use clap::Parser; +use easy_parallel::Parallel; +use smol::{channel, future, Executor}; + +use karyons_net::{Endpoint, Port}; + +use karyons_p2p::{Backend, Config, PeerID}; + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +struct Cli { +    /// Optional list of bootstrap peers to start the seeding process. +    #[arg(short)] +    bootstrap_peers: Vec<Endpoint>, + +    /// Optional list of peer endpoints for manual connections. +    #[arg(short)] +    peer_endpoints: Vec<Endpoint>, + +    /// Optional endpoint for accepting incoming connections. +    #[arg(short)] +    listen_endpoint: Option<Endpoint>, + +    /// Optional TCP/UDP port for the discovery service. +    #[arg(short)] +    discovery_port: Option<Port>, + +    /// Optional user id +    #[arg(long)] +    userid: Option<String>, +} + +fn main() { +    env_logger::init(); +    let cli = Cli::parse(); + +    let peer_id = match cli.userid { +        Some(userid) => PeerID::new(userid.as_bytes()), +        None => PeerID::random(), +    }; + +    // Create the configuration for the backend. +    let config = Config { +        listen_endpoint: cli.listen_endpoint, +        peer_endpoints: cli.peer_endpoints, +        bootstrap_peers: cli.bootstrap_peers, +        discovery_port: cli.discovery_port.unwrap_or(0), +        ..Default::default() +    }; + +    // Create a new Backend +    let backend = Backend::new(peer_id, config); + +    let (ctrlc_s, ctrlc_r) = channel::unbounded(); +    let handle = move || ctrlc_s.try_send(()).unwrap(); +    ctrlc::set_handler(handle).unwrap(); + +    let (signal, shutdown) = channel::unbounded::<()>(); + +    // Create a new Executor +    let ex = Arc::new(Executor::new()); + +    let task = async { +        let monitor = backend.monitor().await; + +        let monitor_task = ex.spawn(async move { +            loop { +                let event = monitor.recv().await.unwrap(); +                println!("{}", event); +            } +        }); + +        // Run the backend +        backend.run(ex.clone()).await.unwrap(); + +        // Wait for ctrlc signal +        ctrlc_r.recv().await.unwrap(); + +        // Shutdown the backend +        backend.shutdown().await; + +        monitor_task.cancel().await; + +        drop(signal); +    }; + +    // Run four executor threads. +    Parallel::new() +        .each(0..4, |_| future::block_on(ex.run(shutdown.recv()))) +        .finish(|| future::block_on(task)); +} diff --git a/p2p/examples/net_simulation.sh b/p2p/examples/net_simulation.sh new file mode 100755 index 0000000..1a05adf --- /dev/null +++ b/p2p/examples/net_simulation.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +# build +cargo build --release --example peer  + +tmux new-session -d -s karyons_p2p  + +tmux send-keys -t karyons_p2p "../../target/release/examples/peer --userid 'peer1'\ +    -l 'tcp://127.0.0.1:30000' -d  '30010'" Enter + +tmux split-window -h -t karyons_p2p +tmux send-keys -t karyons_p2p "../../target/release/examples/peer --userid 'peer2'\ +    -l 'tcp://127.0.0.1:30001' -d  '30011' -b 'tcp://127.0.0.1:30010 ' " Enter + +tmux split-window -h -t karyons_p2p +tmux send-keys -t karyons_p2p "../../target/release/examples/peer --userid 'peer3'\ +    -l 'tcp://127.0.0.1:30002' -d  '30012' -b 'tcp://127.0.0.1:30010'" Enter + +tmux split-window -h -t karyons_p2p +tmux send-keys -t karyons_p2p "../../target/release/examples/peer --userid 'peer4'\ +    -l 'tcp://127.0.0.1:30003' -d  '30013' -b 'tcp://127.0.0.1:30010'" Enter + +tmux split-window -h -t karyons_p2p +tmux send-keys -t karyons_p2p "../../target/release/examples/peer --userid 'peer5'\ +    -l 'tcp://127.0.0.1:30004' -d  '30014' -b 'tcp://127.0.0.1:30010'" Enter + +tmux split-window -h -t karyons_p2p +tmux send-keys -t karyons_p2p "../../target/release/examples/peer --userid 'peer6'\ +    -l 'tcp://127.0.0.1:30005' -d  '30015' -b 'tcp://127.0.0.1:30010'" Enter + +tmux select-layout even-horizontal + +sleep 3; + +tmux select-pane -t karyons_p2p:0.0 + +tmux split-window -v -t karyons_p2p +tmux send-keys -t karyons_p2p "../../target/release/examples/peer --userid 'peer7'\ +    -b 'tcp://127.0.0.1:30010' -b 'tcp://127.0.0.1:30011'" Enter + +tmux select-pane -t karyons_p2p:0.2 + +tmux split-window -v -t karyons_p2p +tmux send-keys -t karyons_p2p "../../target/release/examples/peer --userid 'peer8'\ +    -b 'tcp://127.0.0.1:30010' -b 'tcp://127.0.0.1:30012' -p 'tcp://127.0.0.1:30005'" Enter + +tmux select-pane -t karyons_p2p:0.4 + +tmux split-window -v -t karyons_p2p +tmux send-keys -t karyons_p2p "../../target/release/examples/peer --userid 'peer9'\ +    -b 'tcp://127.0.0.1:30010' -b 'tcp://127.0.0.1:30013'" Enter + +tmux select-pane -t karyons_p2p:0.6 + +tmux split-window -v -t karyons_p2p +tmux send-keys -t karyons_p2p "../../target/release/examples/peer --userid 'peer10'\ +    -b 'tcp://127.0.0.1:30010' -b 'tcp://127.0.0.1:30014'" Enter + +tmux select-pane -t karyons_p2p:0.8 + +tmux split-window -v -t karyons_p2p +tmux send-keys -t karyons_p2p "../../target/release/examples/peer --userid 'peer11'\ +    -b 'tcp://127.0.0.1:30010' -b 'tcp://127.0.0.1:30015'" Enter + +tmux select-pane -t karyons_p2p:0.10 + +tmux split-window -v -t karyons_p2p +tmux send-keys -t karyons_p2p "../../target/release/examples/peer --userid 'peer12'\ +    -b 'tcp://127.0.0.1:30010' -b 'tcp://127.0.0.1:30015' -b 'tcp://127.0.0.1:30011'" Enter + +# tmux set-window-option -t karyons_p2p synchronize-panes on + +tmux attach -t karyons_p2p diff --git a/p2p/examples/peer.rs b/p2p/examples/peer.rs new file mode 100644 index 0000000..f805d68 --- /dev/null +++ b/p2p/examples/peer.rs @@ -0,0 +1,82 @@ +use std::sync::Arc; + +use clap::Parser; +use easy_parallel::Parallel; +use smol::{channel, future, Executor}; + +use karyons_net::{Endpoint, Port}; + +use karyons_p2p::{Backend, Config, PeerID}; + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +struct Cli { +    /// Optional list of bootstrap peers to start the seeding process. +    #[arg(short)] +    bootstrap_peers: Vec<Endpoint>, + +    /// Optional list of peer endpoints for manual connections. +    #[arg(short)] +    peer_endpoints: Vec<Endpoint>, + +    /// Optional endpoint for accepting incoming connections. +    #[arg(short)] +    listen_endpoint: Option<Endpoint>, + +    /// Optional TCP/UDP port for the discovery service. +    #[arg(short)] +    discovery_port: Option<Port>, + +    /// Optional user id +    #[arg(long)] +    userid: Option<String>, +} + +fn main() { +    env_logger::init(); +    let cli = Cli::parse(); + +    let peer_id = match cli.userid { +        Some(userid) => PeerID::new(userid.as_bytes()), +        None => PeerID::random(), +    }; + +    // Create the configuration for the backend. +    let config = Config { +        listen_endpoint: cli.listen_endpoint, +        peer_endpoints: cli.peer_endpoints, +        bootstrap_peers: cli.bootstrap_peers, +        discovery_port: cli.discovery_port.unwrap_or(0), +        ..Default::default() +    }; + +    // Create a new Backend +    let backend = Backend::new(peer_id, config); + +    let (ctrlc_s, ctrlc_r) = channel::unbounded(); +    let handle = move || ctrlc_s.try_send(()).unwrap(); +    ctrlc::set_handler(handle).unwrap(); + +    let (signal, shutdown) = channel::unbounded::<()>(); + +    // Create a new Executor +    let ex = Arc::new(Executor::new()); + +    let task = async { +        // Run the backend +        backend.run(ex.clone()).await.unwrap(); + +        // Wait for ctrlc signal +        ctrlc_r.recv().await.unwrap(); + +        // Shutdown the backend +        backend.shutdown().await; + +        drop(signal); +    }; + +    // Run four executor threads. +    Parallel::new() +        .each(0..4, |_| future::block_on(ex.run(shutdown.recv()))) +        .finish(|| future::block_on(task)); +} | 
