A Constrained Application Protocol(CoAP) library implemented in Rust.

Overview

coap-rs

Travis Build Status Windows Build Status Downloads Coverage Status MIT licensed

A fast and stable Constrained Application Protocol(CoAP) library implemented in Rust.

Features:

Documentation

Installation

First add this to your Cargo.toml:

[dependencies]
coap = "0.9"

Example

Server:

#![feature(async_closure)]

use coap_lite::{RequestType as Method};
use coap::Server;
use tokio::runtime::Runtime;

fn main() {
    let addr = "127.0.0.1:5683";

	Runtime::new().unwrap().block_on(async move {
		let mut server = Server::new(addr).unwrap();
		println!("Server up on {}", addr);
		
		server.run(async move |request| {
            match request.get_method() {
				&Method::Get => println!("request by get {}", request.get_path()),
				&Method::Post => println!("request by post {}", String::from_utf8(request.message.payload).unwrap()),
				&Method::Put => println!("request by put {}", String::from_utf8(request.message.payload).unwrap()),
				_ => println!("request by other method"),
			};
			
			return match request.response {
				Some(mut message) => {
					message.message.payload = b"OK".to_vec();
					Some(message)
				},
				_ => None
			};
    	}).await.unwrap();
	});
}

Client:

use coap::CoAPClient;

fn main() {
    let url = "coap://127.0.0.1:5683/Rust";
    println!("Client request: {}", url);

    let response = CoAPClient::get(url).unwrap();
    println!("Server reply: {}", String::from_utf8(response.message.payload).unwrap());
}

Benchmark

$ cargo bench
Comments
  • Respond from the CoAP port to support Copper

    Respond from the CoAP port to support Copper

    The Mozilla Copper plugin only recognizes messages that return from the CoAP port. Previously, responses were returned from a random UDP socket.

    I have added a "CoAPResponse" class which is based on the CoAPClient class. This allows for responses from the server to be on the same port that requests were sent to.

    opened by jamesmunns 28
  • no_std support

    no_std support

    Is there any plan to support no_std with this crate since CoAP is heavily used in embedded? There is coap-lite but it's unmaintaned and it handles only packet parsing and creation

    opened by jiayihu 18
  • Bumped dependency versions

    Bumped dependency versions

    The main motivation behind this was that thetokio version being used in this crate was still 0.2 and this was causing major issues in my project. Refactored it to use tokio 1.7*, and also ran cargo fmt (Do tell me if this might cause issues).

    I also wanted to ask if this warrants a version bump since the change in tokio versions might cause issues for others.

    opened by pranav-bhatt 12
  • Pass socket to handler callback

    Pass socket to handler callback

    For some applications it's necessary to have access to the sender from the callback. It would be useful to have the SocketAddr in the handler signature.

    opened by ptxmac 12
  • Updating observes from server?

    Updating observes from server?

    Hi!!! I want to use CoAP-rs for voice assistant components, and we need to use observe, however, there's no support for updating the resources from the server anymore and trying to access the same server from a client in the same process (as a workaround) throws:

    thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }'
    

    Is server-side resource update planned again, or at least, can the workaround be made to work in the meantime?

    opened by sheosi 10
  • Packet refactor

    Packet refactor

    Still planning to add some tests, but please feel free to review. I can also squash the commits once we are ready (I included them in case you wanted to see the steps).

    opened by jamesmunns 10
  • Fix: Make URLs with IPv6 addresses usable

    Fix: Make URLs with IPv6 addresses usable

    Previously, in parsing URLs, the latters' domains were considered instead of their literal hosts, which would fail for IPv6 addresses (and presumably also IPv4 addresses) that failed to reverse-look-up.

    Now, the literal host is used instead, stripped of encapsulating square brackets (denoting an IPv6 address), if any.

    This resolves #24.

    opened by curio77 7
  • static handler brings problems

    static handler brings problems

    The CoAPServer::handle takes a 'static handler.

    I'm a bit new to rust, but I believe this means we can only use top level methods as handler, and then all state needed for the server will need to be stored in global variables?

    As far as I understand it, this will also make the routing tool in #4 impossible.

    Please correct me if I'm wrong!

    opened by ptxmac 6
  • Generic subject observer (RFC 7641) support

    Generic subject observer (RFC 7641) support

    The observer support today is a very useful start however it's missing a few key APIs to customize it to work similar to other CoAP implementations and, more importantly, generalized to the use cases described in RFC 7641. For example, the support requires that PUT request be issued in order for the system to work, even though we wouldn't normally expect read-only endpoints to have such a feature. Further, the implementation is just a limited replaying of the last PUT payload without any of the handling consideration that you'd get with a GET request (like if the GET response included ContentFormat options, the resulting notification for this resource path would not include that information).

    I believe this can be addressed relatively easily but the easy way will break a few implementation assumptions and change the public API. For those reasons I wanted to open a dialog to make sure my assumptions are correct and my goals are consistent with the projects before proceeding to a pull request. Specifically, the following changes should make this possible:

    1. A limited portion of the Observer features becomes visible from the Server object such that stateless components can invoke an API like server.resource_changed(path).
    2. PUT would no longer automatically affect resources or perform caching, but instead a synthetic GET request would be injected and handled in response to server.resource_changed(path). This response would be cached instead and copied to all observing clients.
    3. Resource observing eligibility would be based on the response issued when handling the initial GET {Observe:0} request rather than being assumed valid in response to a PUT. For example, if the initial GET request yields a 4.xx error, the observe would be rejected.

    What do you think of these changes? Are you interested in me proceeding with a possible PR?

    Thanks for the great project, this is really helping me get a cool project of mine off the ground using an ultra low powered old Lego EV3 brick as the hub!

    opened by jasta 5
  • Pass channel to CoAPServer handle

    Pass channel to CoAPServer handle

    I've been trying to add a channel to the coapserver message handler, but failing This is as far as I get:

    use coap::{CoAPRequest, CoAPResponse, CoAPServer};
    
    use std::sync::mpsc;
    use std::sync::mpsc::{Receiver, Sender};
    
    fn request_handler(request: CoAPRequest, channel_tx : Sender<u8>) -> Option<CoAPResponse> {
        None
    }
    
    fn main() {
        let addr = "[::]:5683";
    
        let mut server = CoAPServer::new(addr).unwrap();
        
        let (channel_tx, channel_rx): (Sender<u8>, Receiver<u8>) = mpsc::channel();   
        server.handle( move |request| {
            request_handler(request, channel_tx.clone())
        }).unwrap();
    }
    

    Errors when building:

    error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
      --> src/main.rs:18:20
       |
    18 |     server.handle( move |request| {
       |            ------  ^^^^^^^^^^^^^^ this closure implements `FnOnce`, not `Fn`
       |            |
       |            the requirement to implement `Fn` derives from here
    19 |         request_handler(request, channel_tx)
       |                                  ---------- closure is `FnOnce` because it moves the variable `channel_tx` out of its environment
    
    error[E0277]: `std::sync::mpsc::Sender<u8>` cannot be shared between threads safely
      --> src/main.rs:18:12
       |
    18 |     server.handle( move |request| {
       |            ^^^^^^ `std::sync::mpsc::Sender<u8>` cannot be shared between threads safely
       |
       = help: within `[closure@src/main.rs:18:20: 20:6 channel_tx:std::sync::mpsc::Sender<u8>]`, the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<u8>`
       = note: required because it appears within the type `[closure@src/main.rs:18:20: 20:6 channel_tx:std::sync::mpsc::Sender<u8>]`
       = note: required because of the requirements on the impl of `coap::server::CoAPHandler` for `[closure@src/main.rs:18:20: 20:6 channel_tx:std::sync::mpsc::Sender<u8>]`
    
    error[E0277]: the trait bound `std::sync::mpsc::Sender<u8>: std::marker::Copy` is not satisfied in `[closure@src/main.rs:18:20: 20:6 channel_tx:std::sync::mpsc::Sender<u8>]`
      --> src/main.rs:18:12
       |
    18 |     server.handle( move |request| {
       |            ^^^^^^ within `[closure@src/main.rs:18:20: 20:6 channel_tx:std::sync::mpsc::Sender<u8>]`, the trait `std::marker::Copy` is not implemented for `std::sync::mpsc::Sender<u8>`
       |
       = note: required because it appears within the type `[closure@src/main.rs:18:20: 20:6 channel_tx:std::sync::mpsc::Sender<u8>]`
       = note: required because of the requirements on the impl of `coap::server::CoAPHandler` for `[closure@src/main.rs:18:20: 20:6 channel_tx:std::sync::mpsc::Sender<u8>]`
    
    error: aborting due to 3 previous errors
    
    opened by vervaekejonathan 5
  • Receive multicast messages on wpan0 with IPv6 address

    Receive multicast messages on wpan0 with IPv6 address

    Hi, I'm trying to receive multicast coap messages from a thread network. This network is available via wpan0 and has ipv6 addresses. I'm trying the server demo, with the following modification: let addr = ":::0"; Unfortunately, I do not receive any packages. What could be wrong?

    Things I've tried:

    • set address to 0.0.0.0:5683 and send packages via ipv4 on eth0 -> this works fine
    • receive the multicast messages with a node.js implementation -> this works fine

    Thanks.

    opened by vervaekejonathan 5
  • Blockwise transfer for with a request payload

    Blockwise transfer for with a request payload

    Are there any plans / ideas / thoughts around implementation of Blockwise transfer for Block1 type of requests? I can help with the implementation.

    https://datatracker.ietf.org/doc/html/rfc7959#section-2.5

    opened by digitwolf 3
  • Client: Separate responses not processed

    Client: Separate responses not processed

    A CoAP server has the choice to either send the response message to a confirmable request as a piggy-backed response (along with the ACK), or as a separate message. When coap-rs is used in a client and the server sends a separate message, the empty ACK is given to the application, where I'd expect the library to give the application the actual response (which is sent later).

    If this is not handled in the CoAP library, client applications can easily start breaking once a server is updated to a newer version (that might make better informed decisions on when to send which kind of response), when proxies are in use, or simply when the server is under higher load than usual. I do not think that it is reasonable to expect application code to handle this manually, given the overall high level of abstraction coap-rs provides. Depending on how #79 is implemented, applications might not even have the means to implement the necessary behavior on their own.

    RFC 7252 has the precise details, but the rough logic I'm using in other implementations is:

    • Send the request, configuring its retransmissions.
    • When an empty ACK is received, cease retransmissions. The application configured total timeout is still left active.
    • When receiving a response, present it to the application and terminate all timeouts.
      • If the response is sent in a CON, send an ACK.
    • When receiving a response that does not match any (or, in a fully serialized library, the) outstanding request, and the response is sent in a CON, send a RST. If ihas any other type, silently ignore it.

    (CC @malishav with whom I encountered this).

    enhancement 
    opened by chrysn 1
  • [Proposal] Referencing implemented IETF standards into the project topics

    [Proposal] Referencing implemented IETF standards into the project topics

    Hi, I am proprosing the following: coap-rs should recense every implemented IETF standards (i.e. draft, proposed standard rfc and possibly informational standard rfc that updates RFC 7252 Standard) onto the project about section in the topics like on plgd-dev/go-coap

    image

    • [X] RFC 7252 CoAP [also describes UDP, DTLS and multicast support]
    • [X] RFC 8516 Too Many Requests Response Code
    • [X] RFC 7641 Observing Resources in the CoAP
    • [ ] RFC 6347 Datagram Transport Layer Security (DTLS) Version 1.2 *
    • [x] RFC 7959 Block-Wise Transfers in the CoAP
    • [ ] RFC 8323 CoAP over TCP, TLS, and WebSockets
    • [ ] RFC 8613 Object Security for Constrained RESTful Environments (OSCORE)

    If you have any other standards to suggest, please let a comment.

    * DTLS 1.2 is very important to the core standard of CoAP. Please if you are looking for a bounty, I suggest to look for this one. You can even create your own crate on doc.rs and we will help you implementing this.

    opened by StEvUgnIn 0
  • Support for rfc8323 (CoAP over TCP)

    Support for rfc8323 (CoAP over TCP)

    This is more of a question, rather than an issue, but curious if there are any plans to support TCP RFC (https://datatracker.ietf.org/doc/rfc8323/) for coap-rs.

    feature-request 
    opened by joemag1 10
  • Async client requests

    Async client requests

    It appears that the underlying IO library is asynchronous, and the server implementation does indeed expose an asynchronous handler interface.

    It would be nice if the client side could also be made to have an asynchronous interface rather than having to do a blocking read.

    opened by weili-jiang 2
Releases(0.12.0)
Owner
Covertness
benefiting all without contending
Covertness
A µTP (Micro/uTorrent Transport Library) library implemented in Rust

rust-utp A Micro Transport Protocol library implemented in Rust. API documentation Overview The Micro Transport Protocol is a reliable transport proto

Ricardo Martins 134 Dec 11, 2022
A generic Rust based Bigtable connection library implemented using gRPC

A generic Rust based Bigtable connection library refactored out the solana mono-repo so that can be shared for different applications.

Lijun Wang 3 Sep 25, 2022
A Rust library for parsing the SOME/IP network protocol (without payload interpretation).

someip_parse A Rust library for parsing the SOME/IP network protocol (without payload interpretation). Usage Add the following to your Cargo.toml: [de

Julian Schmid 18 Oct 31, 2022
Peer-to-peer communications library for Rust based on QUIC protocol

qp2p Crate Documentation MaidSafe website SAFE Dev Forum SAFE Network Forum Overview This library provides an API to simplify common tasks when creati

MaidSafe 337 Dec 14, 2022
Simple VPN implemented using rust

fubuki Simple VPN implemented using rust fubuki是类似与tincVPN的简单组网工具 不支持对等NAT 支持的平台: Windows Linux 工作机制 它由一台拥有公网IP的服务器来维持各个内网客户端的实际地址映射,在客户端和客户端之间实现P2P通信

XTY 84 Dec 31, 2022
TeleMQ is an experimental MQTT broker implemented in Rust language.

TeleMQ TeleMQ is an experimental MQTT broker implemented in Rust language. The broker implements MQTT version 3.1.1 specification. License This projec

null 12 Dec 27, 2022
A minimal ngrok liked reverse proxy implemented in Rust.

rok A minimal ngrok implementation in Rust, for educational purpose. This work is largely based on rathole, especially the very first commit. Other ho

Kai 3 Jun 21, 2022
Nacos server re-implemented in Rust.

rnacos 简介 rnacos是一个用rust实现的nacos服务。 rnacos是一个轻量、快速、稳定的服务,包含注册中心、配置中心、web管理控制台功能。 rnacos兼容nacos client sdk用到的协议(包含1.x的http OpenApi,和2.x的grpc协议),支持使用nac

heqingpan 18 Jun 7, 2023
Easy protocol definitions in Rust

protocol Documentation Easy protocol definitions in Rust. This crate adds a custom derive that can be added to types, allowing structured data to be s

Dylan McKay 157 Dec 30, 2022
Rustus - TUS protocol implementation in Rust.

Rustus Tus protocol implementation written in Rust. Features This implementation has several features to make usage as simple as possible. Rustus is r

Pavel Kirilin 74 Jan 1, 2023
RakNet Protocol implementation by Rust.

rust-raknet RakNet Protocol implementation by Rust. Raknet is a reliable udp transport protocol that is often used for communication between game clie

b23r0 161 Dec 29, 2022
A simple tool in Rust to split urls in their protocol, host, port, path and query parts.

rexturl A simple tool to split urls in their protocol, host, port, path and query parts. Install cargo install rexturl or clone the source code and r

Volker Schwaberow 3 Oct 22, 2022
Rust implementation of TCP + UDP Proxy Protocol (aka. MMProxy)

mmproxy-rs A Rust implementation of MMProxy! ?? Rationale Many previous implementations only support PROXY Protocol for either TCP or UDP, whereas thi

Saikō Technology 3 Dec 29, 2022
Rust implementation of PRECIS Framework: Preparation, Enforcement, and Comparison of Internationalized Strings in Application Protocols

Rust PRECIS Framework libray PRECIS Framework: Preparation, Enforcement, and Comparison of Internationalized Strings in Application Protocols as descr

Santiago Carot-Nemesio 1 Oct 20, 2022
Tiny CLI application in rust to scan ports from a given IP and find how many are open. You can also pass the amount of threads for that scan

Port Scanner A simple multi-threaded port scanner written in Rust. Usage Run the port scanner by providing the target IP address and optional flags. $

nicolas lopes 4 Aug 29, 2023
🥧 Savoury implementation of the QUIC transport protocol and HTTP/3

quiche is an implementation of the QUIC transport protocol and HTTP/3 as specified by the IETF. It provides a low level API for processing QUIC packet

Cloudflare 7.1k Jan 8, 2023
🤖 brwrs is a new protocol running over TCP/IP that is intended to be a suitable candidate for terminal-only servers

brwrs is a new protocol running over TCP/IP that is intended to be a suitable candidate for terminal-only servers (plain text data). That is, although it can be accessed from a browser, brwrs will not correctly interpret the browser's GET request.

daCoUSB 3 Jul 30, 2021
A multi-protocol network relay

A multi-protocol network relay

zephyr 43 Dec 13, 2022
The Graph is a protocol for building decentralized applications (dApps) quickly on Ethereum and IPFS using GraphQL.

Graph Node The Graph is a protocol for building decentralized applications (dApps) quickly on Ethereum and IPFS using GraphQL. Graph Node is an open s

Mindy.wang 2 Jun 18, 2022