mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 11:15:07 +03:00 
			
		
		
		
	Move multicasting into yggdrasil package
This commit is contained in:
		
							parent
							
								
									388ae09fca
								
							
						
					
					
						commit
						6f79184c9b
					
				
					 6 changed files with 196 additions and 129 deletions
				
			
		| 
						 | 
				
			
			@ -10,8 +10,8 @@ type NodeConfig struct {
 | 
			
		|||
	BoxPriv        string    `json:"EncryptionPrivateKey" comment:"Your private encryption key (do not share this with anyone!)"`
 | 
			
		||||
	SigPub         string    `json:"SigningPublicKey" comment:"Your public signing key"`
 | 
			
		||||
	SigPriv        string    `json:"SigningPrivateKey" comment:"Your private signing key (do not share this with anyone!)"`
 | 
			
		||||
	Multicast      bool      `comment:"Enable or disable automatic peer discovery on the same LAN using multicast"`
 | 
			
		||||
	LinkLocal      string    `json:"MulticastInterfaces" comment:"Regex for which interfaces multicast peer discovery should be enabled on"`
 | 
			
		||||
	Multicast      bool      `json:"MulticastEnabled,omitempty" comment:"Enable or disable automatic peer discovery on the same LAN using multicast"`
 | 
			
		||||
	LinkLocal      []string  `json:"MulticastInterfaces" comment:"Regexes for which interfaces multicast peer discovery should be enabled\non. If none specified, multicast peer discovery is disabled"`
 | 
			
		||||
	IfName         string    `comment:"Local network interface name for TUN/TAP adapter, or \"auto\", or \"none\""`
 | 
			
		||||
	IfTAPMode      bool      `comment:"Set local network interface to TAP mode rather than TUN mode (if supported\nby your platform, option will be ignored if not)"`
 | 
			
		||||
	IfMTU          int       `comment:"Maximux Transmission Unit (MTU) size for your local network interface"`
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,10 +19,11 @@ type Core struct {
 | 
			
		|||
	tun         tunDevice
 | 
			
		||||
	admin       admin
 | 
			
		||||
	searches    searches
 | 
			
		||||
	multicast   multicast
 | 
			
		||||
	tcp         *tcpInterface
 | 
			
		||||
	udp         *udpInterface
 | 
			
		||||
	log         *log.Logger
 | 
			
		||||
	ifceExpr    *regexp.Regexp // the zone of link-local IPv6 peers must match this
 | 
			
		||||
	ifceExpr    []*regexp.Regexp // the zone of link-local IPv6 peers must match this
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Core) Init() {
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +50,7 @@ func (c *Core) init(bpub *boxPubKey,
 | 
			
		|||
	c.searches.init(c)
 | 
			
		||||
	c.dht.init(c)
 | 
			
		||||
	c.sessions.init(c)
 | 
			
		||||
	c.multicast.init(c)
 | 
			
		||||
	c.peers.init(c)
 | 
			
		||||
	c.router.init(c)
 | 
			
		||||
	c.switchTable.init(c, c.sigPub) // TODO move before peers? before router?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -387,6 +387,13 @@ func (c *Core) DEBUG_setupAndStartAdminInterface(addrport string) {
 | 
			
		|||
	c.admin = a
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Core) DEBUG_setupAndStartMulticastInterface() {
 | 
			
		||||
	m := multicast{}
 | 
			
		||||
	m.init(c)
 | 
			
		||||
	c.multicast = m
 | 
			
		||||
	m.Start()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
func (c *Core) DEBUG_setLogger(log *log.Logger) {
 | 
			
		||||
| 
						 | 
				
			
			@ -394,7 +401,7 @@ func (c *Core) DEBUG_setLogger(log *log.Logger) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (c *Core) DEBUG_setIfceExpr(expr *regexp.Regexp) {
 | 
			
		||||
	c.ifceExpr = expr
 | 
			
		||||
	c.ifceExpr = append(c.ifceExpr, expr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Core) DEBUG_addAllowedBoxPub(boxStr string) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										160
									
								
								src/yggdrasil/multicast.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								src/yggdrasil/multicast.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,160 @@
 | 
			
		|||
package yggdrasil
 | 
			
		||||
 | 
			
		||||
import "net"
 | 
			
		||||
import "time"
 | 
			
		||||
import "fmt"
 | 
			
		||||
 | 
			
		||||
import "golang.org/x/net/ipv6"
 | 
			
		||||
 | 
			
		||||
type multicast struct {
 | 
			
		||||
	core      *Core
 | 
			
		||||
	sock      *ipv6.PacketConn
 | 
			
		||||
	groupAddr string
 | 
			
		||||
  interfaces []net.Interface
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *multicast) init(core *Core) {
 | 
			
		||||
	m.core = core
 | 
			
		||||
	m.groupAddr = "[ff02::114]:9001"
 | 
			
		||||
  // Ask the system for network interfaces
 | 
			
		||||
  allifaces, err := net.Interfaces()
 | 
			
		||||
  if err != nil {
 | 
			
		||||
    panic(err)
 | 
			
		||||
  }
 | 
			
		||||
  // Work out which interfaces to announce on
 | 
			
		||||
  for _, iface := range allifaces {
 | 
			
		||||
    if iface.Flags & net.FlagUp == 0 {
 | 
			
		||||
      // Ignore interfaces that are down
 | 
			
		||||
      continue
 | 
			
		||||
    }
 | 
			
		||||
    if iface.Flags & net.FlagMulticast == 0 {
 | 
			
		||||
      // Ignore non-multicast interfaces
 | 
			
		||||
      continue
 | 
			
		||||
    }
 | 
			
		||||
    if iface.Flags & net.FlagPointToPoint != 0 {
 | 
			
		||||
      // Ignore point-to-point interfaces
 | 
			
		||||
      continue
 | 
			
		||||
    }
 | 
			
		||||
    for _, expr := range m.core.ifceExpr {
 | 
			
		||||
      m.core.log.Println(expr)
 | 
			
		||||
      if expr.MatchString(iface.Name) {
 | 
			
		||||
        m.core.log.Println(iface.Name, "matched", expr)
 | 
			
		||||
        m.interfaces = append(m.interfaces, iface)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  m.core.log.Println("Found", len(m.interfaces), "multicast interfaces")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *multicast) Start() {
 | 
			
		||||
	if len(m.core.ifceExpr) == 0 {
 | 
			
		||||
		m.core.log.Println("Not starting multicast discovery")
 | 
			
		||||
	} else {
 | 
			
		||||
    m.core.log.Println("Starting multicast discovery...")
 | 
			
		||||
  	addr, err := net.ResolveUDPAddr("udp", m.groupAddr)
 | 
			
		||||
  	if err != nil {
 | 
			
		||||
  		panic(err)
 | 
			
		||||
  	}
 | 
			
		||||
  	listenString := fmt.Sprintf("[::]:%v", addr.Port)
 | 
			
		||||
  	conn, err := net.ListenPacket("udp6", listenString)
 | 
			
		||||
  	if err != nil {
 | 
			
		||||
  		panic(err)
 | 
			
		||||
  	}
 | 
			
		||||
  	//defer conn.Close() // Let it close on its own when the application exits
 | 
			
		||||
  	m.sock = ipv6.NewPacketConn(conn)
 | 
			
		||||
  	if err = m.sock.SetControlMessage(ipv6.FlagDst, true); err != nil {
 | 
			
		||||
  		// Windows can't set this flag, so we need to handle it in other ways
 | 
			
		||||
  		//panic(err)
 | 
			
		||||
  	}
 | 
			
		||||
 | 
			
		||||
  	go m.listen()
 | 
			
		||||
  	go m.announce()
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *multicast) announce() {
 | 
			
		||||
	groupAddr, err := net.ResolveUDPAddr("udp6", m.groupAddr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	var anAddr net.TCPAddr
 | 
			
		||||
	myAddr := m.core.DEBUG_getGlobalTCPAddr()
 | 
			
		||||
	anAddr.Port = myAddr.Port
 | 
			
		||||
	destAddr, err := net.ResolveUDPAddr("udp6", m.groupAddr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	for {
 | 
			
		||||
		for _, iface := range m.interfaces {
 | 
			
		||||
 | 
			
		||||
			m.sock.JoinGroup(&iface, groupAddr)
 | 
			
		||||
			//err := n.sock.JoinGroup(&iface, groupAddr)
 | 
			
		||||
			//if err != nil { panic(err) }
 | 
			
		||||
			addrs, err := iface.Addrs()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				panic(err)
 | 
			
		||||
			}
 | 
			
		||||
			for _, addr := range addrs {
 | 
			
		||||
				addrIP, _, _ := net.ParseCIDR(addr.String())
 | 
			
		||||
				if addrIP.To4() != nil {
 | 
			
		||||
					continue
 | 
			
		||||
				} // IPv6 only
 | 
			
		||||
				if !addrIP.IsLinkLocalUnicast() {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
				anAddr.IP = addrIP
 | 
			
		||||
				anAddr.Zone = iface.Name
 | 
			
		||||
				destAddr.Zone = iface.Name
 | 
			
		||||
				msg := []byte(anAddr.String())
 | 
			
		||||
				m.sock.WriteTo(msg, nil, destAddr)
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			time.Sleep(time.Second)
 | 
			
		||||
		}
 | 
			
		||||
		time.Sleep(time.Second)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *multicast) listen() {
 | 
			
		||||
	groupAddr, err := net.ResolveUDPAddr("udp6", m.groupAddr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	bs := make([]byte, 2048)
 | 
			
		||||
	for {
 | 
			
		||||
		nBytes, rcm, fromAddr, err := m.sock.ReadFrom(bs)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
		//if rcm == nil { continue } // wat
 | 
			
		||||
		//fmt.Println("DEBUG:", "packet from:", fromAddr.String())
 | 
			
		||||
		if rcm != nil {
 | 
			
		||||
			// Windows can't set the flag needed to return a non-nil value here
 | 
			
		||||
			// So only make these checks if we get something useful back
 | 
			
		||||
			// TODO? Skip them always, I'm not sure if they're really needed...
 | 
			
		||||
			if !rcm.Dst.IsLinkLocalMulticast() {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if !rcm.Dst.Equal(groupAddr.IP) {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		anAddr := string(bs[:nBytes])
 | 
			
		||||
		addr, err := net.ResolveTCPAddr("tcp6", anAddr)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
			continue
 | 
			
		||||
		} // Panic for testing, remove later
 | 
			
		||||
		from := fromAddr.(*net.UDPAddr)
 | 
			
		||||
		//fmt.Println("DEBUG:", "heard:", addr.IP.String(), "from:", from.IP.String())
 | 
			
		||||
		if addr.IP.String() != from.IP.String() {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		addr.Zone = from.Zone
 | 
			
		||||
		saddr := addr.String()
 | 
			
		||||
		//if _, isIn := n.peers[saddr]; isIn { continue }
 | 
			
		||||
		//n.peers[saddr] = struct{}{}
 | 
			
		||||
		m.core.DEBUG_addTCPConn(saddr)
 | 
			
		||||
		//fmt.Println("DEBUG:", "added multicast peer:", saddr)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -341,11 +341,17 @@ func (iface *udpInterface) reader() {
 | 
			
		|||
			if them.isValid() {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if udpAddr.IP.IsLinkLocalUnicast() &&
 | 
			
		||||
				!iface.core.ifceExpr.MatchString(udpAddr.Zone) {
 | 
			
		||||
				continue
 | 
			
		||||
			if udpAddr.IP.IsLinkLocalUnicast() {
 | 
			
		||||
				if len(iface.core.ifceExpr) == 0 {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				for _, expr := range iface.core.ifceExpr {
 | 
			
		||||
					if expr.MatchString(udpAddr.Zone) {
 | 
			
		||||
						iface.handleKeys(msg, addr)
 | 
			
		||||
						break
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			iface.handleKeys(msg, addr)
 | 
			
		||||
		case udp_isClose(msg):
 | 
			
		||||
			iface.handleClose(msg, addr)
 | 
			
		||||
		default:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue