Skip to content

Commit

Permalink
Merge pull request #13 from post-cyberlabs/rust1.64
Browse files Browse the repository at this point in the history
migrate to rust 1.64 network primitives
  • Loading branch information
phsym authored Sep 23, 2024
2 parents 51f5106 + 8ff8fbc commit f26137e
Show file tree
Hide file tree
Showing 4 changed files with 381 additions and 222 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]

name = "rust-sctp"
version = "0.0.5"
version = "0.0.6"
description = "High level SCTP networking library"
repository = "https://github.com/phsym/rust-sctp"
documentation = "http://phsym.github.io/rust-sctp"
Expand Down
80 changes: 45 additions & 35 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ use std::net::{ToSocketAddrs, SocketAddr, Shutdown};

#[cfg(target_os="linux")]
use std::os::unix::io::{AsRawFd, RawFd, FromRawFd};

#[cfg(target_os="linux")]
pub mod mio_unix;

#[cfg(target_os="windows")]
use std::os::windows::io::{AsRawHandle, RawHandle, FromRawHandle};

Expand Down Expand Up @@ -60,9 +64,9 @@ impl SctpStream {

/// Create a new stream by connecting it to a remote endpoint
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(), SOCK_STREAM));
try!(sock.connect(raw_addr));
let raw_addr = SocketAddr::from_addr(&address)?;
let sock = SctpSocket::new(raw_addr.family(), SOCK_STREAM)?;
sock.connect(raw_addr)?;
return Ok(SctpStream(sock));
}

Expand All @@ -72,26 +76,32 @@ impl SctpStream {
let mut vec = Vec::with_capacity(addresses.len());
let mut family = AF_INET;
for address in addresses {
let a = try!(SocketAddr::from_addr(address));
let a = SocketAddr::from_addr(address)?;
if a.family() == AF_INET6 { family = AF_INET6; }
vec.push(a);
}

let sock = try!(SctpSocket::new(family, SOCK_STREAM));
try!(sock.connectx(&vec));
let sock = SctpSocket::new(family, SOCK_STREAM)?;
sock.connectx(&vec)?;
return Ok(SctpStream(sock));
}

/// Send bytes on the specified SCTP stream. On success, returns the
/// quantity of bytes read
pub fn sendmsg(&self, msg: &[u8], stream: u16) -> Result<usize> {
return self.0.sendmsg::<SocketAddr>(msg, None, stream, 0);
return self.0.sendmsg::<SocketAddr>(msg, None, 0, stream, 0);
}

/// Send bytes on the specified SCTP stream. On success, returns the
/// quantity of bytes read
pub fn sendmsg_ppid(&self, msg: &[u8], ppid: u32, stream: u16) -> Result<usize> {
return self.0.sendmsg::<SocketAddr>(msg, None, ppid, stream, 0);
}

/// Read bytes. On success, return a tuple with the quantity of
/// bytes received and the stream they were recived on
pub fn recvmsg(&self, msg: &mut [u8]) -> Result<(usize, u16)> {
let (size, stream, _) = try!(self.0.recvmsg(msg));
let (size, stream, _) = self.0.recvmsg(msg)?;
return Ok((size, stream));
}

Expand All @@ -118,7 +128,7 @@ impl SctpStream {

/// Verify if SCTP_NODELAY option is activated for this socket
pub fn has_nodelay(&self) -> Result<bool> {
let val: libc::c_int = try!(self.0.sctp_opt_info(sctp_sys::SCTP_NODELAY, 0));
let val: libc::c_int = self.0.sctp_opt_info(sctp_sys::SCTP_NODELAY, 0)?;
return Ok(val == 1);
}

Expand All @@ -129,8 +139,8 @@ impl SctpStream {
}

/// Get the socket buffer size for the direction specified by `dir`
pub fn get_buffer_size(&self, dir: SoDirection) -> Result<(usize)> {
let val: u32 = try!(self.0.getsockopt(SOL_SOCKET, dir.buffer_opt()));
pub fn get_buffer_size(&self, dir: SoDirection) -> Result<usize> {
let val: u32 = self.0.getsockopt(SOL_SOCKET, dir.buffer_opt())?;
return Ok(val as usize);
}

Expand All @@ -144,7 +154,7 @@ impl SctpStream {
/// Try to clone the SctpStream. On success, returns a new stream
/// wrapping a new socket handler
pub fn try_clone(&self) -> Result<SctpStream> {
return Ok(SctpStream(try!(self.0.try_clone())));
return Ok(SctpStream(self.0.try_clone()?));
}
}

Expand Down Expand Up @@ -200,10 +210,10 @@ impl SctpEndpoint {

/// Create a one-to-many SCTP endpoint bound to a single address
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(), SOCK_SEQPACKET));
try!(sock.bind(raw_addr));
try!(sock.listen(-1));
let raw_addr = SocketAddr::from_addr(&address)?;
let sock = SctpSocket::new(raw_addr.family(), SOCK_SEQPACKET)?;
sock.bind(raw_addr)?;
sock.listen(-1)?;
return Ok(SctpEndpoint(sock));
}

Expand All @@ -213,14 +223,14 @@ impl SctpEndpoint {
let mut vec = Vec::with_capacity(addresses.len());
let mut family = AF_INET;
for address in addresses {
let a = try!(SocketAddr::from_addr(address));
let a = SocketAddr::from_addr(address)?;
if a.family() == AF_INET6 { family = AF_INET6; }
vec.push(a);
}

let sock = try!(SctpSocket::new(family, SOCK_SEQPACKET));
try!(sock.bindx(&vec, BindOp::AddAddr));
try!(sock.listen(-1));
let sock = SctpSocket::new(family, SOCK_SEQPACKET)?;
sock.bindx(&vec, BindOp::AddAddr)?;
sock.listen(-1)?;
return Ok(SctpEndpoint(sock));
}

Expand All @@ -234,7 +244,7 @@ impl SctpEndpoint {
/// Send data in Sctp style, to the provided address on the stream `stream`.
/// On success, returns the quantity on bytes sent
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);
return self.0.sendmsg(msg, Some(address), 0, stream, 0);
}

/// Get local socket addresses to which this socket is bound
Expand All @@ -255,7 +265,7 @@ impl SctpEndpoint {

/// Verify if SCTP_NODELAY option is activated for this socket
pub fn has_nodelay(&self) -> Result<bool> {
let val: libc::c_int = try!(self.0.sctp_opt_info(sctp_sys::SCTP_NODELAY, 0));
let val: libc::c_int = self.0.sctp_opt_info(sctp_sys::SCTP_NODELAY, 0)?;
return Ok(val == 1);
}

Expand All @@ -266,8 +276,8 @@ impl SctpEndpoint {
}

/// Get the socket buffer size for the direction specified by `dir`
pub fn get_buffer_size(&self, dir: SoDirection) -> Result<(usize)> {
let val: u32 = try!(self.0.getsockopt(SOL_SOCKET, dir.buffer_opt()));
pub fn get_buffer_size(&self, dir: SoDirection) -> Result<usize> {
let val: u32 = self.0.getsockopt(SOL_SOCKET, dir.buffer_opt())?;
return Ok(val as usize);
}

Expand All @@ -280,7 +290,7 @@ impl SctpEndpoint {

/// Try to clone this socket
pub fn try_clone(&self) -> Result<SctpEndpoint> {
return Ok(SctpEndpoint(try!(self.0.try_clone())));
return Ok(SctpEndpoint(self.0.try_clone()?));
}
}

Expand Down Expand Up @@ -336,10 +346,10 @@ impl SctpListener {

/// Create a listener bound to a single address
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(), SOCK_STREAM));
try!(sock.bind(raw_addr));
try!(sock.listen(-1));
let raw_addr = SocketAddr::from_addr(&address)?;
let sock = SctpSocket::new(raw_addr.family(), SOCK_STREAM)?;
sock.bind(raw_addr)?;
sock.listen(-1)?;
return Ok(SctpListener(sock));
}

Expand All @@ -349,20 +359,20 @@ impl SctpListener {
let mut vec = Vec::with_capacity(addresses.len());
let mut family = AF_INET;
for address in addresses {
let a = try!(SocketAddr::from_addr(address));
let a = SocketAddr::from_addr(address)?;
if a.family() == AF_INET6 { family = AF_INET6; }
vec.push(a);
}

let sock = try!(SctpSocket::new(family, SOCK_STREAM));
try!(sock.bindx(&vec, BindOp::AddAddr));
try!(sock.listen(-1));
let sock = SctpSocket::new(family, SOCK_STREAM)?;
sock.bindx(&vec, BindOp::AddAddr)?;
sock.listen(-1)?;
return Ok(SctpListener(sock));
}

/// Accept a new connection
pub fn accept(&self) -> Result<(SctpStream, SocketAddr)> {
let (sock, addr) = try!(self.0.accept());
let (sock, addr) = self.0.accept()?;
return Ok((SctpStream(sock), addr));
}

Expand All @@ -385,7 +395,7 @@ impl SctpListener {

/// Try to clone this listener
pub fn try_clone(&self) -> Result<SctpListener> {
return Ok(SctpListener(try!(self.0.try_clone())));
return Ok(SctpListener(self.0.try_clone()?));
}
}

