70 lines
1.3 KiB
Go
70 lines
1.3 KiB
Go
|
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
|
||
|
}
|
||
|
}
|