use std::io::{self, Cursor};
use std::net::ToSocketAddrs;
use std::time::Duration;
use super::errors::Error;
use super::frame::{Frame, ReqBuf};
use bytes::BytesMut;
use may::net::UdpSocket;
#[derive(Debug)]
pub struct UdpClient {
id: u64,
sock: UdpSocket,
buf: Vec<u8>,
}
impl UdpClient {
pub fn connect<L: ToSocketAddrs>(addr: L) -> io::Result<UdpClient> {
let sock = UdpSocket::bind("0.0.0.0:0")?;
sock.connect(addr)?;
sock.set_read_timeout(Some(Duration::from_secs(1))).unwrap();
Ok(UdpClient {
sock,
id: 0,
buf: vec![0; 1024],
})
}
pub fn set_timeout(&mut self, timeout: Duration) {
self.sock.set_read_timeout(Some(timeout)).unwrap();
}
}
impl UdpClient {
pub fn call_service(&mut self, req: ReqBuf) -> Result<Frame, Error> {
let id = self.id;
self.id += 1;
info!("request id = {}", id);
self.sock.send(&(req.finish(id))).map_err(Error::from)?;
let mut buf = BytesMut::with_capacity(1024 * 32);
loop {
self.sock.recv(&mut self.buf).map_err(Error::from)?;
let rsp_frame = Frame::decode_from(&mut Cursor::new(&self.buf), &mut buf)
.map_err(|e| Error::ClientDeserialize(e.to_string()))?;
if rsp_frame.id == id {
info!("get response id = {}", id);
return Ok(rsp_frame);
}
}
}
}