Files @ fcf8c30ed335
Branch filter:

Location: CSY/reowolf/src/ffi/pseudo_socket_api.rs - annotation

fcf8c30ed335 7.1 KiB application/rls-services+xml Show Source Show as Raw Download as Raw
mh
WIP on fixing type inferencer
4db4ea6f0eb3
6c04a99de862
c9b0aaff86e5
70e2e44574a6
ca2fee316732
ca2fee316732
ca2fee316732
ca2fee316732
ca2fee316732
ca2fee316732
ca2fee316732
bdcf814bde8c
bdcf814bde8c
bdcf814bde8c
6c04a99de862
6c04a99de862
bdcf814bde8c
7e252436097c
7e252436097c
7e252436097c
7e252436097c
7e252436097c
70e2e44574a6
7e252436097c
7e252436097c
bdcf814bde8c
bdcf814bde8c
14c1a07d148a
db1798f3905e
bdcf814bde8c
bdcf814bde8c
fdc328afed95
3028e66928d3
3028e66928d3
3028e66928d3
3028e66928d3
3028e66928d3
e223cf27bf2e
c8994576abce
fdc328afed95
bdcf814bde8c
bdcf814bde8c
70e2e44574a6
70e2e44574a6
bdcf814bde8c
bdcf814bde8c
bdcf814bde8c
6c04a99de862
bdcf814bde8c
bdcf814bde8c
bdcf814bde8c
bdcf814bde8c
bdcf814bde8c
bdcf814bde8c
bdcf814bde8c
bdcf814bde8c
bdcf814bde8c
6c04a99de862
bdcf814bde8c
bdcf814bde8c
bdcf814bde8c
bdcf814bde8c
e223cf27bf2e
1f3007fd929e
1f3007fd929e
1f3007fd929e
7e252436097c
7e252436097c
526b221270eb
70e2e44574a6
70e2e44574a6
7e252436097c
7e252436097c
1f3007fd929e
1f3007fd929e
1f3007fd929e
1f3007fd929e
bdcf814bde8c
1f3007fd929e
bdcf814bde8c
db1798f3905e
3801521d486d
4bf1367cd8a1
bdcf814bde8c
7e252436097c
7e252436097c
7e252436097c
7e252436097c
7e252436097c
7e252436097c
7e252436097c
7e252436097c
db1798f3905e
bdcf814bde8c
bdcf814bde8c
bdcf814bde8c
6c04a99de862
bdcf814bde8c
3801521d486d
4bf1367cd8a1
14c1a07d148a
1db6ec21a437
4bf1367cd8a1
bdcf814bde8c
4bf1367cd8a1
bdcf814bde8c
bdcf814bde8c
bdcf814bde8c
fdc328afed95
3801521d486d
e223cf27bf2e
fdc328afed95
4bf1367cd8a1
fdc328afed95
3801521d486d
4bf1367cd8a1
4bf1367cd8a1
4bf1367cd8a1
c9b0aaff86e5
4bf1367cd8a1
7e252436097c
1f3007fd929e
1f3007fd929e
4bf1367cd8a1
1f3007fd929e
700221108e9f
bdcf814bde8c
bdcf814bde8c
6c04a99de862
6c04a99de862
fdc328afed95
fdc328afed95
bdcf814bde8c
e223cf27bf2e
fdc328afed95
4bf1367cd8a1
fdc328afed95
bdcf814bde8c
3801521d486d
4bf1367cd8a1
4bf1367cd8a1
4bf1367cd8a1
c9b0aaff86e5
4bf1367cd8a1
c9b0aaff86e5
1f3007fd929e
1f3007fd929e
4bf1367cd8a1
3801521d486d
3801521d486d
bdcf814bde8c
bdcf814bde8c
6c04a99de862
6c04a99de862
6c04a99de862
6c04a99de862
7b9df91324ad
7b9df91324ad
6c04a99de862
3801521d486d
4bf1367cd8a1
4bf1367cd8a1
4bf1367cd8a1
c9b0aaff86e5
c9b0aaff86e5
4bf1367cd8a1
c9b0aaff86e5
1f3007fd929e
c9b0aaff86e5
c9b0aaff86e5
e223cf27bf2e
3801521d486d
3801521d486d
b747c570a11c
b747c570a11c
3801521d486d
b747c570a11c
b747c570a11c
b747c570a11c
b747c570a11c
b747c570a11c
3801521d486d
3801521d486d
4bf1367cd8a1
4bf1367cd8a1
4bf1367cd8a1
c9b0aaff86e5
c9b0aaff86e5
4bf1367cd8a1
c9b0aaff86e5
c9b0aaff86e5
c9b0aaff86e5
c9b0aaff86e5
e223cf27bf2e
e223cf27bf2e
e223cf27bf2e
e223cf27bf2e
e223cf27bf2e
1f3007fd929e
6c04a99de862
526b221270eb
use super::*;

