const express = require('express'); const Hyperswarm = require('hyperswarm'); const crypto = require('crypto'); const b4a = require('b4a'); const { v4: uuidv4 } = require('uuid'); const app = express(); const PORT = process.env.PORT || 3000; // --- CONFIGURATION --- const TOPIC_NAME = 'hypermind-lklynet-v1'; const TOPIC = crypto.createHash('sha256').update(TOPIC_NAME).digest(); const MY_ID = uuidv4(); let mySeq = 0; const seenPeers = new Map(); const sseClients = new Set(); seenPeers.set(MY_ID, { seq: mySeq, lastSeen: Date.now() }); function broadcastUpdate() { const data = JSON.stringify({ count: seenPeers.size, direct: swarm.connections.size, id: MY_ID }); for (const client of sseClients) { client.write(`data: ${data}\n\n`); } } const swarm = new Hyperswarm(); swarm.on('connection', (socket) => { const hello = JSON.stringify({ type: 'HEARTBEAT', id: MY_ID, seq: mySeq, hops: 0 }); socket.write(hello); broadcastUpdate(); socket.on('data', (data) => { try { const msgs = data.toString().split('\n').filter(x => x.trim()); for (const msgStr of msgs) { const msg = JSON.parse(msgStr); handleMessage(msg, socket); } } catch (e) { // console.error('Invalid message', e); } }); socket.on('close', () => { if (socket.peerId && seenPeers.has(socket.peerId)) { seenPeers.delete(socket.peerId); } broadcastUpdate(); }); socket.on('error', () => {}); }); const discovery = swarm.join(TOPIC); discovery.flushed().then(() => { console.log('[P2P] Joined topic:', TOPIC_NAME); }); function handleMessage(msg, sourceSocket) { if (msg.type === 'HEARTBEAT') { const { id, seq, hops } = msg; if (hops === 0) { sourceSocket.peerId = id; } const now = Date.now(); const stored = seenPeers.get(id); let shouldUpdate = false; if (!stored) { // New peer shouldUpdate = true; } else if (seq > stored.seq) { shouldUpdate = true; } if (shouldUpdate) { const wasNew = !stored; seenPeers.set(id, { seq, lastSeen: now }); if (wasNew) broadcastUpdate(); if (hops < 3) { relayMessage({ ...msg, hops: hops + 1 }, sourceSocket); } } } else if (msg.type === 'LEAVE') { const { id, hops } = msg; if (seenPeers.has(id)) { seenPeers.delete(id); broadcastUpdate(); if (hops < 3) { relayMessage({ ...msg, hops: hops + 1 }, sourceSocket); } } } } function relayMessage(msg, sourceSocket) { const data = JSON.stringify(msg) + '\n'; for (const socket of swarm.connections) { if (socket !== sourceSocket) { socket.write(data); } } } // Periodic Heartbeat setInterval(() => { mySeq++; seenPeers.set(MY_ID, { seq: mySeq, lastSeen: Date.now() }); const heartbeat = JSON.stringify({ type: 'HEARTBEAT', id: MY_ID, seq: mySeq, hops: 0 }) + '\n'; for (const socket of swarm.connections) { socket.write(heartbeat); } const now = Date.now(); let changed = false; for (const [id, data] of seenPeers) { if (now - data.lastSeen > 2500) { seenPeers.delete(id); changed = true; } } if (changed) broadcastUpdate(); }, 500); // Graceful Shutdown function handleShutdown() { console.log('[P2P] Shutting down, sending goodbye...'); const goodbye = JSON.stringify({ type: 'LEAVE', id: MY_ID, hops: 0 }) + '\n'; for (const socket of swarm.connections) { socket.write(goodbye); } setTimeout(() => { process.exit(0); }, 500); } process.on('SIGINT', handleShutdown); process.on('SIGTERM', handleShutdown); // --- WEB SERVER --- app.get('/', (req, res) => { const count = seenPeers.size; const directPeers = swarm.connections.size; res.send(` Hypermind Counter
${count}
Active Nodes
ID: ${MY_ID.slice(0, 8)}...
Direct Connections: ${directPeers}
`); }); // SSE Endpoint app.get('/events', (req, res) => { res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); res.flushHeaders(); sseClients.add(res); const data = JSON.stringify({ count: seenPeers.size, direct: swarm.connections.size, id: MY_ID }); res.write(`data: ${data}\n\n`); req.on('close', () => { sseClients.delete(res); }); }); app.get('/api/stats', (req, res) => { res.json({ count: seenPeers.size, direct: swarm.connections.size, id: MY_ID }); }); app.listen(PORT, () => { console.log(`Hypermind Node running on port ${PORT}`); console.log(`ID: ${MY_ID}`); });