Last active
April 16, 2023 20:01
-
-
Save carloslfu/ec389a3d55e07edbf48e23fbd8d65689 to your computer and use it in GitHub Desktop.
Make a P2P connection in 10 minutes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const crypto = require('crypto') | |
const Swarm = require('discovery-swarm') | |
const defaults = require('dat-swarm-defaults') | |
const getPort = require('get-port') | |
const readline = require('readline') | |
/** | |
* Here we will save our TCP peer connections | |
* using the peer id as key: { peer_id: TCP_Connection } | |
*/ | |
const peers = {} | |
// Counter for connections, used for identify connections | |
let connSeq = 0 | |
// Peer Identity, a random hash for identify your peer | |
const myId = crypto.randomBytes(32) | |
console.log('Your identity: ' + myId.toString('hex')) | |
// reference to redline interface | |
let rl | |
/** | |
* Function for safely call console.log with readline interface active | |
*/ | |
function log () { | |
if (rl) { | |
rl.clearLine() | |
rl.close() | |
rl = undefined | |
} | |
for (let i = 0, len = arguments.length; i < len; i++) { | |
console.log(arguments[i]) | |
} | |
askUser() | |
} | |
/* | |
* Function to get text input from user and send it to other peers | |
* Like a chat :) | |
*/ | |
const askUser = async () => { | |
rl = readline.createInterface({ | |
input: process.stdin, | |
output: process.stdout | |
}) | |
rl.question('Send message: ', message => { | |
// Broadcast to peers | |
for (let id in peers) { | |
peers[id].conn.write(message) | |
} | |
rl.close() | |
rl = undefined | |
askUser() | |
}); | |
} | |
/** | |
* Default DNS and DHT servers | |
* This servers are used for peer discovery and establishing connection | |
*/ | |
const config = defaults({ | |
// peer-id | |
id: myId, | |
}) | |
/** | |
* discovery-swarm library establishes a TCP p2p connection and uses | |
* discovery-channel library for peer discovery | |
*/ | |
const sw = Swarm(config) | |
;(async () => { | |
// Choose a random unused port for listening TCP peer connections | |
const port = await getPort() | |
sw.listen(port) | |
console.log('Listening to port: ' + port) | |
/** | |
* The channel we are connecting to. | |
* Peers should discover other peers in this channel | |
*/ | |
sw.join('our-fun-channel') | |
sw.on('connection', (conn, info) => { | |
// Connection id | |
const seq = connSeq | |
const peerId = info.id.toString('hex') | |
log(`Connected #${seq} to peer: ${peerId}`) | |
// Keep alive TCP connection with peer | |
if (info.initiator) { | |
try { | |
conn.setKeepAlive(true, 600) | |
} catch (exception) { | |
log('exception', exception) | |
} | |
} | |
conn.on('data', data => { | |
// Here we handle incomming messages | |
log( | |
'Received Message from peer ' + peerId, | |
'----> ' + data.toString() | |
) | |
}) | |
conn.on('close', () => { | |
// Here we handle peer disconnection | |
log(`Connection ${seq} closed, peer id: ${peerId}`) | |
// If the closing connection is the last connection with the peer, removes the peer | |
if (peers[peerId].seq === seq) { | |
delete peers[peerId] | |
} | |
}) | |
// Save the connection | |
if (!peers[peerId]) { | |
peers[peerId] = {} | |
} | |
peers[peerId].conn = conn | |
peers[peerId].seq = seq | |
connSeq++ | |
}) | |
// Read user message from command line | |
askUser() | |
})() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, Carlos,
It's a very interesting example.
You wrote in the article https://medium.com/@carloslfu/make-a-p2p-connection-in-10-minutes-57d9559fd1c that it works in any other computer with internet. I tried, but it's not working if the computers are not in the same LAN. Can you explain how it's possible?