code wiki / (root) / nx_net_chan_blob_test.nx

nx_net_chan_blob_test.nx source

↩ module page · 152 lines · 5484 B

1// nx_net_chan_blob_test.nx -- variable-length frames over TCP. 2// 3// Round-trips three blobs of varying length (8B, 64B, 1024B) over 4// loopback and verifies bytes intact end-to-end. Builds on 5// [[nx_net_chan_tcp_i64]] with length-prefix framing. 6 7import "nx_kernel_v2.nx" 8import "nx_log.nx" 9import "nx_atom.nx" 10import "nx_thread.nx" 11import "nx_socket.nx" 12import "nx_net_chan.nx" 13 14const NX_PORT: i64 = 38923 15 16struct BlobState { 17 done_flag: i64, 18 diag: i64, 19} 20 21func _sleep_ms(ms: i64) -> i64 { 22 let ts_raw: *u8 = sys_mmap(16) 23 let ts: *i64 = ts_raw as *i64 24 ts[0] = ms / 1000 25 ts[1] = (ms % 1000) * 1000000 26 return __syscall(SYS_CLOCK_NANOSLEEP, 1, 0, ts as i64, 0, 0, 0) 27} 28 29func _fill(buf: *u8, n: i64, seed: i64) -> i64 { 30 var i: i64 = 0 31 while i < n { 32 buf[i] = ((seed + i) & 0xFF) as u8 33 i = i + 1 34 } 35 return 0 36} 37 38func _check(buf: *u8, n: i64, seed: i64) -> i64 { 39 var i: i64 = 0 40 while i < n { 41 let expected: i64 = (seed + i) & 0xFF 42 if buf[i] != expected { return i + 1 } 43 i = i + 1 44 } 45 return 0 46} 47 48// Client: send 3 blobs (8B seed 10, 64B seed 20, 1024B seed 30) + 49// recv 3 echo blobs that should match. 50func client_main(arg: *u8) -> i64 { 51 let s: *BlobState = arg as *BlobState 52 let done_addr: *i64 = (arg as *i64) 53 54 _sleep_ms(150) 55 let fd: i64 = nx_sock_socket(NX_AF_INET, NX_SOCK_STREAM, NX_IPPROTO_TCP) 56 if fd < 0 { s.diag = 10; nx_atom_store_i64(done_addr, -1, NX_MO_SEQ_CST); return 0 } 57 let addr: *u8 = sys_mmap(16) 58 nx_sock_sin_init(addr, 0x0100007F, NX_PORT) 59 if nx_sock_connect(fd, addr, 16) < 0 { 60 s.diag = 20; nx_atom_store_i64(done_addr, -1, NX_MO_SEQ_CST); return 0 61 } 62 let nc: *NxNetChan = nx_net_chan_from_fd(fd) 63 64 // Send 8-byte blob. 65 let b8: *u8 = sys_mmap(16); _fill(b8, 8, 10) 66 if nx_net_chan_send_blob(nc, b8, 8) != 0 { 67 s.diag = 30; nx_atom_store_i64(done_addr, -1, NX_MO_SEQ_CST); return 0 68 } 69 // Send 64-byte blob. 70 let b64: *u8 = sys_mmap(128); _fill(b64, 64, 20) 71 if nx_net_chan_send_blob(nc, b64, 64) != 0 { 72 s.diag = 31; nx_atom_store_i64(done_addr, -1, NX_MO_SEQ_CST); return 0 73 } 74 // Send 1024-byte blob. 75 let b1k: *u8 = sys_mmap(2048); _fill(b1k, 1024, 30) 76 if nx_net_chan_send_blob(nc, b1k, 1024) != 0 { 77 s.diag = 32; nx_atom_store_i64(done_addr, -1, NX_MO_SEQ_CST); return 0 78 } 79 80 // Recv 3 echoed blobs + verify each. 81 let r1: *u8 = sys_mmap(4096) 82 let n1: i64 = nx_net_chan_recv_blob(nc, r1, 4096) 83 if n1 != 8 { s.diag = 40; nx_atom_store_i64(done_addr, -1, NX_MO_SEQ_CST); return 0 } 84 if _check(r1, 8, 10) != 0 { s.diag = 41; nx_atom_store_i64(done_addr, -1, NX_MO_SEQ_CST); return 0 } 85 86 let r2: *u8 = sys_mmap(4096) 87 let n2: i64 = nx_net_chan_recv_blob(nc, r2, 4096) 88 if n2 != 64 { s.diag = 42; nx_atom_store_i64(done_addr, -1, NX_MO_SEQ_CST); return 0 } 89 if _check(r2, 64, 20) != 0 { s.diag = 43; nx_atom_store_i64(done_addr, -1, NX_MO_SEQ_CST); return 0 } 90 91 let r3: *u8 = sys_mmap(4096) 92 let n3: i64 = nx_net_chan_recv_blob(nc, r3, 4096) 93 if n3 != 1024 { s.diag = 44; nx_atom_store_i64(done_addr, -1, NX_MO_SEQ_CST); return 0 } 94 if _check(r3, 1024, 30) != 0 { s.diag = 45; nx_atom_store_i64(done_addr, -1, NX_MO_SEQ_CST); return 0 } 95 96 nx_net_chan_close(nc) 97 s.diag = 1 98 nx_atom_store_i64(done_addr, 1, NX_MO_SEQ_CST) 99 return 0 100} 101 102func main() -> nx_exit { 103 println("=== nx_net_chan_blob round-trip (8B, 64B, 1024B) ===" as *u8) 104 105 let state_raw: *u8 = sys_mmap(64) 106 let s: *BlobState = state_raw as *BlobState 107 s.done_flag = 0 108 s.diag = 0 109 110 let lfd: i64 = nx_sock_socket(NX_AF_INET, NX_SOCK_STREAM, NX_IPPROTO_TCP) 111 if lfd < 0 { println("FAIL: socket" as *u8); return 1 } 112 nx_sock_reuseaddr(lfd) 113 let laddr: *u8 = sys_mmap(16) 114 nx_sock_sin_init(laddr, 0, NX_PORT) 115 if nx_sock_bind(lfd, laddr, 16) < 0 { println("FAIL: bind" as *u8); return 2 } 116 if nx_sock_listen(lfd, 1) < 0 { println("FAIL: listen" as *u8); return 3 } 117 118 let tid: i64 = nx_thread_spawn_fn(client_main, state_raw, 65536) 119 if tid <= 0 { println("FAIL: spawn" as *u8); return 4 } 120 121 let cfd: i64 = nx_sock_accept(lfd, 0 as *u8, 0 as *i64) 122 if cfd < 0 { println("FAIL: accept" as *u8); return 5 } 123 let server_nc: *NxNetChan = nx_net_chan_from_fd(cfd) 124 125 // Echo 3 blobs back to client. 126 var i: i64 = 0 127 while i < 3 { 128 let recv_buf: *u8 = sys_mmap(4096) 129 let n: i64 = nx_net_chan_recv_blob(server_nc, recv_buf, 4096) 130 if n < 0 { println("FAIL: server recv blob" as *u8); print_i64(n); println("" as *u8); return 6 } 131 if nx_net_chan_send_blob(server_nc, recv_buf, n) != 0 { 132 println("FAIL: server send blob" as *u8); return 7 133 } 134 i = i + 1 135 } 136 nx_net_chan_close(server_nc) 137 sys_close(lfd) 138 139 let done_addr: *i64 = (state_raw as *i64) 140 var spins: i64 = 0 141 while nx_atom_load_i64(done_addr, NX_MO_SEQ_CST) == 0 { 142 nx_thread_yield() 143 spins = spins + 1 144 if spins > 100000000 { println("FAIL: client timeout" as *u8); return 8 } 145 } 146 if nx_atom_load_i64(done_addr, NX_MO_SEQ_CST) != 1 { 147 println("FAIL: client diag=" as *u8); print_i64(s.diag); println("" as *u8); return 9 148 } 149 println("PASS: 3 variable-length blobs (8B+64B+1024B) round-tripped over TCP." as *u8) 150 println("Length-prefix framing works; foundation for typed-struct RPC + bulk transfer." as *u8) 151 return 0 152}