A Twitch.tv viewer reward and games system.
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.
 
 
 

147 lines
4.2 KiB

// An experimental fake MySQL server for tricky integration tests. Expanded
// as needed.
var Net = require('net');
var Packets = require('../lib/protocol/packets');
var PacketWriter = require('../lib/protocol/PacketWriter');
var Parser = require('../lib/protocol/Parser');
var Auth = require('../lib/protocol/Auth');
var EventEmitter = require('events').EventEmitter;
var Util = require('util');
module.exports = FakeServer;
Util.inherits(FakeServer, EventEmitter);
function FakeServer(options) {
EventEmitter.call(this);
this._server = null;
this._connections = [];
}
FakeServer.prototype.listen = function(port, cb) {
this._server = Net.createServer(this._handleConnection.bind(this));
this._server.listen(port, cb);
};
FakeServer.prototype._handleConnection = function(socket) {
var connection = new FakeConnection(socket);
this.emit('connection', connection);
this._connections.push(connection);
};
FakeServer.prototype.destroy = function() {
this._server.close();
this._connections.forEach(function(connection) {
connection.destroy();
});
};
Util.inherits(FakeConnection, EventEmitter);
function FakeConnection(socket) {
EventEmitter.call(this);
this._socket = socket;
this._parser = new Parser({onPacket: this._parsePacket.bind(this)});
this._handshakeInitializationPacket = null;
this._clientAuthenticationPacket = null;
this._oldPasswordPacket = null;
this._handshakeOptions = {};
socket.on('data', this._handleData.bind(this));
}
FakeConnection.prototype.handshake = function(options) {
this._handshakeOptions = options || {};
this._handshakeInitializationPacket = new Packets.HandshakeInitializationPacket({
scrambleBuff1: new Buffer(8),
scrambleBuff2: new Buffer(12),
});
this._sendPacket(this._handshakeInitializationPacket);
};
FakeConnection.prototype.deny = function(message, errno) {
this._sendPacket(new Packets.ErrorPacket({
message: message,
errno: errno,
}));
};
FakeConnection.prototype._sendPacket = function(packet) {
var writer = new PacketWriter();
packet.write(writer);
this._socket.write(writer.toBuffer(this._parser));
};
FakeConnection.prototype._handleData = function(buffer) {
this._parser.write(buffer);
};
FakeConnection.prototype._parsePacket = function(header) {
var Packet = this._determinePacket(header);
var packet = new Packet();
packet.parse(this._parser);
switch (Packet) {
case Packets.ClientAuthenticationPacket:
this._clientAuthenticationPacket = packet;
if (this._handshakeOptions.oldPassword) {
this._sendPacket(new Packets.UseOldPasswordPacket());
} else {
if (this._handshakeOptions.user || this._handshakeOptions.password) {
throw new Error('not implemented');
}
this._sendPacket(new Packets.OkPacket());
this._parser.resetPacketNumber();
}
break;
case Packets.OldPasswordPacket:
this._oldPasswordPacket = packet;
var expected = Auth.scramble323(this._handshakeInitializationPacket.scrambleBuff(), this._handshakeOptions.password);
var got = packet.scrambleBuff;
var toString = function(buffer) {
return Array.prototype.slice.call(buffer).join(',');
};
if (toString(expected) === toString(got)) {
this._sendPacket(new Packets.OkPacket());
} else {
this._sendPacket(new Packets.ErrorPacket());
}
this._parser.resetPacketNumber();
break;
case Packets.ComQueryPacket:
this.emit('query', packet);
break;
default:
throw new Error('Unexpected packet: ' + Packet.name)
}
};
FakeConnection.prototype._determinePacket = function() {
if (!this._clientAuthenticationPacket) {
return Packets.ClientAuthenticationPacket;
} else if (this._handshakeOptions.oldPassword && !this._oldPasswordPacket) {
return Packets.OldPasswordPacket;
}
var firstByte = this._parser.peak();
switch (firstByte) {
case 0x03: return Packets.ComQueryPacket;
default:
throw new Error('Unknown packet, first byte: ' + firstByte);
break;
}
};
FakeConnection.prototype.destroy = function() {
this._socket.destroy();
};