arcast/pkg/client/scan.go

70 lines
1.3 KiB
Go
Raw Normal View History

2023-12-13 20:07:22 +01:00
package client
import (
"context"
"slices"
"forge.cadoles.com/arcad/arcast/pkg/server"
"github.com/grandcat/zeroconf"
"github.com/pkg/errors"
)
func (c *Client) Scan(ctx context.Context, funcs ...ScanOptionFunc) ([]*Player, error) {
opts := NewScanOptions(funcs...)
resolver, err := zeroconf.NewResolver(nil)
if err != nil {
return nil, errors.WithStack(err)
}
done := make(chan struct{})
players := make([]*Player, 0)
entries := make(chan *zeroconf.ServiceEntry)
go func(results <-chan *zeroconf.ServiceEntry) {
defer close(done)
for entry := range results {
addPlayer := func() {
players = append(players, &Player{
ID: entry.Instance,
IPs: entry.AddrIPv4,
Port: entry.Port,
})
}
searchedLen := len(opts.PlayerIDs)
if searchedLen == 0 {
addPlayer()
continue
}
if slices.Contains(opts.PlayerIDs, entry.Instance) {
addPlayer()
}
if searchedLen == len(players) {
break
}
}
done <- struct{}{}
}(entries)
err = resolver.Browse(ctx, server.MDNSService, server.MDNSDomain, entries)
if err != nil {
return nil, errors.WithStack(err)
}
select {
case <-done:
return players, nil
case <-ctx.Done():
if err := ctx.Err(); err != nil {
return players, errors.WithStack(err)
}
return players, nil
}
}