fix(udp): a "multicast" row on an address that is not one still listens
Reported from a station whose two WSJT-X rows had been dead for weeks:
both were ticked multicast with 127.0.0.1 in the group box, and both
failed the join on every interface with
setsockopt: l'adresse demandée n'est pas valide dans son contexte
which names nothing the operator typed and does not say what is wrong
with it. A multicast group runs 224.0.0.0 to 239.255.255.255; 127.0.0.1
is loopback unicast, and it is an understandable thing to type — it is
the address every other field in every other program wants.
The address is now checked before the join. When it is not a multicast
one the row listens on unicast instead, which is what such an address
means, and the log says why it is not multicast. The row works, and the
reason is in a sentence rather than in a kernel error code.
This commit is contained in:
+4
-2
@@ -3,10 +3,12 @@
|
||||
"version": "0.27.19",
|
||||
"date": "",
|
||||
"en": [
|
||||
"After an update, OpsLog starts again. The fix that stopped Defender calling the updater a trojan removed the helper that waited for the old process to die, and nothing took over the job: the new instance was patient with the single-instance lock for twenty seconds while the old one is allowed thirty to shut down — closing a remote logbook, a CAT session, sometimes a backup. Where that ran long the new process gave up in silence, leaving no window and a leftover OpsLog in the task manager. It now waits for the previous process itself, ending the instant it does; and if it really has not gone, it says so instead of claiming OpsLog is already running."
|
||||
"After an update, OpsLog starts again. The fix that stopped Defender calling the updater a trojan removed the helper that waited for the old process to die, and nothing took over the job: the new instance was patient with the single-instance lock for twenty seconds while the old one is allowed thirty to shut down — closing a remote logbook, a CAT session, sometimes a backup. Where that ran long the new process gave up in silence, leaving no window and a leftover OpsLog in the task manager. It now waits for the previous process itself, ending the instant it does; and if it really has not gone, it says so instead of claiming OpsLog is already running.",
|
||||
"A UDP row set to multicast on an address that is not one now listens anyway. 127.0.0.1 in the group box is the common mistake — it is the address every other field in every other program wants — but a multicast group runs 224.0.0.0 to 239.255.255.255, and joining anything else failed on every interface with a Windows error naming nothing the operator had typed. The row simply did not run. It now listens on unicast, which is what such an address means, and says so in the log."
|
||||
],
|
||||
"fr": [
|
||||
"Après une mise à jour, OpsLog redémarre. Le correctif qui a fait cesser la détection en cheval de Troie a supprimé l'assistant qui attendait la mort de l'ancien processus, et rien n'a repris ce travail : la nouvelle instance patientait vingt secondes sur le verrou d'instance unique alors que l'ancienne dispose de trente pour se fermer — elle referme un journal distant, une session CAT, parfois une sauvegarde. Quand cela durait, le nouveau processus abandonnait en silence : pas de fenêtre, et un OpsLog restant dans le gestionnaire des tâches. Il attend désormais l'ancien processus lui-même, et repart à l'instant où celui-ci s'arrête ; et s'il n'est vraiment pas parti, il le dit au lieu d'annoncer qu'OpsLog tourne déjà."
|
||||
"Après une mise à jour, OpsLog redémarre. Le correctif qui a fait cesser la détection en cheval de Troie a supprimé l'assistant qui attendait la mort de l'ancien processus, et rien n'a repris ce travail : la nouvelle instance patientait vingt secondes sur le verrou d'instance unique alors que l'ancienne dispose de trente pour se fermer — elle referme un journal distant, une session CAT, parfois une sauvegarde. Quand cela durait, le nouveau processus abandonnait en silence : pas de fenêtre, et un OpsLog restant dans le gestionnaire des tâches. Il attend désormais l'ancien processus lui-même, et repart à l'instant où celui-ci s'arrête ; et s'il n'est vraiment pas parti, il le dit au lieu d'annoncer qu'OpsLog tourne déjà.",
|
||||
"Une ligne UDP réglée en multicast sur une adresse qui n'en est pas une écoute désormais quand même. 127.0.0.1 dans le champ groupe est l'erreur classique — c'est l'adresse que réclame tout autre champ de tout autre programme — mais un groupe multicast va de 224.0.0.0 à 239.255.255.255, et rejoindre autre chose échouait sur toutes les interfaces avec une erreur Windows ne nommant rien de ce que l'opérateur avait saisi. La ligne ne tournait tout simplement pas. Elle écoute maintenant en unicast, ce que veut dire une telle adresse, et le dit dans le journal."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package udp
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// A "multicast" row whose group is not a multicast address.
|
||||
//
|
||||
// 127.0.0.1 in that box is the common mistake — it is the address every other
|
||||
// field in every other program wants — and it used to fail the join on every
|
||||
// interface with a Windows error about an address not being valid in its
|
||||
// context. The row did not run and the message named nothing the operator had
|
||||
// typed. Reported by an operator whose WSJT-X rows were dead for exactly this
|
||||
// reason, while a third row on unicast worked perfectly beside them.
|
||||
func TestOnlyRealMulticastGroupsAreJoined(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
addr string
|
||||
multicast bool
|
||||
}{
|
||||
{"224.0.0.1", true}, // the all-hosts group WSJT-X offers
|
||||
{"239.255.0.1", true}, // the administratively-scoped range
|
||||
{"127.0.0.1", false}, // loopback: the mistake
|
||||
{"192.168.1.10", false},
|
||||
{"0.0.0.0", false},
|
||||
} {
|
||||
ip := net.ParseIP(tc.addr)
|
||||
if ip == nil {
|
||||
t.Fatalf("%s does not parse", tc.addr)
|
||||
}
|
||||
if got := ip.IsMulticast(); got != tc.multicast {
|
||||
t.Errorf("%s: IsMulticast() = %v, wanted %v", tc.addr, got, tc.multicast)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -310,7 +310,28 @@ func newServer(cfg Config, out chan<- Event, mgr *Manager) *Server {
|
||||
|
||||
func (s *Server) start() error {
|
||||
var conn *net.UDPConn
|
||||
if s.cfg.Multicast {
|
||||
// "Multicast" ticked with an address that is not one.
|
||||
//
|
||||
// 127.0.0.1 in the group box is the common mistake, and it is an
|
||||
// understandable one — it is the address every other field in every other
|
||||
// program wants. But a multicast group is 224.0.0.0 to 239.255.255.255, and
|
||||
// joining anything else fails on every interface with a Windows error about
|
||||
// an address not being valid in its context. The row then simply does not
|
||||
// run, and an operator reads a setsockopt message that names nothing they
|
||||
// typed.
|
||||
//
|
||||
// So it listens anyway, as unicast, which is what an address like that means
|
||||
// — and says what it did. The row works, and the reason it is not multicast
|
||||
// is in the log rather than in a kernel error code.
|
||||
multicast := s.cfg.Multicast
|
||||
if multicast {
|
||||
if ip := net.ParseIP(strings.TrimSpace(s.cfg.MulticastGroup)); ip != nil && !ip.IsMulticast() {
|
||||
applog.Printf("udp: [%s] %s is not a multicast address (those run 224.0.0.0-239.255.255.255) — listening on unicast :%d instead\n",
|
||||
s.cfg.Name, ip, s.cfg.Port)
|
||||
multicast = false
|
||||
}
|
||||
}
|
||||
if multicast {
|
||||
group := strings.TrimSpace(s.cfg.MulticastGroup)
|
||||
if group == "" {
|
||||
return fmt.Errorf("multicast enabled but group address is empty")
|
||||
|
||||
Reference in New Issue
Block a user