GithubHelp home page GithubHelp logo

covertness / coap-rs Goto Github PK

View Code? Open in Web Editor NEW
196.0 12.0 47.0 40.6 MB

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

License: MIT License

Rust 100.00%
coap rust crates

coap-rs's People

Contributors

aav avatar allenste-aws avatar awhiteknight avatar chilimatic avatar chrysn avatar covertness avatar curio77 avatar erik-nilsson-indentive avatar f-stibane avatar gagath avatar ivajloip avatar jamesmunns avatar jasta avatar jiayihu avatar marcoieni avatar matteobettini avatar osobiehl avatar pranav-bhatt avatar sjm42 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  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  avatar  avatar  avatar  avatar

Watchers

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

coap-rs's Issues

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!

Empty path components dropped

CoAP URIs distinguish between coap://foo/path/parts and coap://foo/path/parts/ (as does any other type of URI). While the former is encoded in two CoAP Uri-Path options ("path", "parts"), the latter is encoded in three ("path", "parts", "") with the third having zero length.

The .set_path() / .get_path() method pair appears to drop the distinction (set_path("/path/parts/") followed by get_path() returns "/path/parts"), indicating that the distinction is not made in the coap-rs library.

Looking at the code, it appears that it is sufficient to drop the if-is-empty check for components, though things might still need special treatment then to avoid inserting an empty component at the beginning when a path is passed in with a leading slash.

Server response retransmission due to duplicate client request (duplicate MID)

Hello,

I have a case when remote modem-connected client does not hear response to its latest request, so it retransmits the request, with the same MID.

I thought this is handled in coap-rs library server code, but it seems it's not.

What's the usual solution to this - when request with the same MID is received from the same endpoint?
Should my (user) code on server side just re-execute the request handler again producing new response, or should it cache previous response and just resend the response?

I need clarification on this.

Thanks.

Provide easier way for setting CoAPOption::ContentFormat

Hello and thanks for your great library. I managed to extend the provided example client and server with some features. One of them is setting the correct CoAPOption::ContentFormat header.

I managed to do it by consulting RFC7252 and by using the following code snippet:

fn set_content_type(resp: &mut CoAPResponse, content_type: u16) -> () {
    let msb = (content_type >> 8) as u8;
    let lsb = (content_type & 0xFF) as u8;

    let content_format: Vec<u8> = vec![msb, lsb];
    resp.add_option(CoAPOption::ContentFormat, content_format);
}

fn main() {
    // ...
    let content_format = 42; // octet-stream, cf. RFC7252
    set_content_type(&mut response, content_format);
}

However I think there is an abstraction to bring here. The first step is to create an enum for all the available registered format types, like this:

enum ContentFormat {
    TextPlain,
    ApplicationLinkFormat,
    ApplicationXML,
    ApplicationOctetStream,
    ApplicationEXI,
    ApplicationJSON
}

fn content_format_id(content_format: ContentFormat) -> u16 {
    match content_format {
        ContentFormat::TextPlain => 0,
        ContentFormat::ApplicationLinkFormat => 40,
        ContentFormat::ApplicationXML => 41,
        ContentFormat::ApplicationOctetStream => 42,
        ContentFormat::ApplicationEXI => 47,
        ContentFormat::ApplicationJSON => 50,
    }
}

And then we can think of helpers like a set_content_format method.

What do you think?

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!

The observer implementation and my use case

Hi,

I'm hoping you can help. I'm not sure if what I've found is an issue, or if I'm using your coap-rs implementation incorrectly.

I'm also new to Rust and CoAP, so hopefully my question and code are not too painful...

My use case:

  • I want to use your coap crate to implement a CoAP server that handles a GET+OBS request from multiple CoAP clients.
  • The server has a resource called 'point' that the client needs to get and maintain a copy of.
  • The client can update 'point' by sending a CoAP PUT to the server.
  • The server needs to notify the client of changes that it makes to 'point', which is why the client previously sent the GET+OBS to register itself as an observer.

My obstacle:

  • The problem I have is that whenever the client sends the GET+OBS request to /point, it gets a 404 response and I have no visibility into where this response is being generated.
  • e.g. I'm logging all request packets passed to the server's request handler, but the GET+OBS registration request is not seen.
  • I want the server to relay the request to the request handler so that I can create the 'point' resource if it doesn't yet exist, and reply to the GET with the 'point' data.
  • Please help me understand why this isn't working as I expect?

A simplified version of my client and server programs are attached:
CoapTesting.zip

A code snippet taken from my server code is below and this illustrates:

  1. The log_request call that never captures the GET+OBS request.
  2. How I was expecting my handle_get function to be able to manage the register and deregister behaviour.

