Skip to content

Instantly share code, notes, and snippets.

@carloslfu
Last active April 16, 2023 20:01
Show Gist options
  • Save carloslfu/ec389a3d55e07edbf48e23fbd8d65689 to your computer and use it in GitHub Desktop.
Save carloslfu/ec389a3d55e07edbf48e23fbd8d65689 to your computer and use it in GitHub Desktop.
Make a P2P connection in 10 minutes
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()
})()
@alexvirtech
Copy link

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment