Skip to content

Commit 57ffceb

Browse files
authored
feat: add ability to provide interface list to advertise through zeroconf (#164)
* add ability to provide interface list to advertise throw zeroconf * 1. rename advertise parameter interfaces_to_advertise -> zeroconf_interfaces_to_advertise 2. add some documentation about new parameter * docs: Fix typo * docs: fix typo
1 parent 633b140 commit 57ffceb

File tree

4 files changed

+47
-27
lines changed

4 files changed

+47
-27
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ credentials:
7979
If `persist_credentials` is `true`, after connecting to the device for the first time credentials will be stored locally
8080
and you can switch to interactive mode without having to authenticate manually.
8181

82+
If `zeroconf_interfaces_to_advertise` is provided, you can limit interfaces that will be advertised. For example, if you have Docker installed on your host, you may want to disable advertising to its bridge interface, or you may want to disable interfaces that will not be reachable.
83+
8284
### Interactive mode
8385

8486
This mode allows you to associate your account with the device and make it discoverable even outside the network. It

cmd/daemon/main.go

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"encoding/json"
77
"errors"
88
"fmt"
9-
librespot "github.com/devgianlu/go-librespot"
109
"math"
1110
"net/http"
1211
"os"
@@ -15,6 +14,8 @@ import (
1514
"sync"
1615
"time"
1716

17+
librespot "github.com/devgianlu/go-librespot"
18+
1819
"github.com/devgianlu/go-librespot/apresolve"
1920
"github.com/devgianlu/go-librespot/player"
2021
devicespb "github.com/devgianlu/go-librespot/proto/spotify/connectstate/devices"
@@ -234,7 +235,7 @@ func (app *App) withAppPlayer(ctx context.Context, appPlayerFunc func(context.Co
234235
}
235236

236237
// start zeroconf server and dispatch
237-
z, err := zeroconf.NewZeroconf(app.log, app.cfg.ZeroconfPort, app.cfg.DeviceName, app.deviceId, app.deviceType)
238+
z, err := zeroconf.NewZeroconf(app.log, app.cfg.ZeroconfPort, app.cfg.DeviceName, app.deviceId, app.deviceType, app.cfg.ZeroconfInterfacesToAdvertise)
238239
if err != nil {
239240
return fmt.Errorf("failed initializing zeroconf: %w", err)
240241
}
@@ -361,29 +362,30 @@ type Config struct {
361362
// finalizer will run, probably closing the lock.
362363
configLock *flock.Flock
363364

364-
LogLevel log.Level `koanf:"log_level"`
365-
DeviceId string `koanf:"device_id"`
366-
DeviceName string `koanf:"device_name"`
367-
DeviceType string `koanf:"device_type"`
368-
ClientToken string `koanf:"client_token"`
369-
AudioBackend string `koanf:"audio_backend"`
370-
AudioDevice string `koanf:"audio_device"`
371-
MixerDevice string `koanf:"mixer_device"`
372-
MixerControlName string `koanf:"mixer_control_name"`
373-
AudioBufferTime int `koanf:"audio_buffer_time"`
374-
AudioPeriodCount int `koanf:"audio_period_count"`
375-
AudioOutputPipe string `koanf:"audio_output_pipe"`
376-
AudioOutputPipeFormat string `koanf:"audio_output_pipe_format"`
377-
Bitrate int `koanf:"bitrate"`
378-
VolumeSteps uint32 `koanf:"volume_steps"`
379-
InitialVolume uint32 `koanf:"initial_volume"`
380-
NormalisationDisabled bool `koanf:"normalisation_disabled"`
381-
NormalisationPregain float32 `koanf:"normalisation_pregain"`
382-
ExternalVolume bool `koanf:"external_volume"`
383-
ZeroconfEnabled bool `koanf:"zeroconf_enabled"`
384-
ZeroconfPort int `koanf:"zeroconf_port"`
385-
DisableAutoplay bool `koanf:"disable_autoplay"`
386-
Server struct {
365+
LogLevel log.Level `koanf:"log_level"`
366+
DeviceId string `koanf:"device_id"`
367+
DeviceName string `koanf:"device_name"`
368+
DeviceType string `koanf:"device_type"`
369+
ClientToken string `koanf:"client_token"`
370+
AudioBackend string `koanf:"audio_backend"`
371+
AudioDevice string `koanf:"audio_device"`
372+
MixerDevice string `koanf:"mixer_device"`
373+
MixerControlName string `koanf:"mixer_control_name"`
374+
AudioBufferTime int `koanf:"audio_buffer_time"`
375+
AudioPeriodCount int `koanf:"audio_period_count"`
376+
AudioOutputPipe string `koanf:"audio_output_pipe"`
377+
AudioOutputPipeFormat string `koanf:"audio_output_pipe_format"`
378+
Bitrate int `koanf:"bitrate"`
379+
VolumeSteps uint32 `koanf:"volume_steps"`
380+
InitialVolume uint32 `koanf:"initial_volume"`
381+
NormalisationDisabled bool `koanf:"normalisation_disabled"`
382+
NormalisationPregain float32 `koanf:"normalisation_pregain"`
383+
ExternalVolume bool `koanf:"external_volume"`
384+
ZeroconfEnabled bool `koanf:"zeroconf_enabled"`
385+
ZeroconfPort int `koanf:"zeroconf_port"`
386+
DisableAutoplay bool `koanf:"disable_autoplay"`
387+
ZeroconfInterfacesToAdvertise []string `koanf:"zeroconf_interfaces_to_advertise"`
388+
Server struct {
387389
Enabled bool `koanf:"enabled"`
388390
Address string `koanf:"address"`
389391
Port int `koanf:"port"`

config_schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,11 @@
155155
"description": "The port to use for the Zeroconf service (empty for random)",
156156
"default": 0
157157
},
158+
"zeroconf_interfaces_to_advertise": {
159+
"type": "array",
160+
"description": "List of network interfaces that will be advertised through zeroconf (empty to advertise all present interfaces)",
161+
"default": []
162+
},
158163
"credentials": {
159164
"type": "object",
160165
"properties": {

zeroconf/zeroconf.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ type NewUserRequest struct {
4646
result chan bool
4747
}
4848

49-
func NewZeroconf(log librespot.Logger, port int, deviceName, deviceId string, deviceType devicespb.DeviceType) (_ *Zeroconf, err error) {
49+
func NewZeroconf(log librespot.Logger, port int, deviceName, deviceId string, deviceType devicespb.DeviceType, interfacesToAdvertise []string) (_ *Zeroconf, err error) {
5050
z := &Zeroconf{log: log, deviceId: deviceId, deviceName: deviceName, deviceType: deviceType}
5151
z.reqsChan = make(chan NewUserRequest)
5252

@@ -63,7 +63,18 @@ func NewZeroconf(log librespot.Logger, port int, deviceName, deviceId string, de
6363
listenPort := z.listener.Addr().(*net.TCPAddr).Port
6464
log.Infof("zeroconf server listening on port %d", listenPort)
6565

66-
z.server, err = zeroconf.Register(deviceName, "_spotify-connect._tcp", "local.", listenPort, []string{"CPath=/", "VERSION=1.0", "Stack=SP"}, nil)
66+
var ifaces []net.Interface
67+
for _, ifaceName := range interfacesToAdvertise {
68+
liface, err := net.InterfaceByName(ifaceName)
69+
if err != nil {
70+
return nil, fmt.Errorf("failed to get info for network interface %s: %w", ifaceName, err)
71+
}
72+
73+
ifaces = append(ifaces, *liface)
74+
log.Info(fmt.Sprintf("advertising on network interface %s", ifaceName))
75+
}
76+
77+
z.server, err = zeroconf.Register(deviceName, "_spotify-connect._tcp", "local.", listenPort, []string{"CPath=/", "VERSION=1.0", "Stack=SP"}, ifaces)
6778
if err != nil {
6879
return nil, fmt.Errorf("failed registering zeroconf server: %w", err)
6980
}

0 commit comments

Comments
 (0)