rumpk/apps/subject_rust/src/lib.rs

106 lines
3.2 KiB
Rust

#![no_std]
#![no_main]
#![feature(alloc_error_handler)]
extern crate alloc;
use alloc::string::String;
use alloc::format;
// ----------------------------------------------------------------------------
// 1. The Nervous System (FFI to Membrane)
// ----------------------------------------------------------------------------
extern "C" {
fn socket(domain: i32, type_: i32, protocol: i32) -> i32;
fn connect(fd: i32, addr: *const u8, len: i32) -> i32;
fn write(fd: i32, buf: *const u8, count: usize) -> isize;
fn sleep(seconds: u32);
// We also need the allocator from libnexus (clib.c or libc.nim exports)
fn malloc(size: usize) -> *mut u8;
fn free(ptr: *mut u8);
}
// ----------------------------------------------------------------------------
// 2. The Stomach (Global Allocator)
// ----------------------------------------------------------------------------
struct NexusAllocator;
unsafe impl core::alloc::GlobalAlloc for NexusAllocator {
unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 {
malloc(layout.size())
}
unsafe fn dealloc(&self, ptr: *mut u8, _layout: core::alloc::Layout) {
free(ptr)
}
}
#[global_allocator]
static ALLOCATOR: NexusAllocator = NexusAllocator;
#[alloc_error_handler]
fn alloc_error(_layout: core::alloc::Layout) -> ! {
panic!("OOM");
}
// ----------------------------------------------------------------------------
// 3. The Voice (Panic Handler)
// ----------------------------------------------------------------------------
#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
let msg = "RUST PANIC!\n";
unsafe { write(1, msg.as_ptr(), msg.len()); }
loop {}
}
// ----------------------------------------------------------------------------
// 4. The Astronaut (Main Logic)
// ----------------------------------------------------------------------------
// We need struct layouts for sockaddr if we want to be precise,
// but for this test, we can use the raw bytes or simple C structs.
#[repr(C)]
struct SockAddrIn {
sin_family: u16,
sin_port: u16,
sin_addr: u32, // 10.0.2.2 = 0x0202000A (Little Endian)
zero: [u8; 8],
}
#[no_mangle]
pub extern "C" fn main() -> i32 {
let msg = String::from("[Rust] Booting sequence...\n");
unsafe { write(1, msg.as_ptr(), msg.len()); }
let fd = unsafe { socket(2, 1, 0) }; // AF_INET, SOCK_STREAM
if fd < 0 {
let err = "[Rust] Socket failed\n";
unsafe { write(1, err.as_ptr(), err.len()); }
return 1;
}
// 10.0.2.2 = 0x0202000A
// 8080 = 0x1F90 (Big Endian)
let port_be: u16 = 8080u16.to_be();
let addr_fixed = SockAddrIn {
sin_family: 2,
sin_port: port_be,
sin_addr: 0x0202000A,
zero: [0; 8],
};
let hello = format!("[Rust] Hello from the Iron Lung! FD={}\n", fd);
unsafe {
let res = connect(fd, &addr_fixed as *const _ as *const u8, 16);
if res < 0 {
let fail = "[Rust] Connection Failed\n";
write(1, fail.as_ptr(), fail.len());
} else {
write(fd, hello.as_ptr(), hello.len());
let success = "[Rust] Payload Sent.\n";
write(1, success.as_ptr(), success.len());
}
}
loop { unsafe { sleep(1); } }
}