Git Product home page Git Product logo

rust-async-coap's Introduction

async-coap: An experimental, asynchronous CoAP library

Build Status Crates.io API

Introduction

rust-async-coap is an experimental, asynchronous Rust library for using and serving Constrained Application Protocol (CoAP) resources.

This library provides a flexible, asynchronous interface for using and serving CoAP resources. A back-end that wraps around Rust's standard UdpSocket is included, but can be replaced with one supporting DTLS, SMS, or whatever else you might think of.

See the crate documentation for more information.

What is CoAP?

CoAP is a RESTful application protocol (like HTTP) designed for highly embedded devices and small packet sizes. It is similar to HTTP in the sense that it is request/response based, has methods like GET/PUT/POST, and uses hierarchical URLs to identify resources; but unlike HTTP it is optimized for machine-to-machine interactions and includes mechanisms for asynchronously observing resources for changes.

CoAP is the basis for several upcoming IoT protocols.

Usage

Add this to your Cargo.toml:

[dependencies]
async-coap = "0.1.0"

Now, you can use rust-async-coap:

use async_coap::prelude::*;

License

rust-async-coap is released under the Apache 2.0 license.

Copyright (c) 2019 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

	http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Disclaimer

This is not an officially supported Google product.

rust-async-coap's People

Contributors

aav avatar darconeous avatar joe1994 avatar luro02 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

rust-async-coap's Issues

Need datagram::MockSocket implementation for better unit tests

This project needs better testing in order to be able to confirm fixes for things like #20. What's needed is a mock socket that we can use to get fine-tuned programatic input/output tests. With that in place we can re-implement many of the unit tests which hit coap.me to tests which are much more reliable and flexible.

Characterize and possibly improve the performance of `decode_option`

The function async_coap::message::codec::decode_option is called often and thus its performance should be characterized and optimized. The current version was written for correctness rather than performance, so should be easily outperformed by a more carefully optimized version.

ArcGuard's Send and Sync should have bounds on RC

Hi there, we (Rust group @sslab-gatech) are scanning crates on crates.io for potential soundness bugs. We noticed that async_coap::arc_guard::ArcGuard implements Send and Sync so long as T: Send and T: Sync.

unsafe impl<RC, T: Send> Send for ArcGuard<RC, T> {}
unsafe impl<RC, T: Sync> Sync for ArcGuard<RC, T> {}

However, this should also probably be bounded by RC: Send and RC: Sync, otherwise it's possible to smuggle across non-Send types across thread boundaries. Here's a proof-of-concept that segfaults safe rust code:

#![forbid(unsafe_code)]

use async_coap::arc_guard::ArcGuard;

use std::{cell::Cell, sync::Arc};
use crossbeam_utils::thread;

