Last active
June 29, 2022 08:29
-
-
Save xmdhs/062678d81502649931efa4833195a8d2 to your computer and use it in GitHub Desktop.
minecraft lan list
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"math/rand" | |
"net" | |
"os" | |
"strconv" | |
"sync" | |
"time" | |
) | |
func main() { | |
for i := 0; i < 100; i++ { | |
port := r.Intn(9999) + 1 | |
go sendPing(randStr(10, []byte(atext)), strconv.Itoa(port)) | |
} | |
os.Stdin.Read(make([]byte, 1)) | |
} | |
type arand struct { | |
*rand.Rand | |
*sync.Mutex | |
} | |
var r = arand{ | |
Rand: rand.New(rand.NewSource(time.Now().Unix())), | |
Mutex: &sync.Mutex{}, | |
} | |
const atext = `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%` | |
func randStr(n int, words []byte) string { | |
b := make([]byte, n) | |
r.Lock() | |
for i := range b { | |
b[i] = words[r.Intn(len(words))] | |
} | |
r.Unlock() | |
return string(b) | |
} | |
func sendPing(motd, port string) { | |
dstAddr, err := net.ResolveUDPAddr("udp", "224.0.2.60:4445") | |
if err != nil { | |
panic(err) | |
} | |
srcAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0} | |
conn, err := net.ListenUDP("udp", srcAddr) | |
if err != nil { | |
fmt.Println(err) | |
} | |
msg := []byte(fmt.Sprintf(`[MOTD]%s[/MOTD][AD]%s[/AD]`, motd, port)) | |
for { | |
_, err := conn.WriteToUDP(msg, dstAddr) | |
if err != nil { | |
panic(err) | |
} | |
time.Sleep(2 * time.Second) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"errors" | |
"fmt" | |
"net" | |
"golang.org/x/net/ipv4" | |
) | |
func main() { | |
err := Listen(context.TODO(), "224.0.2.60:4445", "0.0.0.0", func(u *net.UDPAddr, b []byte) { | |
fmt.Println(string(b), u.String()) | |
}) | |
if err != nil { | |
panic(err) | |
} | |
} | |
const maxDatagramSize = 8024 | |
func Listen(cxt context.Context, address, laddress string, handler func(*net.UDPAddr, []byte)) error { | |
msgCh := make(chan readMsg, 10) | |
errCh := make(chan error, 10) | |
addr, err := net.ResolveUDPAddr("udp4", address) | |
if err != nil { | |
return fmt.Errorf("Listen: %w", err) | |
} | |
il, err := net.Interfaces() | |
if err != nil { | |
return fmt.Errorf("Listen: %w", err) | |
} | |
if laddress != "0.0.0.0" { | |
lip := net.ParseIP(laddress) | |
var itf *net.Interface | |
B: | |
for _, v := range il { | |
addr, _ := v.Addrs() | |
for _, vv := range addr { | |
if ipnet, ok := vv.(*net.IPNet); ok && ipnet.IP.Equal(lip) { | |
itf = &v | |
break B | |
} | |
} | |
} | |
if itf == nil { | |
return fmt.Errorf("Listen: %w", ErrNotItf) | |
} | |
il = []net.Interface{*itf} | |
} | |
cxt, cancel := context.WithCancel(cxt) | |
defer cancel() | |
for _, v := range il { | |
if v.Flags&net.FlagMulticast != net.FlagMulticast || v.Flags&net.FlagUp != net.FlagUp { | |
continue | |
} | |
v := v | |
go read(cxt, &v, addr, errCh, msgCh) | |
} | |
for { | |
select { | |
case err := <-errCh: | |
return fmt.Errorf("Listen: %w", err) | |
case msg := <-msgCh: | |
handler(msg.addr, msg.msg) | |
case <-cxt.Done(): | |
return nil | |
} | |
} | |
} | |
var ErrNotItf = errors.New("not find interface") | |
func read(cxt context.Context, itf *net.Interface, addr *net.UDPAddr, eCh chan<- error, msgCh chan<- readMsg) { | |
cxt, cancel := context.WithCancel(cxt) | |
defer cancel() | |
conn, err := net.ListenMulticastUDP("udp", itf, addr) | |
doErr := func(err error) { | |
select { | |
case <-cxt.Done(): | |
case eCh <- fmt.Errorf("read: %w", err): | |
} | |
} | |
if err != nil { | |
doErr(err) | |
return | |
} | |
defer conn.Close() | |
go func() { | |
<-cxt.Done() | |
conn.Close() | |
}() | |
conn.SetReadBuffer(maxDatagramSize) | |
pc := ipv4.NewPacketConn(conn) | |
if err := pc.SetMulticastLoopback(true); err != nil { | |
doErr(err) | |
return | |
} | |
for { | |
buffer := make([]byte, maxDatagramSize) | |
numBytes, src, err := conn.ReadFromUDP(buffer) | |
if err != nil { | |
doErr(err) | |
return | |
} | |
select { | |
case msgCh <- readMsg{ | |
addr: src, | |
msg: buffer[:numBytes], | |
}: | |
case <-cxt.Done(): | |
return | |
} | |
} | |
} | |
type readMsg struct { | |
addr *net.UDPAddr | |
msg []byte | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment