Skip to content

Commit f26137e

Browse files
authored
Merge pull request #13 from post-cyberlabs/rust1.64
migrate to rust 1.64 network primitives
2 parents 51f5106 + 8ff8fbc commit f26137e

File tree

4 files changed

+381
-222
lines changed

4 files changed

+381
-222
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22

33
name = "rust-sctp"
4-
version = "0.0.5"
4+
version = "0.0.6"
55
description = "High level SCTP networking library"
66
repository = "https://github.com/phsym/rust-sctp"
77
documentation = "http://phsym.github.io/rust-sctp"

src/lib.rs

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ use std::net::{ToSocketAddrs, SocketAddr, Shutdown};
1919

2020
#[cfg(target_os="linux")]
2121
use std::os::unix::io::{AsRawFd, RawFd, FromRawFd};
22+
23+
#[cfg(target_os="linux")]
24+
pub mod mio_unix;
25+
2226
#[cfg(target_os="windows")]
2327
use std::os::windows::io::{AsRawHandle, RawHandle, FromRawHandle};
2428

@@ -60,9 +64,9 @@ impl SctpStream {
6064

6165
/// Create a new stream by connecting it to a remote endpoint
6266
pub fn connect<A: ToSocketAddrs>(address: A) -> Result<SctpStream> {
63-
let raw_addr = try!(SocketAddr::from_addr(&address));
64-
let sock = try!(SctpSocket::new(raw_addr.family(), SOCK_STREAM));
65-
try!(sock.connect(raw_addr));
67+
let raw_addr = SocketAddr::from_addr(&address)?;
68+
let sock = SctpSocket::new(raw_addr.family(), SOCK_STREAM)?;
69+
sock.connect(raw_addr)?;
6670
return Ok(SctpStream(sock));
6771
}
6872

@@ -72,26 +76,32 @@ impl SctpStream {
7276
let mut vec = Vec::with_capacity(addresses.len());
7377
let mut family = AF_INET;
7478
for address in addresses {
75-
let a = try!(SocketAddr::from_addr(address));
79+
let a = SocketAddr::from_addr(address)?;
7680
if a.family() == AF_INET6 { family = AF_INET6; }
7781
vec.push(a);
7882
}
7983

80-
let sock = try!(SctpSocket::new(family, SOCK_STREAM));
81-
try!(sock.connectx(&vec));
84+
let sock = SctpSocket::new(family, SOCK_STREAM)?;
85+
sock.connectx(&vec)?;
8286
return Ok(SctpStream(sock));
8387
}
8488

8589
/// Send bytes on the specified SCTP stream. On success, returns the
8690
/// quantity of bytes read
8791
pub fn sendmsg(&self, msg: &[u8], stream: u16) -> Result<usize> {
88-
return self.0.sendmsg::<SocketAddr>(msg, None, stream, 0);
92+
return self.0.sendmsg::<SocketAddr>(msg, None, 0, stream, 0);
93+
}
94+
95+
/// Send bytes on the specified SCTP stream. On success, returns the
96+
/// quantity of bytes read
97+
pub fn sendmsg_ppid(&self, msg: &[u8], ppid: u32, stream: u16) -> Result<usize> {
98+
return self.0.sendmsg::<SocketAddr>(msg, None, ppid, stream, 0);
8999
}
90100

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

@@ -118,7 +128,7 @@ impl SctpStream {
118128

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

@@ -129,8 +139,8 @@ impl SctpStream {
129139
}
130140

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

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

@@ -200,10 +210,10 @@ impl SctpEndpoint {
200210

201211
/// Create a one-to-many SCTP endpoint bound to a single address
202212
pub fn bind<A: ToSocketAddrs>(address: A) -> Result<SctpEndpoint> {
203-
let raw_addr = try!(SocketAddr::from_addr(&address));
204-
let sock = try!(SctpSocket::new(raw_addr.family(), SOCK_SEQPACKET));
205-
try!(sock.bind(raw_addr));
206-
try!(sock.listen(-1));
213+
let raw_addr = SocketAddr::from_addr(&address)?;
214+
let sock = SctpSocket::new(raw_addr.family(), SOCK_SEQPACKET)?;
215+
sock.bind(raw_addr)?;
216+
sock.listen(-1)?;
207217
return Ok(SctpEndpoint(sock));
208218
}
209219

@@ -213,14 +223,14 @@ impl SctpEndpoint {
213223
let mut vec = Vec::with_capacity(addresses.len());
214224
let mut family = AF_INET;
215225
for address in addresses {
216-
let a = try!(SocketAddr::from_addr(address));
226+
let a = SocketAddr::from_addr(address)?;
217227
if a.family() == AF_INET6 { family = AF_INET6; }
218228
vec.push(a);
219229
}
220230

221-
let sock = try!(SctpSocket::new(family, SOCK_SEQPACKET));
222-
try!(sock.bindx(&vec, BindOp::AddAddr));
223-
try!(sock.listen(-1));
231+
let sock = SctpSocket::new(family, SOCK_SEQPACKET)?;
232+
sock.bindx(&vec, BindOp::AddAddr)?;
233+
sock.listen(-1)?;
224234
return Ok(SctpEndpoint(sock));
225235
}
226236

@@ -234,7 +244,7 @@ impl SctpEndpoint {
234244
/// Send data in Sctp style, to the provided address on the stream `stream`.
235245
/// On success, returns the quantity on bytes sent
236246
pub fn send_to<A: ToSocketAddrs>(&self, msg: &mut [u8], address: A, stream: u16) -> Result<usize> {
237-
return self.0.sendmsg(msg, Some(address), stream, 0);
247+
return self.0.sendmsg(msg, Some(address), 0, stream, 0);
238248
}
239249

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

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

@@ -266,8 +276,8 @@ impl SctpEndpoint {
266276
}
267277

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

@@ -280,7 +290,7 @@ impl SctpEndpoint {
280290

281291
/// Try to clone this socket
282292
pub fn try_clone(&self) -> Result<SctpEndpoint> {
283-
return Ok(SctpEndpoint(try!(self.0.try_clone())));
293+
return Ok(SctpEndpoint(self.0.try_clone()?));
284294
}
285295
}
286296

@@ -336,10 +346,10 @@ impl SctpListener {
336346

337347
/// Create a listener bound to a single address
338348
pub fn bind<A: ToSocketAddrs>(address: A) -> Result<SctpListener> {
339-
let raw_addr = try!(SocketAddr::from_addr(&address));
340-
let sock = try!(SctpSocket::new(raw_addr.family(), SOCK_STREAM));
341-
try!(sock.bind(raw_addr));
342-
try!(sock.listen(-1));
349+
let raw_addr = SocketAddr::from_addr(&address)?;
350+
let sock = SctpSocket::new(raw_addr.family(), SOCK_STREAM)?;
351+
sock.bind(raw_addr)?;
352+
sock.listen(-1)?;
343353
return Ok(SctpListener(sock));
344354
}
345355

@@ -349,20 +359,20 @@ impl SctpListener {
349359
let mut vec = Vec::with_capacity(addresses.len());
350360
let mut family = AF_INET;
351361
for address in addresses {
352-
let a = try!(SocketAddr::from_addr(address));
362+
let a = SocketAddr::from_addr(address)?;
353363
if a.family() == AF_INET6 { family = AF_INET6; }
354364
vec.push(a);
355365
}
356366

357-
let sock = try!(SctpSocket::new(family, SOCK_STREAM));
358-
try!(sock.bindx(&vec, BindOp::AddAddr));
359-
try!(sock.listen(-1));
367+
let sock = SctpSocket::new(family, SOCK_STREAM)?;
368+
sock.bindx(&vec, BindOp::AddAddr)?;
369+
sock.listen(-1)?;
360370
return Ok(SctpListener(sock));
361371
}
362372

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

@@ -385,7 +395,7 @@ impl SctpListener {
385395

386396
/// Try to clone this listener
387397
pub fn try_clone(&self) -> Result<SctpListener> {
388-
return Ok(SctpListener(try!(self.0.try_clone())));
398+
return Ok(SctpListener(self.0.try_clone()?));
389399
}
390400
}
391401

src/mio_unix.rs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
#[macro_export]
2+
// copy from mio::sys::unix::mod
3+
// https://github.com/faern/mio/blob/master/src/sys/unix/mod.rs
4+
/// Helper macro to execute a system call that returns an `io::Result`.
5+
//
6+
// Macro must be defined before any modules that uses them.
7+
#[allow(unused_macros)]
8+
macro_rules! syscall {
9+
($fn: ident ( $($arg: expr),* $(,)* ) ) => {{
10+
let res = unsafe { libc::$fn($($arg, )*) };
11+
if res == -1 {
12+
Err(std::io::Error::last_os_error())
13+
} else {
14+
Ok(res)
15+
}
16+
}};
17+
}
18+
19+
#[macro_export]
20+
#[allow(unused_macros)]
21+
macro_rules! sctp_syscall {
22+
($fn: ident ( $($arg: expr),* $(,)* ) ) => {{
23+
let res = unsafe { sctp_sys::$fn($($arg, )*) };
24+
if res == -1 {
25+
Err(std::io::Error::last_os_error())
26+
} else {
27+
Ok(res)
28+
}
29+
}};
30+
}
31+
32+
use std::mem;
33+
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
34+
35+
// copy from mio::sys::unix::net
36+
// https://github.com/faern/mio/blob/master/src/sys/unix/net.rs
37+
/// A type with the same memory layout as `libc::sockaddr`. Used in converting Rust level
38+
/// SocketAddr* types into their system representation. The benefit of this specific
39+
/// type over using `libc::sockaddr_storage` is that this type is exactly as large as it
40+
/// needs to be and not a lot larger. And it can be initialized cleaner from Rust.
41+
#[repr(C)]
42+
pub(crate) union SocketAddrCRepr {
43+
v4: libc::sockaddr_in,
44+
v6: libc::sockaddr_in6,
45+
}
46+
47+
impl SocketAddrCRepr {
48+
pub(crate) fn as_ptr(&self) -> *const libc::sockaddr {
49+
self as *const _ as *const libc::sockaddr
50+
}
51+
}
52+
53+
/// Converts a Rust `SocketAddr` into the system representation.
54+
pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, libc::socklen_t) {
55+
match addr {
56+
SocketAddr::V4(ref addr) => {
57+
// `s_addr` is stored as BE on all machine and the array is in BE order.
58+
// So the native endian conversion method is used so that it's never swapped.
59+
let sin_addr = libc::in_addr { s_addr: u32::from_ne_bytes(addr.ip().octets()) };
60+
61+
let sockaddr_in = libc::sockaddr_in {
62+
sin_family: libc::AF_INET as libc::sa_family_t,
63+
sin_port: addr.port().to_be(),
64+
sin_addr,
65+
sin_zero: [0; 8],
66+
#[cfg(any(
67+
target_os = "dragonfly",
68+
target_os = "freebsd",
69+
target_os = "ios",
70+
target_os = "macos",
71+
target_os = "netbsd",
72+
target_os = "openbsd"
73+
))]
74+
sin_len: 0,
75+
};
76+
77+
let sockaddr = SocketAddrCRepr { v4: sockaddr_in };
78+
(sockaddr, mem::size_of::<libc::sockaddr_in>() as libc::socklen_t)
79+
}
80+
SocketAddr::V6(ref addr) => {
81+
let sockaddr_in6 = libc::sockaddr_in6 {
82+
sin6_family: libc::AF_INET6 as libc::sa_family_t,
83+
sin6_port: addr.port().to_be(),
84+
sin6_addr: libc::in6_addr { s6_addr: addr.ip().octets() },
85+
sin6_flowinfo: addr.flowinfo(),
86+
sin6_scope_id: addr.scope_id(),
87+
#[cfg(any(
88+
target_os = "dragonfly",
89+
target_os = "freebsd",
90+
target_os = "ios",
91+
target_os = "macos",
92+
target_os = "netbsd",
93+
target_os = "openbsd"
94+
))]
95+
sin6_len: 0,
96+
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
97+
__sin6_src_id: 0,
98+
};
99+
100+
let sockaddr = SocketAddrCRepr { v6: sockaddr_in6 };
101+
(sockaddr, mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t)
102+
}
103+
}
104+
}
105+
106+
/// Converts a `libc::sockaddr` compatible struct into a native Rust `SocketAddr`.
107+
///
108+
/// # Safety
109+
///
110+
/// `storage` must have the `ss_family` field correctly initialized.
111+
/// `storage` must be initialised to a `sockaddr_in` or `sockaddr_in6`.
112+
pub(crate) unsafe fn to_socket_addr(
113+
storage: *const libc::sockaddr_storage,
114+
) -> std::io::Result<SocketAddr> {
115+
match (*storage).ss_family as libc::c_int {
116+
libc::AF_INET => {
117+
// Safety: if the ss_family field is AF_INET then storage must be a sockaddr_in.
118+
let addr: &libc::sockaddr_in = &*(storage as *const libc::sockaddr_in);
119+
let ip = Ipv4Addr::from(addr.sin_addr.s_addr.to_ne_bytes());
120+
let port = u16::from_be(addr.sin_port);
121+
Ok(SocketAddr::V4(SocketAddrV4::new(ip, port)))
122+
},
123+
libc::AF_INET6 => {
124+
// Safety: if the ss_family field is AF_INET6 then storage must be a sockaddr_in6.
125+
let addr: &libc::sockaddr_in6 = &*(storage as *const libc::sockaddr_in6);
126+
let ip = Ipv6Addr::from(addr.sin6_addr.s6_addr);
127+
let port = u16::from_be(addr.sin6_port);
128+
Ok(SocketAddr::V6(SocketAddrV6::new(ip, port, addr.sin6_flowinfo, addr.sin6_scope_id)))
129+
},
130+
_ => Err(std::io::ErrorKind::InvalidInput.into()),
131+
}
132+
}
133+
//
134+
// CODE COPY ENDS HERE
135+
//

0 commit comments

Comments
 (0)