// A simple tagged union used to demonstrate problems with data races in Cell.
#[derive(Debug, Clone, Copy)]
enum RefOrInt {
    Ref(&'static u64),
    Int(u64),
}
static SOME_INT: u64 = 123;

fn main() {
    let cell = Cell::new(RefOrInt::Ref(&SOME_INT));
    let arc = Arc::new(cell);

    let arc_guard = ArcGuard::new(arc, |_| ());
    thread::scope(|s| {
        s.spawn(|_| {
            let smuggled_arc = (&arc_guard).head();

            loop {
                // Repeatedly write Ref(&addr) and Int(0xdeadbeef) into the cell.
                smuggled_arc.set(RefOrInt::Ref(&SOME_INT));
                smuggled_arc.set(RefOrInt::Int(0xdeadbeef));
            }
        });

        loop {
            if let RefOrInt::Ref(addr) = (**arc_guard.head()).get() {
                // Hope that between the time we pattern match the object as a
                // `Ref`, it gets written to by the other thread.
                if addr as *const u64 == &SOME_INT as *const u64 { continue; }

                println!("Pointer is now: {:p}", addr);
                println!("Dereferencing addr will now segfault: {}", *addr);
            }
        }
    });
}

Output:

Pointer is now: 0xdeadbeef

Terminated with signal 11 (SIGSEGV)

async-coap-uri: Rewrite `AnyUriRef::write_resolved` to not depend on allocation

AnyUriRef::write_resolved, as currently written, depends on the std crate, due to the use of dynamically-sized container types. It should be possible to rewrite this method in such a way that this dependency is no longer required.

This issue is the largest impediment to allowing async-coap-uri to work in no-std environments.

Additionally, while the method does currently pass the rather large unit test corpus, the implementation is a bit of a mess. Any re-write should also attempt to make the code easier to follow.

Update OptionIteratorExt::extract_location to comply with RFC7252 section 5.10.7

The relevant portion of RFC7252 section 5.10.7 is the last paragraph (emphasis mine):

The options that are used to compute the relative URI-reference are collectively called Location-\* options. Beyond Location-Path and Location-Query, more Location-\* options may be defined in the future and have been reserved option numbers 128, 132, 136, and 140. If any of these reserved option numbers occurs in addition to Location-Path and/or Location-Query and are not supported, then a 4.02 (Bad Option) error MUST be returned.

Currently we are ignoring options 128, 132, 136, and 140. This must be fixed to be in compliance with RFC7252.

async-coap-uri: fix imports

Almost all modules have wildcard imports

use super::*;

which I would consider bad practice, because it is harder to see which files/modules a file depends on.

It could also cause unexpected overwrites of imports, if one is not careful about it.

For example:

file.rs

pub struct Wrapper(usize);

impl Wrapper {
    pub fn new() -> Self {
        Self(1)
    }
}

other.rs

pub struct Wrapper(usize);

impl Wrapper {
    pub fn new() -> Self {
        Self(2)
    }
}

lib.rs

mod file;
mod other;

use file::*;
use other::*;

third.rs

use super::*;

pub fn hello() {
    // this would print `wrapper: 2`, because other::Wrapper overwrites file::Wrapper
    println!("wrapper: {}", Wrapper::new());
}

but if one removes the other::Wrapper the behavior of third::hello would change without anyone noticing.

UdpResponseTracker should not have unsafe code

There is a transmute in the implementation of UdpResponseTracker::add_response_handler:

fn add_response_handler<'a>(
    &mut self,
    msg_id: MsgId,
    msg_token: MsgToken,
    socket_addr: IC::SocketAddr,
    handler: Arc<Mutex<dyn HandleResponse<IC> + 'a>>,
) {
    let handler: Arc<Mutex<dyn HandleResponse<IC>>> =
        unsafe { std::mem::transmute(handler) };
   
    // ...

This transmute is a hack to coerce the lifetime 'a into (ultimately) 'static. At the time I wrote this, I felt like there must have been a way to restructure things without having to switch over to a 'static lifetime, but after 8+ hours of lifetime hell I couldn't figure it out. In order to not stay blocked I added the transmute.

While I know that this is currently safe to do, I would much rather the compiler be able to make the determination and not require an unsafe block. So, ultimately this issue needs to be revisited.

DTLS support query

First of this project is absolutely amazing. It was really easy to create a server and client. I'm now experimenting to get this to work with DTLS.

In RFC-7252 Section 6 it indicates that a DTLS secured coap requests have a URI of coaps://. I checked the uri module but it seems coaps is not included. Is DTLS support something that is still a work in progress?

I did see in the crate documentation the following:

By implementing datagram::AsyncDatagramSocket, you can use the provided datagram-based back-end with whatever datagram-based network layer you might want, be it UDP, DTLS, or even SMS

If I read this correctly, DTLS support can be added by implementing the async_coap::LocalEndPoint trait. Is this correct?

async-coap-uri: Investigate how safety guarantees clash with `AnyUriRef::write_to`

From the rustdocs for AnyUriRef::write_to:

Safety

Calling this method is not unsafe, but implementing it is! The underlying guarantee is that the written URI reference SHALL be well-formed. If this method writes out something that is not a valid URI reference, the resulting behavior is undefined.

That this method is safe to use but "unsafe" to implement seems problematic. This issue is tracking potential ways to clear this up from an API perspective.

async-coap-uri: no_std implementation is broken

The crate provides the following features:

[features]
default = ["std"]
std = ["alloc"]
alloc = []

by default std is enabled, which works as expected.

To test the features I simply ran the tests of async-coap-uri with the below commands.

To disable all default features one could try the following command (this would be true no_std without any allocator):

cargo test --no-default-features

which fails (with lots of errors).

Enabling only the alloc-feature also fails

cargo test --no-default-features --features alloc

Implement more traits for UriRefBuf and UriBuf

The following traits could be implemented

  • FromStr
  • TryFrom
    -> TryFrom<&str>
    -> TryFrom<&String>
    -> TryFrom<String> (only for UriBuf)
    -> impl<T: AsRef<UriRef>> TryFrom<T>

Most of these traits can be simply delegated to their respective function

use std::str::FromStr;

impl FromStr for UriBuf {
   type Err = ParseError;

    fn from_str(input: &str) -> Result<Self, Self::Err> { Self::from_str(input) }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.