[Pkg-javascript-commits] [ltx] 63/469: new experimental s2s & router code

Jonas Smedegaard dr at jones.dk
Wed Aug 31 13:01:01 UTC 2016


This is an automated email from the git hooks/post-receive script.

js pushed a commit to branch master
in repository ltx.

commit 6167033750ecb8c13d2724438ca4ece597b687eb
Author: Astro <astro at spaceboyz.net>
Date:   Sat Sep 4 19:47:32 2010 +0200

    new experimental s2s & router code
---
 lib/xmpp.js        |   2 +
 lib/xmpp/router.js | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/xmpp/server.js | 156 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 331 insertions(+)

diff --git a/lib/xmpp.js b/lib/xmpp.js
index e74b311..d63fc36 100644
--- a/lib/xmpp.js
+++ b/lib/xmpp.js
@@ -2,9 +2,11 @@ var Client = require('./xmpp/client').Client;
 var Component = require('./xmpp/component').Component;
 var JID = require('./xmpp/jid').JID;
 var XML = require('./xmpp/xml');
+var Router = require('./xmpp/router');
 
 exports.Client = Client;
 exports.Component = Component;
 exports.JID = JID;
 exports.XML = XML;
 exports.Element = XML.Element;
+exports.Router = Router.Router;
diff --git a/lib/xmpp/router.js b/lib/xmpp/router.js
new file mode 100644
index 0000000..d7d5d11
--- /dev/null
+++ b/lib/xmpp/router.js
@@ -0,0 +1,173 @@
+var net = require('net');
+var Server = require('./server');
+var JID = require('./jid');
+
+
+dbgStream = function(tag, stream) {
+    stream.on('data', function(data) {
+	console.log(tag + ' in: ' + data);
+    });
+    stream.on('error', function(e) {
+	console.log(tag + ' error: ' + e.stack);
+    });
+    stream.on('close', function() {
+	console.log(tag + ' close');
+    });
+    var oldSend = stream.send;
+    stream.send = function(data) {
+	console.log(tag + ' out: ' + data);
+	oldSend.call(stream, data);
+    };
+};
+
+function DomainContext(domain) {
+    this.domain = domain;
+    this.s2sIn = {};
+    this.s2sOut = {};
+}
+
+DomainContext.prototype.getOut = function(domain) {
+    var self = this;
+
+    if (this.s2sOut.hasOwnProperty(domain)) {
+	return this.s2sOut[domain];
+    } else {
+	var outStream = this.s2sOut[domain] =
+	    Server.makeOutgoingServer(domain);
+	outStream.dbKey = generateKey();
+	outStream.addListener('online', function() {
+	    outStream.dialbackKey(self.domain, domain, outStream.dbKey);
+	});
+	outStream.addListener('dialbackResult', function(from, to, isValid) {
+	    console.log({outDialbackResult:arguments});
+	    if (isValid) {
+		outStream.isValid = true;
+		console.log({outStreamQueue:outStream.queue});
+		if (outStream.queue) {
+		    outStream.queue.forEach(function(stanza) {
+			outStream.send(stanza);
+		    });
+		    delete outStream.queue;
+		}
+	    } else {
+		outStream.emit('error', new Error('Dialback failure'));
+	    }
+	});
+	outStream.addListener('error', function() {
+	    // TODO: purge queue
+	    delete self.s2sOut[domain];
+	});
+
+	dbgStream('outgoing', outStream);
+	return outStream;
+    }
+};
+
+DomainContext.prototype.send = function(stanza) {
+    var self = this;
+    // TODO: return on empty to
+    var domain = (new JID.JID(stanza.attrs.to)).domain;
+
+    var outStream = this.getOut(domain);
+    if (outStream.isValid)
+	outStream.send(stanza);
+    else {
+	outStream.queue = outStream.queue || [];
+	outStream.queue.push(stanza);
+    }
+};
+
+DomainContext.prototype.verifyDialback = function(domain, id, key) {
+    var outStream;
+    if (this.s2sOut.hasOwnProperty(domain) &&
+	(outStream = this.s2sOut[domain])) {
+
+	var isValid = outStream.streamAttrs.id === id &&
+	    outStream.dbKey === key;
+
+	outStream.dialbackResult(this.domain, domain, isValid);
+	return isValid;
+    } else
+	return false;
+};
+
+function Router(s2sPort) {
+    var self = this;
+    this.ctxs = {};
+
+    net.createServer(function(stream) {
+	dbgStream('incoming', stream);
+	var domain;
+	stream.verifyDialback = function(from, to, id, key) {
+	    domain = from;
+	    return self.verifyDialback(from, to, id, key);
+	};
+	Server.makeIncomingServer(stream);
+	stream.addListener('dialbackVerify', function(from, to, id, key) {
+	    isValid = self.verifyDialback(from, to, id, key);
+	    stream.dialbackVerified(to, from, id, isValid);
+	});
+	stream.addListener('dialbackKey', function(from, to, key) {
+	    var outStream = self.getContext(to).getOut(from);
+	    var sendVerify = function() {
+		outStream.dialbackVerify(to, from, stream.streamId, key);
+
+		var onVerified;
+		onVerified = function(from, to, id, isValid) {
+		    stream.dialbackResult(to, from, isValid);
+		    
+		    outStream.removeListener('dialbackVerified', onVerified);
+		};
+		outStream.addListener('dialbackVerified', onVerified);
+	    };
+	    if (outStream.writable)
+		sendVerify();
+	    else {
+		var connectHook;
+		var connectHook = function() {
+		    sendVerify();
+		    outStream.removeListener('connect', step);
+		};
+		outStream.addListener('connect', connectHook);
+	    }
+	});
+    }).listen(s2sPort || 5269);
+}
+exports.Router = Router;
+
+Router.prototype.send = function(stanza) {
+    if (stanza.root)
+	stanza = stanza.root();
+
+    console.log({send:stanza});
+    if (stanza.attrs && stanza.attrs.from) {
+	var domain = (new JID.JID(stanza.attrs.from)).domain;
+	this.getContext(domain).send(stanza);
+    } else
+	throw 'Sending stanza without destination';
+};
+
+Router.prototype.hasContext = function(domain) {
+    return this.ctxs.hasOwnProperty(domain);
+};
+
+Router.prototype.getContext = function(domain) {
+    if (this.ctxs.hasOwnProperty(domain))
+	return this.ctxs[domain];
+    else
+	return (this.ctxs[domain] = new DomainContext(domain));
+};
+
+Router.prototype.verifyDialback = function(from, to, id, key) {
+    return this.hasContext(to) &&
+	this.getContext(to).verifyDialback(from, id, key);
+};
+
+
+function generateKey() {
+    var r = new Buffer(16);
+    for(var i = 0; i < r.length; i++) {
+	r[i] = 48 + Math.floor(Math.random() * 10);  // '0'..'9'
+    }
+    return r.toString();
+}
diff --git a/lib/xmpp/server.js b/lib/xmpp/server.js
new file mode 100644
index 0000000..b2582ae
--- /dev/null
+++ b/lib/xmpp/server.js
@@ -0,0 +1,156 @@
+var dns = require('dns');
+var Connection = require('./connection');
+var xml = require('./xml');
+
+var NS_SERVER = 'jabber:server';
+var NS_DIALBACK = 'jabber:server:dialback';
+
+/**
+ * Dialback-specific events:
+ * (1) dialbackKey(from, to, key)
+ * (2) dialbackVerify(from, to, id, key)
+ * (3) dialbackVerified(from, to, id, isValid)
+ * (4) dialbackResult(from, to, isValid)
+ */
+function initServer(self) {
+    self.xmlns = NS_SERVER;
+    self.xmppVersion = '1.0';
+
+    self.addListener('rawStanza', function(stanza) {
+	var key = stanza.getText();
+
+	if (stanza.is('result', NS_DIALBACK) &&
+	    stanza.attrs.from && stanza.attrs.to &&
+	    key.length > 0) {
+
+	    self.emit('dialbackKey',
+		      stanza.attrs.from, stanza.attrs.to,
+		      key);
+
+	} else if (stanza.is('verify', NS_DIALBACK) &&
+		   stanza.attrs.from && stanza.attrs.to &&
+		   stanza.attrs.id && key.length > 0) {
+
+	    self.emit('dialbackVerify',
+		      stanza.attrs.from, stanza.attrs.to,
+		      stanza.attrs.id, key);
+
+	} else if (stanza.is('verify', NS_DIALBACK) &&
+		   stanza.attrs.from && stanza.attrs.to &&
+		   stanza.attrs.id && stanza.attrs.type) {
+
+	    self.emit('dialbackVerified',
+		      stanza.attrs.from, stanza.attrs.to,
+		      stanza.attrs.id, stanza.attrs.type == 'valid');
+
+	} else if (stanza.is('result', NS_DIALBACK) &&
+		   stanza.attrs.from && stanza.attrs.to &&
+		   stanza.attrs.type) {
+
+	    self.emit('dialbackResult',
+		      stanza.attrs.from, stanza.attrs.to,
+		      stanza.attrs.type == 'valid');
+	} else
+	    self.emit('stanza', stanza);
+    });
+    
+    self.dialbackKey = function(from, to, key) {
+	self.send(new xml.Element('db:result', { to: to,
+						 from: from }).
+		  t(key)
+		 );	
+    };
+    self.dialbackVerify = function(from, to, id, key) {
+	self.send(new xml.Element('db:verify', { to: to,
+						 from: from,
+						 id: id }).
+		  t(key)
+		 );
+    };
+    self.dialbackVerified = function(from, to, id, isValid) {
+	self.send(new xml.Element('db:verify', { to: to,
+						 from: from,
+						 id: id,
+						 type: isValid ? 'valid' : 'invalid' })
+		 );
+    };
+    self.dialbackResult = function(from, to, isValid) {
+	self.send(new xml.Element('db:result', { to: to,
+						 from: from,
+						 type: isValid ? 'valid' : 'invalid' })
+		 );	
+    };
+}
+
+exports.makeIncomingServer = function(self) {
+    Connection.makeConnection(self);
+
+    initServer(self);
+    self.startStream();
+    self.streamId = generateId();
+
+    self.addListener('streamStart', function(streamAttrs) {
+	var tag = "<stream:stream xmlns='" + self.xmlns +
+	    "' xmlns:stream='" + Connection.NS_STREAM +
+	    "' xmlns:db='" + NS_DIALBACK +
+	    "' id='" + self.streamId + "'";
+	if (self.xmppVersion)
+	    tag += " version='" + self.xmppVersion + "'";
+	tag += "><stream:features/>";
+	self.send(tag);
+    });
+
+    return self;
+};
+
+function dnsLookup(domain, cb) {
+    dns.resolveSrv('_xmpp-server._tcp.' + domain, function(error, data) {
+	if (data[0])
+	    cb(data[0].name, data[0].port);
+	else
+	    dns.resolveSrv('_jabber._tcp.' + domain, function(error, data) {
+		if (data[0])
+		    cb(data[0].name, data[0].port);
+		else
+		    cb(domain, 5269);
+	    });
+    });
+}
+
+exports.makeOutgoingServer = function(domain) {
+    var self = new Connection.Connection();
+    initServer(self);
+    self.startStream = function() {
+	Connection.Connection.prototype.startStream.call(self);
+
+	var tag = "<stream:stream xmlns='" + self.xmlns +
+	    "' xmlns:stream='" + Connection.NS_STREAM +
+	    "' xmlns:db='" + NS_DIALBACK +
+	    "' to='" + domain + "'";
+	if (self.xmppVersion)
+	    tag += " version='" + self.xmppVersion + "'";
+	tag += ">";
+	self.send(tag);
+    };
+
+    dnsLookup(domain, function(host, port) {
+	self.connect(port, host);
+	self.addListener('connect', self.startStream);
+    });
+
+    self.addListener('rawStanza', function(stanza) {
+	if (stanza.is('features', Connection.NS_STREAM)) {
+	    self.emit('online');
+	}
+    });
+
+    return self;
+};
+
+function generateId() {
+    var r = new Buffer(16);
+    for(var i = 0; i < r.length; i++) {
+	r[i] = 48 + Math.floor(Math.random() * 10);  // '0'..'9'
+    }
+    return r.toString();
+};

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/ltx.git



More information about the Pkg-javascript-commits mailing list