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