ipfs daemon
Ipfs daemon will initialize all modules using uber.fx dependency injection.
Before invoking NewNode(), we have to create the FSRepo at first.
repo, err := fsrepo.Open(cctx.ConfigRoot)
...
ncfg := &core.BuildCfg{
Repo: repo,
Permanent: true, // It is temporary way to signify that node is permanent
Online: !offline,
DisableEncryptedConnections: unencrypted,
ExtraOpts: map[string]bool{
"pubsub": pubsub,
"ipnsps": ipnsps,
"mplex": mplex,
},
//TODO(Kubuxu): refactor Online vs Offline by adding Permanent vs Ephemeral
}
...
node, err := core.NewNode(req.Context, ncfg)
if err != nil {
log.Error("error from node construction: ", err)
return err
}
node.IsDaemon = true
NewNode
Using fx to initialize IpfsNode, starting DHT bootstrap once upon initlization done.
// IpfsNode is IPFS Core module. It represents an IPFS instance.
type IpfsNode struct {
// Self
Identity peer.ID // the local node's identity
Repo repo.Repo
// Local node
Pinning pin.Pinner // the pinning manager
Mounts Mounts `optional:"true"` // current mount state, if any.
PrivateKey ic.PrivKey `optional:"true"` // the local node's private Key
PNetFingerprint libp2p.PNetFingerprint `optional:"true"` // fingerprint of private network
// Services
Peerstore pstore.Peerstore `optional:"true"` // storage for other Peer instances
Blockstore bstore.GCBlockstore // the block store (lower level)
Filestore *filestore.Filestore `optional:"true"` // the filestore blockstore
BaseBlocks node.BaseBlocks // the raw blockstore, no filestore wrapping
GCLocker bstore.GCLocker // the locker used to protect the blockstore during gc
Blocks bserv.BlockService // the block service, get/add blocks.
DAG ipld.DAGService // the merkle dag service, get/add objects.
Resolver *resolver.Resolver // the path resolution system
Reporter *metrics.BandwidthCounter `optional:"true"`
Discovery discovery.Service `optional:"true"`
FilesRoot *mfs.Root
RecordValidator record.Validator
// Online
PeerHost p2phost.Host `optional:"true"` // the network host (server+client)
Bootstrapper io.Closer `optional:"true"` // the periodic bootstrapper
Routing routing.Routing `optional:"true"` // the routing system. recommend ipfs-dht
Exchange exchange.Interface // the block exchange + strategy (bitswap)
Namesys namesys.NameSystem // the name system, resolves paths to hashes
Provider provider.System // the value provider system
IpnsRepub *ipnsrp.Republisher `optional:"true"`
AutoNAT *autonat.AutoNATService `optional:"true"`
PubSub *pubsub.PubSub `optional:"true"`
PSRouter *psrouter.PubsubValueStore `optional:"true"`
DHT *dht.IpfsDHT `optional:"true"`
P2P *p2p.P2P `optional:"true"`
Process goprocess.Process
ctx context.Context
stop func() error
// Flags
IsOnline bool `optional:"true"` // Online is set when networking is enabled.
IsDaemon bool `optional:"true"` // Daemon is set when running on a long-running daemon.
}
// NewNode constructs and returns an IpfsNode using the given cfg.
func NewNode(ctx context.Context, cfg *BuildCfg) (*IpfsNode, error) {
ctx = metrics.CtxScope(ctx, "ipfs")
n := &IpfsNode{
ctx: ctx,
}
app := fx.New(
node.IPFS(ctx, cfg),
fx.NopLogger,
fx.Extract(n),
)
var once sync.Once
var stopErr error
n.stop = func() error {
once.Do(func() {
stopErr = app.Stop(context.Background())
})
return stopErr
}
n.IsOnline = cfg.Online
go func() {
// Note that some services use contexts to signal shutting down, which is
// very suboptimal. This needs to be here until that's addressed somehow
<-ctx.Done()
err := n.stop()
if err != nil {
log.Error("failure on stop: ", err)
}
}()
if app.Err() != nil {
return nil, app.Err()
}
if err := app.Start(ctx); err != nil {
return nil, err
}
// TODO: How soon will bootstrap move to libp2p?
if !cfg.Online {
return n, nil
}
return n, n.Bootstrap(bootstrap.DefaultBootstrapConfig)
}
Core.Plugin
// Start "core" plugins. We want to do this *before* starting the HTTP
// API as the user may be relying on these plugins.
err = cctx.Plugins.Start(node)
if err != nil {
return err
}
node.Process.AddChild(goprocess.WithTeardown(cctx.Plugins.Close))
HttpAPI
// construct api endpoint - every time
apiErrc, err := serveHTTPApi(req, cctx)
if err != nil {
return err
}
Fuse Mount
mount, _ := req.Options[mountKwd].(bool)
if mount && offline {
return cmds.Errorf(cmds.ErrClient, "mount is not currently supported in offline mode")
}
if mount {
if err := mountFuse(req, cctx); err != nil {
return err
}
}
HttpGateway
// construct http gateway
gwErrc, err := serveHTTPGateway(req, cctx)
if err != nil {
return err
}