coap-server 0.1.1

Robust async CoAP server
Documentation
use std::net::SocketAddr;
use std::pin::Pin;
use std::sync::Arc;

use coap_lite::{CoapResponse, Packet};
use futures::Stream;
use log::info;
use tokio::sync::Mutex;

use coap_server::packet_handler::PacketHandler;
use coap_server::server::FatalServerError;
use coap_server::{CoapServer, UdpTransport};

#[tokio::main]
async fn main() -> Result<(), FatalServerError> {
    env_logger::init();

    let server = CoapServer::bind(UdpTransport::new("0.0.0.0:5683")).await?;
    info!("Server is bound to 0.0.0.0:5683!");
    server.serve(CountingService::default()).await
}

#[derive(Clone)]
struct CountingService {
    counter: Arc<Mutex<u32>>,
}

impl Default for CountingService {
    fn default() -> Self {
        Self {
            counter: Arc::new(Mutex::new(0)),
        }
    }
}

/// It is possible to do all the raw packet handling yourself if you have some very sophisticated
/// use case not currently covered by the generic App-based handler.  Pull requests welcome,
/// however!
impl PacketHandler<SocketAddr> for CountingService {
    fn handle(
        &self,
        packet: Packet,
        peer: SocketAddr,
    ) -> Pin<Box<dyn Stream<Item = Packet> + Send + '_>> {
        let stream = async_stream::stream! {
          if let Some(mut response) = CoapResponse::new(&packet) {
            let count = {
              let mut counter = self.counter.lock().await;
              *counter += 1;
              *counter
            };
            response.message.payload = format!("Hello {peer}, count is now {count}").into_bytes();
            yield response.message;
          }
        };
        Box::pin(stream)
    }
}