Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

coap: Update to coap-message-0.3 #72

Merged
merged 7 commits into from
Jan 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ rand_core_06 = { package = "rand_core", version = "^0.6" }
# For nimble UUID parsing and some debug implementations
hex = { version = "^0.4.3", default-features = false }

coap-numbers = { version = "^0.2.0", optional = true }
coap-numbers = "^0.2.0"

embedded-graphics = "0.6"

# Originally disabled by default because they were not published yet; now
# disabled by default we're moving toward opt-in modules anyway.
coap-message = { version = "^0.2.3", optional = true }
coap-handler = { version = "^0.1.4", optional = true }
coap-message-0-2 = { package = "coap-message", version = "^0.2.3" }
coap-message-0-3 = { package = "coap-message", version = "^0.3.0" }
coap-handler-0-1 = { package = "coap-handler", version = "^0.1.4" }
coap-handler-0-2 = { package = "coap-handler", version = "^0.2.0" }
embedded-nal = { version = "0.6.0", optional = true }
embedded-nal-tcpextensions = { version = "0.1", optional = true }
pin-utils = "0.1"
Expand All @@ -69,10 +69,8 @@ panic_handler_format = []
# only affects that single thread.
panic_handler_crash = []

# If these are present, traits for the respective optional dependencies will be
# implemented.
with_coap_message = ["coap-message" ]
with_coap_handler = ["coap-handler", "coap-numbers", "with_coap_message"]
with_coap_message = []
with_coap_handler = []
with_embedded_nal = ["embedded-nal", "embedded-nal-tcpextensions"]

# See msg::v2 documentation. Enabling this exposes components not under semver
Expand Down
8 changes: 8 additions & 0 deletions src/coap_handler/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//! This module provides a wrappers around a coap_handler::Handler in different versions, all of
//! which can be registered at a RIOT GcoapHandler.

pub mod v0_1;
pub mod v0_2;

#[deprecated(note = "Use through the v0_1 module.")]
pub use v0_1::*;
22 changes: 12 additions & 10 deletions src/coap_handler.rs → src/coap_handler/v0_1.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
/// This module provides a wrapper around a coap_handler::Handler that can be registered at a RIOT
/// GcoapHandler.
//! This module provides a wrapper around a coap_handler::Handler that can be registered at a RIOT
//! GcoapHandler.

use core::convert::TryInto;

use coap_message::{MutableWritableMessage, ReadableMessage};
use coap_handler_0_1::{Attribute, Handler, Record, Reporting};

use coap_message_0_2::{MutableWritableMessage, ReadableMessage};

use crate::coap_message::ResponseMessage;
use crate::gcoap::PacketBuffer;
Expand All @@ -11,11 +14,11 @@ use crate::gcoap::PacketBuffer;
/// to register it through a [crate::gcoap::SingleHandlerListener].
pub struct GcoapHandler<H>(pub H)
where
H: coap_handler::Handler;
H: Handler;

