89 lines
1.9 KiB
Go
89 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"musique/server/proto"
|
|
"net"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/RobertBendun/zeroconf/v2"
|
|
)
|
|
|
|
func doHandshake(wg *sync.WaitGroup, service *zeroconf.ServiceEntry, remotes chan<- Remote, timeout time.Duration) {
|
|
for _, ip := range service.AddrIPv4 {
|
|
wg.Add(1)
|
|
go func(ip net.IP) {
|
|
defer wg.Done()
|
|
target := fmt.Sprintf("%s:%d", ip, service.Port)
|
|
if isThisMyAddress(target) {
|
|
return
|
|
}
|
|
|
|
var hs proto.HandshakeResponse
|
|
err := proto.CommandTimeout(target, proto.Handshake(), &hs, timeout)
|
|
if err == nil {
|
|
log.Println("Received handshake response", target, hs)
|
|
remotes <- Remote{
|
|
Address: target,
|
|
Nick: hs.Nick,
|
|
Version: hs.Version,
|
|
}
|
|
}
|
|
}(ip)
|
|
}
|
|
}
|
|
|
|
// Register all remotes that cane be found in `waitTime` seconds
|
|
func registerRemotes(waitTime int) error {
|
|
wg := sync.WaitGroup{}
|
|
done := make(chan error, 1)
|
|
incomingRemotes := make(chan Remote, 32)
|
|
entries := make(chan *zeroconf.ServiceEntry, 12)
|
|
timeout := time.Second*time.Duration(waitTime)
|
|
|
|
wg.Add(1)
|
|
go func(results <-chan *zeroconf.ServiceEntry) {
|
|
for entry := range results {
|
|
log.Println("Found service at", entry.HostName, "at addrs", entry.AddrIPv4)
|
|
doHandshake(&wg, entry, incomingRemotes, timeout)
|
|
}
|
|
wg.Done()
|
|
done <- nil
|
|
}(entries)
|
|
|
|
go func() {
|
|
wg.Wait()
|
|
close(incomingRemotes)
|
|
}()
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
defer cancel()
|
|
|
|
go func() {
|
|
err := zeroconf.Browse(ctx, "_musique._tcp", "local", entries)
|
|
if err != nil {
|
|
done <- fmt.Errorf("failed to browse: %v", err)
|
|
}
|
|
<-ctx.Done()
|
|
}()
|
|
|
|
remotes = make(map[string]*Remote)
|
|
for remote := range incomingRemotes {
|
|
remote := remote
|
|
remotes[remote.Address] = &remote
|
|
}
|
|
|
|
return <-done
|
|
}
|
|
|
|
type dnsServer interface {
|
|
Shutdown()
|
|
}
|
|
|
|
func registerDNS() (dnsServer, error) {
|
|
return zeroconf.Register("Musique", "_musique._tcp", "local", port, []string{}, nil)
|
|
}
|