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" />
<script src="node_modules/xterm/dist/xterm.js"></script>
<script src="node_modules/xterm/dist/addons/attach/attach.js"></script>
<script src="node_modules/xterm/dist/addons/fit/fit.js"></script>
<script src="node_modules/xterm/dist/addons/winptyCompat/winptyCompat.js"></script>
</head>
<body>
<div id="terminal"></div>
<script>
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+')\n\r');
// term.write('Hello from \x1B[1;3;31mxterm.js\x1B[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);
};
</script>
</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.