close() went straight to shutdown(SHUT_RDWR) + close(). Doing that while either
side still has unread data makes the stack send RST rather than FIN, and the
device's FromRadio stream means there is essentially always unread data.
Winsock discards data that was received but not yet read when an RST arrives, so
an admin message written moments earlier is thrown away before the device reads
it. Linux delivers the buffered bytes before reporting ECONNRESET, which is why
this only surfaced on Windows: every one-shot TCP write there (--set, --seturl,
--sendtext) reported success and did nothing.
writeConfig() does not wait for an ack, so close() runs microseconds after
sendall(). The device cannot compensate; it polls every 5ms and the RST beats its
next read.
Send FIN first with shutdown(SHUT_WR), which lets the device consume what we
wrote, wait briefly for the reader thread to drain and exit, then tear down
exactly as before. The full shutdown is kept so a reader still blocked in recv()
is unblocked for the join in StreamInterface.close(). The wait is bounded: the
device is not obliged to close just because we half-closed.
Fixes#957
- Unify parsing for yaml/DeviceProfile paths
- Improve autodetection
- Ensure partial-config behavior with yaml
- gate configuration to local node (avoiding some pre-existing bugs)
- gate fixed position updates behind explicit opt-in via position settings field
- use setOwner properly
- tests, tests, and more tests
This enables e.g. `--set position.position_flags ALTITUDE,SPEED`
rather than the dedicated `--pos-flags`, and similarly for
`network.enabled_protocols`.
Displaying these named values when printing out configurations
is not yet implemented.
ROUTING_APP with errorReason NONE is an ACK (success), not an error.
Only print failure message for non-NONE error reasons.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously, receiving a ROUTING_APP packet in response to a traceroute
would cause the function to attempt parsing it as a RouteDiscovery
payload, resulting in a crash or silent failure followed by a timeout.
This mirrors the error handling already present in onResponseTelemetry
and onResponseWaypoint, but displays the specific errorReason instead
of a hardcoded firmware version message, since traceroute is a
diagnostic tool where the exact failure reason is more valuable.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>