master
go 125 lines 3.9 KB
Raw
1 package libp2p
2
3 import (
4 "context"
5
6 "github.com/ipfs/kubo/config"
7 "github.com/libp2p/go-libp2p"
8 "github.com/libp2p/go-libp2p/core/peer"
9 "github.com/libp2p/go-libp2p/p2p/host/autorelay"
10 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay"
11 "go.uber.org/fx"
12 )
13
14 func RelayTransport(enableRelay bool) func() (opts Libp2pOpts, err error) {
15 return func() (opts Libp2pOpts, err error) {
16 if enableRelay {
17 opts.Opts = append(opts.Opts, libp2p.EnableRelay())
18 } else {
19 opts.Opts = append(opts.Opts, libp2p.DisableRelay())
20 }
21 return
22 }
23 }
24
25 func RelayService(enable bool, relayOpts config.RelayService) func() (opts Libp2pOpts, err error) {
26 return func() (opts Libp2pOpts, err error) {
27 if enable {
28 def := relay.DefaultResources()
29 // Real defaults live in go-libp2p.
30 // Here we apply any overrides from user config.
31 opts.Opts = append(opts.Opts, libp2p.EnableRelayService(relay.WithResources(relay.Resources{
32 Limit: &relay.RelayLimit{
33 Data: relayOpts.ConnectionDataLimit.WithDefault(def.Limit.Data),
34 Duration: relayOpts.ConnectionDurationLimit.WithDefault(def.Limit.Duration),
35 },
36 MaxCircuits: int(relayOpts.MaxCircuits.WithDefault(int64(def.MaxCircuits))),
37 BufferSize: int(relayOpts.BufferSize.WithDefault(int64(def.BufferSize))),
38 ReservationTTL: relayOpts.ReservationTTL.WithDefault(def.ReservationTTL),
39 MaxReservations: int(relayOpts.MaxReservations.WithDefault(int64(def.MaxReservations))),
40 MaxReservationsPerIP: int(relayOpts.MaxReservationsPerIP.WithDefault(int64(def.MaxReservationsPerIP))),
41 MaxReservationsPerASN: int(relayOpts.MaxReservationsPerASN.WithDefault(int64(def.MaxReservationsPerASN))),
42 })))
43 }
44 return
45 }
46 }
47
48 func MaybeAutoRelay(staticRelays []string, cfgPeering config.Peering, enabled bool) fx.Option {
49 if !enabled {
50 return fx.Options()
51 }
52
53 if len(staticRelays) > 0 {
54 return fx.Provide(func() (opts Libp2pOpts, err error) {
55 if len(staticRelays) > 0 {
56 static := make([]peer.AddrInfo, 0, len(staticRelays))
57 for _, s := range staticRelays {
58 var addr *peer.AddrInfo
59 addr, err = peer.AddrInfoFromString(s)
60 if err != nil {
61 return
62 }
63 static = append(static, *addr)
64 }
65 opts.Opts = append(opts.Opts, libp2p.EnableAutoRelayWithStaticRelays(static))
66 }
67 return
68 })
69 }
70
71 peerChan := make(chan peer.AddrInfo)
72 return fx.Options(
73 // Provide AutoRelay option
74 fx.Provide(func() (opts Libp2pOpts, err error) {
75 opts.Opts = append(opts.Opts,
76 libp2p.EnableAutoRelayWithPeerSource(
77 func(ctx context.Context, numPeers int) <-chan peer.AddrInfo {
78 // TODO(9257): make this code smarter (have a state and actually try to grow the search outward) instead of a long running task just polling our K cluster.
79 r := make(chan peer.AddrInfo)
80 go func() {
81 defer close(r)
82 for ; numPeers != 0; numPeers-- {
83 select {
84 case v, ok := <-peerChan:
85 if !ok {
86 return
87 }
88 select {
89 case r <- v:
90 case <-ctx.Done():
91 return
92 }
93 case <-ctx.Done():
94 return
95 }
96 }
97 }()
98 return r
99 },
100 autorelay.WithMinInterval(0),
101 ))
102 return
103 }),
104 autoRelayFeeder(cfgPeering, peerChan),
105 )
106 }
107
108 func HolePunching(flag config.Flag, hasRelayClient bool) func() (opts Libp2pOpts, err error) {
109 return func() (opts Libp2pOpts, err error) {
110 if flag.WithDefault(true) {
111 if !hasRelayClient {
112 // If hole punching is explicitly enabled but the relay client is disabled then panic,
113 // otherwise just silently disable hole punching
114 if flag != config.Default {
115 log.Fatal("Failed to enable `Swarm.EnableHolePunching`, it requires `Swarm.RelayClient.Enabled` to be true.")
116 } else {
117 log.Info("HolePunching has been disabled due to the RelayClient being disabled.")
118 }
119 return
120 }
121 opts.Opts = append(opts.Opts, libp2p.EnableHolePunching())
122 }
123 return
124 }
125 }