ruma / lb

Ruma wrapper for low-bandwidth matrix
MIT License
2 stars 0 forks source link

Proper CoAP abstraction to match `matrix-org/go-coap` #3

Open ShadowJonathan opened 3 years ago

ShadowJonathan commented 3 years ago

There seems to be sparse support for specific CoAP clients that matches matrix-org/go-coap, which has the following clauses;

This is the matrix.org fork of go-coap, specialised for MSC3079. There are several reasons to fork the original implementation:

  • FIN packet handling is easier to do at the go-coap level, and is matrix.org specific. See these comments for context.
  • We were hitting many known issues with the original implementation around retry handling, congestion control (NSTART handling), accessing MIDs on UDP messages, etc.
  • We want to add WebSockets support.

This repo was originally forked from an even earlier implementation for FOSDEM 2019, but this new work is based on v2.4.0.

The go-coap provides servers and clients for DTLS, TCP-TLS, UDP, TCP in golang.

coap currently supports only plain UDP, https://github.com/Covertness/coap-rs/pull/57 attempts to add DTLS to that. (for https://github.com/Covertness/coap-rs/issues/16)

udp_dtls exists, but has last been updated in 2019 (and uses openssl)

rustls doesn't have DTLS support at the moment, but wants to implement it after DTLS 1.3 nears completion (https://github.com/rustls/rustls/issues/40)


The goal here is to have a CoAP implementation that "just works", doesn't block (and hopefully also neatly integrate with tokio/async), takes some notes from what the matrix.org team encountered when first experimenting with dtls+coap, and remove as many footguns and "leftovers" as possible (sending DTLS close on drop, etc.).

This'd probably mean forking repos and tracking commits in Cargo.toml, i'll fork the repos under my own namespace for the moment, until there's enough interest to move it to ruma's.

This'll be the case until probably rustls supports DTLS, but we also have to be ready for a pure openssl-based implementation.


So, my proposal is this; make a sub-module (or crate) named ruma-lb-coap/ruma_lb::coap that wraps and fixes all of these problems into an abstract and manageable interface, with exclusive features openssl and later rustls to have dependent crates select which backend to use.

Have a CoAPClient in there, intended for internal plumbing (for now), that is able to open and close CoAPClientSessions to endpoints.

The same happens for servers; CoAPServer and CoAPServerSession.

So in the end, it'd look something like this;

LowBandwidthClient -> CoAPClient -> CoAPClientSession -> <DTLS>

LowBandwidthServer <- CoAPServer <- CoAPServerSession <- <DTLS>
ShadowJonathan commented 3 years ago

Block-wise transfer is also needed: https://github.com/matrix-org/matrix-doc/pull/3079#discussion_r692081370

ShadowJonathan commented 2 years ago

I think the best plan, at this time, is to find a DTLS translator (to wrap Read + Write or AsyncRead + AsyncWrite objects) and use coap-lite together with that.

This would allow a plethora of underlying transports, and makes it not tied to UDP like coap is.

ShadowJonathan commented 2 years ago

Some of my comments from the chat;

i think the idea of lb is becoming more and more clear to me, i would probably have to fork coap-lite to mod to my will, and then ill make ruma_lb::coap to create the high-level connection, pumping, and observe mechanisms, then ruma_lb could be a layer around that that converts and works from the MSC, converting to cbor and back, and handling low-level connection problems in a more opinionated way, i think because of this, a ruma_lb_coap crate would be useful on its own, for anyone who wants to use different native libraries to convert data

ShadowJonathan commented 2 years ago

matrix-org/go-coap is using DTLS 1.2, so we'll go with that.

ShadowJonathan commented 2 years ago

http://coap.technology/tools.html and https://coap.me/ could probably be used to test this.