Skip to content

Commit

Permalink
deploy: 0db1efc
Browse files Browse the repository at this point in the history
  • Loading branch information
mempirate committed Aug 28, 2024
1 parent af8e786 commit 342b786
Show file tree
Hide file tree
Showing 13 changed files with 144 additions and 69 deletions.
2 changes: 0 additions & 2 deletions css/chrome.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
/* CSS for UI elements (a.k.a. chrome) */

@import 'variables.css';

html {
scrollbar-color: var(--scrollbar) var(--bg);
}
Expand Down
2 changes: 0 additions & 2 deletions css/general.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
/* Base styles and content styles */

@import 'variables.css';

:root {
/* Browser default font-size is 16px, this way 1 rem = 10px */
font-size: 62.5%;
Expand Down
1 change: 1 addition & 0 deletions highlight.js

Large diffs are not rendered by default.

101 changes: 70 additions & 31 deletions print.html
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ <h2 id="contributing"><a class="header" href="#contributing">Contributing</a></h
<div style="break-before: page; page-break-before: always;"></div><h1 id="getting-started-with-msg-rs"><a class="header" href="#getting-started-with-msg-rs">Getting started with MSG-RS</a></h1>
<p>To add MSG-RS to your project, add the following to your <code>Cargo.toml</code> file:</p>
<pre><code class="language-toml">[dependencies]
msg = { git = &quot;https://github.com/chainbound/msg-rs&quot; }
msg = { git = "https://github.com/chainbound/msg-rs" }
</code></pre>
<p><strong>Warning: MSG-RS is currently in ALPHA, and is not yet recommended for use in production.</strong></p>
<p>We plan to release MSG-RS to <a href="https://crates.io/">Crates.io</a> once it reaches a beta stage.
Expand Down Expand Up @@ -263,23 +263,23 @@ <h2 id="requestreply"><a class="header" href="#requestreply">Request/Reply</a></
async fn main() {
// Initialize the reply socket (server side) with a transport
let mut rep = RepSocket::new(Tcp::default());
rep.bind(&quot;0.0.0.0:4444&quot;).await.unwrap();
rep.bind("0.0.0.0:4444").await.unwrap();

// Initialize the request socket (client side) with a transport
let mut req = ReqSocket::new(Tcp::default());
req.connect(&quot;0.0.0.0:4444&quot;).await.unwrap();
req.connect("0.0.0.0:4444").await.unwrap();

tokio::spawn(async move {
// Receive the request and respond with &quot;world&quot;
// Receive the request and respond with "world"
// (RepSocket implements `Stream`)
let req = rep.next().await.unwrap();
println!(&quot;Message: {:?}&quot;, req.msg());
println!("Message: {:?}", req.msg());

req.respond(Bytes::from(&quot;world&quot;)).unwrap();
req.respond(Bytes::from("world")).unwrap();
});

let res: Bytes = req.request(Bytes::from(&quot;hello&quot;)).await.unwrap();
println!(&quot;Response: {:?}&quot;, res);
let res: Bytes = req.request(Bytes::from("hello")).await.unwrap();
println!("Response: {:?}", res);
}</code></pre></pre>
<h2 id="publishsubscribe"><a class="header" href="#publishsubscribe">Publish/Subscribe</a></h2>
<p>The publish/subscribe socket type is used for sending a message to multiple subscribers.
Expand All @@ -296,24 +296,24 @@ <h2 id="publishsubscribe"><a class="header" href="#publishsubscribe">Publish/Sub
async fn main() {
// Initialize the publisher socket (server side) with a transport
let mut pub_socket = PubSocket::new(Tcp::default());
pub_socket.bind(&quot;0.0.0.0:4444&quot;).await.unwrap();
pub_socket.bind("0.0.0.0:4444").await.unwrap();

// Initialize the subscriber socket (client side) with a transport
let mut sub_socket = SubSocket::new(Tcp::default());
sub_socket.connect(&quot;0.0.0.0:4444&quot;).await.unwrap();
sub_socket.connect("0.0.0.0:4444").await.unwrap();

let topic = &quot;some_interesting_topic&quot;.to_string();
let topic = "some_interesting_topic".to_string();

// Subscribe to a topic
sub_socket.subscribe(topic.clone()).await.unwrap();

tokio::spawn(async move {
// Values are `bytes::Bytes`
pub_socket.publish(topic, Bytes::from(&quot;hello_world&quot;)).await.unwrap();
pub_socket.publish(topic, Bytes::from("hello_world")).await.unwrap();
});

let msg = sub_socket.next().await.unwrap();
println!(&quot;Received message: {:?}&quot;, msg);
println!("Received message: {:?}", msg);
}</code></pre></pre>
<!-- External -->
<!-- MSG links -->
Expand All @@ -325,9 +325,9 @@ <h2 id="publishsubscribe"><a class="header" href="#publishsubscribe">Publish/Sub
<ul>
<li><a href="usage/transport-layers.html#tcp">TCP</a></li>
<li><a href="usage/transport-layers.html#quic">QUIC</a></li>
<li><a href="usage/transport-layers.html#ipc">IPC</a></li>
</ul>
<!--
- [IPC](#ipc)
- [Inproc](#inproc)
- [UDP](#udp)
- [TLS](#tls)
Expand All @@ -351,13 +351,13 @@ <h3 id="how-to-use-tcp"><a class="header" href="#how-to-use-tcp">How to use TCP<
let mut rep = RepSocket::new(Tcp::default());
// Bind the socket to the address. This will start listening for incoming connections.
// This method does DNS resolution internally, so you can use hostnames here.
rep.bind(&quot;0.0.0.0:4444&quot;).await.unwrap();
rep.bind("0.0.0.0:4444").await.unwrap();

// Initialize the request socket (client side) with default TCP
let mut req = ReqSocket::new(Tcp::default());
// Connect the socket to the address. This will initiate a connection to the server.
// This method does DNS resolution internally, so you can use hostnames here.
req.connect(&quot;0.0.0.0:4444&quot;).await.unwrap();
req.connect("0.0.0.0:4444").await.unwrap();

// ...
}</code></pre></pre>
Expand All @@ -366,13 +366,21 @@ <h3 id="why-choose-quic"><a class="header" href="#why-choose-quic">Why choose QU
<p>QUIC is a new transport layer protocol that is built on top of UDP. It is designed to provide the same
reliability &amp; security guarantees as TCP + TLS, while solving some of the issues that it has, like</p>
<ul>
<li><strong>Head-of-line blocking</strong>: If a packet is lost, all subsequent packets are held up until the lost packet is retransmitted. This can be a problem especially when multiplexing multiple streams over a single connection because it can cause a single slow stream to block all other streams.</li>
<li><strong>Slow connection setup</strong>: TCP + TLS requires 2-3 round trips to establish a connection, which can be slow on high latency networks.</li>
<li><strong>No support for multiplexing</strong>: TCP does not support multiplexing multiple streams over a single connection. This means that if you want to send multiple streams of data over a single connection, you have to implement your own multiplexing layer on top of TCP, which can run into issues like head-of-line blocking that we've seen above.</li>
<li><strong>Head-of-line blocking</strong>: If a packet is lost, all subsequent packets are held up until the lost packet
is retransmitted. This can be a problem especially when multiplexing multiple streams over a single
connection because it can cause a single slow stream to block all other streams.</li>
<li><strong>Slow connection setup</strong>: TCP + TLS requires 2-3 round trips to establish a connection, which can be
slow on high latency networks.</li>
<li><strong>No support for multiplexing</strong>: TCP does not support multiplexing multiple streams over a single connection.
This means that if you want to send multiple streams of data over a single connection, you have to
implement your own multiplexing layer on top of TCP, which can run into issues like head-of-line
blocking that we've seen above.</li>
</ul>
<h3 id="quic-in-msg"><a class="header" href="#quic-in-msg">QUIC in MSG</a></h3>
<p>The MSG QUIC implementation is based on <a href="https://github.com/quinn-rs/quinn">quinn</a>. It relies on self-signed certificates and does not verify
server certificates. Also, due to how our <code>Transport</code> abstraction works, we don't support QUIC connections with multiple streams. This means that the <code>Quic</code> transport implementation will do all its work over a single, bi-directional stream for now.</p>
<p>The MSG QUIC implementation is based on <a href="https://github.com/quinn-rs/quinn">quinn</a>. It relies on self-signed
certificates and does not verify server certificates. Also, due to how our <code>Transport</code> abstraction works, we
don't support QUIC connections with multiple streams. This means that the <code>Quic</code> transport implementation will
do all its work over a single, bi-directional stream for now.</p>
<h3 id="how-to-use-quic"><a class="header" href="#how-to-use-quic">How to use QUIC</a></h3>
<p>In MSG, here is how you can setup any socket type with the QUIC transport:</p>
<pre><pre class="playground"><code class="language-rust">use msg::{RepSocket, ReqSocket, Quic};
Expand All @@ -383,13 +391,44 @@ <h3 id="how-to-use-quic"><a class="header" href="#how-to-use-quic">How to use QU
let mut rep = RepSocket::new(Quic::default());
// Bind the socket to the address. This will start listening for incoming connections.
// This method does DNS resolution internally, so you can use hostnames here.
rep.bind(&quot;0.0.0.0:4444&quot;).await.unwrap();
rep.bind("0.0.0.0:4444").await.unwrap();

// Initialize the request socket (client side) with default QUIC
let mut req = ReqSocket::new(Quic::default());
// Connect the socket to the address. This will initiate a connection to the server.
// This method does DNS resolution internally, so you can use hostnames here.
req.connect(&quot;0.0.0.0:4444&quot;).await.unwrap();
req.connect("0.0.0.0:4444").await.unwrap();

// ...
}</code></pre></pre>
<h2 id="ipc"><a class="header" href="#ipc">IPC</a></h2>
<p>More precisely, MSG-RS supports <a href="https://en.wikipedia.org/wiki/Unix_domain_socket">Unix Domain Sockets (UDS)</a> for IPC.</p>
<h3 id="why-choose-ipc"><a class="header" href="#why-choose-ipc">Why choose IPC?</a></h3>
<p>IPC is a transport layer that allows for communication between processes on the same machine.
The main difference between IPC and other transport layers is that IPC sockets use the filesystem
as the address namespace.</p>
<p>IPC is useful when you want to avoid the overhead of network sockets and want to have a low-latency
communication link between processes on the same machine, all while being able to use the same API
as the other transport layers that MSG-RS supports.</p>
<p>Due to its simplicity, IPC is typically faster than TCP and QUIC, but the exact performance improvements
also depend on the throughput of the underlying UDS implementation. We only recommend using IPC when you
know that the performance benefits outweigh the overhead of using a network socket.</p>
<h3 id="how-to-use-ipc"><a class="header" href="#how-to-use-ipc">How to use IPC</a></h3>
<p>In MSG, here is how you can setup any socket type with the IPC transport:</p>
<pre><pre class="playground"><code class="language-rust">use msg::{RepSocket, ReqSocket, Ipc};

#[tokio::main]
async fn main() {
// Initialize the reply socket (server side) with default IPC
let mut rep = RepSocket::new(Ipc::default());
// Bind the socket to the address. This will start listening for incoming connections.
// You can use any path that is valid for a Unix Domain Socket.
rep.bind("/tmp/msg.sock").await.unwrap();

// Initialize the request socket (client side) with default IPC
let mut req = ReqSocket::new(Ipc::default());
// Connect the socket to the address. This will initiate a connection to the server.
req.connect("/tmp/msg.sock").await.unwrap();

// ...
}</code></pre></pre>
Expand Down Expand Up @@ -426,7 +465,7 @@ <h3 id="how-to-use-quic"><a class="header" href="#how-to-use-quic">How to use QU

impl Authenticator for Auth {
fn authenticate(&amp;self, id: &amp;Bytes) -&gt; bool {
println!(&quot;Auth request from: {:?}&quot;, id);
println!("Auth request from: {:?}", id);
// Custom authentication logic goes here
// ...
true
Expand All @@ -438,14 +477,14 @@ <h3 id="how-to-use-quic"><a class="header" href="#how-to-use-quic">How to use QU
// Initialize the reply socket (server side) with a transport
// and an authenticator that we just implemented:
let mut rep = RepSocket::new(Tcp::default()).with_auth(Auth);
rep.bind(&quot;0.0.0.0:4444&quot;).await.unwrap();
rep.bind("0.0.0.0:4444").await.unwrap();

// Initialize the request socket (client side) with a transport
// and an identifier. This will implicitly turn on client authentication.
// The identifier will be sent to the server when the connection is established.
let mut req = ReqSocket::with_options(
Tcp::default(),
ReqOptions::default().auth_token(Bytes::from(&quot;client1&quot;)),
ReqOptions::default().auth_token(Bytes::from("client1")),
);

...
Expand Down Expand Up @@ -475,7 +514,7 @@ <h2 id="requestresponse"><a class="header" href="#requestresponse">Request/Respo
// Enable Gzip compression (compression level 6).
.with_compressor(GzipCompressor::new(6));

rep.bind(&quot;0.0.0.0:4444&quot;).await.unwrap();
rep.bind("0.0.0.0:4444").await.unwrap();

// Initialize the request socket (client side) with a transport
let mut req = ReqSocket::new(Tcp::default())
Expand All @@ -484,7 +523,7 @@ <h2 id="requestresponse"><a class="header" href="#requestresponse">Request/Respo
// use the same compression algorithm or level.
.with_compressor(GzipCompressor::new(6));

req.connect(&quot;0.0.0.0:4444&quot;).await.unwrap();
req.connect("0.0.0.0:4444").await.unwrap();

// ...
}</code></pre></pre>
Expand All @@ -504,8 +543,8 @@ <h2 id="publishsubscribe-1"><a class="header" href="#publishsubscribe-1">Publish

// ...
}</code></pre></pre>
<p>By looking at this example, you might be wondering: &quot;how does the subscriber know that the
publisher is compressing messages, if the subscriber is not configured with Gzip compression?&quot;</p>
<p>By looking at this example, you might be wondering: "how does the subscriber know that the
publisher is compressing messages, if the subscriber is not configured with Gzip compression?"</p>
<p>The answer is that in MSG, compression is defined by the publisher for each message that is sent.
In practice, each message contains info in its <code>Header</code> that tells the subscriber whether the message
payload is compressed - and if so, which compression algorithm was used. The subscriber then uses this
Expand Down Expand Up @@ -540,7 +579,7 @@ <h2 id="metrics"><a class="header" href="#metrics">Metrics</a></h2>
<!-- Chainbound links -->
<div style="break-before: page; page-break-before: always;"></div><h1 id="faq"><a class="header" href="#faq">FAQ</a></h1>
<h2 id="how-do-i-pronounce-msg-rs"><a class="header" href="#how-do-i-pronounce-msg-rs">How do I pronounce MSG-RS?</a></h2>
<p>You can either pronounce it as &quot;message&quot;, or as &quot;em-es-gee&quot;. We prefer the latter.</p>
<p>You can either pronounce it as "message", or as "em-es-gee". We prefer the latter.</p>
<h2 id="is-msg-rs-production-ready"><a class="header" href="#is-msg-rs-production-ready">Is MSG-RS production ready?</a></h2>
<p>MSG-RS is currently in ALPHA, and is not yet recommended for use in production.</p>
<p>We plan to release MSG-RS to <a href="https://crates.io/">Crates.io</a> once it reaches a beta stage.
Expand Down
2 changes: 1 addition & 1 deletion searcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ window.search = window.search || {};

// Eventhandler for keyevents on `document`
function globalKeyHandler(e) {
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey || e.target.type === 'textarea' || e.target.type === 'text') { return; }
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey || e.target.type === 'textarea' || e.target.type === 'text' || !hasFocus() && /^(?:input|select|textarea)$/i.test(e.target.nodeName)) { return; }

if (e.keyCode === ESCAPE_KEYCODE) {
e.preventDefault();
Expand Down
2 changes: 1 addition & 1 deletion searchindex.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion searchindex.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions usage/authentication.html
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ <h1 id="authentication"><a class="header" href="#authentication">Authentication<

impl Authenticator for Auth {
fn authenticate(&amp;self, id: &amp;Bytes) -&gt; bool {
println!(&quot;Auth request from: {:?}&quot;, id);
println!("Auth request from: {:?}", id);
// Custom authentication logic goes here
// ...
true
Expand All @@ -215,14 +215,14 @@ <h1 id="authentication"><a class="header" href="#authentication">Authentication<
// Initialize the reply socket (server side) with a transport
// and an authenticator that we just implemented:
let mut rep = RepSocket::new(Tcp::default()).with_auth(Auth);
rep.bind(&quot;0.0.0.0:4444&quot;).await.unwrap();
rep.bind("0.0.0.0:4444").await.unwrap();

// Initialize the request socket (client side) with a transport
// and an identifier. This will implicitly turn on client authentication.
// The identifier will be sent to the server when the connection is established.
let mut req = ReqSocket::with_options(
Tcp::default(),
ReqOptions::default().auth_token(Bytes::from(&quot;client1&quot;)),
ReqOptions::default().auth_token(Bytes::from("client1")),
);

...
Expand Down
8 changes: 4 additions & 4 deletions usage/compression.html
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ <h2 id="requestresponse"><a class="header" href="#requestresponse">Request/Respo
// Enable Gzip compression (compression level 6).
.with_compressor(GzipCompressor::new(6));

rep.bind(&quot;0.0.0.0:4444&quot;).await.unwrap();
rep.bind("0.0.0.0:4444").await.unwrap();

// Initialize the request socket (client side) with a transport
let mut req = ReqSocket::new(Tcp::default())
Expand All @@ -204,7 +204,7 @@ <h2 id="requestresponse"><a class="header" href="#requestresponse">Request/Respo
// use the same compression algorithm or level.
.with_compressor(GzipCompressor::new(6));

req.connect(&quot;0.0.0.0:4444&quot;).await.unwrap();
req.connect("0.0.0.0:4444").await.unwrap();

// ...
}</code></pre></pre>
Expand All @@ -224,8 +224,8 @@ <h2 id="publishsubscribe"><a class="header" href="#publishsubscribe">Publish/Sub

// ...
}</code></pre></pre>
<p>By looking at this example, you might be wondering: &quot;how does the subscriber know that the
publisher is compressing messages, if the subscriber is not configured with Gzip compression?&quot;</p>
<p>By looking at this example, you might be wondering: "how does the subscriber know that the
publisher is compressing messages, if the subscriber is not configured with Gzip compression?"</p>
<p>The answer is that in MSG, compression is defined by the publisher for each message that is sent.
In practice, each message contains info in its <code>Header</code> that tells the subscriber whether the message
payload is compressed - and if so, which compression algorithm was used. The subscriber then uses this
Expand Down
2 changes: 1 addition & 1 deletion usage/faq.html
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ <h1 class="menu-title">The MSG-RS Book</h1>
<main>
<h1 id="faq"><a class="header" href="#faq">FAQ</a></h1>
<h2 id="how-do-i-pronounce-msg-rs"><a class="header" href="#how-do-i-pronounce-msg-rs">How do I pronounce MSG-RS?</a></h2>
<p>You can either pronounce it as &quot;message&quot;, or as &quot;em-es-gee&quot;. We prefer the latter.</p>
<p>You can either pronounce it as "message", or as "em-es-gee". We prefer the latter.</p>
<h2 id="is-msg-rs-production-ready"><a class="header" href="#is-msg-rs-production-ready">Is MSG-RS production ready?</a></h2>
<p>MSG-RS is currently in ALPHA, and is not yet recommended for use in production.</p>
<p>We plan to release MSG-RS to <a href="https://crates.io/">Crates.io</a> once it reaches a beta stage.
Expand Down
2 changes: 1 addition & 1 deletion usage/getting-started.html
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ <h1 class="menu-title">The MSG-RS Book</h1>
<h1 id="getting-started-with-msg-rs"><a class="header" href="#getting-started-with-msg-rs">Getting started with MSG-RS</a></h1>
<p>To add MSG-RS to your project, add the following to your <code>Cargo.toml</code> file:</p>
<pre><code class="language-toml">[dependencies]
msg = { git = &quot;https://github.com/chainbound/msg-rs&quot; }
msg = { git = "https://github.com/chainbound/msg-rs" }
</code></pre>
<p><strong>Warning: MSG-RS is currently in ALPHA, and is not yet recommended for use in production.</strong></p>
<p>We plan to release MSG-RS to <a href="https://crates.io/">Crates.io</a> once it reaches a beta stage.
Expand Down
Loading

0 comments on commit 342b786

Please sign in to comment.