diff --git a/package.json b/package.json index a60850e..328f2e8 100644 --- a/package.json +++ b/package.json @@ -15,11 +15,12 @@ "test": "node test/test-network.js" }, "dependencies": { - "simple-peer": "^9.11.1", - "ws": "^8.14.2", + "@koush/wrtc": "^0.5.3", + "chalk": "^5.3.0", "express": "^4.18.2", + "simple-peer": "^9.11.1", "uuid": "^9.0.1", - "chalk": "^5.3.0" + "ws": "^8.14.2" }, "devDependencies": { "nodemon": "^3.0.2" diff --git a/src/ring-node.js b/src/ring-node.js index b26cce6..917d80c 100644 --- a/src/ring-node.js +++ b/src/ring-node.js @@ -172,7 +172,7 @@ export class RingNode extends EventEmitter { ws.on('error', reject); - setTimeout(() => reject(new Error('Connection timeout')), 10000); + setTimeout(() => reject(new Error('Connection timeout')), 15000); }); } catch (error) { console.error(`Failed to connect to peer ${nodeId}:`, error); @@ -282,48 +282,102 @@ export class RingNode extends EventEmitter { try { console.log(chalk.yellow(`🔄 Attempting to join ring via ${bootstrapNode}`)); - const success = await this.connectToPeer('bootstrap', bootstrapNode); - if (success) { - // Request to join the ring network - this.sendJoinRingRequest(); - return true; - } - return false; + return new Promise((resolve, reject) => { + const ws = new WebSocket(`ws://${bootstrapNode}`); + let timeoutId; + + ws.on('open', () => { + console.log(chalk.cyan('🔗 Connected to bootstrap node, sending join request...')); + + // Send join ring request directly through WebSocket + ws.send(JSON.stringify({ + type: 'join-ring', + from: this.id, + payload: { + nodeId: this.id, + port: this.port, + isOracle: this.isOracle + } + })); + }); + + ws.on('message', (data) => { + try { + const message = JSON.parse(data.toString()); + if (message.type === 'join-response') { + if (message.success) { + console.log(chalk.green('✅ Successfully joined the ring network!')); + clearTimeout(timeoutId); + ws.close(); + resolve(true); + } else { + console.log(chalk.red('❌ Join request was rejected')); + clearTimeout(timeoutId); + ws.close(); + resolve(false); + } + } + } catch (error) { + console.error('Error parsing join response:', error); + } + }); + + ws.on('error', (error) => { + console.error('WebSocket error:', error); + clearTimeout(timeoutId); + reject(error); + }); + + ws.on('close', () => { + clearTimeout(timeoutId); + }); + + // Set timeout for join process + timeoutId = setTimeout(() => { + ws.close(); + reject(new Error('Connection timeout')); + }, 15000); // Increased timeout to 15 seconds + }); } catch (error) { console.error('Failed to join ring:', error); return false; } } - sendJoinRingRequest() { - const message = { - id: uuidv4(), - type: 'join-ring', - from: this.id, - payload: { - nodeId: this.id, - port: this.port, - isOracle: this.isOracle - } - }; - - this.webrtc.broadcast(message); - } - async handleJoinRingRequest(ws, payload) { const { nodeId, port, isOracle } = payload; console.log(chalk.cyan(`🔗 New node ${nodeId.substring(0, 8)} wants to join the ring`)); - // Add to known nodes - this.knownNodes.set(nodeId, { port, isOracle }); - - if (isOracle) { - this.oracleNodes.add(nodeId); - } + try { + // Add to known nodes + this.knownNodes.set(nodeId, { port, isOracle }); + + if (isOracle) { + this.oracleNodes.add(nodeId); + } - // Find optimal position in rings for the new node - await this.integrateNewNode(nodeId); + // Find optimal position in rings for the new node + await this.integrateNewNode(nodeId); + + // Send success response + ws.send(JSON.stringify({ + type: 'join-response', + success: true, + message: 'Successfully integrated into ring network' + })); + + console.log(chalk.green(`✅ Node ${nodeId.substring(0, 8)} successfully joined the ring`)); + } catch (error) { + console.error(`Error handling join request from ${nodeId}:`, error); + + // Send failure response + ws.send(JSON.stringify({ + type: 'join-response', + success: false, + message: 'Failed to integrate into ring network' + })); + } } async integrateNewNode(nodeId) { diff --git a/src/webrtc-manager.js b/src/webrtc-manager.js index 932e296..654a37e 100644 --- a/src/webrtc-manager.js +++ b/src/webrtc-manager.js @@ -1,6 +1,7 @@ import SimplePeer from 'simple-peer'; import { EventEmitter } from 'events'; import { v4 as uuidv4 } from 'uuid'; +import wrtc from '@koush/wrtc'; export class WebRTCManager extends EventEmitter { constructor(nodeId) { @@ -20,6 +21,7 @@ export class WebRTCManager extends EventEmitter { const peer = new SimplePeer({ initiator: isInitiator, trickle: false, + wrtc: wrtc, config: { iceServers: [ { urls: 'stun:stun.l.google.com:19302' },