#StackBounty: #javascript #node.js #websocket #xtermjs #blessed Blessed server (Node.js) over websocket to Xterm.js client in Browser

Bounty: 50

What I have:

  • Node.js script running Blessed, and http/websocket server.
  • Browser running Xterm.js and websocket client.

What I want to do:

  • Render blessed to the xterm window over websockets.

Server Code:

"use strict";

process.title = 'neosim-server';

var blessed = require('neo-blessed');
var contrib = require('blessed-contrib');
var webSocketServer = require('websocket').server;
var http = require('http');

const webSocketsServerPort = 8080;
var clients = [ ];

/**
 * HTTP server
 */
var server = http.createServer(function(request, response) {
    // Not important for us. We're writing WebSocket server,
    // not HTTP server
});
server.listen(webSocketsServerPort, function() {
    console.log((new Date()) + " Server is listening on port "
        + webSocketsServerPort + ".");
});

/**
 * WebSocket server
 */
var wsServer = new webSocketServer({
    // WebSocket server is tied to a HTTP server. WebSocket
    // request is just an enhanced HTTP request. For more info 
    // http://tools.ietf.org/html/rfc6455#page-6
    httpServer: server,
    autoAcceptConnections: false
});

function originIsAllowed(origin) {
    // put logic here to detect whether the specified origin is allowed.

    return true;
  }

// This callback function is called every time someone
// tries to connect to the WebSocket server
wsServer.on('request', function(request) {
    if (!originIsAllowed(request.origin)) {
        request.reject();
        console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
        return;
    }
    console.log((new Date()) + ' Connection from origin '
        + request.origin + '.');

    // accept connection - you should check 'request.origin' to
    // make sure that client is connecting from your website
    // (http://en.wikipedia.org/wiki/Same_origin_policy)
    var connection = request.accept(null, request.origin); 
    // we need to know client index to remove them on 'close' event
    connection.write = connection.send;
    connection.read = connection.socket.read;
    connection.program = blessed.program({
        tput: true,
        input: connection,
        output: connection
    });
    connection.program.tput = blessed.tput({
        term: 'xterm-256color',
        extended: true,
    });
    connection.screen = blessed.screen({
        program: connection.program,
        tput: connection.program.tput,
        input: connection,
        output: connection,
        //smartCSR: true,
        terminal: 'xterm-256color',
        fullUnicode: true
    });


    var index = clients.push(connection) - 1;

    var userName = false;

    console.log((new Date()) + ' Connection accepted.');
    connection.program.write("test");

    // send back chat history
    /*if (history.length > 0) {
    connection.sendUTF(
        JSON.stringify({ type: 'history', data: history} ));
    }*/

    // terminal type message
    connection.on('term', function(terminal) {
        console.log("Term");
        connection.screen.terminal = terminal;
        connection.screen.render();
    });

    connection.on('resize', function(width, height) {
        console.log("Resize");
        connection.columns = width;
        connection.rows = height;
        connection.emit('resize');
    });

    // user sent some message
    connection.on('message', function(message) {
        if (message.type === 'utf8') { // accept only text
            console.log((new Date()) + ' Received Message: ' + message.utf8Data);
        }
    });

    // user disconnected
    connection.on('close', function(connection) {
        if (connection.screen && !connection.screen.destroyed) {
            connection.screen.destroy();
        }
    });

    connection.screen.key(['C-c', 'q'], function(ch, key) {
        connection.screen.destroy();
    });

    connection.screen.on('destroy', function() {
        if (connection.writable) {
            connection.destroy();
        }
    });

    connection.screen.data.main = blessed.box({
        parent: connection.screen,
        left: 'center',
        top: 'center',
        width: '80%',
        height: '90%',
        border: 'line',
        content: 'Welcome to my server. Here is your own private session.'
    });

    connection.screen.render();
});

Client page:

<!doctype html>
  <html lang="en">
    <head>
      <link rel="stylesheet" href="node_modules/xterm/dist/xterm.css" />
      http://node_modules/xterm/dist/xterm.js
      http://node_modules/xterm/dist/addons/attach/attach.js
      http://node_modules/xterm/dist/addons/fit/fit.js
      http://node_modules/xterm/dist/addons/winptyCompat/winptyCompat.js
    </head>
    <body>
      
Terminal.applyAddon(attach); Terminal.applyAddon(fit); Terminal.applyAddon(winptyCompat); var term = new Terminal(); var socket = new WebSocket('ws://localhost:8080', null); term.open(document.getElementById('terminal')); term.winptyCompatInit(); term.fit(); term.focus(); term.write('Terminal ('+term.cols+'x'+term.rows+')nr'); // term.write('Hello from x1B[1;3;31mxterm.jsx1B[0m $ ') // window.addEventListener('resize', resizeScreen, false) function resizeScreen () { term.fit(); socket.emit('resize', { cols: term.cols, rows: term.rows }); }; socket.onopen = function (connection) { term.attach(socket, true, false); //term.emit('term'); //term.emit('resize'); }; socket.onmessage = function (message) { term.write(message); }; </body> </html>

The issue I am having is when screen.render() is called, nothing shows up on the client. When creating my blessed.screen, I’ve attempted using:

connection.screen = blessed.screen({input: connection.socket, output: connection.socket});

But this does not work either. In my current server code, I was attempting to trick blessed into using connection.send rather than connect.socket.write, because I think that browser websockets only accept the ‘onmessage’ event. Like so:

connection.write = connection.send;
connection.read = connection.socket.read;
connection.screen = blessed.screen({input: connection, output: connection});

Nothing I have tried so far has worked. What am I doing wrong here? Or is it simply that blessed won’t work with browser websockets. Also, I know the connection is working, because I can send/receive messages on both ends.


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.