Struct toad_msg::Message

source ·
pub struct Message<PayloadBytes, Options> {
    pub id: Id,
    pub ty: Type,
    pub ver: Version,
    pub token: Token,
    pub code: Code,
    pub opts: Options,
    pub payload: Payload<PayloadBytes>,
}
Expand description

CoAP Messages

This struct provides a high-level API for manipulating requests & responses, while still being cheaply serializable to & from the byte layout of CoAP messages on the wire.

Options

Options (the CoAP equivalent to HTTP headers) can be manipulated with methods provided in the MessageOptions trait. This includes getting & setting common options known to this library.

Constructing

Message::new is the most straightforward way to initialize messages.

Being one of the few structs in the toad-lib libraries with public fields, you may also initialize it with a struct literal.

use toad_msg::alloc::Message;
use toad_msg::{Code, Id, Payload, Token, Type, Version};

let a = Message { id: Id(1),
                  token: Token(Default::default()),
                  ver: Version::default(),
                  ty: Type::Con,
                  code: Code::GET,
                  payload: Payload(vec![]),
                  opts: Default::default() };

let b = Message::new(Type::Con, Code::GET, Id(1), Token(Default::default()));

assert_eq!(a, b);

Sending / Receiving

This crate (toad-msg) explicitly does not know or care about how the messages are sent and received, and is just concerned with the data structures involved on the machines having a CoAP conversation.

For a runtime that uses this library, see toad.

Further Reading from RFC7252

Messaging Model

generated from RFC7252 section 2.1

The CoAP messaging model is based on the exchange of messages over UDP between endpoints.

CoAP uses a short fixed-length binary header (4 bytes) that may be followed by compact binary options and a payload. This message format is shared by requests and responses. The CoAP message format is specified in Section 3. Each message contains a Message ID used to detect duplicates and for optional reliability. (The Message ID is compact; its 16-bit size enables up to about 250 messages per second from one endpoint to another with default protocol parameters.)

Reliability is provided by marking a message as Confirmable (CON). A Confirmable message is retransmitted using a default timeout and exponential back-off between retransmissions, until the recipient sends an Acknowledgement message (ACK) with the same Message ID (in this example, 0x7d34) from the corresponding endpoint; see Figure 2. When a recipient is not at all able to process a Confirmable message (i.e., not even able to provide a suitable error response), it replies with a Reset message (RST) instead of an Acknowledgement (ACK).

                     Client              Server
                        |                  |
                        |   CON [0x7d34]   |
                        +----------------->|
                        |                  |
                        |   ACK [0x7d34]   |
                        |<-----------------+
                        |                  |

Figure 2: Reliable Message Transmission

A message that does not require reliable transmission (for example, each single measurement out of a stream of sensor data) can be sent as a Non-confirmable message (NON). These are not acknowledged, but still have a Message ID for duplicate detection (in this example, 0x01a0); see Figure 3. When a recipient is not able to process a Non-confirmable message, it may reply with a Reset message (RST).

                     Client              Server
                        |                  |
                        |   NON [0x01a0]   |
                        +----------------->|
                        |                  |

              Figure 3: Unreliable Message Transmission

See Section 4 for details of CoAP messages.

As CoAP runs over UDP, it also supports the use of multicast IP destination addresses, enabling multicast CoAP requests. Section 8 discusses the proper use of CoAP messages with multicast addresses and precautions for avoiding response congestion.

Several security modes are defined for CoAP in Section 9 ranging from no security to certificate-based security. This document specifies a binding to DTLS for securing the protocol; the use of IPsec with CoAP is discussed in [IPsec-CoAP].

Message Format

generated from RFC7252 section 3

CoAP is based on the exchange of compact messages that, by default, are transported over UDP (i.e., each CoAP message occupies the data section of one UDP datagram). CoAP may also be used over Datagram Transport Layer Security (DTLS) (see Section 9.1). It could also be used over other transports such as SMS, TCP, or SCTP, the specification of which is out of this document’s scope. (UDP-lite [RFC3828] and UDP zero checksum [RFC6936] are not supported by CoAP.)

CoAP messages are encoded in a simple binary format. The message format starts with a fixed-size 4-byte header. This is followed by a variable-length Token value, which can be between 0 and 8 bytes long.

Following the Token value comes a sequence of zero or more CoAP Options in Type-Length-Value (TLV) format, optionally followed by a payload that takes up the rest of the datagram.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Ver| T |  TKL  |      Code     |          Message ID           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   Token (if any, TKL bytes) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   Options (if any) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|1 1 1 1 1 1 1 1|    Payload (if any) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                      Figure 7: Message Format

The fields in the header are defined as follows:

Version (Ver): 2-bit unsigned integer. Indicates the CoAP version number. Implementations of this specification MUST set this field to 1 (01 binary). Other values are reserved for future versions. Messages with unknown version numbers MUST be silently ignored.

Type (T): 2-bit unsigned integer. Indicates if this message is of type Confirmable (0), Non-confirmable (1), Acknowledgement (2), or Reset (3). The semantics of these message types are defined in Section 4.

Token Length (TKL): 4-bit unsigned integer. Indicates the length of the variable-length Token field (0-8 bytes). Lengths 9-15 are reserved, MUST NOT be sent, and MUST be processed as a message format error.

Code: 8-bit unsigned integer, split into a 3-bit class (most significant bits) and a 5-bit detail (least significant bits), documented as “c.dd” where “c” is a digit from 0 to 7 for the 3-bit subfield and “dd” are two digits from 00 to 31 for the 5-bit subfield. The class can indicate a request (0), a success response (2), a client error response (4), or a server error response (5). (All other class values are reserved.) As a special case, Code 0.00 indicates an Empty message. In case of a request, the Code field indicates the Request Method; in case of a response, a Response Code. Possible values are maintained in the CoAP Code Registries (Section 12.1). The semantics of requests and responses are defined in Section 5.

Message ID: 16-bit unsigned integer in network byte order. Used to detect message duplication and to match messages of type Acknowledgement/Reset to messages of type Confirmable/Non- confirmable. The rules for generating a Message ID and matching messages are defined in Section 4.

The header is followed by the Token value, which may be 0 to 8 bytes, as given by the Token Length field. The Token value is used to correlate requests and responses. The rules for generating a Token and correlating requests and responses are defined in Section 5.3.1.

Header and Token are followed by zero or more Options (Section 3.1). An Option can be followed by the end of the message, by another Option, or by the Payload Marker and the payload.

Following the header, token, and options, if any, comes the optional payload. If present and of non-zero length, it is prefixed by a fixed, one-byte Payload Marker (0xFF), which indicates the end of options and the start of the payload. The payload data extends from after the marker to the end of the UDP datagram, i.e., the Payload Length is calculated from the datagram size. The absence of the Payload Marker denotes a zero-length payload. The presence of a marker followed by a zero-length payload MUST be processed as a message format error.

Implementation Note: The byte value 0xFF may also occur within an option length or value, so simple byte-wise scanning for 0xFF is not a viable technique for finding the payload marker. The byte 0xFF has the meaning of a payload marker only where the beginning of another option could occur.

Fields§

§id: Id

see Id for details

§ty: Type

see Type for details

§ver: Version

see Version for details

§token: Token

see Token for details

§code: Code

see Code for details

§opts: Options

see opt::Opt for details

§payload: Payload<PayloadBytes>

see Payload

Implementations§

source§

impl<PayloadBytes: Array<Item = u8> + AppendCopy<u8>, Options: OptionMap> Message<PayloadBytes, Options>

source

pub fn new(ty: Type, code: Code, id: Id, token: Token) -> Self

Create a new message

source

pub fn cache_key(&self) -> u64

Using DefaultCacheKey, get the cache key for this request.

The cache key can be used to compare messages for representing the same action against the same resource; requests with different IDs but the same method and cache-key affecting options (ex. path, query parameters) will yield the same cache-key.

