diff --git a/client.go b/client.go index 128c471c..9a45a669 100644 --- a/client.go +++ b/client.go @@ -252,6 +252,48 @@ func supportsGetParameter(header base.Header) bool { return false } +func interfaceOfConn(c net.Conn) (*net.Interface, error) { + var localIP net.IP + + switch addr := c.LocalAddr().(type) { + case *net.TCPAddr: + localIP = addr.IP + case *net.UDPAddr: + localIP = addr.IP + default: + return nil, fmt.Errorf("unknown connection type: %T", c.LocalAddr()) + } + + interfaces, err := net.Interfaces() + if err != nil { + return nil, err + } + + for _, iface := range interfaces { + var addrs []net.Addr + addrs, err = iface.Addrs() + if err != nil { + continue + } + + for _, addr := range addrs { + var ip net.IP + switch v := addr.(type) { + case *net.IPNet: + ip = v.IP + case *net.IPAddr: + ip = v.IP + } + + if ip != nil && ip.Equal(localIP) { + return &iface, nil + } + } + } + + return nil, fmt.Errorf("no interface found for IP %s", localIP) +} + type clientState int const ( @@ -1796,9 +1838,16 @@ func (c *Client) doSetup( remoteIP = c.nconn.RemoteAddr().(*net.TCPAddr).IP } + var intf *net.Interface + intf, err = interfaceOfConn(c.nconn) + if err != nil { + cm.close() + return nil, err + } + err = cm.createUDPListeners( true, - remoteIP, + intf, net.JoinHostPort(thRes.Destination.String(), strconv.FormatInt(int64(thRes.Ports[0]), 10)), net.JoinHostPort(thRes.Destination.String(), strconv.FormatInt(int64(thRes.Ports[1]), 10)), ) diff --git a/client_media.go b/client_media.go index abf60223..3c273f62 100644 --- a/client_media.go +++ b/client_media.go @@ -101,17 +101,17 @@ func (cm *clientMedia) close() { } func (cm *clientMedia) createUDPListeners( - multicastEnable bool, - multicastSourceIP net.IP, + multicast bool, + multicastInterface *net.Interface, rtpAddress string, rtcpAddress string, ) error { if rtpAddress != ":0" { l1 := &clientUDPListener{ - c: cm.c, - multicastEnable: multicastEnable, - multicastSourceIP: multicastSourceIP, - address: rtpAddress, + c: cm.c, + multicast: multicast, + multicastInterface: multicastInterface, + address: rtpAddress, } err := l1.initialize() if err != nil { @@ -119,10 +119,10 @@ func (cm *clientMedia) createUDPListeners( } l2 := &clientUDPListener{ - c: cm.c, - multicastEnable: multicastEnable, - multicastSourceIP: multicastSourceIP, - address: rtcpAddress, + c: cm.c, + multicast: multicast, + multicastInterface: multicastInterface, + address: rtcpAddress, } err = l2.initialize() if err != nil { @@ -146,10 +146,8 @@ func (cm *clientMedia) createUDPListeners( rtcpPort := rtpPort + 1 cm.udpRTPListener = &clientUDPListener{ - c: cm.c, - multicastEnable: false, - multicastSourceIP: nil, - address: net.JoinHostPort("", strconv.FormatInt(int64(rtpPort), 10)), + c: cm.c, + address: net.JoinHostPort("", strconv.FormatInt(int64(rtpPort), 10)), } err = cm.udpRTPListener.initialize() if err != nil { @@ -158,10 +156,8 @@ func (cm *clientMedia) createUDPListeners( } cm.udpRTCPListener = &clientUDPListener{ - c: cm.c, - multicastEnable: false, - multicastSourceIP: nil, - address: net.JoinHostPort("", strconv.FormatInt(int64(rtcpPort), 10)), + c: cm.c, + address: net.JoinHostPort("", strconv.FormatInt(int64(rtcpPort), 10)), } err = cm.udpRTCPListener.initialize() if err != nil { diff --git a/client_udp_listener.go b/client_udp_listener.go index b0243555..c28bc138 100644 --- a/client_udp_listener.go +++ b/client_udp_listener.go @@ -29,10 +29,10 @@ type packetConn interface { } type clientUDPListener struct { - c *Client - multicastEnable bool - multicastSourceIP net.IP - address string + c *Client + multicast bool + multicastInterface *net.Interface + address string pc packetConn readFunc readFunc @@ -47,13 +47,9 @@ type clientUDPListener struct { } func (u *clientUDPListener) initialize() error { - if u.multicastEnable { - intf, err := multicast.InterfaceForSource(u.multicastSourceIP) - if err != nil { - return err - } - - u.pc, err = multicast.NewSingleConn(intf, u.address, u.c.ListenPacket) + if u.multicast { + var err error + u.pc, err = multicast.NewSingleConn(u.multicastInterface, u.address, u.c.ListenPacket) if err != nil { return err } diff --git a/pkg/multicast/multicast.go b/pkg/multicast/multicast.go index bc76544f..a332ae05 100644 --- a/pkg/multicast/multicast.go +++ b/pkg/multicast/multicast.go @@ -13,6 +13,8 @@ type Conn interface { } // InterfaceForSource returns a multicast-capable interface that can communicate with given IP. +// +// Deprecated: not used anymore. func InterfaceForSource(ip net.IP) (*net.Interface, error) { if ip.Equal(net.ParseIP("127.0.0.1")) { return nil, fmt.Errorf("IP 127.0.0.1 can't be used as source of a multicast stream. Use the LAN IP of your PC")