Changeset - 4db4ea6f0eb3
[Not reviewed]
0 2 0
Christopher Esterhuyse - 5 years ago 2020-07-10 12:52:18
christopher.esterhuyse@gmail.com
misc ffi refactoring
2 files changed with 56 insertions and 72 deletions:
0 comments (0 inline, 0 general)
src/ffi/mod.rs
Show inline comments
 
use crate::{common::*, runtime::*};
 
use core::{cell::RefCell, convert::TryFrom};
 
use std::os::raw::c_int;
 
use std::slice::from_raw_parts as slice_from_raw_parts;
 

	
 
#[cfg(feature = "ffi_socket_api")]
 
pub mod socket_api;
 
///////////////////////////////////////////////
 
type ErrorCode = std::os::raw::c_int;
 
#[derive(Default)]
 
struct StoredError {
 
    // invariant: len is zero IFF its occupied
 
    // contents are 1+ bytes because we also store the NULL TERMINATOR
 
    buf: Vec<u8>,
 
}
 
@@ -62,25 +62,32 @@ impl StoredError {
 
thread_local! {
 
    static STORED_ERROR: RefCell<StoredError> = RefCell::new(StoredError::default());
 
}
 
unsafe fn tl_socketaddr_from_raw(
 
    bytes_ptr: *const u8,
 
    bytes_len: usize,
 
) -> Result<SocketAddr, ErrorCode> {
 
) -> Result<SocketAddr, c_int> {
 
    std::str::from_utf8(&*slice_from_raw_parts(bytes_ptr, bytes_len))
 
        .map_err(|err| {
 
            StoredError::tl_debug_store(&err);
 
            -1
 
            ERR_REOWOLF
 
        })?
 
        .parse()
 
        .map_err(|err| {
 
            StoredError::tl_debug_store(&err);
 
            -2
 
            ERR_REOWOLF
 
        })
 
}
 

	
 
pub const ERR_OK: c_int = 0;
 
pub const ERR_REOWOLF: c_int = -1;
 
pub const WRONG_STATE: c_int = -2;
 
pub const FD_LOCK_POISONED: c_int = -3;
 
pub const CLOSE_FAIL: c_int = -4;
 
pub const BAD_FD: c_int = -5;
 

	
 
///////////////////// REOWOLF //////////////////////////
 

	
 
/// Returns length (via out pointer) and pointer (via return value) of the last Reowolf error.
 
/// - pointer is NULL iff there was no last error
 
/// - data at pointer is null-delimited
 
/// - len does NOT include the length of the null-delimiter
 
@@ -205,22 +212,22 @@ pub unsafe extern "C" fn connector_add_port_pair(
 
pub unsafe extern "C" fn connector_add_component(
 
    connector: &mut Connector,
 
    ident_ptr: *const u8,
 
    ident_len: usize,
 
    ports_ptr: *const PortId,
 
    ports_len: usize,
 
) -> ErrorCode {
 
) -> c_int {
 
    StoredError::tl_clear();
 
    match connector.add_component(
 
        &*slice_from_raw_parts(ident_ptr, ident_len),
 
        &*slice_from_raw_parts(ports_ptr, ports_len),
 
    ) {
 
        Ok(()) => 0,
 
        Ok(()) => ERR_OK,
 
        Err(err) => {
 
            StoredError::tl_debug_store(&err);
 
            -1
 
            ERR_REOWOLF
 
        }
 
    }
 
}
 

	
 
/// Given
 
/// - an initialized connector in setup or connecting state,
 
@@ -233,28 +240,28 @@ pub unsafe extern "C" fn connector_add_net_port(
 
    connector: &mut Connector,
 
    port: *mut PortId,
 
    addr_str_ptr: *const u8,
 
    addr_str_len: usize,
 
    port_polarity: Polarity,
 
    endpoint_polarity: EndpointPolarity,
 
) -> ErrorCode {
 
) -> c_int {
 
    StoredError::tl_clear();
 
    let addr = match tl_socketaddr_from_raw(addr_str_ptr, addr_str_len) {
 
        Ok(local) => local,
 
        Err(errcode) => return errcode,
 
    };
 
    match connector.new_net_port(port_polarity, addr, endpoint_polarity) {
 
        Ok(p) => {
 
            if !port.is_null() {
 
                port.write(p);
 
            }
 
            0
 
            ERR_OK
 
        }
 
        Err(err) => {
 
            StoredError::tl_debug_store(&err);
 
            -3
 
            ERR_REOWOLF
 
        }
 
    }
 
}
 

	
 
/// Given
 
/// - an initialized connector in setup or connecting state,
 
@@ -269,13 +276,13 @@ pub unsafe extern "C" fn connector_add_udp_port(
 
    putter: *mut PortId,
 
    getter: *mut PortId,
 
    local_addr_str_ptr: *const u8,
 
    local_addr_str_len: usize,
 
    peer_addr_str_ptr: *const u8,
 
    peer_addr_str_len: usize,
 
) -> ErrorCode {
 
) -> c_int {
 
    StoredError::tl_clear();
 
    let local = match tl_socketaddr_from_raw(local_addr_str_ptr, local_addr_str_len) {
 
        Ok(local) => local,
 
        Err(errcode) => return errcode,
 
    };
 
    let peer = match tl_socketaddr_from_raw(peer_addr_str_ptr, peer_addr_str_len) {
 
@@ -287,46 +294,46 @@ pub unsafe extern "C" fn connector_add_udp_port(
 
            if !putter.is_null() {
 
                putter.write(p);
 
            }
 
            if !getter.is_null() {
 
                getter.write(g);
 
            }
 
            0
 
            ERR_OK
 
        }
 
        Err(err) => {
 
            StoredError::tl_debug_store(&err);
 
            -3
 
            ERR_REOWOLF
 
        }
 
    }
 
}
 

	
 
/// Connects this connector to the distributed system of connectors reachable through endpoints,
 
/// Usable in setup state, and changes the state to communication.
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_connect(
 
    connector: &mut Connector,
 
    timeout_millis: i64,
 
) -> ErrorCode {
 
) -> c_int {
 
    StoredError::tl_clear();
 
    let option_timeout_millis: Option<u64> = TryFrom::try_from(timeout_millis).ok();
 
    let timeout = option_timeout_millis.map(Duration::from_millis);
 
    match connector.connect(timeout) {
 
        Ok(()) => 0,
 
        Ok(()) => ERR_OK,
 
        Err(err) => {
 
            StoredError::tl_debug_store(&err);
 
            -1
 
            ERR_REOWOLF
 
        }
 
    }
 
}
 

	
 
// #[no_mangle]
 
// pub unsafe extern "C" fn connector_put_payload(
 
//     connector: &mut Connector,
 
//     port: PortId,
 
//     payload: *mut Payload,
 
// ) -> ErrorCode {
 
// ) -> c_int {
 
//     match connector.put(port, payload.read()) {
 
//         Ok(()) => 0,
 
//         Err(err) => {
 
//             StoredError::tl_debug_store(&err);
 
//             -1
 
//         }
 
@@ -335,13 +342,13 @@ pub unsafe extern "C" fn connector_connect(
 

	
 
// #[no_mangle]
 
// pub unsafe extern "C" fn connector_put_payload_cloning(
 
//     connector: &mut Connector,
 
//     port: PortId,
 
//     payload: &Payload,
 
// ) -> ErrorCode {
 
// ) -> c_int {
 
//     match connector.put(port, payload.clone()) {
 
//         Ok(()) => 0,
 
//         Err(err) => {
 
//             StoredError::tl_debug_store(&err);
 
//             -1
 
//         }
 
@@ -353,42 +360,42 @@ pub unsafe extern "C" fn connector_connect(
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_put_bytes(
 
    connector: &mut Connector,
 
    port: PortId,
 
    bytes_ptr: *const u8,
 
    bytes_len: usize,
 
) -> ErrorCode {
 
) -> c_int {
 
    StoredError::tl_clear();
 
    let bytes = &*slice_from_raw_parts(bytes_ptr, bytes_len);
 
    match connector.put(port, Payload::from(bytes)) {
 
        Ok(()) => 0,
 
        Ok(()) => ERR_OK,
 
        Err(err) => {
 
            StoredError::tl_debug_store(&err);
 
            -1
 
            ERR_REOWOLF
 
        }
 
    }
 
}
 

	
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_get(connector: &mut Connector, port: PortId) -> ErrorCode {
 
pub unsafe extern "C" fn connector_get(connector: &mut Connector, port: PortId) -> c_int {
 
    match connector.get(port) {
 
        Ok(()) => 0,
 
        Ok(()) => ERR_OK,
 
        Err(err) => {
 
            StoredError::tl_debug_store(&err);
 
            -1
 
            ERR_REOWOLF
 
        }
 
    }
 
}
 

	
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_next_batch(connector: &mut Connector) -> isize {
 
    match connector.next_batch() {
 
        Ok(n) => n as isize,
 
        Err(err) => {
 
            StoredError::tl_debug_store(&err);
 
            -1
 
            ERR_REOWOLF as isize
 
        }
 
    }
 
}
 

	
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_sync(connector: &mut Connector, timeout_millis: i64) -> isize {
 
@@ -396,13 +403,13 @@ pub unsafe extern "C" fn connector_sync(connector: &mut Connector, timeout_milli
 
    let option_timeout_millis: Option<u64> = TryFrom::try_from(timeout_millis).ok();
 
    let timeout = option_timeout_millis.map(Duration::from_millis);
 
    match connector.sync(timeout) {
 
        Ok(n) => n as isize,
 
        Err(err) => {
 
            StoredError::tl_debug_store(&err);
 
            -1
 
            ERR_REOWOLF as isize
 
        }
 
    }
 
}
 

	
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_gotten_bytes(
src/ffi/socket_api.rs
Show inline comments
 
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 {}
 
@@ -47,86 +48,62 @@ lazy_static::lazy_static! {
 
}
 
///////////////////////////////////////////////////////////////////
 

	
 
#[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 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 mut w = CONNECTOR_STORAGE.write().expect("Fd lock poisoned!");
 
    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() {
 
        0
 
        ERR_OK
 
    } else {
 
        -1
 
        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 = 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;
 
    }
 
    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 = 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;
 
    }
 
    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 = 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;
 
    }
 
    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
 
}
0 comments (0 inline, 0 general)