holepunch-hop 0.4.5 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/settings.json +3 -0
- package/package.json +11 -5
- package/src/adapters/timeConvertor.js +3 -0
- package/src/index.js +45 -10
- package/src/{peers.js → network/peers.js} +507 -136
- package/src/{bees.js → storage/bees.js} +142 -60
- package/src/{drive.js → storage/drive.js} +2 -3
- package/src/{fileParser.js → storage/fileParser.js} +7 -1
- package/test/datacommands/files/data/jan3-bitcoin.csv +17 -0
- package/test/datacommands/files/large-csv.test.js +7 -0
- package/test/datacommands/files/small-csv.test.js +76 -0
- package/test/datacommands/ledger/save-get-ledger.test.js +117 -0
- package/test/datacommands/results/save-get-results.test.js +122 -0
- package/test/holepunch-initiate.test.js +47 -0
- package/test/multipers/ten-peers-network.test.js +437 -0
- package/test/setup-bee-holepunch.test.js +45 -0
- package/test/setup-holepunch.test.js +14 -13
- package/test/threepers/peer3-geninvite-after.test.js +439 -0
- package/test/threepers/three-peers.test.js +159 -0
- package/test/threepers/two-then-three.test.js +434 -0
- package/test/twopeers/peerClient-Server.test.js +243 -0
- package/test/twopeers/reconnect-peers.test.js +257 -0
- package/test/twopeers/reconnect-serverthen-conerr.test.js +304 -0
- package/test/twopeers/reconnect-then-conerr.test.js +309 -0
- package/test/twopeers/two-peer-one-disconnect.test.js +162 -0
- package/test/twopeers/two-peer-server-disconnect.test.js +167 -0
- package/vitest.config.js +8 -0
- /package/src/{kbledger.js → ledger/kbledger.js} +0 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
|
|
2
|
+
import { spawn } from 'child_process'
|
|
3
|
+
import path from 'path'
|
|
4
|
+
import crypto from 'crypto'
|
|
5
|
+
import Hyperswarm from 'hyperswarm'
|
|
6
|
+
import NetworkPeers from '../../src/network/peers.js'
|
|
7
|
+
|
|
8
|
+
// Set global test timeout to 10 seconds
|
|
9
|
+
const testTimeout = 10000;
|
|
10
|
+
|
|
11
|
+
describe('peer reconnection', () => {
|
|
12
|
+
let hopProcess
|
|
13
|
+
let clientPeer
|
|
14
|
+
let serverPeer
|
|
15
|
+
let clientSwarm
|
|
16
|
+
let serverSwarm
|
|
17
|
+
let clientPublicKey
|
|
18
|
+
let serverPublicKey
|
|
19
|
+
let savedPeerNetworkClient = []
|
|
20
|
+
let savedPeerNetworkServer = []
|
|
21
|
+
let topicReconnect = ''
|
|
22
|
+
let testConfig
|
|
23
|
+
let peerNetworkMock = []
|
|
24
|
+
|
|
25
|
+
beforeEach(async () => {
|
|
26
|
+
// Start HOP server
|
|
27
|
+
const baseHOPStepsUp = path.join(__dirname, '../..')
|
|
28
|
+
// hopProcess = spawn('npm', ['run', 'start'], { stdio: 'inherit', cwd: baseHOPStepsUp })
|
|
29
|
+
// await new Promise((resolve) => setTimeout(resolve, 3000))
|
|
30
|
+
|
|
31
|
+
// Initialize peers
|
|
32
|
+
// Create real swarms
|
|
33
|
+
clientSwarm = new Hyperswarm()
|
|
34
|
+
serverSwarm = new Hyperswarm()
|
|
35
|
+
|
|
36
|
+
// Create client and server peers
|
|
37
|
+
clientPeer = new NetworkPeers({}, clientSwarm)
|
|
38
|
+
serverPeer = new NetworkPeers({}, serverSwarm)
|
|
39
|
+
|
|
40
|
+
testConfig = {
|
|
41
|
+
peer1to2: {
|
|
42
|
+
peer1: {
|
|
43
|
+
publicKey: clientPeer.swarm.keyPair.publicKey.toString('hex'),
|
|
44
|
+
client: true
|
|
45
|
+
},
|
|
46
|
+
peer2: {
|
|
47
|
+
publicKey: serverPeer.swarm.keyPair.publicKey.toString('hex'),
|
|
48
|
+
client: false
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const randomString = crypto.randomBytes(32).toString('hex')
|
|
54
|
+
// Convert the random string to a buffer
|
|
55
|
+
const buffer = Buffer.from(randomString, 'hex')
|
|
56
|
+
topicReconnect = randomString
|
|
57
|
+
|
|
58
|
+
}, 10000) // 10 second timeout for setup
|
|
59
|
+
|
|
60
|
+
afterEach(async () => {
|
|
61
|
+
console.log('Cleaning up test environment')
|
|
62
|
+
await clientSwarm.destroy()
|
|
63
|
+
await serverSwarm.destroy()
|
|
64
|
+
clientPeer = null
|
|
65
|
+
serverPeer = null
|
|
66
|
+
}, 20000) // 20 second timeout for cleanup
|
|
67
|
+
|
|
68
|
+
describe('initial connection and relationship storage', () => {
|
|
69
|
+
it('should save relationship data for reconnection', async () => {
|
|
70
|
+
// make initial connection
|
|
71
|
+
console.log('FIRT TIME CONNECT start')
|
|
72
|
+
let connectionCount = 0
|
|
73
|
+
let mockServerPeer = {
|
|
74
|
+
publickey: clientPeer.swarm.keyPair.publicKey.toString('hex'),
|
|
75
|
+
live: false,
|
|
76
|
+
value: {
|
|
77
|
+
live: false,
|
|
78
|
+
key: clientPeer.swarm.keyPair.publicKey.toString('hex')
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// make client listen
|
|
82
|
+
clientPeer.peerJoinClient()
|
|
83
|
+
// serverPeer.peerJoinClient()
|
|
84
|
+
console.log('start NETWORK plumbing client peer1 and server peer2')
|
|
85
|
+
serverPeer.peerJoin(mockServerPeer)
|
|
86
|
+
// Create connection promise to verify connection details
|
|
87
|
+
let connectionPromise = new Promise((resolve) => {
|
|
88
|
+
clientPeer.swarm.on('connection', (conn, info) => {
|
|
89
|
+
connectionCount++
|
|
90
|
+
// Verify client connection details
|
|
91
|
+
console.log('Client FIRST connection details:')
|
|
92
|
+
expect(info.publicKey).toBeDefined()
|
|
93
|
+
expect(info.publicKey.toString('hex')).toBeDefined()
|
|
94
|
+
expect(info.client).toBe(false) // Client sees itself as false
|
|
95
|
+
expect(info.topics.length).toBe(0)
|
|
96
|
+
expect(clientPeer.topicHolder['']).toBeUndefined()
|
|
97
|
+
|
|
98
|
+
// Store connection for verification
|
|
99
|
+
const publicKeyHex = info.publicKey.toString('hex')
|
|
100
|
+
// expect(clientPeer.peerConnect[publicKeyHex]).toBeDefined()
|
|
101
|
+
|
|
102
|
+
// Save the peer network data for reconnection
|
|
103
|
+
savedPeerNetworkClient.push({
|
|
104
|
+
key: publicKeyHex,
|
|
105
|
+
value: {
|
|
106
|
+
name: 'peer2',
|
|
107
|
+
publickey: publicKeyHex,
|
|
108
|
+
roletaken: true,
|
|
109
|
+
longterm: true,
|
|
110
|
+
settopic: true,
|
|
111
|
+
topic: topicReconnect,
|
|
112
|
+
live: false,
|
|
113
|
+
livePeerkey: ''
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
// Resolve when client connection is established
|
|
117
|
+
if (connectionCount === 2) {
|
|
118
|
+
console.log('resolve peer two')
|
|
119
|
+
resolve()
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
serverPeer.swarm.on('connection', (conn, info) => {
|
|
124
|
+
console.log('Server FIRST connection details:')
|
|
125
|
+
connectionCount++
|
|
126
|
+
const publicKeyHex2 = info.publicKey.toString('hex')
|
|
127
|
+
// Verify server connection details
|
|
128
|
+
expect(info.publicKey).toBeDefined()
|
|
129
|
+
expect(info.publicKey.toString('hex')).toBeDefined()
|
|
130
|
+
expect(info.client).toBe(true) // Server sees itself as true
|
|
131
|
+
expect(info.topics.length).toBe(0)
|
|
132
|
+
expect(serverPeer.topicHolder['']).toBeUndefined()
|
|
133
|
+
|
|
134
|
+
// Store connection for verification on reconnect
|
|
135
|
+
savedPeerNetworkServer.push({
|
|
136
|
+
key: publicKeyHex2,
|
|
137
|
+
value: {
|
|
138
|
+
name: 'peer1',
|
|
139
|
+
publickey: publicKeyHex2,
|
|
140
|
+
roletaken: false,
|
|
141
|
+
longterm: true,
|
|
142
|
+
settopic: false,
|
|
143
|
+
topic: topicReconnect,
|
|
144
|
+
live: false,
|
|
145
|
+
livePeerkey: ''
|
|
146
|
+
}
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
// Resolve when server connection is established
|
|
150
|
+
if (connectionCount === 2) {
|
|
151
|
+
console.log('resolve peer two')
|
|
152
|
+
resolve()
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
// Wait for connection to be established
|
|
158
|
+
await connectionPromise
|
|
159
|
+
|
|
160
|
+
// Add timeout to prevent hanging
|
|
161
|
+
const timeout = setTimeout(() => {
|
|
162
|
+
throw new Error('Connection did not establish within timeout period')
|
|
163
|
+
}, 30000)
|
|
164
|
+
|
|
165
|
+
// Clear timeout if connection was successful
|
|
166
|
+
clearTimeout(timeout)
|
|
167
|
+
}, 50000) // 50 second timeout
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
describe('reconnection using saved data', async() => {
|
|
171
|
+
it('should use saved relationship data for reconnection', async () => {
|
|
172
|
+
let connectionCount = 0
|
|
173
|
+
console.log('reconnection using saved data')
|
|
174
|
+
let logicPrepserverStatus = async function (holePunch, info, publicKey) {
|
|
175
|
+
return await holePunch.prepareConnectionInfo(info, publicKey)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Reconnect using saved peer network data
|
|
179
|
+
clientPeer.setupConnectionBegin(savedPeerNetworkClient)
|
|
180
|
+
|
|
181
|
+
// Add 3 second delay before starting serverPeer
|
|
182
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
183
|
+
serverPeer.setupConnectionBegin(savedPeerNetworkServer)
|
|
184
|
+
|
|
185
|
+
// Create connection promise to verify reconnection details
|
|
186
|
+
let reconnectionPromise = new Promise(async (resolve) => {
|
|
187
|
+
clientPeer.swarm.on('connection', async (conn, info) => {
|
|
188
|
+
console.log('Client2 RECON connection details:')
|
|
189
|
+
connectionCount++
|
|
190
|
+
// Verify reconnection details
|
|
191
|
+
expect(info.publicKey).toBeDefined()
|
|
192
|
+
expect(info.publicKey.toString('hex')).toBeDefined()
|
|
193
|
+
expect(info.client).toBe(false) // Client sees itself as false
|
|
194
|
+
expect(info.topics.length).toBe(0)
|
|
195
|
+
expect(clientPeer.topicHolder['']).toBeUndefined()
|
|
196
|
+
|
|
197
|
+
peerNetworkMock.push({
|
|
198
|
+
key: testConfig.peer1to2.peer1.publicKey,
|
|
199
|
+
value: {
|
|
200
|
+
name: 'peer1',
|
|
201
|
+
publickey: testConfig.peer1to2.peer1.publicKey,
|
|
202
|
+
roletaken: true,
|
|
203
|
+
longterm: true,
|
|
204
|
+
settopic: true,
|
|
205
|
+
topic: 'letitbe',
|
|
206
|
+
live: false,
|
|
207
|
+
livePeerkey: testConfig.peer1to2.peer1.publicKey
|
|
208
|
+
}
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
// Store connection for verification
|
|
212
|
+
const publicKeyHex = info.publicKey.toString('hex')
|
|
213
|
+
// check logic
|
|
214
|
+
let logicInfo = await logicPrepserverStatus(clientPeer, info)
|
|
215
|
+
// Verify reconnection logic
|
|
216
|
+
if (info.client === testConfig.peer1to2.peer1.client) {
|
|
217
|
+
expect(logicInfo.discoveryTopicInfo.firstTime).toBe(false)
|
|
218
|
+
} else {
|
|
219
|
+
// Either serverStatus is true or there's a topic set
|
|
220
|
+
}
|
|
221
|
+
// Resolve when reconnection is established
|
|
222
|
+
console.log('TEST COMPLERE 111')
|
|
223
|
+
if (connectionCount === 2) {
|
|
224
|
+
console.log('resolve peer two')
|
|
225
|
+
clientSwarm.destroy()
|
|
226
|
+
clientPeer = null
|
|
227
|
+
// resolve()
|
|
228
|
+
// esolve()
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
serverPeer.swarm.on('connection', async (conn, info) => {
|
|
233
|
+
console.log('Server2 RECON connection details:')
|
|
234
|
+
connectionCount++
|
|
235
|
+
// Verify server reconnection details
|
|
236
|
+
expect(info.publicKey).toBeDefined()
|
|
237
|
+
expect(info.publicKey.toString('hex')).toBeDefined()
|
|
238
|
+
expect(info.client).toBe(true) // Server sees itself as true
|
|
239
|
+
expect(info.topics.length).toBe(1)
|
|
240
|
+
expect(serverPeer.topicHolder['']).toBeUndefined()
|
|
241
|
+
|
|
242
|
+
// Store connection for verification
|
|
243
|
+
const publicKeyHex = info.publicKey.toString('hex')
|
|
244
|
+
// expect(serverPeer.peerConnect[publicKeyHex]).toBeDefined()
|
|
245
|
+
|
|
246
|
+
// Store connection for later disconnection
|
|
247
|
+
serverPeer.peerConnect = {}
|
|
248
|
+
serverPeer.peerConnect[testConfig.peer1to2.peer1.publicKey] = conn
|
|
249
|
+
|
|
250
|
+
// check logic
|
|
251
|
+
let logicInfo = await logicPrepserverStatus(serverPeer, info)
|
|
252
|
+
// Verify reconnection logic
|
|
253
|
+
if (info.client === testConfig.peer1to2.peer2.client) {
|
|
254
|
+
expect(logicInfo.discoveryTopicInfo.firstTime).toBe(false)
|
|
255
|
+
} else {
|
|
256
|
+
// Either serverStatus is true or there's a topic set
|
|
257
|
+
}
|
|
258
|
+
console.log('TEST COMPLERE 222')
|
|
259
|
+
if (connectionCount === 2) {
|
|
260
|
+
console.log('resolve peer two')
|
|
261
|
+
// resolve()
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
let disconnectCount = 0
|
|
265
|
+
// listen for error
|
|
266
|
+
conn.on('error', data => {
|
|
267
|
+
console.log('error incoming, which peer?')
|
|
268
|
+
disconnectCount++
|
|
269
|
+
expect(info).toBeDefined()
|
|
270
|
+
expect(info.publicKey).toBeDefined()
|
|
271
|
+
expect(info.publicKey.toString('hex')).toBe(testConfig.peer1to2.peer1.publicKey)
|
|
272
|
+
// match to peer info. and inform beebee ui
|
|
273
|
+
let connectLivekeys = Object.keys(serverPeer.peerConnect)
|
|
274
|
+
for (let peer of peerNetworkMock) {
|
|
275
|
+
for (let pconn of connectLivekeys) {
|
|
276
|
+
if (peer.value.livePeerkey === pconn) {
|
|
277
|
+
// check if connect is close?
|
|
278
|
+
// let keysNoise = Object.keys(serverPeer.peerConnect[pconn]['noiseStream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['rawStream']['_closed'])
|
|
279
|
+
// console.log(this.peerConnect[pconn]['noiseStream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['rawStream']['_closed'])
|
|
280
|
+
let closeStatus = serverPeer.peerConnect[pconn]['noiseStream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['rawStream']['_closed']
|
|
281
|
+
expect(closeStatus).toBe(true)
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
// Verify disconnection info
|
|
286
|
+
if (disconnectCount === 1) {
|
|
287
|
+
resolve()
|
|
288
|
+
}
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
// Wait for connection to be established
|
|
298
|
+
await reconnectionPromise
|
|
299
|
+
|
|
300
|
+
// Add timeout to prevent hanging
|
|
301
|
+
const timeout = setTimeout(() => {
|
|
302
|
+
throw new Error('Connection did not establish within timeout period')
|
|
303
|
+
}, 30000)
|
|
304
|
+
|
|
305
|
+
// Clear timeout if connection was successful
|
|
306
|
+
clearTimeout(timeout)
|
|
307
|
+
}, 20000) // 50 second timeout
|
|
308
|
+
})
|
|
309
|
+
})
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
|
|
2
|
+
import Hyperswarm from 'hyperswarm'
|
|
3
|
+
import NetworkPeers from '../../src/network/peers.js'
|
|
4
|
+
import crypto from 'crypto'
|
|
5
|
+
|
|
6
|
+
// Set global test timeout to 10 seconds
|
|
7
|
+
const testTimeout = 10000;
|
|
8
|
+
|
|
9
|
+
describe('Peer Disconnection Tests', () => {
|
|
10
|
+
let clientPeer
|
|
11
|
+
let serverPeer
|
|
12
|
+
let clientSwarm
|
|
13
|
+
let serverSwarm
|
|
14
|
+
let testConfig
|
|
15
|
+
let peerNetworkMock = []
|
|
16
|
+
|
|
17
|
+
beforeEach(async () => {
|
|
18
|
+
// Create real swarms
|
|
19
|
+
clientSwarm = new Hyperswarm()
|
|
20
|
+
serverSwarm = new Hyperswarm()
|
|
21
|
+
|
|
22
|
+
// Create client and server peers
|
|
23
|
+
clientPeer = new NetworkPeers({}, clientSwarm)
|
|
24
|
+
serverPeer = new NetworkPeers({}, serverSwarm)
|
|
25
|
+
|
|
26
|
+
testConfig = {
|
|
27
|
+
peer1to2: {
|
|
28
|
+
peer1: {
|
|
29
|
+
publicKey: clientPeer.swarm.keyPair.publicKey.toString('hex'),
|
|
30
|
+
client: true
|
|
31
|
+
},
|
|
32
|
+
peer2: {
|
|
33
|
+
publicKey: serverPeer.swarm.keyPair.publicKey.toString('hex'),
|
|
34
|
+
client: false
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
// Set up initial connection
|
|
41
|
+
clientPeer.peerJoinClient()
|
|
42
|
+
serverPeer.peerJoinClient()
|
|
43
|
+
|
|
44
|
+
// Create mock server peer for client to connect to
|
|
45
|
+
const mockServerPeer = {
|
|
46
|
+
publickey: serverPeer.swarm.keyPair.publicKey.toString('hex'),
|
|
47
|
+
live: false,
|
|
48
|
+
value: {
|
|
49
|
+
live: false,
|
|
50
|
+
key: serverPeer.swarm.keyPair.publicKey.toString('hex')
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
clientPeer.peerJoin(mockServerPeer)
|
|
54
|
+
|
|
55
|
+
// Wait for initial setup
|
|
56
|
+
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
57
|
+
}, 10000)
|
|
58
|
+
|
|
59
|
+
afterEach(async () => {
|
|
60
|
+
console.log('Cleaning up test environment')
|
|
61
|
+
await Promise.all([
|
|
62
|
+
clientSwarm.destroy(),
|
|
63
|
+
serverSwarm.destroy()
|
|
64
|
+
])
|
|
65
|
+
clientPeer = null
|
|
66
|
+
serverPeer = null
|
|
67
|
+
}, 10000)
|
|
68
|
+
|
|
69
|
+
describe('First-time connection and disconnection', () => {
|
|
70
|
+
it('should handle first-time connection and proper disconnection', async () => {
|
|
71
|
+
let connectionCount = 0
|
|
72
|
+
let disconnectCount = 0
|
|
73
|
+
|
|
74
|
+
// Track connection
|
|
75
|
+
const connectionPromise = new Promise((resolve) => {
|
|
76
|
+
clientPeer.swarm.on('connection', (conn, info) => {
|
|
77
|
+
connectionCount++
|
|
78
|
+
console.log('Client connection:')
|
|
79
|
+
expect(info.publicKey).toBeDefined()
|
|
80
|
+
expect(info.client).toBe(true)
|
|
81
|
+
expect(info.topics.length).toBe(0)
|
|
82
|
+
|
|
83
|
+
// Store connection for later disconnection
|
|
84
|
+
clientPeer.connection = conn
|
|
85
|
+
|
|
86
|
+
if (connectionCount === 1) {
|
|
87
|
+
console.log('Client disconnecting')
|
|
88
|
+
clientSwarm.destroy()
|
|
89
|
+
clientPeer = null
|
|
90
|
+
resolve()
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
// Track server connection
|
|
96
|
+
const serverConnectionPromise = new Promise((resolve) => {
|
|
97
|
+
serverPeer.swarm.on('connection', (conn, info) => {
|
|
98
|
+
connectionCount++
|
|
99
|
+
console.log('Server connection:')
|
|
100
|
+
expect(info.publicKey).toBeDefined()
|
|
101
|
+
expect(info.publicKey).toBeDefined()
|
|
102
|
+
// Server sees itself as false
|
|
103
|
+
expect(info.client).toBe(false)
|
|
104
|
+
expect(info.topics.length).toBe(0)
|
|
105
|
+
|
|
106
|
+
// Store connection for later disconnection
|
|
107
|
+
serverPeer.peerConnect = {}
|
|
108
|
+
serverPeer.peerConnect[testConfig.peer1to2.peer1.publicKey] = conn
|
|
109
|
+
|
|
110
|
+
peerNetworkMock.push({
|
|
111
|
+
key: testConfig.peer1to2.peer1.publicKey,
|
|
112
|
+
value: {
|
|
113
|
+
name: 'peer1',
|
|
114
|
+
publickey: testConfig.peer1to2.peer1.publicKey,
|
|
115
|
+
roletaken: true,
|
|
116
|
+
longterm: true,
|
|
117
|
+
settopic: true,
|
|
118
|
+
topic: 'letitbe',
|
|
119
|
+
live: false,
|
|
120
|
+
livePeerkey: testConfig.peer1to2.peer1.publicKey
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
if (connectionCount === 2) {
|
|
125
|
+
console.log('server count disconnecting')
|
|
126
|
+
}
|
|
127
|
+
// listen for error
|
|
128
|
+
conn.on('error', data => {
|
|
129
|
+
console.log('error incoming, which peer?')
|
|
130
|
+
disconnectCount++
|
|
131
|
+
expect(info).toBeDefined()
|
|
132
|
+
expect(info.publicKey).toBeDefined()
|
|
133
|
+
expect(info.publicKey.toString('hex')).toBe(testConfig.peer1to2.peer1.publicKey)
|
|
134
|
+
// match to peer info. and inform beebee ui
|
|
135
|
+
let connectLivekeys = Object.keys(serverPeer.peerConnect)
|
|
136
|
+
for (let peer of peerNetworkMock) {
|
|
137
|
+
for (let pconn of connectLivekeys) {
|
|
138
|
+
if (peer.value.livePeerkey === pconn) {
|
|
139
|
+
// check if connect is close?
|
|
140
|
+
// let keysNoise = Object.keys(serverPeer.peerConnect[pconn]['noiseStream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['rawStream']['_closed'])
|
|
141
|
+
// console.log(this.peerConnect[pconn]['noiseStream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['rawStream']['_closed'])
|
|
142
|
+
let closeStatus = serverPeer.peerConnect[pconn]['noiseStream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['rawStream']['_closed']
|
|
143
|
+
expect(closeStatus).toBe(true)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Verify disconnection info
|
|
148
|
+
if (disconnectCount === 1) {
|
|
149
|
+
resolve()
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
})
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
// Wait for both connections to be established
|
|
157
|
+
await Promise.all([connectionPromise, serverConnectionPromise])
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
}, 30000)
|
|
161
|
+
})
|
|
162
|
+
})
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
|
|
2
|
+
import Hyperswarm from 'hyperswarm'
|
|
3
|
+
import NetworkPeers from '../../src/network/peers.js'
|
|
4
|
+
import crypto from 'crypto'
|
|
5
|
+
|
|
6
|
+
// Set global test timeout to 10 seconds
|
|
7
|
+
const testTimeout = 10000;
|
|
8
|
+
|
|
9
|
+
describe('Peer Disconnection Tests', () => {
|
|
10
|
+
let clientPeer
|
|
11
|
+
let serverPeer
|
|
12
|
+
let clientSwarm
|
|
13
|
+
let serverSwarm
|
|
14
|
+
let testConfig
|
|
15
|
+
let peerNetworkMock = []
|
|
16
|
+
|
|
17
|
+
beforeEach(async () => {
|
|
18
|
+
// Create real swarms
|
|
19
|
+
clientSwarm = new Hyperswarm()
|
|
20
|
+
serverSwarm = new Hyperswarm()
|
|
21
|
+
|
|
22
|
+
// Create client and server peers
|
|
23
|
+
clientPeer = new NetworkPeers({}, clientSwarm)
|
|
24
|
+
serverPeer = new NetworkPeers({}, serverSwarm)
|
|
25
|
+
|
|
26
|
+
testConfig = {
|
|
27
|
+
peer1to2: {
|
|
28
|
+
peer1: {
|
|
29
|
+
publicKey: clientPeer.swarm.keyPair.publicKey.toString('hex'),
|
|
30
|
+
client: true
|
|
31
|
+
},
|
|
32
|
+
peer2: {
|
|
33
|
+
publicKey: serverPeer.swarm.keyPair.publicKey.toString('hex'),
|
|
34
|
+
client: false
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
// Set up initial connection
|
|
41
|
+
clientPeer.peerJoinClient()
|
|
42
|
+
serverPeer.peerJoinClient()
|
|
43
|
+
|
|
44
|
+
// Create mock server peer for client to connect to
|
|
45
|
+
const mockServerPeer = {
|
|
46
|
+
publickey: serverPeer.swarm.keyPair.publicKey.toString('hex'),
|
|
47
|
+
live: false,
|
|
48
|
+
value: {
|
|
49
|
+
live: false,
|
|
50
|
+
key: serverPeer.swarm.keyPair.publicKey.toString('hex')
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
clientPeer.peerJoin(mockServerPeer)
|
|
54
|
+
|
|
55
|
+
// Wait for initial setup
|
|
56
|
+
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
57
|
+
}, 10000)
|
|
58
|
+
|
|
59
|
+
afterEach(async () => {
|
|
60
|
+
console.log('Cleaning up test environment')
|
|
61
|
+
await Promise.all([
|
|
62
|
+
clientSwarm.destroy(),
|
|
63
|
+
serverSwarm.destroy()
|
|
64
|
+
])
|
|
65
|
+
clientPeer = null
|
|
66
|
+
serverPeer = null
|
|
67
|
+
}, 10000)
|
|
68
|
+
|
|
69
|
+
describe('First-time connection and disconnection', () => {
|
|
70
|
+
it('should handle first-time connection and proper disconnection', async () => {
|
|
71
|
+
let connectionCount = 0
|
|
72
|
+
let disconnectCount = 0
|
|
73
|
+
|
|
74
|
+
// Track connection
|
|
75
|
+
const connectionPromise = new Promise((resolve) => {
|
|
76
|
+
clientPeer.swarm.on('connection', (conn, info) => {
|
|
77
|
+
connectionCount++
|
|
78
|
+
console.log('Client connection:')
|
|
79
|
+
expect(info.publicKey).toBeDefined()
|
|
80
|
+
expect(info.client).toBe(true)
|
|
81
|
+
expect(info.topics.length).toBe(0)
|
|
82
|
+
|
|
83
|
+
// Store connection for later disconnection
|
|
84
|
+
clientPeer.connection = conn
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
clientPeer.peerConnect = {}
|
|
89
|
+
clientPeer.peerConnect[testConfig.peer1to2.peer2.publicKey] = conn
|
|
90
|
+
|
|
91
|
+
peerNetworkMock.push({
|
|
92
|
+
key: testConfig.peer1to2.peer2.publicKey,
|
|
93
|
+
value: {
|
|
94
|
+
name: 'peer2',
|
|
95
|
+
publickey: testConfig.peer1to2.peer2.publicKey,
|
|
96
|
+
roletaken: true,
|
|
97
|
+
longterm: true,
|
|
98
|
+
settopic: true,
|
|
99
|
+
topic: 'letitbe',
|
|
100
|
+
live: false,
|
|
101
|
+
livePeerkey: testConfig.peer1to2.peer2.publicKey
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
// listen for error
|
|
106
|
+
conn.on('error', data => {
|
|
107
|
+
let disconnectCount = 0
|
|
108
|
+
console.log('error incoming client, which peer?')
|
|
109
|
+
disconnectCount++
|
|
110
|
+
expect(info).toBeDefined()
|
|
111
|
+
expect(info.publicKey).toBeDefined()
|
|
112
|
+
expect(info.publicKey.toString('hex')).toBe(testConfig.peer1to2.peer2.publicKey)
|
|
113
|
+
// match to peer info. and inform beebee ui
|
|
114
|
+
let connectLivekeys = Object.keys(clientPeer.peerConnect)
|
|
115
|
+
for (let peer of peerNetworkMock) {
|
|
116
|
+
for (let pconn of connectLivekeys) {
|
|
117
|
+
if (peer.value.livePeerkey === pconn) {
|
|
118
|
+
// check if connect is close?
|
|
119
|
+
// let keysNoise = Object.keys(serverPeer.peerConnect[pconn]['noiseStream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['rawStream']['_closed'])
|
|
120
|
+
// console.log(this.peerConnect[pconn]['noiseStream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['rawStream']['_closed'])
|
|
121
|
+
let closeStatus = clientPeer.peerConnect[pconn]['noiseStream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['_writableState']['stream']['rawStream']['_closed']
|
|
122
|
+
expect(closeStatus).toBe(true)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Verify disconnection info
|
|
128
|
+
if (disconnectCount === 1) {
|
|
129
|
+
console.log('resolve finish')
|
|
130
|
+
resolve()
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
// Track server connection
|
|
138
|
+
const serverConnectionPromise = new Promise((resolve) => {
|
|
139
|
+
serverPeer.swarm.on('connection', (conn, info) => {
|
|
140
|
+
connectionCount++
|
|
141
|
+
console.log('Server connection:')
|
|
142
|
+
expect(info.publicKey).toBeDefined()
|
|
143
|
+
expect(info.publicKey).toBeDefined()
|
|
144
|
+
// Server sees itself as false
|
|
145
|
+
expect(info.client).toBe(false)
|
|
146
|
+
expect(info.topics.length).toBe(0)
|
|
147
|
+
|
|
148
|
+
// Store connection for later disconnection
|
|
149
|
+
serverPeer.peerConnect = {}
|
|
150
|
+
serverPeer.peerConnect[testConfig.peer1to2.peer1.publicKey] = conn
|
|
151
|
+
|
|
152
|
+
if (connectionCount === 2) {
|
|
153
|
+
console.log('server count disconnecting')
|
|
154
|
+
serverSwarm.destroy()
|
|
155
|
+
serverPeer = null
|
|
156
|
+
resolve()
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
})
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
// Wait for both connections to be established
|
|
163
|
+
await Promise.all([connectionPromise, serverConnectionPromise])
|
|
164
|
+
|
|
165
|
+
}, 50000)
|
|
166
|
+
})
|
|
167
|
+
})
|
package/vitest.config.js
ADDED
|
File without changes
|