core: rearranged initialization a bit

This commit is contained in:
Juan Batiz-Benet 2015-01-02 05:40:38 -08:00
parent 56867c8b70
commit 1fa14335b9
2 changed files with 104 additions and 75 deletions

View File

@ -57,6 +57,7 @@ type IpfsNode struct {
PeerHost p2phost.Host // the network host (server+client)
Routing routing.IpfsRouting // the routing system. recommend ipfs-dht
Exchange exchange.Interface // the block exchange + strategy (bitswap)
Blockstore bstore.Blockstore // the block store (lower level)
Blocks *bserv.BlockService // the block service, get/add blocks.
DAG merkledag.DAGService // the merkle dag service, get/add objects.
Resolver *path.Resolver // the path resolution system
@ -94,87 +95,39 @@ func NewIpfsNode(ctx context.Context, cfg *config.Config, online bool) (n *IpfsN
n.ContextGroup = ctxgroup.WithContextAndTeardown(ctx, n.teardown)
ctx = n.ContextGroup.Context()
// setup Peerstore
n.Peerstore = peer.NewPeerstore()
// setup datastore.
if n.Datastore, err = makeDatastore(cfg.Datastore); err != nil {
return nil, debugerror.Wrap(err)
}
// setup local peer identity
n.Identity, n.PrivateKey, err = initIdentity(&n.Config.Identity, online)
// setup local peer ID (private key is loaded in online setup)
if err := n.loadID(); err != nil {
return nil, err
}
n.Blockstore, err = bstore.WriteCached(bstore.NewBlockstore(n.Datastore), kSizeBlockstoreWriteCache)
if err != nil {
return nil, debugerror.Wrap(err)
}
// setup Peerstore
n.Peerstore = peer.NewPeerstore()
if n.PrivateKey != nil {
n.Peerstore.AddPrivKey(n.Identity, n.PrivateKey)
}
blockstore, err := bstore.WriteCached(bstore.NewBlockstore(n.Datastore), kSizeBlockstoreWriteCache)
n.Exchange = offline.Exchange(blockstore)
// setup online services
if online {
// setup the network
listenAddrs, err := listenAddresses(cfg)
if err != nil {
return nil, debugerror.Wrap(err)
if err := n.StartOnlineServices(); err != nil {
return nil, err // debugerror.Wraps.
}
network, err := swarm.NewNetwork(ctx, listenAddrs, n.Identity, n.Peerstore)
if err != nil {
return nil, debugerror.Wrap(err)
}
n.AddChildGroup(network.CtxGroup())
n.PeerHost = p2pbhost.New(network)
// explicitly set these as our listen addrs.
// (why not do it inside inet.NewNetwork? because this way we can
// listen on addresses without necessarily advertising those publicly.)
addrs, err := n.PeerHost.Network().InterfaceListenAddresses()
if err != nil {
return nil, debugerror.Wrap(err)
}
n.Peerstore.AddAddresses(n.Identity, addrs)
// setup diagnostics service
n.Diagnostics = diag.NewDiagnostics(n.Identity, n.PeerHost)
// setup routing service
dhtRouting := dht.NewDHT(ctx, n.PeerHost, n.Datastore)
dhtRouting.Validators[IpnsValidatorTag] = namesys.ValidateIpnsRecord
// TODO(brian): perform this inside NewDHT factory method
n.Routing = dhtRouting
n.AddChildGroup(dhtRouting)
// setup exchange service
const alwaysSendToPeer = true // use YesManStrategy
bitswapNetwork := bsnet.NewFromIpfsHost(n.PeerHost, n.Routing)
n.Exchange = bitswap.New(ctx, n.Identity, bitswapNetwork, blockstore, alwaysSendToPeer)
// TODO consider moving connection supervision into the Network. We've
// discussed improvements to this Node constructor. One improvement
// would be to make the node configurable, allowing clients to inject
// an Exchange, Network, or Routing component and have the constructor
// manage the wiring. In that scenario, this dangling function is a bit
// awkward.
go superviseConnections(ctx, n.PeerHost, dhtRouting, n.Peerstore, n.Config.Bootstrap)
} else {
n.Exchange = offline.Exchange(n.Blockstore)
}
// TODO(brian): when offline instantiate the BlockService with a bitswap
// session that simply doesn't return blocks
n.Blocks, err = bserv.New(blockstore, n.Exchange)
n.Blocks, err = bserv.New(n.Blockstore, n.Exchange)
if err != nil {
return nil, debugerror.Wrap(err)
}
n.DAG = merkledag.NewDAGService(n.Blocks)
n.Namesys = namesys.NewNameSystem(n.Routing)
n.Pinning, err = pin.LoadPinner(n.Datastore, n.DAG)
if err != nil {
n.Pinning = pin.NewPinner(n.Datastore, n.DAG)
@ -185,6 +138,67 @@ func NewIpfsNode(ctx context.Context, cfg *config.Config, online bool) (n *IpfsN
return n, nil
}
func (n *IpfsNode) StartOnlineServices() error {
ctx := n.Context()
if n.PeerHost != nil { // already online.
return debugerror.New("node already online")
}
// load private key
if err := n.loadPrivateKey(); err != nil {
return err
}
// setup the network
listenAddrs, err := listenAddresses(n.Config)
if err != nil {
return debugerror.Wrap(err)
}
network, err := swarm.NewNetwork(ctx, listenAddrs, n.Identity, n.Peerstore)
if err != nil {
return debugerror.Wrap(err)
}
n.AddChildGroup(network.CtxGroup())
n.PeerHost = p2pbhost.New(network)
// explicitly set these as our listen addrs.
// (why not do it inside inet.NewNetwork? because this way we can
// listen on addresses without necessarily advertising those publicly.)
addrs, err := n.PeerHost.Network().InterfaceListenAddresses()
if err != nil {
return debugerror.Wrap(err)
}
n.Peerstore.AddAddresses(n.Identity, addrs)
// setup diagnostics service
n.Diagnostics = diag.NewDiagnostics(n.Identity, n.PeerHost)
// setup routing service
dhtRouting := dht.NewDHT(ctx, n.PeerHost, n.Datastore)
dhtRouting.Validators[IpnsValidatorTag] = namesys.ValidateIpnsRecord
n.Routing = dhtRouting
n.AddChildGroup(dhtRouting)
// setup exchange service
const alwaysSendToPeer = true // use YesManStrategy
bitswapNetwork := bsnet.NewFromIpfsHost(n.PeerHost, n.Routing)
n.Exchange = bitswap.New(ctx, n.Identity, bitswapNetwork, n.Blockstore, alwaysSendToPeer)
// setup name system
// TODO implement an offline namesys that serves only local names.
n.Namesys = namesys.NewNameSystem(n.Routing)
// TODO consider moving connection supervision into the Network. We've
// discussed improvements to this Node constructor. One improvement
// would be to make the node configurable, allowing clients to inject
// an Exchange, Network, or Routing component and have the constructor
// manage the wiring. In that scenario, this dangling function is a bit
// awkward.
go superviseConnections(ctx, n.PeerHost, dhtRouting, n.Peerstore, n.Config.Bootstrap)
return nil
}
func (n *IpfsNode) teardown() error {
if err := n.Datastore.Close(); err != nil {
return err
@ -196,29 +210,40 @@ func (n *IpfsNode) OnlineMode() bool {
return n.onlineMode
}
func initIdentity(cfg *config.Identity, online bool) (peer.ID, ic.PrivKey, error) {
if cfg.PeerID == "" {
return "", nil, debugerror.New("Identity was not set in config (was ipfs init run?)")
func (n *IpfsNode) loadID() error {
if n.Identity != "" {
return debugerror.New("identity already loaded")
}
if len(cfg.PeerID) == 0 {
return "", nil, debugerror.New("No peer ID in config! (was ipfs init run?)")
cid := n.Config.Identity.PeerID
if cid == "" {
return debugerror.New("Identity was not set in config (was ipfs init run?)")
}
if len(cid) == 0 {
return debugerror.New("No peer ID in config! (was ipfs init run?)")
}
id := peer.ID(b58.Decode(cfg.PeerID))
n.Identity = peer.ID(b58.Decode(cid))
return nil
}
// when not online, don't need to parse private keys (yet)
if !online {
return id, nil, nil
func (n *IpfsNode) loadPrivateKey() error {
if n.Identity == "" || n.Peerstore == nil {
return debugerror.New("loaded private key out of order.")
}
sk, err := loadPrivateKey(cfg, id)
if n.PrivateKey != nil {
return debugerror.New("private key already loaded")
}
sk, err := loadPrivateKey(&n.Config.Identity, n.Identity)
if err != nil {
return "", nil, err
return err
}
return id, sk, nil
n.PrivateKey = sk
n.Peerstore.AddPrivKey(n.Identity, n.PrivateKey)
return nil
}
func loadPrivateKey(cfg *config.Identity, id peer.ID) (ic.PrivKey, error) {

View File

@ -23,6 +23,10 @@ type routingResolver struct {
// NewRoutingResolver constructs a name resolver using the IPFS Routing system
// to implement SFS-like naming on top.
func NewRoutingResolver(route routing.IpfsRouting) Resolver {
if route == nil {
panic("attempt to create resolver with nil routing system")
}
return &routingResolver{routing: route}
}