Skip to content

feat(native): PR1B — byte-bounded outbound queue, typed send result#4

Open
mrmidi wants to merge 1 commit into
pr1a/native-baselinefrom
pr1b/queue-bounds
Open

feat(native): PR1B — byte-bounded outbound queue, typed send result#4
mrmidi wants to merge 1 commit into
pr1a/native-baselinefrom
pr1b/queue-bounds

Conversation

@mrmidi

@mrmidi mrmidi commented Jul 20, 2026

Copy link
Copy Markdown
Owner

PR1B — Queue and Batch Bounds

Base: pr1a/native-baseline (stacked PR chain)
fptn submodule: 13acece (pr1b/queue-bounds)

Send() — typed result + byte accounting

  • Returns SendResult enum: accepted, queue_full, transport_stopped, invalid_packet
  • Overflow-safe CAS byte reservation before try_send. Both bytes and packet count reserved before the channel operation.
  • Rollback both counters on channel-full or exception. Channel-full increments queue_full_count_.
  • iOS caps: 256 KiB queued bytes, 64 KiB batch raw bytes
  • Other platforms: unlimited (existing 256-packet channel bound)

RunSender() — strict batch limit + accounting release

  • releaseDequeuedPacketAccounting() called immediately on every dequeue, before IP-version validation
  • Carried packet (pending_packet) prevents batch overshoot: bounds raw IP payload bytes to 64 KiB except one individually oversized packet
  • Exact encoded-size control deferred to PR5

Queue counters (unsigned, never reset in Stop)

Counter Semantics
queued_packets Current gauge
queued_bytes Current gauge (channel queue only; sender may additionally hold a batch + carried packet)
queued_bytes_peak Lifetime high-water mark
queue_full_count Lifetime byte-cap/channel-capacity rejection count

C++ → Swift boundary

  • C++ sendPacket() returns uint8_t; null/zero-length rejected as invalid_packet
  • Swift WebsocketSendResult enum in SharedTunnelRuntime; init(bridgeValue:) maps raw value; .unknown = 255

Provider behavior

packetLoop: for packet in packets {
    switch client?.sendPacket(packet) ?? .transportStopped {
    case .accepted:         break
    case .queueFull:        queueFullPackets += 1
    case .transportStopped: transportStopped = true; break packetLoop
    case .invalidPacket:    invalidPackets += 1
    case .unknown:          unknownResults += 1
    }
}
// totalBytes computed before send loop (full read batch)
// only queueFullPackets passed to recordPacketFlowRead()
// transportStopped → early return

Native cleanups

  • #include <TargetConditionals.h> moved outside namespace
  • Null/zero-length check in bridge sendPacket before vector construction

Verification

  • Native framework (Debug, C++23): built
  • Xcode Debug build: succeeded
  • Tests: 24/24 passed

Native test debt

C++ accounting tests (concurrent CAS, rollback, gauge lifecycle, batch bounds) need fptn gtest infrastructure. Tracked for PR1B/PR1C fptn branch.

Stack

PR-1  Measurement safety
PR0   Production native build
PR1A  Native fixed baseline       (base)
PR1B  Queue and batch bounds      ← this PR
PR1C  Native teardown ownership
PR2   Wrapper/provider integration
PR3   C-based binary flight recorder

@mrmidi
mrmidi force-pushed the pr1b/queue-bounds branch from 43dddd5 to 63f8ff9 Compare July 20, 2026 14:25
Pin fptn submodule to 7443f40 (pr1b/queue-bounds).

C++ bridge:
- sendPacket() returns uint8_t (0=accepted, 1=queue_full,
  2=transport_stopped, 3=invalid_packet)
- Status struct: +4 queue fields (queued_packets, queued_bytes,
  queued_bytes_peak, queue_full_count)

Swift:
- WebsocketSendResult enum in SharedTunnelRuntime (shared by app +
  tunnel). Mapped from C++ uint8_t via init(bridgeValue:).
- TunnelWebSocketTransport protocol updated: sendPacket returns
  WebsocketSendResult.
- Both wrappers (app + tunnel) return typed result.
- Status struct: +4 queue diagnostic fields.

Provider:
- startReadLoop uses switch by result:
  .queueFull → feeds backpressure
  .transportStopped → breaks batch early (labeled loop)
  .invalidPacket/.unknown → counted, does not slow valid traffic

Tests: 22/22 passed. Debug build succeeded.
@mrmidi
mrmidi force-pushed the pr1b/queue-bounds branch from 63f8ff9 to 58cca42 Compare July 20, 2026 14:55
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.

1 participant