source

pub fn payload(&self) -> &Payload<PayloadBytes>

Get the payload

source

pub fn set_payload( &mut self, p: Payload<PayloadBytes> ) -> Option<Payload<PayloadBytes>>

Set the payload, returning the old payload if there was one

source

pub fn ack(&self, id: Id) -> Self

Create a new message that ACKs this one.

This needs an Id to assign to the newly created message.

// we are a server

use std::net::SocketAddr;

use toad_msg::alloc::Message;
use toad_msg::Id;

fn server_get_request() -> Option<(SocketAddr, Message)> {
  // Servery sockety things...
}

fn server_send_msg(addr: SocketAddr, msg: Message) -> Result<(), ()> {
  // Message sendy bits...
}

let (addr, req) = server_get_request().unwrap();
let ack_id = Id(req.id.0 + 1);
let ack = req.ack(ack_id);

server_send_msg(addr, ack).unwrap();

Trait Implementations§

source§

impl<PayloadBytes: Clone, Options: Clone> Clone for Message<PayloadBytes, Options>

source§

fn clone(&self) -> Message<PayloadBytes, Options>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<PayloadBytes: Debug, Options: Debug> Debug for Message<PayloadBytes, Options>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<C, O> Hash for Message<C, O>where O: OptionMap + PartialEq + Hash, C: Array<Item = u8>,

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl<PayloadBytes: Array<Item = u8>, Options: OptionMap> Len for Message<PayloadBytes, Options>

source§

const CAPACITY: Option<usize> = None

The maximum number of elements that this data structure can acommodate.
source§

fn len(&self) -> usize

Get the runtime size (in bytes) of a struct Read more
source§

fn is_full(&self) -> bool

Is there no room left in this collection? Read more
source§

fn is_empty(&self) -> bool

Check if the runtime size is zero Read more
source§

impl<P, O> MessageOptions for Message<P, O>where P: Array<Item = u8> + AppendCopy<u8>, O: OptionMap,

§

type OptValues = <O as OptionMap>::OptValues

§

type OptValueBytes = <O as OptionMap>::OptValue

§

type SetError = SetOptionError<OptValue<<Message<P, O> as MessageOptions>::OptValueBytes>, <Message<P, O> as MessageOptions>::OptValues>

source§

fn add( &mut self, n: OptNumber, v: OptValue<Self::OptValueBytes> ) -> Result<(), Self::SetError>

Insert a new value for a given option Read more
source§

fn set( &mut self, n: OptNumber, v: OptValue<Self::OptValueBytes> ) -> Result<Option<Self::OptValues>, Self::SetError>

Replace any / all existing values with a new one, yielding the previous value(s)
source§

fn count(&self, n: OptNumber) -> usize

Get the number of values for a given option
source§

fn get(&self, n: OptNumber) -> Option<&Self::OptValues>

Get the value(s) of an option by number Read more
source§

fn get_first(&self, n: OptNumber) -> Option<&OptValue<Self::OptValueBytes>>

Get the value of an option, taking the first if there are multiple.
source§

fn get_str(&self, n: OptNumber) -> Result<Option<&str>, Utf8Error>

Get the value of an option, and interpret it as a UTF-8 string
source§

fn get_strs<'a, F>(&'a self, n: OptNumber) -> Result<F, Utf8Error>where F: FromIterator<&'a str>,

Get all values for an option, and interpret them as UTF-8 strings
source§

fn get_u8(&self, n: OptNumber) -> Option<u8>

Get the value of an option, and interpret it as a u8
source§

fn get_u16(&self, n: OptNumber) -> Option<u16>

Get the value of an option, and interpret it as a u16
source§

fn get_u32(&self, n: OptNumber) -> Option<u32>

Get the value of an option, and interpret it as a u32
source§

fn get_u64(&self, n: OptNumber) -> Option<u64>

Get the value of an option, and interpret it as a u64
source§

fn remove(&mut self, n: OptNumber) -> Option<Self::OptValues>

