Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

no more parse errors but the test hangs

  • Loading branch information...
commit 1d5d2a3af67213d9aad17fdd262e45c124e40bad 1 parent 30c3f0d
@substack authored
Showing with 316 additions and 0 deletions.
  1. +187 −0 lib/handshake.js
  2. +116 −0 lib/messages.js
  3. +13 −0 lib/parser.js
View
187 lib/handshake.js
@@ -0,0 +1,187 @@
+var exports = module.exports = function (rfb, opts) {
+ [ 'version', 'security', 'init' ].forEach((function (x) {
+ exports[x].call(this, rfb, opts);
+ }).bind(this));
+};
+
+exports.version = function (rfb, opts) {
+ this
+ .buffer('prelude', 12)
+ .tap(function (vars) {
+ var m = vars.prelude.toString().match(/^RFB (\d{3}\.\d{3})/);
+ if (!m) {
+ rfb.emit('error', new Error(
+ "Couldn't parse version handshake: " + vars.prelude
+ ));
+ }
+ else {
+ var version = Number(m[1]);
+ if (version < 3.008) {
+ rfb.emit('error', new Error(
+ 'Remote version ' + version + ' < 3.008'
+ ));
+ }
+ else {
+ rfb.write('RFB 003.008\n');
+ rfb.emit('version', version);
+ }
+ }
+ })
+};
+
+exports.security = function (rfb, opts) {
+ this
+ .word8('secLen')
+ .tap(function (vars) {
+ if (vars.secLen === 0) {
+ this
+ .word8('msgLen')
+ .buffer('msg','msgLen')
+ .tap(function (vars) {
+ rfb.emit('error', new Error(
+ 'Server returned error in security handshake: '
+ + vars.msg.toString()
+ ));
+ })
+ }
+ })
+ .buffer('secTypes', 'secLen')
+ .tap(function (vars) {
+ var secTypes = [].slice.call(vars.secTypes);
+ var names = { 1 : 'none', 2 : 'vnc' };
+ vars.secNum = { 'none' : 1, 'vnc' : 2 }[opts.securityType];
+
+ rfb.emit('security', secTypes.map(
+ function (t) { return names[t] }
+ ));
+
+ if (secTypes.indexOf(vars.secNum) < 0) {
+ rfb.emit('error', new Error(
+ 'Security type ' + rfb.securityType + ' not supported'
+ ));
+ }
+
+ Put().word8(vars.secNum).write(rfb.stream);
+ })
+ .tap(function (vars) {
+ if (vars.secNum === 2) {
+ this
+ .buffer('challenge', 16)
+ .tap(function (vars) {
+ var response = des.encrypt(rfb.password, vars.challenge);
+ Put().put(response).write(rfb);
+ })
+ }
+ })
+ .word32be('secRes')
+ .tap(function (vars) {
+ if (vars.secRes !== 0) {
+ this
+ .getWord32be('msgLen')
+ .getBuffer('msg', 'msgLen')
+ .tap(function (vars) {
+ sys.log('Security handshake failed with message: '
+ + vars.msg.toString()
+ );
+ });
+ }
+ })
+};
+
+exports.init = function (rfb, opts) {
+ this
+ .tap(function (vars) {
+ Put().word8(opts.shared).write(rfb.stream);
+ })
+ .into('size', function () {
+ this
+ .getWord16be('width')
+ .getWord16be('height')
+ .tap(function (size) { rfb.dimensions = size })
+ })
+ .into('pf', function () {
+ this
+ .getWord8('bitsPerPixel')
+ .getWord8('depth')
+ .getWord8('bigEndian')
+ .getWord8('trueColor')
+ .getWord16be('redMax')
+ .getWord16be('greenMax')
+ .getWord16be('blueMax')
+ .getWord8('redShift')
+ .getWord8('greenShift')
+ .getWord8('blueShift')
+ .tap(function (pf) {
+ var bpp = depth = 24;
+ if (rfb.engine == 'tightvnc') {
+ bpp = 32;
+ depth = 32;
+ }
+ // override server values
+ pf.bitsPerPixel = bpp;
+ pf.depth = depth;
+ pf.bigEndian = 0;
+ pf.trueColor = 1;
+ pf.redMax = 0xFF;
+ pf.greenMax = 0xFF;
+ pf.blueMax = 0xFF;
+ pf.redShift = 16;
+ pf.greenShift = 8;
+ pf.blueShift = 0;
+ })
+ })
+ .skip(3)
+ .getWord32be('nameLength')
+ .getBuffer('nameString', 'nameLength')
+ .tap(function (vars) {
+ Put() // tell the server the format we'd like to receive data in
+ .word8(clientMsgTypes.setPixelFormat)
+ .pad(3)
+ .word8(vars.pf.bitsPerPixel)
+ .word8(vars.pf.depth)
+ .word8(vars.pf.bigEndian)
+ .word8(vars.pf.trueColor)
+ .word16be(vars.pf.redMax)
+ .word16be(vars.pf.greenMax)
+ .word16be(vars.pf.blueMax)
+ .word8(vars.pf.redShift)
+ .word8(vars.pf.greenShift)
+ .word8(vars.pf.blueShift)
+ .pad(3)
+ .write(rfb)
+ ;
+
+ Put()
+ .word8(clientMsgTypes.setEncodings)
+ .pad(1)
+ .word16be(3) // number of encodings following
+ .word32be(encodings.pseudoDesktopSize)
+ .word32be(encodings.copyRect)
+ .word32be(encodings.raw)
+ .write(rfb)
+ ;
+
+ // send {left-,right-}{ctrl,alt,shift}
+ [0xffe3, 0xffe4, 0xffe9, 0xffea, 0xffe1, 0xffe2].forEach(
+ function (key) {
+ rfb.sendKeyDown(key);
+ rfb.sendKeyUp(key);
+ }
+ );
+ })
+ .tap(function (vars) {
+ if (rfb.engine == 'vmware') {
+ rfb.requestRedraw();
+ }
+ else {
+ rfb.dimensions(function (dims) {
+ rfb.subscribe({
+ x : 0,
+ y : 0,
+ width : dims.width,
+ height : dims.height,
+ });
+ });
+ }
+ })
+};
View
116 lib/messages.js
@@ -0,0 +1,116 @@
+var exports = module.exports = function (rfb, opts) {
+ var bs = this;
+
+ bs.loop(function () {
+ exports.message.call(bs, rfb, opts)
+ });
+};
+
+var serverMsgTypes = {
+ fbUpdate : 0,
+ setColorMap : 1,
+ bell: 2,
+ cutText: 3
+};
+
+var encodings = {
+ raw : 0,
+ copyRect : 1,
+ rre : 2,
+ hextile : 5,
+ zrle : 16,
+ pseudoCursor : -239,
+ pseudoDesktopSize : -223
+};
+
+exports.message = function (rfb, opts) {
+ this
+ .word8('serverMsgType')
+ .tap(function (vars) {
+ var handler = exports.serverMsg[vars.serverMsgType];
+ if (!handler) {
+ rfb.emit('error', new Error(
+ 'No handler for type ' + vars.serverMsgType
+ ));
+ }
+ else {
+ handler.call(this, rfb, opts);
+ }
+ })
+};
+
+exports.serverMsg = {};
+
+exports.serverMsg[serverMsgTypes.setColorMap] = function (rfb, opts) {
+ rfb.emit('error', 'setColorMap not implemented');
+};
+exports.serverMsg[serverMsgTypes.bell] = function (rfb, opts) {
+ rfb.emit('error', 'bell not implemented');
+};
+
+exports.serverMsg[serverMsgTypes.cutText] = function (rfb, opts) {
+ rfb.emit('error', 'cutText not implemented');
+};
+
+exports.serverMsg[serverMsgTypes.fbUpdate] = function (rfb, opts) {
+ this
+ .skip(1)
+ .word16be('nRects')
+ .tap(function (vars) {
+ rfb.emit('startRects', vars.nRects);
+ vars.i = 0;
+ })
+ .loop(function (end, vars) {
+ if (vars.i >= vars.nRects) {
+ rfb.emit('endRects', vars.nRects);
+ end();
+ return;
+ }
+
+ var bpp = vars.pf.bitsPerPixel / 8;
+
+ this.into('rect', function (rect) {
+ rect.nRects = vars.nRects;
+ rect.type = 'unknownRect';
+ rect.index = i;
+
+ this
+ .word16be('x')
+ .word16be('y')
+ .word16be('width')
+ .word16be('height')
+ .word32bes('encodingType')
+ .tap(function () {
+ switch (rect.encodingType) {
+ case encodings.raw :
+ rect.type = 'raw';
+ rect.fbSize = rect.width * rect.height * bpp;
+ this.buffer('fb','fbSize');
+ break;
+ case encodings.copyRect :
+ rect.type = 'copyRect';
+ this
+ .word16be('srcX')
+ .word16be('srcY')
+ break;
+ case encodings.pseudoDesktopSize :
+ rfb.dimensions = {
+ width : rect.width,
+ height : rect.height,
+ };
+ rect.type = 'desktopSize';
+
+ rfb.subscribe({
+ x : 0, y : 0,
+ width : rect.width,
+ height : rect.height,
+ });
+
+ break;
+ }
+
+ rfb.emit(rect.type, rect);
+ })
+ })
+ })
+};
View
13 lib/parser.js
@@ -0,0 +1,13 @@
+var Binary = require('binary')
+
+var handshake = require('./handshake');
+var messages = require('./messages');
+
+module.exports = function (rfb, opts) {
+ var bs = Binary(rfb.stream);
+
+ handshake.call(bs, rfb, opts);
+ bs.loop(function () {
+ messages.call(this, rfb, opts);
+ });
+};
Please sign in to comment.
Something went wrong with that request. Please try again.