remove unnecessary configs
Kim committed
Oct 21, 2025 at 18:43 UTC
2c91f7c321641fe4dbe5e5ffaefdbac467ec935c
8 files changed
+193
-179
Makefile
+6
-12
@@ -17,15 +17,10 @@ server-build:
17
# ---------- Client (local go) ----------
18
# Default flags (override via `make VAR=value`)
19
SERVER_URL ?= http://localhost:8080
20
-BACKEND_HTTP ?= :8081
21
-# Optional repeated flags: BOOTSTRAPS="/dnsaddr/example/p2p/12D3... /ip4/1.2.3.4/tcp/4001/p2p/12D3..."
22
-BOOTSTRAPS ?=
23
-CLIENT_BOOTSTRAPS_FLAGS := $(foreach b,$(BOOTSTRAPS),--bootstrap $(b))
24
-
20
+BACKEND_PORT ?= 8081
21
CLIENT_FLAGS := \
22
--server-url $(SERVER_URL) \
27
- --backend-http $(BACKEND_HTTP) \
28
- $(CLIENT_BOOTSTRAPS_FLAGS)
23
+ --port $(BACKEND_PORT)
24
25
client-run:
26
go run ./cmd/example_http_client $(CLIENT_FLAGS)
@@ -34,14 +29,13 @@ client-build:
29
go build -trimpath -o bin/relaydns-client ./cmd/example_http_client
30
31
# ---------- Chat (local go) ----------
37
-CHAT_ADDR ?= :8091
32
+CHAT_PORT ?= 8091
33
CHAT_NAME ?= demo-chat
34
35
CHAT_FLAGS := \
36
--server-url $(SERVER_URL) \
42
- --addr $(CHAT_ADDR) \
43
- --name $(CHAT_NAME) \
44
- $(CLIENT_BOOTSTRAPS_FLAGS)
37
+ --port $(CHAT_PORT) \
38
+ --name $(CHAT_NAME)
39
40
chat-run:
41
go run ./cmd/example_chat $(CHAT_FLAGS)
@@ -66,4 +60,4 @@ help:
60
@echo " make chat-run # run example_chat locally (WS UI + advertiser)"
61
@echo " make chat-build # build example_chat to ./bin/relaydns-chat"
62
@echo "\nFlags (override with make VAR=value):"
69
- @echo " SERVER_URL BACKEND_HTTP BOOTSTRAPS CHAT_ADDR CHAT_NAME"
63
+ @echo " SERVER_URL BACKEND_PORT CHAT_PORT CHAT_NAME"
README.md
+6
-10
@@ -45,16 +45,14 @@ Clients are NOT required to run the server. They are provided for testing/demo.
45
```bash
46
make client-run
47
# Optional overrides:
48
- # make client-run BACKEND_HTTP=:8081 SERVER_URL=http://localhost:8080 \
49
- # BOOTSTRAPS="/dnsaddr/your.bootstrap/p2p/12D3Koo..."
48
+ # make client-run BACKEND_PORT=8081 SERVER_URL=http://localhost:8080
49
```
50
51
- Chat client (optional): WebSocket chat UI (local) + advertiser (libp2p). Uses coder/websocket.
52
```bash
53
make chat-run
54
# Optional overrides:
56
- # make chat-run CHAT_ADDR=:8091 CHAT_NAME=demo-chat SERVER_URL=http://localhost:8080 \
57
- # BOOTSTRAPS="/ip4/1.2.3.4/tcp/4001/p2p/12D3Koo..."
55
+ # make chat-run CHAT_PORT=8091 CHAT_NAME=demo-chat SERVER_URL=http://localhost:8080
56
```
57
58
If you run the chat client:
@@ -101,20 +99,18 @@ Server flags (see `docker-compose.yml`):
99
100
HTTP client flags (see `make client-run`):
101
- `--server-url` Admin base URL to fetch `/health` (default `http://localhost:8080`)
104
-- `--bootstrap` Repeatable multiaddr with `/p2p/`
105
-- `--backend-http` Local backend HTTP listen address (default `:8081`)
102
+- `--port` Local backend HTTP port (default `8081`)
103
104
Chat client flags (see `make chat-run`):
105
- `--server-url` Admin base URL to fetch `/health` (default `http://localhost:8080`)
109
-- `--bootstrap` Repeatable multiaddr with `/p2p/`
110
-- `--addr` Local chat HTTP listen address (default `:8091`)
106
+- `--port` Local chat HTTP port (default `8091`)
107
- `--name` Display name (shown on server UI)
108
109
## Deploying the Server (public)
110
111
- Expose ports:
116
- - `8080/tcp` Admin UI + HTTP/WS proxy (`/peer/<peerID>/`)
117
- - `4001/tcp` and `4001/udp` libp2p (GossipSub/streams)
112
+ - `8080/tcp` Admin UI + HTTP/WS proxy (`/peer/<peerID>/`) — flag: `--http-port`
113
+ - `4001/tcp` and `4001/udp` libp2p (GossipSub/streams) — flag: `--p2p-port`
114
- Cloudflare DNS:
115
- Web UI/proxy (8080): can be proxied (orange cloud) if using HTTP/HTTPS
116
- libp2p (4001 tcp/udp): must be DNS only (gray cloud). Cloudflare proxy doesn’t support arbitrary TCP/UDP ports.
cmd/example_chat/main.go
+10
-21
@@ -22,22 +22,16 @@ var rootCmd = &cobra.Command{
22
}
23
24
var (
25
- flagServerURL string
26
- flagBootstraps []string
27
- flagAddr string
28
- flagName string
29
- flagProtocol string
30
- flagTopic string
25
+ flagServerURL string
26
+ flagPort int
27
+ flagName string
28
)
29
30
func init() {
31
flags := rootCmd.PersistentFlags()
32
flags.StringVar(&flagServerURL, "server-url", "http://localhost:8080", "relayserver base URL to auto-fetch multiaddrs from /health")
36
- flags.StringSliceVar(&flagBootstraps, "bootstrap", nil, "multiaddrs with /p2p/ (supports /dnsaddr/ that resolves to /p2p/)")
37
- flags.StringVar(&flagAddr, "addr", ":8091", "local chat HTTP listen address")
33
+ flags.IntVar(&flagPort, "port", 8091, "local chat HTTP port")
34
flags.StringVar(&flagName, "name", "demo-chat", "backend display name")
39
- flags.StringVar(&flagProtocol, "protocol", "/relaydns/http/1.0", "libp2p protocol id for streams (must match server)")
40
- flags.StringVar(&flagTopic, "topic", "relaydns.backends", "pubsub topic for backend adverts")
35
}
36
37
func main() {
@@ -51,7 +45,7 @@ func runChat(cmd *cobra.Command, args []string) error {
45
defer cancel()
46
47
// 1) start local chat HTTP backend
54
- ln, err := net.Listen("tcp", flagAddr)
48
+ ln, err := net.Listen("tcp", fmt.Sprintf(":%d", flagPort))
49
if err != nil {
50
return fmt.Errorf("listen chat: %w", err)
51
}
@@ -70,17 +64,12 @@ func runChat(cmd *cobra.Command, args []string) error {
64
65
// 2) advertise over RelayDNS (HTTP tunneled via server /peer route)
66
client, err := relaydns.NewClient(ctx, relaydns.ClientConfig{
73
- Protocol: flagProtocol,
74
- Topic: flagTopic,
75
- AdvertiseEvery: 3 * time.Second,
76
- Name: flagName,
77
- TargetTCP: relaydns.AddrToTarget(flagAddr),
67
+ Name: flagName,
68
+ TargetTCP: relaydns.AddrToTarget(fmt.Sprintf(":%d", flagPort)),
69
+ ServerURL: flagServerURL,
70
79
- ServerURL: flagServerURL,
80
- Bootstraps: flagBootstraps,
81
- HTTPTimeout: 5 * time.Second,
82
- PreferQUIC: true,
83
- PreferLocal: true,
71
+ Protocol: relaydns.DefaultProtocol,
72
+ Topic: relaydns.DefaultTopic,
73
})
74
if err != nil {
75
return fmt.Errorf("new client: %w", err)
cmd/example_http_client/main.go
+14
-25
@@ -22,22 +22,16 @@ var rootCmd = &cobra.Command{
22
}
23
24
var (
25
- flagServerURL string
26
- flagBootstraps []string
27
- flagAddr string
28
- flagClientName string
29
- flagProtocol string
30
- flagTopic string
25
+ flagServerURL string
26
+ flagPort int
27
+ flagName string
28
)
29
30
func init() {
31
flags := rootCmd.PersistentFlags()
32
flags.StringVar(&flagServerURL, "server-url", "http://localhost:8080", "relayserver admin base URL to auto-fetch multiaddrs from /health")
36
- flags.StringSliceVar(&flagBootstraps, "bootstrap", nil, "multiaddrs with /p2p/ (supports /dnsaddr/ that resolves to /p2p/)")
37
- flags.StringVar(&flagAddr, "addr", ":8081", "local backend HTTP listen address")
38
- flags.StringVar(&flagClientName, "name", "", "backend display name shown on server UI")
39
- flags.StringVar(&flagProtocol, "protocol", "/relaydns/http/1.0", "libp2p protocol id for streams (must match server)")
40
- flags.StringVar(&flagTopic, "topic", "relaydns.backends", "pubsub topic for backend adverts")
33
+ flags.IntVar(&flagPort, "port", 8081, "local backend HTTP port")
34
+ flags.StringVar(&flagName, "name", "", "backend display name shown on server UI")
35
}
36
37
func main() {
@@ -50,24 +44,24 @@ func runClient(cmd *cobra.Command, args []string) error {
44
ctx, cancel := context.WithCancel(context.Background())
45
defer cancel()
46
53
- if flagClientName == "" {
47
+ if flagName == "" {
48
hn, err := os.Hostname()
49
if err != nil {
50
hn = "unknown-" + rand.Text()
51
}
58
- flagClientName = hn
52
+ flagName = hn
53
}
54
55
// 1) HTTP backend
56
var clientRef *relaydns.RelayClient
63
- ln, err := net.Listen("tcp", flagAddr)
57
+ ln, err := net.Listen("tcp", fmt.Sprintf(":%d", flagPort))
58
if err != nil {
59
log.Fatal().Err(err).Msg("failed to listen")
60
}
61
log.Info().Msgf("[client] local backend http listening on %s", ln.Addr().String())
62
63
// Serve local backend view in a goroutine
70
- go serveClientHTTP(ctx, ln, flagClientName, func() string {
64
+ go serveClientHTTP(ctx, ln, flagName, func() string {
65
if clientRef == nil {
66
return "Starting..."
67
}
@@ -76,17 +70,12 @@ func runClient(cmd *cobra.Command, args []string) error {
70
71
// 2) libp2p host
72
client, err := relaydns.NewClient(ctx, relaydns.ClientConfig{
79
- Protocol: flagProtocol,
80
- Topic: flagTopic,
81
- AdvertiseEvery: 3 * time.Second,
82
- Name: flagClientName,
83
- TargetTCP: relaydns.AddrToTarget(flagAddr),
73
+ Name: flagName,
74
+ TargetTCP: relaydns.AddrToTarget(fmt.Sprintf(":%d", flagPort)),
75
+ ServerURL: flagServerURL,
76
85
- ServerURL: flagServerURL,
86
- Bootstraps: flagBootstraps,
87
- HTTPTimeout: 5 * time.Second,
88
- PreferQUIC: true,
89
- PreferLocal: true,
77
+ Protocol: relaydns.DefaultProtocol,
78
+ Topic: relaydns.DefaultTopic,
79
})
80
if err != nil {
81
return fmt.Errorf("new client: %w", err)
cmd/server/main.go
+12
-20
@@ -2,6 +2,7 @@ package main
2
3
import (
4
"context"
5
+ "fmt"
6
"net"
7
"os"
8
"os/signal"
@@ -20,22 +21,16 @@ var rootCmd = &cobra.Command{
21
}
22
23
var (
23
- flagBootstraps []string
24
-
25
- httpAddr string // unified admin + HTTP proxy (e.g. :8080)
26
- protocol string
27
- topic string
28
- tcpAddr string // optional raw TCP ingress (e.g. :2222 for SSH)
24
+ flagP2pPort int // libp2p outbound TCP/UDP port (e.g. 4001)
25
+ flagHttpPort int // admin UI + HTTP proxy port (e.g. 8080)
26
+ flagTcpPort int // optional raw TCP ingress port (0 to disable)
27
)
28
29
func init() {
30
flags := rootCmd.PersistentFlags()
33
- flags.StringSliceVar(&flagBootstraps, "bootstrap", nil, "multiaddrs with /p2p/ (supports /dnsaddr/ that resolves to /p2p/)")
34
-
35
- flags.StringVar(&httpAddr, "http", ":8080", "Unified admin UI and HTTP proxy listen address")
36
- flags.StringVar(&protocol, "protocol", "/relaydns/http/1.0", "libp2p protocol id for streams (must match clients)")
37
- flags.StringVar(&topic, "topic", "relaydns.backends", "pubsub topic for backend adverts")
38
- flags.StringVar(&tcpAddr, "tcp", "", "Optional raw TCP ingress (e.g. :2222 for SSH). Empty to disable")
31
+ flags.IntVar(&flagHttpPort, "http-port", 8080, "admin UI and HTTP proxy port")
32
+ flags.IntVar(&flagP2pPort, "p2p-port", 4001, "libp2p outbound TCP/UDP port")
33
+ flags.IntVar(&flagTcpPort, "tcp-port", 0, "optional raw TCP ingress port (0 to disable)")
34
}
35
36
func main() {
@@ -48,24 +43,21 @@ func runServer(cmd *cobra.Command, args []string) error {
43
ctx, cancel := context.WithCancel(context.Background())
44
defer cancel()
45
51
- const outBoundPort = 4001
52
- h, err := relaydns.MakeHost(ctx, outBoundPort, true)
46
+ h, err := relaydns.MakeHost(ctx, flagP2pPort, true)
47
if err != nil {
48
return err
49
}
56
- relaydns.ConnectBootstraps(ctx, h, flagBootstraps)
57
-
58
- d, err := relaydns.NewRelayServer(ctx, h, protocol, topic)
50
+ d, err := relaydns.NewRelayServer(ctx, h, relaydns.DefaultProtocol, relaydns.DefaultTopic)
51
if err != nil {
52
return err
53
}
54
55
// Admin UI + per-peer HTTP proxy served here
64
- go serveHTTP(ctx, httpAddr, d, h, cancel)
56
+ go serveHTTP(ctx, fmt.Sprintf(":%d", flagHttpPort), d, h, cancel)
57
58
// Optional raw TCP ingress (e.g., SSH)
67
- if tcpAddr != "" {
68
- go serveTCPIngress(ctx, tcpAddr, d)
59
+ if flagTcpPort > 0 {
60
+ go serveTCPIngress(ctx, fmt.Sprintf(":%d", flagTcpPort), d)
61
}
62
63
// graceful shutdown
docker-compose.yml
+4
-5
@@ -7,11 +7,10 @@ services:
7
dockerfile: Dockerfile
8
image: dreamcacao/relaydns:latest
9
command:
10
- - "--http"
11
- - ":8080"
12
- # To add bootstraps, add more lines like below (repeatable):
13
- # - "--bootstrap"
14
- # - "/dnsaddr/bootstrap.example/p2p/12D3Koo..."
10
+ - "--http-port"
11
+ - "8080"
12
+ - "--p2p-port"
13
+ - "4001"
14
ports:
15
- "8080:8080" # Admin UI + HTTP proxy
16
- "4001:4001/tcp" # libp2p tcp
relaydns/client.go
+130
-81
@@ -58,27 +58,43 @@ type RelayClient struct {
58
serverHealthy bool
59
}
60
61
-// NewClient constructs a client with defaults applied and an initialized libp2p host.
62
-// It does not start networking. Call Start(ctx) to begin handlers, pubsub, and advertising.
63
-func NewClient(ctx context.Context, cfg ClientConfig) (*RelayClient, error) {
61
+// sensible defaults for optional client config
62
+const (
63
+ defaultAdvertiseEvery = 5 * time.Second
64
+ defaultHTTPTimeout = 3 * time.Second
65
+ defaultRefreshBootstraps = 20 * time.Second
66
+)
67
+
68
+// applyDefaults fills zero-values in cfg with sane defaults.
69
+func applyDefaults(cfg ClientConfig) ClientConfig {
70
if cfg.AdvertiseEvery <= 0 {
65
- cfg.AdvertiseEvery = 5 * time.Second
71
+ cfg.AdvertiseEvery = defaultAdvertiseEvery
72
}
73
if cfg.AdvertiseTTL <= 0 {
74
cfg.AdvertiseTTL = 10 * cfg.AdvertiseEvery
75
}
76
if cfg.HTTPTimeout <= 0 {
71
- cfg.HTTPTimeout = 3 * time.Second
72
- }
73
- if cfg.RefreshBootstrapsEvery <= 0 {
74
- cfg.RefreshBootstrapsEvery = 20 * time.Second
75
- }
76
- if cfg.Protocol == "" {
77
- cfg.Protocol = "/relaydns/http/1.0"
77
+ cfg.HTTPTimeout = defaultHTTPTimeout
78
}
79
+ if cfg.RefreshBootstrapsEvery <= 0 {
80
+ cfg.RefreshBootstrapsEvery = defaultRefreshBootstraps
81
+ }
82
+ // Always prefer QUIC and local addresses for better performance and locality.
83
+ cfg.PreferQUIC = true
84
+ cfg.PreferLocal = true
85
+ if cfg.Protocol == "" {
86
+ cfg.Protocol = DefaultProtocol
87
+ }
88
if cfg.Topic == "" {
80
- cfg.Topic = "relaydns.backends"
89
+ cfg.Topic = DefaultTopic
90
}
91
+ return cfg
92
+}
93
+
94
+// NewClient constructs a client with defaults applied and an initialized libp2p host.
95
+// It does not start networking. Call Start(ctx) to begin handlers, pubsub, and advertising.
96
+func NewClient(ctx context.Context, cfg ClientConfig) (*RelayClient, error) {
97
+ cfg = applyDefaults(cfg)
98
99
h, err := MakeHost(ctx, 0, true)
100
if err != nil {
@@ -97,7 +113,68 @@ func (b *RelayClient) Start(ctx context.Context) error {
113
if b.stop != nil {
114
return fmt.Errorf("client already started")
115
}
100
- // resolve bootstraps (from flags and optional server health)
116
+ // 1) resolve bootstraps (flags + optional server health)
117
+ boot := b.resolveBootstraps()
118
+ if len(boot) > 0 {
119
+ ConnectBootstraps(ctx, b.h, boot)
120
+ } else {
121
+ log.Warn().Msg("relaydns: no bootstrap sources provided (Bootstraps/ServerURL); discovery may fail")
122
+ }
123
+
124
+ // 2) stream handler for inbound libp2p streams
125
+ if err := b.setupStreamHandler(); err != nil {
126
+ return err
127
+ }
128
+
129
+ // 3) pubsub join (for adverts)
130
+ if err := b.joinPubSub(ctx); err != nil {
131
+ return err
132
+ }
133
+
134
+ // 4) advertiser loop
135
+ advCtx, cancel := context.WithCancel(ctx)
136
+ b.stop = cancel
137
+ b.wg.Add(1)
138
+ b.startAdvertiser(advCtx)
139
+
140
+ // 5) background: periodically re-fetch bootstraps from server and reconnect
141
+ if b.cfg.ServerURL != "" {
142
+ b.startRefreshLoop(advCtx)
143
+ }
144
+
145
+ if addrs := BuildAddrs(b.Host()); len(addrs) > 0 {
146
+ for _, s := range addrs {
147
+ log.Info().Msgf("[client] host addr: %s", s)
148
+ }
149
+ } else {
150
+ log.Info().Msgf("[client] host peer: %s (no listen addrs yet)", b.Host().ID().String())
151
+ }
152
+
153
+ return nil
154
+}
155
+
156
+func (b *RelayClient) Host() host.Host {
157
+ return b.h
158
+}
159
+
160
+func (b *RelayClient) Close() error {
161
+ if b.stop != nil {
162
+ b.stop()
163
+ }
164
+ b.wg.Wait()
165
+ // leaving topic is optional; libp2p will clean up on host close
166
+ return nil
167
+}
168
+
169
+func (b *RelayClient) setServerHealthy(ok bool) {
170
+ b.statusMu.Lock()
171
+ b.serverHealthy = ok
172
+ b.statusMu.Unlock()
173
+}
174
+
175
+// resolveBootstraps merges configured bootstraps with optional server-provided
176
+// multiaddrs from /health. It updates serverHealthy accordingly.
177
+func (b *RelayClient) resolveBootstraps() []string {
178
boot := make([]string, 0, len(b.cfg.Bootstraps)+4)
179
if len(b.cfg.Bootstraps) > 0 {
180
boot = append(boot, b.cfg.Bootstraps...)
@@ -112,14 +189,11 @@ func (b *RelayClient) Start(ctx context.Context) error {
189
boot = append(boot, addrs...)
190
}
191
}
115
- boot = uniq(boot)
116
- if len(boot) > 0 {
117
- ConnectBootstraps(ctx, b.h, boot)
118
- } else {
119
- log.Warn().Msg("relaydns: no bootstrap sources provided (Bootstraps/ServerURL); discovery may fail")
120
- }
192
+ return uniq(boot)
193
+}
194
122
- // stream handler
195
+// setupStreamHandler installs the appropriate libp2p stream handler.
196
+func (b *RelayClient) setupStreamHandler() error {
197
switch {
198
case b.cfg.Handler != nil:
199
b.h.SetStreamHandler(b.protoID, b.cfg.Handler)
@@ -139,8 +213,11 @@ func (b *RelayClient) Start(ctx context.Context) error {
213
default:
214
return fmt.Errorf("relaydns: either Handler or TargetTCP must be set")
215
}
216
+ return nil
217
+}
218
143
- // pubsub join
219
+// joinPubSub creates a GossipSub instance and joins the advert topic.
220
+func (b *RelayClient) joinPubSub(ctx context.Context) error {
221
ps, err := pubsub.NewGossipSub(ctx, b.h, pubsub.WithMessageSigning(true))
222
if err != nil {
223
return err
@@ -150,10 +227,11 @@ func (b *RelayClient) Start(ctx context.Context) error {
227
return err
228
}
229
b.ps, b.t = ps, t
230
+ return nil
231
+}
232
154
- // advertiser loop
155
- advCtx, cancel := context.WithCancel(ctx)
156
- b.stop = cancel
233
+// startAdvertiser periodically publishes Advertise messages with host addrs.
234
+func (b *RelayClient) startAdvertiser(ctx context.Context) {
235
b.wg.Add(1)
236
go func() {
237
defer b.wg.Done()
@@ -161,7 +239,7 @@ func (b *RelayClient) Start(ctx context.Context) error {
239
defer ticker.Stop()
240
for {
241
select {
164
- case <-advCtx.Done():
242
+ case <-ctx.Done():
243
return
244
case <-ticker.C:
245
enc := BuildAddrs(b.h)
@@ -177,69 +255,40 @@ func (b *RelayClient) Start(ctx context.Context) error {
255
Proto: string(b.protoID),
256
}
257
payload, _ := json.Marshal(ad)
180
- _ = b.t.Publish(advCtx, payload)
258
+ _ = b.t.Publish(ctx, payload)
259
}
260
}
261
}()
262
+}
263
185
- // background: periodically re-fetch bootstraps from server and reconnect
186
- if b.cfg.ServerURL != "" {
187
- b.wg.Add(1)
188
- go func() {
189
- defer b.wg.Done()
190
- t := time.NewTicker(b.cfg.RefreshBootstrapsEvery)
191
- defer t.Stop()
192
- for {
193
- select {
194
- case <-advCtx.Done():
195
- return
196
- case <-t.C:
197
- addrs, err := fetchMultiaddrsFromHealth(b.cfg.ServerURL, b.cfg.HTTPTimeout)
198
- if err != nil {
199
- b.setServerHealthy(false)
200
- log.Warn().Err(err).Msgf("refresh /health from %s failed", b.cfg.ServerURL)
201
- continue
202
- }
203
- b.setServerHealthy(true)
204
- sortMultiaddrs(addrs, b.cfg.PreferQUIC, b.cfg.PreferLocal)
205
- addrs = uniq(addrs)
206
- if len(addrs) > 0 {
207
- // Always attempt (re)connect; ConnectBootstraps handles dedupe and quiet logging
208
- ConnectBootstraps(ctx, b.h, addrs)
209
- }
264
+// startRefreshLoop periodically fetches /health and attempts (re)connects.
265
+func (b *RelayClient) startRefreshLoop(ctx context.Context) {
266
+ b.wg.Add(1)
267
+ go func() {
268
+ defer b.wg.Done()
269
+ t := time.NewTicker(b.cfg.RefreshBootstrapsEvery)
270
+ defer t.Stop()
271
+ for {
272
+ select {
273
+ case <-ctx.Done():
274
+ return
275
+ case <-t.C:
276
+ addrs, err := fetchMultiaddrsFromHealth(b.cfg.ServerURL, b.cfg.HTTPTimeout)
277
+ if err != nil {
278
+ b.setServerHealthy(false)
279
+ log.Warn().Err(err).Msgf("refresh /health from %s failed", b.cfg.ServerURL)
280
+ continue
281
+ }
282
+ b.setServerHealthy(true)
283
+ sortMultiaddrs(addrs, b.cfg.PreferQUIC, b.cfg.PreferLocal)
284
+ addrs = uniq(addrs)
285
+ if len(addrs) > 0 {
286
+ // Always attempt (re)connect; ConnectBootstraps handles dedupe and quiet logging
287
+ ConnectBootstraps(ctx, b.h, addrs)
288
}
289
}
212
- }()
213
- }
214
-
215
- if addrs := BuildAddrs(b.Host()); len(addrs) > 0 {
216
- for _, s := range addrs {
217
- log.Info().Msgf("[client] host addr: %s", s)
290
}
219
- } else {
220
- log.Info().Msgf("[client] host peer: %s (no listen addrs yet)", b.Host().ID().String())
221
- }
222
-
223
- return nil
224
-}
225
-
226
-func (b *RelayClient) Host() host.Host {
227
- return b.h
228
-}
229
-
230
-func (b *RelayClient) Close() error {
231
- if b.stop != nil {
232
- b.stop()
233
- }
234
- b.wg.Wait()
235
- // leaving topic is optional; libp2p will clean up on host close
236
- return nil
237
-}
238
-
239
-func (b *RelayClient) setServerHealthy(ok bool) {
240
- b.statusMu.Lock()
241
- b.serverHealthy = ok
242
- b.statusMu.Unlock()
291
+ }()
292
}
293
294
// ServerStatus returns a human-friendly status regarding connection to ServerURL.
relaydns/types.go
+11
-5
@@ -1,15 +1,21 @@
1
package relaydns
2
3
import (
4
- "time"
4
+ "time"
5
6
- "github.com/libp2p/go-libp2p/core/peer"
6
+ "github.com/libp2p/go-libp2p/core/peer"
7
+)
8
+
9
+// Defaults shared by server and client.
10
+const (
11
+ DefaultProtocol = "/relaydns/http/1.0"
12
+ DefaultTopic = "relaydns.backends"
13
)
14
15
type Advertise struct {
10
- Peer string `json:"peer"`
11
- Name string `json:"name,omitempty"`
12
- DNS string `json:"dns,omitempty"`
16
+ Peer string `json:"peer"`
17
+ Name string `json:"name,omitempty"`
18
+ DNS string `json:"dns,omitempty"`
19
Addrs []string `json:"addrs"`
20
Ready bool `json:"ready"`
21
Load float64 `json:"load"`