` 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 {}", now_time_str(), addr);

      server
          .run(|request| async {
              log_request(&request);

              let payload_data: String;
              match request.get_method() {
                  &Method::Get =>  {
                      match handle_get(&request) {
                          Ok(data) => {
                              payload_data = data;
                          },
                          Err(e) => {
                              payload_data = format!("Error: {}", e);
                          }
                      }
                  },
                  &Method::Post => {
                      match handle_post(&request) {
                          Ok(data) => {
                              payload_data = data;
                          },
                          Err(e) => {
                              payload_data = format!("Error: {}", e);
                          }
                      }
                  },
                  &Method::Put => {
                      match handle_put(&request) {
                          Ok(data) => {
                              payload_data = data;
                          },
                          Err(e) => {
                              payload_data = format!("Error: {}", e);
                          }
                      }
                  },
                  _ => {
                      payload_data = "method not supported".to_string();
                  },
              };

              return match request.response {
                  Some(mut resp) => {
                      resp.message.payload = payload_data.into();
                      log_response(&resp);
                      Some(resp)
                  }
                  _ => None,
              };
          })
          .await
          .unwrap();
  });

}`

` fn handle_get(request: &CoapRequest) -> Result<String, String> {
println!("{} Handling GET: {}", now_time_str(), request.get_path());

  if let Some(observe_option) = request.get_observe_flag() {
      // Handle observe register/deregister
      match observe_option {
          Ok(observe_value) => {
              match observe_value {
                  ObserveOption::Register => {
                      // To do..
                  },
                  ObserveOption::Deregister => {
                      // To do..
                  },
              }
          }, 
          Err(_) => {
              // Handle unknown observe value
              return Err("Invalid observe option".to_string());  
          } 
      }
  }

  // Handle different GET scenarios...
  return Ok("Some Data".to_string());

}`

Thanks

Update Content-Format list

The ContentFormat enum currently only supports the six content formats defined in RFC7252.

Please update that list to the latest IANA published state or allow extension (eg. Other(u16)). No further support by the CoAP library beyond extending the list is required; applications need to then parse their respective formats themselves anyway, but currently can't set a content-format not in the list from 2014.

My particular application will need the application/cbor and application/senml+cbor types, but it probably makes sense to batch-import all the currently registered types.

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.

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

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.

Communication with the IKEA-tradfri gateway

Very happy to se coap implemented in rust.

I am trying to communicate with my IKEA tradfri gateway over the coap-protocol.
The request i am trying to do is to mimic this terminal command:

coap-client -m post -u "Client_identity" -k "$GATEWAYCODE" -e '{"9090":"$USERNAME"}' "coaps://$GATEWAYIP:5684/15011/9063"

My understanding from reading https://github.com/obgm/libcoap/:

-e is the payload
-k is supposed to add a key to the header
-u is adding a user to the header

But when i try to use the example_post() code in the gateway does not even respond with a status code.

As you can see in the terminal command above the request is to 'coaps:://' and not 'coap::// which im thinking might be where my problem lies. I have not managed to find where this is set in the source of coap-rs.

In addition to this i cant seem to find the best way to mimic adding a key or user to the header from looking at the source of coap-rs.

Anybody that could enlighten me? Would be much appreciated.

Add bind address to CoAPClient::new()

So by default CoAPClient::new() binds to 0.0.0.0:0 for Ipv4 and :::0 for Ipv6.
I have the need to use Ipv6's scope_id when binding, so I can specify which interface I want the packet to go out on. SocketAddrV6::new() lets me specify the scope_id I want to use, but the current CoAPClient assumes I want :::0. Allowing the user to pass in another ToSocketAddrs for the bind address would alleviate this issue.

I have forked the repo and made the change so I can continue working, but it'd be cool if the main repo had support for it. Change is here: robbym@4fa038d

To prevent API breakage, maybe a different function that takes both the bind address and destination address?

GET, POST etc. with Uri-Host

Currently, coap-rs never sets the Uri-Host option. This behavior is independent of the value of the host portion of the URI passed in.

If a URI is decomposed into options and the host component (domain in the source) is not an IP literal, it would be turned into a Uri-Host option according to RFC 7252 Section 6.4 item 5.

Not doing this becomes an issue for clients that interact with servers that do name based virtual hosting, as is often the case with reverse proxies as employed in NAT traversal.

As many systems do not require this option even when the IP address is resolved through DNS, it might be practical to offer methods like .post() both in a variant that sets and one that does not set the Uri-Host. (Also, different people have different opinions of how optional it is to send it, the CoAP wiki has both sides (disclaimer: I wrote that)).

