Skip to content

Commit 108aec5

Browse files
author
pierresy
committed
Initial code import
1 parent 3d42f0b commit 108aec5

File tree

6 files changed

+738
-0
lines changed

6 files changed

+738
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99

1010
# Generated by Cargo
1111
/target/
12+
/Cargo.lock

.project

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<projectDescription>
3+
<name>rust-sctp</name>
4+
<comment></comment>
5+
<projects>
6+
</projects>
7+
<buildSpec>
8+
<buildCommand>
9+
<name>com.github.rustdt.ide.core.Builder</name>
10+
<arguments>
11+
</arguments>
12+
</buildCommand>
13+
</buildSpec>
14+
<natures>
15+
<nature>com.github.rustdt.ide.core.nature</nature>
16+
</natures>
17+
</projectDescription>

Cargo.toml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[package]
2+
3+
name = "rust-sctp"
4+
version = "0.0.1"
5+
description = "High level SCTP networking library"
6+
repository = "https://github.com/phsym/rust-sctp"
7+
readme = "README.md"
8+
authors = [ "Pierre-Henri Symoneaux" ]
9+
keywords = ["transport", "network", "sctp", "libsctp", "socket"]
10+
license = "MIT"
11+
12+
[dependencies]
13+
sctp-sys = "*"
14+
libc = "*"
15+
16+
[lib]
17+
name = "sctp"
18+
19+
[[bin]]
20+
21+
name = "sctp"

