Back to Project List

mquictt

Create a library for MQTT over QUIC, leveraging the concureent streams of QUIC to multiplex the MQTT publishes and subscribes over to seperate streams.

Repository Video ▶️

MQuicTT

MQuicTT logo


A rustlang utility/library for [MQTT] over [QUIC].

QUIC allows us to send data over multiple concurrent streams. We can leverage this ability to multiplex the pub-sub architecture of MQTT. This means that: - when a MQTT client is subscribed to multiple topics, it can get data for these subscriptions concurrently. Even if data for some subscriptions gets delayed, rest of the subscriptions can carry on. When running MQTT over TCP, a single subscription's data being delayed can block rest of the data as well (see [head-of-line blocking]). Similarly on the server side, the server can send data for multiple subscriptions concurrently. - when a MQTT client publishes messages on multiple topics, these can again me sent concurrently, and the server can receive them concurrently.

QUIC also provides at-most-once message delivery guarantees, and thus the MQTT running on top of it gets QoS2 support by default. Thus the library does not give an option to configure the QoS.

As QUIC is basically a state-machine slapped on top of UDP, the only change needed is at application level. We can use the UDP APIs exposed by the Rust's standard library and we are good to go!.

Usage

To create a MQTT server:

async fn spawn_server() {
    mquictt::server(
        &([127, 0, 0, 1], 1883).into(),
        mquictt::Config::empty(),
    )
    .await
    .unwrap();
}

To create a MQTT client:

use std::net::SocketAddr;

async fn spawn_client(
    bind_addr: &SocketAddr,
    connect_addr: &SocketAddr
) -> Result<(), mquictt::Error> {
    // create a client
    let mut client = mquictt::Client::connect(
        bind_addr,
        connect_addr,
        "localhost",
        "mquictt-client",
    )
    .await?;

    // create a publisher for a particular topic
    let mut publisher = client.publisher("hello/world", b"hello".into()).await?;
    publisher.publish(b"hello again!".into()).await?;

    // create a subscriber
    let mut subscriber = client.subscriber("hello/world").await?;
    println!("{}", str::from_utf8(&subscriber.read()?).unwrap());
}

Acknowledgements

We use: - quinn-rs/quinn underneath to interface with QUIC - bytebeamio/mqttbytes to parse MQTT packets

Abhik Jain
Devdutt Shenoi

We aren't able to make a presentation due to a lot of errors such as "invalid certificate: BadDER" that we were unable to debug/fix. We have decided to end our battle with the error demons for today, but they won't survive the next time we are challenged :D

November 14, 2021

Project created by Abhik Jain

November 11, 2021