@@ -24,6 +24,7 @@ import (
24
24
"github.com/libp2p/go-libp2p/p2p/host/autonat"
25
25
"github.com/libp2p/go-libp2p/p2p/host/autorelay"
26
26
bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
27
+ blankhost "github.com/libp2p/go-libp2p/p2p/host/blank"
27
28
"github.com/libp2p/go-libp2p/p2p/host/eventbus"
28
29
"github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoremem"
29
30
rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
@@ -131,6 +132,13 @@ type Config struct {
131
132
SwarmOpts []swarm.Option
132
133
133
134
DisableIdentifyAddressDiscovery bool
135
+
136
+ EnableAutoNATv2 bool
137
+
138
+ UDPBlackHoleSuccessCounter * swarm.BlackHoleSuccessCounter
139
+ CustomUDPBlackHoleSuccessCounter bool
140
+ IPv6BlackHoleSuccessCounter * swarm.BlackHoleSuccessCounter
141
+ CustomIPv6BlackHoleSuccessCounter bool
134
142
}
135
143
136
144
func (cfg * Config ) makeSwarm (eventBus event.Bus , enableMetrics bool ) (* swarm.Swarm , error ) {
@@ -165,7 +173,10 @@ func (cfg *Config) makeSwarm(eventBus event.Bus, enableMetrics bool) (*swarm.Swa
165
173
return nil , err
166
174
}
167
175
168
- opts := cfg .SwarmOpts
176
+ opts := append (cfg .SwarmOpts ,
177
+ swarm .WithUDPBlackHoleSuccessCounter (cfg .UDPBlackHoleSuccessCounter ),
178
+ swarm .WithIPv6BlackHoleSuccessCounter (cfg .IPv6BlackHoleSuccessCounter ),
179
+ )
169
180
if cfg .Reporter != nil {
170
181
opts = append (opts , swarm .WithMetrics (cfg .Reporter ))
171
182
}
@@ -193,6 +204,77 @@ func (cfg *Config) makeSwarm(eventBus event.Bus, enableMetrics bool) (*swarm.Swa
193
204
return swarm .NewSwarm (pid , cfg .Peerstore , eventBus , opts ... )
194
205
}
195
206
207
+ func (cfg * Config ) makeAutoNATV2Host () (host.Host , error ) {
208
+ autonatPrivKey , _ , err := crypto .GenerateEd25519Key (rand .Reader )
209
+ if err != nil {
210
+ return nil , err
211
+ }
212
+ ps , err := pstoremem .NewPeerstore ()
213
+ if err != nil {
214
+ return nil , err
215
+ }
216
+
217
+ autoNatCfg := Config {
218
+ Transports : cfg .Transports ,
219
+ Muxers : cfg .Muxers ,
220
+ SecurityTransports : cfg .SecurityTransports ,
221
+ Insecure : cfg .Insecure ,
222
+ PSK : cfg .PSK ,
223
+ ConnectionGater : cfg .ConnectionGater ,
224
+ Reporter : cfg .Reporter ,
225
+ PeerKey : autonatPrivKey ,
226
+ Peerstore : ps ,
227
+ DialRanker : swarm .NoDelayDialRanker ,
228
+ UDPBlackHoleSuccessCounter : cfg .UDPBlackHoleSuccessCounter ,
229
+ IPv6BlackHoleSuccessCounter : cfg .IPv6BlackHoleSuccessCounter ,
230
+ ResourceManager : cfg .ResourceManager ,
231
+ SwarmOpts : []swarm.Option {
232
+ // Don't update black hole state for failed autonat dials
233
+ swarm .WithReadOnlyBlackHoleDetector (),
234
+ },
235
+ }
236
+ fxopts , err := autoNatCfg .addTransports ()
237
+ if err != nil {
238
+ return nil , err
239
+ }
240
+ var dialerHost host.Host
241
+ fxopts = append (fxopts ,
242
+ fx .Provide (eventbus .NewBus ),
243
+ fx .Provide (func (lifecycle fx.Lifecycle , b event.Bus ) (* swarm.Swarm , error ) {
244
+ lifecycle .Append (fx.Hook {
245
+ OnStop : func (context.Context ) error {
246
+ return ps .Close ()
247
+ }})
248
+ sw , err := autoNatCfg .makeSwarm (b , false )
249
+ return sw , err
250
+ }),
251
+ fx .Provide (func (sw * swarm.Swarm ) * blankhost.BlankHost {
252
+ return blankhost .NewBlankHost (sw )
253
+ }),
254
+ fx .Provide (func (bh * blankhost.BlankHost ) host.Host {
255
+ return bh
256
+ }),
257
+ fx .Provide (func () crypto.PrivKey { return autonatPrivKey }),
258
+ fx .Provide (func (bh host.Host ) peer.ID { return bh .ID () }),
259
+ fx .Invoke (func (bh * blankhost.BlankHost ) {
260
+ dialerHost = bh
261
+ }),
262
+ )
263
+ app := fx .New (fxopts ... )
264
+ if err := app .Err (); err != nil {
265
+ return nil , err
266
+ }
267
+ err = app .Start (context .Background ())
268
+ if err != nil {
269
+ return nil , err
270
+ }
271
+ go func () {
272
+ <- dialerHost .Network ().(* swarm.Swarm ).Done ()
273
+ app .Stop (context .Background ())
274
+ }()
275
+ return dialerHost , nil
276
+ }
277
+
196
278
func (cfg * Config ) addTransports () ([]fx.Option , error ) {
197
279
fxopts := []fx.Option {
198
280
fx .WithLogger (func () fxevent.Logger { return getFXLogger () }),
@@ -291,6 +373,14 @@ func (cfg *Config) addTransports() ([]fx.Option, error) {
291
373
}
292
374
293
375
func (cfg * Config ) newBasicHost (swrm * swarm.Swarm , eventBus event.Bus ) (* bhost.BasicHost , error ) {
376
+ var autonatv2Dialer host.Host
377
+ if cfg .EnableAutoNATv2 {
378
+ ah , err := cfg .makeAutoNATV2Host ()
379
+ if err != nil {
380
+ return nil , err
381
+ }
382
+ autonatv2Dialer = ah
383
+ }
294
384
h , err := bhost .NewHost (swrm , & bhost.HostOpts {
295
385
EventBus : eventBus ,
296
386
ConnManager : cfg .ConnManager ,
@@ -306,6 +396,8 @@ func (cfg *Config) newBasicHost(swrm *swarm.Swarm, eventBus event.Bus) (*bhost.B
306
396
EnableMetrics : ! cfg .DisableMetrics ,
307
397
PrometheusRegisterer : cfg .PrometheusRegisterer ,
308
398
DisableIdentifyAddressDiscovery : cfg .DisableIdentifyAddressDiscovery ,
399
+ EnableAutoNATv2 : cfg .EnableAutoNATv2 ,
400
+ AutoNATv2Dialer : autonatv2Dialer ,
309
401
})
310
402
if err != nil {
311
403
return nil , err
@@ -488,9 +580,8 @@ func (cfg *Config) addAutoNAT(h *bhost.BasicHost) error {
488
580
Peerstore : ps ,
489
581
DialRanker : swarm .NoDelayDialRanker ,
490
582
SwarmOpts : []swarm.Option {
491
- // It is better to disable black hole detection and just attempt a dial for autonat
492
- swarm .WithUDPBlackHoleConfig (false , 0 , 0 ),
493
- swarm .WithIPv6BlackHoleConfig (false , 0 , 0 ),
583
+ swarm .WithUDPBlackHoleSuccessCounter (nil ),
584
+ swarm .WithIPv6BlackHoleSuccessCounter (nil ),
494
585
},
495
586
}
496
587
0 commit comments