aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/socket.asm57
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