fix(logging): say why the antenna stopped and what the ADIF port is receiving
Two problems from one operator's log, both of them the log's fault. SteppIR. The last line about it is "status query failed, reconnecting: Port has been closed" and then nothing — for the rest of the session. The poll loop does retry every two seconds, but a failed open was a bare `continue`: no line, ever. And startUltrabeam had three silent ways out — settings unreadable, the antenna turned off, no port or host configured — so a cleared field and a lost adapter produced exactly the same evidence, which is none. Both now say what happened, with the port or host named. Reopen failures are reported three times and then throttled (a port that is gone stays gone), and the recovery says how many attempts it took. FLDIGI. Four hundred "ADIF payload ignored" lines and nothing else legible. The cause is in the same log: two inbound listeners on the SAME multicast group and port, 239.255.0.1:2237 — one WSJT (MSHV), one ADIF (FLDIGI). Every WSJT-X packet is delivered to both, and an FT8 cycle is dozens of decodes every fifteen seconds; the bursts in the log are exactly 15 s apart. The ADIF listener now checks for the WSJT-X magic and says so once, with what to do about it, instead of rejecting each packet in writing. Anything else is described a few times with its payload and then goes quiet.
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
package udp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// An operator's log arrived with four hundred identical "ADIF payload ignored"
|
||||
// lines and nothing else legible: two inbound listeners were configured on the
|
||||
// SAME multicast group and port, one WSJT and one ADIF, so every WSJT-X decode
|
||||
// was delivered to both and the ADIF one rejected each in writing. An FT8 cycle
|
||||
// is dozens of decodes every fifteen seconds.
|
||||
//
|
||||
// The listener has to recognise that traffic and say what it is — once.
|
||||
func TestIgnoredADIFStaysBounded(t *testing.T) {
|
||||
s := &Server{cfg: Config{Name: "FLDIGI", Port: 2237}}
|
||||
|
||||
// A WSJT-X packet: magic first. One line is the whole diagnosis, so the
|
||||
// counter is pushed past the cap immediately.
|
||||
pkt := make([]byte, 16)
|
||||
binary.BigEndian.PutUint32(pkt[:4], wsjtMagic)
|
||||
s.noteIgnoredADIF(pkt)
|
||||
if s.badPkts <= maxBadPktDumps {
|
||||
t.Errorf("badPkts = %d — WSJT traffic should silence the listener at once", s.badPkts)
|
||||
}
|
||||
|
||||
// Anything else is described a few times before going quiet, so an ordinary
|
||||
// keep-alive does not get the same one-line treatment as a real diagnosis.
|
||||
s2 := &Server{cfg: Config{Name: "FLDIGI", Port: 2237}}
|
||||
s2.noteIgnoredADIF([]byte("keep-alive"))
|
||||
if s2.badPkts > maxBadPktDumps {
|
||||
t.Errorf("one unusable payload silenced the listener (badPkts = %d)", s2.badPkts)
|
||||
}
|
||||
for i := 0; i < 50; i++ {
|
||||
s2.noteIgnoredADIF([]byte("keep-alive"))
|
||||
}
|
||||
if s2.badPkts <= maxBadPktDumps {
|
||||
t.Errorf("badPkts = %d — the throttle never engaged", s2.badPkts)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user