Expand Down
135 changes: 135 additions & 0 deletions src/mio_unix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#[macro_export]
// copy from mio::sys::unix::mod
// https://github.com/faern/mio/blob/master/src/sys/unix/mod.rs
/// Helper macro to execute a system call that returns an `io::Result`.
//
// Macro must be defined before any modules that uses them.
#[allow(unused_macros)]
macro_rules! syscall {
($fn: ident ( $($arg: expr),* $(,)* ) ) => {{
let res = unsafe { libc::$fn($($arg, )*) };
if res == -1 {
Err(std::io::Error::last_os_error())
} else {
Ok(res)
}
}};
}

#[macro_export]
#[allow(unused_macros)]
macro_rules! sctp_syscall {
($fn: ident ( $($arg: expr),* $(,)* ) ) => {{
let res = unsafe { sctp_sys::$fn($($arg, )*) };
if res == -1 {
Err(std::io::Error::last_os_error())
} else {
Ok(res)
}
}};
}

use std::mem;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};

// copy from mio::sys::unix::net
// https://github.com/faern/mio/blob/master/src/sys/unix/net.rs
/// A type with the same memory layout as `libc::sockaddr`. Used in converting Rust level
/// SocketAddr* types into their system representation. The benefit of this specific
/// type over using `libc::sockaddr_storage` is that this type is exactly as large as it
/// needs to be and not a lot larger. And it can be initialized cleaner from Rust.
#[repr(C)]
pub(crate) union SocketAddrCRepr {
v4: libc::sockaddr_in,
v6: libc::sockaddr_in6,
}

impl SocketAddrCRepr {
pub(crate) fn as_ptr(&self) -> *const libc::sockaddr {
self as *const _ as *const libc::sockaddr
}
}

/// Converts a Rust `SocketAddr` into the system representation.
pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, libc::socklen_t) {
match addr {
SocketAddr::V4(ref addr) => {
// `s_addr` is stored as BE on all machine and the array is in BE order.
// So the native endian conversion method is used so that it's never swapped.
let sin_addr = libc::in_addr { s_addr: u32::from_ne_bytes(addr.ip().octets()) };

let sockaddr_in = libc::sockaddr_in {
sin_family: libc::AF_INET as libc::sa_family_t,
sin_port: addr.port().to_be(),
sin_addr,
sin_zero: [0; 8],
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"
))]
sin_len: 0,
};

let sockaddr = SocketAddrCRepr { v4: sockaddr_in };
(sockaddr, mem::size_of::<libc::sockaddr_in>() as libc::socklen_t)
}
SocketAddr::V6(ref addr) => {
let sockaddr_in6 = libc::sockaddr_in6 {
sin6_family: libc::AF_INET6 as libc::sa_family_t,
sin6_port: addr.port().to_be(),
sin6_addr: libc::in6_addr { s6_addr: addr.ip().octets() },
sin6_flowinfo: addr.flowinfo(),
sin6_scope_id: addr.scope_id(),
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"
))]
sin6_len: 0,
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
__sin6_src_id: 0,
};

let sockaddr = SocketAddrCRepr { v6: sockaddr_in6 };
(sockaddr, mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t)
}
}
}

/// Converts a `libc::sockaddr` compatible struct into a native Rust `SocketAddr`.
///
/// # Safety
///
/// `storage` must have the `ss_family` field correctly initialized.
/// `storage` must be initialised to a `sockaddr_in` or `sockaddr_in6`.
pub(crate) unsafe fn to_socket_addr(
storage: *const libc::sockaddr_storage,
) -> std::io::Result<SocketAddr> {
match (*storage).ss_family as libc::c_int {
libc::AF_INET => {
// Safety: if the ss_family field is AF_INET then storage must be a sockaddr_in.
let addr: &libc::sockaddr_in = &*(storage as *const libc::sockaddr_in);
let ip = Ipv4Addr::from(addr.sin_addr.s_addr.to_ne_bytes());
let port = u16::from_be(addr.sin_port);
Ok(SocketAddr::V4(SocketAddrV4::new(ip, port)))
},
libc::AF_INET6 => {
// Safety: if the ss_family field is AF_INET6 then storage must be a sockaddr_in6.
let addr: &libc::sockaddr_in6 = &*(storage as *const libc::sockaddr_in6);
let ip = Ipv6Addr::from(addr.sin6_addr.s6_addr);
let port = u16::from_be(addr.sin6_port);
Ok(SocketAddr::V6(SocketAddrV6::new(ip, port, addr.sin6_flowinfo, addr.sin6_scope_id)))
},
_ => Err(std::io::ErrorKind::InvalidInput.into()),
}
}
//
// CODE COPY ENDS HERE
//
Loading

0 comments on commit f26137e

Please sign in to comment.