haproxy_stats_socket/client/
mod.rs

1use core::fmt;
2use std::{
3    io::{Error as IoError, Read as _, Write as _},
4    net::{SocketAddr, TcpStream},
5    os::unix::net::UnixStream,
6    path::Path,
7};
8
9use futures_util_either::Either;
10use haproxy_stats::Command;
11use tokio::{
12    io::{AsyncReadExt as _, AsyncWriteExt as _},
13    net::{TcpStream as TokioTcpStream, UnixStream as TokioUnixStream},
14};
15
16//
17mod impl_show_env;
18mod impl_show_info;
19mod impl_show_stat;
20
21pub use impl_show_env::ClientShowEnvError;
22pub use impl_show_info::ClientShowInfoError;
23pub use impl_show_stat::ClientShowStatError;
24
25//
26pub struct Client {
27    connect_info: ConnectInfo,
28}
29
30enum ConnectInfo {
31    Tcp(SocketAddr),
32    Unix(Box<Path>),
33}
34
35impl Client {
36    pub fn with_tcp(addr: impl Into<SocketAddr>) -> Self {
37        Self {
38            connect_info: ConnectInfo::Tcp(addr.into()),
39        }
40    }
41
42    pub fn with_unix(path: impl AsRef<Path>) -> Self {
43        Self {
44            connect_info: ConnectInfo::Unix(path.as_ref().into()),
45        }
46    }
47
48    pub fn send(&self, command: &Command) -> Result<Vec<u8>, ClientSendError> {
49        let write_bytes = command.to_write_bytes();
50
51        //
52        let mut stream = match &self.connect_info {
53            ConnectInfo::Tcp(addr) => {
54                Either::Left(TcpStream::connect(addr).map_err(ClientSendError::ConnectFailed)?)
55            }
56            ConnectInfo::Unix(path) => {
57                Either::Right(UnixStream::connect(path).map_err(ClientSendError::ConnectFailed)?)
58            }
59        };
60
61        //
62        stream
63            .write_all(&write_bytes[..])
64            .map_err(ClientSendError::WriteFailed)?;
65
66        //
67        let mut response: Vec<u8> = Vec::with_capacity(2048);
68        stream
69            .read_to_end(&mut response)
70            .map_err(ClientSendError::ReadFailed)?;
71
72        Ok(response)
73    }
74
75    pub async fn send_async(&self, command: &Command) -> Result<Vec<u8>, ClientSendError> {
76        let write_bytes = command.to_write_bytes();
77
78        //
79        let mut stream = match &self.connect_info {
80            ConnectInfo::Tcp(addr) => Either::Left(
81                TokioTcpStream::connect(addr)
82                    .await
83                    .map_err(ClientSendError::ConnectFailed)?,
84            ),
85            ConnectInfo::Unix(path) => Either::Right(
86                TokioUnixStream::connect(path)
87                    .await
88                    .map_err(ClientSendError::ConnectFailed)?,
89            ),
90        };
91
92        //
93        stream
94            .write_all(&write_bytes[..])
95            .await
96            .map_err(ClientSendError::WriteFailed)?;
97
98        //
99        let mut response: Vec<u8> = Vec::with_capacity(2048);
100        let mut buf = vec![0; 2048];
101        loop {
102            let n = stream
103                .read(&mut buf)
104                .await
105                .map_err(ClientSendError::ReadFailed)?;
106
107            if n == 0 {
108                break;
109            }
110            response.extend_from_slice(&buf[..n]);
111        }
112
113        Ok(response)
114    }
115
116    // TODO,
117    // pub fn send_multiple(&self, commands: Commands<'_>) -> Result<Vec<Vec<u8>>, ClientSendError> {
118    //     let _write_bytes = commands.to_write_bytes();
119
120    //     todo!()
121    // }
122
123    // TODO,
124    // pub async fn send_multiple_async(
125    //     &self,
126    //     commands: Commands<'_>,
127    // ) -> Result<Vec<Vec<u8>>, ClientSendError> {
128    //     let _write_bytes = commands.to_write_bytes();
129
130    //     todo!()
131    // }
132}
133
134//
135//
136//
137#[derive(Debug)]
138pub enum ClientSendError {
139    ConnectFailed(IoError),
140    WriteFailed(IoError),
141    ReadFailed(IoError),
142}
143
144impl fmt::Display for ClientSendError {
145    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146        write!(f, "{:?}", self)
147    }
148}
149
150impl std::error::Error for ClientSendError {}