-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathindex.js
126 lines (115 loc) · 3.88 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
'use strict'
const PeerInfo = require('peer-info')
const dht = require('ipfs-api/src/dht')
const swarm = require('ipfs-api/src/swarm')
const refs = require('ipfs-api/src/refs')
const defaultConfig = require('ipfs-api/src/utils/default-config')
const series = require('async/series')
const parallel = require('async/parallel')
const reflect = require('async/reflect')
const multiaddr = require('multiaddr')
const DEFAULT_IPFS_API = {
protocol: 'https',
port: 443,
host: 'ipfs.io'
}
const DEFAULT_BOOSTRAP_NODES = [
'/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd',
'/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3',
'/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM',
'/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu',
'/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm',
'/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64',
'/ipfs/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic',
'/ipfs/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6'
]
/**
* An implementation of content routing, using a delegated peer.
*/
class DelegatedContentRouting {
/**
* Create a new DelegatedContentRouting instance.
*
* @param {PeerInfo} peerInfo - the node that is using this routing.
* @param {object} [api] - the api endpoint of the delegated node to use.
* @param {Array<Multiaddr>} [bootstrappers] - list of bootstrapper nodes we are connected to.
*/
constructor (peerInfo, api, bootstrappers) {
if (peerInfo == null) {
throw new Error('missing self peerInfo')
}
this.api = Object.assign({}, defaultConfig(), api || DEFAULT_IPFS_API)
this.dht = dht(this.api)
this.swarm = swarm(this.api)
this.refs = refs(this.api)
this.peerInfo = peerInfo
this.bootstrappers = bootstrappers || DEFAULT_BOOSTRAP_NODES.map((addr) => multiaddr(addr))
}
/**
* Search the dht for providers of the given CID.
*
* - call `findProviders` on the delegated node.
* - does not support the `timeout` parameter, as this is specific to the delegate node.
*
* @param {CID} key
* @param {function(Error, Array<PeerInfo>)} callback
* @returns {void}
*/
findProviders (key, callback) {
this.dht.findprovs(key, (err, results) => {
if (err) {
return callback(err)
}
// cleanup result from ipfs-api
const infos = []
results
.filter((res) => Boolean(res.Responses))
.forEach((res) => {
res.Responses.forEach((raw) => {
const info = new PeerInfo(raw.ID)
if (raw.Addrs) {
raw.Addrs.forEach((addr) => info.multiaddrs.add(addr))
}
infos.push(info)
})
})
callback(null, infos)
})
}
/**
* Announce to the network that the delegated node can provide the given key.
*
* Currently this uses the following hack
* - call swarm.connect on the delegated node to us, to ensure we are connected
* - call refs --recursive on the delegated node, so it fetches the content
*
* @param {CID} key
* @param {function(Error)} callback
* @returns {void}
*/
provide (key, callback) {
const addrs = this.bootstrappers.map((addr) => {
return addr.encapsulate(`/p2p-circuit/ipfs/${this.peerInfo.id}`)
})
series([
// TODO: do we want to connect through all of them?
(cb) => parallel(addrs.map((addr) => {
return reflect((cb) => this.swarm.connect(addr.toString(), cb))
}), (err, results) => {
if (err) {
return cb(err)
}
// only some need to succeed
const success = results.filter((res) => res.error == null)
if (success.length === 0) {
return cb(new Error('unable to swarm.connect using p2p-circuit'))
}
cb()
}),
(cb) => {
this.refs(key.toBaseEncodedString(), {recursive: true}, cb)
}
], (err) => callback(err))
}
}
module.exports = DelegatedContentRouting