use addr::ToSingleSocketAddr;
use packet::{
CompleteGafferPacket,
GafferPacket,
GAFFER_MTU,
};
use socket::GafferState;
use std::io;
use std::net::UdpSocket;
pub struct GafferSocket {
udp_socket: UdpSocket,
state: GafferState,
recv_buffer: [u8; GAFFER_MTU],
}
impl GafferSocket {
pub fn bind<A: ToSingleSocketAddr>(addr: A) -> io::Result<Self> {
let first_addr = addr.to_single_socket_addr().unwrap();
UdpSocket::bind(&first_addr).map(|sock| {
GafferSocket {
udp_socket: sock,
state: GafferState::new(),
recv_buffer: [0; GAFFER_MTU]
}
})
}
pub fn recv(&mut self) -> io::Result<GafferPacket> {
self.udp_socket.recv_from(&mut self.recv_buffer)
.and_then(|(len, addr)| CompleteGafferPacket::deserialize(self.recv_buffer[..len].to_vec()).map(|res| (addr, res)) )
.map(|(addr, packet)| self.state.receive(addr, packet))
}
pub fn send(&mut self, p: GafferPacket) -> io::Result<usize> {
let dropped_packets = self.state.dropped_packets(p.addr);
for packet in dropped_packets.into_iter() {
try!(self.single_send(packet));
}
self.single_send(p)
}
fn single_send(&mut self, p: GafferPacket) -> io::Result<usize> {
let (destination, payload) = self.state.preprocess_packet(p);
self.udp_socket.send_to(payload.as_ref(), &destination)
}
}