fix: deadlock on retrieving WebTransport addresses (#9857)
Co-authored-by: Marco Polo <git@marcopolo.io>
Henrique Dias committed
May 8, 2023 at 16:11 UTC
8684f05ef376f5971b8df6f67e9aaddccdba5bed
9 files changed
+48
-42
core/mock/mock.go
+10
-1
@@ -34,7 +34,16 @@ func NewMockNode() (*core.IpfsNode, error) {
34
}
35
36
func MockHostOption(mn mocknet.Mocknet) libp2p2.HostOption {
37
- return func(id peer.ID, ps pstore.Peerstore, _ ...libp2p.Option) (host.Host, error) {
37
+ return func(id peer.ID, ps pstore.Peerstore, opts ...libp2p.Option) (host.Host, error) {
38
+ var cfg libp2p.Config
39
+ if err := cfg.Apply(opts...); err != nil {
40
+ return nil, err
41
+ }
42
+
43
+ // The mocknet does not use the provided libp2p.Option. This options include
44
+ // the listening addresses we want our peer listening on. Therefore, we have
45
+ // to manually parse the configuration and add them here.
46
+ ps.AddAddrs(id, cfg.ListenAddrs, pstore.PermanentAddrTTL)
47
return mn.AddPeerWithPeerstore(id, ps)
48
}
49
}
core/node/groups.go
+1
-1
@@ -155,7 +155,7 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part
155
fx.Provide(libp2p.RelayTransport(enableRelayTransport)),
156
fx.Provide(libp2p.RelayService(enableRelayService, cfg.Swarm.RelayService)),
157
fx.Provide(libp2p.Transports(cfg.Swarm.Transports)),
158
- fx.Invoke(libp2p.StartListening(cfg.Addresses.Swarm)),
158
+ fx.Provide(libp2p.ListenOn(cfg.Addresses.Swarm)),
159
fx.Invoke(libp2p.SetupDiscovery(cfg.Discovery.MDNS.Enabled)),
160
fx.Provide(libp2p.ForceReachability(cfg.Internal.Libp2pForceReachability)),
161
fx.Provide(libp2p.HolePunching(cfg.Swarm.EnableHolePunching, enableRelayClient)),
core/node/libp2p/addrs.go
+6
-32
@@ -4,7 +4,6 @@ import (
4
"fmt"
5
6
"github.com/libp2p/go-libp2p"
7
- "github.com/libp2p/go-libp2p/core/host"
7
p2pbhost "github.com/libp2p/go-libp2p/p2p/host/basic"
8
ma "github.com/multiformats/go-multiaddr"
9
mamask "github.com/whyrusleeping/multiaddr-filter"
@@ -99,37 +98,12 @@ func AddrsFactory(announce []string, appendAnnouce []string, noAnnounce []string
98
}
99
}
100
102
-func listenAddresses(addresses []string) ([]ma.Multiaddr, error) {
103
- listen := make([]ma.Multiaddr, len(addresses))
104
- for i, addr := range addresses {
105
- maddr, err := ma.NewMultiaddr(addr)
106
- if err != nil {
107
- return nil, fmt.Errorf("failure to parse config.Addresses.Swarm: %s", addresses)
108
- }
109
- listen[i] = maddr
110
- }
111
-
112
- return listen, nil
113
-}
114
-
115
-func StartListening(addresses []string) func(host host.Host) error {
116
- return func(host host.Host) error {
117
- listenAddrs, err := listenAddresses(addresses)
118
- if err != nil {
119
- return err
120
- }
121
-
122
- // Actually start listening:
123
- if err := host.Network().Listen(listenAddrs...); err != nil {
124
- return err
125
- }
126
-
127
- // list out our addresses
128
- addrs, err := host.Network().InterfaceListenAddresses()
129
- if err != nil {
130
- return err
101
+func ListenOn(addresses []string) interface{} {
102
+ return func() (opts Libp2pOpts) {
103
+ return Libp2pOpts{
104
+ Opts: []libp2p.Option{
105
+ libp2p.ListenAddrStrings(addresses...),
106
+ },
107
}
132
- log.Infof("Swarm listening at: %s", addrs)
133
- return nil
108
}
109
}
docs/examples/kubo-as-a-library/go.mod
+1
-1
@@ -9,7 +9,7 @@ replace github.com/ipfs/kubo => ./../../..
9
require (
10
github.com/ipfs/boxo v0.8.1
11
github.com/ipfs/kubo v0.0.0-00010101000000-000000000000
12
- github.com/libp2p/go-libp2p v0.27.1
12
+ github.com/libp2p/go-libp2p v0.27.2
13
github.com/multiformats/go-multiaddr v0.9.0
14
)
15
docs/examples/kubo-as-a-library/go.sum
+2
-2
@@ -489,8 +489,8 @@ github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZ
489
github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs=
490
github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
491
github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro=
492
-github.com/libp2p/go-libp2p v0.27.1 h1:k1u6RHsX3hqKnslDjsSgLNURxJ3O1atIZCY4gpMbbus=
493
-github.com/libp2p/go-libp2p v0.27.1/go.mod h1:FAvvfQa/YOShUYdiSS03IR9OXzkcJXwcNA2FUCh9ImE=
492
+github.com/libp2p/go-libp2p v0.27.2 h1:I1fxqxdm/O0TFoAZKje8wSMu9tfLlLdzTQvgT3HA6v0=
493
+github.com/libp2p/go-libp2p v0.27.2/go.mod h1:FAvvfQa/YOShUYdiSS03IR9OXzkcJXwcNA2FUCh9ImE=
494
github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s=
495
github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w=
496
github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g=
go.mod
+1
-1
@@ -45,7 +45,7 @@ require (
45
github.com/jbenet/goprocess v0.1.4
46
github.com/julienschmidt/httprouter v1.3.0
47
github.com/libp2p/go-doh-resolver v0.4.0
48
- github.com/libp2p/go-libp2p v0.27.1
48
+ github.com/libp2p/go-libp2p v0.27.2
49
github.com/libp2p/go-libp2p-http v0.5.0
50
github.com/libp2p/go-libp2p-kad-dht v0.23.0
51
github.com/libp2p/go-libp2p-kbucket v0.5.0
go.sum
+2
-2
@@ -540,8 +540,8 @@ github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZ
540
github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs=
541
github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
542
github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro=
543
-github.com/libp2p/go-libp2p v0.27.1 h1:k1u6RHsX3hqKnslDjsSgLNURxJ3O1atIZCY4gpMbbus=
544
-github.com/libp2p/go-libp2p v0.27.1/go.mod h1:FAvvfQa/YOShUYdiSS03IR9OXzkcJXwcNA2FUCh9ImE=
543
+github.com/libp2p/go-libp2p v0.27.2 h1:I1fxqxdm/O0TFoAZKje8wSMu9tfLlLdzTQvgT3HA6v0=
544
+github.com/libp2p/go-libp2p v0.27.2/go.mod h1:FAvvfQa/YOShUYdiSS03IR9OXzkcJXwcNA2FUCh9ImE=
545
github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s=
546
github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w=
547
github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g=
test/cli/harness/peering.go
+2
-2
@@ -13,7 +13,7 @@ type Peering struct {
13
To int
14
}
15
16
-func newRandPort() int {
16
+func NewRandPort() int {
17
n := rand.Int()
18
return 3000 + (n % 1000)
19
}
@@ -24,7 +24,7 @@ func CreatePeerNodes(t *testing.T, n int, peerings []Peering) (*Harness, Nodes)
24
nodes.ForEachPar(func(node *Node) {
25
node.UpdateConfig(func(cfg *config.Config) {
26
cfg.Routing.Type = config.NewOptionalString("none")
27
- cfg.Addresses.Swarm = []string{fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", newRandPort())}
27
+ cfg.Addresses.Swarm = []string{fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", NewRandPort())}
28
})
29
30
})
test/cli/transports_test.go
+23
@@ -1,6 +1,7 @@
1
package cli
2
3
import (
4
+ "fmt"
5
"os"
6
"path/filepath"
7
"testing"
@@ -124,4 +125,26 @@ func TestTransports(t *testing.T) {
125
runTests(nodes)
126
})
127
128
+ t.Run("QUIC connects with non-dialable transports", func(t *testing.T) {
129
+ // This test targets specific Kubo internals which may change later. This checks
130
+ // if we can announce an address we do not listen on, and then are able to connect
131
+ // via a different address that is available.
132
+ t.Parallel()
133
+ nodes := harness.NewT(t).NewNodes(5).Init()
134
+ nodes.ForEachPar(func(n *harness.Node) {
135
+ n.UpdateConfig(func(cfg *config.Config) {
136
+ // We need a specific port to announce so we first generate a random port.
137
+ // We can't use 0 here to automatically assign an available port because
138
+ // that would only work with Swarm, but not for the announcing.
139
+ port := harness.NewRandPort()
140
+ quicAddr := fmt.Sprintf("/ip4/127.0.0.1/udp/%d/quic-v1", port)
141
+ cfg.Addresses.Swarm = []string{quicAddr}
142
+ cfg.Addresses.Announce = []string{quicAddr, quicAddr + "/webtransport"}
143
+ })
144
+ })
145
+ disableRouting(nodes)
146
+ nodes.StartDaemons().Connect()
147
+ runTests(nodes)
148
+ })
149
+
150
}