Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Merge fix for #4 from Dev #5

Merged
merged 2 commits into from

1 participant

@kmpm
Owner

No description provided.

added some commits
@kmpm new mocha testst a2d232c
@kmpm Generate a better idToken.
Only first 4 bits of each byte is used so we ended up
with duplicate responses if there were a lot of consecutive
requests done.
Now it masks of anything but the last 4 bits so that
we have a correct token to match against.
Closes #4
a03c175
@kmpm kmpm merged commit a89d85b into master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Aug 13, 2013
  1. new mocha testst

    authored
  2. Generate a better idToken.

    authored
    Only first 4 bits of each byte is used so we ended up
    with duplicate responses if there were a lot of consecutive
    requests done.
    Now it masks of anything but the last 4 bits so that
    we have a correct token to match against.
    Closes #4
This page is out of date. Refresh to see the latest.
Showing with 157 additions and 124 deletions.
  1. +24 −10 mcquery.js
  2. +4 −2 package.json
  3. +0 −112 test/base-test.js
  4. +129 −0 test/test.js
View
34 mcquery.js
@@ -230,8 +230,10 @@ var Query = module.exports = function Query(host, port){
*/
function generateToken(){
counter +=1;
- if(counter>50000) counter = 0; //just not let it get to big
- return 10000 + counter;
+ //just not let it get to big. 32 bit int is max.
+ if(counter>999999) counter = 0;
+ //the protocol only uses the first 4 bits in every byte so mask.
+ return (10000 + counter) & 0x0F0F0F0F;
}
@@ -245,15 +247,21 @@ function makePacket(type, challengeToken, idToken, payloadBuffer){
var pLength = typeof(payloadBuffer)==='undefined'? 0 : payloadBuffer.length;
var sLength = typeof(challengeToken) !== 'number' ? 0: 4;
var b = new Buffer(7 + sLength+pLength);
- b.writeUInt8(0xFE, 0);
- b.writeUInt8(0xFD, 1);
- b.writeUInt8(type, 2);
- b.writeUInt32BE(idToken, 3);
- if(sLength>0){
- b.writeUInt32BE(challengeToken, 7);
+ try {
+ b.writeUInt8(0xFE, 0);
+ b.writeUInt8(0xFD, 1);
+ b.writeUInt8(type, 2);
+ b.writeUInt32BE(idToken, 3);
+ if(sLength>0){
+ b.writeUInt32BE(challengeToken, 7);
+ }
+ if(pLength>0){
+ payloadBuffer.copy(b, 7+sLength +1);
+ }
}
- if(pLength>0){
- payloadBuffer.copy(b, 7+sLength +1);
+ catch(err){
+ log.error("type=%s, challengeToken=%s, idToken=%s", type, challengeToken, idToken);
+ throw err;
}
return b;
}
@@ -268,12 +276,15 @@ function readPacket(data){
type:data.readUInt8(0),
idToken:data.readUInt32BE(1),
};
+ log.debug("response=%j", res);
+
data = data.slice(5);
if(res.type===CHALLENGE_TYPE){
res.challengeToken=parseInt(data.toString());
}
else if(res.type===STAT_TYPE){
var r = readString(data);
+ log.debug("data=%j", r);
if(r.text !== 'splitnum'){
//basic stat
res.MOTD = r.text;
@@ -296,6 +307,7 @@ function readPacket(data){
else {
var offset=r.offset;
res.splitnum = r.text;
+ //add key_val_start to response. It's the start byte of the response
res.key_val_start = data.readUInt16LE(offset);offset+=2;
var key;
var value;
@@ -306,6 +318,8 @@ function readPacket(data){
value = r.text;
res[key]=value;
}
+
+ //add key_val_ed to response. It's the end byte of the response
res.key_val_end = data.readUInt16LE(offset);offset+=2;
r = readString(data, offset); offset=r.offset;
View
6 package.json
@@ -4,7 +4,7 @@
"keywords": ["mcquery", "protocol", "query", "minecraft"],
"homepage": "https://github.com/kmpm/node-mcquery",
"author": "Peter Magnusson kmpm@birchroad.net",
- "version": "0.1.0",
+ "version": "0.1.1",
"main":"mcquery.js",
"engines": {
"node": ">=v0.6.2"
@@ -15,6 +15,8 @@
"url" : "http://github.com/kmpm/node-mcquery.git"
},
"devDependencies": {
- "vows": "*"
+ "mocha": "*",
+ "should": "*",
+ "nimble": "*"
}
}
View
112 test/base-test.js
@@ -1,112 +0,0 @@
-/*!
- * Copyright © 2011-2012 Peter Magnusson.
- * All rights reserved.
- */
-var vows = require('vows'),
- assert = require('assert'),
- fs = require('fs'),
- path = require('path');
-
-var f = path.resolve('./config.json');
-
-if(fs.existsSync(f)){
- var config = require(f);
-}
-else {
- config={host:'localhost', port:25565};
-}
-var Query = require('../mcquery');
-
-var TEST_HOST=config.host;
-var TEST_PORT=config.port;
-var global_query = new Query(TEST_HOST, TEST_PORT);
-
-vows.describe('GS4 Query').addBatch({
- 'connect':{
- topic:function(){
- global_query.connect(this.callback);
- },
- 'does not return error':function(err, session){
- assert.isNull(err);
- },
- 'returns a session object':function(err, session){
- assert.isObject(session);
- },
- 'session object':{
- topic:function(session){
- return session;
- },
- 'has challengeToken':function(session){
- assert.include(session, 'challengeToken');
- assert.isNumber(session.challengeToken);
- //have never seen a lower value then 20000
- assert.isTrue(session.challengeToken>20000);
- },
- /*'has host':function(session){
- assert.include(session, 'host');
- assert.isString(session.host);
- assert.equal(session.host, TEST_HOST);
- },
- 'has port':function(session){
- assert.include(session, 'port');
- assert.isNumber(session.port);
- assert.equal(session.port, TEST_PORT);
- },
- 'has sessionToken':function(session){
- assert.include(session, 'sessionToken');
- assert.isNumber(session.sessionToken);
- }*/
- },//topic session object
- 'basic_stat':{
- topic:function(session){
- //var query = new Query(TEST_HOST, TEST_PORT);
- global_query.basic_stat(this.callback);
- },
- 'does not return error':function(err, stat){
- assert.isNull(err);
- },
- 'returns a stat object':function(err, stat){
- assert.isObject(stat);
- assert.include(stat, 'MOTD');
- assert.include(stat, 'gametype');
- assert.include(stat, 'map');
- assert.include(stat, 'numplayers');
- assert.isNumber(stat.numplayers);
- assert.include(stat, 'maxplayers');
- assert.isNumber(stat.maxplayers);
- assert.include(stat, 'hostport');
- assert.isNumber(stat.hostport);
- assert.include(stat, 'hostip');
- //console.log(stat);
- }
- },//topic basic_stat
- 'full_stat':{
- topic:function(){
- //var query=new Query(TEST_HOST, TEST_PORT);
- var callback= this.callback;
- //start a new session, we are async!
- //query.connect(function(err, session){
- global_query.full_stat(callback);
- //});
- },
- 'does not return error':function(err, stat){
- assert.isNull(err);
- },
- 'returns a full stat object':function(err, stat){
- assert.isObject(stat);
- var props = ['splitnum', 'key_val_start'
- , 'hostname', 'gametype'
- , 'game_id', 'version'
- , 'plugins', 'map'
- , 'numplayers', 'maxplayers'
- , 'hostport', 'hostip'
- , 'key_val_end', 'player_'];
- for(var i=0; i<props.length;i++){
- assert.include(stat, props[i]);
- }
- assert.isArray(stat.player_);
- }
- }//topic full_stat
- }//topic startSession
-
-}).export(module);
View
129 test/test.js
@@ -0,0 +1,129 @@
+
+/*global describe it before after */
+
+var assert = require('assert')
+ , should = require('should')
+ , flow = require('nimble')
+ , util = require('util');
+
+var server_missing ={
+ host: 'srv8.streamcraft.net',
+ port: 33334
+};
+
+var server_existing = {
+ host: 'mc.craftyn.com', //'srv1.streamcraft.net',
+ port: 25565, //11111
+}
+
+var Query = require('../mcquery');
+
+var global_query = new Query(server_existing.host, server_existing.port );
+var global_session;
+
+describe('mcquery', function() {
+
+ after(function(done){
+ //global_query.close();
+ console.log("closing");
+ done();
+ });
+
+ it('should connect', function(done){
+ global_query.connect(function(err, session){
+ should.not.exist(err);
+ should.exist(session);
+ global_session=session;
+ done();
+ });
+ });
+
+ it('should have a proper session', function(){
+ should.exist(global_session);
+ global_session.should.be.instanceOf(Query);
+ global_session.should.have.property('challengeToken');
+ global_session.challengeToken.should.be.within(1, 0XFFFFFFFF);
+ });
+
+ it('should have a correct idToken', function(){
+ should.exist(global_session);
+ global_session.should.have.property('idToken');
+ global_session.challengeToken.should.be.within(1, 0XFFFFFFFF);
+ //test masking
+ global_session.idToken.should.equal(global_session.idToken & 0x0F0F0F0F);
+ });
+
+ describe('.basic_stat(err, result)', function(){
+ var result, err;
+ before(function(done){
+ should.exist(global_session);
+ global_query.basic_stat(function(er, res){
+ err = er;
+ result = res;
+ done();
+ });
+ });
+
+ it('err should be null', function(){
+ should.not.exist(err);
+ });
+
+ it('result should be correct', function(){
+ should.exist(result);
+ result.should.have.property('MOTD');
+ result.should.have.property('gametype');
+ result.should.have.property('map');
+ result.should.have.property('numplayers');
+ result.numplayers.should.be.within(0, 1024);
+ result.should.have.property('maxplayers');
+ result.maxplayers.should.be.within(0,1024);
+
+ result.should.have.property('hostport');
+ result.hostport.should.be.within(1, 65535);
+ result.should.have.property('hostip');
+ })
+ });
+
+
+ describe('.full_stat(err, result)', function(){
+ var err, result;
+ before(function(done){
+ global_query.full_stat(function(er, stat){
+ err = er;
+ result = stat;
+ done();
+ })
+ });
+
+ it('err should be null', function(){
+ should.not.exist(err);
+ });
+
+ it('result should be correct', function(){
+ should.exist(result);
+ var props = [
+ 'hostname',
+ 'gametype',
+ 'numplayers',
+ 'maxplayers',
+ 'hostport',
+ 'hostip',
+ 'splitnum',
+ 'key_val_start', //bonus
+ 'game_id',
+ 'version',
+ 'plugins', 'map',
+ 'player_',
+ 'key_val_end', //bonus
+ ];
+ for(var i=0; i<props.length;i++){
+ result.should.have.property(props[i]);
+ }
+ result.player_.should.be.instanceOf(Array);
+
+
+ });
+ });
+
+
+});
Something went wrong with that request. Please try again.