package multicast import ( "bytes" "fmt" "log" "net" "net/netip" "time" ) func Receiver(vpnNet netip.Prefix, selfVPNIP netip.Addr, ch chan<- Packet) { for { if err := receiver(vpnNet, selfVPNIP, ch); err != nil { log.Printf("[MCReader] %v", err) } time.Sleep(errorTimeout) } } func receiver(vpnNet netip.Prefix, selfVPNIP netip.Addr, ch chan<- Packet) error { selfIP := selfVPNIP.As4()[3] conn, err := net.ListenMulticastUDP("udp", nil, addr) if err != nil { return fmt.Errorf("bind: %w", err) } defer conn.Close() buf := make([]byte, SignedPacketSize+1) // +1 to detect oversized packets for { conn.SetReadDeadline(time.Now().Add(32 * time.Second)) n, src, err := conn.ReadFromUDPAddrPort(buf) if err != nil { if ne, ok := err.(net.Error); ok && ne.Timeout() { continue } return fmt.Errorf("read: %w", err) } if n != SignedPacketSize { continue } packet := unmarshal(buf[:n]) if packet.PeerIP == selfIP { continue } age := time.Since(time.Unix(packet.Timestamp, 0)) if age > maxPacketAge || age < -maxPacketAge { continue } packet.Signed = bytes.Clone(packet.Signed) packet.Src = src.Addr().Unmap() ch <- packet } }