src/lib.rs

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
extern crate sctp_sys;
2+
extern crate libc;
3+
4+
mod sctpsock;
5+
use sctpsock::{SctpSocket, BindOp, RawSocketAddr};
6+
use sctp_sys::SOCK_SEQPACKET;
7+
8+
use std::io::prelude::*;
9+
use std::io::{Result, Error, ErrorKind};
10+
use std::net::{ToSocketAddrs, SocketAddr};
11+
12+
#[cfg(target_os="linux")]
13+
use std::os::unix::io::{AsRawFd, RawFd, FromRawFd};
14+
#[cfg(target_os="windows")]
15+
use std::os::windows::io::{AsRawHandle, RawHandle, FromRawHandle};
16+
17+
18+
/// One-to-one SCTP connected stream which behaves like a TCP stream.
19+
/// A `SctpStream` can be obtained either actively by connecting to a SCTP endpoint with the
20+
/// `connect` constructor, or passively from a `SctpListener` which accepts new connections
21+
pub struct SctpStream(SctpSocket);
22+
23+
impl SctpStream {
24+
25+
/// Create a new stream by connecting it to a remote endpoint
26+
pub fn connect<A: ToSocketAddrs>(address: A) -> Result<SctpStream> {
27+
let raw_addr = try!(SocketAddr::from_addr(&address));
28+
let sock = try!(SctpSocket::new(raw_addr.family(), libc::SOCK_STREAM));
29+
try!(sock.connect(raw_addr));
30+
return Ok(SctpStream(sock));
31+
}
32+
33+
/// Send bytes on the specified SCTP stream. On success, returns the
34+
/// quantity of bytes read
35+
pub fn sendmsg(&self, msg: &[u8], stream: u16) -> Result<usize> {
36+
return self.0.sendmsg::<SocketAddr>(msg, None, stream, 0);
37+
}
38+
39+
/// Read bytes. On success, return a tulpe with the quantity of
40+
/// bytes received and the stream they were recived on
41+
pub fn recvmsg(&self, msg: &mut [u8]) -> Result<(usize, u16)> {
42+
let (size, stream, _) = try!(self.0.recvmsg(msg));
43+
return Ok((size, stream));
44+
}
45+
46+
/// Return the list of local socket addresses for this stream
47+
pub fn local_addrs(&self) -> Result<Vec<SocketAddr>> {
48+
return self.0.local_addrs(0);
49+
}
50+
51+
/// Return the list of socket addresses for the peer this stream is connected to
52+
pub fn peer_addrs(&self) -> Result<Vec<SocketAddr>> {
53+
return self.0.peer_addrs(0);
54+
}
55+
56+
/// Try to clone the SctpStream. On success, returns a new stream
57+
/// wrapping a new socket handler
58+
pub fn try_clone(&self) -> Result<SctpStream> {
59+
return Ok(SctpStream(try!(self.0.try_clone())));
60+
}
61+
}
62+
63+
impl Read for SctpStream {
64+
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
65+
return self.0.recv(buf);
66+
}
67+
}
68+
69+
impl Write for SctpStream {
70+
fn write(&mut self, buf: &[u8]) -> Result<usize> {
71+
return self.0.send(buf);
72+
}
73+
74+
fn flush(&mut self) -> Result<()> {
75+
return Ok(());
76+
}
77+
}
78+
79+
#[cfg(target_os="windows")]
80+
impl AsRawHandle for SctpStream {
81+
fn as_raw_handle(&self) -> RawHandle {
82+
return return self.0.as_raw_handle();
83+
}
84+
}
85+
86+
#[cfg(target_os="windows")]
87+
impl FromRawHandle for SctpStream {
88+
unsafe fn from_raw_handle(hdl: RawHandle) -> SctpStream {
89+
return SctpStream(SctpSocket::from_raw_handle(hdl));
90+
}
91+
}
92+
93+
#[cfg(target_os="linux")]
94+
impl AsRawFd for SctpStream {
95+
fn as_raw_fd(&self) -> RawFd {
96+
return self.0.as_raw_fd();
97+
}
98+
}
99+
100+
#[cfg(target_os="linux")]
101+
impl FromRawFd for SctpStream {
102+
unsafe fn from_raw_fd(fd: RawFd) -> SctpStream {
103+
return SctpStream(SctpSocket::from_raw_fd(fd));
104+
}
105+
}
106+
107+
108+
/// One-to-many SCTP stream.
109+
pub struct SctpDatagram(SctpSocket);
110+
111+
impl SctpDatagram {
112+
113+
/// Create a one-to-many SCTP socket bound to a single address
114+
pub fn bind<A: ToSocketAddrs>(address: A) -> Result<SctpDatagram> {
115+
return Self::bindx(&[address]);
116+
}
117+
118+
/// Create a one-to-many SCTP socket bound to a multiple addresses. Requires at least one address
119+
pub fn bindx<A: ToSocketAddrs>(addresses: &[A]) -> Result<SctpDatagram> {
120+
if addresses.len() == 0 { return Err(Error::new(ErrorKind::InvalidInput, "No addresses given")); }
121+
let mut vec = Vec::with_capacity(addresses.len());
122+
let mut family = libc::AF_INET;
123+
for address in addresses {
124+
let a = try!(SocketAddr::from_addr(address));
125+
if a.family() == libc::AF_INET6 { family = libc::AF_INET6; }
126+
vec.push(a);
127+
}
128+
129+
let sock = try!(SctpSocket::new(family, SOCK_SEQPACKET));
130+
try!(sock.bindx(&vec, BindOp::AddAddr));
131+
try!(sock.listen(-1));
132+
return Ok(SctpDatagram(sock));
133+
}
134+
135+
/// Wait for data to be received. On success, returns a triplet containing
136+
/// the quantity of bytes received, the sctp stream id on which data were received, and
137+
/// the socket address used by the peer to send the data
138+
pub fn recv_from(&self, msg: &mut [u8]) -> Result<(usize, u16, SocketAddr)> {
139+
return self.0.recvmsg(msg);
140+
}
141+
142+
/// Send data in Sctp style, to the provided address on the stream `stream`.
143+
/// On success, returns the quantity on bytes sent
144+
pub fn send_to<A: ToSocketAddrs>(&self, msg: &mut [u8], address: A, stream: u16, ) -> Result<usize> {
145+
return self.0.sendmsg(msg, Some(address), stream, 0);
146+
}
147+
148+
/// Get local socket addresses on which this socket is bound
149+
pub fn local_addrs(&self) -> Result<Vec<SocketAddr>> {
150+
return self.0.local_addrs(0);
151+
}
152+
153+
/// Try to clone this socket
154+
pub fn try_clone(&self) -> Result<SctpDatagram> {
155+
return Ok(SctpDatagram(try!(self.0.try_clone())));
156+
}
157+
}
158+
159+
#[cfg(target_os="windows")]
160+
impl AsRawHandle for SctpDatagram {
161+
fn as_raw_handle(&self) -> RawHandle {
162+
return return self.0.as_raw_handle();
163+
}
164+
}
165+
166+
#[cfg(target_os="windows")]
167+
impl FromRawHandle for SctpDatagram {
168+
unsafe fn from_raw_handle(hdl: RawHandle) -> SctpDatagram {
169+
return SctpDatagram(SctpSocket::from_raw_handle(hdl));
170+
}
171+
}
172+
173+
#[cfg(target_os="linux")]
174+
impl AsRawFd for SctpDatagram {
175+
fn as_raw_fd(&self) -> RawFd {
176+
return self.0.as_raw_fd();
177+
}
178+
}
179+
180+
#[cfg(target_os="linux")]
181+
impl FromRawFd for SctpDatagram {
182+
unsafe fn from_raw_fd(fd: RawFd) -> SctpDatagram {
183+
return SctpDatagram(SctpSocket::from_raw_fd(fd));
184+
}
185+
}
186+
187+
/// Iterator over incoming connections on `SctpListener`
188+
pub struct Incoming<'a>(&'a SctpListener);
189+
190+
impl <'a> std::iter::Iterator for Incoming<'a> {
191+
type Item = Result<SctpStream>;
192+
193+
fn next(&mut self) -> Option<Result<SctpStream>> {
194+
return match self.0.accept() {
195+
Ok((stream, _)) => Some(Ok(stream)),
196+
Err(e) => Some(Err(e))
197+
};
198+
}
199+
}
200+
201+
202+
/// SCTP listener which behaves like a `TcpListener`.
203+
/// A SCTP listener is used to wait for and accept one-to-one SCTP connections.
204+
/// An accepted connection is represented by `SctpStream`.
205+
pub struct SctpListener(SctpSocket);
206+
207+
impl SctpListener {
208+
209+
/// Create a listener bound to a single address
210+
pub fn bind<A: ToSocketAddrs>(address: A) -> Result<SctpListener> {
211+
return Self::bindx(&[address]);
212+
}
213+
214+
/// Create a listener bound to multiple addresses. Requires at least one address
215+
pub fn bindx<A: ToSocketAddrs>(addresses: &[A]) -> Result<SctpListener> {
216+
if addresses.len() == 0 { return Err(Error::new(ErrorKind::InvalidInput, "No addresses given")); }
217+
let mut vec = Vec::with_capacity(addresses.len());
218+
let mut family = libc::AF_INET;
219+
for address in addresses {
220+
let a = try!(SocketAddr::from_addr(address));
221+
if a.family() == libc::AF_INET6 { family = libc::AF_INET6; }
222+
vec.push(a);
223+
}
224+
225+
let sock = try!(SctpSocket::new(family, libc::SOCK_STREAM));
226+
try!(sock.bindx(&vec, BindOp::AddAddr));
227+
try!(sock.listen(-1));
228+
return Ok(SctpListener(sock));
229+
}
230+
231+
/// Accept a new connection
232+
pub fn accept(&self) -> Result<(SctpStream, SocketAddr)> {
233+
let (sock, addr) = try!(self.0.accept());
234+
return Ok((SctpStream(sock), addr));
235+
}
236+
237+
/// Iterate over new connections.
238+
pub fn incoming(&self) -> Incoming {
239+
return Incoming(self);
240+
}
241+
242+
/// Get the listener ocal addresses
243+
pub fn local_addrs(&self) -> Result<Vec<SocketAddr>> {
244+
return self.0.local_addrs(0);
245+
}
246+
247+
/// Try to clone this listener
248+
pub fn try_clone(&self) -> Result<SctpListener> {
249+
return Ok(SctpListener(try!(self.0.try_clone())));
250+
}
251+
}
252+
253+
#[cfg(target_os="windows")]
254+
impl AsRawHandle for SctpListener {
255+
fn as_raw_handle(&self) -> RawHandle {
256+
return return self.0.as_raw_handle();
257+
}
258+
}
259+
260+
#[cfg(target_os="windows")]
261+
impl FromRawHandle for SctpListener {
262+
unsafe fn from_raw_handle(hdl: RawHandle) -> SctpListener {
263+
return SctpListener(SctpSocket::from_raw_handle(hdl));
264+
}
265+
}
266+
267+
#[cfg(target_os="linux")]
268+
impl AsRawFd for SctpListener {
269+
fn as_raw_fd(&self) -> RawFd {
270+
return self.0.as_raw_fd();
271+
}
272+
}
273+
274+
#[cfg(target_os="linux")]
275+
impl FromRawFd for SctpListener {
276+
unsafe fn from_raw_fd(fd: RawFd) -> SctpListener {
277+
return SctpListener(SctpSocket::from_raw_fd(fd));
278+
}
279+
}

