81 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			81 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package utils
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"net"
 | 
						|
	"packets/internal/consts"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"golang.org/x/net/ipv4"
 | 
						|
)
 | 
						|
 | 
						|
type Peer struct {
 | 
						|
	IP   net.IP
 | 
						|
	Port int
 | 
						|
}
 | 
						|
 | 
						|
func BroadcastAddr(ip net.IP, mask net.IPMask) net.IP {
 | 
						|
	b := make(net.IP, len(ip))
 | 
						|
	for i := range ip {
 | 
						|
		b[i] = ip[i] | ^mask[i]
 | 
						|
	}
 | 
						|
	return b
 | 
						|
}
 | 
						|
 | 
						|
func AskLAN(filename string) ([]Peer, error) {
 | 
						|
	var peers []Peer
 | 
						|
	query := []byte("Q:" + filename)
 | 
						|
 | 
						|
	pc, err := net.ListenPacket("udp", ":0")
 | 
						|
	if err != nil {
 | 
						|
		return []Peer{}, err
 | 
						|
	}
 | 
						|
	defer pc.Close()
 | 
						|
 | 
						|
	if pconn := ipv4.NewPacketConn(pc); pconn != nil {
 | 
						|
		_ = pconn.SetTTL(1)
 | 
						|
	}
 | 
						|
 | 
						|
	ifaces, _ := net.Interfaces()
 | 
						|
	for _, ifc := range ifaces {
 | 
						|
		if ifc.Flags&net.FlagUp == 0 || ifc.Flags&net.FlagLoopback != 0 {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		addrs, _ := ifc.Addrs()
 | 
						|
		for _, a := range addrs {
 | 
						|
			ipnet, ok := a.(*net.IPNet)
 | 
						|
			if !ok || ipnet.IP.To4() == nil {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
			bcast := BroadcastAddr(ipnet.IP.To4(), ipnet.Mask)
 | 
						|
			dst := &net.UDPAddr{IP: bcast, Port: 1333}
 | 
						|
 | 
						|
			_, err = pc.WriteTo(query, dst)
 | 
						|
			if err != nil {
 | 
						|
				fmt.Printf(":: (%s) can't send to  %s: %s\n", ifc.Name, bcast, err.Error())
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	_ = pc.SetDeadline(time.Now().Add(consts.LANDeadline))
 | 
						|
	buf := make([]byte, 1500)
 | 
						|
 | 
						|
	for {
 | 
						|
		n, addr, err := pc.ReadFrom(buf)
 | 
						|
		if err != nil {
 | 
						|
			break
 | 
						|
		}
 | 
						|
		msg := string(buf[:n])
 | 
						|
 | 
						|
		if strings.HasPrefix(msg, "H:"+filename) {
 | 
						|
			parts := strings.Split(msg, ":")
 | 
						|
			port, _ := strconv.Atoi(parts[2])
 | 
						|
			peers = append(peers, Peer{IP: addr.(*net.UDPAddr).IP, Port: port})
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return peers, nil
 | 
						|
}
 |