diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/socket.asm | 57 |
1 files changed, 54 insertions, 3 deletions
diff --git a/src/socket.asm b/src/socket.asm index fa6b245..20ed982 100644 --- a/src/socket.asm +++ b/src/socket.asm @@ -48,6 +48,11 @@ wNetReq:: DS NR_SIZE wNetSockPtr:: DS 2 wNetIhl:: DS 1 wNetSeq:: DS 1 +wNetEchoId:: DS 2 ; ICMP echo identifier: unique per boot + per host. + ; A fixed id (the old $1234) made every GB's ping + ; flow identical across boots/sessions, colliding in + ; upstream NAT conntrack (keyed on icmp id) - replies + ; were silently dropped until the stale entry expired. wNetTx:: DS 320 ; tx build buffer wNetRxBuf:: DS 320 ; rx frame assembly / parse wNetRxLen:: DS 2 ; 16-bit: frames can exceed 255 bytes (DHCP/BOOTP) @@ -90,6 +95,10 @@ net_init:: ld [wConHead], a ld [wConTail], a ld [wNetSeq], a + ldh a, [rDIV] ; per-boot echo id seed (refined at DHCP lease) + ld [wNetEchoId], a + cpl + ld [wNetEchoId+1], a ret ; con_push(A) - queue a console-input byte (dropped if the ring is full) @@ -147,6 +156,9 @@ net_op_setip: ld [wNetOurIP+2], a ld a, [wNetReq+NR_IP+3] ld [wNetOurIP+3], a + ld [wNetEchoId], a ; echo id hi = our host octet (distinct per GB) + ldh a, [rDIV] ; lo = timer noise at lease time (distinct per + ld [wNetEchoId+1], a ; boot - DHCP timing varies with the network) xor a ret @@ -300,6 +312,8 @@ sys_net:: jp z, net_op_poll cp NET_SETIP jp z, net_op_setip + cp NET_RECVNB + jp z, net_op_recvnb ld a, $FF ret @@ -418,6 +432,43 @@ net_op_send: ld a, $FF ret +; ---- recvnb(sock, buf, maxlen) -> A = len / $FE (nothing yet) / 0 (TCP EOF) -- +; One pump, no blocking: programs that need their own (wall-clock) timeout - +; ping, most of all - loop recvnb+msleep instead of sitting in net_op_recv's +; pump-counted wait, which at native speed can block for minutes if a reply +; is lost (e.g. a host that rate-limits ICMP). +net_op_recvnb: + ld a, [wNetReq + NR_SOCK] + call net_sock_ptr + ld a, l + ld [wNetSockPtr], a + ld a, h + ld [wNetSockPtr+1], a + call net_pump + ld a, [wNetReq+NR_SOCK] ; tcp_in may have moved wNetSockPtr; restore + call net_sock_ptr + ld a, l + ld [wNetSockPtr], a + ld a, h + ld [wNetSockPtr+1], a + call sock_has_rx + jp nz, net_op_recv.got ; deliver exactly like a blocking recv + call sock_ptr_hl ; TCP peer closed + nothing buffered -> EOF + ld a, l + add SK_STATE + ld l, a + ld a, h + adc 0 + ld h, a + ld a, [hl] + cp TCP_DONE + jr nz, .none + xor a ; EOF -> 0, same as net_op_recv + ret +.none + ld a, $FE ; nothing buffered yet + ret + ; ---- recv(sock, buf, maxlen) -> A = len or $FF (timeout) --------------------- net_op_recv: ld a, [wNetReq + NR_SOCK] @@ -595,9 +646,9 @@ icmp_send: ld [wNetTx+21], a ; code ld [wNetTx+22], a ld [wNetTx+23], a ; cksum - ld a, $12 - ld [wNetTx+24], a ; id - ld a, $34 + ld a, [wNetEchoId] + ld [wNetTx+24], a ; id (unique per boot + host, set by net_setip) + ld a, [wNetEchoId+1] ld [wNetTx+25], a xor a ld [wNetTx+26], a ; seq hi |
