diff options
author | xegineering <me@xegineering.eu> | 2024-11-17 12:45:35 +0100 |
---|---|---|
committer | xegineering <me@xegineering.eu> | 2024-11-17 12:48:00 +0100 |
commit | d4cf5ed8e38d1e5d0b8110e8959e002c216f073f (patch) | |
tree | 4565ee3c50e6de74b6ce65c615ac71dcf8378a7f /soundbox/network.go | |
parent | a95013aa0813d1644aa15780f360fa4dad2223a8 (diff) | |
download | soundbox-go-d4cf5ed8e38d1e5d0b8110e8959e002c216f073f.tar soundbox-go-d4cf5ed8e38d1e5d0b8110e8959e002c216f073f.tar.zst soundbox-go-d4cf5ed8e38d1e5d0b8110e8959e002c216f073f.zip |
Fix streaming only via first interface candidate
Diffstat (limited to 'soundbox/network.go')
-rw-r--r-- | soundbox/network.go | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/soundbox/network.go b/soundbox/network.go new file mode 100644 index 0000000..6e7acea --- /dev/null +++ b/soundbox/network.go @@ -0,0 +1,58 @@ +package soundbox + +import ( + "context" + "fmt" + "net" + "time" +) + +const dialTimeoutSeconds = 3 + +// toLinkLocal converts a MAC address to the corresponding IPv6 link-local +// address. +func toLinkLocal(ha net.HardwareAddr) (net.IP, error) { + switch len(ha) { + case 6: + ip := net.IP{0xfe, 0x80, 0, 0, 0, 0, 0, 0, + ha[0] ^ 0b10, ha[1], ha[2], 0xff, 0xfe, ha[3], ha[4], ha[5]} + return ip, nil + default: + return nil, fmt.Errorf("Only IEEE 802 MAC-48 addresses supported") + } +} + +func dialContext(ctx context.Context, ha net.HardwareAddr) (net.Conn, error) { + ip, err := toLinkLocal(ha) + if err != nil { + return nil, err + } + + ifaces, err := net.Interfaces() + if err != nil { + return nil, err + } + + c := make(chan net.Conn) + dialContext, cancel := context.WithTimeout(ctx, dialTimeoutSeconds * time.Second) + defer cancel() + for _, iface := range ifaces { + go func() { + var d net.Dialer + conn, err := d.DialContext( + ctx, + "tcp6", + fmt.Sprintf("[%s%%%s]:%d", ip, iface.Name, streamingPort), + ) + if err == nil { + c <- conn + } + }() + } + select { + case conn := <-c: + return conn, nil + case <-dialContext.Done(): + return nil, fmt.Errorf("Could not dial TCP connection to %v on port %d on any interface.", ha, streamingPort) + } +} |