use {NonBlock, IntoNonBlock, Io};
use buf::{Buf, MutBuf};
use io::{self, Evented, FromFd, Result};
use net::{self, nix, Socket};
use std::mem;
use std::net::SocketAddr;
use std::os::unix::io::RawFd;
pub use std::net::UdpSocket;
pub fn v4() -> Result<NonBlock<UdpSocket>> {
net::socket(nix::AddressFamily::Inet, nix::SockType::Datagram, true)
.map(|fd| NonBlock::new(FromFd::from_fd(fd)))
}
pub fn v6() -> Result<NonBlock<UdpSocket>> {
net::socket(nix::AddressFamily::Inet6, nix::SockType::Datagram, true)
.map(|fd| NonBlock::new(FromFd::from_fd(fd)))
}
pub fn bind(addr: &SocketAddr) -> io::Result<NonBlock<UdpSocket>> {
let sock = match *addr {
SocketAddr::V4(..) => try!(v4()),
SocketAddr::V6(..) => try!(v6()),
};
try!(sock.bind(addr));
Ok(sock)
}
impl Evented for UdpSocket {
}
impl FromFd for UdpSocket {
fn from_fd(fd: RawFd) -> UdpSocket {
unsafe { mem::transmute(Io::new(fd)) }
}
}
impl Socket for UdpSocket {
}
impl IntoNonBlock for UdpSocket {
fn into_non_block(self) -> Result<NonBlock<UdpSocket>> {
try!(net::set_non_block(as_io(&self)));
Ok(NonBlock::new(self))
}
}
impl NonBlock<UdpSocket> {
pub fn bind(&self, addr: &SocketAddr) -> io::Result<()> {
net::bind(as_io(&*self), &net::to_nix_addr(addr))
}
pub fn send_to<B: Buf>(&self, buf: &mut B, target: &SocketAddr) -> io::Result<Option<()>> {
net::sendto(as_io(&*self), buf.bytes(), &net::to_nix_addr(target))
.map(|cnt| {
buf.advance(cnt);
Some(())
})
.or_else(io::to_non_block)
}
pub fn recv_from<B: MutBuf>(&self, buf: &mut B) -> io::Result<Option<SocketAddr>> {
net::recvfrom(as_io(&*self), buf.mut_bytes())
.map(|(cnt, addr)| {
buf.advance(cnt);
Some(net::to_std_addr(addr))
})
.or_else(io::to_non_block)
}
}
fn as_io<'a, T>(udp: &'a T) -> &'a Io {
unsafe { mem::transmute(udp) }
}