code wiki / (root) / nx_iot_sc_broadcast.nx

nx_iot_sc_broadcast.nx source

↩ module page · 90 lines · 3946 B

1// nx_iot_sc_broadcast.nx -- SOVEREIGN ESP-Touch v1 BROADCASTER (R1b-live). Sends the U8 length 2// sequence from nx_iot_smartconfig as real UDP packets so a Tuya/ESP device in pairing mode sniffs 3// the Wi-Fi creds off the 2.4GHz air. NO app, NO Windows tooling on the program path. 4// 5// Mechanism (verified from sovereignly-fetched Espressif source, knowledge/fetched/sc_java_*.raw): 6// - each U8 length L -> one UDP packet whose PAYLOAD is L bytes of '1' (ByteUtil.genSpecBytes: 7// `byte[] data=new byte[len]; for(i) data[i]='1';` -- only the LENGTH carries data) 8// - device sniffs in promiscuous mode (sc_idf_device.raw) so the dest addr only has to put the 9// frame on the air: multicast 234.x:7001 or broadcast 255.255.255.255 both work 10// - send the 4 guide lengths repeatedly until the device locks, then loop the datum block 11// 12// Sockets via nx_syscalls.nx (the @ifdef TARGET_X86_64 path: SYS_SOCKET=41/SYS_SENDTO=44 -- the 13// WORKING path; nx_syscalls_x86_64.nx's socket() dies with ENOSYS in WSL). Runs on any x86_64 Linux 14// host that can transmit on the 2.4GHz (NishiOS box on the IoT SSID, or a Wi-Fi-client rung). The 15// ARM router has no Nishi backend yet -> that deployment seam is documented, not faked. 16// NEVER-BRICK #26: emits reversible Wi-Fi creds only; no firmware write. license_tier: ORIGINAL 17import "nx_syscalls.nx" 18import "nx_iot_smartconfig.nx" 19const SO_MAGIC_1024: i64 = 1024 20 21const SO_BROADCAST: i64 = 6 22 23// genSpecBytes(L): payload of L bytes, all '1' (0x31). Verified byte-exact vs ByteUtil.genSpecBytes. 24func nx_sc_genspec(buf: *u8, len: i64) -> i64 { 25 var i: i64 = 0 26 while i < len { buf[i] = 0x31 as u8; i = i + 1 } 27 return len 28} 29 30// Build a 16-byte sockaddr_in: family AF_INET, port (big-endian), addr a.b.c.d (network order), sin_zero. 31func nx_sc_sockaddr(sa: *u8, a: i64, b: i64, c: i64, d: i64, port: i64) -> i64 { 32 sa[0] = (AF_INET & 0xff) as u8 33 sa[1] = ((AF_INET >> 8) & 0xff) as u8 34 sa[2] = ((port >> 8) & 0xff) as u8 35 sa[3] = (port & 0xff) as u8 36 sa[4] = a as u8 37 sa[5] = b as u8 38 sa[6] = c as u8 39 sa[7] = d as u8 40 var i: i64 = 8 41 while i < 16 { sa[i] = 0 as u8; i = i + 1 } 42 return 16 43} 44 45// Open a UDP socket with SO_BROADCAST enabled (so 255.255.255.255 works); returns fd or <0. 46func nx_sc_open() -> i64 { 47 let fd: i64 = sys_socket(AF_INET, SOCK_DGRAM, 0) 48 if fd < 0 { return fd } 49 let one: *i64 = sys_mmap(8) as *i64 50 one[0] = 1 51 sys_setsockopt(fd, SOL_SOCKET, SO_BROADCAST, one as *u8, 4) 52 return fd 53} 54 55// Send one packet of length L (payload = '1'*L) to sa. Returns sys_sendto result (L on success). 56func nx_sc_send_one(fd: i64, sa: *u8, scratch: *u8, len: i64) -> i64 { 57 nx_sc_genspec(scratch, len) 58 return sys_sendto(fd, scratch, len, 0, sa, 16) 59} 60 61// Broadcast the full ESP-Touch sequence to a.b.c.d:port: guide block x guide_reps, then datum block 62// x datum_reps. Returns total packets sent (>=0), or negative on encode/socket failure. 63func nx_sc_broadcast(ssid: *u8, ssid_n: i64, bssid: *u8, pwd: *u8, pwd_n: i64, ip: *u8, 64 a: i64, b: i64, c: i64, d: i64, port: i64, 65 guide_reps: i64, datum_reps: i64) -> i64 { 66 let u8s: *i64 = sys_mmap(512 * 8) as *i64 67 let n: i64 = nx_sc_encode(ssid, ssid_n, bssid, pwd, pwd_n, ip, u8s, 512) 68 if n < 0 { return 0 - 2 } 69 let fd: i64 = nx_sc_open() 70 if fd < 0 { return 0 - 3 } 71 let sa: *u8 = sys_mmap(16) 72 nx_sc_sockaddr(sa, a, b, c, d, port) 73 let scratch: *u8 = sys_mmap(SO_MAGIC_1024) 74 var sent: i64 = 0 75 76 var r: i64 = 0 77 while r < guide_reps { 78 var i: i64 = 0 79 while i < 4 { nx_sc_send_one(fd, sa, scratch, u8s[i]); sent = sent + 1; i = i + 1 } 80 r = r + 1 81 } 82 r = 0 83 while r < datum_reps { 84 var j: i64 = 4 85 while j < n { nx_sc_send_one(fd, sa, scratch, u8s[j]); sent = sent + 1; j = j + 1 } 86 r = r + 1 87 } 88 sys_close(fd) 89 return sent 90}