libcoap_rs/lib.rs
1// SPDX-License-Identifier: BSD-2-Clause
2/*
3 * Copyright © The libcoap-rs Contributors, all rights reserved.
4 * This file is part of the libcoap-rs project, see the README file for
5 * general information on this project and the NOTICE.md and LICENSE files
6 * for information regarding copyright ownership and terms of use.
7 *
8 * lib.rs - Main library entry point for safe libcoap bindings.
9 */
10
11//! A safe wrapper around the libcoap C library.
12//!
13//! This wrapper allows for safe and idiomatic usage of the libcoap C library in Rust.
14//!
15//! # Feature support
16//! libcoap-rs currently supports the following subset of the libcoap feature set:
17//! - [x] Basic CoAP client
18//! - [x] Basic CoAP server
19//! - [ ] Transports:
20//! - [x] UDP
21//! - [x] DTLS
22//! - [x] DTLS using PSK
23//! - [x] DTLS using PKI/RPK
24//! - [ ] TCP
25//! - [ ] TLS
26//! - [ ] OSCORE
27//! - [ ] WebSockets
28//! - [ ] Blockwise Transfer
29//! - [x] Receiving large messages
30//! - Note: Handled in libcoap by setting `COAP_BLOCK_USE_LIBCOAP|COAP_BLOCK_SINGLE_BODY`.
31//! Manually constructing and managing blockwise transfers is currently not in scope
32//! for this library.
33//! - [x] sending client-side large messages
34//! - [ ] sending server-side large messages
35//! - [ ] Resource observation
36//! - [ ] Observing resources as a client
37//! - [x] Notifying observers as a server
38//!
39//! # Building
40//! libcoap-rs is based on libcoap-sys, which provide many different ways to obtain and link against
41//! a system-provided or vendored version of the libcoap C library.
42//!
43//! Refer to [its documentation](libcoap_sys) for detailed instructions on how to
44//! build libcoap-sys as well as this library.
45//!
46//! Most of these instructions can be applied to libcoap-rs directly, although libcoap-rs does
47//! abstract away some of the features.
48//!
49//! For your convenience, libcoap-rs "re-exports" some features that do not have any influence on
50//! the safe wrapper, but may have to be set in libcoap-sys to enable building (e.g., the
51//! `dtls-<LIBRARY NAME>-sys` features).
52//! This way, you don't need to add libcoap-sys as a dependency yourself, and may just enable the
53//! feature in this crate instead.
54//!
55//! # Examples
56//!
57//! ## Client
58//! This example runs a simple CoAP client which makes a request to `coap://[::1]:5683/hello_world`
59//! and checks whether the result has the code 2.00 (Content) and the payload `Hello World!`.
60//!
61//! ```no_run
62//! use std::{
63//! net::{SocketAddr, UdpSocket},
64//! time::Duration,
65//! };
66//!
67//! use libcoap_rs::{
68//! CoapContext,
69//! message::{CoapMessageCommon, CoapResponse, CoapRequest},
70//! protocol::{CoapRequestCode, CoapResponseCode, CoapMessageCode, CoapMessageType},
71//! CoapRequestHandler, CoapResource,
72//! session::{CoapSessionCommon, CoapClientSession},
73//! types::{CoapUriScheme, CoapUri}
74//! };
75//!
76//! let server_address : SocketAddr = "[::1]:5683".parse().unwrap();
77//!
78//! // Create a new context.
79//! let mut context = CoapContext::new().expect("Failed to create CoAP context");
80//!
81//! // Connect to the server at the specified address over UDP (no encryption)
82//! let session = CoapClientSession::connect_udp(&mut context, server_address)
83//! .expect("Failed to create client-side session");
84//!
85//! // Create a new CoAP URI to request from.
86//! let uri = "coap://[::1]:5683/hello_world".parse().unwrap();
87//!
88//! // Create a new request of type get with the specified URI.
89//! let mut request = CoapRequest::new(CoapMessageType::Con, CoapRequestCode::Get, uri).unwrap();
90//!
91//! // Send the request and wait for a response.
92//! let req_handle = session.send_request(request).expect("Unable to send request");
93//! loop {
94//! context.do_io(Some(Duration::from_secs(10))).expect("error during IO");
95//! // Poll for responses to a request using the request handle.
96//! for response in session.poll_handle(&req_handle) {
97//! assert_eq!(response.code(), CoapMessageCode::Response(CoapResponseCode::Content));
98//! assert_eq!(response.data().unwrap().as_ref(), "Hello World!".as_bytes());
99//! return;
100//! }
101//! }
102//! ```
103//!
104//! ## Server
105//! This example runs a simple CoAP server that provides a resource under the URI path
106//! `/hello_world` with `Hello World!` as the response payload.
107//!
108//! ```no_run
109//! use std::{
110//! net::{SocketAddr, UdpSocket},
111//! time::Duration,
112//! };
113//!
114//! use libcoap_rs::{
115//! CoapContext,
116//! message::{CoapMessageCommon, CoapResponse, CoapRequest},
117//! protocol::{CoapRequestCode, CoapResponseCode},
118//! CoapRequestHandler, CoapResource,
119//! session::{CoapSessionCommon, CoapServerSession},
120//! };
121//!
122//! // a new CoAP context and bind to the generated SocketAddr.
123//! let mut context = CoapContext::new().expect("Failed to create CoAP context");
124//! context.add_endpoint_udp("[::1]:5683".parse().unwrap()).expect("Unable to add/bind to endpoint");
125//!
126//! // Create a new resource that is available at the URI path `hello_world`
127//! // The second argument can be used to provide any kind of user-specific data, which will
128//! // then be passed to the handler function.
129//! let resource = CoapResource::new("hello_world", (), false);
130//! // Set a method handler for the GET method.
131//! resource.set_method_handler(
132//! CoapRequestCode::Get,
133//! Some(CoapRequestHandler::new(
134//! // The handler can be a lambda or some other kind of function.
135//! // Using methods is also possible by setting the resource's user data to an instance
136//! // of the struct, as the first argument will then be a mutable reference to the
137//! // user data. Methods will then use this user data as the `&mut self` reference.
138//! //
139//! // The provided CoapResponse is already filled with the correct token to be
140//! // interpreted as a response to the correct request by the client.
141//! |completed: &mut (), session: &mut CoapServerSession, request: &CoapRequest, mut response: CoapResponse| {
142//! // Set content of the response message to "Hello World!"
143//! let data = Vec::<u8>::from("Hello World!".as_bytes());
144//! response.set_data(Some(data));
145//! // Set the response code to 2.00 "Content"
146//! response.set_code(CoapResponseCode::Content);
147//! // Send the response message.
148//! session.send(response).expect("Unable to send response");
149//! },
150//! )),
151//! );
152//!
153//! // Add the resource to the context.
154//! context.add_resource(resource);
155//! loop {
156//! // process IO in a loop...
157//! if let Err(e) = context.do_io(Some(Duration::from_secs(1))) {
158//! break;
159//! }
160//! // ...until we want to shut down.
161//! }
162//! // Properly shut down, completing outstanding IO requests and properly closing sessions.
163//! context.shutdown(Some(Duration::from_secs(0))).unwrap();
164//! ```
165
166extern crate core;
167
168pub use context::CoapContext;
169pub use event::CoapEventHandler;
170pub use resource::{CoapRequestHandler, CoapResource};
171
172mod context;
173#[cfg(feature = "dtls")]
174pub mod crypto;
175pub mod error;
176mod event;
177mod mem;
178pub mod message;
179pub mod prng;
180pub mod protocol;
181mod resource;
182pub mod session;
183pub mod transport;
184pub mod types;