package udp import ( "net" "testing" "time" ) // The relay exists so a second application can be fed the same WSJT-X stream, // and the ONE thing it must get right is that the bytes are unchanged. The // relays in the field prepend an origin header ("127.0.0.1:2237|") — which is // why stripForwarderHeader had to be written on the receiving side — so a // header here would inflict on the next program the fault we had to survive. func TestRelayForwardsVerbatim(t *testing.T) { dst, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0}) if err != nil { t.Fatal(err) } defer dst.Close() port := dst.LocalAddr().(*net.UDPAddr).Port m := &Manager{outbound: []Config{{ ID: 1, Name: "relay", ServiceType: ServiceWSJTRelay, DestinationIP: "127.0.0.1", Port: port, }}} // A packet with bytes that no parser here understands, on purpose: the relay // must not care what it is carrying. sent := []byte{0xad, 0xbc, 0xcb, 0xda, 0x00, 0x00, 0x00, 0x63, 0xde, 0xad, 0xbe, 0xef} m.RelayInbound(sent, 2237) buf := make([]byte, 1024) _ = dst.SetReadDeadline(time.Now().Add(2 * time.Second)) n, _, err := dst.ReadFromUDP(buf) if err != nil { t.Fatalf("nothing relayed: %v", err) } if got := buf[:n]; string(got) != string(sent) { t.Errorf("relayed % X, want % X — the bytes must go out unchanged", got, sent) } } // A relay aimed at one of OpsLog's OWN listening ports would come straight back // in, be relayed again, and saturate the loopback within seconds. The row is // skipped instead. func TestRelayRefusesToFeedItself(t *testing.T) { own, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0}) if err != nil { t.Fatal(err) } defer own.Close() port := own.LocalAddr().(*net.UDPAddr).Port m := &Manager{ inbound: map[int64]*Server{ 7: {cfg: Config{ID: 7, Port: port, ServiceType: ServiceWSJT}}, }, outbound: []Config{{ ID: 1, Name: "loop", ServiceType: ServiceWSJTRelay, DestinationIP: "127.0.0.1", Port: port, }}, } m.RelayInbound([]byte{1, 2, 3, 4}, 2237) buf := make([]byte, 64) _ = own.SetReadDeadline(time.Now().Add(300 * time.Millisecond)) if n, _, err := own.ReadFromUDP(buf); err == nil { t.Fatalf("relayed %d bytes back into our own listener — that is the loop", n) } } // No relay rows configured must cost nothing and send nothing. func TestRelayWithNoRowsIsSilent(t *testing.T) { m := &Manager{} m.RelayInbound([]byte{1, 2, 3}, 2237) // must not panic m.RelayInbound(nil, 2237) }