7 - Gossiping P2P Chat.

So, there is a problem with problem 6.

Run this commands in 3 different terminals.

node peer.js eduardo localhost:3000 localhost:3001
node peer.js mafintosh localhost:3001 localhost:3002
node peer.js watson localhost:3002

If you try to run this you'll notice that eudardo's and watson's messages are not getting to every peer. That is because the network is no longer fully connected (we intentionally made it not be). Not all p2p networks are going to be fully connected, so we have to find a way to deal with this.

Tips

So of course we would build up on the problem 6 solution, here is ours.

var topology = require('fully-connected-topology')
var jsonStream = require('duplex-json-stream')
var streamSet = require('stream-set')

var username = process.argv[2]
var me = process.argv[3]
var peers = process.argv.slice(4)

var swarm = topology(me, peers)
var connections = streamSet()

swarm.on('connection', function (socket, id) {
  console.log('info> new connection from', id)

  socket = jsonStream(socket)
  socket.on('data', function (data) {
    console.log(data.username + '> ' + data.message)
  })

  connections.add(socket)
})

process.stdin.on('data', function (data) {
  connections.forEach(function (socket) {
    var message = data.toString().trim()
    socket.write({username: username, message: message})
  })
})

In the example at the beginning the resulting network would be like this

eduardo <-> mafintosh <-> watson

So there is no direct link between eduardo and watson, but they should be able to send each other messages through mafintosh. One could feel tempted to just make the peers send forward every message they receive but this would constitute and infinite chain of messages. But we can build up on that.

If every peer creates an auto numeric sequence of the messages they send out, every peer can keep track of the latest message they have received from a specific peer.

So for instance, when eduardo sends a message out, he would include a sequence number, the first one would be number 1, the second number 2 the third 3 and so on, so for the fourth message it would be message '4'. When mafintosh receives it, he checks that it is newer than the last message he received from eduardo by comparing the sequence numbers. Because it is newer he prints it out and sends it forward to all connected peers. When watson receives it he goes through the same process of comparison and sends it back to mafintosh. This time, mafintosh compares sequence numbers and determines that he already received this message, so he just ignores it.

Note that you only have to store the latest message in order to make the comparison.

There are of course some redundant messages sent, so this protocol is not perfect, but it is a simple way to solve the problem.

To do this, you're gonna need a seq variable and an id. You cannot use the username as an id, since, on restart, the seq number would be reset to 0 and your messages won't be received by anybody, so you need to make it a random number.

var seq = 0
var id = Math.random()

Then you would need to modify the part where you send the message. Along with the message and username, the seq number should be sent with each message.

Code also has to be added to ignore message that have already been received (or sent), so the peer should only process the message if the message sequence is bigger than the biggest received so far, and when this happens the object that tracks received messages sequences should be updated.

Testing.

Run the example on the problem definition and it should work now.

When you are done click here to go to the next exercise