78 lines
1.9 KiB
Nim
78 lines
1.9 KiB
Nim
# core/rumpk/libs/membrane/libc_net.nim
|
|
# Phase 37: The Shim (LwIP Socket Bridge) - Raw API Version
|
|
|
|
import socket
|
|
import strutils
|
|
from ../../libs/membrane/libc import pump_membrane_stack
|
|
|
|
# --- 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
|
|
## Returns file descriptor on success, negative error code on failure
|
|
|
|
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 (Fake FD)
|
|
let fd = new_socket()
|
|
if fd < 0: return -2
|
|
|
|
# 2. Connect
|
|
if connect_flow(fd, target_ip, port) != 0:
|
|
discard close_flow(fd)
|
|
return -3
|
|
|
|
# 3. Wait for connection (Blocking)
|
|
var attempts = 0
|
|
while not is_connected(fd):
|
|
if is_closed_or_error(fd):
|
|
discard close_flow(fd)
|
|
return -4
|
|
|
|
pump_membrane_stack()
|
|
attempts += 1
|
|
if attempts > 500000: # Timeout
|
|
discard close_flow(fd)
|
|
return -5
|
|
|
|
# Small pause
|
|
for i in 0..10_000: discard
|
|
|
|
return fd
|
|
|
|
proc net_send*(fd: int, data: string): int =
|
|
## Send string data over the socket
|
|
if data.len == 0: return 0
|
|
return send_flow(fd, unsafeAddr data[0], data.len)
|
|
|
|
proc net_recv*(fd: int, size: int): string =
|
|
## Receive up to `size` bytes
|
|
if size <= 0: return ""
|
|
var buf = newString(size)
|
|
let bytes = recv_flow(fd, addr buf[0], size)
|
|
if bytes > 0:
|
|
buf.setLen(bytes)
|
|
return buf
|
|
return ""
|
|
|
|
proc net_close*(fd: int) =
|
|
discard close_flow(fd)
|