-
Notifications
You must be signed in to change notification settings - Fork 236
chore(iroh): Add echo-no-router.rs
example
#3267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
b8ca9db
chore(iroh): Add `echo-no-router.rs` example
matheus23 a318617
Code review
matheus23 f727187
Rename `accept_side` -> `start_accept_side`
matheus23 35804df
Whitespace format
matheus23 978b11e
Update iroh/examples/echo-no-router.rs
matheus23 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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,102 @@ | ||
//! Very basic example showing how to implement a basic echo protocol, | ||
//! without using the `Router` API. (For the router version, check out the echo.rs example.) | ||
//! | ||
//! The echo protocol echos any data sent to it in the first stream. | ||
//! | ||
//! ## Running the Example | ||
//! | ||
//! cargo run --example echo-no-router --features=examples | ||
|
||
use anyhow::Result; | ||
use iroh::{Endpoint, NodeAddr}; | ||
|
||
/// 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 endpoint = accept_side().await?; | ||
let node_addr = endpoint.node_addr().await?; | ||
|
||
connect_side(node_addr).await?; | ||
|
||
endpoint.close().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 on this particular stream. | ||
matheus23 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
send.finish()?; | ||
|
||
// Receive the echo | ||
matheus23 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let response = recv.read_to_end(1000).await?; | ||
assert_eq!(&response, b"Hello, world!"); | ||
|
||
// Explicitly close the whole connection. | ||
conn.close(0u32.into(), b"bye!"); | ||
matheus23 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Ok(()) | ||
} | ||
|
||
async fn accept_side() -> Result<Endpoint> { | ||
let endpoint = Endpoint::builder() | ||
.discovery_n0() | ||
.alpns(vec![ALPN.to_vec()]) | ||
matheus23 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
.bind() | ||
.await?; | ||
|
||
let ep = endpoint.clone(); // Cloning so we can both return it and use it in the tokio task | ||
matheus23 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// spawn a task so that `accept_side` returns immediately and we can continue in main(). | ||
tokio::spawn(async move { | ||
matheus23 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// This task won't leak, because we call `endpoint.close()` in `main()`, | ||
// which causes `endpoint.accept().await` to return `None`. | ||
while let Some(incoming) = endpoint.accept().await { | ||
// spawn a task for each incoming connection, so we can serve multiple connections asynchronously | ||
tokio::spawn(async move { | ||
let connection = incoming.await?; | ||
|
||
// We can get the remote's node id from the connection. | ||
let node_id = connection.remote_node_id()?; | ||
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. | ||
matheus23 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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; | ||
|
||
anyhow::Ok(()) | ||
}); | ||
} | ||
|
||
anyhow::Ok(()) | ||
}); | ||
|
||
Ok(ep) | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.