1use crate::message;
2use crate::stream;
3use log::{error, info, trace};
4use std::fs::File;
5use std::io::ErrorKind;
6use std::io::Read;
7use tokio::{
8 io::{AsyncReadExt, AsyncWriteExt},
9 net::TcpStream,
10 net::UnixStream,
11};
12use tokio_native_tls::native_tls::{Certificate, TlsConnector};
13use tokio_native_tls::TlsStream;
14
15#[derive(Debug, Clone)]
17pub struct PubSubTcpClient {
18 pub server: String,
19 pub port: u16,
20 pub cert: Option<String>,
21 pub cert_password: Option<String>,
22}
23
24#[derive(Debug, Clone)]
26pub struct PubSubUnixClient {
27 pub path: String,
28}
29
30#[derive(Debug, Clone)]
32pub enum PubSubClient {
33 Tcp(PubSubTcpClient),
34 Unix(PubSubUnixClient),
35}
36
37#[derive(Debug)]
39pub enum StreamType {
40 Tcp(TcpStream),
41 Tls(TlsStream<TcpStream>),
42 Unix(UnixStream),
43}
44
45type Callback = fn(String, Vec<u8>);
47
48#[derive(Debug)]
50pub struct Client {
51 pub client_type: PubSubClient,
52 stream: Option<StreamType>,
53 callback: Option<Callback>,
54}
55
56pub fn on_message(topic: String, message: Vec<u8>) {
58 match String::from_utf8(message.clone()) {
59 Ok(msg_str) => {
60 info!("topic: {} message: {}", topic, msg_str);
61 }
62 Err(_) => {
63 info!("topic: {} message: {:?}", topic, message);
64 }
65 };
66}
67
68impl Client {
69 pub fn new(client_type: PubSubClient) -> Client {
71 Client {
72 client_type,
73 stream: None,
74 callback: None,
75 }
76 }
77
78 pub fn on_message(&mut self, callback: Callback) {
80 self.callback = Some(callback)
81 }
82
83 async fn connect_tls(&mut self, url: String, cert: String) -> Result<(), tokio::io::Error> {
84 let mut file = match File::open(cert) {
86 Ok(file) => file,
87 Err(e) => {
88 error!("unable to open the certificate file: {}", e);
89 return Err(tokio::io::Error::new(tokio::io::ErrorKind::Other, e));
90 }
91 };
92 let mut ca_cert = vec![];
93 match file.read_to_end(&mut ca_cert) {
94 Ok(size) => size,
95 Err(e) => {
96 error!("unable to read the CA file: {}", e);
97 return Err(tokio::io::Error::new(tokio::io::ErrorKind::Other, e));
98 }
99 };
100 let ca_cert = match Certificate::from_pem(&ca_cert) {
101 Ok(cert) => cert,
102 Err(e) => {
103 error!("unable to parse the CA certificate: {}", e);
104 return Err(tokio::io::Error::new(tokio::io::ErrorKind::Other, e));
105 }
106 };
107
108 let connector = match TlsConnector::builder()
110 .add_root_certificate(ca_cert)
111 .build()
112 {
113 Ok(connector) => connector,
114 Err(e) => {
115 error!("cannot create TLS connector: {}", e);
116 return Err(tokio::io::Error::new(tokio::io::ErrorKind::Other, e));
117 }
118 };
119
120 let connector = tokio_native_tls::TlsConnector::from(connector);
121
122 let stream = match TcpStream::connect(url).await {
124 Ok(stream) => stream,
125 Err(e) => {
126 error!("failed to connect to server: {}", e);
127 return Err(tokio::io::Error::new(tokio::io::ErrorKind::Other, e));
128 }
129 };
130
131 self.stream = match connector.connect("localhost", stream).await {
132 Ok(stream) => Some(StreamType::Tls(stream)),
133 Err(e) => {
134 error!("could not establish the tls connection: {}", e);
135 return Err(tokio::io::Error::new(tokio::io::ErrorKind::Other, e));
136 }
137 };
138 Ok(())
139 }
140
141 pub async fn connect(&mut self) -> Result<(), tokio::io::Error> {
143 match self.client_type.clone() {
144 PubSubClient::Tcp(tcp_client) => {
145 let server_url: String = format!("{}:{}", tcp_client.server, tcp_client.port);
146 if let Some(cert) = tcp_client.cert {
147 self.connect_tls(server_url, cert).await?;
148 } else {
149 let stream = TcpStream::connect(server_url).await?;
150 self.stream = Some(StreamType::Tcp(stream));
151 }
152 }
153 PubSubClient::Unix(unix_stream) => {
154 let path = unix_stream.path;
155 let stream = UnixStream::connect(path).await?;
156 self.stream = Some(StreamType::Unix(stream));
157 }
158 }
159 Ok(())
160 }
161
162 pub async fn post(&mut self, msg: message::Msg) -> Result<Vec<u8>, tokio::io::Error> {
165 self.write(msg.bytes()).await?;
166 let mut buf: Vec<u8>;
167 buf = vec![0; 8];
168 match self.read(&mut buf).await {
169 Ok(()) => {
170 trace!("buf: {:?}", buf);
171 match message::Header::from_vec(buf.clone()) {
172 Ok(resp) => {
173 trace!("resp: {:?}", resp);
174 let mut buf_buf = Vec::with_capacity(resp.message_length as usize);
176 trace!("reading remaining bytes");
177 match self.read_buf(&mut buf_buf).await {
178 Ok(()) => {
179 buf.extend(buf_buf);
180 }
181 Err(e) => {
182 return Err(e);
183 }
184 }
185 }
186 Err(e) => {
187 return Err(tokio::io::Error::new(ErrorKind::Other, format!("{:?}", e)));
188 }
189 };
190
191 Ok(buf)
192 }
193 Err(e) => Err(e),
194 }
195 }
196
197 pub async fn publish(
199 &mut self,
200 topic: String,
201 message: Vec<u8>,
202 ) -> Result<(), tokio::io::Error> {
203 let msg: message::Msg = message::Msg::new(message::PktType::PUBLISH, topic, Some(message));
204 trace!("msg: {:?}", msg);
205
206 let buf = match self.post(msg).await {
207 Ok(resp) => resp,
208 Err(e) => return Err(e),
209 };
210
211 trace!("the raw buffer is: {:?}", buf);
212 let resp_: message::Header = match message::Header::from_vec(buf) {
213 Ok(resp) => resp,
214 Err(e) => {
215 return Err(tokio::io::Error::new(ErrorKind::Other, format!("{:?}", e)));
216 }
217 };
218 trace!("{:?}", resp_);
219
220 Ok(())
221 }
222
223 pub async fn query(&mut self, topic: String) -> Result<String, tokio::io::Error> {
225 let msg: message::Msg = message::Msg::new(
226 message::PktType::QUERY,
227 topic,
228 Some(" ".to_string().as_bytes().to_vec()),
229 );
230 trace!("msg: {:?}", msg);
231
232 self.write(msg.bytes()).await?;
233 let msg = self.read_message().await;
234 match msg {
235 Ok(m) => match String::from_utf8(m.message) {
236 Ok(s) => Ok(s),
237 Err(e) => Err(tokio::io::Error::new(ErrorKind::Other, e.to_string())),
238 },
239 Err(e) => Err(e),
240 }
241 }
242
243 pub async fn subscribe(&mut self, topic: String) -> Result<(), tokio::io::Error> {
245 let msg: message::Msg = message::Msg::new(message::PktType::SUBSCRIBE, topic, None);
246 trace!("msg: {:?}", msg);
247 self.write(msg.bytes()).await?;
248 if let Some(callback) = self.callback {
249 loop {
250 match self.read_message().await {
251 Ok(m) => {
252 callback(m.topic, m.message);
253 }
254 Err(e) => {
255 return Err(e);
256 }
257 }
258 }
259 } else {
260 Err(tokio::io::Error::new(
261 tokio::io::ErrorKind::Other,
262 "no callback function is set".to_string(),
263 ))
264 }
265 }
266 pub async fn write(&mut self, message: Vec<u8>) -> Result<(), tokio::io::Error> {
267 if let Some(stream) = &mut self.stream {
268 match stream {
269 StreamType::Tls(tls_stream) => match tls_stream.write_all(&message).await {
270 Ok(size) => {
271 trace!("{:?} bytes written", size);
272 Ok(())
273 }
274 Err(e) => Err(tokio::io::Error::new(
275 tokio::io::ErrorKind::Other,
276 e.to_string(),
277 )),
278 },
279 StreamType::Tcp(ref mut tcp_stream) => match tcp_stream.write_all(&message).await {
280 Ok(size) => {
281 trace!("{:?} bytes written", size);
282 Ok(())
283 }
284 Err(e) => Err(e),
285 },
286
287 StreamType::Unix(ref mut unix_stream) => {
288 match unix_stream.write_all(&message).await {
289 Ok(size) => {
290 trace!("{:?} bytes written", size);
291 Ok(())
292 }
293
294 Err(e) => Err(e),
295 }
296 }
297 }
298 } else {
299 Err(tokio::io::Error::new(
300 tokio::io::ErrorKind::Other,
301 "client not connected yet".to_string(),
302 ))
303 }
304 }
305
306 pub async fn read(&mut self, message: &mut [u8]) -> Result<(), tokio::io::Error> {
307 if let Some(stream) = &mut self.stream {
308 match stream {
309 StreamType::Tls(ref mut tls_stream) => match tls_stream.read(message).await {
310 Ok(_) => Ok(()),
311 Err(e) => Err(e),
312 },
313 StreamType::Tcp(ref mut tcp_stream) => match tcp_stream.read(message).await {
314 Ok(_) => Ok(()),
315 Err(e) => Err(e),
316 },
317 StreamType::Unix(ref mut unix_stream) => match unix_stream.read(message).await {
318 Ok(_) => Ok(()),
319 Err(e) => Err(e),
320 },
321 }
322 } else {
323 Err(tokio::io::Error::new(
324 tokio::io::ErrorKind::Other,
325 "client not connected yet.".to_string(),
326 ))
327 }
328 }
329 pub async fn read_buf(&mut self, message: &mut Vec<u8>) -> Result<(), tokio::io::Error> {
330 if let Some(stream) = &mut self.stream {
331 match stream {
332 StreamType::Tls(ref mut tls_stream) => match tls_stream.read_buf(message).await {
333 Ok(_) => Ok(()),
334 Err(e) => Err(e),
335 },
336 StreamType::Tcp(ref mut tcp_stream) => match tcp_stream.read_buf(message).await {
337 Ok(_) => Ok(()),
338 Err(e) => Err(e),
339 },
340 StreamType::Unix(ref mut unix_stream) => {
341 match unix_stream.read_buf(message).await {
342 Ok(_) => Ok(()),
343 Err(e) => Err(e),
344 }
345 }
346 }
347 } else {
348 Err(tokio::io::Error::new(
349 tokio::io::ErrorKind::Other,
350 "client not connected yet.".to_string(),
351 ))
352 }
353 }
354
355 pub async fn read_message(&mut self) -> Result<message::Msg, tokio::io::Error> {
356 if let Some(stream) = &mut self.stream {
357 match stream {
358 StreamType::Tcp(stream) => match stream::read_message(stream).await {
359 Ok(msg) => Ok(msg),
360 Err(e) => {
361 error!("could not read the message from the tcp stream: {}", e);
362 Err(e)
363 }
364 },
365 StreamType::Tls(stream) => match stream::read_message(stream).await {
366 Ok(msg) => Ok(msg),
367 Err(e) => {
368 error!("could not read the message from the tcp stream: {}", e);
369 Err(e)
370 }
371 },
372 StreamType::Unix(stream) => match stream::read_message(stream).await {
373 Ok(msg) => Ok(msg),
374 Err(e) => {
375 error!("could not read the message from the tcp stream: {}", e);
376 Err(e)
377 }
378 },
379 }
380 } else {
381 Err(tokio::io::Error::new(
382 tokio::io::ErrorKind::Other,
383 "client not connected yet.".to_string(),
384 ))
385 }
386 }
387}