1
0
Fork 0
mirror of https://github.com/openstf/stf synced 2025-10-05 10:39:25 +02:00

Now able to read VNC Viewer's primary requests.

This commit is contained in:
Simo Kinnunen 2015-09-13 20:09:15 +09:00
parent 045737e4bf
commit 66182666bd
3 changed files with 412 additions and 0 deletions

View file

@ -0,0 +1,14 @@
function PixelFormat(values) {
this.bitsPerPixel = values.bitsPerPixel
this.depth = values.depth
this.bigEndianFlag = values.bigEndianFlag
this.trueColorFlag = values.trueColorFlag
this.redMax = values.redMax
this.greenMax = values.greenMax
this.blueMax = values.blueMax
this.redShift = values.redShift
this.greenShift = values.greenShift
this.blueShift = values.blueShift
}
module.exports = PixelFormat

View file

@ -0,0 +1,397 @@
var net = require('net')
var util = require('util')
var EventEmitter = require('eventemitter3').EventEmitter
var debug = require('debug')('vnc')
var PixelFormat = require('./pixelformat')
function VncServer(server) {
this._bound = {
_connectionListener: this._connectionListener.bind(this)
}
this.server = server
.on('connection', this._bound._connectionListener)
}
util.inherits(VncServer, EventEmitter)
VncServer.prototype._connectionListener = function(conn) {
debug('connection', conn.remoteAddress, conn.remotePort)
new VncConnection(conn)
}
function VncConnection(conn) {
this._bound = {
_readableListener: this._readableListener.bind(this)
}
this._buffer = null
this._state = 0
this._changeState(VncConnection.STATE_NEED_CLIENT_VERSION)
this._serverVersion = VncConnection.V3_008
this._serverSupportedSecurity = [VncConnection.SECURITY_NONE]
this._serverWidth = 800
this._serverHeight = 600
this._serverPixelFormat = new PixelFormat({
bitsPerPixel: 32
, depth: 24
, bigEndianFlag: 1
, trueColorFlag: 1
, redMax: 255
, greenMax: 255
, blueMax: 255
, redShift: 16
, greenShift: 8
, blueShift: 0
})
this._serverName = 'stf'
this._clientVersion = null
this._clientShare = false
this._clientWidth = this._serverWidth
this._clientHeight = this._serverHeight
this._clientPixelFormat = this._serverPixelFormat
this._clientEncodingCount = 0
this._clientEncodings = []
this.conn = conn
.on('readable', this._bound._readableListener)
this._writeServerVersion()
this._read()
}
util.inherits(VncConnection, EventEmitter)
VncConnection.V3_003 = 3003
VncConnection.V3_007 = 3007
VncConnection.V3_008 = 3008
VncConnection.SECURITY_NONE = 1
VncConnection.SECURITY_VNC = 2
VncConnection.SECURITYRESULT_OK = 0
VncConnection.SECURITYRESULT_FAIL = 1
VncConnection.CLIENT_MESSAGE_SETPIXELFORMAT = 0
VncConnection.CLIENT_MESSAGE_SETENCODINGS = 2
VncConnection.CLIENT_MESSAGE_FBUPDATEREQUEST = 3
VncConnection.CLIENT_MESSAGE_KEYEVENT = 4
VncConnection.CLIENT_MESSAGE_POINTEREVENT = 5
VncConnection.CLIENT_MESSAGE_CLIENTCUTTEXT = 6
var StateReverse = Object.create(null), State = {
STATE_NEED_CLIENT_VERSION: 10
, STATE_NEED_CLIENT_SECURITY: 20
, STATE_NEED_CLIENT_INIT: 30
, STATE_NEED_CLIENT_MESSAGE: 40
, STATE_NEED_CLIENT_MESSAGE_SETPIXELFORMAT: 50
, STATE_NEED_CLIENT_MESSAGE_SETENCODINGS: 60
, STATE_NEED_CLIENT_MESSAGE_SETENCODINGS_ARRAY: 61
, STATE_NEED_CLIENT_MESSAGE_FBUPDATEREQUEST: 70
, STATE_NEED_CLIENT_MESSAGE_KEYEVENT: 80
, STATE_NEED_CLIENT_MESSAGE_POINTEREVENT: 90
, STATE_NEED_CLIENT_MESSAGE_CLIENTCUTTEXT: 100
}
Object.keys(State).map(function(name) {
VncConnection[name] = State[name]
StateReverse[State[name]] = name
})
VncConnection.prototype._writeServerVersion = function() {
// Yes, we could just format the string instead. Didn't feel like it.
switch (this._serverVersion) {
case VncConnection.V3_003:
this._write(new Buffer('RFB 003.003\n'))
break
case VncConnection.V3_007:
this._write(new Buffer('RFB 003.007\n'))
break
case VncConnection.V3_008:
this._write(new Buffer('RFB 003.008\n'))
break
}
}
VncConnection.prototype._writeSupportedSecurity = function() {
var chunk = new Buffer(1 + this._serverSupportedSecurity.length)
chunk[0] = this._serverSupportedSecurity.length
this._serverSupportedSecurity.forEach(function(security, i) {
chunk[1 + i] = security
})
this._write(chunk)
}
VncConnection.prototype._writeSelectedSecurity = function() {
var chunk = new Buffer(4)
chunk.writeUInt32BE(VncConnection.SECURITY_NONE, 0)
this._write(chunk)
}
VncConnection.prototype._writeSecurityResult = function(result, reason) {
var chunk
switch (result) {
case VncConnection.SECURITYRESULT_OK:
chunk = new Buffer(4)
chunk.writeUInt32BE(result, 0)
this._write(chunk)
break
case VncConnection.SECURITYRESULT_FAIL:
chunk = new Buffer(4 + 4 + reason.length)
chunk.writeUInt32BE(result, 0)
chunk.writeUInt32BE(reason.length, 4)
chunk.write(reason, 8, reason.length)
this._write(chunk)
break
}
}
VncConnection.prototype._writeServerInit = function() {
var chunk = new Buffer(2 + 2 + 16 + 4 + this._serverName.length)
chunk.writeUInt16BE(this._serverWidth, 0)
chunk.writeUInt16BE(this._serverHeight, 2)
chunk[4] = this._serverPixelFormat.bitsPerPixel
chunk[5] = this._serverPixelFormat.depth
chunk[6] = this._serverPixelFormat.bigEndianFlag
chunk[7] = this._serverPixelFormat.trueColorFlag
chunk.writeUInt16BE(this._serverPixelFormat.redMax, 8)
chunk.writeUInt16BE(this._serverPixelFormat.greenMax, 10)
chunk.writeUInt16BE(this._serverPixelFormat.blueMax, 12)
chunk[14] = this._serverPixelFormat.redShift
chunk[15] = this._serverPixelFormat.greenShift
chunk[16] = this._serverPixelFormat.blueShift
chunk[17] = 0 // padding
chunk[18] = 0 // padding
chunk[19] = 0 // padding
chunk.writeUInt32BE(this._serverName.length, 20)
chunk.write(this._serverName, 24, this._serverName.length)
this._write(chunk)
}
VncConnection.prototype._readableListener = function() {
this._read()
}
VncConnection.prototype._read = function() {
var chunk, lo, hi
while (this._append(this.conn.read())) {
do {
debug('state', StateReverse[this._state])
switch (this._state) {
case VncConnection.STATE_NEED_CLIENT_VERSION:
if ((chunk = this._consume(12))) {
this._clientVersion = this._parseVersion(chunk)
debug('client version', this._clientVersion)
this._writeSupportedSecurity()
this._changeState(VncConnection.STATE_NEED_CLIENT_SECURITY)
}
break
case VncConnection.STATE_NEED_CLIENT_SECURITY:
if ((chunk = this._consume(1))) {
this._clientSecurity = this._parseSecurity(chunk)
debug('client security', this._clientSecurity)
this._writeSecurityResult(VncConnection.SECURITYRESULT_OK)
this._changeState(VncConnection.STATE_NEED_CLIENT_INIT)
}
break
case VncConnection.STATE_NEED_CLIENT_INIT:
if ((chunk = this._consume(1))) {
this._clientShare = chunk[0]
debug('client shareFlag', this._clientShare)
this._writeServerInit()
this._changeState(VncConnection.STATE_NEED_CLIENT_MESSAGE)
}
break
case VncConnection.STATE_NEED_CLIENT_MESSAGE:
if ((chunk = this._consume(1))) {
switch (chunk[0]) {
case VncConnection.CLIENT_MESSAGE_SETPIXELFORMAT:
this._changeState(VncConnection.STATE_NEED_CLIENT_MESSAGE_SETPIXELFORMAT)
break
case VncConnection.CLIENT_MESSAGE_SETENCODINGS:
this._changeState(VncConnection.STATE_NEED_CLIENT_MESSAGE_SETENCODINGS)
break
case VncConnection.CLIENT_MESSAGE_FBUPDATEREQUEST:
this._changeState(VncConnection.STATE_NEED_CLIENT_MESSAGE_FBUPDATEREQUEST)
break
case VncConnection.CLIENT_MESSAGE_KEYEVENT:
this._changeState(VncConnection.STATE_NEED_CLIENT_MESSAGE_KEYEVENT)
break
case VncConnection.CLIENT_MESSAGE_POINTEREVENT:
this._changeState(VncConnection.STATE_NEED_CLIENT_MESSAGE_POINTEREVENT)
break
case VncConnection.CLIENT_MESSAGE_CLIENTCUTTEXT:
this._changeState(VncConnection.STATE_NEED_CLIENT_MESSAGE_CLIENTCUTTEXT)
break
default:
throw new Error(util.format('Unsupported message type %d', chunk[0]))
}
}
break
case VncConnection.STATE_NEED_CLIENT_MESSAGE_SETPIXELFORMAT:
if ((chunk = this._consume(19))) {
// [0b, 3b) padding
this._clientPixelFormat = new PixelFormat({
bitsPerPixel: chunk[3]
, depth: chunk[4]
, bigEndianFlag: chunk[5]
, trueColorFlag: chunk[6]
, redMax: chunk.readUInt16BE(7, true)
, greenMax: chunk.readUInt16BE(9, true)
, blueMax: chunk.readUInt16BE(11, true)
, redShift: chunk[13]
, greenShift: chunk[14]
, blueShift: chunk[15]
})
// [16b, 19b) padding
debug('client pixel format', this._clientPixelFormat)
this._changeState(VncConnection.STATE_NEED_CLIENT_MESSAGE)
}
break
case VncConnection.STATE_NEED_CLIENT_MESSAGE_SETENCODINGS:
if ((chunk = this._consume(3))) {
// [0b, 1b) padding
this._clientEncodingCount = chunk.readUInt16BE(1, true)
this._changeState(VncConnection.STATE_NEED_CLIENT_MESSAGE_SETENCODINGS_ARRAY)
}
break
case VncConnection.STATE_NEED_CLIENT_MESSAGE_SETENCODINGS_ARRAY:
lo = 0
hi = 4 * this._clientEncodingCount
if ((chunk = this._consume(hi))) {
this._clientEncodings = []
while (lo < hi) {
this._clientEncodings.push(chunk.readInt32BE(lo, true))
lo += 4
}
debug('client encodings', this._clientEncodings)
this._changeState(VncConnection.STATE_NEED_CLIENT_MESSAGE)
}
break
case VncConnection.STATE_NEED_CLIENT_MESSAGE_FBUPDATEREQUEST:
if ((chunk = this._consume(9))) {
// incremental = chunk[0]
// xPosition = chunk.readUInt16BE(1, true)
// yPosition = chunk.readUInt16BE(3, true)
// width = chunk.readUInt16BE(5, true)
// height = chunk.readUInt16BE(7, true)
this._changeState(VncConnection.STATE_NEED_CLIENT_MESSAGE)
}
break
case VncConnection.STATE_NEED_CLIENT_MESSAGE_KEYEVENT:
if ((chunk = this._consume(7))) {
// downFlag = chunk[0]
// [1b, 3b) padding
// key = chunk.readUInt32BE(3, true)
this._changeState(VncConnection.STATE_NEED_CLIENT_MESSAGE)
}
break
case VncConnection.STATE_NEED_CLIENT_MESSAGE_POINTEREVENT:
if ((chunk = this._consume(5))) {
// buttonMask = chunk[0]
// xPosition = chunk.readUInt16BE(1, true)
// yPosition = chunk.readUInt16BE(3, true)
this._changeState(VncConnection.STATE_NEED_CLIENT_MESSAGE)
}
break
case VncConnection.STATE_NEED_CLIENT_MESSAGE_CLIENTCUTTEXT:
if ((chunk = this._consume(7))) {
// [0b, 3b) padding
// length = chunk.readUInt32BE(3)
this._changeState(VncConnection.STATE_NEED_CLIENT_MESSAGE_CLIENTCUTTEXT_VALUE)
}
break
}
}
while (chunk)
}
}
VncConnection.prototype._parseVersion = function(chunk) {
if (chunk.equals(new Buffer('RFB 003.008\n'))) {
return VncConnection.V3_008
}
if (chunk.equals(new Buffer('RFB 003.007\n'))) {
return VncConnection.V3_007
}
if (chunk.equals(new Buffer('RFB 003.003\n'))) {
return VncConnection.V3_003
}
throw new Error('Unsupported version')
}
VncConnection.prototype._parseSecurity = function(chunk) {
switch (chunk[0]) {
case VncConnection.SECURITY_NONE:
case VncConnection.SECURITY_VNC:
return chunk[0]
default:
throw new Error('Unsupported security type')
}
}
VncConnection.prototype._changeState = function(state) {
this._state = state
}
VncConnection.prototype._append = function(chunk) {
if (!chunk) {
return false
}
debug('in', chunk)
if (this._buffer) {
this._buffer = Buffer.concat(
[this._buffer, chunk], this._buffer.length + chunk.length)
}
else {
this._buffer = chunk
}
return true
}
VncConnection.prototype._consume = function(n) {
var chunk
if (!this._buffer) {
return null
}
if (n < this._buffer.length) {
chunk = this._buffer.slice(0, n)
this._buffer = this._buffer.slice(n)
return chunk
}
if (n === this._buffer.length) {
chunk = this._buffer
this._buffer = null
return chunk
}
return null
}
VncConnection.prototype._write = function(chunk) {
debug('out', chunk)
this.conn.write(chunk)
}
var nserv = net.createServer({
allowHalfOpen: true
})
var vserv = new VncServer(nserv)
nserv.listen(5910)

View file

@ -40,6 +40,7 @@
"compression": "^1.5.2", "compression": "^1.5.2",
"cookie-session": "^1.2.0", "cookie-session": "^1.2.0",
"csurf": "^1.7.0", "csurf": "^1.7.0",
"debug": "^2.2.0",
"eventemitter3": "^0.1.6", "eventemitter3": "^0.1.6",
"express": "^4.13.3", "express": "^4.13.3",
"express-validator": "^2.17.1", "express-validator": "^2.17.1",