0

I am trying to convert the following PHP code to Node.JS code:

PHP

$TimeStart = microtime(true); // for read timeout purposes

// See http://wiki.vg/Protocol (Status Ping)
$Data = "\x00"; // packet ID = 0 (varint)

$Data .= "\x04"; // Protocol version (varint)
$Data .= Pack( 'c', StrLen( $this->ServerAddress ) ) . $this->ServerAddress; // Server (varint len + UTF-8 addr)
$Data .= Pack( 'n', $this->ServerPort ); // Server port (unsigned short)
$Data .= "\x01"; // Next state: status (varint)

$Data = Pack( 'c', StrLen( $Data ) ) . $Data; // prepend length of packet ID + data

fwrite( $this->Socket, $Data ); // handshake
fwrite( $this->Socket, "\x01\x00" ); // status ping

$Length = $this->ReadVarInt( ); // full packet length

if( $Length < 10 )
{
    return FALSE;
}

fgetc( $this->Socket ); // packet type, in server ping it's 0

$Length = $this->ReadVarInt( ); // string length

$Data = "";
do
{
    if (microtime(true) - $TimeStart > $this->Timeout)
    {
        //exception
    }

    $Remainder = $Length - StrLen( $Data );
    $block = fread( $this->Socket, $Remainder ); // and finally the json string
    // abort if there is no progress
    if (!$block)
    {
        //exception
    }

    $Data .= $block;
} while( StrLen($Data) < $Length );

This is what i thought it was but apparently it's not the same as i dont get any data returned.

var socket = new net.Socket();
socket = net.connect(port, host, function(){
    console.log('Connected');

    /*
    Returns data but protocol is not correctly folllowed
    -----------------------------------------------------*/
    var PACKET_HEAD = new Buffer([
        0, // Packet ID 0
        4 // Version 4 (1.7.2), 5 is 1.7.6
    ]);
    var PACKET_PORT = new Buffer(2);
    var PACKET_NEXTSTATE = new Buffer([1]);
    var PACKET_STATUS_REQ = new Buffer([1, 0]);


    host = new Buffer(host);
    var addrLen = new Buffer(varint.encode(host.length));

    PACKET_PORT.writeUInt16BE(port, 0);

    var packetLength = 2 + addrLen.length + host.length + 2 + 1;
    var lengthBuffer = new Buffer(varint.encode(packetLength));

    var packet = Buffer.concat([
        lengthBuffer,
        PACKET_HEAD,
        addrLen,
        host,
        PACKET_PORT,
        PACKET_NEXTSTATE,
        PACKET_STATUS_REQ
    ], packetLength + 3);

    socket.write(packet);

    /*
    TRY 1
    ------*/
    var packet;
    packet = "\x00";
    packet += "\x04";
    packet += bufferpack.pack('c', host.length.toString()) + host;
    packet += bufferpack.pack('n', port.toString());
    packet += "\x01";
    packet = bufferpack.pack('c', packet.length.toString()) + packet;

    socket.write(packet);
    socket.write("\x01\x00");


    /*TRY 2
    -------*/
    var packet;
    packet = packData(
        '\x00\x00' 
        + packData(host.toString('utf8'))
        + packPort(port)
        + '\x01'
    );

    socket.write(packet);
    socket.write(packData('\x00'));
});



socket.on('error', function(err){
    console.log(errorHandler(err));
    socket.end();
});

socket.on('data', function(data){
    console.log(data);
    socket.end();
});

setTimeout(function(){
    console.log("Timeout");
    socket.end();
    socket.destroy();
}, 1000);


function char(value) {
    return value.toString().charCodeAt(0);
}
function packData(data) {
    return varint.encode(data.length) + data;
}
function packPort(data) {
    return bufferpack.pack('>H', data.toString());
}

I have tried numerous ways to replicate the php code to nodejs end ended up using libraries that mimic the pack behavior (bufferpack).

I think i am missing something but i can't figure out what it is.

1 Answer 1

1

Maybe a bit late, but I've made your code working for me.

The module I've used: https://github.com/ryanrolds/bufferpack

installing using: npm install bufferpack

This is the plain code (copied)

var _connection;
var connect = function(port, host, callback) {
    _connection = new net.Socket();
    _connection.connect(port, host, function() {
        system.log('Connected to the server, authenticating now.');

        var PACKET_HEAD = new Buffer([
            0, // Packet ID 0
            47 // Version 4 (1.7.2), 5 is 1.7.6
        ]);
        var PACKET_PORT = new Buffer(2);
        var PACKET_NEXTSTATE = new Buffer([1]);
        var PACKET_STATUS_REQ = new Buffer([1, 0]);


        host = new Buffer(host);
        var addrLen = new Buffer(varint.encode(host.length));

        PACKET_PORT.writeUInt16BE(port, 0);

        var packetLength = 2 + addrLen.length + host.length + 2 + 1;
        var lengthBuffer = new Buffer(varint.encode(packetLength));

        var packet = Buffer.concat([
            lengthBuffer,
            PACKET_HEAD,
            addrLen,
            host,
            PACKET_PORT,
            PACKET_NEXTSTATE,
            PACKET_STATUS_REQ
        ], packetLength + 3);

        _connection.write(packet);

        /*
        TRY 1
        ------*/
        var packet;
        packet = "\x00";
        packet += "\x04";
        packet += bufferpack.pack('c', host.length.toString()) + host;
        packet += bufferpack.pack('n', port.toString());
        packet += "\x01";
        packet = bufferpack.pack('c', packet.length.toString()) + packet;

        _connection.write(packet);
        _connection.write("\x01\x00");


        /*TRY 2
        -------*/
        var packet;
        packet = packData(
            '\x00\x00' 
            + packData(host.toString('utf8'))
            + packPort(port)
            + '\x01'
        );

        _connection.write(packet);
        _connection.write(packData('\x00'));

    });
    _connection.on('error', function(err){
        system.log(err);
        _connection.end();
    });
    _connection.on('data', function(data){
        system.log(data);
    });
};
exports.connect = connect;

function packData(data) {
    return varint.encode(data.length) + data;
}

function packPort(data) {
    return bufferpack.pack('>H', data.toString());
}

My github repo: https://github.com/AtlasDev/NodeCraft

This part is in libs/connection.js

Hope this still helps, AtlasDev

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.