diff --git a/js/x11/core/xserver.js b/js/x11/core/xserver.js new file mode 100644 index 0000000..64e34e1 --- /dev/null +++ b/js/x11/core/xserver.js @@ -0,0 +1,198 @@ +"use strict"; +var util = Require('util'); +var net = Require('net'); +var PackStream = Require('x11/core/unpackstream'); +var EventEmitter = Require('events').EventEmitter; + +function XServer(servsock, params) +{ + var server = this; + EventEmitter.call(this); + servsock.on('connection', function(stream) { + var cli = new XServerClientConnection(stream, params); + server.emit('connection', cli); + }); +} +util.inherits(XServer, EventEmitter); + +function XServerClientConnection(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.sequence = 0; + serv.readClientHandshake(); +} +util.inherits(XServerClientConnection, EventEmitter); + +XServerClientConnection.prototype.readClientHandshake = function() +{ + var serv = this; + var hello = {}; + serv.pack_stream.unpackTo(hello, + [ + 'C byteOrder', + 'x', + 'S protocolMajor', + 'S protocolMinor', + 'S authTypeLength', + 'S authDataLength', + 'x', + 'x' + ], + function() { + console.log(hello); + serv.pack_stream.get(hello.authTypeLength, function(authType) { + serv.pack_stream.get(hello.authDataLength, function(authData) { + serv.byteOrder = hello.byteOrder; + serv.protocolMajor = hello.protocolMajor; + serv.protocolMinor = hello.protocolMinor; + serv.checkAuth(authType.toString('ascii'), authData); + }); + }); + } + ); +} + +XServerClientConnection.prototype.checkAuth = function(authType, authData) +{ + var serv = this; + // ignore check for now; + // protocol page 140: add code for reject & ask additional info + console.log('check auth'); + console.log([authType, authData.toString()]); + + // auth ok: reply with list of screens, visuals, root window info etc + var stream = serv.pack_stream; + +/* + xquartz exemple reply + +{ major: 11, + minor: 0, + xlen: 537, (bytes in whole header) + release: 11300000, + resource_base: 6291456, + resource_mask: 2097151, + motion_buffer_size: 256, + vlen: 20, + max_request_length: 65535, + screen_num: 1, + format_num: 7, + image_byte_order: 0, + bitmap_bit_order: 0, + bitmap_scanline_unit: 32, + bitmap_scanline_pad: 32, + min_keycode: 8, + max_keycode: 255 } + +per screen: +screen: { root: 226, + default_colormap: 33, + white_pixel: 16777215, + black_pixel: 0, + input_masks: 1703936, + pixel_width: 3286, + pixel_height: 1058, + mm_width: 866, + mm_height: 277, + min_installed_maps: 1, + max_installed_maps: 1, + root_visual: 34, + root_depth: 24, + backing_stores: 0, + num_depths: 7 } +17 'L root',¬ + 18 'L default_colormap',¬ + 19 'L white_pixel',¬ + 20 'L black_pixel',¬ + 21 'L input_masks',¬ + 22 'S pixel_width',¬ + 23 'S pixel_height',¬ + 24 'S mm_width',¬ + 25 'S mm_height',¬ + 26 'S min_installed_maps',¬ + 27 'S max_installed_maps',¬ + 28 'L root_visual',¬ + 29 'C root_depth',¬ + 30 'C backing_stores',¬ + 31 'C root_depth',¬ + 32 'C num_depths'¬ + + +per depth: + depth: [ 24, 80 ] (depth, num visuals) + +per visual: + visual { vid: 146, + class: 4, + bits_per_rgb: 8, + map_ent: 256, + red_mask: 16711680, + green_mask: 65280, + blue_mask: 255 } + +*/ + + //stream.pack('') + // [2, reason, + //serv.pack_stream.unpack('C', function(isShared) { + // console.log([isShared]); + // serv.writeServerInit(); + //}); + // + var hello = Require('fs').readFileSync('hello1.bin'); + stream.pack('CxSSSa', [1, 11, 0, hello.length/4, hello]); + stream.flush(); + serv.expectMessage(); +} + +XServerClientConnection.prototype.expectMessage = function() +{ + var serv = this; + console.log('expecting messages'); + serv.pack_stream.unpack('CCS', function(header) { + serv.sequence++; + console.log('Request:', header[0]); + console.log('Extra:', header[1]); + console.log('length:', header[2]); + serv.pack_stream.get((header[2]-1)*4, function(reqBody) { + + console.log('BODY:', reqBody, reqBody.toString()); + + if (header[0] == 98) { + serv.pack_stream.pack('CCSLCCCCLLLLL', [1, 0, serv.sequence, 0, 1, 134, 0, 0, 0, 0, 0, 0, 0, 0]); + serv.pack_stream.flush(); + } else if (header[0] == 134) { + console.log('ENABLE BIG REQ'); + serv.pack_stream.pack('CCSLLLLLLLL', [1, 0, serv.sequence, 0, 10000000, 0, 0, 0, 0, 0, 0 ]); + serv.pack_stream.flush(); + } + serv.expectMessage(); + + }); + }); +} + +module.exports.createServer = function(options, onconnect) { + if (typeof(options) === 'function') { + onconnect = options; + options = {}; + } + var s = net.createServer(); + var serv = new XServer(s, options); + serv.on('connect', onconnect); + return s; +} + +//module.exports.createServer(6002) ; +//function(client) { +//});