UNPKG

holepunch-hop

Version:
434 lines (391 loc) 16.3 kB
import { describe, it, expect, beforeEach, afterEach } from 'vitest' import Hyperswarm from 'hyperswarm' import NetworkPeers from '../../src/network/peers.js' import crypto from 'crypto' describe('Three Peer Connection Tests', () => { let peer1 let peer2 let peer3 let swarm1 let swarm2 let swarm3 let testConfig let savedPeerNetworkClient = [] let savedPeerNetworkServer = [] let topicReconnect = '' let topicReconnect13 = '' const randomString = crypto.randomBytes(32).toString('hex') topicReconnect = randomString console.log(topicReconnect) const randomString13 = crypto.randomBytes(32).toString('hex') topicReconnect13 = randomString13 console.log(topicReconnect13) beforeEach(async () => { // Create swarms for each peer swarm1 = new Hyperswarm() swarm2 = new Hyperswarm() swarm3 = new Hyperswarm() // Create peer instances peer1 = new NetworkPeers({}, swarm1) peer2 = new NetworkPeers({}, swarm2) peer3 = new NetworkPeers({}, swarm3) console.log('TTpppppppppppppppppppp---PUBKEY owner---pppppppp') console.log(peer1.swarm.keyPair.publicKey.toString('hex')) console.log(peer2.swarm.keyPair.publicKey.toString('hex')) console.log(peer3.swarm.keyPair.publicKey.toString('hex')) testConfig = { peer1to2: { peer1: { publicKey: peer1.swarm.keyPair.publicKey.toString('hex'), client: false }, peer2: { publicKey: peer2.swarm.keyPair.publicKey.toString('hex'), client: true }, }, peer1to3: { peer1: { publicKey: peer1.swarm.keyPair.publicKey.toString('hex'), client: false }, peer3: { publicKey: peer3.swarm.keyPair.publicKey.toString('hex'), client: true } }, peer2to3: { peer2: { publicKey: peer2.swarm.keyPair.publicKey.toString('hex'), client: false }, peer3: { publicKey: peer3.swarm.keyPair.publicKey.toString('hex'), client: true } } } }, 20000) afterEach(async () => { console.log('TTCleaning up test environment') await Promise.all([ swarm1.destroy(), swarm2.destroy(), swarm3.destroy() ]) peer1 = null peer2 = null peer3 = null }, 10000) describe('Basic Connection', () => { it('should establish start connections peer one to peer two', async () => { let countConnect = 0 // Set up peer1 as the initial listener peer1.peerJoinClient() peer2.peerJoinClient() let logicPrepserverStatus = async function (holePunch, info, publicKey) { return await holePunch.prepareConnectionInfo(info, publicKey) } // Set up peer2 and peer3 with mock peer data const mockPeer1 = { publickey: peer1.swarm.keyPair.publicKey.toString('hex'), live: false, value: { live: false, key: peer1.swarm.keyPair.publicKey.toString('hex') } } peer2.peerJoin(mockPeer1) // Create connection promises for each peer const connectionPromises = [ /* PEER 1 FIRST */ new Promise((resolve) => { peer1.swarm.on('connection', (conn, info) => { console.log('TTPeer1 FIRST connection:') // console.log(conn) // console.log(info.topics) // console.log(info.publicKey.toString('hex')) // console.log(peer1.swarm.peers) countConnect++ //expect(info.publicKey).toBeDefined() //expect(info.client).toBe(testConfig.peer1to2.peer1.client) const publicKeyPeer1 = info.publicKey.toString('hex') let logicInfo = logicPrepserverStatus(peer1, info, publicKeyPeer1) if (info.client === testConfig.peer1to2.peer1.client) { // peer1 is server console.log('TT peer1 logic assertions') // expect(logicInfo.serverStatus).toBe(true) // expect(logicInfo.topicKeylive.length).toBe(0) // expect(logicInfo.discoveryTopicInfo.firstTime).toBe(true) } else { // Either serverStatus is true or there's a topic set expect(logicInfo.serverStatus || logicInfo.topicKeylive.length > 0).toBe(true) } // Save the peer network data for reconnection // Store connection for verification const publicKeyHex = info.publicKey.toString('hex') savedPeerNetworkClient.push({ key: publicKeyHex, value: { name: 'peer2', publickey: publicKeyHex, roletaken: true, longterm: true, settopic: true, topic: topicReconnect, live: false, livePeerkey: '' } }) // process network message conn.on('data', data => // assess data peer1.assessData(publicKeyHex, data) ) if (countConnect === 2) { console.log('TTnow resolve') resolve() } }) }), /* PEER 2 FIRST */ new Promise((resolve) => { peer2.swarm.on('connection', (conn, info) => { console.log('TT Peer2 FIRST connection:') // console.log(conn) // console.log(info.topics) // console.log(peer2.swarm.peers) countConnect++ // expect(info.publicKey).toBeDefined() // Peer2's role depends on which peer it's connecting to if (info.publicKey === testConfig.peer1to2.peer1.publicKey) { // expect(info.client).toBe(testConfig.peer1to2.peer2.client) // Peer2 is client to Peer1 } // Store connection for verification on reconnect const publicKeyHex2 = info.publicKey.toString('hex') let logicInfo = logicPrepserverStatus(peer1, info, publicKeyHex2) if (info.client === testConfig.peer1to2.peer2.client) { // peer2 is client console.log('TTpeer2 assertion logic') // expect(logicInfo.serverStatus).toBe(false) // xpect(logicInfo.topicKeylive.length).toBe(0) // expect(logicInfo.discoveryTopicInfo.firstTime).toBe(true) } else { // Either serverStatus is true or there's a topic set expect(logicInfo.serverStatus || logicInfo.topicKeylive.length > 0).toBe(true) } savedPeerNetworkServer.push({ key: publicKeyHex2, value: { name: 'peer1', publickey: publicKeyHex2, roletaken: false, longterm: true, settopic: false, topic: topicReconnect, live: false, livePeerkey: '' } }) // process network message conn.on('data', data => // assess data peer2.assessData(publicKeyHex2, data) ) if (countConnect === 1) { console.log('TTresolve two') resolve() } }) }) ] // Wait for all connections to be established await Promise.all(connectionPromises) // Add timeout to prevent hanging const timeout = setTimeout(() => { throw new Error('Connection did not establish within timeout period') }, 2000) // Clear timeout if connection was successful clearTimeout(timeout) }, 20000) // 50 second timeout }) /* reconnection TEST from here */ describe('reconnection using saved data', () => { it('should use saved relationship data for reconnection but peer1 to peer2 first time should go through first time path logic', async () => { console.log('TTreconnection using saved data') // keep track count connection to closetest let connectionCount = 0 let peer1Count = 0 // Set up peer1 as the initial listener peer1.peerJoinClient() peer2.peerJoinClient() let logicPrepserverStatus = async function (holePunch, info, publicKey) { return await holePunch.prepareConnectionInfo(info, publicKey) } // Create connection promise to verify reconnection details let reconnectionPromise = new Promise(async (resolve) => { // Reconnect using saved peer network data peer1.setupConnectionBegin(savedPeerNetworkClient) // Add 3 second delay before starting serverPeer await new Promise(resolve => setTimeout(resolve, 3000)); peer2.setupConnectionBegin(savedPeerNetworkServer) peer1.swarm.on('connection', async (conn, info) => { console.log('TT Peer1 RECON connection details:') // console.log(peer1.swarm.status(topicReconnect)) connectionCount++ peer1Count++ let test2complete = false // Store connection for verification const publicKeyHex = info.publicKey.toString('hex') // to differenciate between peer 2 and peer3 if (peer1Count === 1) { console.log('TT peer one RECON batch assert 111111') // check logic let logicInfo = await logicPrepserverStatus(peer1, info, publicKeyHex) if (info.client === testConfig.peer1to2.peer1.client) { // peer1 is server expect(logicInfo.discoveryTopicInfo.firstTime).toBe('wait-topic-confirm') } else { // Either serverStatus is true or there's a topic set } } else if (peer1Count === 2) { console.log('TT peer one RECON batch assert 222222') // check logic let logicInfo = await logicPrepserverStatus(peer1, info, publicKeyHex) // For peer1 (server) - first-time connection if (info.client === false) { // peer1 is server console.log('TT server asserts peer1 to peer3 first time but with peer2 already connected') expect(logicInfo.discoveryTopicInfo.firstTime).toBe('wait-topic-confirm') test2complete = true console.log('test2222 over') // resolve() } else { // Either serverStatus is true or there's a topic set } } else { console.log('no match to peer 2 or 3 XXXXXXXX') } // process network message conn.on('data', data => // assess data peer1.assessData(publicKeyHex, data) ) // Resolve when reconnection is established if (connectionCount === 4 && test2complete === true) { console.log('TT resolve peerone') resolve() } }) peer2.swarm.on('connection', async (conn, info) => { console.log('TT Peer2 RECON connection details:') // console.log(peer2.swarm.status(topicReconnect)) connectionCount++ // Store connection for verification const publicKeyHex = info.publicKey.toString('hex') // Determine the correct client value from testConfig const clientValue = testConfig.peer1to2.peer2.client // check logic let logicInfo = await logicPrepserverStatus(peer2, info, publicKeyHex) // Verify reconnection logic if (info.client === clientValue) { // peer1 is server // expect(logicInfo.serverStatus).toBe(false) // expect(logicInfo.topicKeylive.length).toBe(1) expect(logicInfo.discoveryTopicInfo.firstTime).toBe(false) } else { // Either serverStatus is true or there's a topic set expect(logicInfo.serverStatus || logicInfo.topicKeylive.length > 0).toBe(true) } // Ensure peer1 and peer2 are connected before peer3 connects console.log('TT Peer1 and Peer2 Reconnt now -- code location') // Wait until both peer1 and peer2 connections are established // keep tabs on invites generated peer1.setRole({ pubkey: peer1.swarm.keyPair.publicKey.toString('hex'), codename: '12345677654321', name: 'primepeer' }) // Create function to handle peer3 connection const connectPeer3 = async () => { console.log('TT Connecting peer3 now that peer1 and peer2 are connected') peer3.peerJoinClient() const mockPeer1 = { publickey: peer1.swarm.keyPair.publicKey.toString('hex'), live: false, value: { live: false, key: peer1.swarm.keyPair.publicKey.toString('hex') } } peer3.peerJoin(mockPeer1) } // Call connectPeer3 when connectionCount reaches 2 if (connectionCount === 2) { console.log('TT wait 1111') await connectPeer3() } else { // Set up a listener for when connectionCount reaches 2 const checkConnectionCount = setInterval(async () => { console.log('TT wait 2222') // put a time delay in here too if (connectionCount === 2) { clearInterval(checkConnectionCount) console.log('TT Waiting 3 seconds before connecting peer3...') await new Promise(resolve => setTimeout(resolve, 10000)) connectPeer3() } }, 100) } // process network message conn.on('data', data => // assess data peer2.assessData(publicKeyHex, data) ) if (connectionCount === 4) { console.log('resolve peer two') resolve() } }) peer3.swarm.on('connection', async (conn, info) => { console.log('TT Peer3 FIRST connection details:') connectionCount++ // Verify server reconnection details // expect(info.publicKey).toBeDefined() // expect(info.publicKey.toString('hex')).toBeDefined() // expect(info.topics.length).toBe(0) // expect(peer3.topicHolder['']).toBeUndefined() // Store connection for verification const publicKeyHex = info.publicKey.toString('hex') // expect(serverPeer.peerConnect[publicKeyHex]).toBeDefined() // check logic if (info.publicKey === testConfig.peer1to3.peer1.publicKey) { expect(info.client).toBe(testConfig.peer1to3.peer3.client) // Peer3 is client to Peer1 } else if (info.publicKey === testConfig.peer2to3.peer2.publicKey) { expect(info.client).toBe(testConfig.peer2to3.peer3.client) // Peer3 is client to Peer2 } // check logic let logicInfo = await logicPrepserverStatus(peer3, info, publicKeyHex) if (info.client === testConfig.peer2to3.peer3.client) { // peer1 is server // expect(logicInfo.serverStatus).toBe(false) // expect(logicInfo.topicKeylive.length).toBe(0) expect(logicInfo.discoveryTopicInfo.firstTime).toBe(true) } else { // Either serverStatus is true or there's a topic set expect(logicInfo.serverStatus || logicInfo.topicKeylive.length > 0).toBe(true) } // process network message conn.on('data', data => // assess data peer3.assessData(publicKeyHex, data) ) if (connectionCount === 4) { console.log('resolve peer three') resolve() } }) }) // Wait for connection to be established await reconnectionPromise // Add timeout to prevent hanging const timeout = setTimeout(() => { throw new Error('Connection did not establish within timeout period') }, 30000) // Clear timeout if connection was successful clearTimeout(timeout) }, 40000) // 30 second timeout }) })