src/main.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
extern crate sctp;
2+
use sctp::*;
3+
4+
fn main() {
5+
println!("Hello, world!");
6+
7+
// match SctpStream::connect("127.0.0.1:3868") {
8+
// Err(e) => println!("{:?}", e.kind()),
9+
// _ => println!("OK")
10+
// }
11+
12+
// match SctpListener::bind("0.0.0.0:3868") {
13+
// match SctpListener::bindx(&["10.0.2.15:3868", "127.0.0.1:3868"]) {
14+
// Ok(serv) => {
15+
// println!("bound to {:?}", serv.local_addrs().unwrap());
16+
// match serv.accept() {
17+
// Err(e) => println!("{:?}", e.kind()),
18+
// Ok((peer, _)) => {
19+
// let p2 = peer.try_clone().unwrap();
20+
// println!("connection from {:?} on {:?}", p2.peer_addrs().unwrap(), p2.local_addrs().unwrap());
21+
// p2.sendmsg(6, "taatayoyooo\n".as_bytes()).unwrap();
22+
// let mut reply = [0u8; 1024];
23+
// let (len, stream) = p2.recvmsg(&mut reply).unwrap();
24+
// println!("Received {} bytes on {}", len, stream);
25+
// }
26+
// };
27+
// },
28+
// Err(e) => panic!("{:?}", e.kind())
29+
// }
30+
31+
// let sock = match SctpDatagram::bindx(&["10.0.2.15:3868", "127.0.0.1:3868"]) {
32+
let sock = match SctpDatagram::bind("0.0.0.0:3868") {
33+
Ok(s) => s,
34+
Err(e) => panic!("{:?}", e.kind())
35+
};
36+
println!("Bound to {:?}", sock.local_addrs().unwrap());
37+
let mut buf = [0u8; 1024];
38+
match sock.recv_from(&mut buf) {
39+
Ok((len, stream, addr)) => println!("Received {} bytes from {} on stream {}", len, addr, stream),
40+
Err(e) => println!("{:?}", e.kind())
41+
};
42+
}

0 commit comments

Comments
 (0)