194 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			194 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								"use strict";
							 | 
						||
| 
								 | 
							
								var util = require('util');
							 | 
						||
| 
								 | 
							
								var net = require('net');
							 | 
						||
| 
								 | 
							
								var PackStream = require('./unpackstream');
							 | 
						||
| 
								 | 
							
								var EventEmitter = require('events').EventEmitter;
							 | 
						||
| 
								 | 
							
								var rfb = require('./constants');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function RfbServer(stream, params)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								     EventEmitter.call(this);
							 | 
						||
| 
								 | 
							
								     this.params = params;
							 | 
						||
| 
								 | 
							
								     var serv = this;
							 | 
						||
| 
								 | 
							
								     serv.stream = stream;
							 | 
						||
| 
								 | 
							
								     serv.pack_stream = new PackStream();
							 | 
						||
| 
								 | 
							
								     serv.pack_stream.on('data', function( data ) {
							 | 
						||
| 
								 | 
							
								         serv.stream.write(data);
							 | 
						||
| 
								 | 
							
								     });
							 | 
						||
| 
								 | 
							
								     stream.on('data', function( data ) {
							 | 
						||
| 
								 | 
							
								         serv.pack_stream.write(data);
							 | 
						||
| 
								 | 
							
								     });
							 | 
						||
| 
								 | 
							
								     serv.writeServerVersion();
							 | 
						||
| 
								 | 
							
								     serv.params = {};
							 | 
						||
| 
								 | 
							
								     serv.params.password = 'tetris';
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								util.inherits(RfbServer, EventEmitter);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								RfbServer.prototype.writeServerVersion = function()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    var serv = this;
							 | 
						||
| 
								 | 
							
								    this.stream.write(rfb.versionstring.V3_008);
							 | 
						||
