tftp: say what to do when the server cannot take its address - #129
Conversation
In OpenIPC/firmware#2299 a user running `defib install` got "OS Address already in use" partway through Phase 2 and had nothing to act on: the kernel's text names neither the address nor the port nor the fix. They went looking for 192.168.1.10 on their interfaces, which was the wrong trail -- EADDRINUSE means something else already holds UDP/69, typically a system tftpd or dnsmasq, or an earlier defib that has not exited. start_tftp_server let the bare OSError out of create_datagram_endpoint. Raise TFTPBindError instead, with the address, the likely cause and the command that finds the culprit, distinguishing the three failures that actually happen here: the port being held, the IP not being configured on any interface, and port 69 needing root. The original OSError stays attached as __cause__. This lands in the middle of a flash recovery, where guessing is expensive and the camera is already half-written.
PR Summary by QodoAdd actionable TFTP bind failure diagnostics
AI Description
Diagram
High-Level Assessment
Files changed (2)
|
Code Review by Qodo
1.
|
Review pointed out that the remediation text was Linux-only while defib ships on macOS and Windows -- the test matrix covers all three. Telling a Mac user to run `ss -ulpn`, or a Windows user to `ip addr add` and grant CAP_NET_BIND_SERVICE, sends them looking for tools that are not there, in the middle of a recovery. Pick the command per platform: ss/ip/CAP on Linux, lsof/ifconfig on macOS, netstat/netsh/ipconfig on Windows. Windows also has no reserved port range, so a refusal there is a firewall rule or an excluded port range rather than a missing privilege, and the advice says so instead of telling the operator to become root. Tests parametrise over all three platforms and assert both that the right tooling appears and that no Linux-only tooling leaks into the other two.
Follow-up from OpenIPC/firmware#2299.
The report
A user running
defib installhit this partway through Phase 2:They went hunting for a missing IP, which was the wrong trail —
EADDRINUSEmeans something else already holds UDP/69. The kernel's text names neither the address, nor the port, nor the fix, and this fails in the middle of a flash recovery on a camera that is already half-written.The change
start_tftp_serverlet the bareOSErrorout ofcreate_datagram_endpoint. It now raisesTFTPBindErrorwith something actionable, distinguishing the three failures that actually occur here:EADDRINUSEsudo ss -ulpn 'sport = :69'to find the holder (system tftpd, dnsmasq, a previous defib), and mentions--tftp-via podEADDRNOTAVAILip addr addline andip -brief addressto checkEACCES/EPERMAnything else still names the address and includes the original text. The
OSErrorstays attached as__cause__.Fixed inside
start_tftp_serverrather than at the call sites, so all three (recover,install,flash) get it.Tests
5 new, including an end-to-end one that binds an ephemeral UDP port and confirms the real bind path raises
TFTPBindErrorrather thanOSError.Message text only — no behaviour change to a successful transfer.