diff --git a/client/client.go b/client/client.go
index d8c26639cfcc0bdfead3dd8e3f5b52c4a897ed3d..4393420e792c321d3c358c83c1b8be5edca97180 100644
--- a/client/client.go
+++ b/client/client.go
@@ -4,7 +4,7 @@ import (
 	"context"
 	"errors"
 
-	"github.com/golang/protobuf/proto"
+	"google.golang.org/protobuf/proto"
 	"go.etcd.io/etcd/client/v3"
 
 	"git.autistici.org/ale/autoradio"
diff --git a/client/config.go b/client/config.go
index 66fcdd465650604182a0e1a7806dd65d58112755..2fe8ca695ba7fcaa98f340825606733615eeb37a 100644
--- a/client/config.go
+++ b/client/config.go
@@ -8,7 +8,7 @@ import (
 	"git.autistici.org/ale/autoradio"
 	"git.autistici.org/ale/autoradio/coordination/watcher"
 	pb "git.autistici.org/ale/autoradio/proto"
-	"github.com/golang/protobuf/proto"
+	"google.golang.org/protobuf/proto"
 	"go.etcd.io/etcd/client/v3"
 )
 
diff --git a/coordination/election/election.go b/coordination/election/election.go
index 3cffc5a1d6651bc326cf2684270062c1ba92bb71..6578702aaf45132ddfb36db124736f409b46dc6b 100644
--- a/coordination/election/election.go
+++ b/coordination/election/election.go
@@ -2,14 +2,15 @@ package election
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"log"
 	"sync"
 	"time"
 
 	pb "git.autistici.org/ale/autoradio/proto"
-	"github.com/golang/protobuf/proto"
 	"go.etcd.io/etcd/client/v3/concurrency"
+	"google.golang.org/protobuf/proto"
 )
 
 // Op is a function that will be called when a node participating in
