-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathlib.rs
144 lines (140 loc) · 5.45 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//! ## Introduction
//!
//! Hypercore protocol is a streaming, message based protocol. This is a rust port of the wire
//! protocol implementation in [the original Javascript version][holepunch-hypercore] aiming
//! for interoperability with LTS version.
//!
//! This crate is built on top of the [hypercore] crate, which defines some structs used here.
//!
//! ## Design
//!
//! This crate does not include any IO related code, it is up to the user to supply a streaming IO
//! handler that implements the [AsyncRead] and [AsyncWrite] traits.
//!
//! When opening a Hypercore protocol stream on an IO handler, the protocol will perform a Noise
//! handshake followed by libsodium's [crypto_secretstream] to setup a secure and authenticated
//! connection. After that, each side can request any number of channels on the protocol. A
//! channel is opened with a [Key], a 32 byte buffer. Channels are only opened if both peers
//! opened a channel for the same key. It is automatically verified that both parties know the
//! key without transmitting the key itself.
//!
//! On a channel, the predefined messages, including a custom Extension message, of the Hypercore
//! protocol can be sent and received.
//!
//! ## Features
//!
//! ### `sparse` (default)
//!
//! When using disk storage for hypercore, clearing values may create sparse files. On by default.
//!
//! ### `async-std` (default)
//!
//! Use the async-std runtime, on by default. Either this or `tokio` is mandatory.
//!
//! ### `tokio`
//!
//! Use the tokio runtime. Either this or `async_std` is mandatory.
//!
//! ### `wasm-bindgen`
//!
//! Enable for WASM runtime support.
//!
//! ### `cache`
//!
//! Use a moka cache for hypercore's merkle tree nodes to speed-up reading.
//!
//! ## Example
//!
//! The following example opens a TCP server on localhost and connects to that server. Both ends
//! then open a channel with the same key and exchange a message.
//!
//! ```no_run
//! # async_std::task::block_on(async {
//! use hypercore_protocol::{ProtocolBuilder, Event, Message};
//! use hypercore_protocol::schema::*;
//! use async_std::prelude::*;
//! // Start a tcp server.
//! let listener = async_std::net::TcpListener::bind("localhost:8000").await.unwrap();
//! async_std::task::spawn(async move {
//! let mut incoming = listener.incoming();
//! while let Some(Ok(stream)) = incoming.next().await {
//! async_std::task::spawn(async move {
//! onconnection(stream, false).await
//! });
//! }
//! });
//!
//! // Connect a client.
//! let stream = async_std::net::TcpStream::connect("localhost:8000").await.unwrap();
//! onconnection(stream, true).await;
//!
//! /// Start Hypercore protocol on a TcpStream.
//! async fn onconnection (stream: async_std::net::TcpStream, is_initiator: bool) {
//! // A peer either is the initiator or a connection or is being connected to.
//! let name = if is_initiator { "dialer" } else { "listener" };
//! // A key for the channel we want to open. Usually, this is a pre-shared key that both peers
//! // know about.
//! let key = [3u8; 32];
//! // Create the protocol.
//! let mut protocol = ProtocolBuilder::new(is_initiator).connect(stream);
//!
//! // Iterate over the protocol events. This is required to "drive" the protocol.
//!
//! while let Some(Ok(event)) = protocol.next().await {
//! eprintln!("{} received event {:?}", name, event);
//! match event {
//! // The handshake event is emitted after the protocol is fully established.
//! Event::Handshake(_remote_key) => {
//! protocol.open(key.clone()).await;
//! },
//! // A Channel event is emitted for each established channel.
//! Event::Channel(mut channel) => {
//! // A Channel can be sent to other tasks.
//! async_std::task::spawn(async move {
//! // A Channel can both send messages and is a stream of incoming messages.
//! channel.send(Message::Want(Want { start: 0, length: 1 })).await;
//! while let Some(message) = channel.next().await {
//! eprintln!("{} received message: {:?}", name, message);
//! }
//! });
//! },
//! _ => {}
//! }
//! }
//! }
//! # })
//! ```
//!
//! Find more examples in the [Github repository][examples].
//!
//! [holepunch-hypercore]: https://github.com/holepunchto/hypercore
//! [datrs-hypercore]: https://github.com/datrs/hypercore
//! [AsyncRead]: futures_lite::AsyncRead
//! [AsyncWrite]: futures_lite::AsyncWrite
//! [examples]: https://github.com/datrs/hypercore-protocol-rs#examples
#![forbid(unsafe_code, future_incompatible, rust_2018_idioms)]
#![deny(missing_debug_implementations, nonstandard_style)]
#![warn(missing_docs, unreachable_pub)]
mod builder;
mod channels;
mod constants;
mod crypto;
mod duplex;
mod message;
mod protocol;
mod reader;
mod util;
mod writer;
/// The wire messages used by the protocol.
pub mod schema;
pub use builder::Builder as ProtocolBuilder;
pub use channels::Channel;
// Export the needed types for Channel::take_receiver, and Channel::local_sender()
pub use async_channel::{
Receiver as ChannelReceiver, SendError as ChannelSendError, Sender as ChannelSender,
};
pub use duplex::Duplex;
pub use hypercore; // Re-export hypercore
pub use message::Message;
pub use protocol::{Command, CommandTx, DiscoveryKey, Event, Key, Protocol};
pub use util::discovery_key;