Files
@ 7b9df91324ad
Branch filter:
Location: CSY/reowolf/src/ffi/socket_api.rs
7b9df91324ad
3.8 KiB
application/rls-services+xml
fixed unintentional name collisions in socket-micking API
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 | use super::*;
use atomic_refcell::AtomicRefCell;
use mio::net::UdpSocket;
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 rw_socket(_domain: c_int, _type: c_int) -> c_int {
// assuming _domain is AF_INET and _type is SOCK_DGRAM
let mut w = if let Ok(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 rw_close(fd: ConnectorFd, _how: c_int) -> c_int {
// ignoring HOW
let mut w = if let Ok(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 unsafe extern "C" fn rw_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 Ok(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 mc.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 rw_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 Ok(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 mc.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 rw_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 Ok(r) = CONNECTOR_STORAGE.read() { r } else { return FD_LOCK_POISONED as isize };
let mc = if let Some(mc) = r.fd_to_connector.get(&fd) { mc } else { return BAD_FD as isize };
let mc: &mut Mc = &mut mc.borrow_mut();
let _c = if let Mc::Connected(c) = mc { c } else { return WRONG_STATE as isize };
// TODO
ERR_OK as isize
}
|