Skip to content

fix: classify OP_FAILED replies as operation failures, not dropped connections - #112

Merged
MegaManSec merged 1 commit into
mainfrom
fix/classify-op-failed-replies
Aug 20, 2026
Merged

fix: classify OP_FAILED replies as operation failures, not dropped connections#112
MegaManSec merged 1 commit into
mainfrom
fix/classify-op-failed-replies

Conversation

@MegaManSec

Copy link
Copy Markdown
Owner

OutgoingConnection.run's body callback was a Bool, so a peer that answered OP_FAILED over a healthy authenticated channel was classified as .bodyFailed — the same bucket as a mid-message connection drop. Two consequences:

  • The outbound rate limiter recorded it as a host failure, so a reachable peer that legitimately reports "couldn't do it" a few times throttles further attempts into tooManyRecentFailures — against a perfectly healthy peer.
  • The user-facing notification read "The connection dropped mid-message." when the peer actually received, processed, and answered the request.

Changes:

  • The body callback is now typed Result<Void, OutgoingFailure>; two new cases distinguish an authenticated OP_FAILED (.remoteOperationFailed) from a malformed or command-shaped reply (.invalidResponse), each with its own user-facing message.
  • A shared decodeOperationResponse replaces the four inline OP_SUCCESS comparisons. INTRODUCE keeps its custom reply handling (a legacy peer's OP_FAILED still maps to .legacy).
  • An authenticated OP_FAILED now counts as rate-limiter success: the channel proved healthy, and the failure is the operation's, not the network's.

continueAdoption already treats any non-connect failure as "peer is up" via its default arm, so adoption/reclaim behavior is unchanged; only its comment reference moves from .bodyFailed to .remoteOperationFailed.

Ported from the classification half of cssmagic/magic-switch@a912313, minus its fork-only release-lease context.

Verified with swift-format lint and swiftc -parse only — no Xcode on this machine, so this hasn't been built or run against hardware.

…nnections

A peer that answers OP_FAILED over a healthy authenticated channel was
classified as .bodyFailed — the same bucket as a mid-message connection
drop. That fed the outbound rate limiter as a host failure (throttling a
reachable peer into tooManyRecentFailures) and showed the user "The
connection dropped mid-message." when the peer actually answered.

Type the body callback as Result<Void, OutgoingFailure>, add
.remoteOperationFailed and .invalidResponse, decode OP_SUCCESS/OP_FAILED
acks in one shared helper, and count an authenticated OP_FAILED as
rate-limiter success since the channel proved healthy.

Ported from cssmagic/magic-switch@a912313, minus its fork-only
release-lease context.
@MegaManSec
MegaManSec merged commit f2806d9 into main Aug 20, 2026
2 checks passed
@MegaManSec
MegaManSec deleted the fix/classify-op-failed-replies branch August 20, 2026 20:16
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 2.25.6 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant