haproxy_stats_socket/client/
mod.rs1use 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
16mod 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
25pub 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 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 stream
63 .write_all(&write_bytes[..])
64 .map_err(ClientSendError::WriteFailed)?;
65
66 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 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 stream
94 .write_all(&write_bytes[..])
95 .await
96 .map_err(ClientSendError::WriteFailed)?;
97
98 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 }
133
134#[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 {}