use protobuf::{
CodedInputStream,
Message,
ProtobufError,
ProtobufResult,
parse_from_bytes,
};
use protocol::{
ClientRequest,
ServerResponse,
};
use retry::retry;
use std::io::{
self,
BufReader,
BufWriter,
Read,
Write,
};
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 = try!(stream.try_clone());
Ok(ServerConnection {
reader : BufReader::new(stream),
writer : BufWriter::new(writer),
})
}
pub fn request(&mut self, request : ClientRequest)
-> ProtobufResult<ServerResponse> {
trace!("ServerConnection::request");
try!(request.write_length_delimited_to_writer(&mut self.writer));
try!(self.writer.flush().or_else(|e| Err(ProtobufError::IoError(e))));
trace!("ServerConnection::request: sent request");
self.read_one_response()
}
pub fn read_one_response(&mut self) -> ProtobufResult<ServerResponse> {
trace!("ServerConnection::read_one_response");
let len = try!({
let mut is = CodedInputStream::from_buffered_reader(&mut self.reader);
is.read_raw_varint32()
});
trace!("Should read {} more bytes", len);
let mut buf = vec![0; len as usize];
try!(self.reader.read_exact(&mut buf).or_else(|e| Err(ProtobufError::IoError(e))));
trace!("Done reading");
parse_from_bytes::<ServerResponse>(&buf)
}
}
pub fn connect_to_server(port: u16) -> io::Result<ServerConnection> {
trace!("connect_to_server({})", port);
let stream = try!(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(10, 500, || connect_to_server(port), |res| res.is_ok()) {
Ok(Ok(conn)) => Ok(conn),
_ => Err(io::Error::new(io::ErrorKind::TimedOut,
"Connection to server timed out")),
}
}