coap_lite/lib.rs
1//! A lightweight low-level CoAP message manipulation crate.
2//!
3//! Its goal is to be compliant with the CoAP standards and to provide a
4//! building block for libraries (e.g.
5//! [coap](https://github.com/Covertness/coap-rs)) and applications.
6//!
7//! `coap-lite` supports `#![no_std]` and embedded environments.
8//!
9//! It was originally based on the improved low-level message handling code
10//! from the [coap] crate as well as [rust-async-coap], made to work in bare
11//! metal environments.
12//!
13//! ## Supported RFCs
14//!
15//! - CoAP [RFC 7252](https://tools.ietf.org/html/rfc7252)
16//! - CoAP Observe Option [RFC 7641](https://tools.ietf.org/html/rfc7641)
17//! - Too Many Requests Response Code [RFC 8516](https://tools.ietf.org/html/rfc8516)
18//! - Block-Wise Transfers [RFC 7959](https://tools.ietf.org/html/rfc7959)
19//! - Constrained RESTful Environments (CoRE) Link Format
20//! [RFC6690](https://tools.ietf.org/html/rfc6690#:~:text=well-known%2Fcore)
21//!
22//! ## Usage
23//!
24//! This crate provides several types that can be used to build, modify and
25//! encode/decode CoAP messages to/from their byte representation.
26//!
27//! **Note for no_std users**: it does require allocation, so you might have to
28//! set a global allocator depending on your target.
29//!
30//! ### Client
31//!
32//! The following example uses `std::net::UdpSocket` to send the UDP packet but
33//! you can use anything, e.g. [smoltcp](https://github.com/smoltcp-rs/smoltcp)
34//! for embedded.
35//!
36//! ```rust
37//! use coap_lite::{
38//! CoapRequest, RequestType as Method
39//! };
40//! use std::net::{SocketAddr, UdpSocket};
41//!
42//! fn main() {
43//! let mut request: CoapRequest<SocketAddr> = CoapRequest::new();
44//!
45//! request.set_method(Method::Get);
46//! request.set_path("/test");
47//!
48//! let socket = UdpSocket::bind("127.0.0.1:0").unwrap();
49//!
50//! let packet = request.message.to_bytes().unwrap();
51//! socket.send_to(&packet[..], "127.0.0.1:5683").expect("Could not send the data");
52//! }
53//! ```
54//!
55//! ### Server
56//!
57//! ```rust
58//! use coap_lite::{CoapRequest, Packet};
59//! use std::net::{UdpSocket};
60//!
61//! fn main() {
62//! let socket = UdpSocket::bind("127.0.0.1:5683").unwrap();
63//! let mut buf = [0; 100];
64//! let (size, src) = socket.recv_from(&mut buf).expect("Didn't receive data");
65//!
66//! println!("Payload {:x?}", &buf[..size]);
67//!
68//! let packet = Packet::from_bytes(&buf[..size]).unwrap();
69//! let request = CoapRequest::from_packet(packet, src);
70//!
71//! let method = request.get_method().clone();
72//! let path = request.get_path();
73//!
74//! println!("Received CoAP request '{:?} {}' from {}", method, path, src);
75//!
76//! let mut response = request.response.unwrap();
77//! response.message.payload = b"OK".to_vec();
78//!
79//! let packet = response.message.to_bytes().unwrap();
80//! socket.send_to(&packet[..], &src).expect("Could not send the data");
81//! }
82//! ```
83//!
84//! ### Low-level binary conversion
85//!
86//! ```rust
87//! use coap_lite::{
88//! CoapOption, MessageClass, MessageType,
89//! Packet, RequestType, ResponseType,
90//! };
91//!
92//! let mut request = Packet::new();
93//! request.header.message_id = 23839;
94//! request.header.code = MessageClass::Request(RequestType::Get);
95//! request.set_token(vec![0, 0, 57, 116]);
96//! request.add_option(CoapOption::UriHost, b"localhost".to_vec());
97//! request.add_option(CoapOption::UriPath, b"tv1".to_vec());
98//! assert_eq!(
99//! [
100//! 0x44, 0x01, 0x5D, 0x1F, 0x00, 0x00, 0x39, 0x74, 0x39, 0x6C, 0x6F,
101//! 0x63, 0x61, 0x6C, 0x68, 0x6F, 0x73, 0x74, 0x83, 0x74, 0x76, 0x31,
102//! ],
103//! request.to_bytes().unwrap()[..]
104//! );
105//!
106//! let response = Packet::from_bytes(&[
107//! 0x64, 0x45, 0x5D, 0x1F, 0x00, 0x00, 0x39, 0x74, 0xFF, 0x48, 0x65,
108//! 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21,
109//! ])
110//! .unwrap();
111//! assert_eq!(23839, response.header.message_id);
112//! assert_eq!(
113//! MessageClass::Response(ResponseType::Content),
114//! response.header.code
115//! );
116//! assert_eq!(MessageType::Acknowledgement, response.header.get_type());
117//! assert_eq!([0, 0, 57, 116], response.get_token()[..]);
118//! assert_eq!(b"Hello World!", &response.payload[..]);
119//! ```
120//!
121//! [coap]: https://github.com/covertness/coap-rs
122//! [rust-async-coap]: https://github.com/google/rust-async-coap
123
124#![cfg_attr(not(feature = "std"), no_std)]
125#![allow(clippy::needless_doctest_main)]
126
127#[macro_use]
128extern crate alloc;
129
130pub mod error;
131
132#[cfg(feature = "std")]
133pub mod block_handler;
134mod header;
135pub mod link_format;
136#[macro_use]
137mod log;
138mod observe;
139pub mod option_value;
140mod packet;
141mod request;
142mod response;
143
144mod impl_coap_message;
145mod impl_coap_message_0_3;
146
147#[cfg(feature = "std")]
148pub use block_handler::{BlockHandler, BlockHandlerConfig};
149pub use header::{
150 Header, HeaderRaw, MessageClass, MessageType, RequestType, ResponseType,
151};
152pub use observe::{create_notification, Subject};
153pub use packet::{CoapOption, ContentFormat, ObserveOption, Packet};
154pub use request::CoapRequest;
155pub use response::CoapResponse;