// Copyright 2019 sctp-sys Developers // // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be // copied, modified, or distributed except according to those terms. //! Quick and (very) dirty example. //! Not many checks are performed 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!"); // sctp_sys::winsock::init(); 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 = connect(sock, transmute(&addr), std::mem::size_of::() as u32); 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) { 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); } }