use crate::errors::*;
use crate::protocol::{Request, Response};
use crate::util;
use byteorder::{BigEndian, ByteOrder};
use retry::{delay::Fixed, retry};
use std::io::{self, BufReader, BufWriter, Read};
use std::net::TcpStream;
pub struct ServerConnection {
reader: BufReader<TcpStream>,
writer: BufWriter<TcpStream>,
}
impl ServerConnection {
pub fn new(stream: TcpStream) -> io::Result<ServerConnection> {
let writer = stream.try_clone()?;
Ok(ServerConnection {
reader: BufReader::new(stream),
writer: BufWriter::new(writer),
})
}
pub fn request(&mut self, request: Request) -> Result<Response> {
trace!("ServerConnection::request");
util::write_length_prefixed_bincode(&mut self.writer, request)?;
trace!("ServerConnection::request: sent request");
self.read_one_response()
}
pub fn read_one_response(&mut self) -> Result<Response> {
trace!("ServerConnection::read_one_response");
let mut bytes = [0; 4];
self.reader
.read_exact(&mut bytes)
.context("Failed to read response header")?;
let len = BigEndian::read_u32(&bytes);
trace!("Should read {} more bytes", len);
let mut data = vec![0; len as usize];
self.reader.read_exact(&mut data)?;
trace!("Done reading");
Ok(bincode::deserialize(&data)?)
}
}
pub fn connect_to_server(port: u16) -> io::Result<ServerConnection> {
trace!("connect_to_server({})", port);
let stream = TcpStream::connect(("127.0.0.1", port))?;
ServerConnection::new(stream)
}
pub fn connect_with_retry(port: u16) -> io::Result<ServerConnection> {
trace!("connect_with_retry({})", port);
match retry(Fixed::from_millis(500).take(10), || connect_to_server(port)) {
Ok(conn) => Ok(conn),
_ => Err(io::Error::new(
io::ErrorKind::TimedOut,
"Connection to server timed out",
)),
}
}