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;