Skip to content

Commit 3a99415

Browse files
committed
feat: abstract Zeroconf discovery backend
1 parent 15a4f26 commit 3a99415

File tree

5 files changed

+71
-9
lines changed

5 files changed

+71
-9
lines changed

cmd/daemon/main.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,8 @@ func (app *App) withAppPlayer(ctx context.Context, appPlayerFunc func(context.Co
253253
DeviceId: app.deviceId,
254254
DeviceType: app.deviceType,
255255

256-
InterfacesToAdvertise: app.cfg.ZeroconfInterfacesToAdvertise,
256+
DiscoveryImplementation: app.cfg.ZeroconfImplementation,
257+
InterfacesToAdvertise: app.cfg.ZeroconfInterfacesToAdvertise,
257258
})
258259
if err != nil {
259260
return fmt.Errorf("failed initializing zeroconf: %w", err)
@@ -409,6 +410,7 @@ type Config struct {
409410
ZeroconfEnabled bool `koanf:"zeroconf_enabled"`
410411
ZeroconfPort int `koanf:"zeroconf_port"`
411412
DisableAutoplay bool `koanf:"disable_autoplay"`
413+
ZeroconfImplementation string `koanf:"zeroconf_implementation"`
412414
ZeroconfInterfacesToAdvertise []string `koanf:"zeroconf_interfaces_to_advertise"`
413415
MprisEnabled bool `koanf:"mpris_enabled"`
414416
Server struct {

config_schema.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,14 @@
165165
"description": "List of network interfaces that will be advertised through zeroconf (empty to advertise all present interfaces)",
166166
"default": []
167167
},
168+
"zeroconf_implementation": {
169+
"type": "string",
170+
"description": "The Zeroconf implementation to use",
171+
"enum": [
172+
"builtin"
173+
],
174+
"default": "builtin"
175+
},
168176
"credentials": {
169177
"type": "object",
170178
"properties": {

zeroconf/discovery/builtin.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package discovery
2+
3+
import (
4+
"net"
5+
6+
"github.com/grandcat/zeroconf"
7+
)
8+
9+
func init() {
10+
discoveryServices["builtin"] = &builtinDiscoveryService{}
11+
}
12+
13+
type builtinDiscoveryService struct {
14+
server *zeroconf.Server
15+
}
16+
17+
func (s *builtinDiscoveryService) Register(name, service, domain string, port int, txt []string, ifaces []net.Interface) (err error) {
18+
s.server, err = zeroconf.Register(name, service, domain, port, txt, ifaces)
19+
if err != nil {
20+
return err
21+
}
22+
return nil
23+
}
24+
25+
func (s *builtinDiscoveryService) Shutdown() {
26+
if s.server != nil {
27+
s.server.Shutdown()
28+
}
29+
}

zeroconf/discovery/impl.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package discovery
2+
3+
import "net"
4+
5+
type Service interface {
6+
Register(name, service, domain string, port int, txt []string, ifaces []net.Interface) error
7+
Shutdown()
8+
}
9+
10+
var discoveryServices = map[string]Service{}
11+
12+
func GetService(name string) Service {
13+
return discoveryServices[name]
14+
}

zeroconf/zeroconf.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
librespot "github.com/devgianlu/go-librespot"
1717
"github.com/devgianlu/go-librespot/dh"
1818
devicespb "github.com/devgianlu/go-librespot/proto/spotify/connectstate/devices"
19-
"github.com/grandcat/zeroconf"
19+
"github.com/devgianlu/go-librespot/zeroconf/discovery"
2020
log "github.com/sirupsen/logrus"
2121
)
2222

@@ -27,8 +27,8 @@ type Zeroconf struct {
2727
deviceId string
2828
deviceType devicespb.DeviceType
2929

30-
listener net.Listener
31-
server *zeroconf.Server
30+
listener net.Listener
31+
discovery discovery.Service
3232

3333
dh *dh.DiffieHellman
3434

@@ -88,9 +88,18 @@ func NewZeroconf(opts Options) (_ *Zeroconf, err error) {
8888
log.Info(fmt.Sprintf("advertising on network interface %s", ifaceName))
8989
}
9090

91-
z.server, err = zeroconf.Register(z.deviceName, "_spotify-connect._tcp", "local.", listenPort, []string{"CPath=/", "VERSION=1.0", "Stack=SP"}, ifaces)
92-
if err != nil {
93-
return nil, fmt.Errorf("failed registering zeroconf server: %w", err)
91+
discoveryImpl := opts.DiscoveryImplementation
92+
if discoveryImpl == "" {
93+
discoveryImpl = "builtin"
94+
}
95+
96+
z.discovery = discovery.GetService(discoveryImpl)
97+
if z.discovery == nil {
98+
return nil, fmt.Errorf("unknown discovery implementation: %s", discoveryImpl)
99+
}
100+
101+
if err := z.discovery.Register(z.deviceName, "_spotify-connect._tcp", "local.", listenPort, []string{"CPath=/", "VERSION=1.0", "Stack=SP"}, ifaces); err != nil {
102+
return nil, fmt.Errorf("failed registering zeroconf service: %w", err)
94103
}
95104

96105
return z, nil
@@ -105,7 +114,7 @@ func (z *Zeroconf) SetCurrentUser(username string) {
105114
// Close stops the zeroconf responder and HTTP listener,
106115
// but does not close the last opened session.
107116
func (z *Zeroconf) Close() {
108-
z.server.Shutdown()
117+
z.discovery.Shutdown()
109118
_ = z.listener.Close()
110119
}
111120

@@ -260,7 +269,7 @@ func (z *Zeroconf) handleAddUser(writer http.ResponseWriter, request *http.Reque
260269
type HandleNewRequestFunc func(req NewUserRequest) bool
261270

262271
func (z *Zeroconf) Serve(handler HandleNewRequestFunc) error {
263-
defer z.server.Shutdown()
272+
defer z.discovery.Shutdown()
264273

265274
mux := http.NewServeMux()
266275
mux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {

0 commit comments

Comments
 (0)