extern crate sctp_sys;
extern crate libc;
mod sctpsock;
use sctpsock::{SctpSocket, BindOp, RawSocketAddr};
use sctp_sys::{SOCK_SEQPACKET, SOL_SCTP};
use std::io::prelude::*;
use std::io::{Result, Error, ErrorKind};
use std::net::{ToSocketAddrs, SocketAddr, Shutdown};
#[cfg(target_os="linux")]
use std::os::unix::io::{AsRawFd, RawFd, FromRawFd};
#[cfg(target_os="windows")]
use std::os::windows::io::{AsRawHandle, RawHandle, FromRawHandle};
pub enum SoDirection {
Receive,
Send
}
impl SoDirection {
fn buffer_opt(&self) -> libc::c_int {
return match *self {
SoDirection::Receive => libc::SO_RCVBUF,
SoDirection::Send => libc::SO_SNDBUF
};
}
fn timeout_opt(&self) -> libc::c_int {
return match *self {
SoDirection::Receive => libc::SO_RCVTIMEO,
SoDirection::Send => libc::SO_SNDTIMEO
};
}
}
pub struct SctpStream(SctpSocket);
impl SctpStream {
pub fn connect<A: ToSocketAddrs>(address: A) -> Result<SctpStream> {
let raw_addr = try!(SocketAddr::from_addr(&address));
let sock = try!(SctpSocket::new(raw_addr.family(), libc::SOCK_STREAM));
try!(sock.connect(raw_addr));
return Ok(SctpStream(sock));
}
pub fn connectx<A: ToSocketAddrs>(addresses: &[A]) -> Result<SctpStream> {
if addresses.len() == 0 { return Err(Error::new(ErrorKind::InvalidInput, "No addresses given")); }
let mut vec = Vec::with_capacity(addresses.len());
let mut family = libc::AF_INET;
for address in addresses {
let a = try!(SocketAddr::from_addr(address));
if a.family() == libc::AF_INET6 { family = libc::AF_INET6; }
vec.push(a);
}
let sock = try!(SctpSocket::new(family, libc::SOCK_STREAM));
try!(sock.connectx(&vec));
return Ok(SctpStream(sock));
}
pub fn sendmsg(&self, msg: &[u8], stream: u16) -> Result<usize> {
return self.0.sendmsg::<SocketAddr>(msg, None, stream, 0);
}
pub fn recvmsg(&self, msg: &mut [u8]) -> Result<(usize, u16)> {
let (size, stream, _) = try!(self.0.recvmsg(msg));
return Ok((size, stream));
}
pub fn local_addrs(&self) -> Result<Vec<SocketAddr>> {
return self.0.local_addrs(0);
}
pub fn peer_addrs(&self) -> Result<Vec<SocketAddr>> {
return self.0.peer_addrs(0);
}
pub fn shutdown(&self, how: Shutdown) -> Result<()> {
return self.0.shutdown(how);
}
pub fn set_nodelay(&self, nodelay: bool) -> Result<()> {
let val: libc::c_int = if nodelay { 1 } else { 0 };
return self.0.setsockopt(SOL_SCTP, sctp_sys::SCTP_NODELAY, &val);
}
pub fn has_nodelay(&self) -> Result<bool> {
let val: libc::c_int = try!(self.0.sctp_opt_info(sctp_sys::SCTP_NODELAY, 0));
return Ok(val == 1);
}
pub fn set_buffer_size(&self, dir: SoDirection, size: usize) -> Result<()> {
return self.0.setsockopt(libc::SOL_SOCKET, dir.buffer_opt(), &(size as libc::c_int));
}
pub fn get_buffer_size(&self, dir: SoDirection) -> Result<(usize)> {
let val: u32 = try!(self.0.getsockopt(libc::SOL_SOCKET, dir.buffer_opt()));
return Ok(val as usize);
}
pub fn set_timeout(&self, dir: SoDirection, timeout: i32) -> Result<()> {
let tval = libc::timeval { tv_sec: timeout as libc::c_long, tv_usec: 0 };
return self.0.setsockopt(libc::SOL_SOCKET, dir.timeout_opt(), &tval);
}
pub fn try_clone(&self) -> Result<SctpStream> {
return Ok(SctpStream(try!(self.0.try_clone())));
}
}
impl Read for SctpStream {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
return self.0.recv(buf);
}
}
impl Write for SctpStream {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
return self.0.send(buf);
}
fn flush(&mut self) -> Result<()> {
return Ok(());
}
}
#[cfg(target_os="windows")]
impl AsRawHandle for SctpStream {
fn as_raw_handle(&self) -> RawHandle {
return return self.0.as_raw_handle();
}
}
#[cfg(target_os="windows")]
impl FromRawHandle for SctpStream {
unsafe fn from_raw_handle(hdl: RawHandle) -> SctpStream {
return SctpStream(SctpSocket::from_raw_handle(hdl));
}
}
#[cfg(target_os="linux")]
impl AsRawFd for SctpStream {
fn as_raw_fd(&self) -> RawFd {
return self.0.as_raw_fd();
}
}
#[cfg(target_os="linux")]
impl FromRawFd for SctpStream {
unsafe fn from_raw_fd(fd: RawFd) -> SctpStream {
return SctpStream(SctpSocket::from_raw_fd(fd));
}
}
pub struct SctpEndpoint(SctpSocket);
impl SctpEndpoint {
pub fn bind<A: ToSocketAddrs>(address: A) -> Result<SctpEndpoint> {
let raw_addr = try!(SocketAddr::from_addr(&address));
let sock = try!(SctpSocket::new(raw_addr.family(), libc::SOCK_STREAM));
try!(sock.bind(raw_addr));
return Ok(SctpEndpoint(sock));
}
pub fn bindx<A: ToSocketAddrs>(addresses: &[A]) -> Result<SctpEndpoint> {
if addresses.len() == 0 { return Err(Error::new(ErrorKind::InvalidInput, "No addresses given")); }
let mut vec = Vec::with_capacity(addresses.len());
let mut family = libc::AF_INET;
for address in addresses {
let a = try!(SocketAddr::from_addr(address));
if a.family() == libc::AF_INET6 { family = libc::AF_INET6; }
vec.push(a);
}
let sock = try!(SctpSocket::new(family, SOCK_SEQPACKET));
try!(sock.bindx(&vec, BindOp::AddAddr));
try!(sock.listen(-1));
return Ok(SctpEndpoint(sock));
}
pub fn recv_from(&self, msg: &mut [u8]) -> Result<(usize, u16, SocketAddr)> {
return self.0.recvmsg(msg);
}
pub fn send_to<A: ToSocketAddrs>(&self, msg: &mut [u8], address: A, stream: u16) -> Result<usize> {
return self.0.sendmsg(msg, Some(address), stream, 0);
}
pub fn local_addrs(&self) -> Result<Vec<SocketAddr>> {
return self.0.local_addrs(0);
}
pub fn shutdown(&self, how: Shutdown) -> Result<()> {
return self.0.shutdown(how);
}
pub fn set_nodelay(&self, nodelay: bool) -> Result<()> {
let val: libc::c_int = if nodelay { 1 } else { 0 };
return self.0.setsockopt(SOL_SCTP, sctp_sys::SCTP_NODELAY, &val);
}
pub fn has_nodelay(&self) -> Result<bool> {
let val: libc::c_int = try!(self.0.sctp_opt_info(sctp_sys::SCTP_NODELAY, 0));
return Ok(val == 1);
}
pub fn set_buffer_size(&self, dir: SoDirection, size: usize) -> Result<()> {
return self.0.setsockopt(libc::SOL_SOCKET, dir.buffer_opt(), &(size as libc::c_int));
}
pub fn get_buffer_size(&self, dir: SoDirection) -> Result<(usize)> {
let val: u32 = try!(self.0.getsockopt(libc::SOL_SOCKET, dir.buffer_opt()));
return Ok(val as usize);
}
pub fn set_timeout(&self, dir: SoDirection, timeout: i32) -> Result<()> {
let tval = libc::timeval { tv_sec: timeout as libc::c_long, tv_usec: 0 };
return self.0.setsockopt(libc::SOL_SOCKET, dir.timeout_opt(), &tval);
}
pub fn try_clone(&self) -> Result<SctpEndpoint> {
return Ok(SctpEndpoint(try!(self.0.try_clone())));
}
}
#[cfg(target_os="windows")]
impl AsRawHandle for SctpEndpoint {
fn as_raw_handle(&self) -> RawHandle {
return return self.0.as_raw_handle();
}
}
#[cfg(target_os="windows")]
impl FromRawHandle for SctpEndpoint {
unsafe fn from_raw_handle(hdl: RawHandle) -> SctpEndpoint {
return SctpEndpoint(SctpSocket::from_raw_handle(hdl));
}
}
#[cfg(target_os="linux")]
impl AsRawFd for SctpEndpoint {
fn as_raw_fd(&self) -> RawFd {
return self.0.as_raw_fd();
}
}
#[cfg(target_os="linux")]
impl FromRawFd for SctpEndpoint {
unsafe fn from_raw_fd(fd: RawFd) -> SctpEndpoint {
return SctpEndpoint(SctpSocket::from_raw_fd(fd));
}
}
pub struct Incoming<'a>(&'a SctpListener);
impl <'a> std::iter::Iterator for Incoming<'a> {
type Item = Result<SctpStream>;
fn next(&mut self) -> Option<Result<SctpStream>> {
return match self.0.accept() {
Ok((stream, _)) => Some(Ok(stream)),
Err(e) => Some(Err(e))
};
}
}
pub struct SctpListener(SctpSocket);
impl SctpListener {
pub fn bind<A: ToSocketAddrs>(address: A) -> Result<SctpListener> {
let raw_addr = try!(SocketAddr::from_addr(&address));
let sock = try!(SctpSocket::new(raw_addr.family(), libc::SOCK_STREAM));
try!(sock.bind(raw_addr));
return Ok(SctpListener(sock));
}
pub fn bindx<A: ToSocketAddrs>(addresses: &[A]) -> Result<SctpListener> {
if addresses.len() == 0 { return Err(Error::new(ErrorKind::InvalidInput, "No addresses given")); }
let mut vec = Vec::with_capacity(addresses.len());
let mut family = libc::AF_INET;
for address in addresses {
let a = try!(SocketAddr::from_addr(address));
if a.family() == libc::AF_INET6 { family = libc::AF_INET6; }
vec.push(a);
}
let sock = try!(SctpSocket::new(family, libc::SOCK_STREAM));
try!(sock.bindx(&vec, BindOp::AddAddr));
try!(sock.listen(-1));
return Ok(SctpListener(sock));
}
pub fn accept(&self) -> Result<(SctpStream, SocketAddr)> {
let (sock, addr) = try!(self.0.accept());
return Ok((SctpStream(sock), addr));
}
pub fn incoming(&self) -> Incoming {
return Incoming(self);
}
pub fn local_addrs(&self) -> Result<Vec<SocketAddr>> {
return self.0.local_addrs(0);
}
pub fn set_timeout(&self, timeout: i32) -> Result<()> {
let tval = libc::timeval { tv_sec: timeout as libc::c_long, tv_usec: 0 };
return self.0.setsockopt(libc::SOL_SOCKET, libc::SO_RCVTIMEO, &tval);
}
pub fn try_clone(&self) -> Result<SctpListener> {
return Ok(SctpListener(try!(self.0.try_clone())));
}
}
#[cfg(target_os="windows")]
impl AsRawHandle for SctpListener {
fn as_raw_handle(&self) -> RawHandle {
return return self.0.as_raw_handle();
}
}
#[cfg(target_os="windows")]
impl FromRawHandle for SctpListener {
unsafe fn from_raw_handle(hdl: RawHandle) -> SctpListener {
return SctpListener(SctpSocket::from_raw_handle(hdl));
}
}
#[cfg(target_os="linux")]
impl AsRawFd for SctpListener {
fn as_raw_fd(&self) -> RawFd {
return self.0.as_raw_fd();
}
}
#[cfg(target_os="linux")]
impl FromRawFd for SctpListener {
unsafe fn from_raw_fd(fd: RawFd) -> SctpListener {
return SctpListener(SctpSocket::from_raw_fd(fd));
}
}