Skip to content

feat: reply-on-connection (TypeAutoAnswer frame + AutoAnswer service)#19

Closed
Alexgodoroja wants to merge 1 commit into
mainfrom
proto/reply-on-conn
Closed

feat: reply-on-connection (TypeAutoAnswer frame + AutoAnswer service)#19
Alexgodoroja wants to merge 1 commit into
mainfrom
proto/reply-on-conn

Conversation

@Alexgodoroja

Copy link
Copy Markdown
Collaborator

What

Adds reply-on-connection at the data-exchange layer: a new opt-in request type TypeAutoAnswer (6) and an AutoAnswer service mode that answers a request on the same connection the sender opened, instead of relying on a dial-back.

Why

The dial-back is the biggest source of lost replies — it fails whenever the requester is unreachable for an inbound connection (NAT, no public port, transient client). Reply-on-connection removes that dependency for opted-in requests.

How it works

On a service with ServiceConfig.AutoAnswer, a TypeAutoAnswer request is:

  • not saved to the inbox (so a responder never also dial-backs it),
  • dispatched via ReplyHook,
  • answered with the reply written back on the same connection as a TEXT frame,
  • closed after exactly one request + one reply (no loop — two AutoAnswer peers can't ping-pong),
  • bounded by a 40s watchdog window, with a graceful close (wait for the sender to consume the reply before teardown) to avoid the ~50% abortive-teardown loss.

Backwards compatible

Plain TypeText/TypeJSON/TypeBinary requests are unchanged. A TypeAutoAnswer frame reaching a node that does not auto-answer falls through to a normal inbox save (still dial-backed). Enabling AutoAnswer never changes how a node serves ordinary senders.

API additions

  • TypeAutoAnswer; TypeName(TypeAutoAnswer)"AUTOANSWER"
  • Client.SendAutoAnswer(text), Client.SetReadDeadline(t)

Tests

zz_autoanswer_test.go: frame type/name, client send + deadline, and integration through handleConn (ACK+REPLY + reply + skip-inbox; plain TEXT unaffected; fallback-to-inbox when AutoAnswer off; no-reply when the hook declines).


Part of a coordinated reply-on-connection rollout (pilotprotocol, pilot-agents/responder, pilot-skills). Merge this first — pilotprotocol depends on it.

@codecov

codecov Bot commented Jun 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@TeoSlayer

Copy link
Copy Markdown
Contributor

Closing this reply-on-connection chain after review — holding, not rejecting the idea.

Rationale:

  1. Wire-format change without real negotiation — adds TypeAutoAnswer=6, but backward-compat relies on string-matching a human-readable ack ("ACK+REPLY", "AUTOANSWER") rather than a versioned capability handshake. Those strings + TypeName become silent load-bearing protocol tokens; a rename breaks fallback.
  2. Amplification / DoS surface--auto-answer holds each inbound connection open up to ~40s and drives a per-frame upstream fetch, with no concurrency cap, rate limit, or per-peer cap.
  3. At-least-once delivery with no idempotency key — documented resend-on-lost-reply can double-process non-idempotent responders.

To revisit safely: versioned capability negotiation (not ack string-sniffing), receiver-side concurrency/rate limits + a real read deadline, and an idempotency key. Happy to pair on a v2.

@TeoSlayer TeoSlayer closed this Jun 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants