Mon 21 Jul 22:43:21 CEST 2025

This commit is contained in:
sbosse 2025-07-21 22:59:57 +02:00
parent f6f81aceee
commit 93e74774fd

231
js/x11/core/handshake.js Normal file
View File

@ -0,0 +1,231 @@
var getAuthString = Require('x11/core/auth');
var xutil = Require('x11/core/xutil');
function readVisuals(bl, visuals, n_visuals, cb)
{
if (n_visuals == 0)
{
cb();
return;
}
var visual = {};
bl.unpackTo( visual,
[
'L vid',
'C class',
'C bits_per_rgb',
'S map_ent',
'L red_mask',
'L green_mask',
'L blue_mask',
'xxxx'
],
function() {
var vid = visual.vid;
// delete visual.vid;
visuals[visual.vid] = visual;
if (Object.keys(visuals).length == n_visuals)
cb()
else
readVisuals(bl, visuals, n_visuals, cb);
});
}
function readScreens(bl, display, cbDisplayReady)
{
var numParsedDepths = 0;
var readDepths = function(bl, display, depths, n_depths, cb)
{
if (n_depths == 0)
{
cb();
return;
}
bl.unpack( 'CxSxxxx', function(res) {
var dep = res[0];
var n_visuals = res[1];
var visuals = {};
readVisuals(bl, visuals, n_visuals, function()
{
if (dep in depths) {
for (var visual in visuals) {
depths[dep][visual] = visuals[visual];
}
} else {
depths[dep] = visuals;
}
numParsedDepths++;
if (numParsedDepths == n_depths)
cb();
else
readDepths(bl, display, depths, n_depths, cb);
});
});
}
// for (i=0; i < display.screen_num; ++i)
{
var scr = {};
bl.unpackTo( scr,
[
'L root',
'L default_colormap',
'L white_pixel',
'L black_pixel',
'L input_masks',
'S pixel_width',
'S pixel_height',
'S mm_width',
'S mm_height',
'S min_installed_maps',
'S max_installed_maps',
'L root_visual',
'C root_depth',
'C backing_stores',
'C root_depth',
'C num_depths'
],
function () {
var depths = {};
readDepths(bl, display, depths, scr.num_depths, function() {
scr.depths = depths;
delete scr.num_depths;
display.screen.push(scr);
if (display.screen.length == display.screen_num)
{
delete display.screen_num;
cbDisplayReady(null, display);
return;
} else {
readScreens(bl, display, cbDisplayReady);
}
});
});
}
}
function readServerHello(bl, cb)
{
bl.unpack('C', function(res) {
if (res[0] == 0)
{
// conection time error
// unpack error
bl.unpack('Cxxxxxx', function (rlen) {
bl.get(rlen[0], function (reason) {
var err = new Error;
err.message = 'X server connection failed: ' + reason.toString();
cb(err);
});
});
// TODO: do we need to close stream from our side?
// TODO: api to close source stream via attached unpackstream
return;
}
var display = {};
bl.unpackTo(
display,
[
'x',
'S major',
'S minor',
'S xlen',
'L release',
'L resource_base',
'L resource_mask',
'L motion_buffer_size',
'S vlen',
'S max_request_length',
'C screen_num',
'C format_num',
'C image_byte_order',
'C bitmap_bit_order',
'C bitmap_scanline_unit',
'C bitmap_scanline_pad',
'C min_keycode',
'C max_keycode',
'xxxx'
],
function()
{
var pvlen = xutil.padded_length(display.vlen);
// setup data to generate resource id
// TODO: cleaunup code here
var mask = display.resource_mask;
display.rsrc_shift = 0;
while (!( (mask >> display.rsrc_shift) & 1) )
display.rsrc_shift++;
display.rsrc_id = 0;
bl.get(pvlen, function(vendor)
{
display.vendor = vendor.toString().substr(0, display.vlen); // utf8 by default?
display.format = {};
for (var i=0; i < display.format_num; ++i)
{
bl.unpack('CCCxxxxx', function(fmt) {
var depth = fmt[0];
display.format[depth] = {};
display.format[depth].bits_per_pixel = fmt[1];
display.format[depth].scanline_pad = fmt[2];
if (Object.keys(display.format).length == display.format_num)
{
delete display.format_num;
display.screen = [];
readScreens(bl, display, cb);
}
});
}
});
}
);
});
}
function getByteOrder() {
var isLittleEndian = ((new Uint32Array((new Uint8Array([1,2,3,4])).buffer))[0] === 0x04030201);
if (isLittleEndian) {
return 'l'.charCodeAt(0);
} else {
return 'B'.charCodeAt(0);
}
}
function writeClientHello(stream, displayNum, authHost, authFamily)
{
getAuthString( displayNum, authHost, authFamily, function( err, cookie ) {
if (err) {
throw err;
}
var byte_order = getByteOrder();
var protocol_major = 11; // TODO: config? env?
var protocol_minor = 0;
stream.pack(
'CxSSSSxxpp',
[
byte_order,
protocol_major,
protocol_minor,
cookie.authName.length,
cookie.authData.length,
cookie.authName,
cookie.authData
]
);
stream.flush();
});
}
module.exports.readServerHello = readServerHello;
module.exports.writeClientHello = writeClientHello;