(CC @malishav with whom I encountered this).

Mio 1.8.8 incompatible with newer Tokio versions

Versions of Tokio >=1.34 and higher require Mio >=1.8.9 and causes a version conflict when compiling as coap uses 1.8.8.

A semver bump may resolve this unless there are other aspects that this introduces that would need testing first?

Server-side only modified observer

From looking at the example and observer code, it seems that the only way to modify a resource and trigger an observe notification is for a client to PUT new data.

I have many CoAP usage examples which call for an observable resource that is only modifiable by the server (e.g. server exposing a temperature sensor resource). This is doable in other CoAP libraries (e.g. Lobaro, CoAPthon) but not this one.

I think that the resource modification and notify should be decoupled from client requests entirely, and be up to the server implementation to trigger a resource update when required.

No easy way to set options in client requests

Using CoAPClient, there is no way to set options in a request. It's possible to do so by constructing a CoapRequest manually, but to do so requires re-implementing a bunch of functionality already present in CoAPClient (gen_message_id, request_path_with_timeout and parse_coap_url in particular).

Custom Option IDs

It would be good to have the ability to add a custom option.

A quick and dirty way could be to add to the CoapOption Enum: Custom(u8)

Issues with IPv6 address in URLs

coap-rs depends on an ancient version of rust-url (v0.2.36 of Jul 2015) that appears to have issues with IPv6 addresses in URLs. Upgrading this dependency needs to take care of API changes, however. (Sadly, I'm too much of a Rust noob still to do this myself and offer a PR.)

Anyway, the effect is that coap-rs will choke on URLs such as "coap://[bbbb::9329:f033:f558:7418]/.well-known/core" with a "domain error".

Inject/queue a notification for the Server to dispatch

I'd like to request a feature where once the coap-rs Server is running, the program that calls server.run() can inject/queue a notification packet for the Server to send. If the notification that was injected/queued is confirmable, then the confirmation response can be exposed via the same mechanism that other requests are exposed (e.g. via the server.run() closure).

This feature follows on from the disable_observe_handling() feature that I'm super grateful you implemented so quickly.

To summarise how and why I'm looking to use this new feature...

  • 'Program A' uses coap-rs to run a Server.
  • The Server receives a confirmable GET+OBS request for /some_path.
  • Because disable_observe_handling() is set, the request is forwarded to the server.run() closure.
  • When processing the GET+OBS request, the observer details (ip, port, token, and path) are stored externally (e.g. Redis).
  • At some stage in the future, 'Program B' (which monitors the observers stored within Redis), determines that a notification needs to be sent. When this occurs, it writes an instruction to a notify_queue (stored within Redis).
  • 'Program A' monitors the notify_queue and when a new entry is added, it is read from the queue, turned into a CoapRequest and passed to the coap-rs Server to internally queue and/or send to the observer.

Note: Initially, I had hoped that 'Program B' could send a notification packet to the observer itself, but I've found that this doesn't work, and I suspect it is because the Coap Client only accepts notifications from the Coap Server's IP:Port and not from a different IP:Port source.

Below is some prototype code that shows how I'm currently using coap-rs Server. I have some 'TO DO' comments where I could conceivably implement the new feature I'm requesting.

`fn run_server(server_settings: ServerSettings) {

let running = Arc::new(AtomicBool::new(true));
let running_setup = running.clone();
let running_monitor = running.clone();

// Set up the signal handler
ctrlc::set_handler(move || {
    running_setup.store(false, Ordering::SeqCst);
}).expect("Error setting Ctrl-C handler");

let rt = Runtime::new().unwrap();
rt.block_on(async move {
    let server_addr = server_settings.uri.clone();
    let mut server = Server::new_udp(server_addr).unwrap();
    server.disable_observe_handling(true).await;

    println!("Server up on {}", server_settings.uri.clone());

    // Spawn the CoAP server as a separate task
    let server_task = tokio::spawn(async move {
        server.run(move |request| {

            let running_copy = running.clone();
            let server_settings_copy = server_settings.clone();
            async move {
                let result = handle_request(request, running_copy, &server_settings_copy).await;
                if let Some(ref response) = result.response {
                    log_response(&response, &server_settings_copy);
                }
                // TO DO.. If the notify_waiting flag is set, then build the 
                // notification and pass it to server to internally queue and send when able
                return result;
            }
        }).await.unwrap();
    });

    // TO DO.. Spawn a task that monitors a Redis notify_queue and if an entry is found
    // toggle a notify_waiting flag within server_task. 

    // Detect and handle the program shutdown signal
    while running_monitor.load(Ordering::SeqCst) {

        tokio::time::sleep(Duration::from_secs(2)).await;
    }
    println!("Shutting down");
    server_task.abort();
});

}`

What do you think? Is my feature request doable/useful? Or is there a better way to do what I'm attempting to do?

Message IDs and tokens not set

When used as a CoAP client, the token is always empty, and the message ID is not set.

This does not cause practical problems as long as they are sent from per-request sockets (as they are in the client example), but if multiple requests are sent to the same client, for example as in

    let mut client = CoAPClient::new("localhost:5683").unwrap();
    client.request_path("/time", coap_lite::RequestType::Get, None, None).unwrap();
    client.request_path("/location", coap_lite::RequestType::Get, None, None).unwrap();

then a CoAP server that does request deduplication will respond to the second request with the time of the first request, rather than with its location.

(CC @malishav with whom I encountered this).

0.12.2's update of coap-lite is incompatible

The 0.12.2 version updated the coap-lite dependency from 0.9 to 0.11. That update is semver incompatible because some coap APIs (eg. post_with_timeout) implicitly re-export coap-lite types.

The only semver compatible way out of this is yanking the 0.12.2 version, and re-publish as 0.13.0. Otherwise, acknowledging that this happened and will not be yanked is also fine with me (most dependencies that are affected can probably work around it by depending on ^0.12.2 and coap-lite 0.11) -- in which case I'd just like to ask for more careful re-exporting in future updates.

[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

  • RFC 7252 CoAP [also describes UDP, DTLS and multicast support]
  • RFC 8516 Too Many Requests Response Code
  • RFC 7641 Observing Resources in the CoAP
  • RFC 6347 Datagram Transport Layer Security (DTLS) Version 1.2 *
  • 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.

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.

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?

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).

Update coap-lite dependency

The last version coap-lite = "0.11.3" contains an important fix for block-wise transfer: martindisch/coap-lite#31

coap-rs currently depends on coap-lite = "0.9.1". Also, it might be better not to depend on a strict minor version.

Production use

Hi. Thank you very much for this crate. Is this ready for production use?

Server::run abruptly returns when a response payload is too large

I recently hit a case where I had too large of a response payload which resulted in a quite confusing error as it returned from server.run() only to panic based on server.run(...).await.unwrap():

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Custom { kind: InvalidData, error: "CoAP error: invalid packet length" }', src/main.rs:69:14

I understand we don't have Block1/2 (RFC 7959) support, however we should be able to do better than "crash" the server in this case. At a minimum I think we want to make sure I/O errors during server.run() don't return for every customer since that would easily allow for a DoS attack. Maybe just isolate self.server.send(...) errors and log them instead of returning?

Out of curiosity as well, what would it take to actually implement RFC 7959 support? It seems like we'd need to do some kind of caching by (Token,Endpoint) for some period of time and then add some request/response handling to add/interpret Block2 options accordingly when serving our cached result. Shouldn't be too bad though, right? I might take a crack at a generic implementation downstream of coap-rs and see if it can't be ported back into the core if there's interest.

Building for Linux

I am looking at building this for Linux however I am getting the following error:

error: failed to build archive: Text file busy

error: aborting due to previous error

error: Could not compile `winapi-build`.

This is using the minimal example provided.

Document way for clients to send non-GET requests

It appears that the only way to construct a client request without manually splitting the URI (ie. re-implementing parse_coap_url) is using the get method, which precludes the use of different request methods.

Please document how a request POST or PUT message, with possible additional options, is supposed to be created from a URI.

Crash when using python aiocoap

I'm experimenting and when this as a server and Python's aiocoap as a client I get a crash:

thread 'main' panicked at 'index out of bounds: the len is 0 but the index is 0', /home/sergio/.cargo/registry/src/github.com-1ecc6299db9ec823/coap-0.11.3/src/observer.rs:85:59
import asyncio
from aiocoap import *

async def main():
    protocol = await Context.create_client_context()

    request = Message(code=GET, uri='coap://127.0.0.1:5683/hello/put', observe=0)

    pr = protocol.request(request)

    r = await pr.response
    print("First response: %s\n%r"%(r, r.payload))

if __name__ == "__main__":
    asyncio.run(main())

Changing the "observe" flag to something other than 0 doesn't crash, however, the resource is not observed.

EDIT: On second thought this looks more like an issue in coap-lite isn't it?

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

Block and Link Format support

Hello,

I know this library doesn't support Observe RFC yet. Does it support Blockwise Transfer (RFC7959) and Link Formats (RFC6690)?
Besides those, which other options are NOT supported?

Thanks!

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.