This repository has been archived by the owner on Feb 26, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathindex.js
145 lines (124 loc) · 3.95 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
'use strict'
const debug = require('debug')
const log = debug('libp2p:stardust')
log.error = debug('libp2p:stardust:error')
const withIs = require('class-is')
const { EventEmitter } = require('events')
const { AbortError } = require('abortable-iterator')
const errCode = require('err-code')
const Listener = require('./listener')
const toConnection = require('libp2p-utils/src/stream-to-ma-conn')
const { CODE_CIRCUIT } = require('./constants')
const { messages, codes } = require('./errors')
function getServerForAddress (addr) {
return String(addr.decapsulate('p2p-stardust'))
}
/**
* Stardust Transport
* @class
*/
class Stardust {
/**
* @constructor
* @param {Object} options - Options for the listener
* @param {Upgrader} options.upgrader
* @param {Libp2p} options.libp2p - Libp2p instance.
* @param {boolean} options.softFail - Whether to softly fail on listen errors
*/
constructor ({ upgrader, libp2p, softFail = false }) {
if (!upgrader) {
throw new Error('An upgrader must be provided. See https://github.com/libp2p/interface-transport#upgrader.')
} else if (!libp2p) {
// TODO: this should not be a requirement in the future
throw new Error('A libp2p instance must be provided')
}
this._upgrader = upgrader
this.libp2p = libp2p
this.id = libp2p.peerInfo.id
this.softFail = softFail
this.listeners = {}
// Discovery
this.discovery = new EventEmitter()
this.discovery.tag = 'stardust'
this.discovery._isStarted = false
this.discovery.start = () => {
this.discovery._isStarted = true
}
this.discovery.stop = () => {
this.discovery._isStarted = false
}
}
/**
* @async
* @param {Multiaddr} ma
* @param {object} options
* @param {AbortSignal} options.signal Used to abort dial requests
* @returns {Connection} An upgraded Connection
*/
async dial (ma, options = {}) {
const stream = await this._connect(ma, options)
const maConn = toConnection({
stream,
remoteAddr: ma
}, options)
log('new outbound connection %s', maConn.remoteAddr)
const conn = await this._upgrader.upgradeOutbound(maConn)
log('outbound connection %s upgraded', maConn.remoteAddr)
return conn
}
/**
* @private
* @param {Multiaddr} ma
* @param {object} options
* @param {AbortSignal} options.signal Used to abort dial requests
* @returns {Promise<DuplexIterableStream>} Resolves a duplex iterable stream with the target peer
*/
_connect (ma, options = {}) {
if (options.signal && options.signal.aborted) {
throw new AbortError()
}
const server = this.listeners[getServerForAddress(ma)]
if (!server) {
throw errCode(new Error(messages.NO_LISTENING_SERVER), codes.NO_LISTENING_SERVER)
}
return server._dial(ma, options)
}
/**
* Creates a stardust listener. The provided `handler` function will be called
* anytime a new incoming Connection has been successfully upgraded via
* `upgrader.upgradeInbound`.
* @param {object} [options]
* @param {function (Connection)} handler
* @returns {Listener} A stardust listener
*/
createListener (options, handler) {
if (typeof options === 'function') {
handler = options
options = {}
}
return new Listener({
handler,
upgrader: this._upgrader,
client: this,
options
})
}
/**
* Takes a list of `Multiaddr`s and returns only valid Stardust addresses
* @param {Multiaddr[]} multiaddrs
* @returns {Multiaddr[]} Valid Stardust multiaddrs
*/
filter (multiaddrs) {
multiaddrs = Array.isArray(multiaddrs) ? multiaddrs : [multiaddrs]
return multiaddrs.filter((ma) => {
if (ma.protoCodes().includes(CODE_CIRCUIT)) {
return false
}
if (ma.protoNames().includes('p2p-stardust')) {
return true
}
return false
})
}
}
module.exports = withIs(Stardust, { className: 'stardust', symbolName: '@libp2p/js-libp2p-stardust/stardust' })