| 
								 | 
							
								    this.pack_stream.get(12, function(buf) {
							 | 
						||
| 
								 | 
							
								        serv.emit('clientversion', buf.toString('ascii'));
							 | 
						||
| 
								 | 
							
								        console.log(['client version', buf]);
							 | 
						||
| 
								 | 
							
								        serv.writeSecurityTypes();
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								RfbServer.prototype.writeSecurityTypes = function()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    console.log("RfbServer.prototype.writeSecurityTypes");
							 | 
						||
| 
								 | 
							
								    var serv = this;
							 | 
						||
| 
								 | 
							
								    var sectypes = [rfb.security.VNC];
							 | 
						||
| 
								 | 
							
								    serv.pack_stream.pack('C', [sectypes.length]);
							 | 
						||
| 
								 | 
							
								    serv.pack_stream.flush();
							 | 
						||
| 
								 | 
							
								    for (var i=0; i < sectypes.length; ++i)
							 | 
						||
| 
								 | 
							
								        serv.pack_stream.pack('C', [sectypes[i]]);
							 | 
						||
| 
								 | 
							
								    serv.pack_stream.flush();
							 | 
						||
| 
								 | 
							
								    serv.pack_stream.unpack('C', function(cliSecType) {
							 | 
						||
| 
								 | 
							
								        serv.securityType = cliSecType[0];
							 | 
						||
| 
								 | 
							
								        serv.processSecurity();
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								RfbServer.prototype.processSecurity = function()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    console.log("RfbServer.prototype.processSecurity");
							 | 
						||
| 
								 | 
							
								    var serv = this;
							 | 
						||
| 
								 | 
							
								    switch(serv.securityType)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    case rfb.security.None:
							 | 
						||
| 
								 | 
							
								        console.log('not yet');
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    case rfb.security.VNC:
							 | 
						||
| 
								 | 
							
								        // generate random 16 byte challenge
							 | 
						||
| 
								 | 
							
								        serv.challenge = new Buffer(16);
							 | 
						||
| 
								 | 
							
								        serv.challenge.write('1234567890abcdef');
							 | 
						||
| 
								 | 
							
								        console.log(['sending challenge', serv.challenge]);
							 | 
						||
| 
								 | 
							
								        serv.pack_stream.pack('a', [serv.challenge]).flush();
							 | 
						||
| 
								 | 
							
								        serv.pack_stream.get(16, function(clientResponseBuf)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            var response = require('./d3des').response(serv.challenge, serv.params.password).toString('binary');
							 | 
						||
| 
								 | 
							
								            var clientResponse = clientResponseBuf.toString('binary');
							 | 
						||
| 
								 | 
							
								            console.log([response, clientResponse]);
							 | 
						||
| 
								 | 
							
								            if (response === clientResponse) {
							 | 
						||
| 
								 | 
							
								                serv.pack_stream.pack('L', [0]).flush();
							 | 
						||
| 
								 | 
							
								                serv.readClientInit();
							 | 
						||
| 
								 | 
							
								                return;
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                console.error('invalid password!');
							 | 
						||
| 
								 | 
							
								                process.exit(0);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        })
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								RfbServer.prototype.readClientInit = function()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // TODO: read options, add 'disconnect others' code
							 | 
						||
| 
								 | 
							
								    var serv = this;
							 | 
						||
| 
								 | 
							
								    serv.pack_stream.unpack('C', function(isShared) {
							 | 
						||
| 
								 | 
							
								        console.log([isShared]);
							 | 
						||
| 
								 | 
							
								        serv.writeServerInit();
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								RfbServer.prototype.writeServerInit = function()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    var serv = this;
							 | 
						||
| 
								 | 
							
								    var title = 'Param-pam-pam';
							 | 
						||
| 
								 | 
							
								    serv.pack_stream.pack('SSCCCCSSSCCCxxxLa', [
							 | 
						||
| 
								 | 
							
								        800, //serv.width,
							 | 
						||
| 
								 | 
							
								        600, //serv.height,
							 | 
						||
| 
								 | 
							
								        32, //serv.bpp,
							 | 
						||
| 
								 | 
							
								        24, //serv.depth,
							 | 
						||
| 
								 | 
							
								        1, // bigEndien
							 | 
						||
| 
								 | 
							
								        1, // trueColor
							 | 
						||
| 
								 | 
							
								        255, // red max
							 | 
						||
| 
								 | 
							
								        255, // green
							 | 
						||
| 
								 | 
							
								        255, // blue
							 | 
						||
| 
								 | 
							
								        16,  // red shift
							 | 
						||
| 
								 | 
							
								        8,   // green 
							 | 
						||
| 
								 | 
							
								        0,    // blue
							 | 
						||
| 
								 | 
							
								        title.length,
							 | 
						||
| 
								 | 
							
								        title
							 | 
						||
| 
								 | 
							
								    ]);
							 | 
						||
| 
								 | 
							
								    serv.pack_stream.flush();
							 | 
						||
| 
								 | 
							
								    serv.expectMessage();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function repeat(str, num)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    var res = '';
							 | 
						||
| 
								 | 
							
								    for (var i=0; i < num; ++i)
							 | 
						||
| 
								 | 
							
								        res += str;
							 | 
						||
| 
								 | 
							
								    return res;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								RfbServer.prototype.expectMessage = function()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    var serv = this;
							 | 
						||
| 
								 | 
							
								    serv.pack_stream.get(1, function(msgType) {
							 | 
						||
| 
								 | 
							
								        switch(msgType[0]) {
							 | 
						||
| 
								 | 
							
								        case rfb.clientMsgTypes.setPixelFormat:
							 | 
						||
| 
								 | 
							
								        case rfb.clientMsgTypes.fbUpdate:
							 | 
						||
| 
								 | 
							
								            var updateRequest = {};
							 | 
						||
| 
								 | 
							
								            serv.pack_stream.unpackTo(updateRequest, [
							 | 
						||
| 
								 | 
							
								                'C incremental',
							 | 
						||
| 
								 | 
							
								                'S width',
							 | 
						||
| 
								 | 
							
								                'S height', 
							 | 
						||
| 
								 | 
							
								                'S x', 
							 | 
						||
| 
								 | 
							
								                'S y'], 
							 | 
						||
| 
								 | 
							
								            function() {
							 | 
						||
| 
								 | 
							
								                serv.emit('fbUpdate', updateRequest);
							 | 
						||
| 
								 | 
							
								                serv.expectMessage();
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								        case rfb.clientMsgTypes.setEncodings:
							 | 
						||
| 
								 | 
							
								            serv.pack_stream.unpack('xS', function(numEnc)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                serv.pack_stream.unpack(repeat('L', numEnc), function(res) {
							 | 
						||
| 
								 | 
							
								                    serv.emit('setEncodings', res);
							 | 
						||
| 
								 | 
							
								                    console.log(['setEncodings', res]);
							 | 
						||
| 
								 | 
							
								                    serv.expectMessage();
							 | 
						||
| 
								 | 
							
								                })
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								        case rfb.clientMsgTypes.pointerEvent:
							 | 
						||
| 
								 | 
							
								             serv.pack_stream.unpack('CSS', function(res) {
							 | 
						||
| 
								 | 
							
									        var pointerEvent = {
							 | 
						||
| 
								 | 
							
								                    buttons: res[0],
							 | 
						||
| 
								 | 
							
								                    x: res[1],
							 | 
						||
| 
								 | 
							
								                    y: res[2]
							 | 
						||
| 
								 | 
							
								                };
							 | 
						||
| 
								 | 
							
								                serv.emit('pointer', pointerEvent);
							 | 
						||
| 
								 | 
							
								                console.log(['pointer', pointerEvent]);
							 | 
						||
| 
								 | 
							
									        serv.expectMessage();
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								        case rfb.clientMsgTypes.keyEvent:
							 | 
						||
| 
								 | 
							
								             serv.pack_stream.unpack('CxxL', function(res) {
							 | 
						||
| 
								 | 
							
									        var keyEvent = {
							 | 
						||
| 
								 | 
							
								                    isDown: res[0],
							 | 
						||
| 
								 | 
							
								                    keysym: res[1]
							 | 
						||
| 
								 | 
							
								                };
							 | 
						||
| 
								 | 
							
								                serv.emit('key', keyEvent);
							 | 
						||
| 
								 | 
							
								                console.log(['key', keyEvent]);
							 | 
						||
| 
								 | 
							
									        serv.expectMessage();
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								        case rfb.clientMsgTypes.cutText:
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								            console.log('Got message from client: ' + msgType[0]);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								    });   
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var s = net.createServer(function(conn) {
							 | 
						||
| 
								 | 
							
								    var rfbserv = new RfbServer(conn);
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								s.listen(5910);
							 |