Files
@ 4db4ea6f0eb3
Branch filter:
Location: CSY/reowolf/src/ffi/socket_api.rs
4db4ea6f0eb3
3.7 KiB
application/rls-services+xml
misc ffi refactoring
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 | use super::*;
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 w = if let Some(w) = CONNECTOR_STORAGE.write() { w } else { return 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 w = if let Some(w) = CONNECTOR_STORAGE.write() { w } else { return FD_LOCK_POISONED };
w.fd_allocator.free(fd);
if w.fd_to_connector.remove(&fd).is_some() {
ERR_OK
} else {
CLOSE_FAIL
}
}
#[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 = if let Some(r) = CONNECTOR_STORAGE.read() { r } else { return FD_LOCK_POISONED };
let mc = if let Some(mc) = r.fd_to_connector.get(&fd) { mc } else { return BAD_FD };
let mc: &mut Mc = &mut maybe_conn.borrow_mut();
let _ = if let Mc::New = mc { () } else { return WRONG_STATE };
*mc = Mc::Bound(address.read());
ERR_OK
}
#[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 = if let Some(r) = CONNECTOR_STORAGE.read() { r } else { return FD_LOCK_POISONED };
let mc = if let Some(mc) = r.fd_to_connector.get(&fd) { mc } else { return BAD_FD };
let mc: &mut Mc = &mut maybe_conn.borrow_mut();
let local = if let Mc::Bound(local) = mc { local } else { return WRONG_STATE };
*mc = Mc::Connected(Connector {});
ERR_OK
}
#[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 = if let Some(r) = CONNECTOR_STORAGE.read() { r } else { return FD_LOCK_POISONED };
let mc = if let Some(mc) = r.fd_to_connector.get(&fd) { mc } else { return BAD_FD };
let mc: &mut Mc = &mut maybe_conn.borrow_mut();
let c = if let Mc::Connected(c) = mc { c } else { return WRONG_STATE };
// TODO
ERR_OK
}
|