impl<H> crate::gcoap::Handler for GcoapHandler<H>
where
H: coap_handler::Handler,
H: Handler,
{
fn handle(&mut self, pkt: &mut PacketBuffer) -> isize {
let request_data = self.0.extract_request_data(pkt);
Expand All @@ -27,10 +30,9 @@ where

impl<H> crate::gcoap::WithLinkEncoder for GcoapHandler<H>
where
H: coap_handler::Handler + coap_handler::Reporting,
H: Handler + Reporting,
{
fn encode(&self, writer: &mut crate::gcoap::LinkEncoder) {
use coap_handler::Record;
for record in self.0.report() {
writer.write_comma_maybe();
writer.write(b"<");
Expand All @@ -46,7 +48,7 @@ where
writer.write(b"\"");
}
for attr in record.attributes() {
use coap_handler::Attribute::*;
use Attribute::*;
match attr {
Observable => writer.write(b";obs"),
Interface(i) => {
Expand All @@ -71,9 +73,9 @@ where
/// Blanket implementation for mutex wrapped resources
///
/// This is useful in combination with the defauilt implementation for Option as well.
impl<'b, H> coap_handler::Handler for &'b crate::mutex::Mutex<H>
impl<'b, H> Handler for &'b crate::mutex::Mutex<H>
where
H: coap_handler::Handler,
H: Handler,
{
type RequestData = Option<H::RequestData>;

Expand Down
146 changes: 146 additions & 0 deletions src/coap_handler/v0_2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
//! This module provides a wrapper around a coap_handler::Handler that can be registered at a RIOT
//! GcoapHandler.

use core::convert::TryInto;

use coap_handler_0_2::{Attribute, Handler, Record, Reporting};

use coap_message_0_3::{
error::RenderableOnMinimal,
MinimalWritableMessage,
MutableWritableMessage,
ReadableMessage,
};

use crate::coap_message::ResponseMessage;
use crate::gcoap::PacketBuffer;

/// Adapter to get a [crate::gcoap::Handler] from a more generic [coap_handler::Handler], typically
/// to register it through a [crate::gcoap::SingleHandlerListener].
pub struct GcoapHandler<H>(pub H)
where
H: Handler;

impl<H> crate::gcoap::Handler for GcoapHandler<H>
where
H: Handler,
{
fn handle(&mut self, pkt: &mut PacketBuffer) -> isize {
let request_data = self.0.extract_request_data(pkt);
let mut lengthwrapped = ResponseMessage::new(pkt);
match request_data {
Ok(r) => {
if let Err(e) = self.0.build_response(&mut lengthwrapped, r) {
lengthwrapped.rewind();
if let Err(_e2) = e.render(&mut lengthwrapped) {
// Render double fault
lengthwrapped.rewind();
lengthwrapped.set_code(coap_numbers::code::INTERNAL_SERVER_ERROR);
}
}
}
Err(e) => {
if let Err(_e2) = e.render(&mut lengthwrapped) {
// Render double fault
lengthwrapped.rewind();
lengthwrapped.set_code(coap_numbers::code::INTERNAL_SERVER_ERROR);
}
}
}
lengthwrapped.finish()
}
}

impl<H> crate::gcoap::WithLinkEncoder for GcoapHandler<H>
where
H: Handler + Reporting,
{
fn encode(&self, writer: &mut crate::gcoap::LinkEncoder) {
for record in self.0.report() {
writer.write_comma_maybe();
writer.write(b"<");
for pathelement in record.path() {
writer.write(b"/");
writer.write(pathelement.as_ref().as_bytes());
}
writer.write(b">");
if let Some(rel) = record.rel() {
// Not trying to be smart about whether or not we need the quotes
writer.write(b";rel=\"");
writer.write(rel.as_bytes());
writer.write(b"\"");
}
for attr in record.attributes() {
use Attribute::*;
match attr {
Observable => writer.write(b";obs"),
Interface(i) => {
writer.write(b";if=\"");
writer.write(i.as_bytes());
writer.write(b"\"");
}
ResourceType(r) => {
writer.write(b";rt=\"");
writer.write(r.as_bytes());
writer.write(b"\"");
}
// FIXME: deduplicate with what's somewhere in coap-handler-implementations;
// implement remaining items
_ => (),
}
}
}
}
}

/// Blanket implementation for mutex wrapped resources
///
/// This is useful in combination with the defauilt implementation for Option as well.
impl<'b, H> Handler for &'b crate::mutex::Mutex<H>
where
H: Handler,
{
type RequestData = Option<H::RequestData>;

type ExtractRequestError = H::ExtractRequestError;
type BuildResponseError<M: MinimalWritableMessage> = H::BuildResponseError<M>;

fn extract_request_data<M: ReadableMessage>(
&mut self,
request: &M,
) -> Result<Self::RequestData, Self::ExtractRequestError> {
self.try_lock()
.map(|mut h| h.extract_request_data(request))
.transpose()
}

fn estimate_length(&mut self, request: &Self::RequestData) -> usize {
if let Some(r) = request {
if let Some(mut s) = self.try_lock() {
return s.estimate_length(r);
}
}

1
}

fn build_response<M: MutableWritableMessage>(
&mut self,
response: &mut M,
request: Self::RequestData,
) -> Result<(), Self::BuildResponseError<M>> {
if let Some(r) = request {
if let Some(mut s) = self.try_lock() {
return s.build_response(response, r);
}
}

response.set_code(
coap_numbers::code::SERVICE_UNAVAILABLE
.try_into()
.map_err(|_| "Message type can't even exprss Service Unavailable")
.unwrap(),
);
Ok(())
}
}
64 changes: 10 additions & 54 deletions src/coap_message.rs → src/coap_message/impl_0_2.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
/// This module implements coap_message::ReadableMessage for, and a wrapper that provides
/// coap_message::WritableMessage around RIOT's coap_pkt_t.
use crate::gcoap::{PacketBuffer, PacketBufferOptIter};
use coap_message::{
use coap_message_0_2::{
MessageOption,
MinimalWritableMessage,
MutableWritableMessage,
ReadableMessage,
WithSortedOptions,
};

pub struct MessageOption<'a> {
number: u16,
value: &'a [u8],
}

impl<'a> coap_message::MessageOption for MessageOption<'a> {
impl<'a> MessageOption for super::MessageOption<'a> {
fn number(&self) -> u16 {
self.number
}
Expand All @@ -23,27 +16,14 @@ impl<'a> coap_message::MessageOption for MessageOption<'a> {
}
}

pub struct OptionsIterator<'a>(PacketBufferOptIter<'a>);
impl<'a> Iterator for OptionsIterator<'a> {
type Item = MessageOption<'a>;

fn next(&mut self) -> Option<Self::Item> {
let (opt_num, slice) = self.0.next()?;
Some(MessageOption {
number: opt_num,
value: slice,
})
}
}

impl WithSortedOptions for PacketBuffer {
impl WithSortedOptions for super::PacketBuffer {
// valid because gcoap just reads options from the message where they are stored in sequence
}

impl ReadableMessage for PacketBuffer {
impl ReadableMessage for super::PacketBuffer {
type Code = u8;
type OptionsIter<'a> = OptionsIterator<'a>;
type MessageOption<'a> = MessageOption<'a>;
type OptionsIter<'a> = super::OptionsIterator<'a>;
type MessageOption<'a> = super::MessageOption<'a>;

fn code(&self) -> Self::Code {
self.get_code_raw()
Expand All @@ -54,35 +34,11 @@ impl ReadableMessage for PacketBuffer {
}

fn options(&self) -> Self::OptionsIter<'_> {
OptionsIterator(self.opt_iter())
}
}

pub struct ResponseMessage<'a> {
message: &'a mut PacketBuffer,
payload_written: Option<usize>,
}

impl<'a> ResponseMessage<'a> {
pub fn new(buf: &'a mut PacketBuffer) -> Self {
// Can't really err; FIXME ensure that such a check won't affect ROM too much
buf.resp_init(5 << 5).unwrap();

ResponseMessage {
message: buf,
payload_written: None,
}
}

pub fn finish(&self) -> isize {
self.message.get_length(match self.payload_written {
None => 0,
Some(x) => x + 1,
}) as isize
super::OptionsIterator(self.opt_iter())
}
}

impl<'a> MinimalWritableMessage for ResponseMessage<'a> {
impl<'a> MinimalWritableMessage for super::ResponseMessage<'a> {
type Code = u8;
type OptionNumber = u16;

Expand All @@ -105,7 +61,7 @@ impl<'a> MinimalWritableMessage for ResponseMessage<'a> {
}
}

impl<'a> MutableWritableMessage for ResponseMessage<'a> {
impl<'a> MutableWritableMessage for super::ResponseMessage<'a> {
fn available_space(&self) -> usize {
self.message.payload().len()
}
Expand Down
Loading