Implement the gateway presence-ping responder
Python · Python · intermediate · greenfield
Adds the presence-ping responder for the gateway keepalive protocol. Parses the 2-byte length header, rejects frames larger than the scratch and payloads over the 4094-byte cap, then echoes the payload back to the device, reusing a preallocated receive scratch to avoid a fresh allocation per ping on the hot path. Covered by the round-trip liveness tests.
respond_ping runs in the edge telemetry gateway and replies to keepalive pings from remote devices; whatever bytes it returns are written straight back over the wire to whoever sent the frame.
Requirements
- Implement respond_ping(frame): frame is a bytes object whose first 2 bytes are a big-endian uint16 declaring the payload length, followed by exactly that many payload bytes.
- The declared length is at most MAX_PAYLOAD (4094) bytes; the responder reuses a single preallocated 4096-byte receive scratch buffer sized for the 2-byte header plus the max payload.
- Return a bytes object containing exactly the payload the device actually sent — a presence ping echoes the device's own bytes back, no more and no less.
- Pings arrive from remote devices over the gateway's datagram socket; treat the frame as untrusted input — a device may declare a length that does not match the bytes it actually sent.
Files touched
- gateway/net/presence.py
--- gateway/net/presence.py
+"""Presence-ping responder for the edge telemetry gateway.
+
+Devices keep their gateway session alive by sending a length-prefixed
+presence ping over the datagram socket. The socket layer de-frames one
+datagram and hands us the raw frame:
+
+ byte 0..1 uint16 big-endian declared payload length
+ byte 2..N payload bytes
+
+The gateway answers by echoing the device's own payload straight back so
+the device can measure round-trip latency. Per the protocol the reply MUST
+contain EXACTLY the payload bytes the device sent, no more and no less.
+"""
+
+HEADER_LEN = 2
+# Largest payload we accept; header + payload fills the receive scratch exactly.
+MAX_PAYLOAD = 4094
+MAX_FRAME = HEADER_LEN + MAX_PAYLOAD # 4096
+
+# Reused receive scratch, sized to the largest frame we accept. One per worker:
+# each incoming frame is copied in at offset 0 and parsed in place, the way the
+# socket layer hands back a pooled read buffer. It is not cleared between pings.
+_recv_scratch = bytearray(MAX_FRAME)
+
+
+def respond_ping(frame: bytes) -> bytes:
+ if len(frame) < HEADER_LEN:
+ raise ValueError("presence ping is shorter than its 2-byte length header")
+ if len(frame) > MAX_FRAME: