-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: Rewrite README (& add
echo.rs
example) (#2960)
## Description <!-- A summary of what this pull request achieves and a rough list of changes. --> - Rewrote the README - Renamed `iroh-router/examples/custom-protocol.rs` to `search.rs` (It's not a "custom" protocol. Just a protocol.) Removed "custom" wording - Added a simpler `echo.rs` example (used in the README) ## Notes & open questions <!-- Any notes, remarks or open questions you have to make about the PR. --> - In the "repository structure" section, I describe the purpose of *some* crates, but not all. Since stuff will be moving around in the coming weeks, I *think* that's, fine, but someone please tell me if we should do sth differently there. ## Change checklist - [x] Self-review. - [x] Documentation updates following the [style guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text), if relevant. - [x] Tests if relevant. - [x] All breaking changes documented.
- Loading branch information
Showing
4 changed files
with
242 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
//! Very basic example to showcase how to use iroh's APIs. | ||
//! | ||
//! This example implements a simple protocol that echos any data sent to it in the first stream. | ||
//! | ||
//! ## Usage | ||
//! | ||
//! cargo run --example echo --features=examples | ||
use std::sync::Arc; | ||
|
||
use anyhow::Result; | ||
use futures_lite::future::Boxed as BoxedFuture; | ||
use iroh_net::{endpoint::Connecting, Endpoint, NodeAddr}; | ||
use iroh_router::{ProtocolHandler, Router}; | ||
|
||
/// Each protocol is identified by its ALPN string. | ||
/// | ||
/// The ALPN, or application-layer protocol negotiation, is exchanged in the connection handshake, | ||
/// and the connection is aborted unless both nodes pass the same bytestring. | ||
const ALPN: &[u8] = b"iroh-example/echo/0"; | ||
|
||
#[tokio::main] | ||
async fn main() -> Result<()> { | ||
let router = accept_side().await?; | ||
let node_addr = router.endpoint().node_addr().await?; | ||
|
||
connect_side(node_addr).await?; | ||
|
||
router.shutdown().await?; | ||
|
||
Ok(()) | ||
} | ||
|
||
async fn connect_side(addr: NodeAddr) -> Result<()> { | ||
let endpoint = Endpoint::builder().discovery_n0().bind().await?; | ||
|
||
// Open a connection to the accepting node | ||
let conn = endpoint.connect(addr, ALPN).await?; | ||
|
||
// Open a bidirectional QUIC stream | ||
let (mut send, mut recv) = conn.open_bi().await?; | ||
|
||
// Send some data to be echoed | ||
send.write_all(b"Hello, world!").await?; | ||
|
||
// Signal the end of transfer. | ||
send.finish()?; | ||
|
||
// Receive the echo | ||
let response = recv.read_to_end(1000).await?; | ||
assert_eq!(&response, b"Hello, world!"); | ||
|
||
// Close the endpoint (and all its connections) in one: | ||
endpoint.close(0u32.into(), b"bye!").await?; | ||
|
||
Ok(()) | ||
} | ||
|
||
async fn accept_side() -> Result<Router> { | ||
let endpoint = Endpoint::builder().discovery_n0().bind().await?; | ||
|
||
// Build our protocol handler and add our protocol, identified by its ALPN, and spawn the node. | ||
let router = Router::builder(endpoint) | ||
.accept(ALPN, Arc::new(Echo)) | ||
.spawn() | ||
.await?; | ||
|
||
Ok(router) | ||
} | ||
|
||
#[derive(Debug, Clone)] | ||
struct Echo; | ||
|
||
impl ProtocolHandler for Echo { | ||
/// The `accept` method is called for each incoming connection for our ALPN. | ||
/// | ||
/// The returned future runs on a newly spawned tokio task, so it can run as long as | ||
/// the connection lasts. | ||
fn accept(self: Arc<Self>, connecting: Connecting) -> BoxedFuture<Result<()>> { | ||
// We have to return a boxed future from the handler. | ||
Box::pin(async move { | ||
// Wait for the connection to be fully established. | ||
let connection = connecting.await?; | ||
// We can get the remote's node id from the connection. | ||
let node_id = iroh_net::endpoint::get_remote_node_id(&connection)?; | ||
println!("accepted connection from {node_id}"); | ||
|
||
// Our protocol is a simple request-response protocol, so we expect the | ||
// connecting peer to open a single bi-directional stream. | ||
let (mut send, mut recv) = connection.accept_bi().await?; | ||
|
||
// Echo any bytes received back directly. | ||
let bytes_sent = tokio::io::copy(&mut recv, &mut send).await?; | ||
println!("Copied over {bytes_sent} byte(s)"); | ||
|
||
// By calling `finish` on the send stream we signal that we will not send anything | ||
// further, which makes the receive stream on the other end terminate. | ||
send.finish()?; | ||
|
||
// Wait until the remote closes the connection, which it does once it | ||
// received the response. | ||
connection.closed().await; | ||
|
||
Ok(()) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters