| 1 | package libp2p |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | |
| 6 | "github.com/libp2p/go-libp2p" |
| 7 | record "github.com/libp2p/go-libp2p-record" |
| 8 | "github.com/libp2p/go-libp2p/core/host" |
| 9 | "github.com/libp2p/go-libp2p/core/peer" |
| 10 | "github.com/libp2p/go-libp2p/core/peerstore" |
| 11 | "github.com/libp2p/go-libp2p/core/routing" |
| 12 | routedhost "github.com/libp2p/go-libp2p/p2p/host/routed" |
| 13 | |
| 14 | "github.com/ipfs/kubo/config" |
| 15 | "github.com/ipfs/kubo/core/node/helpers" |
| 16 | "github.com/ipfs/kubo/core/shutdown" |
| 17 | "github.com/ipfs/kubo/repo" |
| 18 | |
| 19 | "go.uber.org/fx" |
| 20 | ) |
| 21 | |
| 22 | type P2PHostIn struct { |
| 23 | fx.In |
| 24 | |
| 25 | Repo repo.Repo |
| 26 | Validator record.Validator |
| 27 | HostOption HostOption |
| 28 | RoutingOption RoutingOption |
| 29 | ID peer.ID |
| 30 | Peerstore peerstore.Peerstore |
| 31 | |
| 32 | Opts [][]libp2p.Option `group:"libp2p"` |
| 33 | } |
| 34 | |
| 35 | type P2PHostOut struct { |
| 36 | fx.Out |
| 37 | |
| 38 | Host host.Host |
| 39 | Routing routing.Routing `name:"initialrouting"` |
| 40 | } |
| 41 | |
| 42 | func Host(mctx helpers.MetricsCtx, lc fx.Lifecycle, params P2PHostIn) (out P2PHostOut, err error) { |
| 43 | opts := []libp2p.Option{libp2p.NoListenAddrs} |
| 44 | for _, o := range params.Opts { |
| 45 | opts = append(opts, o...) |
| 46 | } |
| 47 | |
| 48 | ctx := helpers.LifecycleCtx(mctx, lc) |
| 49 | cfg, err := params.Repo.Config() |
| 50 | if err != nil { |
| 51 | return out, err |
| 52 | } |
| 53 | // Use auto-config resolution for actual connectivity |
| 54 | bootstrappers, err := cfg.BootstrapPeersWithAutoConf() |
| 55 | if err != nil { |
| 56 | return out, err |
| 57 | } |
| 58 | |
| 59 | // Optimistic provide is enabled either via dedicated expierimental flag, or when DHT Provide Sweep is enabled. |
| 60 | // When DHT Provide Sweep is enabled, all provide operations go through the |
| 61 | // `SweepingProvider`, hence the provides don't use the optimistic provide |
| 62 | // logic. Provides use `SweepingProvider.StartProviding()` and not |
| 63 | // `IpfsDHT.Provide()`, which is where the optimistic provide logic is |
| 64 | // implemented. However, `IpfsDHT.Provide()` is used to quickly provide roots |
| 65 | // when user manually adds content with the `--fast-provide` flag enabled. In |
| 66 | // this case we want to use optimistic provide logic to quickly announce the |
| 67 | // content to the network. This should be the only use case of |
| 68 | // `IpfsDHT.Provide()` when DHT Provide Sweep is enabled. |
| 69 | optimisticProvide := cfg.Experimental.OptimisticProvide || cfg.Provide.DHT.SweepEnabled.WithDefault(config.DefaultProvideDHTSweepEnabled) |
| 70 | |
| 71 | routingOptArgs := RoutingOptionArgs{ |
| 72 | Ctx: ctx, |
| 73 | Datastore: params.Repo.Datastore(), |
| 74 | Validator: params.Validator, |
| 75 | BootstrapPeers: bootstrappers, |
| 76 | OptimisticProvide: optimisticProvide, |
| 77 | OptimisticProvideJobsPoolSize: cfg.Experimental.OptimisticProvideJobsPoolSize, |
| 78 | LoopbackAddressesOnLanDHT: cfg.Routing.LoopbackAddressesOnLanDHT.WithDefault(config.DefaultLoopbackAddressesOnLanDHT), |
| 79 | } |
| 80 | opts = append(opts, libp2p.Routing(func(h host.Host) (routing.PeerRouting, error) { |
| 81 | args := routingOptArgs |
| 82 | args.Host = h |
| 83 | r, err := params.RoutingOption(args) |
| 84 | out.Routing = r |
| 85 | return r, err |
| 86 | })) |
| 87 | |
| 88 | out.Host, err = params.HostOption(params.ID, params.Peerstore, opts...) |
| 89 | if err != nil { |
| 90 | return P2PHostOut{}, err |
| 91 | } |
| 92 | |
| 93 | routingOptArgs.Host = out.Host |
| 94 | |
| 95 | // this code is necessary just for tests: mock network constructions |
| 96 | // ignore the libp2p constructor options that actually construct the routing! |
| 97 | if out.Routing == nil { |
| 98 | r, err := params.RoutingOption(routingOptArgs) |
| 99 | if err != nil { |
| 100 | return P2PHostOut{}, err |
| 101 | } |
| 102 | out.Routing = r |
| 103 | out.Host = routedhost.Wrap(out.Host, out.Routing) |
| 104 | } |
| 105 | |
| 106 | lc.Append(fx.Hook{ |
| 107 | OnStop: func(ctx context.Context) error { |
| 108 | // Host.Close() does not accept a ctx and can block draining |
| 109 | // peer connections on busy nodes. CloseWithCtx returns when |
| 110 | // either the close finishes or the shutdown deadline expires. |
| 111 | return shutdown.CloseWithCtx(ctx, "libp2p-host", out.Host.Close) |
| 112 | }, |
| 113 | }) |
| 114 | |
| 115 | return out, err |
| 116 | } |