268 lines
7.4 KiB
Nim
268 lines
7.4 KiB
Nim
# 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 <ip> <port>")
|
|
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 <ip> <port>, 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()
|