2
2
3
3
const Swarm = require ( 'libp2p-swarm' )
4
4
const PeerInfo = require ( 'peer-info' )
5
+ const PeerId = require ( 'peer-id' )
5
6
const WS = require ( 'libp2p-websockets' )
6
7
const WebRTCStar = require ( 'libp2p-webrtc-star' )
7
8
const spdy = require ( 'libp2p-spdy' )
8
9
const EE = require ( 'events' ) . EventEmitter
10
+ const multiaddr = require ( 'multiaddr' )
11
+ const PeerBook = require ( 'peer-book' )
12
+ const mafmt = require ( 'mafmt' )
9
13
10
14
exports = module . exports
11
15
12
- exports . Node = function Node ( peerInfo ) {
16
+ const OFFLINE_ERROR_MESSAGE = 'The libp2p node is not started yet'
17
+ const IPFS_CODE = 421
18
+
19
+ exports . Node = function Node ( pInfo , pBook ) {
13
20
if ( ! ( this instanceof Node ) ) {
14
- return new Node ( peerInfo )
21
+ return new Node ( pInfo , pBook )
22
+ }
23
+
24
+ if ( ! pInfo ) {
25
+ pInfo = new PeerInfo ( )
26
+ pInfo . multiaddr . add ( multiaddr ( '/ip4/0.0.0.0/tcp/0' ) )
15
27
}
16
- if ( ! peerInfo ) {
17
- peerInfo = new PeerInfo ( )
28
+
29
+ if ( ! pBook ) {
30
+ pBook = new PeerBook ( )
18
31
}
19
32
20
- this . peerInfo = peerInfo
33
+ this . peerInfo = pInfo
34
+ this . peerBook = pBook
21
35
22
36
// Swarm
23
- this . swarm = new Swarm ( peerInfo )
37
+ this . swarm = new Swarm ( pInfo )
24
38
this . swarm . connection . addStreamMuxer ( spdy )
25
39
this . swarm . connection . reuse ( )
26
40
41
+ this . swarm . on ( 'peer-mux-established' , ( peerInfo ) => {
42
+ this . peerBook . put ( peerInfo )
43
+ } )
44
+
45
+ this . swarm . on ( 'peer-mux-closed' , ( peerInfo ) => {
46
+ this . peerBook . removeByB58String ( peerInfo . id . toB58String ( ) )
47
+ } )
48
+
49
+ let isOnline = false
50
+
27
51
this . start = ( callback ) => {
28
52
// if we have `webrtc-star` addrs, then add
29
53
// the WebRTCStar transport
30
54
const wstar = new WebRTCStar ( )
31
- if ( wstar . filter ( peerInfo . multiaddrs ) . length > 0 ) {
55
+ if ( wstar . filter ( this . peerInfo . multiaddrs ) . length > 0 ) {
32
56
this . swarm . transport . add ( 'wstar' , wstar )
33
57
wstar . discovery . on ( 'peer' , ( peerInfo ) => {
34
58
this . discovery . emit ( 'peer' , peerInfo )
@@ -40,20 +64,141 @@ exports.Node = function Node (peerInfo) {
40
64
// WebSockets needs to be added after because
41
65
// it can't have a listener on the browser
42
66
this . swarm . transport . add ( 'ws' , new WS ( ) )
67
+ isOnline = true
43
68
callback ( )
44
69
} )
45
70
} else {
46
71
// if just WebSockets, no thing to listen
47
72
this . swarm . transport . add ( 'ws' , new WS ( ) )
73
+ isOnline = true
48
74
callback ( )
49
75
}
50
76
}
51
77
78
+ this . stop = ( callback ) => {
79
+ isOnline = false
80
+ this . swarm . close ( callback )
81
+ }
82
+
83
+ this . dialById = ( id , protocol , callback ) => {
84
+ if ( typeof protocol === 'function' ) {
85
+ callback = protocol
86
+ protocol = undefined
87
+ }
88
+
89
+ if ( ! isOnline ) {
90
+ return callback ( new Error ( OFFLINE_ERROR_MESSAGE ) )
91
+ }
92
+ // NOTE, these dialById only works if a previous dial
93
+ // was made until we have PeerRouting
94
+ // TODO support PeerRouting when it is Ready
95
+ callback ( new Error ( 'not implemented yet' ) )
96
+ }
97
+
98
+ this . dialByMultiaddr = ( maddr , protocol , callback ) => {
99
+ if ( typeof protocol === 'function' ) {
100
+ callback = protocol
101
+ protocol = undefined
102
+ }
103
+
104
+ if ( ! isOnline ) {
105
+ return callback ( new Error ( OFFLINE_ERROR_MESSAGE ) )
106
+ }
107
+
108
+ if ( typeof maddr === 'string' ) {
109
+ maddr = multiaddr ( maddr )
110
+ }
111
+
112
+ if ( ! mafmt . IPFS . matches ( maddr . toString ( ) ) ) {
113
+ return callback ( new Error ( 'multiaddr not valid' ) )
114
+ }
115
+
116
+ const ipfsIdB58String = maddr . stringTuples ( ) . filter ( ( tuple ) => {
117
+ if ( tuple [ 0 ] === IPFS_CODE ) {
118
+ return true
119
+ }
120
+ } ) [ 0 ] [ 1 ]
121
+
122
+ let peer
123
+ try {
124
+ peer = this . peerBook . getByB58String ( ipfsIdB58String )
125
+ } catch ( err ) {
126
+ peer = new PeerInfo ( PeerId . createFromB58String ( ipfsIdB58String ) )
127
+ }
128
+
129
+ peer . multiaddr . add ( maddr )
130
+ this . dialByPeerInfo ( peer , protocol , callback )
131
+ }
132
+
133
+ this . dialByPeerInfo = ( peer , protocol , callback ) => {
134
+ if ( typeof protocol === 'function' ) {
135
+ callback = protocol
136
+ protocol = undefined
137
+ }
138
+ if ( ! isOnline ) {
139
+ return callback ( new Error ( OFFLINE_ERROR_MESSAGE ) )
140
+ }
141
+
142
+ this . swarm . dial ( peer , protocol , ( err , conn ) => {
143
+ if ( err ) {
144
+ return callback ( err )
145
+ }
146
+ this . peerBook . put ( peer )
147
+ callback ( null , conn )
148
+ } )
149
+ }
150
+
151
+ this . hangUpById = ( id , callback ) => {
152
+ callback ( new Error ( 'not implemented yet' ) )
153
+ // TODO
154
+ }
155
+
156
+ this . hangUpByMultiaddr = ( maddr , callback ) => {
157
+ if ( ! isOnline ) {
158
+ return callback ( new Error ( OFFLINE_ERROR_MESSAGE ) )
159
+ }
160
+
161
+ if ( typeof maddr === 'string' ) {
162
+ maddr = multiaddr ( maddr )
163
+ }
164
+
165
+ if ( ! mafmt . IPFS . matches ( maddr . toString ( ) ) ) {
166
+ return callback ( new Error ( 'multiaddr not valid' ) )
167
+ }
168
+
169
+ const ipfsIdB58String = maddr . stringTuples ( ) . filter ( ( tuple ) => {
170
+ if ( tuple [ 0 ] === IPFS_CODE ) {
171
+ return true
172
+ }
173
+ } ) [ 0 ] [ 1 ]
174
+
175
+ try {
176
+ const pi = this . peerBook . getByB58String ( ipfsIdB58String )
177
+ this . hangUpByPeerInfo ( pi , callback )
178
+ } catch ( err ) {
179
+ // already disconnected
180
+ callback ( )
181
+ }
182
+ }
183
+
184
+ this . hangUpByPeerInfo = ( peer , callback ) => {
185
+ if ( ! isOnline ) {
186
+ return callback ( new Error ( OFFLINE_ERROR_MESSAGE ) )
187
+ }
188
+
189
+ this . peerBook . removeByB58String ( peer . id . toB58String ( ) )
190
+ this . swarm . hangUp ( peer , callback )
191
+ }
192
+
193
+ this . handle = ( protocol , handler ) => {
194
+ return this . swarm . handle ( protocol , handler )
195
+ }
196
+
197
+ this . unhandle = ( protocol ) => {
198
+ return this . swarm . unhandle ( protocol )
199
+ }
200
+
52
201
this . discovery = new EE ( )
53
202
this . routing = null
54
203
this . records = null
55
-
56
- this . dial = ( ) => {
57
- throw new Error ( 'THIS WILL BE EQUIVALENT TO THE ROUTED HOST FEATURE, IT WILL FIGURE OUT EVERYTHING :D' )
58
- }
59
204
}
0 commit comments