aboutsummaryrefslogtreecommitdiffstats
path: root/src/socket.asm (follow)
Commit message (Collapse)AuthorAgeFilesLines
* net: pump the network from the console wait (answer pings at the prompt)user4 days1-10/+78
| | | | | | | | | | | | | | | A Game Boy sitting at the shell prompt now services the network instead of being deaf until you run netd: KGetc (the console input wait) pumps net_pump each poll, so inbound pings are auto-answered while idle. net_pump gained an in-frame model and routes any non-framed link bytes to a small console-input ring (con_push/con_pop), so a headless-injected command still reaches the shell while SLIP frames go to the stack. Removes the old SLIP-skip-in-KGetc hack. Verified: two Game Boys on the hub, GB0 idle at the prompt (no netd), GB1 `ping 10.0.0.2` -> 4/4 replies, routed GB1->hub->GB0->hub->GB1. (Separate, pre-existing: gbhub *spawn* mode and windowed gbjoin can drop an idle link socket - under investigation; daemon mode + headless is solid.)
* net: DHCP client - lease the IP at boot instead of hardcoding ituser4 days1-29/+68
| | | | | | | | | | | | | | | | | | | | | | | | | | | | The address is no longer baked in. net_init starts at 0.0.0.0; a DHCP client runs as the first thing on boot (init/shell forks it and waits), and only once it has a lease (or gives up) does the prompt appear. Kernel: - IP is configurable: 0.0.0.0 until leased; NET_SETIP op stores it. - 16-bit frame length. DHCP/BOOTP packets are ~272 bytes, over the old 255-byte frame cap, so net_slip_send takes a 16-bit length, net_pump assembles into a 320-byte buffer with a 16-bit wNetRxLen, and udp_send writes a 16-bit IP total. Payloads stay <=255 (kept small on purpose) so the per-protocol datalen math is unchanged. wNetTx/wNetRxBuf 256->320, SK_RXBUF 208->288. Userland: - c/dhcp.c: DISCOVER->OFFER->REQUEST->ACK over a UDP socket, then net_setip(); times out gracefully (shell still boots) if there's no server. sh.c runs it before the prompt. Bridge (self-contained DHCP server, no dnsmasq): - tunbridge.py + netboot intercept UDP->:67 and answer OFFER/ACK leasing 10.0.0.2 (gateway 10.0.0.1); everything else is bridged/NATed as before. Regression-tested ICMP/UDP/TCP after the 16-bit change. Verified end to end: dhcp: discovering dhcp: leased 10.0.0.2 /# ping 10.0.0.1 -> 4/4 (traffic from the leased address)
* net: TCP sockets in the kernel - a Game Boy fetches HTTP over real TCPuser4 days1-8/+678
| | | | | | | | | | | | | | | | | | | | | | | | | Kernel TCP client on the socket layer: net_connect(SOCK_TCP) runs the 3-way handshake in-kernel, send()/recv() drive the byte stream, close() does the FIN. - Socket gains state + 32-bit snd_nxt/rcv_nxt (big-endian, add-with-carry-fold). - tcp_send_seg builds IP+TCP with a pseudo-header checksum; the SYN carries an MSS option (200) so the peer never sends a segment larger than our 256-byte frame buffer (we don't do IP reassembly). - tcp_in state machine: SYN_SENT->ESTABLISHED on SYN-ACK, buffers in-order data and ACKs it, handles FIN -> recv() returns 0 (EOF). - No retransmission: the GB<->host link is lossless and the host's real TCP owns the internet side - which removes TCP's hardest part. - net_pump now processes one frame per call so recv drains each segment before the next arrives (single rx slot, no overwrite). wget.c is now a thin socket client: connect -> send "GET / HTTP/1.0" -> recv to EOF -> print. Verified end to end against a host HTTP server: /# wget 10.0.0.1 HTTP/1.0 200 OK Hello from a real HTTP server, fetched by a Game Boy! with a clean SYN/SYN-ACK/ACK ... PSH ... FIN/ACK trace on the wire.
* net: UDP sockets in the kernel + a DNS resolver (real hostname lookups)user5 days1-21/+321
| | | | | | | | | | | | | | | | | | | | Adds UDP to the kernel socket layer on top of the ICMP core: - net_sum() (raw folded sum) split out of net_cksum() so a UDP pseudo-header (src/dst IP + proto + length) can seed the segment checksum. - udp_send: builds IP+UDP with the pseudo-header checksum; NET_BIND sets the local/source port; net_connect sets the peer. - udp_in: demuxes inbound UDP by destination port to the bound socket (net_find_udp), delivers the payload + source addr. Also fixes a real recv bug: net_pump clobbers BC/DE/HL, so the old recv timeout counted in registers and was effectively random. recv now counts in WRAM. New `nslookup HOST` (PROG_NSLOOKUP=28, bank 30): builds a DNS A query and parses the answer (with 0xC0 name-compression) entirely in userland over a UDP socket - the kernel never sees DNS, just UDP. Verified through the bridge NAT: /# nslookup example.com -> example.com -> 172.66.147.243 This gives us name resolution for the TCP/HTTP demo next.
* net: proper socket API in the kernel (SYS_NET) - no more SLIP in userlanduser5 days1-0/+754
The network stack moves into the kernel. src/socket.asm owns SLIP framing, IPv4, RFC1071 checksums, and ICMP; programs now speak a socket API through one syscall (SYS_NET, DE=&netreq dispatched by op): net_socket/connect/send/recv/ close/poll (c/sock.h). No program touches SLIP, IP headers, or checksums. - Socket table (4 sockets) + tx/rx buffers in WRAM0; our IP = 10.0.0.2. - net_pump: drains the link, reassembles SLIP frames, demuxes IPv4. Inbound ICMP echo requests are auto-answered in-kernel, so the GB replies to pings whenever any process pumps RX. - ICMP sockets: send() emits an echo request to the connected peer; recv() returns the matching reply (with a spin/yield timeout). ping.c is now a ~15-line socket client; netd.c is just `for(;;){net_poll(); yield();}`. Verified over tunbridge: /# ping 1.1.1.1 -> replies from the real internet (kernel builds it all) host# ping 10.0.0.2 -> 4/4, 0% loss (kernel auto-answers) Gotchas recorded: gbos.inc isn't a make dep (touch asm after editing); this crt0 doesn't copy initializers (fill arrays at runtime); and the arg string at 0xA000 overlaps _DATA, so parse targets must sit past it (big buffer first). UDP and TCP sockets build on this same core next.