From 523279ef67888ecbf894487c2df803b3c8c95c39 Mon Sep 17 00:00:00 2001 From: Nicolai Ommer Date: Thu, 15 Jun 2023 20:46:45 +0200 Subject: [PATCH] Detect multicast sources from different network interfaces --- cmd/ssl-multicast-sources/main.go | 83 +++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 22 deletions(-) diff --git a/cmd/ssl-multicast-sources/main.go b/cmd/ssl-multicast-sources/main.go index 2d983c3..1eed308 100644 --- a/cmd/ssl-multicast-sources/main.go +++ b/cmd/ssl-multicast-sources/main.go @@ -4,66 +4,105 @@ import ( "flag" "log" "net" - "time" + "os" + "os/signal" + "sync" + "syscall" ) const maxDatagramSize = 8192 -var detectedRemotes map[string][]string +type Source struct { + nif string + ip string + port int +} + +var detectedRemotes map[string][]Source +var detectedRemotesMutex sync.Mutex func main() { flag.Parse() - detectedRemotes = map[string][]string{} + detectedRemotes = map[string][]Source{} mcAddresses := flag.Args() if len(mcAddresses) == 0 { mcAddresses = []string{"224.5.23.1:10003", "224.5.23.2:10006", "224.5.23.2:10010", "224.5.23.2:10012"} } + ifiList := interfaces() for _, address := range mcAddresses { - go watchAddress(address) + for _, ifi := range ifiList { + go receiveOnInterface(address, ifi) + } } - for { - time.Sleep(1 * time.Second) + signals := make(chan os.Signal, 1) + signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) + <-signals +} + +func interfaces() (interfaces []net.Interface) { + interfaces = []net.Interface{} + ifis, err := net.Interfaces() + if err != nil { + log.Println("Could not get available interfaces: ", err) + } + for _, ifi := range ifis { + interfaces = append(interfaces, ifi) } + return } -func watchAddress(address string) { +func receiveOnInterface(address string, ifi net.Interface) { addr, err := net.ResolveUDPAddr("udp", address) if err != nil { - log.Fatal(err) + log.Printf("Could resolve multicast address %v: %v", address, err) + return } - conn, err := net.ListenMulticastUDP("udp", nil, addr) + + conn, err := net.ListenMulticastUDP("udp", &ifi, addr) if err != nil { - log.Fatal(err) + log.Printf("Could not listen at %v: %v", address, err) + return } + if err := conn.SetReadBuffer(maxDatagramSize); err != nil { - log.Printf("Could not set read buffer to %v.", maxDatagramSize) + log.Println("Could not set read buffer: ", err) } - log.Println("Receiving from", address) + + log.Printf("Listening on %s (%s)", address, ifi.Name) + + data := make([]byte, maxDatagramSize) for { - _, udpAddr, err := conn.ReadFromUDP([]byte{0}) + _, remoteAddr, err := conn.ReadFromUDP(data) if err != nil { - log.Print("Could not read: ", err) - time.Sleep(1 * time.Second) - continue + log.Println("ReadFromUDP failed:", err) + return } - addRemote(address, udpAddr.IP.String()) + + addRemote(address, Source{ + nif: ifi.Name, + ip: remoteAddr.IP.String(), + port: remoteAddr.Port, + }) } } -func addRemote(address string, remote string) { +func addRemote(address string, source Source) { + detectedRemotesMutex.Lock() + defer detectedRemotesMutex.Unlock() + remotes, ok := detectedRemotes[address] if !ok { - detectedRemotes[address] = []string{} + detectedRemotes[address] = []Source{} } for _, a := range remotes { - if a == remote { + if a == source { return } } - detectedRemotes[address] = append(detectedRemotes[address], remote) - log.Printf("remote ip on %v: %v\n", address, remote) + detectedRemotes[address] = append(detectedRemotes[address], source) + log.Printf("New source on %v: %+v\n", address, source) }