Remove all values for the option from this message, returning them if there were any.
source§

fn set_host<S>(&mut self, host: S) -> Result<(), Self::SetError>where S: AsRef<str>,

Update the value for the Uri-Host option, discarding any existing values. Read more
source§

fn block1(&self) -> Option<Block>

source§

fn set_block1( &mut self, size: u16, num: u32, more: bool ) -> Result<(), Self::SetError>

source§

fn block2(&self) -> Option<Block>

source§

fn set_block2( &mut self, size: u16, num: u32, more: bool ) -> Result<(), Self::SetError>

source§

fn host(&self) -> Result<Option<&str>, Utf8Error>

Get the value for the Uri-Host option
source§

fn set_port(&mut self, port: u16) -> Result<(), Self::SetError>

Update the value for the Uri-Port option, discarding any existing values. Read more
source§

fn port(&self) -> Option<u16>

Get the value for the Uri-Port option
source§

fn set_path<S>(&mut self, path: S) -> Result<(), Self::SetError>where S: AsRef<str>,

Update the value for the Uri-Path option, discarding any existing values. Read more
source§

fn path<'a, F>(&'a self) -> Result<F, Utf8Error>where F: FromIterator<&'a str>,

Get an iterator over the Uri-Path segments
source§

fn path_string<'a>(&'a self) -> Result<String, Utf8Error>

Get the fully built path, joining segments with ‘/’.
source§

fn add_query<S>(&mut self, query: S) -> Result<(), Self::SetError>where S: AsRef<str>,

Insert a new value for the Uri-Query option, alongside any existing values.
source§

fn query<'a, F>(&'a self) -> Result<F, Utf8Error>where F: FromIterator<&'a str>,

Get all query parameters for this request Read more
source§

fn set_content_format( &mut self, format: ContentFormat ) -> Result<(), Self::SetError>

Update the value for the Content-Format option, discarding any existing values. Read more
source§

fn content_format(&self) -> Option<ContentFormat>

Get the value for the Content-Format option Read more
source§

fn set_observe(&mut self, a: Action) -> Result<(), Self::SetError>

Set the value for the Observe option, discarding any existing values.
source§

fn observe(&self) -> Option<Action>

Get the value for the Observe option
source§

fn set_accept(&mut self, format: ContentFormat) -> Result<(), Self::SetError>

Update the value for the Accept option, discarding any existing values. Read more
source§

fn accept(&self) -> Option<ContentFormat>

Get the value for the Accept option
source§

fn set_size1(&mut self, size_bytes: u64) -> Result<(), Self::SetError>

Update the value for the Size1 option, discarding any existing values. Read more
source§

fn size1(&self) -> Option<u64>

Get the value for the Size1 option
source§

fn set_size2(&mut self, size_bytes: u64) -> Result<(), Self::SetError>

Update the value for the Size2 option, discarding any existing values.
source§

fn size2(&self) -> Option<u64>

Get the value for the Size2 option
source§

fn set_if_exists(&mut self) -> Result<(), Self::SetError>

Discard all values for If-Match, and replace them with an empty value. Read more
source§

fn if_exists_flag_enabled(&self) -> bool

Get whether or not Message::set_if_exists applies
source§

fn set_if_not_exists(&mut self) -> Result<(), Self::SetError>

Enable the If-None-Match flag Read more
source§

fn if_not_exists_flag_enabled(&self) -> bool

Get whether or not Message::set_if_not_exists applies
source§

fn set_max_age(&mut self, max_age_seconds: u32) -> Result<(), Self::SetError>

Update the value for the Max-Age option, discarding any existing values. Read more
source§

fn max_age_seconds(&self) -> Option<u32>

Get the value for the Max-Age option, in seconds
source§

fn set_proxy_uri<S>(&mut self, uri: S) -> Result<(), Self::SetError>where S: AsRef<str>,

Update the value for the Proxy-Uri option, discarding any existing values. Read more
source§

