Files
@ bdcf814bde8c
Branch filter:
Location: CSY/reowolf/src/ffi/socket_api.rs
bdcf814bde8c
3.9 KiB
application/rls-services+xml
first step toward socket-mimicking FFI
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | use atomic_refcell::AtomicRefCell;
use std::{collections::HashMap, ffi::c_void, net::SocketAddr, os::raw::c_int, sync::RwLock};
///////////////////////////////////////////////////////////////////
type ConnectorFd = c_int;
struct Connector {}
struct FdAllocator {
next: Option<ConnectorFd>,
freed: Vec<ConnectorFd>,
}
enum MaybeConnector {
New,
Bound(SocketAddr),
Connected(Connector),
}
#[derive(Default)]
struct ConnectorStorage {
fd_to_connector: HashMap<ConnectorFd, AtomicRefCell<MaybeConnector>>,
fd_allocator: FdAllocator,
}
///////////////////////////////////////////////////////////////////
impl Default for FdAllocator {
fn default() -> Self {
Self {
next: Some(0), // positive values used only
freed: vec![],
}
}
}
impl FdAllocator {
fn alloc(&mut self) -> ConnectorFd {
if let Some(fd) = self.freed.pop() {
return fd;
}
if let Some(fd) = self.next {
self.next = fd.checked_add(1);
return fd;
}
panic!("No more Connector FDs to allocate!")
}
fn free(&mut self, fd: ConnectorFd) {
self.freed.push(fd);
}
}
lazy_static::lazy_static! {
static ref CONNECTOR_STORAGE: RwLock<ConnectorStorage> = Default::default();
}
///////////////////////////////////////////////////////////////////
#[no_mangle]
pub extern "C" fn socket(_domain: c_int, _type: c_int) -> c_int {
// assuming _domain is AF_INET and _type is SOCK_DGRAM
let mut w = CONNECTOR_STORAGE.write().expect("Fd lock poisoned!");
let fd = w.fd_allocator.alloc();
w.fd_to_connector.insert(fd, AtomicRefCell::new(MaybeConnector::New));
fd
}
#[no_mangle]
pub extern "C" fn close(fd: ConnectorFd, _how: c_int) -> c_int {
// ignoring HOW
let mut w = CONNECTOR_STORAGE.write().expect("Fd lock poisoned!");
w.fd_allocator.free(fd);
if w.fd_to_connector.remove(&fd).is_some() {
0
} else {
-1
}
}
#[no_mangle]
pub extern "C" fn bind(fd: ConnectorFd, address: *const SocketAddr, _address_len: usize) -> c_int {
use MaybeConnector as Mc;
// assuming _domain is AF_INET and _type is SOCK_DGRAM
let r = CONNECTOR_STORAGE.read().expect("Fd lock poisoned!");
if let Some(maybe_conn) = r.fd_to_connector.get(&fd) {
let mc: &mut Mc = &mut maybe_conn.borrow_mut();
match mc {
Mc::New => {
*mc = Mc::Bound(address.read());
0
}
_ => -1, // connector in wrong state
}
} else {
// no connector for this fd
return -2;
}
}
#[no_mangle]
pub extern "C" fn connect(
fd: ConnectorFd,
_address: *const SocketAddr,
_address_len: usize,
) -> c_int {
use MaybeConnector as Mc;
// assuming _domain is AF_INET and _type is SOCK_DGRAM
let r = CONNECTOR_STORAGE.read().expect("Fd lock poisoned!");
if let Some(maybe_conn) = r.fd_to_connector.get(&fd) {
let mc: &mut Mc = &mut maybe_conn.borrow_mut();
match mc {
Mc::Bound(_local) => {
*mc = Mc::Connected(Connector {});
0
}
_ => -1, // connector in wrong state
}
} else {
// no connector for this fd
return -2;
}
}
#[no_mangle]
pub extern "C" fn send(fd: ConnectorFd, msg: *const c_void, len: usize, flags: c_int) -> isize {
use MaybeConnector as Mc;
// assuming _domain is AF_INET and _type is SOCK_DGRAM
let r = CONNECTOR_STORAGE.read().expect("Fd lock poisoned!");
if let Some(maybe_conn) = r.fd_to_connector.get(&fd) {
let mc: &mut Mc = &mut maybe_conn.borrow_mut();
match mc {
Mc::Bound(_local) => {
*mc = Mc::Connected(Connector {});
0
}
_ => -1, // connector in wrong state
}
} else {
// no connector for this fd
return -2;
}
}
|