@@ -103,7 +104,7 @@ func (e *Election) Run(ctx context.Context, op Op) error {
 	}
 	for {
 		err := e.runOnce(ctx, string(data), op)
-		if err == context.Canceled {
+		if errors.Is(err, context.Canceled) {
 			return err
 		} else if err != nil {
 			log.Printf("election: %v", err)
diff --git a/coordination/presence/presence.go b/coordination/presence/presence.go
index 7bacc1b3ed0ec7fa945bf64b70f1e15ded4b7552..4ee4d131daacd1dd9a3f220b2150900ccaa81eda 100644
--- a/coordination/presence/presence.go
+++ b/coordination/presence/presence.go
@@ -8,7 +8,7 @@ import (
 	"strings"
 	"sync"
 
-	"github.com/golang/protobuf/proto"
+	"google.golang.org/protobuf/proto"
 	"go.etcd.io/etcd/client/v3"
 
 	"git.autistici.org/ale/autoradio/coordination/watcher"
diff --git a/coordination/presence/registration.go b/coordination/presence/registration.go
index 3185730b7917a46ff762a60faa2b3f97514ab33e..965133b3c649e903d3c7a229acd7e59e7f495e49 100644
--- a/coordination/presence/registration.go
+++ b/coordination/presence/registration.go
@@ -8,7 +8,7 @@ import (
 	"strings"
 
 	pb "git.autistici.org/ale/autoradio/proto"
-	"github.com/golang/protobuf/proto"
+	"google.golang.org/protobuf/proto"
 	"go.etcd.io/etcd/client/v3"
 	"go.etcd.io/etcd/client/v3/concurrency"
 )
diff --git a/go.mod b/go.mod
index bb1930fb604bf4f258557a35312f921b45007bbb..548a406d4523f570d22f652503bbbb6743d31265 100644
--- a/go.mod
+++ b/go.mod
@@ -7,7 +7,6 @@ require (
 	github.com/coreos/go-systemd/v22 v22.3.1 // indirect
 	github.com/elazarl/go-bindata-assetfs v1.0.1
 	github.com/gogo/protobuf v1.3.2 // indirect
-	github.com/golang/protobuf v1.5.2
 	github.com/google/subcommands v1.2.0
 	github.com/jmcvetta/randutil v0.0.0-20150817122601-2bb1b664bcff
 	github.com/lpar/gzipped v1.1.1-0.20190413023519-5d9a18ea7f47
@@ -23,4 +22,5 @@ require (
 	golang.org/x/sys v0.0.0-20210503080704-8803ae5d1324 // indirect
 	google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab // indirect
 	google.golang.org/grpc v1.37.0
+	google.golang.org/protobuf v1.26.0
 )
diff --git a/node/node_test.go b/node/node_test.go
index ad18b7425b604373a2790140bfafc7eb3996814f..23ded5a1c3f8ef076557d41db26055c1a09bab72 100644
--- a/node/node_test.go
+++ b/node/node_test.go
@@ -3,6 +3,7 @@ package node
 import (
 	"context"
 	"fmt"
+	"io/ioutil"
 	"log"
 	"net"
 	"net/http"
@@ -13,10 +14,10 @@ import (
 
 	"git.autistici.org/ale/autoradio"
 	pb "git.autistici.org/ale/autoradio/proto"
-	"github.com/golang/protobuf/proto"
 	"go.etcd.io/etcd/client/v3"
 	"go.etcd.io/etcd/client/v3/concurrency"
 	"go.etcd.io/etcd/server/v3/embed"
+	"google.golang.org/protobuf/proto"
 )
 
 type fakeIcecast struct{}
@@ -31,7 +32,7 @@ func (f *fakeIcecast) Update(_ context.Context, mounts []*pb.Mount, isMaster boo
 
 func createTestEtcd(t testing.TB) (*clientv3.Client, func()) {
 	cfg := embed.NewConfig()
-	cfg.Dir = "default.etcd"
+	cfg.Dir, _ = ioutil.TempDir("", "")
 
 	e, err := embed.StartEtcd(cfg)
 	if err != nil {
@@ -156,4 +157,5 @@ func TestNode_StatusPage(t *testing.T) {
 		t.Fatalf("http.Get(/player/) error: HTTP: %s", resp.Status)
 	}
 
+	cancel()
 }
diff --git a/node/status.go b/node/status.go
index 82e058cd2ec485a27efc81cae6ea77b74fb3a6b8..05913e5ad49344ea06b39e8875e811a419b51ec9 100644
--- a/node/status.go
+++ b/node/status.go
@@ -52,6 +52,8 @@ func withoutNode(nodes []*pb.Status, name string) []*pb.Status {
 }
 
 type statusManager struct {
+	pb.UnimplementedGossipServiceServer
+
 	peers *presence.EndpointSet
 	conns *util.ConnCache
 
diff --git a/proto/autoradio.go b/proto/autoradio.go
index ceaac6bf1d493a45ab2d4a3b570d4c0f1a9ff67c..7e07717048735016e6687fa64b0722d4256363a6 100644
--- a/proto/autoradio.go
+++ b/proto/autoradio.go
@@ -1,4 +1,4 @@
-package autoradio
+package proto
 
 import (
 	"errors"
diff --git a/proto/autoradio.pb.go b/proto/autoradio.pb.go
index 71bf7ed6665d25f77da1d2719efff417c6c1b9fc..0999ea7ddff524fad1400aa3a650dade7e0cce6a 100644
--- a/proto/autoradio.pb.go
+++ b/proto/autoradio.pb.go
@@ -1,227 +1,332 @@
+// Protobufs for objects that are stored in the database.
+
 // Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.26.0
+// 	protoc        v3.6.1
 // source: autoradio.proto
 
-package autoradio
+package proto
 
 import (
-	fmt "fmt"
-	proto "github.com/golang/protobuf/proto"
-	math "math"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
 
 type EncodingParams struct {
-	SourcePath           string   `protobuf:"bytes,1,opt,name=source_path,json=sourcePath,proto3" json:"source_path,omitempty"`
-	Format               string   `protobuf:"bytes,2,opt,name=format,proto3" json:"format,omitempty"`
-	BitRate              int32    `protobuf:"varint,3,opt,name=bit_rate,json=bitRate,proto3" json:"bit_rate,omitempty"`
-	SampleRate           int32    `protobuf:"varint,4,opt,name=sample_rate,json=sampleRate,proto3" json:"sample_rate,omitempty"`
-	Channels             int32    `protobuf:"varint,5,opt,name=channels,proto3" json:"channels,omitempty"`
-	StereoMode           string   `protobuf:"bytes,6,opt,name=stereo_mode,json=stereoMode,proto3" json:"stereo_mode,omitempty"`
-	Quality              float32  `protobuf:"fixed32,7,opt,name=quality,proto3" json:"quality,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
-
-func (m *EncodingParams) Reset()         { *m = EncodingParams{} }
-func (m *EncodingParams) String() string { return proto.CompactTextString(m) }
-func (*EncodingParams) ProtoMessage()    {}
-func (*EncodingParams) Descriptor() ([]byte, []int) {
-	return fileDescriptor_84874ab70d5ff1ed, []int{0}
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *EncodingParams) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_EncodingParams.Unmarshal(m, b)
+	SourcePath string  `protobuf:"bytes,1,opt,name=source_path,json=sourcePath,proto3" json:"source_path,omitempty"`
+	Format     string  `protobuf:"bytes,2,opt,name=format,proto3" json:"format,omitempty"`
+	BitRate    int32   `protobuf:"varint,3,opt,name=bit_rate,json=bitRate,proto3" json:"bit_rate,omitempty"`
+	SampleRate int32   `protobuf:"varint,4,opt,name=sample_rate,json=sampleRate,proto3" json:"sample_rate,omitempty"`
+	Channels   int32   `protobuf:"varint,5,opt,name=channels,proto3" json:"channels,omitempty"`
+	StereoMode string  `protobuf:"bytes,6,opt,name=stereo_mode,json=stereoMode,proto3" json:"stereo_mode,omitempty"`
+	Quality    float32 `protobuf:"fixed32,7,opt,name=quality,proto3" json:"quality,omitempty"`
 }
-func (m *EncodingParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_EncodingParams.Marshal(b, m, deterministic)
-}
-func (m *EncodingParams) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_EncodingParams.Merge(m, src)
+
+func (x *EncodingParams) Reset() {
+	*x = EncodingParams{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_autoradio_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *EncodingParams) XXX_Size() int {
-	return xxx_messageInfo_EncodingParams.Size(m)
+
+func (x *EncodingParams) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *EncodingParams) XXX_DiscardUnknown() {
-	xxx_messageInfo_EncodingParams.DiscardUnknown(m)
+
+func (*EncodingParams) ProtoMessage() {}
+
+func (x *EncodingParams) ProtoReflect() protoreflect.Message {
+	mi := &file_autoradio_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_EncodingParams proto.InternalMessageInfo
+// Deprecated: Use EncodingParams.ProtoReflect.Descriptor instead.
+func (*EncodingParams) Descriptor() ([]byte, []int) {
+	return file_autoradio_proto_rawDescGZIP(), []int{0}
+}
 
-func (m *EncodingParams) GetSourcePath() string {
-	if m != nil {
-		return m.SourcePath
+func (x *EncodingParams) GetSourcePath() string {
+	if x != nil {
+		return x.SourcePath
 	}
 	return ""
 }
 
-func (m *EncodingParams) GetFormat() string {
-	if m != nil {
-		return m.Format
+func (x *EncodingParams) GetFormat() string {
+	if x != nil {
+		return x.Format
 	}
 	return ""
 }
 
-func (m *EncodingParams) GetBitRate() int32 {
-	if m != nil {
-		return m.BitRate
+func (x *EncodingParams) GetBitRate() int32 {
+	if x != nil {
+		return x.BitRate
 	}
 	return 0
 }
 
-func (m *EncodingParams) GetSampleRate() int32 {
-	if m != nil {
-		return m.SampleRate
+func (x *EncodingParams) GetSampleRate() int32 {
+	if x != nil {
+		return x.SampleRate
 	}
 	return 0
 }
 
-func (m *EncodingParams) GetChannels() int32 {
-	if m != nil {
-		return m.Channels
+func (x *EncodingParams) GetChannels() int32 {
+	if x != nil {
+		return x.Channels
 	}
 	return 0
 }
 
-func (m *EncodingParams) GetStereoMode() string {
-	if m != nil {
-		return m.StereoMode
+func (x *EncodingParams) GetStereoMode() string {
+	if x != nil {
+		return x.StereoMode
 	}
 	return ""
 }
 
-func (m *EncodingParams) GetQuality() float32 {
-	if m != nil {
-		return m.Quality
+func (x *EncodingParams) GetQuality() float32 {
+	if x != nil {
+		return x.Quality
 	}
 	return 0
 }
 
 type Mount struct {
-	Path                 string          `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
-	SourceUsername       string          `protobuf:"bytes,2,opt,name=source_username,json=sourceUsername,proto3" json:"source_username,omitempty"`
-	SourcePassword       string          `protobuf:"bytes,3,opt,name=source_password,json=sourcePassword,proto3" json:"source_password,omitempty"`
-	RelayUrl             string          `protobuf:"bytes,4,opt,name=relay_url,json=relayUrl,proto3" json:"relay_url,omitempty"`
-	FallbackPath         string          `protobuf:"bytes,5,opt,name=fallback_path,json=fallbackPath,proto3" json:"fallback_path,omitempty"`
-	Transcode            bool            `protobuf:"varint,6,opt,name=transcode,proto3" json:"transcode,omitempty"`
-	TranscodeParams      *EncodingParams `protobuf:"bytes,7,opt,name=transcode_params,json=transcodeParams,proto3" json:"transcode_params,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}        `json:"-"`
-	XXX_unrecognized     []byte          `json:"-"`
-	XXX_sizecache        int32           `json:"-"`
-}
-
-func (m *Mount) Reset()         { *m = Mount{} }
-func (m *Mount) String() string { return proto.CompactTextString(m) }
-func (*Mount) ProtoMessage()    {}
-func (*Mount) Descriptor() ([]byte, []int) {
-	return fileDescriptor_84874ab70d5ff1ed, []int{1}
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *Mount) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_Mount.Unmarshal(m, b)
-}
-func (m *Mount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_Mount.Marshal(b, m, deterministic)
+	Path            string          `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
+	SourceUsername  string          `protobuf:"bytes,2,opt,name=source_username,json=sourceUsername,proto3" json:"source_username,omitempty"`
+	SourcePassword  string          `protobuf:"bytes,3,opt,name=source_password,json=sourcePassword,proto3" json:"source_password,omitempty"`
+	RelayUrl        string          `protobuf:"bytes,4,opt,name=relay_url,json=relayUrl,proto3" json:"relay_url,omitempty"`
+	FallbackPath    string          `protobuf:"bytes,5,opt,name=fallback_path,json=fallbackPath,proto3" json:"fallback_path,omitempty"`
+	Transcode       bool            `protobuf:"varint,6,opt,name=transcode,proto3" json:"transcode,omitempty"`
+	TranscodeParams *EncodingParams `protobuf:"bytes,7,opt,name=transcode_params,json=transcodeParams,proto3" json:"transcode_params,omitempty"`
 }
-func (m *Mount) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_Mount.Merge(m, src)
+
+func (x *Mount) Reset() {
+	*x = Mount{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_autoradio_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *Mount) XXX_Size() int {
-	return xxx_messageInfo_Mount.Size(m)
+
+func (x *Mount) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *Mount) XXX_DiscardUnknown() {
-	xxx_messageInfo_Mount.DiscardUnknown(m)
+
+func (*Mount) ProtoMessage() {}
+
+func (x *Mount) ProtoReflect() protoreflect.Message {
+	mi := &file_autoradio_proto_msgTypes[1]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_Mount proto.InternalMessageInfo
+// Deprecated: Use Mount.ProtoReflect.Descriptor instead.
+func (*Mount) Descriptor() ([]byte, []int) {
+	return file_autoradio_proto_rawDescGZIP(), []int{1}
+}
 
-func (m *Mount) GetPath() string {
-	if m != nil {
-		return m.Path
+func (x *Mount) GetPath() string {
+	if x != nil {
+		return x.Path
 	}
 	return ""
 }
 
-func (m *Mount) GetSourceUsername() string {
-	if m != nil {
-		return m.SourceUsername
+func (x *Mount) GetSourceUsername() string {
+	if x != nil {
+		return x.SourceUsername
 	}
 	return ""
 }
 
-func (m *Mount) GetSourcePassword() string {
-	if m != nil {
-		return m.SourcePassword
+func (x *Mount) GetSourcePassword() string {
+	if x != nil {
+		return x.SourcePassword
 	}
 	return ""
 }
 
-func (m *Mount) GetRelayUrl() string {
-	if m != nil {
-		return m.RelayUrl
+func (x *Mount) GetRelayUrl() string {
+	if x != nil {
+		return x.RelayUrl
 	}
 	return ""
 }
 
-func (m *Mount) GetFallbackPath() string {
-	if m != nil {
-		return m.FallbackPath
+func (x *Mount) GetFallbackPath() string {
+	if x != nil {
+		return x.FallbackPath
 	}
 	return ""
 }
 
-func (m *Mount) GetTranscode() bool {
-	if m != nil {
-		return m.Transcode
+func (x *Mount) GetTranscode() bool {
+	if x != nil {
+		return x.Transcode
 	}
 	return false
 }
 
-func (m *Mount) GetTranscodeParams() *EncodingParams {
-	if m != nil {
-		return m.TranscodeParams
+func (x *Mount) GetTranscodeParams() *EncodingParams {
+	if x != nil {
+		return x.TranscodeParams
 	}
 	return nil
 }
 
-func init() {
-	proto.RegisterType((*EncodingParams)(nil), "autoradio.EncodingParams")
-	proto.RegisterType((*Mount)(nil), "autoradio.Mount")
-}
-
-func init() { proto.RegisterFile("autoradio.proto", fileDescriptor_84874ab70d5ff1ed) }
-
-var fileDescriptor_84874ab70d5ff1ed = []byte{
-	// 329 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x92, 0xc1, 0x4e, 0xfa, 0x40,
-	0x10, 0xc6, 0x53, 0xfe, 0x14, 0xda, 0xe1, 0x2f, 0x98, 0x3d, 0x98, 0xa2, 0x26, 0x12, 0x3c, 0xc8,
-	0x89, 0x83, 0xbe, 0x82, 0x1e, 0x49, 0xc8, 0x26, 0x9c, 0x9b, 0x69, 0xbb, 0x48, 0xe3, 0x76, 0xb7,
-	0xee, 0x4e, 0x63, 0x78, 0x0e, 0x5f, 0xcf, 0x87, 0x31, 0x99, 0x96, 0x82, 0xb7, 0x7e, 0xbf, 0xef,
-	0x9b, 0xa6, 0xdf, 0x4c, 0x61, 0x86, 0x0d, 0x59, 0x87, 0x45, 0x69, 0xd7, 0xb5, 0xb3, 0x64, 0x45,
-	0xdc, 0x83, 0xe5, 0x4f, 0x00, 0xd3, 0x37, 0x93, 0xdb, 0xa2, 0x34, 0xef, 0x5b, 0x74, 0x58, 0x79,
-	0xf1, 0x00, 0x13, 0x6f, 0x1b, 0x97, 0xab, 0xb4, 0x46, 0x3a, 0x24, 0xc1, 0x22, 0x58, 0xc5, 0x12,
-	0x5a, 0xb4, 0x45, 0x3a, 0x88, 0x1b, 0x18, 0xed, 0xad, 0xab, 0x90, 0x92, 0x01, 0x7b, 0x9d, 0x12,
-	0x73, 0x88, 0xb2, 0x92, 0x52, 0x87, 0xa4, 0x92, 0x7f, 0x8b, 0x60, 0x15, 0xca, 0x71, 0x56, 0x92,
-	0x44, 0x52, 0xfc, 0x4e, 0xac, 0x6a, 0xad, 0x5a, 0x77, 0xc8, 0x2e, 0xb4, 0x88, 0x03, 0xb7, 0x10,
-	0xe5, 0x07, 0x34, 0x46, 0x69, 0x9f, 0x84, 0xec, 0xf6, 0x9a, 0x87, 0x49, 0x39, 0x65, 0xd3, 0xca,
-	0x16, 0x2a, 0x19, 0x75, 0x1f, 0xc4, 0x68, 0x63, 0x0b, 0x25, 0x12, 0x18, 0x7f, 0x36, 0xa8, 0x4b,
-	0x3a, 0x26, 0xe3, 0x45, 0xb0, 0x1a, 0xc8, 0x93, 0x5c, 0x7e, 0x0f, 0x20, 0xdc, 0xd8, 0xc6, 0x90,
-	0x10, 0x30, 0xbc, 0xa8, 0xc3, 0xcf, 0xe2, 0x09, 0x66, 0x5d, 0xd3, 0xc6, 0x2b, 0x67, 0xb0, 0x52,
-	0x5d, 0xa3, 0x69, 0x8b, 0x77, 0x1d, 0xbd, 0x08, 0xd6, 0xe8, 0xfd, 0x97, 0x75, 0x05, 0x17, 0xec,
-	0x83, 0xdb, 0x8e, 0x8a, 0x3b, 0x88, 0x9d, 0xd2, 0x78, 0x4c, 0x1b, 0xa7, 0xb9, 0x65, 0x2c, 0x23,
-	0x06, 0x3b, 0xa7, 0xc5, 0x23, 0x5c, 0xed, 0x51, 0xeb, 0x0c, 0xf3, 0x8f, 0x76, 0xb5, 0x21, 0x07,
-	0xfe, 0x9f, 0x20, 0x2f, 0xf7, 0x1e, 0x62, 0x72, 0x68, 0x7c, 0x7e, 0xaa, 0x1a, 0xc9, 0x33, 0x10,
-	0xaf, 0x70, 0xdd, 0x8b, 0xb4, 0xe6, 0x7b, 0x71, 0xe5, 0xc9, 0xf3, 0x7c, 0x7d, 0xbe, 0xf2, 0xdf,
-	0x83, 0xca, 0x59, 0x3f, 0xd2, 0x82, 0x6c, 0xc4, 0xbf, 0xc1, 0xcb, 0x6f, 0x00, 0x00, 0x00, 0xff,
-	0xff, 0x79, 0x82, 0xae, 0x17, 0x19, 0x02, 0x00, 0x00,
+var File_autoradio_proto protoreflect.FileDescriptor
+
+var file_autoradio_proto_rawDesc = []byte{
+	0x0a, 0x0f, 0x61, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x12, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x22, 0xdc, 0x01, 0x0a,
+	0x0e, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12,
+	0x1f, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x61, 0x74, 0x68,
+	0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x69, 0x74, 0x5f,
+	0x72, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x62, 0x69, 0x74, 0x52,
+	0x61, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x72, 0x61,
+	0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65,
+	0x52, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73,
+	0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73,
+	0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x65, 0x72, 0x65, 0x6f, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18,
+	0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x65, 0x72, 0x65, 0x6f, 0x4d, 0x6f, 0x64,
+	0x65, 0x12, 0x18, 0x0a, 0x07, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01,
+	0x28, 0x02, 0x52, 0x07, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x22, 0x93, 0x02, 0x0a, 0x05,
+	0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x6f, 0x75,
+	0x72, 0x63, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61,
+	0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x61, 0x73,
+	0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x6f, 0x75,
+	0x72, 0x63, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72,
+	0x65, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
+	0x72, 0x65, 0x6c, 0x61, 0x79, 0x55, 0x72, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x61, 0x6c, 0x6c,
+	0x62, 0x61, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x0c, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1c, 0x0a,
+	0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08,
+	0x52, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x44, 0x0a, 0x10, 0x74,
+	0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18,
+	0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x64, 0x69,
+	0x6f, 0x2e, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73,
+	0x52, 0x0f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d,
+	0x73, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x2e, 0x61, 0x75, 0x74, 0x69, 0x73, 0x74, 0x69,
+	0x63, 0x69, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x61, 0x6c, 0x65, 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x72,
+	0x61, 0x64, 0x69, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x33,
+}
+
+var (
+	file_autoradio_proto_rawDescOnce sync.Once
+	file_autoradio_proto_rawDescData = file_autoradio_proto_rawDesc
+)
+
+func file_autoradio_proto_rawDescGZIP() []byte {
+	file_autoradio_proto_rawDescOnce.Do(func() {
+		file_autoradio_proto_rawDescData = protoimpl.X.CompressGZIP(file_autoradio_proto_rawDescData)
+	})
+	return file_autoradio_proto_rawDescData
+}
+
+var file_autoradio_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_autoradio_proto_goTypes = []interface{}{
+	(*EncodingParams)(nil), // 0: autoradio.EncodingParams
+	(*Mount)(nil),          // 1: autoradio.Mount
+}
+var file_autoradio_proto_depIdxs = []int32{
+	0, // 0: autoradio.Mount.transcode_params:type_name -> autoradio.EncodingParams
+	1, // [1:1] is the sub-list for method output_type
+	1, // [1:1] is the sub-list for method input_type
+	1, // [1:1] is the sub-list for extension type_name
+	1, // [1:1] is the sub-list for extension extendee
+	0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_autoradio_proto_init() }
+func file_autoradio_proto_init() {
+	if File_autoradio_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_autoradio_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*EncodingParams); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_autoradio_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Mount); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_autoradio_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   2,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_autoradio_proto_goTypes,
+		DependencyIndexes: file_autoradio_proto_depIdxs,
+		MessageInfos:      file_autoradio_proto_msgTypes,
+	}.Build()
+	File_autoradio_proto = out.File
+	file_autoradio_proto_rawDesc = nil
+	file_autoradio_proto_goTypes = nil
+	file_autoradio_proto_depIdxs = nil
 }
diff --git a/proto/autoradio.proto b/proto/autoradio.proto
index 8202efdb94c24c29a0676e8b30ba402b3ebff970..744c8b112568b8a0aed718620715684cff8b5c5f 100644
--- a/proto/autoradio.proto
+++ b/proto/autoradio.proto
@@ -2,6 +2,8 @@
 
 syntax = "proto3";
 
+option go_package = "git.autistici.org/ale/autoradio/proto";
+
 package autoradio;
 
 message EncodingParams {
diff --git a/proto/presence.go b/proto/presence.go
index bc87f9b2cc6879eaa5539a2b126536c4b4328630..2fdb1b92722554a2a55a9bc42104d359a5ccbea3 100644
--- a/proto/presence.go
+++ b/proto/presence.go
@@ -1,4 +1,4 @@
-package autoradio
+package proto
 
 import (
 	"net"
diff --git a/proto/presence.pb.go b/proto/presence.pb.go
index 22ca0448de47ffc068f0d7690cc190e68e1e3d8d..a117ea60694071cff5dda0fbd871b139f063e7fb 100644
--- a/proto/presence.pb.go
+++ b/proto/presence.pb.go
@@ -1,85 +1,155 @@
+// Protobufs for ephemeral objects used for presence protocols.
+
 // Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.26.0
+// 	protoc        v3.6.1
 // source: presence.proto
 
-package autoradio
+package proto
 
 import (
-	fmt "fmt"
-	proto "github.com/golang/protobuf/proto"
-	math "math"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
 
 type Endpoint struct {
-	Name                 string   `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
-	Addrs                []string `protobuf:"bytes,2,rep,name=addrs,proto3" json:"addrs,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *Endpoint) Reset()         { *m = Endpoint{} }
-func (m *Endpoint) String() string { return proto.CompactTextString(m) }
-func (*Endpoint) ProtoMessage()    {}
-func (*Endpoint) Descriptor() ([]byte, []int) {
-	return fileDescriptor_09da13d0a6600b92, []int{0}
+	Name  string   `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+	Addrs []string `protobuf:"bytes,2,rep,name=addrs,proto3" json:"addrs,omitempty"`
 }
 
-func (m *Endpoint) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_Endpoint.Unmarshal(m, b)
-}
-func (m *Endpoint) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_Endpoint.Marshal(b, m, deterministic)
-}
-func (m *Endpoint) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_Endpoint.Merge(m, src)
+func (x *Endpoint) Reset() {
+	*x = Endpoint{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_presence_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *Endpoint) XXX_Size() int {
-	return xxx_messageInfo_Endpoint.Size(m)
+
+func (x *Endpoint) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *Endpoint) XXX_DiscardUnknown() {
-	xxx_messageInfo_Endpoint.DiscardUnknown(m)
+
+func (*Endpoint) ProtoMessage() {}
+
+func (x *Endpoint) ProtoReflect() protoreflect.Message {
+	mi := &file_presence_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_Endpoint proto.InternalMessageInfo
+// Deprecated: Use Endpoint.ProtoReflect.Descriptor instead.
+func (*Endpoint) Descriptor() ([]byte, []int) {
+	return file_presence_proto_rawDescGZIP(), []int{0}
+}
 
-func (m *Endpoint) GetName() string {
-	if m != nil {
-		return m.Name
+func (x *Endpoint) GetName() string {
+	if x != nil {
+		return x.Name
 	}
 	return ""
 }
 
-func (m *Endpoint) GetAddrs() []string {
-	if m != nil {
-		return m.Addrs
+func (x *Endpoint) GetAddrs() []string {
+	if x != nil {
+		return x.Addrs
 	}
 	return nil
 }
 
-func init() {
-	proto.RegisterType((*Endpoint)(nil), "autoradio.Endpoint")
+var File_presence_proto protoreflect.FileDescriptor
+
+var file_presence_proto_rawDesc = []byte{
+	0x0a, 0x0e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x12, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x22, 0x34, 0x0a, 0x08, 0x45,
+	0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61,
+	0x64, 0x64, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x61, 0x64, 0x64, 0x72,
+	0x73, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x2e, 0x61, 0x75, 0x74, 0x69, 0x73, 0x74, 0x69,
+	0x63, 0x69, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x61, 0x6c, 0x65, 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x72,
+	0x61, 0x64, 0x69, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x33,
+}
+
+var (
+	file_presence_proto_rawDescOnce sync.Once
+	file_presence_proto_rawDescData = file_presence_proto_rawDesc
+)
+
+func file_presence_proto_rawDescGZIP() []byte {
+	file_presence_proto_rawDescOnce.Do(func() {
+		file_presence_proto_rawDescData = protoimpl.X.CompressGZIP(file_presence_proto_rawDescData)
+	})
+	return file_presence_proto_rawDescData
+}
+
+var file_presence_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_presence_proto_goTypes = []interface{}{
+	(*Endpoint)(nil), // 0: autoradio.Endpoint
+}
+var file_presence_proto_depIdxs = []int32{
+	0, // [0:0] is the sub-list for method output_type
+	0, // [0:0] is the sub-list for method input_type
+	0, // [0:0] is the sub-list for extension type_name
+	0, // [0:0] is the sub-list for extension extendee
+	0, // [0:0] is the sub-list for field type_name
 }
 
-func init() { proto.RegisterFile("presence.proto", fileDescriptor_09da13d0a6600b92) }
-
-var fileDescriptor_09da13d0a6600b92 = []byte{
-	// 103 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2b, 0x28, 0x4a, 0x2d,
-	0x4e, 0xcd, 0x4b, 0x4e, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4c, 0x2c, 0x2d, 0xc9,
-	0x2f, 0x4a, 0x4c, 0xc9, 0xcc, 0x57, 0x32, 0xe1, 0xe2, 0x70, 0xcd, 0x4b, 0x29, 0xc8, 0xcf, 0xcc,
-	0x2b, 0x11, 0x12, 0xe2, 0x62, 0xc9, 0x4b, 0xcc, 0x4d, 0x95, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c,
-	0x02, 0xb3, 0x85, 0x44, 0xb8, 0x58, 0x13, 0x53, 0x52, 0x8a, 0x8a, 0x25, 0x98, 0x14, 0x98, 0x35,
-	0x38, 0x83, 0x20, 0x9c, 0x24, 0x36, 0xb0, 0x39, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4a,
-	0x50, 0xd1, 0x41, 0x59, 0x00, 0x00, 0x00,
+func init() { file_presence_proto_init() }
+func file_presence_proto_init() {
+	if File_presence_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_presence_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Endpoint); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_presence_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   1,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_presence_proto_goTypes,
+		DependencyIndexes: file_presence_proto_depIdxs,
+		MessageInfos:      file_presence_proto_msgTypes,
+	}.Build()
+	File_presence_proto = out.File
+	file_presence_proto_rawDesc = nil
+	file_presence_proto_goTypes = nil
+	file_presence_proto_depIdxs = nil
 }
diff --git a/proto/presence.proto b/proto/presence.proto
index e1a8963d2bff1604bf93a43e1d465fe29837315d..ffc5b2327e88e1ce76a32dc0dcdcded45c640f11 100644
--- a/proto/presence.proto
+++ b/proto/presence.proto
@@ -2,6 +2,8 @@
 
 syntax = "proto3";
 
+option go_package = "git.autistici.org/ale/autoradio/proto";
+
 package autoradio;
 
 message Endpoint {
diff --git a/proto/status.pb.go b/proto/status.pb.go
index 70556b331142fb18cbcc071569c23923902aef9d..fc46da4b1f8fa248817e4f32b965368be0ba4a83 100644
--- a/proto/status.pb.go
+++ b/proto/status.pb.go
@@ -1,420 +1,507 @@
+// Protobufs for objects that represent runtime status, and are
+// exchanged between processes over GRPC.
+
 // Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.26.0
+// 	protoc        v3.6.1
 // source: status.proto
 
-package autoradio
+package proto
 
 import (
-	context "context"
-	fmt "fmt"
-	proto "github.com/golang/protobuf/proto"
-	grpc "google.golang.org/grpc"
-	math "math"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
 
 type IcecastMount struct {
-	Path                 string   `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
-	Listeners            int32    `protobuf:"varint,2,opt,name=listeners,proto3" json:"listeners,omitempty"`
-	BitRate              int32    `protobuf:"varint,3,opt,name=bit_rate,json=bitRate,proto3" json:"bit_rate,omitempty"`
-	SampleRate           int32    `protobuf:"varint,4,opt,name=sample_rate,json=sampleRate,proto3" json:"sample_rate,omitempty"`
-	Quality              float32  `protobuf:"fixed32,5,opt,name=quality,proto3" json:"quality,omitempty"`
-	Channels             int32    `protobuf:"varint,6,opt,name=channels,proto3" json:"channels,omitempty"`
-	Artist               string   `protobuf:"bytes,7,opt,name=artist,proto3" json:"artist,omitempty"`
-	Title                string   `protobuf:"bytes,8,opt,name=title,proto3" json:"title,omitempty"`
-	Name                 string   `protobuf:"bytes,9,opt,name=name,proto3" json:"name,omitempty"`
-	Description          string   `protobuf:"bytes,10,opt,name=description,proto3" json:"description,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
-
-func (m *IcecastMount) Reset()         { *m = IcecastMount{} }
-func (m *IcecastMount) String() string { return proto.CompactTextString(m) }
-func (*IcecastMount) ProtoMessage()    {}
-func (*IcecastMount) Descriptor() ([]byte, []int) {
-	return fileDescriptor_dfe4fce6682daf5b, []int{0}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Path        string  `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
+	Listeners   int32   `protobuf:"varint,2,opt,name=listeners,proto3" json:"listeners,omitempty"`
+	BitRate     int32   `protobuf:"varint,3,opt,name=bit_rate,json=bitRate,proto3" json:"bit_rate,omitempty"`
+	SampleRate  int32   `protobuf:"varint,4,opt,name=sample_rate,json=sampleRate,proto3" json:"sample_rate,omitempty"`
+	Quality     float32 `protobuf:"fixed32,5,opt,name=quality,proto3" json:"quality,omitempty"`
+	Channels    int32   `protobuf:"varint,6,opt,name=channels,proto3" json:"channels,omitempty"`
+	Artist      string  `protobuf:"bytes,7,opt,name=artist,proto3" json:"artist,omitempty"`
+	Title       string  `protobuf:"bytes,8,opt,name=title,proto3" json:"title,omitempty"`
+	Name        string  `protobuf:"bytes,9,opt,name=name,proto3" json:"name,omitempty"`
+	Description string  `protobuf:"bytes,10,opt,name=description,proto3" json:"description,omitempty"`
+}
+
+func (x *IcecastMount) Reset() {
+	*x = IcecastMount{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_status_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
 
-func (m *IcecastMount) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_IcecastMount.Unmarshal(m, b)
-}
-func (m *IcecastMount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_IcecastMount.Marshal(b, m, deterministic)
-}
-func (m *IcecastMount) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_IcecastMount.Merge(m, src)
+func (x *IcecastMount) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *IcecastMount) XXX_Size() int {
-	return xxx_messageInfo_IcecastMount.Size(m)
-}
-func (m *IcecastMount) XXX_DiscardUnknown() {
-	xxx_messageInfo_IcecastMount.DiscardUnknown(m)
+
+func (*IcecastMount) ProtoMessage() {}
+
+func (x *IcecastMount) ProtoReflect() protoreflect.Message {
+	mi := &file_status_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_IcecastMount proto.InternalMessageInfo
+// Deprecated: Use IcecastMount.ProtoReflect.Descriptor instead.
+func (*IcecastMount) Descriptor() ([]byte, []int) {
+	return file_status_proto_rawDescGZIP(), []int{0}
+}
 
-func (m *IcecastMount) GetPath() string {
-	if m != nil {
-		return m.Path
+func (x *IcecastMount) GetPath() string {
+	if x != nil {
+		return x.Path
 	}
 	return ""
 }
 
-func (m *IcecastMount) GetListeners() int32 {
-	if m != nil {
-		return m.Listeners
+func (x *IcecastMount) GetListeners() int32 {
+	if x != nil {
+		return x.Listeners
 	}
 	return 0
 }
 
-func (m *IcecastMount) GetBitRate() int32 {
-	if m != nil {
-		return m.BitRate
+func (x *IcecastMount) GetBitRate() int32 {
+	if x != nil {
+		return x.BitRate
 	}
 	return 0
 }
 
-func (m *IcecastMount) GetSampleRate() int32 {
-	if m != nil {
-		return m.SampleRate
+func (x *IcecastMount) GetSampleRate() int32 {
+	if x != nil {
+		return x.SampleRate
 	}
 	return 0
 }
 
-func (m *IcecastMount) GetQuality() float32 {
-	if m != nil {
-		return m.Quality
+func (x *IcecastMount) GetQuality() float32 {
+	if x != nil {
+		return x.Quality
 	}
 	return 0
 }
 
-func (m *IcecastMount) GetChannels() int32 {
-	if m != nil {
-		return m.Channels
+func (x *IcecastMount) GetChannels() int32 {
+	if x != nil {
+		return x.Channels
 	}
 	return 0
 }
 
-func (m *IcecastMount) GetArtist() string {
-	if m != nil {
-		return m.Artist
+func (x *IcecastMount) GetArtist() string {
+	if x != nil {
+		return x.Artist
 	}
 	return ""
 }
 
-func (m *IcecastMount) GetTitle() string {
-	if m != nil {
-		return m.Title
+func (x *IcecastMount) GetTitle() string {
+	if x != nil {
+		return x.Title
 	}
 	return ""
 }
 
-func (m *IcecastMount) GetName() string {
-	if m != nil {
-		return m.Name
+func (x *IcecastMount) GetName() string {
+	if x != nil {
+		return x.Name
 	}
 	return ""
 }
 
-func (m *IcecastMount) GetDescription() string {
-	if m != nil {
-		return m.Description
+func (x *IcecastMount) GetDescription() string {
+	if x != nil {
+		return x.Description
 	}
 	return ""
 }
 
 type Status struct {
-	Name                 string          `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
-	Timestamp            uint64          `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	IcecastOk            bool            `protobuf:"varint,3,opt,name=icecast_ok,json=icecastOk,proto3" json:"icecast_ok,omitempty"`
-	IcecastMounts        []*IcecastMount `protobuf:"bytes,4,rep,name=icecast_mounts,json=icecastMounts,proto3" json:"icecast_mounts,omitempty"`
-	CurBandwidth         int32           `protobuf:"varint,5,opt,name=cur_bandwidth,json=curBandwidth,proto3" json:"cur_bandwidth,omitempty"`
-	MaxBandwidth         int32           `protobuf:"varint,6,opt,name=max_bandwidth,json=maxBandwidth,proto3" json:"max_bandwidth,omitempty"`
-	MaxListeners         int32           `protobuf:"varint,7,opt,name=max_listeners,json=maxListeners,proto3" json:"max_listeners,omitempty"`
-	NumListeners         int32           `protobuf:"varint,8,opt,name=num_listeners,json=numListeners,proto3" json:"num_listeners,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}        `json:"-"`
-	XXX_unrecognized     []byte          `json:"-"`
-	XXX_sizecache        int32           `json:"-"`
-}
-
-func (m *Status) Reset()         { *m = Status{} }
-func (m *Status) String() string { return proto.CompactTextString(m) }
-func (*Status) ProtoMessage()    {}
-func (*Status) Descriptor() ([]byte, []int) {
-	return fileDescriptor_dfe4fce6682daf5b, []int{1}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Name          string          `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+	Timestamp     uint64          `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	IcecastOk     bool            `protobuf:"varint,3,opt,name=icecast_ok,json=icecastOk,proto3" json:"icecast_ok,omitempty"`
+	IcecastMounts []*IcecastMount `protobuf:"bytes,4,rep,name=icecast_mounts,json=icecastMounts,proto3" json:"icecast_mounts,omitempty"`
+	CurBandwidth  int32           `protobuf:"varint,5,opt,name=cur_bandwidth,json=curBandwidth,proto3" json:"cur_bandwidth,omitempty"`
+	MaxBandwidth  int32           `protobuf:"varint,6,opt,name=max_bandwidth,json=maxBandwidth,proto3" json:"max_bandwidth,omitempty"`
+	MaxListeners  int32           `protobuf:"varint,7,opt,name=max_listeners,json=maxListeners,proto3" json:"max_listeners,omitempty"`
+	NumListeners  int32           `protobuf:"varint,8,opt,name=num_listeners,json=numListeners,proto3" json:"num_listeners,omitempty"`
+}
+
+func (x *Status) Reset() {
+	*x = Status{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_status_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
 
-func (m *Status) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_Status.Unmarshal(m, b)
-}
-func (m *Status) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_Status.Marshal(b, m, deterministic)
-}
-func (m *Status) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_Status.Merge(m, src)
+func (x *Status) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *Status) XXX_Size() int {
-	return xxx_messageInfo_Status.Size(m)
-}
-func (m *Status) XXX_DiscardUnknown() {
-	xxx_messageInfo_Status.DiscardUnknown(m)
+
+func (*Status) ProtoMessage() {}
+
+func (x *Status) ProtoReflect() protoreflect.Message {
+	mi := &file_status_proto_msgTypes[1]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_Status proto.InternalMessageInfo
+// Deprecated: Use Status.ProtoReflect.Descriptor instead.
+func (*Status) Descriptor() ([]byte, []int) {
+	return file_status_proto_rawDescGZIP(), []int{1}
+}
 
-func (m *Status) GetName() string {
-	if m != nil {
-		return m.Name
+func (x *Status) GetName() string {
+	if x != nil {
+		return x.Name
 	}
 	return ""
 }
 
-func (m *Status) GetTimestamp() uint64 {
-	if m != nil {
-		return m.Timestamp
+func (x *Status) GetTimestamp() uint64 {
+	if x != nil {
+		return x.Timestamp
 	}
 	return 0
 }
 
-func (m *Status) GetIcecastOk() bool {
-	if m != nil {
-		return m.IcecastOk
+func (x *Status) GetIcecastOk() bool {
+	if x != nil {
+		return x.IcecastOk
 	}
 	return false
 }
 
-func (m *Status) GetIcecastMounts() []*IcecastMount {
-	if m != nil {
-		return m.IcecastMounts
+func (x *Status) GetIcecastMounts() []*IcecastMount {
+	if x != nil {
+		return x.IcecastMounts
 	}
 	return nil
 }
 
-func (m *Status) GetCurBandwidth() int32 {
-	if m != nil {
-		return m.CurBandwidth
+func (x *Status) GetCurBandwidth() int32 {
+	if x != nil {
+		return x.CurBandwidth
 	}
 	return 0
 }
 
-func (m *Status) GetMaxBandwidth() int32 {
-	if m != nil {
-		return m.MaxBandwidth
+func (x *Status) GetMaxBandwidth() int32 {
+	if x != nil {
+		return x.MaxBandwidth
 	}
 	return 0
 }
 
-func (m *Status) GetMaxListeners() int32 {
-	if m != nil {
-		return m.MaxListeners
+func (x *Status) GetMaxListeners() int32 {
+	if x != nil {
+		return x.MaxListeners
 	}
 	return 0
 }
 
-func (m *Status) GetNumListeners() int32 {
-	if m != nil {
-		return m.NumListeners
+func (x *Status) GetNumListeners() int32 {
+	if x != nil {
+		return x.NumListeners
 	}
 	return 0
 }
 
 type ExchangeRequest struct {
-	Nodes                []*Status `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}  `json:"-"`
-	XXX_unrecognized     []byte    `json:"-"`
-	XXX_sizecache        int32     `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *ExchangeRequest) Reset()         { *m = ExchangeRequest{} }
-func (m *ExchangeRequest) String() string { return proto.CompactTextString(m) }
-func (*ExchangeRequest) ProtoMessage()    {}
-func (*ExchangeRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_dfe4fce6682daf5b, []int{2}
+	Nodes []*Status `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"`
 }
 
-func (m *ExchangeRequest) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_ExchangeRequest.Unmarshal(m, b)
-}
-func (m *ExchangeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_ExchangeRequest.Marshal(b, m, deterministic)
-}
-func (m *ExchangeRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_ExchangeRequest.Merge(m, src)
+func (x *ExchangeRequest) Reset() {
+	*x = ExchangeRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_status_proto_msgTypes[2]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *ExchangeRequest) XXX_Size() int {
-	return xxx_messageInfo_ExchangeRequest.Size(m)
+
+func (x *ExchangeRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *ExchangeRequest) XXX_DiscardUnknown() {
-	xxx_messageInfo_ExchangeRequest.DiscardUnknown(m)
+
+func (*ExchangeRequest) ProtoMessage() {}
+
+func (x *ExchangeRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_status_proto_msgTypes[2]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_ExchangeRequest proto.InternalMessageInfo
+// Deprecated: Use ExchangeRequest.ProtoReflect.Descriptor instead.
+func (*ExchangeRequest) Descriptor() ([]byte, []int) {
+	return file_status_proto_rawDescGZIP(), []int{2}
+}
 
-func (m *ExchangeRequest) GetNodes() []*Status {
-	if m != nil {
-		return m.Nodes
+func (x *ExchangeRequest) GetNodes() []*Status {
+	if x != nil {
+		return x.Nodes
 	}
 	return nil
 }
 
 type ExchangeResponse struct {
-	Nodes                []*Status `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}  `json:"-"`
-	XXX_unrecognized     []byte    `json:"-"`
-	XXX_sizecache        int32     `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *ExchangeResponse) Reset()         { *m = ExchangeResponse{} }
-func (m *ExchangeResponse) String() string { return proto.CompactTextString(m) }
-func (*ExchangeResponse) ProtoMessage()    {}
-func (*ExchangeResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_dfe4fce6682daf5b, []int{3}
+	Nodes []*Status `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"`
 }
 
-func (m *ExchangeResponse) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_ExchangeResponse.Unmarshal(m, b)
-}
-func (m *ExchangeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_ExchangeResponse.Marshal(b, m, deterministic)
-}
-func (m *ExchangeResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_ExchangeResponse.Merge(m, src)
-}
-func (m *ExchangeResponse) XXX_Size() int {
-	return xxx_messageInfo_ExchangeResponse.Size(m)
+func (x *ExchangeResponse) Reset() {
+	*x = ExchangeResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_status_proto_msgTypes[3]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *ExchangeResponse) XXX_DiscardUnknown() {
-	xxx_messageInfo_ExchangeResponse.DiscardUnknown(m)
+
+func (x *ExchangeResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
 
-var xxx_messageInfo_ExchangeResponse proto.InternalMessageInfo
+func (*ExchangeResponse) ProtoMessage() {}
 
-func (m *ExchangeResponse) GetNodes() []*Status {
-	if m != nil {
-		return m.Nodes
+func (x *ExchangeResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_status_proto_msgTypes[3]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
 	}
-	return nil
+	return mi.MessageOf(x)
 }
 
-func init() {
-	proto.RegisterType((*IcecastMount)(nil), "autoradio.IcecastMount")
-	proto.RegisterType((*Status)(nil), "autoradio.Status")
-	proto.RegisterType((*ExchangeRequest)(nil), "autoradio.ExchangeRequest")
-	proto.RegisterType((*ExchangeResponse)(nil), "autoradio.ExchangeResponse")
-}
-
-func init() { proto.RegisterFile("status.proto", fileDescriptor_dfe4fce6682daf5b) }
-
-var fileDescriptor_dfe4fce6682daf5b = []byte{
-	// 445 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0xcd, 0x8e, 0xd3, 0x30,
-	0x10, 0x26, 0xdd, 0xa6, 0x4d, 0xa6, 0x2d, 0x3f, 0x16, 0x02, 0x53, 0x16, 0x11, 0x65, 0x0f, 0xf4,
-	0xd4, 0xc3, 0x72, 0x03, 0x89, 0x03, 0xd2, 0x0a, 0x21, 0x81, 0x90, 0xbc, 0x12, 0xd7, 0xca, 0x4d,
-	0x2c, 0x6a, 0x6d, 0x62, 0x67, 0x33, 0x63, 0x28, 0x2f, 0xc2, 0x5b, 0xf0, 0x8e, 0x28, 0x76, 0x9b,
-	0x46, 0xc0, 0x61, 0x6f, 0xfe, 0x7e, 0xc6, 0xf1, 0x7c, 0x9f, 0x02, 0x73, 0x24, 0x49, 0x0e, 0xd7,
-	0x4d, 0x6b, 0xc9, 0xb2, 0x54, 0x3a, 0xb2, 0xad, 0x2c, 0xb5, 0xcd, 0x7f, 0x8d, 0x60, 0xfe, 0xb1,
-	0x50, 0x85, 0x44, 0xfa, 0x6c, 0x9d, 0x21, 0xc6, 0x60, 0xdc, 0x48, 0xda, 0xf1, 0x28, 0x8b, 0x56,
-	0xa9, 0xf0, 0x67, 0x76, 0x0e, 0x69, 0xa5, 0x91, 0x94, 0x51, 0x2d, 0xf2, 0x51, 0x16, 0xad, 0x62,
-	0x71, 0x22, 0xd8, 0x33, 0x48, 0xb6, 0x9a, 0x36, 0xad, 0x24, 0xc5, 0xcf, 0xbc, 0x38, 0xdd, 0x6a,
-	0x12, 0x92, 0x14, 0x7b, 0x09, 0x33, 0x94, 0x75, 0x53, 0xa9, 0xa0, 0x8e, 0xbd, 0x0a, 0x81, 0xf2,
-	0x06, 0x0e, 0xd3, 0x5b, 0x27, 0x2b, 0x4d, 0x3f, 0x79, 0x9c, 0x45, 0xab, 0x91, 0x38, 0x42, 0xb6,
-	0x84, 0xa4, 0xd8, 0x49, 0x63, 0x54, 0x85, 0x7c, 0xe2, 0xe7, 0x7a, 0xcc, 0x9e, 0xc0, 0x44, 0xb6,
-	0xa4, 0x91, 0xf8, 0xd4, 0xbf, 0xf2, 0x80, 0xd8, 0x63, 0x88, 0x49, 0x53, 0xa5, 0x78, 0xe2, 0xe9,
-	0x00, 0xba, 0x8d, 0x8c, 0xac, 0x15, 0x4f, 0xc3, 0x46, 0xdd, 0x99, 0x65, 0x30, 0x2b, 0x15, 0x16,
-	0xad, 0x6e, 0x48, 0x5b, 0xc3, 0xc1, 0x4b, 0x43, 0x2a, 0xff, 0x3d, 0x82, 0xc9, 0xb5, 0x0f, 0xad,
-	0xbf, 0x20, 0x1a, 0x5c, 0x70, 0x0e, 0x29, 0xe9, 0x5a, 0x21, 0xc9, 0xba, 0xf1, 0x91, 0x8c, 0xc5,
-	0x89, 0x60, 0x2f, 0x00, 0x74, 0x08, 0x75, 0x63, 0x6f, 0x7c, 0x28, 0x89, 0x48, 0x0f, 0xcc, 0x97,
-	0x1b, 0xf6, 0x0e, 0xee, 0x1f, 0xe5, 0xba, 0x0b, 0x1d, 0xf9, 0x38, 0x3b, 0x5b, 0xcd, 0x2e, 0x9f,
-	0xae, 0xfb, 0x62, 0xd6, 0xc3, 0x52, 0xc4, 0x42, 0x0f, 0x10, 0xb2, 0x0b, 0x58, 0x14, 0xae, 0xdd,
-	0x6c, 0xa5, 0x29, 0x7f, 0xe8, 0x92, 0x76, 0x3e, 0xbb, 0x58, 0xcc, 0x0b, 0xd7, 0xbe, 0x3f, 0x72,
-	0x9d, 0xa9, 0x96, 0xfb, 0x81, 0x29, 0xa4, 0x38, 0xaf, 0xe5, 0xfe, 0x1f, 0xd3, 0xa9, 0xdd, 0x69,
-	0x6f, 0xfa, 0xd4, 0x17, 0x7c, 0x01, 0x0b, 0xe3, 0xea, 0x81, 0x29, 0x09, 0x26, 0xe3, 0xea, 0xde,
-	0x94, 0xbf, 0x81, 0x07, 0x57, 0xfb, 0xae, 0xa1, 0x6f, 0x4a, 0xa8, 0x5b, 0xa7, 0x90, 0xd8, 0x2b,
-	0x88, 0x8d, 0x2d, 0x15, 0xf2, 0xc8, 0x6f, 0xf7, 0x68, 0xb0, 0x5d, 0x48, 0x56, 0x04, 0x3d, 0x7f,
-	0x0b, 0x0f, 0x4f, 0xb3, 0xd8, 0x58, 0x83, 0xea, 0xce, 0xc3, 0x97, 0x5f, 0x61, 0xf1, 0xc1, 0x22,
-	0xea, 0xe6, 0x5a, 0xb5, 0xdf, 0x75, 0xa1, 0xd8, 0x15, 0x24, 0xc7, 0xdb, 0xd8, 0x72, 0x30, 0xf6,
-	0xd7, 0xf3, 0x96, 0xcf, 0xff, 0xab, 0x85, 0xcf, 0xe7, 0xf7, 0xb6, 0x13, 0xff, 0xaf, 0xbc, 0xfe,
-	0x13, 0x00, 0x00, 0xff, 0xff, 0x7a, 0x9e, 0xa9, 0x9e, 0x3b, 0x03, 0x00, 0x00,
-}
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ context.Context
-var _ grpc.ClientConn
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the grpc package it is being compiled against.
-const _ = grpc.SupportPackageIsVersion4
-
-// GossipServiceClient is the client API for GossipService service.
-//
-// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
-type GossipServiceClient interface {
-	Exchange(ctx context.Context, in *ExchangeRequest, opts ...grpc.CallOption) (*ExchangeResponse, error)
-}
-
-type gossipServiceClient struct {
-	cc *grpc.ClientConn
-}
-
-func NewGossipServiceClient(cc *grpc.ClientConn) GossipServiceClient {
-	return &gossipServiceClient{cc}
-}
-
-func (c *gossipServiceClient) Exchange(ctx context.Context, in *ExchangeRequest, opts ...grpc.CallOption) (*ExchangeResponse, error) {
-	out := new(ExchangeResponse)
-	err := c.cc.Invoke(ctx, "/autoradio.GossipService/Exchange", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
+// Deprecated: Use ExchangeResponse.ProtoReflect.Descriptor instead.
+func (*ExchangeResponse) Descriptor() ([]byte, []int) {
+	return file_status_proto_rawDescGZIP(), []int{3}
 }
 
-// GossipServiceServer is the server API for GossipService service.
-type GossipServiceServer interface {
-	Exchange(context.Context, *ExchangeRequest) (*ExchangeResponse, error)
+func (x *ExchangeResponse) GetNodes() []*Status {
+	if x != nil {
+		return x.Nodes
+	}
+	return nil
 }
 
-func RegisterGossipServiceServer(s *grpc.Server, srv GossipServiceServer) {
-	s.RegisterService(&_GossipService_serviceDesc, srv)
-}
+var File_status_proto protoreflect.FileDescriptor
+
+var file_status_proto_rawDesc = []byte{
+	0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09,
+	0x61, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x22, 0x96, 0x02, 0x0a, 0x0c, 0x49, 0x63,
+	0x65, 0x63, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61,
+	0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1c,
+	0x0a, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x05, 0x52, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x19, 0x0a, 0x08,
+	0x62, 0x69, 0x74, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07,
+	0x62, 0x69, 0x74, 0x52, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x61, 0x6d, 0x70, 0x6c,
+	0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x61,
+	0x6d, 0x70, 0x6c, 0x65, 0x52, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x71, 0x75, 0x61, 0x6c,
+	0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x02, 0x52, 0x07, 0x71, 0x75, 0x61, 0x6c, 0x69,
+	0x74, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x06,
+	0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x16,
+	0x0a, 0x06, 0x61, 0x72, 0x74, 0x69, 0x73, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
+	0x61, 0x72, 0x74, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18,
+	0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04,
+	0x6e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+	0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18,
+	0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
+	0x6f, 0x6e, 0x22, 0xad, 0x02, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a,
+	0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12,
+	0x1d, 0x0a, 0x0a, 0x69, 0x63, 0x65, 0x63, 0x61, 0x73, 0x74, 0x5f, 0x6f, 0x6b, 0x18, 0x03, 0x20,
+	0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x63, 0x65, 0x63, 0x61, 0x73, 0x74, 0x4f, 0x6b, 0x12, 0x3e,
+	0x0a, 0x0e, 0x69, 0x63, 0x65, 0x63, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73,
+	0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x64,
+	0x69, 0x6f, 0x2e, 0x49, 0x63, 0x65, 0x63, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x52,
+	0x0d, 0x69, 0x63, 0x65, 0x63, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x23,
+	0x0a, 0x0d, 0x63, 0x75, 0x72, 0x5f, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x18,
+	0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69,
+	0x64, 0x74, 0x68, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x62, 0x61, 0x6e, 0x64, 0x77,
+	0x69, 0x64, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x42,
+	0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f,
+	0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52,
+	0x0c, 0x6d, 0x61, 0x78, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x23, 0x0a,
+	0x0d, 0x6e, 0x75, 0x6d, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x08,
+	0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65,
+	0x72, 0x73, 0x22, 0x3a, 0x0a, 0x0f, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01,
+	0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x64, 0x69, 0x6f,
+	0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3b,
+	0x0a, 0x10, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x12, 0x27, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
+	0x0b, 0x32, 0x11, 0x2e, 0x61, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x2e, 0x53, 0x74,
+	0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x32, 0x56, 0x0a, 0x0d, 0x47,
+	0x6f, 0x73, 0x73, 0x69, 0x70, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x45, 0x0a, 0x08,
+	0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1a, 0x2e, 0x61, 0x75, 0x74, 0x6f, 0x72,
+	0x61, 0x64, 0x69, 0x6f, 0x2e, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x61, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x64, 0x69, 0x6f,
+	0x2e, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x22, 0x00, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x2e, 0x61, 0x75, 0x74, 0x69, 0x73,
+	0x74, 0x69, 0x63, 0x69, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x61, 0x6c, 0x65, 0x2f, 0x61, 0x75, 0x74,
+	0x6f, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+	file_status_proto_rawDescOnce sync.Once
+	file_status_proto_rawDescData = file_status_proto_rawDesc
+)
 
-func _GossipService_Exchange_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(ExchangeRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(GossipServiceServer).Exchange(ctx, in)
+func file_status_proto_rawDescGZIP() []byte {
+	file_status_proto_rawDescOnce.Do(func() {
+		file_status_proto_rawDescData = protoimpl.X.CompressGZIP(file_status_proto_rawDescData)
+	})
+	return file_status_proto_rawDescData
+}
+
+var file_status_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
+var file_status_proto_goTypes = []interface{}{
+	(*IcecastMount)(nil),     // 0: autoradio.IcecastMount
+	(*Status)(nil),           // 1: autoradio.Status
+	(*ExchangeRequest)(nil),  // 2: autoradio.ExchangeRequest
+	(*ExchangeResponse)(nil), // 3: autoradio.ExchangeResponse
+}
+var file_status_proto_depIdxs = []int32{
+	0, // 0: autoradio.Status.icecast_mounts:type_name -> autoradio.IcecastMount
+	1, // 1: autoradio.ExchangeRequest.nodes:type_name -> autoradio.Status
+	1, // 2: autoradio.ExchangeResponse.nodes:type_name -> autoradio.Status
+	2, // 3: autoradio.GossipService.Exchange:input_type -> autoradio.ExchangeRequest
+	3, // 4: autoradio.GossipService.Exchange:output_type -> autoradio.ExchangeResponse
+	4, // [4:5] is the sub-list for method output_type
+	3, // [3:4] is the sub-list for method input_type
+	3, // [3:3] is the sub-list for extension type_name
+	3, // [3:3] is the sub-list for extension extendee
+	0, // [0:3] is the sub-list for field type_name
+}
+
+func init() { file_status_proto_init() }
+func file_status_proto_init() {
+	if File_status_proto != nil {
+		return
 	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/autoradio.GossipService/Exchange",
+	if !protoimpl.UnsafeEnabled {
+		file_status_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*IcecastMount); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_status_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Status); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_status_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ExchangeRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_status_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ExchangeResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
 	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(GossipServiceServer).Exchange(ctx, req.(*ExchangeRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-var _GossipService_serviceDesc = grpc.ServiceDesc{
-	ServiceName: "autoradio.GossipService",
-	HandlerType: (*GossipServiceServer)(nil),
-	Methods: []grpc.MethodDesc{
-		{
-			MethodName: "Exchange",
-			Handler:    _GossipService_Exchange_Handler,
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_status_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   4,
+			NumExtensions: 0,
+			NumServices:   1,
 		},
-	},
-	Streams:  []grpc.StreamDesc{},
-	Metadata: "status.proto",
+		GoTypes:           file_status_proto_goTypes,
+		DependencyIndexes: file_status_proto_depIdxs,
+		MessageInfos:      file_status_proto_msgTypes,
+	}.Build()
+	File_status_proto = out.File
+	file_status_proto_rawDesc = nil
+	file_status_proto_goTypes = nil
+	file_status_proto_depIdxs = nil
 }
diff --git a/proto/status.proto b/proto/status.proto
index c9a7af8da4720ae4072eaccdf559e84151c374ac..2feaf51d795e9511b6e2b975a4593aa0d496cc39 100644
--- a/proto/status.proto
+++ b/proto/status.proto
@@ -3,6 +3,8 @@
 
 syntax = "proto3";
 
+option go_package = "git.autistici.org/ale/autoradio/proto";
+
 package autoradio;
 
 message IcecastMount {
diff --git a/proto/status_grpc.pb.go b/proto/status_grpc.pb.go
new file mode 100644
index 0000000000000000000000000000000000000000..3cfdaa0f30303591df70ad3b191422fde28634e1
--- /dev/null
+++ b/proto/status_grpc.pb.go
@@ -0,0 +1,101 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+
+package proto
+
+import (
+	context "context"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+// GossipServiceClient is the client API for GossipService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type GossipServiceClient interface {
+	Exchange(ctx context.Context, in *ExchangeRequest, opts ...grpc.CallOption) (*ExchangeResponse, error)
+}
+
+type gossipServiceClient struct {
+	cc grpc.ClientConnInterface
+}
+
+func NewGossipServiceClient(cc grpc.ClientConnInterface) GossipServiceClient {
+	return &gossipServiceClient{cc}
+}
+
+func (c *gossipServiceClient) Exchange(ctx context.Context, in *ExchangeRequest, opts ...grpc.CallOption) (*ExchangeResponse, error) {
+	out := new(ExchangeResponse)
+	err := c.cc.Invoke(ctx, "/autoradio.GossipService/Exchange", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// GossipServiceServer is the server API for GossipService service.
+// All implementations must embed UnimplementedGossipServiceServer
+// for forward compatibility
+type GossipServiceServer interface {
+	Exchange(context.Context, *ExchangeRequest) (*ExchangeResponse, error)
+	mustEmbedUnimplementedGossipServiceServer()
+}
+
+// UnimplementedGossipServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedGossipServiceServer struct {
+}
+
+func (UnimplementedGossipServiceServer) Exchange(context.Context, *ExchangeRequest) (*ExchangeResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Exchange not implemented")
+}
+func (UnimplementedGossipServiceServer) mustEmbedUnimplementedGossipServiceServer() {}
+
+// UnsafeGossipServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to GossipServiceServer will
+// result in compilation errors.
+type UnsafeGossipServiceServer interface {
+	mustEmbedUnimplementedGossipServiceServer()
+}
+
+func RegisterGossipServiceServer(s grpc.ServiceRegistrar, srv GossipServiceServer) {
+	s.RegisterService(&GossipService_ServiceDesc, srv)
+}
+
+func _GossipService_Exchange_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ExchangeRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(GossipServiceServer).Exchange(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/autoradio.GossipService/Exchange",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(GossipServiceServer).Exchange(ctx, req.(*ExchangeRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+// GossipService_ServiceDesc is the grpc.ServiceDesc for GossipService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var GossipService_ServiceDesc = grpc.ServiceDesc{
+	ServiceName: "autoradio.GossipService",
+	HandlerType: (*GossipServiceServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "Exchange",
+			Handler:    _GossipService_Exchange_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "status.proto",
+}
diff --git a/transcoder/manager.go b/transcoder/manager.go
index 6daafb3deb9349dac3aa67b7be6e6662439685b8..0f592bcbbcc751eb6f3c660212b44f0f51de9192 100644
--- a/transcoder/manager.go
+++ b/transcoder/manager.go
@@ -5,7 +5,7 @@ import (
 
 	"git.autistici.org/ale/autoradio/client"
 	pb "git.autistici.org/ale/autoradio/proto"
-	"github.com/golang/protobuf/proto"
+	"google.golang.org/protobuf/proto"
 	"go.etcd.io/etcd/client/v3/concurrency"
 )
 
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 0095bbde3fe349658e1c72b8766e34703f8a6429..b974a971a587a26eac3ed7093bd02f5b04ed27b2 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -25,7 +25,6 @@ github.com/gogo/protobuf/protoc-gen-gogo/descriptor
 # github.com/golang/gddo v0.0.0-20190312205958-5a2505f3dbf0
 github.com/golang/gddo/httputil/header
 # github.com/golang/protobuf v1.5.2
-## explicit
 github.com/golang/protobuf/descriptor
 github.com/golang/protobuf/jsonpb
 github.com/golang/protobuf/proto
@@ -286,6 +285,7 @@ google.golang.org/grpc/stats
 google.golang.org/grpc/status
 google.golang.org/grpc/tap
 # google.golang.org/protobuf v1.26.0
+## explicit
 google.golang.org/protobuf/encoding/protojson
 google.golang.org/protobuf/encoding/prototext
 google.golang.org/protobuf/encoding/protowire