fn proxy_uri(&self) -> Result<Option<&str>, Utf8Error>

Get the value for the Proxy-Uri option
source§

fn set_proxy_scheme<S>(&mut self, scheme: S) -> Result<(), Self::SetError>where S: AsRef<str>,

Update the value for the Proxy-Scheme option, discarding any existing values.
source§

fn proxy_scheme(&self) -> Result<Option<&str>, Utf8Error>

Get the value for the Proxy-Scheme option
source§

fn add_if_match<B>(&mut self, tag: B) -> Result<(), Self::SetError>where B: AsRef<[u8]>,

Insert a new value for the If-Match option, alongside any existing values. Read more
source§

fn if_match(&self) -> Option<&Self::OptValues>

Get all values for the If-Match option
source§

fn add_location_path<S>(&mut self, path: S) -> Result<(), Self::SetError>where S: AsRef<str>,

Insert a new value for the Location-Path option, alongside any existing values. Read more
source§

fn location_path<'a, F>(&'a self) -> Result<F, Utf8Error>where F: FromIterator<&'a str>,

Get all values for the Location-Path option
source§

fn add_location_query<S>(&mut self, query: S) -> Result<(), Self::SetError>where S: AsRef<str>,

Insert a new value for the Location-Query option, alongside any existing values. Read more
source§

fn location_query<'a, F>(&'a self) -> Result<F, Utf8Error>where F: FromIterator<&'a str>,

Get all values for the Location-Query option
source§

fn add_etag<B>(&mut self, tag: B) -> Result<(), Self::SetError>where B: AsRef<[u8]>,

Insert a new value for the ETag option, alongside any existing values. Read more
source§

fn etags(&self) -> Option<&Self::OptValues>

Get all values for the ETag option
source§

impl<C, O> Ord for Message<C, O>where O: OptionMap + PartialOrd, C: Array<Item = u8>,

source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Selfwhere Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Selfwhere Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Selfwhere Self: Sized + PartialOrd<Self>,

Restrict a value to a certain interval. Read more
source§

impl<C, O> PartialEq<Message<C, O>> for Message<C, O>where O: OptionMap + PartialEq, C: Array<Item = u8>,

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<C, O> PartialOrd<Message<C, O>> for Message<C, O>where O: OptionMap + PartialOrd, C: Array<Item = u8>,

source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more
source§

impl<Bytes: AsRef<[u8]>, PayloadBytes: Array<Item = u8> + AppendCopy<u8>, Options: OptionMap> TryFromBytes<Bytes> for Message<PayloadBytes, Options>

§

type Error = MessageParseError

Error type yielded if conversion fails
source§

fn try_from_bytes(bytes: Bytes) -> Result<Self, Self::Error>

Try to convert from some sequence of bytes T into Self
source§

impl<PayloadBytes: Array<Item = u8>, Options: OptionMap> TryIntoBytes for Message<PayloadBytes, Options>

§

type Error = MessageToBytesError

source§

fn try_into_bytes<C: Array<Item = u8>>(self) -> Result<C, Self::Error>

Try to convert into a collection of bytes Read more
source§

impl<C, O> Eq for Message<C, O>where O: OptionMap + PartialEq, C: Array<Item = u8>,

Auto Trait Implementations§

§

impl<PayloadBytes, Options> RefUnwindSafe for Message<PayloadBytes, Options>where Options: RefUnwindSafe, PayloadBytes: RefUnwindSafe,

§

impl<PayloadBytes, Options> Send for Message<PayloadBytes, Options>where Options: Send, PayloadBytes: Send,

§

impl<PayloadBytes, Options> Sync for Message<PayloadBytes, Options>where Options: Sync, PayloadBytes: Sync,

§

impl<PayloadBytes, Options> Unpin for Message<PayloadBytes, Options>where Options: Unpin, PayloadBytes: Unpin,

§

impl<PayloadBytes, Options> UnwindSafe for Message<PayloadBytes, Options>where Options: UnwindSafe, PayloadBytes: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.