#![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); } } }