1extern crate libc;
8extern crate sctp_sys;
9extern crate winapi;
10extern crate ws2_32;
11
12mod sctpsock;
13use sctp_sys::{SOCK_SEQPACKET, SOL_SCTP};
14use sctpsock::{BindOp, RawSocketAddr, SctpSocket};
15
16use std::io::prelude::*;
17use std::io::{Error, ErrorKind, Result};
18use std::net::{Shutdown, SocketAddr, ToSocketAddrs};
19
20#[cfg(target_os = "linux")]
21use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
22
23#[cfg(target_os = "linux")]
24pub mod mio_unix;
25
26#[cfg(target_os = "windows")]
27use std::os::windows::io::{AsRawHandle, FromRawHandle, RawHandle};
28
29#[cfg(target_os = "linux")]
30use libc::{
31 AF_INET, AF_INET6, SOCK_STREAM, SOL_SOCKET, SO_RCVBUF, SO_RCVTIMEO, SO_SNDBUF, SO_SNDTIMEO,
32};
33#[cfg(target_os = "windows")]
34use winapi::{
35 AF_INET, AF_INET6, SOCK_STREAM, SOL_SOCKET, SO_RCVBUF, SO_RCVTIMEO, SO_SNDBUF, SO_SNDTIMEO,
36};
37
38pub enum SoDirection {
40 Receive,
42 Send,
44}
45
46impl SoDirection {
47 fn buffer_opt(&self) -> libc::c_int {
48 match *self {
49 SoDirection::Receive => SO_RCVBUF,
50 SoDirection::Send => SO_SNDBUF,
51 }
52 }
53
54 fn timeout_opt(&self) -> libc::c_int {
55 match *self {
56 SoDirection::Receive => SO_RCVTIMEO,
57 SoDirection::Send => SO_SNDTIMEO,
58 }
59 }
60}
61
62pub struct SctpStream(SctpSocket);
66
67impl SctpStream {
68 pub fn connect<A: ToSocketAddrs>(address: A) -> Result<SctpStream> {
70 let raw_addr = SocketAddr::from_addr(&address)?;
71 let sock = SctpSocket::new(raw_addr.family(), SOCK_STREAM)?;
72 sock.connect(raw_addr)?;
73 Ok(SctpStream(sock))
74 }
75
76 pub fn connectx<A: ToSocketAddrs>(addresses: &[A]) -> Result<SctpStream> {
78 if addresses.is_empty() {
79 return Err(Error::new(ErrorKind::InvalidInput, "No addresses given"));
80 }
81 let mut vec = Vec::with_capacity(addresses.len());
82 let mut family = AF_INET;
83 for address in addresses {
84 let a = SocketAddr::from_addr(address)?;
85 if a.family() == AF_INET6 {
86 family = AF_INET6;
87 }
88 vec.push(a);
89 }
90
91 let sock = SctpSocket::new(family, SOCK_STREAM)?;
92 sock.connectx(&vec)?;
93 Ok(SctpStream(sock))
94 }
95
96 pub fn sendmsg(&self, msg: &[u8], stream: u16) -> Result<usize> {
99 self.0.sendmsg::<SocketAddr>(msg, None, 0, stream, 0)
100 }
101
102 pub fn sendmsg_ppid(&self, msg: &[u8], ppid: u32, stream: u16) -> Result<usize> {
105 self.0.sendmsg::<SocketAddr>(msg, None, ppid, stream, 0)
106 }
107
108 pub fn recvmsg(&self, msg: &mut [u8]) -> Result<(usize, u16)> {
111 let (size, stream, _) = self.0.recvmsg(msg)?;
112 Ok((size, stream))
113 }
114
115 pub fn local_addrs(&self) -> Result<Vec<SocketAddr>> {
117 self.0.local_addrs(0)
118 }
119
120 pub fn peer_addrs(&self) -> Result<Vec<SocketAddr>> {
122 self.0.peer_addrs(0)
123 }
124
125 pub fn shutdown(&self, how: Shutdown) -> Result<()> {
127 self.0.shutdown(how)
128 }
129
130 pub fn set_nodelay(&self, nodelay: bool) -> Result<()> {
132 let val: libc::c_int = if nodelay { 1 } else { 0 };
133 self.0.setsockopt(SOL_SCTP, sctp_sys::SCTP_NODELAY, &val)
134 }
135
136 pub fn has_nodelay(&self) -> Result<bool> {
138 let val: libc::c_int = self.0.sctp_opt_info(sctp_sys::SCTP_NODELAY, 0)?;
139 Ok(val == 1)
140 }
141
142 pub fn set_buffer_size(&self, dir: SoDirection, size: usize) -> Result<()> {
145 self.0
146 .setsockopt(SOL_SOCKET, dir.buffer_opt(), &(size as libc::c_int))
147 }
148
149 pub fn get_buffer_size(&self, dir: SoDirection) -> Result<usize> {
151 let val: u32 = self.0.getsockopt(SOL_SOCKET, dir.buffer_opt())?;
152 Ok(val as usize)
153 }
154
155 pub fn set_timeout(&self, dir: SoDirection, timeout: i32) -> Result<()> {
157 let tval = libc::timeval {
159 tv_sec: timeout as libc::c_long,
160 tv_usec: 0,
161 };
162 self.0.setsockopt(SOL_SOCKET, dir.timeout_opt(), &tval)
163 }
164
165 pub fn try_clone(&self) -> Result<SctpStream> {
168 Ok(SctpStream(self.0.try_clone()?))
169 }
170}
171
172impl Read for SctpStream {
173 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
174 self.0.recv(buf)
175 }
176}
177
178impl Write for SctpStream {
179 fn write(&mut self, buf: &[u8]) -> Result<usize> {
180 self.0.send(buf)
181 }
182
183 fn flush(&mut self) -> Result<()> {
184 Ok(())
185 }
186}
187
188#[cfg(target_os = "windows")]
189impl AsRawHandle for SctpStream {
190 fn as_raw_handle(&self) -> RawHandle {
191 return self.0.as_raw_handle();
192 }
193}
194
195#[cfg(target_os = "windows")]
196impl FromRawHandle for SctpStream {
197 unsafe fn from_raw_handle(hdl: RawHandle) -> SctpStream {
198 SctpStream(SctpSocket::from_raw_handle(hdl))
199 }
200}
201
202#[cfg(target_os = "linux")]
203impl AsRawFd for SctpStream {
204 fn as_raw_fd(&self) -> RawFd {
205 self.0.as_raw_fd()
206 }
207}
208
209#[cfg(target_os = "linux")]
210impl FromRawFd for SctpStream {
211 unsafe fn from_raw_fd(fd: RawFd) -> SctpStream {
212 SctpStream(SctpSocket::from_raw_fd(fd))
213 }
214}
215
216pub struct SctpEndpoint(SctpSocket);
218
219impl SctpEndpoint {
220 pub fn bind<A: ToSocketAddrs>(address: A) -> Result<SctpEndpoint> {
222 let raw_addr = SocketAddr::from_addr(&address)?;
223 let sock = SctpSocket::new(raw_addr.family(), SOCK_SEQPACKET)?;
224 sock.bind(raw_addr)?;
225 sock.listen(-1)?;
226 Ok(SctpEndpoint(sock))
227 }
228
229 pub fn bindx<A: ToSocketAddrs>(addresses: &[A]) -> Result<SctpEndpoint> {
231 if addresses.is_empty() {
232 return Err(Error::new(ErrorKind::InvalidInput, "No addresses given"));
233 }
234 let mut vec = Vec::with_capacity(addresses.len());
235 let mut family = AF_INET;
236 for address in addresses {
237 let a = SocketAddr::from_addr(address)?;
238 if a.family() == AF_INET6 {
239 family = AF_INET6;
240 }
241 vec.push(a);
242 }
243
244 let sock = SctpSocket::new(family, SOCK_SEQPACKET)?;
245 sock.bindx(&vec, BindOp::AddAddr)?;
246 sock.listen(-1)?;
247 Ok(SctpEndpoint(sock))
248 }
249
250 pub fn recv_from(&self, msg: &mut [u8]) -> Result<(usize, u16, SocketAddr)> {
254 self.0.recvmsg(msg)
255 }
256
257 pub fn send_to<A: ToSocketAddrs>(
260 &self,
261 msg: &mut [u8],
262 address: A,
263 stream: u16,
264 ) -> Result<usize> {
265 self.0.sendmsg(msg, Some(address), 0, stream, 0)
266 }
267
268 pub fn local_addrs(&self) -> Result<Vec<SocketAddr>> {
270 self.0.local_addrs(0)
271 }
272
273 pub fn shutdown(&self, how: Shutdown) -> Result<()> {
275 self.0.shutdown(how)
276 }
277
278 pub fn set_nodelay(&self, nodelay: bool) -> Result<()> {
280 let val: libc::c_int = if nodelay { 1 } else { 0 };
281 self.0.setsockopt(SOL_SCTP, sctp_sys::SCTP_NODELAY, &val)
282 }
283
284 pub fn has_nodelay(&self) -> Result<bool> {
286 let val: libc::c_int = self.0.sctp_opt_info(sctp_sys::SCTP_NODELAY, 0)?;
287 Ok(val == 1)
288 }
289
290 pub fn set_buffer_size(&self, dir: SoDirection, size: usize) -> Result<()> {
293 self.0
294 .setsockopt(SOL_SOCKET, dir.buffer_opt(), &(size as libc::c_int))
295 }
296
297 pub fn get_buffer_size(&self, dir: SoDirection) -> Result<usize> {
299 let val: u32 = self.0.getsockopt(SOL_SOCKET, dir.buffer_opt())?;
300 Ok(val as usize)
301 }
302
303 pub fn set_timeout(&self, dir: SoDirection, timeout: i32) -> Result<()> {
305 let tval = libc::timeval {
307 tv_sec: timeout as libc::c_long,
308 tv_usec: 0,
309 };
310 self.0.setsockopt(SOL_SOCKET, dir.timeout_opt(), &tval)
311 }
312
313 pub fn try_clone(&self) -> Result<SctpEndpoint> {
315 Ok(SctpEndpoint(self.0.try_clone()?))
316 }
317}
318
319#[cfg(target_os = "windows")]
320impl AsRawHandle for SctpEndpoint {
321 fn as_raw_handle(&self) -> RawHandle {
322 return self.0.as_raw_handle();
323 }
324}
325
326#[cfg(target_os = "windows")]
327impl FromRawHandle for SctpEndpoint {
328 unsafe fn from_raw_handle(hdl: RawHandle) -> SctpEndpoint {
329 SctpEndpoint(SctpSocket::from_raw_handle(hdl))
330 }
331}
332
333#[cfg(target_os = "linux")]
334impl AsRawFd for SctpEndpoint {
335 fn as_raw_fd(&self) -> RawFd {
336 self.0.as_raw_fd()
337 }
338}
339
340#[cfg(target_os = "linux")]
341impl FromRawFd for SctpEndpoint {
342 unsafe fn from_raw_fd(fd: RawFd) -> SctpEndpoint {
343 SctpEndpoint(SctpSocket::from_raw_fd(fd))
344 }
345}
346
347pub struct Incoming<'a>(&'a SctpListener);
349
350impl<'a> std::iter::Iterator for Incoming<'a> {
351 type Item = Result<SctpStream>;
352
353 fn next(&mut self) -> Option<Result<SctpStream>> {
354 match self.0.accept() {
355 Ok((stream, _)) => Some(Ok(stream)),
356 Err(e) => Some(Err(e)),
357 }
358 }
359}
360
361pub struct SctpListener(SctpSocket);
365
366impl SctpListener {
367 pub fn bind<A: ToSocketAddrs>(address: A) -> Result<SctpListener> {
369 let raw_addr = SocketAddr::from_addr(&address)?;
370 let sock = SctpSocket::new(raw_addr.family(), SOCK_STREAM)?;
371 sock.bind(raw_addr)?;
372 sock.listen(-1)?;
373 Ok(SctpListener(sock))
374 }
375
376 pub fn bindx<A: ToSocketAddrs>(addresses: &[A]) -> Result<SctpListener> {
378 if addresses.is_empty() {
379 return Err(Error::new(ErrorKind::InvalidInput, "No addresses given"));
380 }
381 let mut vec = Vec::with_capacity(addresses.len());
382 let mut family = AF_INET;
383 for address in addresses {
384 let a = SocketAddr::from_addr(address)?;
385 if a.family() == AF_INET6 {
386 family = AF_INET6;
387 }
388 vec.push(a);
389 }
390
391 let sock = SctpSocket::new(family, SOCK_STREAM)?;
392 sock.bindx(&vec, BindOp::AddAddr)?;
393 sock.listen(-1)?;
394 Ok(SctpListener(sock))
395 }
396
397 pub fn accept(&self) -> Result<(SctpStream, SocketAddr)> {
399 let (sock, addr) = self.0.accept()?;
400 Ok((SctpStream(sock), addr))
401 }
402
403 pub fn incoming(&self) -> Incoming {
405 Incoming(self)
406 }
407
408 pub fn local_addrs(&self) -> Result<Vec<SocketAddr>> {
410 self.0.local_addrs(0)
411 }
412
413 pub fn set_timeout(&self, timeout: i32) -> Result<()> {
415 let tval = libc::timeval {
417 tv_sec: timeout as libc::c_long,
418 tv_usec: 0,
419 };
420 self.0.setsockopt(SOL_SOCKET, SO_RCVTIMEO, &tval)
421 }
422
423 pub fn try_clone(&self) -> Result<SctpListener> {
425 Ok(SctpListener(self.0.try_clone()?))
426 }
427}
428
429#[cfg(target_os = "windows")]
430impl AsRawHandle for SctpListener {
431 fn as_raw_handle(&self) -> RawHandle {
432 self.0.as_raw_handle()
433 }
434}
435
436#[cfg(target_os = "windows")]
437impl FromRawHandle for SctpListener {
438 unsafe fn from_raw_handle(hdl: RawHandle) -> SctpListener {
439 SctpListener(SctpSocket::from_raw_handle(hdl))
440 }
441}
442
443#[cfg(target_os = "linux")]
444impl AsRawFd for SctpListener {
445 fn as_raw_fd(&self) -> RawFd {
446 self.0.as_raw_fd()
447 }
448}
449
450#[cfg(target_os = "linux")]
451impl FromRawFd for SctpListener {
452 unsafe fn from_raw_fd(fd: RawFd) -> SctpListener {
453 SctpListener(SctpSocket::from_raw_fd(fd))
454 }
455}