coap_handler/
handler.rs

1/// A minimal stateless testing CoAP server interface.
2use coap_message::{MinimalWritableMessage, MutableWritableMessage, ReadableMessage};
3
4/// A CoAP request handler. This gets called by a CoAP server implementation that the handler is
5/// assigned to; the server has the handler [processes the request's
6/// data](Self::extract_request_data) into a RequestData structure, possibly calls [asks for the
7/// expected length](Self::estimate_length) before allocating a response message, and then asks the
8/// handler to [populate the allocated response message](Self::build_response) with data persisted
9/// in the RequestData structure.
10///
11/// Both data extraction and response building are fallible operations. In the error case, it is up
12/// to the CoAP server implementation to reset the message into a state into which the error can be
13/// [rendered](coap_message::error::RenderableOnMinimal::render). There is currently no trait
14/// method in [`coap_message`] that describes how that would be done, but the CoAP implementation
15/// knows the concrete type and can use its methods directly.
16pub trait Handler {
17    /// Type constructed in [`extract_request_data()`](Self::extract_request_data) passed on to
18    /// [`build_response()`](Self::build_response).
19    ///
20    /// This type can usually be made very compact, with exceptions for POST style requests where
21    /// not only do request and response have large payloads, but also both are needed at the same
22    /// time.
23    type RequestData;
24
25    /// Error type for [`extract_request_data()`](Self::extract_request_data).
26    ///
27    /// Typical types to use here are [core::convert::Infallible] (which, due to the possibility of
28    /// unknown critical CoAP options, is only practical when their presence is carried in the
29    /// extracted data) or types provided by libraries (eg.
30    /// [coap-handler-implementations::Error](https://docs.rs/coap-handler-implementations/0.5.0/coap_handler_implementations/struct.Error.html)).
31    type ExtractRequestError: core::fmt::Debug + coap_message::error::RenderableOnMinimal;
32    /// Error type for [writing response data](Self::build_response).
33    ///
34    /// This is generic over writable messages because the most typical errors to show up here are
35    /// generated when writing to the messages. A suitable type here is `M::UnionError`.
36    // FIXME could we carry an error type in here instead of the message? if so, does the same
37    // apply to render?
38    type BuildResponseError<M: MinimalWritableMessage>: core::fmt::Debug
39        + coap_message::error::RenderableOnMinimal;
40
41    /// Process an incoming request.
42    ///
43    /// Unless the server implementation performs request deduplication, this may be called
44    /// multiple times per request. Whether a server performs request deduplication (and thus the
45    /// handlers need to be idempotent, which is best practice in CoAP anyway) is not expressed in
46    /// the type system.
47    ///
48    /// Effects of requests may already be performed at this step -- to the point where
49    /// [Self::RequestData] is `()` to indicate success.
50    fn extract_request_data<M: ReadableMessage>(
51        &mut self,
52        request: &M,
53    ) -> Result<Self::RequestData, Self::ExtractRequestError>;
54    /// Estimate an upper bound for the number of bytes in the response
55    ///
56    /// Sizes are counted as in UDP after the header, i.e., encoded options plus payload indicator
57    /// plus payload.
58    fn estimate_length(&mut self, request: &Self::RequestData) -> usize;
59    /// Build a response for the request
60    ///
61    /// While this is typically called exactly once per request, it can also be called not at all
62    /// (eg. if a TCP connection was dropped between parsing the request and sending the response)
63    /// or multiple times (if the response was sent in a CON, needed to be retransmitted, and the
64    /// RequestData is Clone).
65    fn build_response<M: MutableWritableMessage>(
66        &mut self,
67        response: &mut M,
68        request: Self::RequestData,
69    ) -> Result<(), Self::BuildResponseError<M>>;
70}