Closed olalonde closed 9 years ago
I wrote a response to this a while ago and forgot to post it...
cc @martindale
Yeah, we can allow this. Should have been there from the beginning, I just never added setRawMode checks to see if it was a tty stream or socket. It's a simple fix.
I'm assuming you are telnetting or ncing to a server (running blessed) from a terminal (possibly for a MUD or Rougelike?).
I have a few pointers here if this is the case, especially if there are multiple clients and/or Screens involved.
It might be screwy with telnet if telnet is line-buffered. It has to be raw (can't be cooked) and it also needs to be one byte at a time, no buffering. If it line buffers, key sequences will not go through properly.
Another gotcha: your blessed server will use whatever terminfo you have set as TERM. So if it's xterm
, whoever is connecting should be using an xterm-like terminal, however, you might be able to work out some kind of (UI) handshake where the client tells you it's TERM and you switch the tput
object around in screen.tput
and screen.program.tput
. (NOTE: Make sure you have all terminfo's available on the server, including rxvt-unicode and screen).
To swap tputs:
var clientTput = blessed.tput({
term: clientTerm,
extended: true
});
screen.tput = clientTput;
screen.program.tput = clientTput;
// Probably also for good measure:
// screen.leave();
// screen.enter();
Or, if you can manage to hold off before instantiating a screen, that would be ideal. You could simply do:
var screen = blessed.screen({
term: term,
input: socket,
output: socket
});
Another gotcha: terminal size. The client will also have to tell you it's rows and cols in this initialization or handshake. It should be easy enough to resize the screen in question.
To resize:
socket.rows = clientRows;
socket.columns = clientCols;
socket.emit('resize');
Or, again, if you can manage to hold off before instantiating, this would be ideal (but you're likely going to have to resize later if a user resizes the terminal):
socket.rows = rows;
socket.columns = cols;
var screen = blessed.screen({
term: term,
input: socket,
output: socket
});
Yet another gotcha: whether the client's machine supports unicode or not. The LANG/LC env vars will have to be relayed to the server to check and changed on the tput object depending. You'll have to hook into Tput.prototype.detectUnicode
. You'll probably also have to alter the screen's _unicode
property.
Also, security measures: do not allow any screen.spawn's, screen.exec's, screen.readEditor's, or textarea.readEditor's because it will use the server's editor/program and the client may then have access to a shell on your server.
More security: it would be easy for a client to DOS the server if they constantly change TERMs. Blessed will go around and parse and compile every terminfo it sees. It doesn't appear to be slow in a local blessed program, but if it's parsing hundreds of terminfos, it can block for quite a while (see node test/tput.js all
for how CPU intensive this really is, if you're interested). You might want to add some kind of throttle for that.
This will be interesting, because it actually puts multiple Screen instances to use, which should technically work, although, it's never been attempted before. Let me know how it goes.
The other solution: simply get all clients to agree on a TERM, LANG, cols/rows, and use one Screen object, which might be a bit easier for the server, but not so nice looking for the clients.
@olalonde, lots of improvements have now been made. There's even an example blessed telnet server if you're interested. See #157.
@chjj thanks.
I've been trying to use blessed with a Socket connection. Here's how initialise blessed:
Some commands seem to work fine, like
program.write
. However, when trying to run a more complex example like in the README, I am getting: