Implemented and fixed many issues
This commit is contained in:
@@ -447,6 +447,52 @@ func (u *UDPClient) runSession() error {
|
||||
}
|
||||
}
|
||||
|
||||
// interfaceForIP returns the interface that owns the given local address, or
|
||||
// nil if no interface matches (in which case callers fall back to letting the
|
||||
// kernel choose).
|
||||
func interfaceForIP(ip net.IP) *net.Interface {
|
||||
if ip == nil || ip.IsUnspecified() {
|
||||
return nil
|
||||
}
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for i := range ifaces {
|
||||
addrs, err := ifaces[i].Addrs()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, a := range addrs {
|
||||
var aIP net.IP
|
||||
switch v := a.(type) {
|
||||
case *net.IPNet:
|
||||
aIP = v.IP
|
||||
case *net.IPAddr:
|
||||
aIP = v.IP
|
||||
}
|
||||
if aIP != nil && aIP.Equal(ip) {
|
||||
return &ifaces[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// interfaceForConn returns the interface a connection's local endpoint sits on.
|
||||
func interfaceForConn(c net.Conn) *net.Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
switch a := c.LocalAddr().(type) {
|
||||
case *net.TCPAddr:
|
||||
return interfaceForIP(a.IP)
|
||||
case *net.UDPAddr:
|
||||
return interfaceForIP(a.IP)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// runMulticastSession handles the multicast mode session.
|
||||
func (u *UDPClient) runMulticastSession() error {
|
||||
tcpAddr, err := net.ResolveTCPAddr("tcp4", u.serverAddr)
|
||||
@@ -500,7 +546,15 @@ func (u *UDPClient) runMulticastSession() error {
|
||||
return &net.AddrError{Err: "invalid multicast group IP", Addr: u.multicastGroup}
|
||||
}
|
||||
mcastAddr := &net.UDPAddr{IP: mcastIP, Port: mcastPort}
|
||||
mcastConn, err := net.ListenMulticastUDP("udp4", nil, mcastAddr)
|
||||
// Join on the interface that reaches the control connection. The UDPStreamer
|
||||
// pins its multicast sends to its configured Interface (IP_MULTICAST_IF), so
|
||||
// a join with a nil interface — which leaves imr_interface at INADDR_ANY and
|
||||
// lets the kernel pick the default-route interface — silently receives
|
||||
// nothing whenever that is not the sending interface. The local address of
|
||||
// the control connection is the interface the server is reachable on, which
|
||||
// is the sending interface in every single-homed and same-host deployment.
|
||||
ifi := interfaceForConn(tcpConn)
|
||||
mcastConn, err := net.ListenMulticastUDP("udp4", ifi, mcastAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -508,7 +562,12 @@ func (u *UDPClient) runMulticastSession() error {
|
||||
if err := mcastConn.SetReadBuffer(udpRcvBufSize); err != nil {
|
||||
log.Printf("[%s] multicast SetReadBuffer: %v", u.sourceID, err)
|
||||
}
|
||||
log.Printf("[%s] joined multicast %s:%s", u.sourceID, u.multicastGroup, strconv.Itoa(mcastPort))
|
||||
ifName := "default"
|
||||
if ifi != nil {
|
||||
ifName = ifi.Name
|
||||
}
|
||||
log.Printf("[%s] joined multicast %s:%s on interface %s",
|
||||
u.sourceID, u.multicastGroup, strconv.Itoa(mcastPort), ifName)
|
||||
|
||||
tcpDone := make(chan error, 1)
|
||||
go func() {
|
||||
|
||||
Reference in New Issue
Block a user