Skip to content
This repository has been archived by the owner on Jun 3, 2021. It is now read-only.

Commit

Permalink
Move packet decoding and encoding to their own files.
Browse files Browse the repository at this point in the history
  • Loading branch information
occanowey committed Feb 18, 2017
1 parent 9f71f5e commit 5d2bdad
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 53 deletions.
77 changes: 24 additions & 53 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ const varint = require( 'varint' );
const Long = require( 'long' );
const State = require( './state.js' );

const Packet = require( './packets/packet.js' );
const handshaking = require( './packets/handshaking.js' );
const status = require( './packets/status.js' );

const config = require( '../config.json' );

let debugSocket = debug( 'socket' );
Expand All @@ -18,81 +22,48 @@ function socketListener( s ) {
};

function handlePacket( packet ) {
let offset = 0;

let length = varint.decode( packet );
offset += varint.decode.bytes;
let packetInfo = Packet.decode( packet );
let packetData = packetInfo.packet;

let id = varint.decode( packet, offset );
offset += varint.decode.bytes;
console.log( packetInfo );

debugSocket( `recieved new packet #${id} of length ${length} at state: ${State.toString( s.info.state )}` );
debugSocket( `recieved new packet #${packetInfo.id} of length ${packetInfo.length} at state: ${State.toString( s.info.state )}` );

if( s.info.state === State.HANDSHAKING ) {
if( id === 0 ) { // Handshake
let version = varint.decode( packet, offset );
offset += varint.decode.bytes;

let addressLength = varint.decode( packet, offset );
offset += varint.decode.bytes;

let address = packet.toString( 'utf8', offset, offset + addressLength );
offset += addressLength;

let port = packet.readUInt16BE( offset );
offset += 2;

let nextState = varint.decode( packet, offset );
if( packetInfo.id === 0 ) { // Handshake
let handshake = handshaking.Handshake.decode( packetData );

s.info.version = version;
s.info.address = address;
s.info.port = port;
s.info.state = nextState;
s.info.version = handshake.version;
s.info.address = handshake.address;
s.info.port = handshake.port;
s.info.state = handshake.nextState;

debugSocket( 'Handshake:', { version, address, port, nextState } );
debugSocket( 'Handshake:', handshake );
}

return;
}

if( s.info.state === State.STATUS ) {
if( id === 0 ) { // Request
if( packetInfo.id === 0 ) { // Request
//TODO: add option to forward packet.

let status = JSON.stringify( config.status )
let response = new status.Response( config.status );

let data = Buffer.concat( [
Buffer.from( varint.encode( 0 ) ),
Buffer.from( varint.encode( status.length ) ),
Buffer.from( status, 'utf8' )
] );

s.write( Buffer.concat( [
Buffer.from( varint.encode( data.length ) ),
data
] ) );
s.write( response.encode() );
}

if( id === 1 ) { // Ping
if( packetInfo.id === 1 ) { // Ping
//TODO: calculate forwarded ping?

let low = packet.readUInt32BE( offset );
offset += 4;

let high = packet.readUInt32BE( offset );

let payload = new Long( low, high );
let ping = status.Ping.decode( packetData );

let data = Buffer.alloc( 8 );
data.writeUInt32BE( payload.low , 0 );
data.writeUInt32BE( payload.high, 0 );
let pong = new status.Pong( ping.payload );

s.write( Buffer.concat( [
Buffer.from( varint.encode( varint.encodingLength( 1 ) + data.length ) ),
Buffer.from( varint.encode( 1 ) ),
data
] ) );
s.write( pong.encode() );
}

return;
}
}

Expand Down
51 changes: 51 additions & 0 deletions src/packets/handshaking.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
const varint = require( 'varint' );

const State = require( '../state.js' );
const Packet = require( './packet.js' );

class Handshake extends Packet {
constructor( version, address, port, nextState ) {
super( State.HANDSHAKING, 0 );

this.version = version;
this.address = address;
this.port = port;

this.nextState = nextState;
}

encode() {
let portBuffer = Buffer.alloc( 2 );
portBuffer.writeUint16BE( this.port, 0 );

return this.createPacket( Buffer.concat( [
Buffer.from( varint.encode( this.version ) ),
Buffer.from( varint.encode( this.address.length ) ),
Buffer.from( this.address, 'utf8' ),
portBuffer,
Buffer.from( varint.encode( this.nextState ) )
] ) );
}

static decode( buffer ) {
let offset = 0;

let version = varint.decode( buffer, offset );
offset += varint.decode.bytes;

let addressLength = varint.decode( buffer, offset );
offset += varint.decode.bytes;

let address = buffer.toString( 'utf8', offset, offset + addressLength );
offset += addressLength;

let port = buffer.readUInt16BE( offset );
offset += 2;

let nextState = varint.decode( buffer, offset );

return new Handshake( version, address, port, nextState );
}
}

module.exports = { Handshake };
32 changes: 32 additions & 0 deletions src/packets/packet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const varint = require( 'varint' );

class Packet {
constructor( state, id ) {
this.state = state;
this.id = id;
}

createPacket( data ) {
return Buffer.concat( [
Buffer.from( varint.encode( varint.encodingLength( this.id ) + data.length ) ),
Buffer.from( varint.encode( this.id ) ),
data
] );
}

static decode( buffer ) {
let offset = 0;

let length = varint.decode( buffer );
offset += varint.decode.bytes;

let id = varint.decode( buffer, offset );
offset += varint.decode.bytes;

let packet = buffer.slice( offset, buffer.length );

return { length, id, packet };
}
}

module.exports = Packet;
95 changes: 95 additions & 0 deletions src/packets/status.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
const varint = require( 'varint' );

const Long = require( 'long' );

const State = require( '../state.js' );
const Packet = require( './packet.js' );

const state = State.STATUS;

class Request extends Packet {
constructor() {
super( state, 0 );
}

encode() {
return this.createPacket();
}

static decode( data ) {
return new Request();
}
}

class Response extends Packet {
constructor( status ) {
super( state, 0 );

this.status = status;
}

encode() {
let statusString = JSON.stringify( this.status );

return this.createPacket( Buffer.concat( [
Buffer.from( varint.encode( statusString.length ) ),
Buffer.from( statusString, 'utf8' )
] ) );
}

static decode( buffer ) {
let statusLength = varint.decode( buffer );

let status = buffer.toString( 'utf8', varint.decode.length, varint.decode.length + statusLength );

return new Response( JSON.parse( status ) );
}
}

class Ping extends Packet {
constructor( payload ) {
super( state, 1 );

this.payload = payload;
}

encode() {
let payloadBuffer = Buffer.alloc( 8 );
payloadBuffer.writeUInt32BE( this.payload.low , 0 );
payloadBuffer.writeUInt32BE( this.payload.high, 0 );

return this.createPacket( payloadBuffer );
}

static decode( buffer ) {
let low = buffer.readUInt32BE( buffer );
let high = buffer.readUInt32BE( buffer, 4 );

return new Ping( new Long( low, high ) );
}
}

class Pong extends Packet {
constructor( payload ) {
super( state, 1 );

this.payload = payload;
}

encode() {
let payloadBuffer = Buffer.alloc( 8 );
payloadBuffer.writeUInt32BE( this.payload.low , 0 );
payloadBuffer.writeUInt32BE( this.payload.high, 0 );

return this.createPacket( payloadBuffer );
}

static decode( buffer ) {
let low = buffer.readUInt32BE( buffer );
let high = buffer.readUInt32BE( buffer, 4 );

return new Pong( new Long( low, high ) );
}
}

module.exports = { Request, Response, Ping, Pong };

0 comments on commit 5d2bdad

Please sign in to comment.