hyperion/servers/
boblight.rs

1//! Boblight protocol server implementation
2
3use std::net::SocketAddr;
4
5use futures::prelude::*;
6use thiserror::Error;
7use tokio::net::TcpStream;
8use tokio_util::codec::Framed;
9
10use crate::{
11    api::boblight::{self, BoblightApiError},
12    global::{Global, InputSourceName},
13    instance::InstanceHandle,
14};
15
16/// Boblight protocol codec definition
17mod codec;
18use codec::*;
19
20#[derive(Debug, Error)]
21pub enum BoblightServerError {
22    #[error("i/o error: {0}")]
23    Io(#[from] futures_io::Error),
24    #[error("codec error: {0}")]
25    Codec(#[from] BoblightCodecError),
26    #[error(transparent)]
27    Api(#[from] BoblightApiError),
28}
29
30#[instrument(skip(socket, led_count, instance, global))]
31pub async fn handle_client(
32    (socket, peer_addr): (TcpStream, SocketAddr),
33    led_count: usize,
34    instance: InstanceHandle,
35    global: Global,
36) -> Result<(), BoblightServerError> {
37    debug!("accepted new connection");
38
39    let framed = Framed::new(socket, BoblightCodec::new());
40    let (mut writer, mut reader) = framed.split();
41
42    let source_handle = global
43        .register_input_source(InputSourceName::Boblight { peer_addr }, None)
44        .await
45        .unwrap();
46
47    let mut connection = boblight::ClientConnection::new(source_handle, led_count, instance);
48
49    while let Some(request) = reader.next().await {
50        trace!(request = ?request, "processing");
51
52        match request {
53            Ok(request) => match connection.handle_request(request).await {
54                Ok(response) => {
55                    if let Some(response) = response {
56                        writer.send(response).await?;
57                        writer.flush().await?;
58                    }
59                }
60                Err(error) => {
61                    warn!(error = %error, "boblight error");
62                }
63            },
64            Err(error) => {
65                warn!(error = %error, "boblight error");
66            }
67        }
68    }
69
70    Ok(())
71}