extern crate libc;
extern crate sctp_sys;
extern crate winapi;
use sctp_sys::*;
use std::mem::transmute;
use std::net::Ipv4Addr;
use std::str::{from_utf8, FromStr};
use std::sync::{Arc, Barrier};
use std::thread;
#[cfg(target_os = "linux")]
mod imports {
pub use libc::{
accept, c_int as SOCKET, close, listen, recv, send, sockaddr_in, socket, AF_INET,
SOCK_STREAM,
};
pub type Buflen = usize;
pub fn check_sock(sock: SOCKET) {
assert!(sock >= 0, "Cannot create socket");
}
}
#[cfg(target_os = "windows")]
mod imports {
pub use winapi::shared::ws2def::{AF_INET, SOCKADDR_IN as sockaddr_in, SOCK_STREAM};
pub use winapi::um::winsock2::{
accept, closesocket as close, listen, recv, send, socket, INVALID_SOCKET, SOCKET,
};
pub type Buflen = i32;
pub fn check_sock(sock: SOCKET) {
assert!(sock != INVALID_SOCKET, "Cannot create socket");
}
}
use crate::imports::*;
fn main() {
println!("Hello, world!");
let rdv = Arc::new(Barrier::new(2));
let th = {
let rdv = rdv.clone();
thread::spawn(|| run_server(rdv))
};
unsafe {
let sock = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
check_sock(sock);
let ip = Ipv4Addr::from_str("127.0.0.1").unwrap();
let addr = sockaddr_in {
sin_family: AF_INET as u16,
sin_port: 3868u16.to_be(),
sin_addr: transmute::<[u8; 4], libc::in_addr>(ip.octets()),
sin_zero: [0; 8],
};
let mut assoc: sctp_assoc_t = 0;
rdv.wait();
println!("connecting");
let res = sctp_connectx(
sock,
&addr as *const libc::sockaddr_in as *mut libc::sockaddr,
1,
&mut assoc as *mut sctp_assoc_t,
);
assert!(res == 0, "Cannot connect");
println!("assoc : {}", assoc);
let mut buf = [0u8; 1024];
let rec = recv(
sock,
&mut buf as *mut [u8; 1024] as *mut libc::c_void,
1024,
0,
);
assert!(rec > 0, "No data recived");
print!("rec : {} ", rec);
println!(
"-> {}",
from_utf8(&buf[0..rec as usize]).expect("cannot decode string")
);
close(sock);
}
th.join().unwrap();
}
fn run_server(rdv: Arc<Barrier>) {
unsafe {
println!("Starting server");
let sock = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
check_sock(sock);
let ip = Ipv4Addr::from_str("127.0.0.1").unwrap();
let mut addr = sockaddr_in {
sin_family: AF_INET as u16,
sin_port: 3868u16.to_be(),
sin_addr: transmute::<[u8; 4], libc::in_addr>(ip.octets()),
sin_zero: [0; 8],
};
sctp_bindx(
sock,
&mut addr as *mut libc::sockaddr_in as *mut libc::sockaddr,
1,
consts::SCTP_BINDX_ADD_ADDR,
);
listen(sock, 1);
let mut l = 0;
rdv.wait();
println!("Accepting connection");
let cli = accept(
sock,
&mut addr as *mut libc::sockaddr_in as *mut libc::sockaddr,
&mut l,
);
println!("Connection received");
check_sock(cli);
let buf = "Hello World\n".as_bytes();
send(
cli,
transmute::<*const u8, *const libc::c_void>(buf.as_ptr()),
buf.len() as Buflen,
0,
);
close(cli);
close(sock);
}
}