Skip to content

Instantly share code, notes, and snippets.

@1N50MN14
Last active December 12, 2015 02:29
Show Gist options
  • Save 1N50MN14/4699295 to your computer and use it in GitHub Desktop.
Save 1N50MN14/4699295 to your computer and use it in GitHub Desktop.
var net = require('net'),
os = require('os'),
es = require('event-stream'),
Doc = require('crdt').Doc,
uuid = require('node-uuid'),
inherits = require('inherits'),
EventEmitter = require('events').EventEmitter;
module.exports = P2P;
function P2P(seaport) {
var self = this;
if (!(self instanceof P2P)) return new P2P(seaport);
self.docs = new Doc();
self.seaport = seaport;
self.host = localhost();
self.peers = [];
self.initp2plistener = function() {
var self = this;
self.peers.length ? listen() :
self.seaport.get(self.role, function (ps) {
ps.forEach(function(peer) {
isp2pmember(peer) && self.peers.push(peer);
})
self.pos = self.position();
listen();
});
function listen() {
self.on('register', function (peer) {
!exists(peer) && isp2pmember(peer) && self.pushpeer(peer);
});
self.on('free', function (peer) {
var i = exists(peer);
false !== i && isp2pmember(peer) && self.splicepeer(i);
});
self.on('close', function () {
self.server.close();
});
}
}
self.splicepeer = function(pos) {
self.peers.splice(pos,1);
self.autopeer(pos);
}
self.pushpeer = function(peer) {
self.peers.push(peer);
self.pos = self.position();
self.autopeer();
}
self.on('listening', function() {
self.initp2plistener();
});
function localhost() {
var interfaces = os.networkInterfaces(),
addresses = [];
for (k in interfaces) {
for (k2 in interfaces[k]) {
var address = interfaces[k][k2];
if (address.family == 'IPv4') addresses.push(address.address)
}
}
return addresses;
}
function exists(p) {
for (var i=0; i<self.peers.length;i++) {
if (self.peers[i] === p) return i;
};
return false;
}
function isp2pmember(peer) {
return self.role == peer.role+'@'+peer.version;
}
}
P2P.prototype.position = function(p) {
var self = this;
p = p || 0;
for (var i = 0; i < self.peers.length; i++) {
if (self.peers[i].host == self.host[p] && self.peers[i].port == self.port) return i;
};
return (p==self.host.length-1 ? false : self.position(p+1));
}
P2P.prototype.cpeer = function() {
var self = this;
if (self.peers.length == 1) return null;
return (self.pos == self.peers.length - 1 ? self.peers[0] : self.peers[self.pos+1]);
}
P2P.prototype.autopeer = function(rpos) {
var self = this,
cpeer;
cpeer = self.cpeer();
self.cpeer === cpeer
? !self.connected && self.connect(cpeer)
: !self.connected ? self.connect(cpeer) : self.disconnect(function() {self.connect(cpeer)})
}
P2P.prototype.connect = function(p) {
var self = this;
if (!p) return;
console.log('pos is:',self.pos, 'length is:',self.peers.length)
console.log(self.host[0],':',self.port,'connecting to',p.host+':'+p.port)
}
P2P.prototype.disconnect = function() {
console.log('disconnect')
}
P2P.prototype.close = function() {
this.closed = true;
this.emit('close');
}
P2P.prototype.list = function() {
return self.peers;
}
P2P.prototype.createServer = function () {
var self = this,
role,
port,
opts = {},
fn,
args = [].slice.call(arguments);
Object.keys(args).forEach(function(key) {
if (typeof args[key]==='object') opts = args[key];
if (typeof args[key]==='string') role = args[key];
if (typeof args[key]==='function') fn = args[key];
})
self.server = net.createServer(function (stream) {
stream.pipe(self.doc.createStream()).pipe(stream)
}).listen(port = self.seaport.register(role, opts), function() {
self.port = self.server.port = port;
self.role = self.server.role = role;
fn && fn(role, port);
});
self.server.on('listening', self.emit.bind(self, 'listening'));
self.server.on('connection', self.emit.bind(self, 'connection'));
self.seaport.on('register', self.emit.bind(self, 'register'));
self.seaport.on('free', self.emit.bind(self, 'free'));
self.on('close', function () {
self.server.close();
});
return self.server;
};
inherits(P2P, EventEmitter);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment