host: add fallback in connectBootstrap

Kim committed Oct 22, 2025 at 09:50 UTC 9ce554057260d88efde3afcfd2916337cad9adb3
6 files changed +65 -14
cmd/example_chat/main.go
+2 -2
@@ -28,9 +28,9 @@ var (
28
29 func init() {
30 flags := rootCmd.PersistentFlags()
31 - flags.StringVar(&flagServerURL, "server-url", "http://localhost:8080", "relayserver base URL to auto-fetch multiaddrs from /health")
31 + flags.StringVar(&flagServerURL, "server-url", "http://relaydns.gosuda.org", "relayserver base URL to auto-fetch multiaddrs from /health")
32 flags.IntVar(&flagPort, "port", 8091, "local chat HTTP port")
33 - flags.StringVar(&flagName, "name", "demo-chat", "backend display name")
33 + flags.StringVar(&flagName, "name", "bangjang-chat", "backend display name")
34 }
35
36 func main() {
cmd/example_http_client/main.go
+2 -2
@@ -29,9 +29,9 @@ var (
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")
32 + flags.StringVar(&flagServerURL, "server-url", "http://relaydns.gosuda.org", "relayserver admin base URL to auto-fetch multiaddrs from /health")
33 flags.IntVar(&flagPort, "port", 8081, "local backend HTTP port")
34 - flags.StringVar(&flagName, "name", "", "backend display name shown on server UI")
34 + flags.StringVar(&flagName, "name", "bangjang-backend", "backend display name shown on server UI")
35 }
36
37 func main() {
go.mod
+1
@@ -3,6 +3,7 @@ module github.com/gosuda/relaydns
3 go 1.25.0
4
5 require (
6 + github.com/cockroachdb/crlib v0.0.0-20251001180057-2a49e1873587
7 github.com/coder/websocket v1.8.14
8 github.com/libp2p/go-libp2p v0.44.0
9 github.com/libp2p/go-libp2p-pubsub v0.15.0
go.sum
+2
@@ -19,6 +19,8 @@ github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7
19 github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
20 github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
21 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
22 +github.com/cockroachdb/crlib v0.0.0-20251001180057-2a49e1873587 h1:qjG2TrBrPbGRVYp5obcAi8OSsuFJ8s1AElDImHLV9tY=
23 +github.com/cockroachdb/crlib v0.0.0-20251001180057-2a49e1873587/go.mod h1:ae57yNis2F1FThSNdPdoXfiPOVi8G1TLreCBQYPOdqo=
24 github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g=
25 github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg=
26 github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
relaydns/host.go
+40 -10
@@ -40,8 +40,10 @@ func MakeHost(ctx context.Context, port int, enableRelay bool) (host.Host, error
40 }
41
42 func ConnectBootstraps(ctx context.Context, h host.Host, addrs []string) {
43 - // Connect once per unique peer ID; skip already-connected peers to avoid noisy logs.
44 - seen := make(map[string]struct{}, len(addrs))
43 + // Aggregate all multiaddrs per peer and dial them together so the dialer
44 + // can fall back from loopback to routable addresses.
45 + perPeer := make(map[peer.ID][]ma.Multiaddr)
46 +
47 for _, s := range addrs {
48 m, err := ma.NewMultiaddr(s)
49 if err != nil {
@@ -53,19 +55,47 @@ func ConnectBootstraps(ctx context.Context, h host.Host, addrs []string) {
55 log.Warn().Err(err).Msgf("bootstrap missing /p2p/ in %q", s)
56 continue
57 }
56 - pid := ai.ID.String()
57 - if _, ok := seen[pid]; ok {
58 + // Prefer the addr(s) returned by AddrInfoFromP2pAddr (base part without /p2p)
59 + bases := ai.Addrs
60 + if len(bases) == 0 {
61 + // Fallback: try to decapsulate /p2p component manually
62 + dec := m
63 + // Construct a /p2p/<peerID> multiaddr for decapsulation
64 + p2pComp, derr := ma.NewMultiaddr(fmt.Sprintf("/p2p/%s", ai.ID.String()))
65 + if derr == nil {
66 + dec = m.Decapsulate(p2pComp)
67 + }
68 + if dec != nil && dec.String() != "" {
69 + bases = []ma.Multiaddr{dec}
70 + }
71 + }
72 + if len(bases) == 0 {
73 continue
74 }
60 - seen[pid] = struct{}{}
75 + // Append while de-duplicating per peer, preserving original order.
76 + cur := perPeer[ai.ID]
77 + seen := make(map[string]struct{}, len(cur))
78 + for _, a := range cur {
79 + seen[a.String()] = struct{}{}
80 + }
81 + for _, a := range bases {
82 + if _, ok := seen[a.String()]; ok {
83 + continue
84 + }
85 + cur = append(cur, a)
86 + seen[a.String()] = struct{}{}
87 + }
88 + perPeer[ai.ID] = cur
89 + }
90
62 - if h.Network().Connectedness(ai.ID) == network.Connected {
63 - // Already connected: skip loudly logging.
91 + // Now attempt a single connect per peer with all known addresses.
92 + for pid, maddrs := range perPeer {
93 + if h.Network().Connectedness(pid) == network.Connected {
94 continue
95 }
66 - if err := h.Connect(ctx, *ai); err != nil {
67 - // Only warn on errors
68 - log.Warn().Err(err).Msgf("bootstrap connect %s", ai.ID)
96 + info := peer.AddrInfo{ID: pid, Addrs: maddrs}
97 + if err := h.Connect(ctx, info); err != nil {
98 + log.Warn().Err(err).Msgf("bootstrap connect %s", pid)
99 }
100 }
101 }
relaydns/utils_test.go new
+18
@@ -0,0 +1,18 @@
1 +package relaydns
2 +
3 +import (
4 + "fmt"
5 + "testing"
6 + "time"
7 +
8 + "github.com/cockroachdb/crlib/testutils/require"
9 +)
10 +
11 +func TestFetchMultiAddrsFromHosts(t *testing.T) {
12 + url := "http://relaydns.gosuda.org"
13 + timeout := 5 * time.Second
14 +
15 + addrs, err := fetchMultiaddrsFromHosts(url, timeout)
16 + require.NoError(t, err)
17 + fmt.Println(addrs)
18 +}