[Pkg-javascript-commits] [ltx] 159/469: remove unneeded node-xmpp files
Jonas Smedegaard
dr at jones.dk
Wed Aug 31 13:01:19 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 19024a98db6b18644969073b4a801f71ea1ba356
Author: Astro <astro at spaceboyz.net>
Date: Sun Nov 21 01:24:49 2010 +0100
remove unneeded node-xmpp files
---
examples/echo_bot.js | 39 ---
examples/echo_component.js | 42 ---
examples/echo_server.js | 12 -
examples/probe_server.js | 57 -----
examples/send_message.js | 30 ---
examples/send_message_component.js | 34 ---
lib/idle_timeout.js | 25 --
lib/node-xmpp.js | 12 -
lib/stream_shaper.js | 25 --
lib/xmpp.js | 3 -
lib/xmpp/client.js | 206 ---------------
lib/xmpp/component.js | 65 -----
lib/xmpp/connection.js | 235 -----------------
lib/xmpp/jid.js | 70 -----
lib/xmpp/router.js | 511 -------------------------------------
lib/xmpp/sasl.js | 174 -------------
lib/xmpp/server.js | 186 --------------
lib/xmpp/srv.js | 147 -----------
lib/xmpp/stream_parser.js | 84 ------
test/test_jid.js | 100 --------
20 files changed, 2057 deletions(-)
diff --git a/examples/echo_bot.js b/examples/echo_bot.js
deleted file mode 100644
index 5c55c36..0000000
--- a/examples/echo_bot.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Echo Bot - the XMPP Hello World
- **/
-var sys = require('sys');
-var xmpp = require('../lib/node-xmpp');
-var argv = process.argv;
-
-if (argv.length != 4) {
- sys.puts('Usage: node echo_bot.js <my-jid> <my-password>');
- process.exit(1);
-}
-
-var cl = new xmpp.Client({ jid: argv[2],
- password: argv[3] });
-cl.on('online',
- function() {
- cl.send(new xmpp.Element('presence',
- { type: 'chat'}).
- c('show').t('chat').up().
- c('status').t('Happily echoing your <message/> stanzas')
- );
- });
-cl.on('stanza',
- function(stanza) {
- if (stanza.is('message') &&
- // Important: never reply to errors!
- stanza.attrs.type !== 'error') {
-
- // Swap addresses...
- stanza.attrs.to = stanza.attrs.from;
- delete stanza.attrs.from;
- // and send back.
- cl.send(stanza);
- }
- });
-cl.on('error',
- function(e) {
- sys.puts(e);
- });
diff --git a/examples/echo_component.js b/examples/echo_component.js
deleted file mode 100644
index 45583ce..0000000
--- a/examples/echo_component.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Echo Component - the XMPP Hello World
- **/
-var sys = require('sys');
-var xmpp = require('../lib/node-xmpp');
-var argv = process.argv;
-
-if (argv.length != 6) {
- sys.puts('Usage: node echo_bot.js <my-jid> <my-password> <host> <port>');
- process.exit(1);
-}
-
-var cl = new xmpp.Component({ jid: argv[2],
- password: argv[3],
- host: argv[4],
- port: argv[5] });
-cl.on('online',
- function() {
- cl.send(new xmpp.Element('presence',
- { type: 'chat'}).
- c('show').t('chat').up().
- c('status').t('Happily echoing your <message/> stanzas')
- );
- });
-cl.on('stanza',
- function(stanza) {
- if (stanza.is('message') &&
- // Important: never reply to errors!
- stanza.attrs.type !== 'error') {
-
- // Swap addresses...
- var me = stanza.attrs.to;
- stanza.attrs.to = stanza.attrs.from;
- stanza.attrs.from = me;
- // and send back.
- cl.send(stanza);
- }
- });
-cl.on('error',
- function(e) {
- sys.puts(e);
- });
diff --git a/examples/echo_server.js b/examples/echo_server.js
deleted file mode 100644
index b6f5402..0000000
--- a/examples/echo_server.js
+++ /dev/null
@@ -1,12 +0,0 @@
-var xmpp = require('../lib/node-xmpp');
-
-var r = new xmpp.Router();
-r.register('codetu.be', function(stanza) {
- console.log("<< "+stanza.toString());
- if (stanza.attrs.type !== 'error') {
- var me = stanza.attrs.to;
- stanza.attrs.to = stanza.attrs.from;
- stanza.attrs.from = me;
- r.send(stanza);
- }
-});
diff --git a/examples/probe_server.js b/examples/probe_server.js
deleted file mode 100644
index bde02b9..0000000
--- a/examples/probe_server.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * This example establishes some s2s connections over time. It is a
- * router test. You must modify it!
- */
-var xmpp = require('../lib/node-xmpp');
-
-var MY_JID = 'codetu.be';
-var r = new xmpp.Router();
-r.loadCredentials('codetu.be', 'codetube.key', 'codetube.crt');
-
-r.register(MY_JID, function(stanza) {
- var time = Date.now();
- var query;
-
- if (stanza.is('iq') &&
- stanza.attrs.type == 'result' &&
- (query = stanza.getChild('query', 'jabber:iq:version'))) {
-
- var name = query.getChildText('name');
- var version = query.getChildText('version');
- var os = query.getChildText('os');
- console.log(time + " >> " + stanza.attrs.from + " " +
- [name, version, os].join('/'));
- } else if (stanza.is('iq') &&
- stanza.attrs.type == 'error') {
- console.log(time + " !! " + stanza.attrs.from);
- } else {
- console.log(time + " ?? " + stanza.toString());
- }
-});
-process.on('SIGINT', function() {
- r.unregister(MY_JID);
- process.nextTick(function() {
- process.exit(0);
- });
-});
-
-
-var PROBE_DOMAINS = ["spaceboyz.net", "jabber.ccc.de",
- "gmail.com", "jabber.org",
- "jabbim.cz", "jabber.ru",
- "process-one.net", "gtalk2voip.com",
- "swissjabber.ch", "aspsms.swissjabber.ch",
- "icq.hq.c3d2.de", "codetu.be",
- "webkeks.org"];
-function probe() {
- setTimeout(probe, Math.floor((Math.random() * 15 + 5) * 1000));
-
- var to = PROBE_DOMAINS[Math.floor(Math.random() * PROBE_DOMAINS.length)];
- r.send(new xmpp.Element('iq', { type: 'get',
- to: to,
- from: MY_JID
- }).
- c('query', { xmlns: 'jabber:iq:version' })
- );
-}
-probe();
diff --git a/examples/send_message.js b/examples/send_message.js
deleted file mode 100644
index 85040ba..0000000
--- a/examples/send_message.js
+++ /dev/null
@@ -1,30 +0,0 @@
-var sys = require('sys');
-var xmpp = require('../lib/node-xmpp');
-var argv = process.argv;
-
-if (argv.length < 6) {
- sys.puts('Usage: node send_message.js <my-jid> <my-password> <my-text> <jid1> [jid2] ... [jidN]');
- process.exit(1);
-}
-
-var cl = new xmpp.Client({ jid: argv[2],
- password: argv[3] });
-cl.addListener('online',
- function() {
- argv.slice(5).forEach(
- function(to) {
- cl.send(new xmpp.Element('message',
- { to: to,
- type: 'chat'}).
- c('body').
- t(argv[4]));
- });
-
- // nodejs has nothing left to do and will exit
- cl.end();
- });
-cl.addListener('error',
- function(e) {
- sys.puts(e);
- process.exit(1);
- });
diff --git a/examples/send_message_component.js b/examples/send_message_component.js
deleted file mode 100644
index ae2b66a..0000000
--- a/examples/send_message_component.js
+++ /dev/null
@@ -1,34 +0,0 @@
-var sys = require('sys');
-var xmpp = require('../lib/node-xmpp');
-var argv = process.argv;
-
-if (argv.length < 6) {
- sys.puts('Usage: node send_message.js <my-jid> <my-password> <server> <port> <my-text> <jid1> [jid2] ... [jidN]');
- process.exit(1);
-}
-
-var c = new xmpp.Component({ jid: argv[2],
- password: argv[3],
- host: argv[4],
- port: Number(argv[5])
- });
-c.addListener('online',
- function() {
- argv.slice(7).forEach(
- function(to) {
- c.send(new xmpp.Element('message',
- { to: to,
- from: c.jid,
- type: 'chat'}).
- c('body').
- t(argv[4]));
- });
-
- // nodejs has nothing left to do and will exit
- c.end();
- });
-c.addListener('error',
- function(e) {
- sys.puts(e);
- process.exit(1);
- });
diff --git a/lib/idle_timeout.js b/lib/idle_timeout.js
deleted file mode 100644
index 50a84e7..0000000
--- a/lib/idle_timeout.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Emulates stream.setTimeout() behaviour, but respects outgoing data
- * too.
- *
- * @param {Number} timeout Milliseconds
- */
-exports.attach = function(stream, timeout) {
- var timer;
- var emitTimeout = function() {
- timer = undefined;
- stream.emit('timeout');
- };
- var updateTimer = function() {
- if (timer)
- clearTimeout(timer);
- timer = setTimeout(emitTimeout, timeout);
- };
-
- var oldWrite = stream.write;
- stream.write = function() {
- updateTimer();
- oldWrite.apply(this, arguments);
- };
- stream.addListener('data', updateTimer);
-};
diff --git a/lib/node-xmpp.js b/lib/node-xmpp.js
deleted file mode 100644
index d63fc36..0000000
--- a/lib/node-xmpp.js
+++ /dev/null
@@ -1,12 +0,0 @@
-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/stream_shaper.js b/lib/stream_shaper.js
deleted file mode 100644
index ef03831..0000000
--- a/lib/stream_shaper.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * This is extremely simple and unprecise.
- *
- * @param {Number} rateLimit B/ms or KB/s
- */
-exports.attach = function(stream, rateLimit) {
- var timer;
- stream.rateLimit = rateLimit; // makes it readjustable after attachment
- stream.addListener('data', function(data) {
- if (timer)
- clearTimeout(timer);
-
- stream.pause();
- var sleep = Math.floor(data.length / stream.rateLimit);
- timer = setTimeout(function() {
- timer = undefined;
- stream.resume();
- }, sleep);
- });
- stream.addListener('close', function() {
- // don't let the last timeout inhibit node shutdown
- if (timer)
- clearTimeout(timeout);
- });
-};
diff --git a/lib/xmpp.js b/lib/xmpp.js
deleted file mode 100644
index a0d5e5e..0000000
--- a/lib/xmpp.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var node_xmpp = require('./node-xmpp');
-for(var k in node_xmpp)
- exports[k] = node_xmpp[k];
diff --git a/lib/xmpp/client.js b/lib/xmpp/client.js
deleted file mode 100644
index ad0f157..0000000
--- a/lib/xmpp/client.js
+++ /dev/null
@@ -1,206 +0,0 @@
-var Connection = require('./connection');
-var JID = require('./jid').JID;
-var xml = require('./xml');
-var sasl = require('./sasl');
-var sys = require('sys');
-var Buffer = require('buffer').Buffer;
-var SRV = require('./srv');
-
-var NS_CLIENT = 'jabber:client';
-var NS_XMPP_SASL = 'urn:ietf:params:xml:ns:xmpp-sasl';
-var NS_XMPP_BIND = 'urn:ietf:params:xml:ns:xmpp-bind';
-var NS_XMPP_SESSION = 'urn:ietf:params:xml:ns:xmpp-session';
-
-var STATE_PREAUTH = 0,
- STATE_AUTH = 1,
- STATE_AUTHED = 2,
- STATE_BIND = 3,
- STATE_SESSION = 4,
- STATE_ONLINE = 5;
-var IQID_SESSION = 'sess',
- IQID_BIND = 'bind';
-
-/**
- * params:
- * jid: String (required)
- * password: String (required)
- * host: String (optional)
- * port: Number (optional)
- */
-function Client(params) {
- var self = this;
- Connection.Connection.call(this);
-
- if (typeof params.jid == 'string')
- this.jid = new JID(params.jid);
- else
- this.jid = params.jid;
- this.password = params.password;
- this.api_key = params.api_key;
- this.secret_key = params.secret_key;
- this.session_key = params.session_key;
- this.xmlns[''] = NS_CLIENT;
- this.xmppVersion = "1.0";
- this.streamTo = this.jid.domain;
- this.state = STATE_PREAUTH;
- this.addListener('rawStanza', this.onRawStanza);
-
- if (params.host) {
- this.socket.connect(params.port || 5222, params.host);
- this.socket.on('connect', function() {
- self.startParser();
- self.startStream();
- });
- } else {
- var attempt = SRV.connect(this.socket,
- ['_xmpp-client._tcp'], this.jid.domain, 5222);
- attempt.addListener('connect', function() {
- self.startParser();
- self.startStream();
- });
- attempt.addListener('error', function(e) {
- self.emit('error', e);
- });
- }
-
- // it's us who must restart after starttls
- this.socket.addListener('secure', function() {
- self.startStream();
- });
- this.socket.addListener('end', function() {
- self.state = STATE_PREAUTH;
- });
-}
-
-sys.inherits(Client, Connection.Connection);
-exports.Client = Client;
-
-Client.prototype.onRawStanza = function(stanza) {
- /* Actually, we shouldn't wait for <stream:features/> if
- this.streamAttrs.version is missing, but who uses pre-XMPP-1.0
- these days anyway? */
- if (this.state != STATE_ONLINE &&
- stanza.is('features', Connection.NS_STREAM)) {
- this.streamFeatures = stanza;
- this.useFeatures();
- } else if (this.state == STATE_AUTH) {
- if (stanza.is('challenge', NS_XMPP_SASL)) {
- var challengeMsg = decode64(stanza.getText());
- var responseMsg = encode64(
- this.mech.challenge(challengeMsg));
- this.send(new xml.Element('response',
- { xmlns: NS_XMPP_SASL
- }).t(responseMsg));
- } else if (stanza.is('success', NS_XMPP_SASL)) {
- this.mech = null;
- this.state = STATE_AUTHED;
- this.startParser();
- this.startStream();
- } else {
- this.emit('error', 'XMPP authentication failure');
- }
- } else if (this.state == STATE_BIND &&
- stanza.is('iq', NS_CLIENT) &&
- stanza.attrs.id == IQID_BIND) {
- if (stanza.attrs.type == 'result') {
- this.state = STATE_AUTHED;
- this.did_bind = true;
-
- var bindEl = stanza.getChild('bind', NS_XMPP_BIND);
- if (bindEl && bindEl.getChild('jid')) {
- this.jid = new JID(bindEl.getChild('jid').getText());
- }
-
- /* no stream restart, but next feature */
- this.useFeatures();
- } else {
- this.emit('error', 'Cannot bind resource');
- }
- } else if (this.state == STATE_SESSION &&
- stanza.is('iq', NS_CLIENT) &&
- stanza.attrs.id == IQID_SESSION) {
- if (stanza.attrs.type == 'result') {
- this.state = STATE_AUTHED;
- this.did_session = true;
-
- /* no stream restart, but next feature (most probably
- we'll go online next) */
- this.useFeatures();
- } else {
- this.emit('error', 'Cannot bind resource');
- }
- } else if (stanza.name == 'stream:error') {
- this.emit('error', stanza);
- } else if (this.state == STATE_ONLINE) {
- this.emit('stanza', stanza);
- }
-};
-
-/**
- * Either we just received <stream:features/>, or we just enabled a
- * feature and are looking for the next.
- */
-Client.prototype.useFeatures = function() {
- if (this.state == STATE_PREAUTH &&
- this.streamFeatures.getChild('mechanisms', NS_XMPP_SASL)) {
- this.state = STATE_AUTH;
- this.mech = sasl.selectMechanism(
- this.streamFeatures.
- getChild('mechanisms', NS_XMPP_SASL).
- getChildren('mechanism', NS_XMPP_SASL).
- map(function(el) { return el.getText(); }));
- if (this.mech) {
- this.mech.authzid = this.jid.bare().toString();
- this.mech.authcid = this.jid.user;
- this.mech.password = this.password;
- this.mech.api_key = this.api_key;
- this.mech.secret_key = this.secret_key;
- this.mech.session_key = this.session_key;
- this.mech.realm = this.jid.domain; // anything?
- this.mech.digest_uri = "xmpp/" + this.jid.domain;
- var authMsg = encode64(this.mech.auth());
- this.send(new xml.Element('auth',
- { xmlns: NS_XMPP_SASL,
- mechanism: this.mech.name
- }).t(authMsg));
- } else {
- this.emit('error', 'No usable SASL mechanism');
- }
- } else if (this.state == STATE_AUTHED &&
- !this.did_bind &&
- this.streamFeatures.getChild('bind', NS_XMPP_BIND)) {
- this.state = STATE_BIND;
- var bindEl = new xml.Element('iq',
- { type: 'set',
- id: IQID_BIND
- }).c('bind',
- { xmlns: NS_XMPP_BIND
- });
- if (this.jid.resource)
- bindEl.c('resource').t(this.jid.resource);
- this.send(bindEl);
- } else if (this.state == STATE_AUTHED &&
- !this.did_session &&
- this.streamFeatures.getChild('session', NS_XMPP_SESSION)) {
- this.state = STATE_SESSION;
- this.send(new xml.Element('iq',
- { type: 'set',
- to: this.jid.domain,
- id: IQID_SESSION
- }).c('session',
- { xmlns: NS_XMPP_SESSION
- }));
- } else if (this.state == STATE_AUTHED) {
- /* Ok, we're authenticated and all features have been
- processed */
- this.state = STATE_ONLINE;
- this.emit('online');
- }
-};
-
-function decode64(encoded) {
- return (new Buffer(encoded, 'base64')).toString('utf8');
-}
-function encode64(decoded) {
- return (new Buffer(decoded, 'utf8')).toString('base64');
-}
diff --git a/lib/xmpp/component.js b/lib/xmpp/component.js
deleted file mode 100644
index 4541c59..0000000
--- a/lib/xmpp/component.js
+++ /dev/null
@@ -1,65 +0,0 @@
-var Connection = require('./connection');
-var JID = require('./jid').JID;
-var xml = require('./xml');
-var sys = require('sys');
-var crypto = require('crypto');
-var SRV = require('./srv');
-
-var NS_COMPONENT = 'jabber:component:accept';
-
-/**
- * params:
- * jid: String (required)
- * password: String (required)
- * host: String (required)
- * port: Number (required)
- */
-function Component(params) {
- var self = this;
- Connection.Connection.call(this);
-
- if (typeof params.jid == 'string')
- this.jid = new JID(params.jid);
- else
- this.jid = params.jid;
- this.password = params.password;
- this.xmlns[''] = NS_COMPONENT;
- this.streamTo = this.jid.domain;
-
- this.addListener('streamStart', function(streamAttrs) {
- self.onStreamStart(streamAttrs);
- });
- this.addListener('rawStanza', function(stanza) {
- self.onRawStanza(stanza);
- });
- var attempt = SRV.connect(this.socket, [], params.host, params.port);
- attempt.addListener('connect', function() {
- self.startParser();
- self.startStream();
- });
- attempt.addListener('error', function(e) {
- self.emit('error', e);
- });
-}
-
-sys.inherits(Component, Connection.Connection);
-exports.Component = Component;
-
-Component.prototype.onStreamStart = function(streamAttrs) {
- var digest = sha1_hex(streamAttrs.id + this.password);
- this.send(new xml.Element('handshake').t(digest));
-};
-
-Component.prototype.onRawStanza = function(stanza) {
- if (stanza.is('handshake', NS_COMPONENT)) {
- this.emit('online');
- } else {
- this.emit('stanza', stanza);
- }
-};
-
-function sha1_hex(s) {
- var hash = crypto.createHash('sha1');
- hash.update(s);
- return hash.digest('hex');
-}
diff --git a/lib/xmpp/connection.js b/lib/xmpp/connection.js
deleted file mode 100644
index 8d98a29..0000000
--- a/lib/xmpp/connection.js
+++ /dev/null
@@ -1,235 +0,0 @@
-var net = require('net');
-var EventEmitter = require('events').EventEmitter;
-var sys = require('sys');
-var xml = require('./xml');
-var StreamParser = require('./stream_parser');
-
-var NS_XMPP_TLS = exports.NS_XMPP_TLS = 'urn:ietf:params:xml:ns:xmpp-tls';
-var NS_STREAM = exports.NS_STREAM = 'http://etherx.jabber.org/streams';
-var NS_XMPP_STREAMS = 'urn:ietf:params:xml:ns:xmpp-streams';
-
-/** A note on events: this base class will emit 'rawStanza' and leaves
- 'stanza' to Client & Component. Therefore we won't confuse the
- user with stanzas before authentication has finished.
-*/
-function Connection(socket) {
- var self = this;
- EventEmitter.call(this);
-
- this.charset = 'UTF-8';
- this.xmlns = { stream: NS_STREAM };
-
- this.socket = socket || new net.Stream();
- this.socket.addListener('data', function(data) {
- self.onData(data);
- });
- this.socket.addListener('end', function() {
- self.onEnd();
- });
- var proxyEvent = function(event) {
- self.socket.addListener(event, function() {
- self.emit.apply(self, Array.prototype.splice.call(arguments, 0, 0, event));
- });
- };
- proxyEvent('data'); // let them sniff
- proxyEvent('drain');
- proxyEvent('close');
-}
-
-sys.inherits(Connection, EventEmitter);
-exports.Connection = Connection;
-
-// Defaults
-Connection.prototype.charset = 'UTF-8';
-Connection.prototype.allowTLS = true;
-
-
-/** Climbs the stanza up if a child was passed,
- but you can send strings and buffers too.
-*/
-Connection.prototype.send = function(stanza) {
- if (!this.socket.writable) {
- this.socket.end();
- return;
- }
-
- if (stanza.root) {
- var el = this.rmStreamNs(stanza.root());
- var socket = this.socket;
- el.write(function(s) { socket.write(s); });
- return el;
- } else {
- this.socket.write(stanza);
- return stanza;
- }
-};
-
-Connection.prototype.startParser = function() {
- var self = this;
- this.parser = new StreamParser.StreamParser(this.charset, this.maxStanzaSize);
-
- this.parser.addListener('start', function(attrs) {
- self.streamAttrs = attrs;
- /* We need those xmlns often, store them extra */
- self.streamNsAttrs = {};
- for(var k in attrs) {
- if (k == 'xmlns' ||
- k.substr(0, 6) == 'xmlns:')
- self.streamNsAttrs[k] = attrs[k];
- }
-
- /* Notify in case we don't wait for <stream:features/>
- (Component or non-1.0 streams)
- */
- self.emit('streamStart', attrs);
- });
- this.parser.addListener('stanza', function(stanza) {
- self.onStanza(self.addStreamNs(stanza));
- });
- this.parser.addListener('error', function(e) {
- self.error(e.condition || 'internal-server-error', e.message);
- });
- this.parser.addListener('end', function() {
- self.stopParser();
- self.end();
- });
-};
-
-Connection.prototype.stopParser = function() {
- delete this.parser;
-};
-
-Connection.prototype.startStream = function() {
- var attrs = {};
- for(var k in this.xmlns) {
- if (this.xmlns.hasOwnProperty(k)) {
- if (!k)
- attrs.xmlns = this.xmlns[k];
- else
- attrs['xmlns:' + k] = this.xmlns[k];
- }
- }
- if (this.xmppVersion)
- attrs.version = this.xmppVersion;
- if (this.streamTo)
- attrs.to = this.streamTo;
- if (this.streamId)
- attrs.id = this.streamId;
-
- var el = new xml.Element('stream:stream', attrs);
- // make it non-empty to cut the closing tag
- el.t(' ');
- var s = el.toString();
- this.send(s.substr(0, s.indexOf(' </stream:stream>')));
-
- this.streamOpened = true;
-};
-
-Connection.prototype.onData = function(data) {
- if (this.parser)
- this.parser.write(data);
-};
-
-Connection.prototype.setSecure = function(credentials) {
- var self = this;
- this.stopParser();
- this.socket.setSecure(credentials || this.credentials);
- this.socket.addListener('secure', function() {
- self.startParser();
- });
-};
-
-/**
- * This is not an event listener, but takes care of the TLS handshake
- * before 'rawStanza' events are emitted to the derived classes.
- */
-Connection.prototype.onStanza = function(stanza) {
- if (stanza.is('error', NS_STREAM)) {
- /* TODO: extract error text */
- this.emit('error', stanza);
- } else if (stanza.is('features', NS_STREAM) &&
- this.allowTLS &&
- stanza.getChild('starttls', NS_XMPP_TLS)) {
- /* Signal willingness to perform TLS handshake */
- this.send(new xml.Element('starttls', { xmlns: NS_XMPP_TLS }));
- } else if (this.allowTLS &&
- stanza.is('proceed', NS_XMPP_TLS)) {
- /* Server is waiting for TLS handshake */
- this.setSecure();
- } else {
- this.emit('rawStanza', stanza);
- }
-};
-
-/**
- * Add stream xmlns to a stanza, so the user can check for
- * 'jabber:client' etc.
- */
-Connection.prototype.addStreamNs = function(stanza) {
- for(var k in this.streamNsAttrs) {
- if (!stanza.attrs[k])
- stanza.attrs[k] = this.streamNsAttrs[k];
- }
- return stanza;
-};
-
-/**
- * Remove superfluous xmlns that were aleady declared in
- * our <stream:stream>
- */
-Connection.prototype.rmStreamNs = function(stanza) {
- for(var k in this.xmlns) {
- var attr = k ? 'xmlns:' + k : 'xmlns';
- if (stanza.attrs[attr] == this.xmlns[k])
- delete stanza.attrs[attr];
- }
- return stanza;
-};
-
-
-/**
- * Connection has been ended by remote, we will not get any incoming
- * 'data' events. Alternatively, used for 'error' event.
- */
-Connection.prototype.onEnd = function() {
- this.stopParser();
- this.socket.end();
-};
-
-/**
- * XMPP-style end connection for user
- */
-Connection.prototype.end = function() {
- if (this.socket.writable) {
- if (this.streamOpened) {
- this.socket.write('</stream:stream>');
- delete this.streamOpened;
- } else {
- this.socket.end();
- }
- }
-};
-
-/**
- * End connection with stream error.
- * Emits 'error' event too.
- *
- * @param {String} condition XMPP error condition, see RFC3920 4.7.3. Defined Conditions
- * @param {String} text Optional error message
- */
-Connection.prototype.error = function(condition, message) {
- this.emit('error', new Error(message));
-
- if (!this.socket.writable)
- return;
-
- var e = new xml.Element('stream:error');
- e.c(condition, { xmlns: NS_XMPP_STREAMS });
- if (message)
- e.c('text', { xmlns: NS_XMPP_STREAMS,
- 'xml:lang': 'en' }).
- t(message);
-
- this.send(e);
- this.end();
-};
diff --git a/lib/xmpp/jid.js b/lib/xmpp/jid.js
deleted file mode 100644
index 5a241d2..0000000
--- a/lib/xmpp/jid.js
+++ /dev/null
@@ -1,70 +0,0 @@
-var StringPrep = require('node-stringprep').StringPrep;
-var nameprep = new StringPrep('nameprep');
-var nodeprep = new StringPrep('nodeprep');
-var resourceprep = new StringPrep('resourceprep');
-
-function JID(a, b, c) {
- if (a && b == null && c == null) {
- this.parseJID(a);
- } else if (b) {
- this.setUser(a);
- this.setDomain(b);
- this.setResource(c);
- } else
- throw 'Argument error';
-}
-
-JID.prototype.parseJID = function(s) {
- if (s.indexOf('@') >= 0) {
- this.setUser(s.substr(0, s.indexOf('@')));
- s = s.substr(s.indexOf('@') + 1);
- }
- if (s.indexOf('/') >= 0) {
- this.setResource(s.substr(s.indexOf('/') + 1));
- s = s.substr(0, s.indexOf('/'));
- }
- this.setDomain(s);
-};
-
-JID.prototype.toString = function() {
- var s = this.domain;
- if (this.user)
- s = this.user + '@' + s;
- if (this.resource)
- s = s + '/' + this.resource;
- return s;
-};
-
-/**
- * Convenience method to distinguish users
- **/
-JID.prototype.bare = function() {
- if (this.resource)
- return new JID(this.user, this.domain, null);
- else
- return this;
-};
-
-/**
- * Comparison function
- **/
-JID.prototype.equals = function(other) {
- return this.user == other.user &&
- this.domain == other.domain &&
- this.resource == other.resource;
-};
-
-/**
- * Setters that do stringprep normalization.
- **/
-JID.prototype.setUser = function(user) {
- this.user = user && nodeprep.prepare(user);
-};
-JID.prototype.setDomain = function(domain) {
- this.domain = domain && nameprep.prepare(domain);
-};
-JID.prototype.setResource = function(resource) {
- this.resource = resource && resourceprep.prepare(resource);
-};
-
-exports.JID = JID;
diff --git a/lib/xmpp/router.js b/lib/xmpp/router.js
deleted file mode 100644
index c1ca9f3..0000000
--- a/lib/xmpp/router.js
+++ /dev/null
@@ -1,511 +0,0 @@
-var net = require('net');
-var Server = require('./server');
-var JID = require('./jid');
-var xml = require('./xml');
-var StreamShaper = require('./../stream_shaper');
-var IdleTimeout = require('./../idle_timeout');
-var StringPrep = require('node-stringprep').StringPrep;
-var nameprep = new StringPrep('nameprep');
-
-var NS_XMPP_SASL = 'urn:ietf:params:xml:ns:xmpp-sasl';
-var NS_XMPP_STANZAS = 'urn:ietf:params:xml:ns:xmpp-stanzas';
-
-
-/**
- * Represents a domain we host with connections to federated servers
- */
-function DomainContext(router, domain) {
- this.router = router;
- this.domain = domain;
- this.s2sIn = {};
- this.s2sOut = {};
-}
-
-/**
- * Buffers until stream has been verified via Dialback
- */
-DomainContext.prototype.send = function(stanza) {
- if (stanza.root)
- stanza = stanza.root();
-
- // no destination? return to ourself
- if (!stanza.attrs.to) {
- // do not provoke ping-pong effects
- if (stanza.attrs.type === 'error')
- return;
-
- stanza.attrs.to = stanza.attrs.from;
- delete stanza.attrs.from;
- stanza.attrs.type = 'error';
- stanza.c('error', { type: 'modify' }).
- c('jid-malformed', { xmlns: NS_XMPP_STANZAS });
- this.receive(stanza);
-
- return;
- }
-
- destDomain = new JID.JID(stanza.attrs.to).domain;
- var outStream = this.getOutStream(destDomain);
-
- if (outStream.isAuthed)
- outStream.send(stanza);
- else {
- // TODO: queues per domain in domaincontext
- outStream.queue = outStream.queue || [];
- outStream.queue.push(stanza);
- }
-};
-
-/**
- * Does only buffer until stream is established, used for Dialback
- * communication itself.
- *
- * returns the stream
- */
-DomainContext.prototype.sendRaw = function(stanza, destDomain) {
- if (stanza.root)
- stanza = stanza.root();
-
- var outStream = this.getOutStream(destDomain);
- var send = function() {
- outStream.send(stanza);
- };
-
- if (outStream.isConnected)
- send();
- else
- outStream.addListener('online', send);
-
- return outStream;
-};
-
-/**
- * Establish outgoing stream on demand
- */
-DomainContext.prototype.getOutStream = function(destDomain) {
- var self = this;
-
- // unfortunately we cannot use the incoming streams
-
- if (!destDomain) {
- throw new Error('Trying to reach empty domain');
- } else if (this.s2sOut.hasOwnProperty(destDomain)) {
- // There's one already
- return this.s2sOut[destDomain];
- } else {
- var credentials = this.router.credentials[this.domain];
- // Setup a new outgoing connection
- var outStream = new Server.OutgoingServer(this.domain, destDomain, credentials);
- this.s2sOut[destDomain] = outStream;
-
- this.router.setupStream(outStream);
- this.setupStream(destDomain, outStream);
-
- var closeCb = function() {
- // purge queue
- if (outStream.queue) {
- outStream.queue.forEach(function(stanza) {
- // do not provoke ping-pong effects
- if (stanza.attrs.type === 'error')
- return;
-
- var dest = stanza.attrs.to;
- stanza.attrs.to = stanza.attrs.from;
- stanza.attrs.from = dest;
- stanza.attrs.type = 'error';
- stanza.c('error', { type: 'cancel' }).
- c('remote-server-not-found', { xmlns: NS_XMPP_STANZAS });
- self.receive(stanza);
- });
- }
- delete outStream.queue;
-
- // remove from DomainContext
- delete self.s2sOut[destDomain];
- };
- outStream.addListener('close', closeCb);
- outStream.addListener('error', closeCb);
-
- var onAuth = function(method) {
- outStream.isConnected = true;
- switch(method) {
- case 'dialback':
- self.startDialback(destDomain, outStream);
- break;
-
- case 'external':
- outStream.send(new xml.Element('auth', { xmlns: NS_XMPP_SASL,
- mechanism: 'EXTERNAL' }).
- t(new Buffer(self.domain).toString('base64'))
- );
- var onStanza;
- onStanza = function(stanza) {
- if (stanza.is('success', NS_XMPP_SASL)) {
- outStream.startParser();
- outStream.startStream();
- outStream.removeListener('stanza', onStanza);
- var onStream;
- onStream = function() {
- outStream.emit('online');
- outStream.removeListener('streamStart', onStream);
- };
- outStream.addListener('streamStart', onStream);
- } else if (stanza.is('failure', NS_XMPP_SASL))
- outStream.end();
- };
- outStream.addListener('stanza', onStanza);
- break;
-
- default:
- outStream.error('undefined-condition',
- 'Cannot authenticate via ' + method);
- }
- outStream.removeListener('auth', onAuth);
- };
- outStream.addListener('auth', onAuth);
-
- outStream.addListener('online', function() {
- outStream.isAuthed = true;
- if (outStream.queue) {
- outStream.queue.forEach(function(stanza) {
- outStream.send(stanza);
- });
- delete outStream.queue;
- }
- });
-
- return outStream;
- }
-};
-
-/**
- * Called by router when verification is done
- */
-DomainContext.prototype.addInStream = function(srcDomain, stream) {
- var self = this;
-
- if (this.s2sIn.hasOwnProperty(srcDomain)) {
- // Replace old
- var oldStream = this.s2sIn[srcDomain];
- oldStream.error('conflict', 'Connection replaced');
- delete self.s2sIn[srcDomain];
- }
-
- this.setupStream(srcDomain, stream);
- stream.isConnected = true;
- stream.isAuthed = true;
- var closeCb = function() {
- if (self.s2sIn[srcDomain] == stream)
- delete self.s2sIn[srcDomain];
- };
- stream.addListener('close', closeCb);
- stream.addListener('error', closeCb);
- this.s2sIn[srcDomain] = stream;
-};
-
-DomainContext.prototype.setupStream = function(domain, stream) {
- var self = this;
-
- stream.addListener('stanza', function(stanza) {
- // Before verified they can send whatever they want
- if (!stream.isAuthed)
- return;
-
- if (stanza.name !== 'message' &&
- stanza.name !== 'presence' &&
- stanza.name !== 'iq')
- // no normal stanza
- return;
-
-
- if (!(typeof stanza.attrs.from === 'string' &&
- typeof stanza.attrs.to === 'string')) {
- stream.error('improper-addressing');
- return;
- }
-
- // Only accept 'from' attribute JIDs that have the same domain
- // that we validated the stream for
- var fromDomain = (new JID.JID(stanza.attrs.from)).domain;
- if (fromDomain !== domain) {
- stream.error('invalid-from');
- return;
- }
-
- // Only accept 'to' attribute JIDs to this DomainContext
- var toDomain = (new JID.JID(stanza.attrs.to)).domain;
- if (toDomain !== self.domain) {
- stream.error('improper-addressing');
- return;
- }
-
- self.receive(stanza);
- });
-};
-
-// we want to get our outgoing connection verified, sends <db:result/>
-DomainContext.prototype.startDialback = function(destDomain, outStream) {
- outStream.dbKey = generateKey();
- outStream.send(Server.dialbackKey(this.domain, destDomain, outStream.dbKey));
-
- var self = this;
- var onResult = function(from, to, isValid) {
- if (from != destDomain ||
- to != self.domain)
- // not for us
- return;
-
- outStream.removeListener('dialbackResult', onResult);
- if (isValid) {
- outStream.emit('online');
- } else {
- // we cannot do anything else with this stream that
- // failed dialback
- outStream.end();
- }
- };
- outStream.addListener('dialbackResult', onResult);
-};
-
-// incoming verification request for our outgoing connection that came
-// in via an inbound server connection
-DomainContext.prototype.verifyDialback = function(domain, id, key, cb) {
- var self = this;
- var outStream;
- if (this.s2sOut.hasOwnProperty(domain) &&
- (outStream = this.s2sOut[domain])) {
-
- if (outStream.isConnected) {
- var isValid = outStream.streamAttrs.id === id &&
- outStream.dbKey === key;
- cb(isValid);
- } else {
- // Not online, wait for outStream.streamAttrs
- // (they may have our stream header & dialback key, but
- // our slow connection hasn't received their stream
- // header)
- outStream.addListener('online', function() {
- // recurse
- self.verifyDialback(domain, id, key, cb);
- });
- outStream.addListener('close', function() {
- cb(false);
- });
- }
- } else
- cb(false);
-};
-
-DomainContext.prototype.verifyIncoming = function(fromDomain, inStream, dbKey) {
- var self = this;
- var outStream = this.sendRaw(Server.dialbackVerify(this.domain, fromDomain,
- inStream.streamId, dbKey),
- fromDomain);
-
- // these are needed before for removeListener()
- var onVerified = function(from, to, id, isValid) {
- from = nameprep.prepare(from);
- to = nameprep.prepare(to);
- if (from !== fromDomain ||
- to !== self.domain ||
- id != inStream.streamId)
- // not for us
- return;
-
- // tell them about it
- inStream.send(Server.dialbackResult(to, from, isValid));
-
- if (isValid) {
- // finally validated them!
- self.addInStream(from, inStream);
- } else {
- // the connection isn't used for another domain, so
- // closing is safe
- inStream.send('</stream:stream>');
- inStream.end();
- }
-
- rmCbs();
- };
- var onClose = function() {
- // outgoing connection didn't work out, tell the incoming
- // connection
- inStream.send(Server.dialbackResult(to, from, false));
-
- rmCbs();
- };
- var onCloseIn = function() {
- // t'was the incoming stream that wanted to get
- // verified, nothing to do remains
-
- rmCbs();
- };
- var rmCbs = function() {
- outStream.removeListener('dialbackVerified', onVerified);
- outStream.removeListener('close', onClose);
- inStream.removeListener('close', onCloseIn);
- };
- outStream.addListener('dialbackVerified', onVerified);
- outStream.addListener('close', onClose);
- inStream.addListener('close', onCloseIn);
-
-};
-
-DomainContext.prototype.receive = function(stanza) {
- if (this.stanzaListener)
- this.stanzaListener(stanza);
-};
-
-DomainContext.prototype.end = function() {
- var shutdown = function(conns) {
- for(var domain in conns)
- if (conns.hasOwnProperty(domain))
- conns[domain].end();
- };
- shutdown(this.s2sOut);
- shutdown(this.s2sIn);
-};
-
-/**
- * Accepts incoming S2S connections. Handles routing of outgoing
- * stanzas, and allows you to register a handler for your own domain.
- *
- * TODO:
- * * Incoming SASL EXTERNAL with certificate validation
- */
-function Router(s2sPort, bindAddress) {
- var self = this;
- this.ctxs = {};
-
- net.createServer(function(inStream) {
- self.acceptConnection(inStream);
- }).listen(s2sPort || 5269, bindAddress || '::');
-}
-exports.Router = Router;
-
-// Defaults
-Router.prototype.rateLimit = 100; // 100 KB/s, it's S2S after all
-Router.prototype.maxStanzaSize = 65536; // 64 KB, by convention
-Router.prototype.keepAlive = 30 * 1000; // 30s
-Router.prototype.streamTimeout = 5 * 60 * 1000; // 5min
-Router.prototype.credentials = {}; // TLS credentials per domain
-
-// little helper, because dealing with crypto & fs gets unwieldy
-Router.prototype.loadCredentials = function(domain, keyPath, certPath) {
- var crypto = require('crypto');
- var fs = require('fs');
-
- var key = fs.readFileSync(keyPath, 'ascii');
- var cert = fs.readFileSync(certPath, 'ascii');
-
- this.credentials[domain] = crypto.createCredentials({ key: key,
- cert: cert });
-};
-
-Router.prototype.acceptConnection = function(socket) {
- var self = this;
-
- var inStream = new Server.IncomingServer(socket, this.credentials);
- this.setupStream(inStream);
-
- // Unhandled 'error' events will trigger exceptions, don't let
- // that happen:
- socket.addListener('error', function() { });
- inStream.addListener('error', function() { });
-
- // incoming server wants to verify an outgoing connection of ours
- inStream.addListener('dialbackVerify', function(from, to, id, key) {
- from = nameprep.prepare(from);
- to = nameprep.prepare(to);
-
- if (self.hasContext(to)) {
- self.getContext(to).verifyDialback(from, id, key, function(isValid) {
- // look if this was a connection of ours
- inStream.send(Server.dialbackVerified(to, from, id, isValid));
- });
- } else
- // we don't host the 'to' domain
- inStream.send(Server.dialbackVerified(to, from, id, false));
- });
- // incoming connection wants to get verified
- inStream.addListener('dialbackKey', function(from, to, key) {
- from = nameprep.prepare(from);
- to = nameprep.prepare(to);
-
- if (self.hasContext(to)) {
- // trigger verification via outgoing connection
- self.getContext(to).verifyIncoming(from, inStream, key);
- } else {
- inStream.error('host-unknown', to + ' is not served here');
- }
- });
-};
-
-Router.prototype.setupStream = function(stream) {
- stream.maxStanzaSize = this.maxStanzaSize;
- StreamShaper.attach(stream.socket, this.rateLimit);
- stream.socket.setKeepAlive(true, this.keepAlive);
- IdleTimeout.attach(stream.socket, this.streamTimeout);
- stream.socket.addListener('timeout', function() {
- stream.error('connection-timeout');
- });
-};
-
-/**
- * Create domain context & register a stanza listener callback
- */
-Router.prototype.register = function(domain, listener) {
- domain = nameprep.prepare(domain);
- this.getContext(domain).stanzaListener = listener;
-};
-
-/**
- * Unregister a context and stop its connections
- */
-Router.prototype.unregister = function(domain) {
- if (this.hasContext(domain)) {
- this.ctxs[domain].end();
-
- delete this.ctxs[domain];
- }
-};
-
-Router.prototype.send = function(stanza) {
- if (stanza.root)
- stanza = stanza.root();
-
- var to = stanza.attrs && stanza.attrs.to;
- var toDomain = to && (new JID.JID(to)).domain;
- if (toDomain && this.hasContext(toDomain)) {
- // inner routing
- this.getContext(toDomain).receive(stanza);
- } else if (stanza.attrs && stanza.attrs.from) {
- // route to domain context for s2s
- var domain = (new JID.JID(stanza.attrs.from)).domain;
- this.getContext(domain).send(stanza);
- } else
- throw 'Sending stanza from a domain we do not host';
-};
-
-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(this, domain));
-};
-
-
-/**
- * TODO: According to XEP-0185 we should hash from, to & streamId
- */
-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/sasl.js b/lib/xmpp/sasl.js
deleted file mode 100644
index 53748db..0000000
--- a/lib/xmpp/sasl.js
+++ /dev/null
@@ -1,174 +0,0 @@
-var crypto = require('crypto');
-var querystring = require('querystring');
-
-function selectMechanism(mechs) {
- if (mechs.indexOf("X-FACEBOOK-PLATFORM") >= 0)
- return new XFacebookPlatform();
- else if (mechs.indexOf("DIGEST-MD5") >= 0)
- return new DigestMD5();
- else if (mechs.indexOf("PLAIN") >= 0)
- return new Plain();
- else if (mechs.indexOf("ANONYMOUS") >= 0)
- return new Anonymous();
- else
- return null;
-}
-exports.selectMechanism = selectMechanism;
-
-function Plain() {
- this.name = "PLAIN";
- this.auth = function() {
- return this.authzid + "\0" +
- this.authcid + "\0" +
- this.password;
- };
-}
-
-function XFacebookPlatform() {
- this.name = "X-FACEBOOK-PLATFORM";
- this.auth = function() {
- return "";
- };
- this.challenge = function(s) {
- var dict = querystring.parse(s);
-
- var response = {
- api_key: this.api_key,
- call_id: new Date().getTime(),
- method: dict.method,
- nonce: dict.nonce,
- session_key: this.session_key,
- v: "1.0"
- };
-
- var message = '';
- ['api_key', 'call_id', 'method', 'nonce', 'session_key', 'v'].forEach(function(v) {
- message += v + "=" + response[v];
- });
-
- response.sig = md5(message + this.secret_key, 'hex');
-
- return querystring.stringify(response);
- };
-}
-
-function Anonymous() {
- this.name = "ANONYMOUS";
- this.auth = function() {
- return this.authzid;
- };
-}
-
-function DigestMD5() {
- this.name = "DIGEST-MD5";
- this.auth = function() {
- return "";
- };
-
- this.nonce_count = 0;
- this.getNC = function() {
- return rjust(this.nonce_count.toString(), 8, '0');
- };
- this.cnonce = generateNonce();
- this.challenge = function(s) {
- var dict = parseDict(s);
- if (dict.realm)
- this.realm = dict.realm;
- //require('sys').puts("dict: "+JSON.stringify(dict));
-
- var response;
- if (dict.nonce && dict.qop) {
- this.nonce_count++;
- var a1 = md5(this.authcid + ':' +
- this.realm + ':' +
- this.password) + ':' +
- dict.nonce + ':' +
- this.cnonce + ':' +
- this.authzid;
- var a2 = "AUTHENTICATE:" + this.digest_uri;
- if (dict.qop == 'auth-int' || dict.qop == 'auth-conf')
- a2 += ":00000000000000000000000000000000";
- var responseValue = md5_hex(md5_hex(a1) + ':' +
- dict.nonce + ':' +
- this.getNC() + ':' +
- this.cnonce + ':' +
- dict.qop + ':' +
- md5_hex(a2)
- );
- response = {
- username: this.authcid,
- realm: this.realm,
- nonce: dict.nonce,
- cnonce: this.cnonce,
- nc: this.getNC(),
- qop: dict.qop,
- 'digest-uri': this.digest_uri,
- response: responseValue,
- authzid: this.authzid,
- charset: 'utf-8'
- };
- } else if (dict.rspauth) {
- return "";
- }
- //require('sys').puts('response: '+JSON.stringify(response));
- return encodeDict(response);
- };
-}
-
-function parseDict(s) {
- var result = {};
- while (s) {
- var m;
-
- if ((m = /^(.+?)="(.*?[^\\])",(.*)/.exec(s))) {
- result[m[1]] = m[2];
- s = m[3];
- } else if ((m = /^(.+?)="(.*?[^\\])"$/.exec(s))) {
- result[m[1]] = m[2];
- s = m[3];
- } else if ((m = /^(.+?)=(.+?),(.*)/.exec(s))) {
- result[m[1]] = m[2];
- s = m[3];
- } else if ((m = /^(.+?)=(.+?)$/.exec(s))) {
- result[m[1]] = m[2];
- s = m[3];
- } else {
- s = null;
- }
- }
- return result;
-}
-
-function encodeDict(dict) {
- var s = "";
- for(k in dict) {
- var v = dict[k];
- if (v)
- s += ',' + k + '="' + v + '"';
- }
- return s.substr(1); // without first ','
-}
-
-function rjust(s, targetLen, padding) {
- while(s.length < targetLen)
- s = padding + s;
- return s;
-}
-
-function md5(s, encoding) {
- var hash = crypto.createHash('md5');
- hash.update(s);
- return hash.digest(encoding || 'binary');
-}
-
-function md5_hex(s) {
- return md5(s, 'hex');
-}
-
-function generateNonce() {
- var result = "";
- for(var i = 0; i < 8; i++)
- result += String.fromCharCode(48 +
- Math.ceil(Math.random() * 10));
- return result;
-}
diff --git a/lib/xmpp/server.js b/lib/xmpp/server.js
deleted file mode 100644
index d348d87..0000000
--- a/lib/xmpp/server.js
+++ /dev/null
@@ -1,186 +0,0 @@
-var dns = require('dns');
-var Connection = require('./connection');
-var xml = require('./xml');
-var sys = require('sys');
-var SRV = require('./srv');
-
-var NS_SERVER = 'jabber:server';
-var NS_DIALBACK = 'jabber:server:dialback';
-var NS_XMPP_SASL = 'urn:ietf:params:xml:ns:xmpp-sasl';
-
-/**
- * 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 Server(socket) {
- var self = this;
- Connection.Connection.call(this, socket);
-
- this.xmlns[''] = NS_SERVER;
- this.xmlns['db'] = NS_DIALBACK;
- this.xmppVersion = '1.0';
-
- this.addListener('rawStanza', function(stanza) {
- var key = stanza.getText();
-
- if (stanza.is('result', NS_DIALBACK)) {
- if (stanza.attrs.from && stanza.attrs.to &&
- stanza.attrs.type) {
-
- self.emit('dialbackResult',
- stanza.attrs.from, stanza.attrs.to,
- stanza.attrs.type == 'valid');
-
- } else if (stanza.attrs.from && stanza.attrs.to) {
-
- self.emit('dialbackKey',
- stanza.attrs.from, stanza.attrs.to,
- key);
-
- }
- } else if (stanza.is('verify', NS_DIALBACK)) {
- if (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.attrs.from && stanza.attrs.to &&
- stanza.attrs.id) {
-
- self.emit('dialbackVerify',
- stanza.attrs.from, stanza.attrs.to,
- stanza.attrs.id, key);
- }
- } else
- self.emit('stanza', stanza);
- });
-}
-sys.inherits(Server, Connection.Connection);
-
-exports.dialbackKey = function(from, to, key) {
- return new xml.Element('db:result', { to: to,
- from: from }).
- t(key);
-};
-exports.dialbackVerify = function(from, to, id, key) {
- return new xml.Element('db:verify', { to: to,
- from: from,
- id: id }).
- t(key);
-};
-exports.dialbackVerified = function(from, to, id, isValid) {
- return new xml.Element('db:verify', { to: to,
- from: from,
- id: id,
- type: isValid ? 'valid' : 'invalid' });
-};
-exports.dialbackResult = function(from, to, isValid) {
- return new xml.Element('db:result', { to: to,
- from: from,
- type: isValid ? 'valid' : 'invalid' });
-};
-
-exports.IncomingServer = function(stream, credentials) {
- var self = this;
- Server.call(this, stream);
-
- this.startParser();
- this.streamId = generateId();
-
- this.addListener('streamStart', function(streamAttrs) {
- if (streamAttrs.to &&
- credentials &&
- credentials.hasOwnProperty(streamAttrs.to))
- // TLS cert & key for this domain
- self.credentials = credentials[streamAttrs.to];
- // No credentials means we cannot <starttls/> on the server
- // side. Unfortunately this is required for XMPP 1.0.
- if (!self.credentials)
- delete self.xmppVersion;
-
- self.startStream();
- });
- this.addListener('rawStanza', function(stanza) {
- if (stanza.is('starttls', Connection.NS_XMPP_TLS)) {
- self.send(new xml.Element('proceed', { xmlns: Connection.NS_XMPP_TLS }));
- self.setSecure();
- }
- });
-
- return self;
-};
-sys.inherits(exports.IncomingServer, Server);
-
-exports.IncomingServer.prototype.startStream = function() {
- Server.prototype.startStream.call(this);
-
- if (this.xmppVersion == '1.0') {
- this.send("<stream:features>");
- if (this.credentials && !this.socket.secureEstablished)
- this.send("<starttls xmlns='" + Connection.NS_XMPP_TLS + "'/>");
- this.send("</stream:features>");
- }
-};
-
-exports.OutgoingServer = function(srcDomain, destDomain, credentials) {
- var self = this;
- Server.call(this);
-
- this.streamTo = destDomain;
- // For outgoing, we only need our own cert & key
- this.credentials = credentials;
- // No credentials means we cannot <starttls/> on the server
- // side. Unfortunately this is required for XMPP 1.0.
- if (!this.credentials)
- delete this.xmppVersion;
-
- this.socket.addListener('secure', function() {
- self.startStream();
- });
- this.addListener('streamStart', function(attrs) {
- if (attrs.version !== "1.0")
- // Don't wait for <stream:features/>
- self.emit('auth', 'dialback');
- });
- self.addListener('rawStanza', function(stanza) {
- if (stanza.is('features', Connection.NS_STREAM)) {
- var mechsEl;
- if ((mechsEl = stanza.getChild('mechanisms', NS_XMPP_SASL))) {
- var mechs = mechsEl.getChildren('mechanism', NS_XMPP_SASL).
- map(function(el) { return el.getText(); });
- if (mechs.indexOf('EXTERNAL') >= 0)
- self.emit('auth', 'external');
- else
- self.emit('auth', 'dialback');
- } else {
- // No SASL mechanisms
- self.emit('auth', 'dialback');
- }
- }
- });
-
- var attempt = SRV.connect(this.socket, ['_xmpp-server._tcp',
- '_jabber._tcp'],
- destDomain, 5269);
- attempt.addListener('connect', function() {
- self.startParser();
- self.startStream();
- });
- attempt.addListener('error', function(e) {
- self.emit('error', e);
- });
-};
-sys.inherits(exports.OutgoingServer, Server);
-
-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();
-};
diff --git a/lib/xmpp/srv.js b/lib/xmpp/srv.js
deleted file mode 100644
index c3826c9..0000000
--- a/lib/xmpp/srv.js
+++ /dev/null
@@ -1,147 +0,0 @@
-var dns = require('dns');
-var EventEmitter = require('events').EventEmitter;
-
-function compareNumbers(a, b) {
- a = parseInt(a, 10);
- b = parseInt(b, 10);
- if (a < b)
- return -1;
- if (a > b)
- return 1;
- return 0;
-}
-
-function groupSrvRecords(addrs) {
- var groups = {}; // by priority
- addrs.forEach(function(addr) {
- if (!groups.hasOwnProperty(addr.priority))
- groups[addr.priority] = [];
-
- groups[addr.priority].push(addr);
- });
-
- var result = [];
- Object.keys(groups).sort(compareNumbers).forEach(function(priority) {
- var group = groups[priority];
- var totalWeight = 0;
- group.forEach(function(addr) {
- totalWeight += addr.weight;
- });
- var w = Math.floor(Math.random() * totalWeight);
- totalWeight = 0;
- var candidate = group[0];
- group.forEach(function(addr) {
- totalWeight += addr.weight;
- if (w < totalWeight)
- candidate = addr;
- });
- if (candidate)
- result.push(candidate);
- });
- return result;
-}
-
-function resolveSrv(name, cb) {
- dns.resolveSrv(name, function(err, addrs) {
- if (err) {
- /* no SRV record, try domain as A */
- cb(err);
- } else {
- var pending = 0, error, results = [];
- var cb1 = function(e, addrs1) {
- error = error || e;
- results = results.concat(addrs1);
- pending--;
- if (pending < 1) {
- cb(results ? null : error, results);
- }
- };
- groupSrvRecords(addrs).forEach(function(addr) {
- resolveHost(addr.name, function(e, a) {
- if (a)
- a = a.map(function(a1) {
- return { name: a1,
- port: addr.port };
- });
- cb1(e, a);
- });
- pending++;
- });
- }
- });
-}
-
-// one of both A & AAAA, in case of broken tunnels
-function resolveHost(name, cb) {
- var error, results = [], pending = 2;
- var cb1 = function(e, addrs) {
- error = error || e;
- var addr = addrs && addrs[Math.floor(Math.random() * addrs.length)];
- if (addr)
- results.push(addr);
-
- pending--;
- if (pending < 1)
- cb((results.length > 0) ? null : error, results);
- };
-
- dns.resolve4(name, cb1);
- dns.resolve6(name, cb1);
-}
-
-// connection attempts to multiple addresses in a row
-function tryConnect(socket, addrs, listener) {
- var onConnect = function() {
- socket.removeListener('connect', onConnect);
- socket.removeListener('error', onError);
- // done!
- listener.emit('connect');
- };
- var error;
- var onError = function(e) {
- error = e;
- connectNext();
- };
- var connectNext = function() {
- var addr = addrs.shift();
- if (addr)
- socket.connect(addr.port, addr.name);
- else
- listener.emit('error', error);
- };
- socket.addListener('connect', onConnect);
- socket.addListener('error', onError);
- connectNext();
-}
-
-// returns EventEmitter with 'connect' & 'error'
-exports.connect = function(socket, services, domain, defaultPort) {
- var listener = new EventEmitter();
-
- var tryServices = function() {
- var service = services.shift();
- if (service) {
- resolveSrv(service + '.' + domain, function(error, addrs) {
- if (addrs)
- tryConnect(socket, addrs, listener);
- else
- tryServices();
- });
- } else {
- resolveHost(domain, function(error, addrs) {
- if (addrs && addrs.length > 0) {
- addrs = addrs.map(function(addr) {
- return { name: addr,
- port: defaultPort };
- });
- tryConnect(socket, addrs, listener);
- } else
- listener.emit('error', error);
- });
- }
-
- };
- tryServices();
-
- return listener;
-};
diff --git a/lib/xmpp/stream_parser.js b/lib/xmpp/stream_parser.js
deleted file mode 100644
index 90e1f08..0000000
--- a/lib/xmpp/stream_parser.js
+++ /dev/null
@@ -1,84 +0,0 @@
-var sys = require('sys');
-var EventEmitter = require('events').EventEmitter;
-var expat = require('node-expat');
-var xml = require('./xml');
-
-function StreamParser(charset, maxStanzaSize) {
- EventEmitter.call(this);
-
- var self = this;
- this.parser = new expat.Parser(charset);
- this.maxStanzaSize = maxStanzaSize;
- this.bytesParsedOnStanzaBegin = 0;
-
- this.parser.addListener('startElement', function(name, attrs) {
- // TODO: refuse anything but <stream:stream>
- if (!self.element && name == 'stream:stream') {
- self.emit('start', attrs);
- } else {
- var child = new xml.Element(name, attrs);
- if (!self.element) {
- /* A new stanza */
- self.element = child;
- self.bytesParsedOnStanzaBegin = self.bytesParsed;
- } else {
- /* A child element of a stanza */
- self.element = self.element.cnode(child);
- }
- }
- });
- this.parser.addListener('endElement', function(name, attrs) {
- if (!self.element && name == 'stream:stream') {
- self.end();
- } else if (self.element && name == self.element.name) {
- if (self.element.parent)
- self.element = self.element.parent;
- else {
- /* Stanza complete */
- self.emit('stanza', self.element);
- delete self.element;
- delete self.bytesParsedOnStanzaBegin;
- }
- } else {
- self.error('xml-not-well-formed', 'XML parse error');
- }
- });
- this.parser.addListener('text', function(str) {
- if (self.element)
- self.element.t(str);
- });
-}
-sys.inherits(StreamParser, EventEmitter);
-exports.StreamParser = StreamParser;
-
-StreamParser.prototype.write = function(data) {
- if (this.parser) {
- if (this.bytesParsedOnStanzaBegin && this.maxStanzaSize &&
- this.bytesParsed > this.bytesParsedOnStanzaBegin + this.maxStanzaSize) {
-
- this.error('policy-violation', 'Maximum stanza size exceeded');
- return;
- }
- this.bytesParsed += data.length;
-
- if (!this.parser.parse(data, this.final ? true : false)) {
- this.error('xml-not-well-formed', 'XML parse error');
- }
- }
-};
-
-StreamParser.prototype.end = function(data) {
- if (data) {
- this.final = true;
- this.write(data);
- }
-
- delete this.parser;
- this.emit('end');
-};
-
-StreamParser.prototype.error = function(condition, message) {
- var e = new Error(message);
- e.condition = condition;
- this.emit('error', e);
-};
diff --git a/test/test_jid.js b/test/test_jid.js
deleted file mode 100644
index 15f805b..0000000
--- a/test/test_jid.js
+++ /dev/null
@@ -1,100 +0,0 @@
-var vows = require('vows'),
-assert = require('assert'),
-xmpp = require('./../lib/xmpp');
-
-vows.describe('JID').addBatch({
-
- 'parsing': {
- 'parse a "domain" JID':
- function() {
- var j = new xmpp.JID('d');
- assert.equal(j.user, null);
- assert.equal(j.domain, 'd');
- assert.equal(j.resource, null);
- },
- 'parse a "user at domain" JID':
- function() {
- var j = new xmpp.JID('u at d');
- assert.equal(j.user, 'u');
- assert.equal(j.domain, 'd');
- assert.equal(j.resource, null);
- },
- 'parse a "domain/resource" JID':
- function() {
- var j = new xmpp.JID('d/r');
- assert.equal(j.user, null);
- assert.equal(j.domain, 'd');
- assert.equal(j.resource, 'r');
- },
- 'parse a "user at domain/resource" JID':
- function() {
- var j = new xmpp.JID('u at d/r');
- assert.equal(j.user, 'u');
- assert.equal(j.domain, 'd');
- assert.equal(j.resource, 'r');
- }
- },
-
- 'serialization': {
- 'serialize a "domain" JID':
- function() {
- var j = new xmpp.JID(null, 'd');
- assert.equal(j.toString(), 'd');
- },
- 'serialize a "user at domain" JID':
- function() {
- var j = new xmpp.JID('u', 'd');
- assert.equal(j.toString(), 'u at d');
- },
- 'serialize a "domain/resource" JID':
- function() {
- var j = new xmpp.JID(null, 'd', 'r');
- assert.equal(j.toString(), 'd/r');
- },
- 'serialize a "user at domain/resource" JID':
- function() {
- var j = new xmpp.JID('u', 'd', 'r');
- assert.equal(j.toString(), 'u at d/r');
- }
- },
-
- 'equality': {
- 'parsed JIDs should be equal':
- function() {
- var j1 = new xmpp.JID('foo at bar/baz');
- var j2 = new xmpp.JID('foo at bar/baz');
- assert.equal(j1.equals(j2), true);
- },
- 'parsed JIDs should be not equal':
- function() {
- var j1 = new xmpp.JID('foo at bar/baz');
- var j2 = new xmpp.JID('quux at bar/baz');
- assert.equal(j1.equals(j2), false);
- },
- 'should ignore case in user':
- function() {
- var j1 = new xmpp.JID('foo at bar/baz');
- var j2 = new xmpp.JID('FOO at bar/baz');
- assert.equal(j1.equals(j2), true);
- },
- 'should ignore case in domain':
- function() {
- var j1 = new xmpp.JID('foo at bar/baz');
- var j2 = new xmpp.JID('foo at BAR/baz');
- assert.equal(j1.equals(j2), true);
- },
- 'should not ignore case in resource':
- function() {
- var j1 = new xmpp.JID('foo at bar/baz');
- var j2 = new xmpp.JID('foo at bar/Baz');
- assert.equal(j1.equals(j2), false);
- },
- 'should ignore international caseness':
- function() {
- var j1 = new xmpp.JID('föö@bär/baß');
- var j2 = new xmpp.JID('fÖö@BÄR/baß');
- assert.equal(j1.equals(j2), true);
- }
- }
-
-}).run();
--
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