github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/core/core.go (about) 1 package core 2 3 import ( 4 "encoding/base64" 5 "errors" 6 "fmt" 7 8 context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" 9 b58 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58" 10 ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore" 11 ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" 12 13 bserv "github.com/jbenet/go-ipfs/blockservice" 14 config "github.com/jbenet/go-ipfs/config" 15 diag "github.com/jbenet/go-ipfs/diagnostics" 16 exchange "github.com/jbenet/go-ipfs/exchange" 17 bitswap "github.com/jbenet/go-ipfs/exchange/bitswap" 18 merkledag "github.com/jbenet/go-ipfs/merkledag" 19 namesys "github.com/jbenet/go-ipfs/namesys" 20 inet "github.com/jbenet/go-ipfs/net" 21 mux "github.com/jbenet/go-ipfs/net/mux" 22 netservice "github.com/jbenet/go-ipfs/net/service" 23 path "github.com/jbenet/go-ipfs/path" 24 peer "github.com/jbenet/go-ipfs/peer" 25 pin "github.com/jbenet/go-ipfs/pin" 26 routing "github.com/jbenet/go-ipfs/routing" 27 dht "github.com/jbenet/go-ipfs/routing/dht" 28 u "github.com/jbenet/go-ipfs/util" 29 ctxc "github.com/jbenet/go-ipfs/util/ctxcloser" 30 ) 31 32 var log = u.Logger("core") 33 34 // IpfsNode is IPFS Core module. It represents an IPFS instance. 35 type IpfsNode struct { 36 37 // the node's configuration 38 Config *config.Config 39 40 // the local node's identity 41 Identity peer.Peer 42 43 // storage for other Peer instances 44 Peerstore peer.Peerstore 45 46 // the local datastore 47 Datastore ds.ThreadSafeDatastore 48 49 // the network message stream 50 Network inet.Network 51 52 // the routing system. recommend ipfs-dht 53 Routing routing.IpfsRouting 54 55 // the block exchange + strategy (bitswap) 56 Exchange exchange.Interface 57 58 // the block service, get/add blocks. 59 Blocks *bserv.BlockService 60 61 // the merkle dag service, get/add objects. 62 DAG merkledag.DAGService 63 64 // the path resolution system 65 Resolver *path.Resolver 66 67 // the name system, resolves paths to hashes 68 Namesys namesys.NameSystem 69 70 // the diagnostics service 71 Diagnostics *diag.Diagnostics 72 73 // the pinning manager 74 Pinning pin.Pinner 75 76 ctxc.ContextCloser 77 78 onlineMode bool // alternatively, offline 79 } 80 81 // NewIpfsNode constructs a new IpfsNode based on the given config. 82 func NewIpfsNode(cfg *config.Config, online bool) (n *IpfsNode, err error) { 83 success := false // flip to true after all sub-system inits succeed 84 defer func() { 85 if !success && n != nil { 86 n.Close() 87 } 88 }() 89 90 if cfg == nil { 91 return nil, fmt.Errorf("configuration required") 92 } 93 94 // derive this from a higher context. 95 ctx := context.TODO() 96 n = &IpfsNode{ 97 onlineMode: online, 98 Config: cfg, 99 ContextCloser: ctxc.NewContextCloser(ctx, nil), 100 } 101 102 // setup datastore. 103 if n.Datastore, err = makeDatastore(cfg.Datastore); err != nil { 104 return nil, err 105 } 106 107 // setup peerstore + local peer identity 108 n.Peerstore = peer.NewPeerstore() 109 n.Identity, err = initIdentity(n.Config, n.Peerstore, online) 110 if err != nil { 111 return nil, err 112 } 113 114 // setup online services 115 if online { 116 117 dhtService := netservice.NewService(ctx, nil) // nil handler for now, need to patch it 118 exchangeService := netservice.NewService(ctx, nil) // nil handler for now, need to patch it 119 diagService := netservice.NewService(ctx, nil) // nil handler for now, need to patch it 120 121 muxMap := &mux.ProtocolMap{ 122 mux.ProtocolID_Routing: dhtService, 123 mux.ProtocolID_Exchange: exchangeService, 124 mux.ProtocolID_Diagnostic: diagService, 125 // add protocol services here. 126 } 127 128 // setup the network 129 listenAddrs, err := listenAddresses(cfg) 130 if err != nil { 131 return nil, err 132 } 133 134 n.Network, err = inet.NewIpfsNetwork(ctx, listenAddrs, n.Identity, n.Peerstore, muxMap) 135 if err != nil { 136 return nil, err 137 } 138 n.AddCloserChild(n.Network) 139 140 // setup diagnostics service 141 n.Diagnostics = diag.NewDiagnostics(n.Identity, n.Network, diagService) 142 diagService.SetHandler(n.Diagnostics) 143 144 // setup routing service 145 dhtRouting := dht.NewDHT(ctx, n.Identity, n.Peerstore, n.Network, dhtService, n.Datastore) 146 // TODO(brian): perform this inside NewDHT factory method 147 dhtService.SetHandler(dhtRouting) // wire the handler to the service. 148 n.Routing = dhtRouting 149 n.AddCloserChild(dhtRouting) 150 151 // setup exchange service 152 const alwaysSendToPeer = true // use YesManStrategy 153 n.Exchange = bitswap.NetMessageSession(ctx, n.Identity, n.Network, exchangeService, n.Routing, n.Datastore, alwaysSendToPeer) 154 // ok, this function call is ridiculous o/ consider making it simpler. 155 156 go initConnections(ctx, n.Config, n.Peerstore, dhtRouting) 157 } 158 159 // TODO(brian): when offline instantiate the BlockService with a bitswap 160 // session that simply doesn't return blocks 161 n.Blocks, err = bserv.NewBlockService(n.Datastore, n.Exchange) 162 if err != nil { 163 return nil, err 164 } 165 166 n.DAG = merkledag.NewDAGService(n.Blocks) 167 n.Namesys = namesys.NewNameSystem(n.Routing) 168 n.Pinning, err = pin.LoadPinner(n.Datastore, n.DAG) 169 if err != nil { 170 n.Pinning = pin.NewPinner(n.Datastore, n.DAG) 171 } 172 n.Resolver = &path.Resolver{DAG: n.DAG} 173 174 success = true 175 return n, nil 176 } 177 178 func (n *IpfsNode) OnlineMode() bool { 179 return n.onlineMode 180 } 181 182 func initIdentity(cfg *config.Config, peers peer.Peerstore, online bool) (peer.Peer, error) { 183 if cfg.Identity.PeerID == "" { 184 return nil, errors.New("Identity was not set in config (was ipfs init run?)") 185 } 186 187 if len(cfg.Identity.PeerID) == 0 { 188 return nil, errors.New("No peer ID in config! (was ipfs init run?)") 189 } 190 191 // get peer from peerstore (so it is constructed there) 192 id := peer.ID(b58.Decode(cfg.Identity.PeerID)) 193 peer, err := peers.Get(id) 194 if err != nil { 195 return nil, err 196 } 197 198 // when not online, don't need to parse private keys (yet) 199 if online { 200 skb, err := base64.StdEncoding.DecodeString(cfg.Identity.PrivKey) 201 if err != nil { 202 return nil, err 203 } 204 205 if err := peer.LoadAndVerifyKeyPair(skb); err != nil { 206 return nil, err 207 } 208 } 209 210 return peer, nil 211 } 212 213 func initConnections(ctx context.Context, cfg *config.Config, pstore peer.Peerstore, route *dht.IpfsDHT) { 214 for _, p := range cfg.Bootstrap { 215 if p.PeerID == "" { 216 log.Errorf("error: peer does not include PeerID. %v", p) 217 } 218 219 maddr, err := ma.NewMultiaddr(p.Address) 220 if err != nil { 221 log.Error(err) 222 continue 223 } 224 225 // setup peer 226 npeer, err := pstore.Get(peer.DecodePrettyID(p.PeerID)) 227 if err != nil { 228 log.Errorf("Bootstrapping error: %v", err) 229 continue 230 } 231 npeer.AddAddress(maddr) 232 233 if _, err = route.Connect(ctx, npeer); err != nil { 234 log.Errorf("Bootstrapping error: %v", err) 235 } 236 } 237 } 238 239 func listenAddresses(cfg *config.Config) ([]ma.Multiaddr, error) { 240 var listen []ma.Multiaddr 241 242 if len(cfg.Addresses.Swarm) > 0 { 243 maddr, err := ma.NewMultiaddr(cfg.Addresses.Swarm) 244 if err != nil { 245 return nil, fmt.Errorf("Failure to parse config.Addresses.Swarm: %s", cfg.Addresses.Swarm) 246 } 247 248 listen = append(listen, maddr) 249 } 250 251 return listen, nil 252 }