# src/npl/nipbox/nipbox.nim # Phase 16: Project PROMETHEUS - The Biosuit Activation # The Sovereign Supervisor (Reforged) import strutils import std import editor # --- MEMBRANE INTERFACE --- # These symbols are provided by libnexus.a (The Biosuit) type SockAddrIn {.packed.} = object sin_family: uint16 sin_port: uint16 sin_addr: uint32 sin_zero: array[8, char] const AF_INET = 2 SOCK_STREAM = 1 IPPROTO_TCP = 6 # Membrane Exports proc membrane_init() {.importc, cdecl.} proc pump_membrane_stack() {.importc, cdecl.} # POSIX API (Intercepted) proc socket(domain, socktype, protocol: cint): cint {.importc, cdecl.} proc connect(fd: cint, address: ptr SockAddrIn, len: cint): cint {.importc, cdecl.} proc send(fd: cint, buf: pointer, len: csize_t, flags: cint): cint {.importc, cdecl.} proc recv(fd: cint, buf: pointer, len: csize_t, flags: cint): cint {.importc, cdecl.} proc close(fd: cint): cint {.importc, cdecl.} # Helpers proc htons(x: uint16): uint16 = ((x and 0xFF) shl 8) or ((x and 0xFF00) shr 8) proc inet_addr(ip: string): uint32 = # A.B.C.D -> Little Endian uint32 (LwIP expects Network Order in memory, but let's check subject_zero) # subject_zero used 0x0202000A for 10.0.2.2. # If we parse parts: 10, 0, 2, 2. # (2<<24)|(2<<16)|(0<<8)|10 = 0x0202000A. Correct. let parts = ip.split('.') if parts.len != 4: return 0 var a, b, c, d: int try: a = parseInt(parts[0]) b = parseInt(parts[1]) c = parseInt(parts[2]) d = parseInt(parts[3]) except: return 0 return (uint32(d) shl 24) or (uint32(c) shl 16) or (uint32(b) shl 8) or uint32(a) # --- SYSTEM INTERFACE --- # Syscalls provided by stubs.o or direct asm proc print(s: string) = if s.len > 0: discard write(cint(1), unsafeAddr s[0], csize_t(s.len)) var nl = "\n" discard write(cint(1), unsafeAddr nl[0], 1) proc print_raw(s: string) = if s.len > 0: discard write(cint(1), unsafeAddr s[0], csize_t(s.len)) # --- COMMANDS --- proc do_mkfs() = print("[mkfs] Partitioning Ledger...") # Placeholder for Phase 7 print("[mkfs] Complete.") proc do_cat(filename: string) = let fd = open(cstring(filename), 0) if fd < 0: print("cat: error opening " & filename) return var buf: array[1024, char] while true: let n = read(fd, addr buf[0], 1024) if n <= 0: break discard write(cint(1), addr buf[0], csize_t(n)) discard close(fd) print("") proc do_ls() = # list_files syscall logic placeholder print(".") proc start_editor(filename: string) = editor.start_editor(filename) # --- PROJECT PROMETHEUS: TCP CONNECT --- proc do_connect(args: string) = let parts = args.strip().split(' ') if parts.len < 2: print("Usage: connect ") return let ip = parts[0] var port: int try: port = parseInt(parts[1]) except: print("Error: Invalid port") return print("[TCP] Creating socket...") let fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) if fd < 0: print("[TCP] ERROR: socket() failed") return var sa: SockAddrIn sa.sin_family = uint16(AF_INET) sa.sin_port = htons(uint16(port)) sa.sin_addr = inet_addr(ip) print("[TCP] Connecting to " & ip & ":" & $port & "...") # The Membrane Handshake let res = connect(fd, addr sa, cint(sizeof(SockAddrIn))) if res == 0: print("[TCP] CONNECTED!") let req = "GET / HTTP/1.1\r\nHost: " & ip & "\r\n\r\n" let sent = send(fd, unsafeAddr req[0], csize_t(req.len), 0) print("[TCP] Sent request (" & $sent & " bytes)") var buf: array[512, char] # Pump stack to receive reply for i in 0..500: pump_membrane_stack() let n = recv(fd, addr buf[0], 512, 0) if n > 0: print("[TCP] Received:") var resp = newString(n) copyMem(addr resp[0], addr buf[0], n) print_raw(resp) break # Simple yield loop for j in 0..10000: discard discard close(fd) else: print("[TCP] Connection Failed") discard close(fd) # --- ENGINE --- proc dispatch_command(input: string) proc run_script(filename: string) = if filename.len == 0: return print("[Init] Sourcing " & filename & "...") let fd = open(cstring(filename), 0) if fd < 0: print("[Init] Script not found: " & filename) return var line = "" var buf: array[1, char] while true: let n = read(fd, addr buf[0], 1) if n <= 0: break if buf[0] == '\n': let t = line.strip() if t.len > 0 and not t.startsWith("#"): dispatch_command(t) line = "" elif buf[0] != '\r': line.add(buf[0]) let t = line.strip() if t.len > 0 and not t.startsWith("#"): dispatch_command(t) discard close(fd) proc dispatch_command(input: string) = let trimmed = input.strip() if trimmed.len == 0: return var cmd = "" var arg = "" var space = false for c in trimmed: if not space and c == ' ': space = true elif not space: cmd.add(c) else: arg.add(c) if cmd == "exit": exit(0) elif cmd == "echo": print(arg) elif cmd == "cat": do_cat(arg) elif cmd == "ls": do_ls() elif cmd == "mkfs": do_mkfs() elif cmd == "ed": start_editor(arg) elif cmd == "source": run_script(arg) elif cmd == "connect": do_connect(arg) elif cmd == "help": print("NipBox v0.6 (Membrane Active)") print("connect , echo, cat, ls, ed, source, exit") else: print("Unknown command: " & cmd) proc main() = print("\n╔═══════════════════════════════════════╗") print("║ SOVEREIGN SUPERVISOR v0.6 ║") print("║ PROJECT PROMETHEUS: MEMBRANE ACTIVE ║") print("╚═══════════════════════════════════════╝") # 1. Activate Biosuit membrane_init() print("[Membrane] TCP/IP Stack Initialized (10.0.2.16)") # 2. Init Script (FS Disabled) # run_script("/etc/init.nsh") # 3. PROMETHEUS BOOT TEST print("[Prometheus] Connecting to Host (10.0.2.2:8000)...") do_connect("10.0.2.2 8000") print_raw("\nroot@nexus:# ") var inputBuffer = "" while true: # 3. Heartbeat pump_membrane_stack() # 4. Input (Blocking Read via read(0) which should yield ideally) # Since we don't have non-blocking read in POSIX standard here without fcntl, # and we want to pump stack... # We'll use a busy loop with small reads or assume read(0) is non-blocking in our Stubs? # Our `write` to fd 1 works. `read` from fd 0? var c: char # Try reading 1 char. If stubs.zig implements it as blocking, networking pauses. # In Phase 16, we accept this simplification or use 'nexus_read_nonblock' if we can link it. # Let's try standard read(0) - if it blocks, the network freezes awaiting input. # For a shell, that's acceptable for now (stop-and-wait). # To fix properly, we need a non-blocking read or a thread. let n = read(0, addr c, 1) # This might block! if n > 0: if c == '\n' or c == '\r': print_raw("\n") dispatch_command(inputBuffer) inputBuffer = "" print_raw("root@nexus:# ") elif c == '\b' or c == char(127): if inputBuffer.len > 0: print_raw("\b \b") inputBuffer.setLen(inputBuffer.len - 1) else: inputBuffer.add(c) var s = "" s.add(c) print_raw(s) # Tiny sleep loop to not burn CPU if read returns 0 immediately (non-blocking) if n <= 0: for k in 0..1000: discard when isMainModule: main()