rumpk/libs/membrane/libc_net.nim

81 lines
2.2 KiB
Nim

# SPDX-License-Identifier: LSL-1.0
# Copyright (c) 2026 Markus Maiwald
# Stewardship: Self Sovereign Society Foundation
#
# This file is part of the Nexus Sovereign Core.
# See legal/LICENSE_SOVEREIGN.md for license terms.
## Nexus Membrane: POSIX Network Shim
# core/rumpk/libs/membrane/libc_net.nim
# Phase 37: The Shim (LwIP Socket Bridge) - Raw API Version
import libc
import strutils
# --- Helpers ---
proc parse_ipv4(host: string): uint32 =
# Simple parser: "a.b.c.d" -> uint32
try:
var parts = host.split('.')
if parts.len != 4: return 0
let a = parts[0].parseInt.uint32
let b = parts[1].parseInt.uint32
let c = parts[2].parseInt.uint32
let d = parts[3].parseInt.uint32
# Pack into uint32 (A | B<<8 | C<<16 | D<<24) - LwIP Native Order
return (a shl 0) or (b shl 8) or (c shl 16) or (d shl 24)
except:
return 0
# --- Public API ---
proc net_dial_tcp*(host: string, port: uint16): int =
## Connect to a remote host via TCP
let target_ip = parse_ipv4(host)
if target_ip == 0 and host != "0.0.0.0":
return -1 # DNS not implemented yet
# 1. Create Socket (AF_INET=2, SOCK_STREAM=1, TCP=6)
let fd = libc.socket(2, 1, 6)
if fd < 0: return -2
# 2. Setup SockAddr
# struct sockaddr_in { u8 family; u8 len; u16 port; u32 ip; ... }
# Layout expected by Kernel glue:
# Offset 0: Family (ignored?)
# Offset 2: Port
# Offset 4: IP
var addr_buf: array[16, byte]
addr_buf[0] = 2 # AF_INET
# Copy Port (Little Endian?)
copyMem(addr addr_buf[2], unsafeAddr port, 2)
copyMem(addr addr_buf[4], unsafeAddr target_ip, 4)
# 3. Connect (Blocking)
if libc.connect(fd, addr addr_buf[0], 16) != 0:
discard libc.close(fd)
return -3
return fd
proc net_send*(fd: int, data: string): int =
## Send string data over the socket
if data.len == 0: return 0
return libc.send(fd, unsafeAddr data[0], uint64(data.len), 0)
proc net_recv*(fd: int, size: int): string =
## Receive up to `size` bytes
if size <= 0: return ""
var buf = newString(size)
let bytes = libc.recv(fd, addr buf[0], uint64(size), 0)
if bytes > 0:
buf.setLen(bytes)
return buf
return ""
proc net_close*(fd: int) =
discard libc.close(fd)