horust_commands_lib/
server.rs

1use crate::proto::messages::horust_msg_message::MessageType::Request;
2use crate::proto::messages::{
3    horust_msg_message, horust_msg_request, horust_msg_response, HorustMsgError, HorustMsgMessage,
4    HorustMsgRequest, HorustMsgResponse, HorustMsgServiceStatus, HorustMsgServiceStatusResponse,
5};
6use crate::UdsConnectionHandler;
7use anyhow::{anyhow, Result};
8use log::{error, info};
9use std::io::ErrorKind;
10use std::os::unix::net::UnixListener;
11
12pub trait CommandsHandlerTrait {
13    fn start(&mut self) -> Result<()> {
14        // put the server logic in a loop to accept several connections
15        loop {
16            self.accept().expect("TODO: panic message");
17        }
18    }
19    fn get_unix_listener(&mut self) -> &mut UnixListener;
20    fn accept(&mut self) -> Result<()> {
21        match self.get_unix_listener().accept() {
22            Ok((stream, _addr)) => {
23                let conn_handler = UdsConnectionHandler::new(stream);
24                if let Err(err) = self.handle_connection(conn_handler) {
25                    //todo: send response back.
26                    error!("Error handling connection: {}", err);
27                }
28            }
29            Err(e) => {
30                let kind = e.kind();
31                if !matches!(kind, ErrorKind::WouldBlock) {
32                    error!("Error accepting connction: {e} - you might need to restart Horust.");
33                }
34            }
35        };
36        Ok(())
37    }
38    fn handle_connection(&self, mut uds_conn_handler: UdsConnectionHandler) -> Result<()> {
39        let received = uds_conn_handler
40            .receive_message()?
41            .message_type
42            .ok_or(anyhow!("No request found in message sent from client."))?;
43
44        if let Request(HorustMsgRequest {
45            request: Some(request),
46        }) = received
47        {
48            let response = match request {
49                horust_msg_request::Request::StatusRequest(status_request) => {
50                    info!("Requested status for {}", status_request.service_name);
51
52                    let service_status = self.get_service_status(&status_request.service_name);
53                    service_status
54                        .map(|status| {
55                            new_horust_msg_service_status_response(
56                                status_request.service_name,
57                                status,
58                            )
59                        })
60                        .unwrap_or_else(|err| {
61                            new_horust_msg_error_response(format!(
62                                "Error from status handler: {err}",
63                            ))
64                        })
65                }
66                horust_msg_request::Request::ChangeRequest(change_request) => {
67                    info!(
68                        "Requested service update for {} to {}",
69                        change_request.service_name, change_request.service_status
70                    );
71                    new_horust_msg_error_response("Unimplemented!".to_string())
72                    /*self.update_service_status(
73                        &change_request.service_name,
74                        HorustMsgServiceStatus::from_i32(change_request.service_status).unwrap(),
75                    )
76                    .map(|new_status| {
77                        // TODO:
78                        new_horust_msg_service_status_response(
79                            change_request.service_name,
80                            new_status,
81                        )
82                    })
83                    .unwrap_or_else(|err| {
84                        new_horust_msg_error_response(format!("Error from change handler: {err}"))
85                    })*/
86                }
87            };
88            uds_conn_handler.send_message(response)?;
89        }
90        Ok(())
91    }
92
93    fn get_service_status(&self, service_name: &str) -> Result<HorustMsgServiceStatus>;
94    fn update_service_status(
95        &self,
96        service_name: &str,
97        new_status: HorustMsgServiceStatus,
98    ) -> Result<()>;
99}
100
101pub fn new_horust_msg_error_response(error: String) -> HorustMsgMessage {
102    HorustMsgMessage {
103        message_type: Some(horust_msg_message::MessageType::Response(
104            HorustMsgResponse {
105                response: Some(horust_msg_response::Response::Error(HorustMsgError {
106                    error_string: error,
107                })),
108            },
109        )),
110    }
111}
112
113pub fn new_horust_msg_service_status_response(
114    service_name: String,
115    status: HorustMsgServiceStatus,
116) -> HorustMsgMessage {
117    HorustMsgMessage {
118        message_type: Some(horust_msg_message::MessageType::Response(
119            HorustMsgResponse {
120                response: Some(horust_msg_response::Response::StatusResponse(
121                    HorustMsgServiceStatusResponse {
122                        service_name,
123                        service_status: status.into(),
124                    },
125                )),
126            },
127        )),
128    }
129}