1
0
Fork 0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 lines
4.2 KiB

var sys = require("sys"),
net = require("net"),
XMLNS = require("./xmlns.js"),
xmpp = require("node-xmpp"),
colors = require("colors"),
events = require("events");
var BytestreamServer = function(client) {
var self = this;
this.client = client;
this.port = (client.params.s5bPort == null) ? 8010 : client.params.s5bPort;
this.host = (client.params.s5bHost == null) ? "proxy." + client.params.host : client.params.s5bHost;
this._clients = {};
this._handlers = {};
this.tcpSocket = net.createServer(function(stream) {self.handleConnection(stream);});
this.tcpSocket.on("error", function(error) {
console.log("Error with S5B server!");
console.log(error);
});
this.tcpSocket.listen(this.port, "0.0.0.0");
};
exports.BytestreamServer = BytestreamServer;
BytestreamServer.prototype.close = function() {
for (ii in this._clients) {
this._clients[ii].end();
}
this.tcpSocket.close();
};
BytestreamServer.prototype.addHandler = function(iqId, sidHash, data, cbSuccess, cbFailure) {
this._handlers[sidHash] = {id: iqId, data: data, cbSuccess:cbSuccess, cbFailure:cbFailure};
};
BytestreamServer.prototype.handleConnection = function(stream) {
var self = this;
this._clients[stream.remoteAddress] = new BytestreamHandler(stream, self);
this._clients[stream.remoteAddress].established = false;
this._clients[stream.remoteAddress].transfered = false;
stream.on("error", function(error) {
console.log("S5B stream error from "+ stream.remoteAddress);
console.log(error);
stream.end();
delete self._clients[stream.remoteAddress];
});
stream.on("connect", this._clients[stream.remoteAddress].onConnect);
stream.on("data", this._clients[stream.remoteAddress].onData);
stream.on("end", this._clients[stream.remoteAddress].onEnd);
};
BytestreamServer.prototype.iq = function(bytestream, query, to, id) {
var self = this;
var jabber = self.client;
if (typeof to === "undefined") {
var to = bytestream.to;
}
if (typeof id === "undefined") {
var id = bytestream.idIq;
}
var params = {
type: "set",
id: id,
to: to
};
jabber.xmpp.send(new xmpp.Element('iq', params).cnode(query).tree());
};
var BytestreamHandler = function(self, parent) {
self.parent = parent;
self.iqId = null;
this.onConnect = function(data) {};
this.onData = function(data) {
// TODO: Disconnect client when BS data is entered
// just a start
if (data[0] !== 0x05 && data[1] > 0x0F) {
console.log("Received erroneous data from " + self.remoteAddress);
self.end();
}
if (self.parent._clients[self.remoteAddress].established === false
&& data.length >= 1 && data[0] === 0x05) {
if (data.length >= 3 && (data[1] === 0x01 || data[1] === 0x02) && data[2] === 0x00) {
if (data[1] === 0x01 || (data.length >= 4 && data[3] === 0x02)) {
self.parent._clients[self.remoteAddress].established = true;
self.write(new Buffer([0x05,0x00])); // Ack
}
}
} else if (self.parent._clients[self.remoteAddress].established === true && data.length == 47
&& data[data.length - 1] === 0x00 && data[data.length - 2] === 0x00) {
var reqHash = data.toString("ascii", 5, 45);
if ((reqHash in self.parent._handlers) === true) {
var buff = [0x05,0x00,0x00,0x03]; // Request header
buff.push(reqHash.length); // Announce data length
// Push our reqHash in the buffer
reqHash.split("").forEach(function(val) {
buff.push(val.charCodeAt(0));
});
// DST.PORT is two bytes
buff.push(0x00, 0x00);
// Add iq handler for receiving the target's ack
self.iqId = self.parent._handlers[reqHash].id;
self.parent.client._iqCallback[self.iqId] = {};
self.parent.client._iqCallback[self.iqId].success = function(data) {
if (typeof self.parent._handlers[reqHash].data === "function") {
self.parent._handlers[reqHash].data(self);
} else {
self.write(self.parent._handlers[reqHash].data);
}
self.parent._clients[self.remoteAddress].transfered = true;
delete self.parent.client._iqCallback[self.iqId];
};
self.parent.client._iqCallback[self.iqId].error = function(error) {
console.log(error);
};
self.write(new Buffer(buff));
}
}
};
this.onEnd = function(data) {
delete self.parent._clients[self.remoteAddress];
};
};