A simple Node.js telnet server/client library.
MIT License
A simple Node.js telnet server/client library. It provides an interface similar to the standard net module (viz. createServer
and createConnection
) while abstracting option negotiation and providing handlers for some common options.
This example is a server that, once option negotiation finishes, says hello world to the client and then echos anything it receives back to the client. The client portion simply echos anything back to the server.
const telnetlib = require('telnetlib');
const server = telnetlib.createServer({}, (c) => {
c.on('negotiated', () => {
c.write('Hello World!');
});
c.on('data', (data) => {
c.write(data);
});
});
server.listen(9001);
const telnetlib = require('telnetlib');
const client = telnetlib.createConnection(
{
host: '127.0.0.1',
port: 9001
},
() => {
client.on('data', (data) => {
client.write(data);
});
}
);
telnetlib.createServer(options, handler)
options
Object
remoteOptions
Array Option codes we want enabled remotelylocalOptions
Array Option codes we want enabled locallyreceiveBuffermax
integer How large the receive buffer issubnegotiationBufferMax
integer How large the subnegotiation buffer ishandler
Function listener for the connection
event.Creates a new telnet server.
telnetlib.createConnection(options, handler)
options
Object
host
String Host the socket should connect toport
Integer Port the socket should connect toremoteOptions
Array Option codes we want enabled remotelylocalOptions
Array Option codes we want enabled locallyreceiveBuffermax
integer How large the receive buffer issubnegotiationBufferMax
integer How large the subnegotiation buffer ishandler
Function listener for the connect
event.A factory function which creates a net.Socket
, wraps it in a TelnetSocket
, initiates option negotiation, and returns the TelnetSocket
.
telnetlib.defineOption(name, code[, handler])
name
String The name of the telnet option.code
Integer The telnet option codehandler
TelnetOption Optional class that manages optionRegister an option handler with the library.
telnetlib.TelnetSocket
This class wraps a socket and manages object negotiation.
new telnetlib.TelnetSocket(socket[, options])
socket
net.Socket Socket object to wrapoptions
Object
remoteOptions
Array Option codes we want enabled remotelylocalOptions
Array Option codes we want enabled locallyreceiveBuffermax
integer How large the receive buffer issubnegotiationBufferMax
integer How large the subnegotiation buffer isnegotiated
Emitted when all option negotiations have been settled either through (dis)agreement or timeout.
enable
optionCode
integer telnet option codeat
String value indicating where the option was enabled. Either 'LOCAL'
or 'REMOTE'
Emitted when an option is enabled.
disable
optionCode
integer telnet option codeat
String value indicating where the option was disabled. Either 'LOCAL'
or 'REMOTE'
Emitted when an option is disabled.
TelnetSocket.enableRemote(option[, timeout])
option
- integer telnet option codetimeout
- integer timeout in millisecondsRequest that an option be enabled remotely.
TelnetSocket.disableRemote(option[, timeout])
option
- integer telnet option codetimeout
- integer timeout in millisecondsRequest that an option be disabled remotely.
TelnetSocket.enableLocal(option[, timeout])
option
- integer telnet option codetimeout
- integer timeout in millisecondsRequest that an option be enabled locally.
TelnetSocket.disableLocal(option[, timeout])
option
- integer telnet option codetimeout
- integer timeout in millisecondsRequest that an option be disabled locally.
TelnetSocket.getOption(code)
code
- integer telnet option codeGet the handler for the specified option.
telnetlib.TelnetOption
This is the base class for option handlers.
enabled(at)
at
String value indicating where option was enabled. Either 'LOCAL'
or 'REMOTE'
Called whenever the option is enabled. Intended to be overridden by subclasses.
disabled(at)
at
String value indicating where option was disabled. Either 'LOCAL'
or 'REMOTE'
Called whenever the option is disabled. Intended to be overridden by subclasses.
subnegotiation(buffer)
buffer
Buffer contents of the subnegotiationCalled when a subnegotiation is received for an option. Intended to be overridden by subclasses.
GMCP
telnetlib.TelnetOption
This class handles sending and receiving GMCP message.
gmcp
packageName
String the name of the package the message belongs tomessageName
String the name of the messagedata
String | Number | Boolean | Object | Array The message dataEmitted when a GMCP message is received. packageName
and messageName
are normalized to lower case.
gmcp/<name>
data
String | Number | Boolean | Object | Array The message dataAs above, but instead of having packageName
and messageName
values they are included in the event name.
send(packageName, messageName[, data])
packageName
String the name of the packagemessageName
String the name of the messagedata
String | Number | Boolean | Object | Array The message dataSend a GMCP message.
MCCP
telnetlib.TelnetOption
This class handles MCCP2 compression.
endCompression([callback])
callback
Function optional callbackOnly valid when MCCP is enabled locally. Sends a Z_FINISH
flush and forces MCCP off locally.
NAWS
telnetlib.TelnetOption
This class handles sending and receiving window resize events.
resize
data
Object
width
Integer The width reported by the client.
height
Integer The height reported by the client.Event emitted when a resize subnegotiation is received.
sendResize([width[, height]])
width
Integer The width to send. Default: 80height
Integer The height to send. Default: 24Send a resize subnegotiation.
The main reason to extend this library would be to add additional option handlers. This can be easily done by subclassing TelnetOption
and registering it with the library using telnetlib.defineOption
before creating a server or client. As in:
const telnetlib = require('telnetlib');
const { where } = telnetlib.constants;
const ourOptionCode = 123;
class Something extends telnetlib.TelnetOption {
constructor(socket, code) {
super(socket, ourOptionCode);
}
enabled(at) {
if (at == where.LOCAL) console.log('this option was enabled locally');
}
disabled(at) {
if (at == where.LOCAL) console.log('this option was disabled locally');
}
subnegotiation(buffer) {}
}
telnetlib.defineOption('Something', ourOptionCode, Something);
This is similar to the simple example above, but instead of sending normal text back and forth across the connection, the same thing is done with GMCP messages.
const telnetlib = require('telnetlib');
const { GMCP } = telnetlib.options;
const server = telnetlib.createServer(
{
localOptions: [GMCP]
},
(c) => {
const gmcp = c.getOption(GMCP);
c.on('negotiated', () => {
gmcp.send('herp', 'derp', 42);
});
gmcp.on('gmcp/herp.derp', (data) => {
gmcp.send('herp', 'derp', data);
});
}
);
server.listen(9001);
const telnetlib = require('telnetlib');
const { GMCP } = telnetlib.options;
const client = telnetlib.createConnection(
{
host: '127.0.0.1',
port: 9001,
remoteOptions: [GMCP]
},
() => {
const gmcp = client.getOption(GMCP);
gmcp.on('gmcp/herp.derp', (data) => {
gmcp.send('herp', 'derp', data);
});
}
);
Using the blessed library this example renders a box with in the middle of the terminal. The box will resize to fit in clients that support NAWS.
const blessed = require('blessed');
const telnetlib = require('telnetlib');
const { ECHO, TRANSMIT_BINARY, NAWS, SGA } = telnetlib.options;
const server = telnetlib.createServer(
{
remoteOptions: [NAWS, TRANSMIT_BINARY, SGA],
localOptions: [ECHO, TRANSMIT_BINARY, SGA]
},
(c) => {
let screen;
c.on('negotiated', () => {
screen = blessed.screen({
smartCSR: true,
input: c,
output: c,
height: 80,
width: 24,
terminal: 'xterm',
fullUnicode: true,
cursor: {
artificial: true,
shape: 'line',
blink: true,
color: null
}
});
const box = blessed.box({
parent: screen,
top: 'center',
left: 'center',
width: '50%',
height: '50%',
content: 'Hello World',
border: 'line'
});
screen.render();
});
c.on('end', () => {
if (screen) screen.destroy();
});
}
);
server.listen(9001);