use core::ops::DerefMut;
use libc::{sockaddr, socklen_t};
use std::{
    collections::HashMap,
    ffi::c_void,
    net::SocketAddr,
    os::raw::c_int,
    sync::{Mutex, RwLock},
};
///////////////////////////////////////////////////////////////////

struct FdAllocator {
    next: Option<c_int>,
    freed: Vec<c_int>,
}
enum ConnectorComplexPhased {
    Setup { local: Option<SocketAddr>, peer: Option<SocketAddr> },
    Communication { putter: PortId, getter: PortId },
}
struct ConnectorComplex {
    // invariant: .connector.phased and .phased are variants Setup/Communication in lockstep.
    connector: Connector,
    phased: ConnectorComplexPhased,
}
#[derive(Default)]
struct CcMap {
    fd_to_cc: HashMap<c_int, Mutex<ConnectorComplex>>,
    fd_allocator: FdAllocator,
}
///////////////////////////////////////////////////////////////////
unsafe fn payload_from_raw(bytes_ptr: *const c_void, bytes_len: usize) -> Payload {
    let bytes_ptr = std::mem::transmute(bytes_ptr);
    let bytes = &*slice_from_raw_parts(bytes_ptr, bytes_len);
    Payload::from(bytes)
}
unsafe fn libc_to_std_sockaddr(addr: *const sockaddr, addr_len: socklen_t) -> Option<SocketAddr> {
    os_socketaddr::OsSocketAddr::from_raw_parts(addr as _, addr_len as usize).into_addr()
}
impl Default for FdAllocator {
    fn default() -> Self {
        // negative FDs aren't used s.t. they are available for error signalling
        Self { next: Some(0), freed: vec![] }
    }
}
impl FdAllocator {
    fn alloc(&mut self) -> c_int {
        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: c_int) {
        self.freed.push(fd);
    }
}
lazy_static::lazy_static! {
    static ref CC_MAP: RwLock<CcMap> = Default::default();
}
impl ConnectorComplex {
    fn try_become_connected(&mut self) {
        match self.phased {
            ConnectorComplexPhased::Setup { local: Some(local), peer: Some(peer) } => {
                // complete setup
                let [putter, getter] =
                    self.connector.new_udp_mediator_component(local, peer).unwrap();
                self.connector.connect(None).unwrap();
                self.phased = ConnectorComplexPhased::Communication { putter, getter }
            }
            _ => {} // setup incomplete
        }
    }
}
/////////////////////////////////
#[no_mangle]
pub extern "C" fn rw_socket(_domain: c_int, _type: c_int, _protocol: c_int) -> c_int {
    // get writer lock
    let mut w = if let Ok(w) = CC_MAP.write() { w } else { return RW_LOCK_POISONED };
    let fd = w.fd_allocator.alloc();
    let cc = ConnectorComplex {
        connector: Connector::new(
            Box::new(crate::DummyLogger),
            crate::TRIVIAL_PD.clone(),
            Connector::random_id(),
        ),
        phased: ConnectorComplexPhased::Setup { local: None, peer: None },
    };
    w.fd_to_cc.insert(fd, Mutex::new(cc));
    fd
}
#[no_mangle]
pub extern "C" fn rw_close(fd: c_int, _how: c_int) -> c_int {
    // ignoring HOW
    // get writer lock
    let mut w = if let Ok(w) = CC_MAP.write() { w } else { return RW_LOCK_POISONED };
    if w.fd_to_cc.remove(&fd).is_some() {
        w.fd_allocator.free(fd);
        RW_OK
    } else {
        RW_CLOSE_FAIL
    }
}
#[no_mangle]
pub unsafe extern "C" fn rw_bind(fd: c_int, addr: *const sockaddr, addr_len: socklen_t) -> c_int {
    // assuming _domain is AF_INET and _type is SOCK_DGRAM
    let addr = match libc_to_std_sockaddr(addr, addr_len) {
        Some(addr) => addr,
        _ => return RW_BAD_SOCKADDR,
    };
    // get outer reader, inner writer locks
    let r = if let Ok(r) = CC_MAP.read() { r } else { return RW_LOCK_POISONED };
    let cc = if let Some(cc) = r.fd_to_cc.get(&fd) { cc } else { return RW_BAD_FD };
    let mut cc = if let Ok(cc) = cc.lock() { cc } else { return RW_LOCK_POISONED };
    match &mut cc.phased {
        ConnectorComplexPhased::Communication { .. } => RW_WRONG_STATE,
        ConnectorComplexPhased::Setup { local, .. } => {
            *local = Some(addr);
            cc.try_become_connected();
            RW_OK
        }
    }
}
#[no_mangle]
pub unsafe extern "C" fn rw_connect(
    fd: c_int,
    addr: *const sockaddr,
    addr_len: socklen_t,
) -> c_int {
    let addr = match libc_to_std_sockaddr(addr, addr_len) {
        Some(addr) => addr,
        _ => return RW_BAD_SOCKADDR,
    };
    // assuming _domain is AF_INET and _type is SOCK_DGRAM
    // get outer reader, inner writer locks
    let r = if let Ok(r) = CC_MAP.read() { r } else { return RW_LOCK_POISONED };
    let cc = if let Some(cc) = r.fd_to_cc.get(&fd) { cc } else { return RW_BAD_FD };
    let mut cc = if let Ok(cc) = cc.lock() { cc } else { return RW_LOCK_POISONED };
    match &mut cc.phased {
        ConnectorComplexPhased::Communication { .. } => RW_WRONG_STATE,
        ConnectorComplexPhased::Setup { peer, .. } => {
            *peer = Some(addr);
            cc.try_become_connected();
            RW_OK
        }
    }
}
#[no_mangle]
pub unsafe extern "C" fn rw_send(
    fd: c_int,
    bytes_ptr: *const c_void,
    bytes_len: usize,
    _flags: c_int,
) -> isize {
    // ignoring flags
    // get outer reader, inner writer locks
    let r = if let Ok(r) = CC_MAP.read() { r } else { return RW_LOCK_POISONED as isize };
    let cc = if let Some(cc) = r.fd_to_cc.get(&fd) { cc } else { return RW_BAD_FD as isize };
    let mut cc = if let Ok(cc) = cc.lock() { cc } else { return RW_LOCK_POISONED as isize };
    let ConnectorComplex { connector, phased } = cc.deref_mut();
    match phased {
        ConnectorComplexPhased::Setup { .. } => RW_WRONG_STATE as isize,
        ConnectorComplexPhased::Communication { putter, .. } => {
            let payload = payload_from_raw(bytes_ptr, bytes_len);
            connector.put(*putter, payload).unwrap();
            connector.sync(None).unwrap();
            bytes_len as isize
        }
    }
}
#[no_mangle]
pub unsafe extern "C" fn rw_recv(
    fd: c_int,
    bytes_ptr: *mut c_void,
    bytes_len: usize,
    _flags: c_int,
) -> isize {
    // ignoring flags
    // get outer reader, inner writer locks
    let r = if let Ok(r) = CC_MAP.read() { r } else { return RW_LOCK_POISONED as isize };
    let cc = if let Some(cc) = r.fd_to_cc.get(&fd) { cc } else { return RW_BAD_FD as isize };
    let mut cc = if let Ok(cc) = cc.lock() { cc } else { return RW_LOCK_POISONED as isize };
    let ConnectorComplex { connector, phased } = cc.deref_mut();
    match phased {
        ConnectorComplexPhased::Setup { .. } => RW_WRONG_STATE as isize,
        ConnectorComplexPhased::Communication { getter, .. } => {
            connector.get(*getter).unwrap();
            connector.sync(None).unwrap();
            let slice = connector.gotten(*getter).unwrap().as_slice();
            if !bytes_ptr.is_null() {
                let cpy_msg_bytes = slice.len().min(bytes_len);
                std::ptr::copy_nonoverlapping(slice.as_ptr(), bytes_ptr as *mut u8, cpy_msg_bytes);
            }
            slice.len() as isize
        }
    }
}