Skip to content

Rust implementation of Hyperswarm, a networking stack for connecting peers

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

datrs/hyperswarm-rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

hyperswarm-rs

Peer to peer networking stack

NOTE: This is still in early stages. See the roadmap below. Please feel free to open issues and send PRs :-)

Installation

$ cargo add hyperswarm --git https://github.com/datrs/hyperswarm-rs.git

Usage

Hyperswarm is a networking stack for connecting peers who are interested in a topic. This project is a port of the Node.js implementation of Hyperswarm.

This crate exposes a Hyperswarm struct. After binding it, this will:

  • Start and bootstrap a local DHT node
  • Bind a socket for mDNS discovery
  • Announce and lookup any 32 byte topic key over both mDNS and the DHT
  • Connect to all peers that are found over both TCP and UTP

It currently depends on the unreleased hyperswarm-dht crate and therefore is also not yet released on crates.io.

The API is designed to be very simple:

use async_std::task;
use futures_lite::{AsyncReadExt, AsyncWriteExt, StreamExt};
use hyperswarm::{Config, Hyperswarm, HyperswarmStream, TopicConfig};
use std::io;

#[async_std::main]
async fn main() -> io::Result<()> {
    // Bind and initialize the swarm with the default config.
    // On the config you can e.g. set bootstrap addresses.
    let config = Config::default();
    let mut swarm = Hyperswarm::bind(config).await?;

    // A topic is any 32 byte array. Usually, this would be the hash of some identifier.
    // Configuring the swarm for a topic starts to lookup and/or announce this topic
    // and connect to peers that are found.
    let topic = [0u8; 32];
    swarm.configure(topic, TopicConfig::announce_and_lookup());

    // The swarm is a Stream of new HyperswarmStream peer connections.
    // The HyperswarmStream is a wrapper around either a TcpStream or a UtpSocket.
    // Usually you'll want to run some loop over the connection, so let's spawn a task
    // for each connection.
    while let Some(stream) = swarm.next().await {
        task::spawn(on_connection(stream?));
    }

    Ok(())
}

// A HyperswarmStream is AsyncRead + AsyncWrite, so you can use it just
// like a TcpStream. Here, we'll send an initial message and then keep
// reading from the stream until it is closed by the remote.
async fn on_connection(mut stream: HyperswarmStream) -> io::Result<()> {
    stream.write_all(b"hello there").await?;
    let mut buf = vec![0u8; 64];
    loop {
        match stream.read(&mut buf).await {
            Ok(0) => return Ok(()),
            Err(e) => return Err(e),
            Ok(n) => eprintln!("received: {}", std::str::from_utf8(&buf[..n]).unwrap()),
        }
    }
}

Examples

Simple example with Node.js interop

See examples/simple.rs for a working example that also runs a bootstrap node. That example can also find and connect to NodeJS peers. To try it out:

cargo run --example simple
# in another terminal
node js/simple.js

Currently, the DHT bootstrap node has to be run from Rust. The Rust implementation does not find peers on a NodeJS bootstrap node.

Hyperchat

examples/hyperchat.rs is a very basic chat-over-hyperswarm example. To try locally you'll need three terminals

  1. Run a bootstrap node:
$ cargo run --example hyperchat -- bootstrap`
Running bootstrap node on 0.0.0.0:49737
  1. Run clients and write with each other.
$ cargo run --example hyperchat -- join --topics asdf --name alice
your name: alice
join topic "asdf": a05d11c6234b3321315ec175592dfc193f5650a28b569b3e09bac5a4216bb138
[tcp:127.0.0.1:42172] connected
[utp:127.0.0.1:38683] connected
[utp:127.0.0.1:38683] is now known as `bob`
[tcp:127.0.0.1:42172] disconnected
[utp:127.0.0.1:38683] <bob> hi there :)
hello!
$ cargo run --example hyperchat -- join -t asdf -n bob
your name: bob
join topic "asdf": a05d11c6234b3321315ec175592dfc193f5650a28b569b3e09bac5a4216bb138
[utp:127.0.0.1:41187] connected
[utp:127.0.0.1:41187] is now known as `alice`
hi there :)
[utp:127.0.0.1:41187] <alice> hello!

Roadmap

  • Initial implementation
  • Find peers over the Hyperswarm DHT
    • Both NodeJS and Rust peers are found if connecting to a Rust bootstrap node
    • Fix hyperswarm-dht to work with NodeJS bootstrap nodes
  • Find peers over mDNS
    • Change colmeia-mdns to better fit the architecture here or copy and adapt the mdns code over into the mdns module
  • Connect to peers over TCP
  • Connect to peers over UTP
    • Can connect to peers over UTP
    • Fix issues in libutp-rs - sometimes the connection is not flushed properly

Safety

This crate uses #![deny(unsafe_code)] to ensure everything is implemented in 100% Safe Rust.

Contributing

Want to join us? Check out our "Contributing" guide and take a look at some of these issues:

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

About

Rust implementation of Hyperswarm, a networking stack for connecting peers

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published