use std::fmt;
use std::from_str::FromStr;
use std::io::net::ip::SocketAddr as StdSocketAddr;
use io::{IoHandle, NonBlock};
use error::MioResult;
use buf::{Buf, MutBuf};
use os;
pub use std::io::net::ip::{IpAddr, Port};
pub use std::io::net::ip::Ipv4Addr as IPv4Addr;
pub use std::io::net::ip::Ipv6Addr as IPv6Addr;
pub trait Socket : IoHandle {
fn linger(&self) -> MioResult<uint> {
os::linger(self.desc())
}
fn set_linger(&self, dur_s: uint) -> MioResult<()> {
os::set_linger(self.desc(), dur_s)
}
fn set_reuseaddr(&self, val: bool) -> MioResult<()> {
os::set_reuseaddr(self.desc(), val)
}
fn set_reuseport(&self, val: bool) -> MioResult<()> {
os::set_reuseport(self.desc(), val)
}
}
pub trait MulticastSocket : Socket {
fn join_multicast_group(&self, addr: &IpAddr, interface: &Option<IpAddr>) -> MioResult<()> {
os::join_multicast_group(self.desc(), addr, interface)
}
fn leave_multicast_group(&self, addr: &IpAddr, interface: &Option<IpAddr>) -> MioResult<()> {
os::leave_multicast_group(self.desc(), addr, interface)
}
fn set_multicast_ttl(&self, val: u8) -> MioResult<()> {
os::set_multicast_ttl(self.desc(), val)
}
}
pub trait UnconnectedSocket {
fn send_to(&mut self, buf: &mut Buf, tgt: &SockAddr) -> MioResult<NonBlock<()>>;
fn recv_from(&mut self, buf: &mut MutBuf) -> MioResult<NonBlock<SockAddr>>;
}
pub enum AddressFamily {
Inet,
Inet6,
Unix,
}
pub enum SockAddr {
UnixAddr(Path),
InetAddr(IpAddr, Port)
}
impl SockAddr {
pub fn parse(s: &str) -> Option<SockAddr> {
let addr: Option<StdSocketAddr> = FromStr::from_str(s);
addr.map(|a| InetAddr(a.ip, a.port))
}
pub fn family(&self) -> AddressFamily {
match *self {
UnixAddr(..) => Unix,
InetAddr(IPv4Addr(..), _) => Inet,
InetAddr(IPv6Addr(..), _) => Inet6
}
}
#[inline]
pub fn consume_std(addr: StdSocketAddr) -> SockAddr {
InetAddr(addr.ip, addr.port)
}
#[inline]
pub fn from_std(addr: &StdSocketAddr) -> SockAddr {
InetAddr(addr.ip.clone(), addr.port)
}
pub fn to_std(&self) -> Option<StdSocketAddr> {
match *self {
InetAddr(ref addr, port) => Some(StdSocketAddr {
ip: addr.clone(),
port: port
}),
_ => None
}
}
pub fn into_std(self) -> Option<StdSocketAddr> {
match self {
InetAddr(addr, port) => Some(StdSocketAddr {
ip: addr,
port: port
}),
_ => None
}
}
}
impl FromStr for SockAddr {
fn from_str(s: &str) -> Option<SockAddr> {
SockAddr::parse(s)
}
}
impl fmt::Show for SockAddr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
InetAddr(ip, port) => write!(fmt, "{}:{}", ip, port),
_ => write!(fmt, "not implemented")
}
}
}
pub enum SocketType {
Dgram,
Stream,
}
pub mod tcp {
use os;
use error::MioResult;
use buf::{Buf, MutBuf};
use io;
use io::{IoHandle, IoAcceptor, IoReader, IoWriter, NonBlock, Ready, WouldBlock};
use net::{AddressFamily, Socket, SockAddr, Inet, Inet6, Stream};
#[deriving(Show)]
pub struct TcpSocket {
desc: os::IoDesc
}
impl TcpSocket {
pub fn v4() -> MioResult<TcpSocket> {
TcpSocket::new(Inet)
}
pub fn v6() -> MioResult<TcpSocket> {
TcpSocket::new(Inet6)
}
fn new(family: AddressFamily) -> MioResult<TcpSocket> {
Ok(TcpSocket { desc: try!(os::socket(family, Stream)) })
}
pub fn bind(self, addr: &SockAddr) -> MioResult<TcpListener> {
try!(os::bind(&self.desc, addr))
Ok(TcpListener { desc: self.desc })
}
}
impl IoHandle for TcpSocket {
fn desc(&self) -> &os::IoDesc {
&self.desc
}
}
impl IoReader for TcpSocket {
fn read(&mut self, buf: &mut MutBuf) -> MioResult<NonBlock<()>> {
io::read(self, buf)
}
}
impl IoWriter for TcpSocket {
fn write(&mut self, buf: &mut Buf) -> MioResult<NonBlock<()>> {
io::write(self, buf)
}
}
impl Socket for TcpSocket {
}
#[deriving(Show)]
pub struct TcpListener {
desc: os::IoDesc,
}
impl TcpListener {
pub fn listen(self, backlog: uint) -> MioResult<TcpAcceptor> {
try!(os::listen(self.desc(), backlog));
Ok(TcpAcceptor { desc: self.desc })
}
}
impl IoHandle for TcpListener {
fn desc(&self) -> &os::IoDesc {
&self.desc
}
}
#[deriving(Show)]
pub struct TcpAcceptor {
desc: os::IoDesc,
}
impl TcpAcceptor {
pub fn new(addr: &SockAddr, backlog: uint) -> MioResult<TcpAcceptor> {
let sock = try!(TcpSocket::new(addr.family()));
let listener = try!(sock.bind(addr));
listener.listen(backlog)
}
}
impl IoHandle for TcpAcceptor {
fn desc(&self) -> &os::IoDesc {
&self.desc
}
}
impl Socket for TcpAcceptor {
}
impl IoAcceptor<TcpSocket> for TcpAcceptor {
fn accept(&mut self) -> MioResult<NonBlock<TcpSocket>> {
match os::accept(self.desc()) {
Ok(sock) => Ok(Ready(TcpSocket { desc: sock })),
Err(e) => {
if e.is_would_block() {
return Ok(WouldBlock);
}
return Err(e);
}
}
}
}
}
pub mod udp {
use os;
use error::MioResult;
use buf::{Buf, MutBuf};
use io::{IoHandle, IoReader, IoWriter, NonBlock, Ready, WouldBlock};
use net::{AddressFamily, Socket, MulticastSocket, SockAddr, Inet, Dgram};
use super::UnconnectedSocket;
#[deriving(Show)]
pub struct UdpSocket {
desc: os::IoDesc
}
impl UdpSocket {
pub fn v4() -> MioResult<UdpSocket> {
UdpSocket::new(Inet)
}
fn new(family: AddressFamily) -> MioResult<UdpSocket> {
Ok(UdpSocket { desc: try!(os::socket(family, Dgram)) })
}
pub fn bind(&self, addr: &SockAddr) -> MioResult<()> {
try!(os::bind(&self.desc, addr))
Ok(())
}
pub fn connect(&self, addr: &SockAddr) -> MioResult<bool> {
os::connect(&self.desc, addr)
}
pub fn bound(addr: &SockAddr) -> MioResult<UdpSocket> {
let sock = try!(UdpSocket::new(addr.family()));
try!(sock.bind(addr));
Ok(sock)
}
}
impl IoHandle for UdpSocket {
fn desc(&self) -> &os::IoDesc {
&self.desc
}
}
impl Socket for UdpSocket {
}
impl MulticastSocket for UdpSocket {
}
impl IoReader for UdpSocket {
fn read(&mut self, buf: &mut MutBuf) -> MioResult<NonBlock<()>> {
match os::read(&self.desc, buf.mut_bytes()) {
Ok(cnt) => {
buf.advance(cnt);
Ok(Ready(()))
}
Err(e) => {
if e.is_would_block() {
Ok(WouldBlock)
} else {
Err(e)
}
}
}
}
}
impl IoWriter for UdpSocket {
fn write(&mut self, buf: &mut Buf) -> MioResult<NonBlock<()>> {
match os::write(&self.desc, buf.bytes()) {
Ok(cnt) => {
buf.advance(cnt);
Ok(Ready(()))
}
Err(e) => {
if e.is_would_block() {
Ok(WouldBlock)
} else {
Err(e)
}
}
}
}
}
impl UnconnectedSocket for UdpSocket {
fn send_to(&mut self, buf: &mut Buf, tgt: &SockAddr) -> MioResult<NonBlock<()>> {
match os::sendto(&self.desc, buf.bytes(), tgt) {
Ok(cnt) => {
buf.advance(cnt);
Ok(Ready(()))
}
Err(e) => {
if e.is_would_block() {
Ok(WouldBlock)
} else {
Err(e)
}
}
}
}
fn recv_from(&mut self, buf: &mut MutBuf) -> MioResult<NonBlock<SockAddr>> {
match os::recvfrom(&self.desc, buf.mut_bytes()) {
Ok((cnt, saddr)) => {
buf.advance(cnt);
Ok(Ready(saddr))
}
Err(e) => {
if e.is_would_block() {
Ok(WouldBlock)
} else {
Err(e)
}
}
}
}
}
}
pub mod pipe {
use os;
use io::{IoHandle};
use net::Socket;
#[deriving(Show)]
pub struct UnixSocket {
desc: os::IoDesc
}
impl IoHandle for UnixSocket {
fn desc(&self) -> &os::IoDesc {
&self.desc
}
}
impl Socket for UnixSocket {
}
}