use std::{io, net};
use std::io::{Read, Write, BufRead, BufReader};
use super::{API_HOST, API_PORT};
pub struct Client<IO> where IO: Read {
io: BufReader<IO>,
read_buf: Vec<u8>,
}
impl Client<net::TcpStream> {
fn socket_connect() -> io::Result<net::TcpStream> {
net::TcpStream::connect((API_HOST, API_PORT))
}
#[inline(always)]
pub fn connect() -> io::Result<Self> {
Ok(Self::new(Self::socket_connect()?))
}
pub fn reconnect(&mut self) -> io::Result<()> {
let _ = self.io.get_mut().shutdown(std::net::Shutdown::Both);
self.io = BufReader::new(Self::socket_connect()?);
self.read_buf.clear();
Ok(())
}
}
#[cfg(feature = "rustls-on")]
impl Client<rustls::StreamOwned<rustls::ClientConnection, net::TcpStream>> {
fn socket_connect_tls() -> io::Result<rustls::StreamOwned<rustls::ClientConnection, net::TcpStream>> {
let socket = std::net::TcpStream::connect((API_HOST, super::API_SSL_PORT))?;
let (dns_name, config) = super::get_rustls_config();
let sess = match rustls::ClientConnection::new(config, dns_name) {
Ok(sess) => sess,
Err(error) => return Err(std::io::Error::new(std::io::ErrorKind::Other, error)),
};
Ok(rustls::StreamOwned::new(sess, socket))
}
#[inline(always)]
pub fn connect_tls() -> io::Result<Self> {
Ok(Self::new(Self::socket_connect_tls()?))
}
pub fn reconnect_tls(&mut self) -> io::Result<()> {
let _ = self.io.get_mut().sock.shutdown(std::net::Shutdown::Both);
self.io = BufReader::new(Self::socket_connect_tls()?);
self.read_buf.clear();
Ok(())
}
}
impl<IO: Read + Write> Client<IO> {
#[inline]
pub fn send(&mut self, req: &crate::protocol::Request) -> io::Result<()> {
self.io.get_mut().write_fmt(format_args!("{}", req))
}
#[inline]
pub fn flush(&mut self) -> io::Result<()> {
self.io.get_mut().flush()
}
}
impl<IO: Read> Client<IO> {
pub fn new(io: IO) -> Self {
Self {
io: BufReader::new(io),
read_buf: Vec::new(),
}
}
pub fn receive(&mut self) -> io::Result<Option<crate::protocol::Response>> {
let size = self.io.read_until(0x04, &mut self.read_buf)?;
if size == 0 {
return Ok(None);
}
let result = super::parse_response(&self.read_buf);
self.read_buf.clear();
result
}
}