1
0
Fork 0
mirror of https://github.com/demostf/demo.js synced 2026-06-03 16:44:12 +02:00

node stream parsing wip

This commit is contained in:
Robin Appelman 2015-04-02 16:57:36 +02:00
commit e88cd0cd7e
5 changed files with 127 additions and 13 deletions

90
StreamParser.js Normal file
View file

@ -0,0 +1,90 @@
var util = require('util');
var Parser = require('./parser');
var State = require('./state');
var BitStream = require('bit-buffer').BitStream;
var StreamParser = function (stream) {
this.stream = stream;
this.state = new State();
this.on('packet', this.state.updateState.bind(this.state));
this.header = null;
this.buffer = new Buffer(0);
};
util.inherits(StreamParser, Parser);
function shrinkBuffer(buffer, length) {
if (length < 0) {
throw 'cant shrink by negative length ' + length;
}
return buffer.slice(length, buffer.length);
}
StreamParser.prototype.eatBuffer = function (length) {
this.buffer = shrinkBuffer(this.buffer, length);
};
StreamParser.prototype.start = function () {
this.stream.on('data', this.handleData.bind(this));
this.stream.on('end', function () {
this.emit('done', this.state.get());
}.bind(this));
};
StreamParser.prototype.handleData = function (data) {
this.buffer = Buffer.concat([this.buffer, data]);
if (this.header === null) {
if (this.buffer.length > 1072) {
this.header = this.parseHeader(new BitStream(this.buffer));
this.eatBuffer(1072);
}
} else {
this.readMessage();
}
};
StreamParser.prototype.readMessage = function () {
if (this.buffer.length < 9) { // 9 byte minimum message header (type, tick, length)
return;
}
var stream = new BitStream(this.buffer);
var type = stream.readBits(8);
if (type === Parser.MessageType.Stop) {
console.log('stop');
return;
}
var tick = stream.readInt32();
var headerSize = 5;
var extraHeader = 0;
switch (type) {
case Parser.MessageType.Sigon:
case Parser.MessageType.Packet:
extraHeader += 0x54; // command/sequence info
break;
case Parser.MessageType.UserCmd:
extraHeader += 0x04; // unknown / outgoing sequence
break;
case Parser.MessageType.Stop:
case Parser.MessageType.SyncTick:
this.eatBuffer(headerSize);
return;
}
stream.byteIndex += extraHeader;
var length = stream.readInt32();
headerSize += extraHeader + 4;
if (this.buffer.length < (headerSize + length)) {
console.log('wants ' + length);
return;
}
console.log('got message ' + tick);
var messageBuffer = this.buffer.slice(headerSize, headerSize + length);
this.eatBuffer(headerSize + length);
var message = this.parseMessage(messageBuffer, type, tick, length);
this.handleMessage(message);
};
module.exports = StreamParser;

View file

@ -12,6 +12,15 @@ var echo = function (data) {
console.log(string);
};
//var stream = fs.createReadStream(argv._[0]);
//
//var demo = Demo.fromNodeStream(stream);
//var parser = demo.getParser();
//parser.on('done', function (state) {
// echo(state);
//});
//parser.start();
fs.readFile(argv._[0], function (err, data) {
if (err) throw err;
var demo = Demo.fromNodeBuffer(data);

13
demo.js
View file

@ -1,5 +1,6 @@
var BitStream = require('bit-buffer').BitStream;
var Parser = require('./parser');
var StreamParser = require('./StreamParser');
var Demo = function (arrayBuffer) {
this.stream = new BitStream(arrayBuffer);
@ -9,6 +10,14 @@ Demo.prototype.getParser = function () {
return new Parser(this.stream);
};
var StreamDemo = function (nodeStream) {
this.stream = nodeStream;
};
StreamDemo.prototype.getParser = function () {
return new StreamParser(this.stream);
};
Demo.fromNodeBuffer = function (nodeBuffer) {
var arrayBuffer = new ArrayBuffer(nodeBuffer.length);
var view = new Uint8Array(arrayBuffer);
@ -18,6 +27,10 @@ Demo.fromNodeBuffer = function (nodeBuffer) {
return new Demo(arrayBuffer);
};
Demo.fromNodeStream = function (nodeStream) {
return new StreamDemo(nodeStream);
};
Demo.fromPath = function (path) {
var arrayBuffer = new ArrayBuffer(nodeBuffer.length);
var view = new Uint8Array(arrayBuffer);

View file

@ -1,13 +1,14 @@
{
"name": "tf2-demo",
"description": "A parser for TF2 demo files",
"version": "0.1.0",
"bin": {
"demo-analyse": "./bin/analyse.js"
},
"main": "demo.js",
"dependencies": {
"bit-buffer": "icewind1991/bit-buffer",
"minimist": "1.1.x"
}
"name": "tf2-demo",
"description": "A parser for TF2 demo files",
"version": "0.1.0",
"bin": {
"demo-analyse": "./bin/analyse.js"
},
"main": "demo.js",
"dependencies": {
"bit-buffer": "icewind1991/bit-buffer",
"minimist": "1.1.x",
"smart-buffer": "^1.0.1"
}
}

View file

@ -7,8 +7,8 @@ var DataTable = require('./datatable');
var BitStream = require('bit-buffer').BitStream;
var EventEmitter = require('events').EventEmitter;
var Parser = function (steam) {
this.stream = steam;
var Parser = function (stream) {
this.stream = stream;
this.state = new State();
this.packets = [];
this.strings = {};
@ -57,6 +57,7 @@ Parser.prototype.parseBody = function () {
this.handleMessage(message);
}
this.strings = StringTable.tables;
this.emit('done', this.state.get());
return this.state.get();
};