telnetlib
telnetlib copied to clipboard
A simple Node.js telnet server/client library.
telnetlib
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.
Simple Example
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.
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);
Client
const telnetlib = require('telnetlib');
const client = telnetlib.createConnection(
{
host: '127.0.0.1',
port: 9001
},
() => {
client.on('data', (data) => {
client.write(data);
});
}
);
Features
- RFC1143 option negotiation
- Telnet option handlers for:
Reference
telnetlib.createServer(options, handler)
optionsObjectremoteOptionsArray Option codes we want enabled remotelylocalOptionsArray Option codes we want enabled locallyreceiveBuffermaxinteger How large the receive buffer issubnegotiationBufferMaxinteger How large the subnegotiation buffer is
handlerFunction listener for theconnectionevent.
Creates a new telnet server.
telnetlib.createConnection(options, handler)
optionsObjecthostString Host the socket should connect toportInteger Port the socket should connect toremoteOptionsArray Option codes we want enabled remotelylocalOptionsArray Option codes we want enabled locallyreceiveBuffermaxinteger How large the receive buffer issubnegotiationBufferMaxinteger How large the subnegotiation buffer is
handlerFunction listener for theconnectevent.
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])
nameString The name of the telnet option.codeInteger The telnet option codehandlerTelnetOption Optional class that manages option
Register an option handler with the library.
Class: telnetlib.TelnetSocket
- Extends: Stream.Stream
This class wraps a socket and manages object negotiation.
new telnetlib.TelnetSocket(socket[, options])
socketnet.Socket Socket object to wrapoptionsObjectremoteOptionsArray Option codes we want enabled remotelylocalOptionsArray Option codes we want enabled locallyreceiveBuffermaxinteger How large the receive buffer issubnegotiationBufferMaxinteger How large the subnegotiation buffer is
Event: negotiated
Emitted when all option negotiations have been settled either through (dis)agreement or timeout.
Event: enable
optionCodeinteger telnet option codeatString value indicating where the option was enabled. Either'LOCAL'or'REMOTE'
Emitted when an option is enabled.
Event: disable
optionCodeinteger telnet option codeatString 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 milliseconds- Returns: Promise
Request that an option be enabled remotely.
TelnetSocket.disableRemote(option[, timeout])
option- integer telnet option codetimeout- integer timeout in milliseconds- Returns: Promise
Request that an option be disabled remotely.
TelnetSocket.enableLocal(option[, timeout])
option- integer telnet option codetimeout- integer timeout in milliseconds- Returns: Promise
Request that an option be enabled locally.
TelnetSocket.disableLocal(option[, timeout])
option- integer telnet option codetimeout- integer timeout in milliseconds- Returns: Promise
Request that an option be disabled locally.
TelnetSocket.getOption(code)
code- integer telnet option code- Returns: TelnetOption
Get the handler for the specified option.
Class: telnetlib.TelnetOption
This is the base class for option handlers.
enabled(at)
atString value indicating where option was enabled. Either'LOCAL'or'REMOTE'
Called whenever the option is enabled. Intended to be overridden by subclasses.
disabled(at)
atString value indicating where option was disabled. Either'LOCAL'or'REMOTE'
Called whenever the option is disabled. Intended to be overridden by subclasses.
subnegotiation(buffer)
bufferBuffer contents of the subnegotiation
Called when a subnegotiation is received for an option. Intended to be overridden by subclasses.
Class: GMCP
- Extends:
telnetlib.TelnetOption
This class handles sending and receiving GMCP message.
Event: gmcp
packageNameString the name of the package the message belongs tomessageNameString the name of the messagedataString | Number | Boolean | Object | Array The message data
Emitted when a GMCP message is received. packageName and messageName are normalized to lower case.
Event: gmcp/<name>
dataString | Number | Boolean | Object | Array The message data
As above, but instead of having packageName and messageName values they are included in the event name.
send(packageName, messageName[, data])
packageNameString the name of the packagemessageNameString the name of the messagedataString | Number | Boolean | Object | Array The message data
Send a GMCP message.
Class: MCCP
- Extends:
telnetlib.TelnetOption
This class handles MCCP2 compression.
endCompression([callback])
callbackFunction optional callback
Only valid when MCCP is enabled locally. Sends a Z_FINISH flush and forces MCCP off locally.
Class: NAWS
- Extends:
telnetlib.TelnetOption
This class handles sending and receiving window resize events.
Event: resize
dataObjectwidthInteger The width reported by the client.heightInteger The height reported by the client.
Event emitted when a resize subnegotiation is received.
sendResize([width[, height]])
widthInteger The width to send. Default: 80heightInteger The height to send. Default: 24
Send a resize subnegotiation.
Extending
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);
Advanced Examples
GMCP
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.
Server
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);
Client
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);
});
}
);
Fancy Interfaces
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);