Skip to content

Commit

Permalink
Add nextData() method. Update tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
kshetline committed Jan 2, 2022
1 parent 51a6ebc commit ce2bb8e
Show file tree
Hide file tree
Showing 18 changed files with 167 additions and 95 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
node_modules/
lib-cov/
lib/
*.log
*.swp
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"scripts": {
"prepack": "tsc",
"test": "nyc --reporter=html mocha --timeout 3000 --require ts-node/register test/**/*.ts",
"coveralls": "tsc && nyc report --reporter=text-lcov | coveralls",
"coveralls": "tsc && (nyc report --reporter=text-lcov | coveralls)",
"lint": "eslint 'src/**/*.ts' 'test/**/*.ts'"
},
"dependencies": {
Expand Down
38 changes: 37 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,48 @@ function stringToRegex(opts: any): void {
}

export class Telnet extends events.EventEmitter {
private dataResolver: any
private inputBuffer: string = ''
private loginPromptReceived = false
private opts = Object.assign({}, defaultOptions)
private pendingData: (string | null)[] = []
private response: string[] = undefined
private socket: Socket
private state: TelnetState = null

constructor() {
super()

this.on('data', data => this.pushNextData(data))
this.on('end', () => this.pushNextData(null))
}

private pushNextData(data: any): void {
if (data instanceof Buffer)
data = data.toString(this.opts.encoding)
else if (data != null)
data = data.toString()

const chunks = data ? data.split(/(?<=\r\r\n|\r?\n)/) : [data]

if (this.dataResolver) {
this.dataResolver(chunks[0])
this.dataResolver = undefined
}
else
this.pendingData.push(chunks[0])

if (chunks.length > 1)
this.pendingData.push(...chunks.slice(1))
}

async nextData(): Promise<string | null> {
if (this.pendingData.length > 0)
return this.pendingData.splice(0, 1)[0]

return new Promise<string>(resolve => this.dataResolver = resolve)
}

connect(opts: any): Promise<void> {
return new Promise<void>((resolve, reject) => {
let connectionPending = true
Expand Down Expand Up @@ -152,7 +187,7 @@ export class Telnet extends events.EventEmitter {
})
}

this.socket.setMaxListeners(20)
this.socket.setMaxListeners(Math.max(15, this.socket.getMaxListeners()))

this.socket.setTimeout(this.opts.timeout, () => {
if (connectionPending) {
Expand Down Expand Up @@ -383,6 +418,7 @@ export class Telnet extends events.EventEmitter {
return new Promise(resolve => {
let timer = setTimeout(() => {
timer = undefined
this.emit('end')
resolve()
}, this.opts.maxEndWait)

Expand Down
2 changes: 1 addition & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function search(str: string, pattern: RegExp | string): number {
export class Stream extends Duplex {
constructor(private source: Socket, options?: DuplexOptions) {
super(options)
this.source.on('data', (data) => this.push(data))
this.source.on('data', data => this.push(data))
}

_write(data: Buffer | string, encoding?: BufferEncoding, callback?: Callback<void>): void {
Expand Down
6 changes: 3 additions & 3 deletions test/001_generic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ let server: Server
let callbackCount: number

describe('generic', () => {
before((done) => {
before(done => {
connection = new Telnet()
callbackCount = 0
server = createServer(() => callbackCount++)
server.listen(2323, done)
})

after((done) => server.close(done))
after(done => server.close(done))

it('connect', (done) => {
it('connect', done => {
connection.connect({
host: '127.0.0.1',
port: 2323 // not using 23, as that one could require sudo
Expand Down
16 changes: 8 additions & 8 deletions test/002_busybox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { createServer, Server, Socket } from 'net'
let server: Server

describe('busybox', () => {
before((done) => {
before(done => {
server = createServer((c: Socket) => {
c.write(Buffer.from('BusyBox v1.19.2 () built-in shell (ash)\n'
+ "Enter 'help' for a list of built-in commands.\n\n/ # ", 'ascii'))
Expand All @@ -20,9 +20,9 @@ describe('busybox', () => {
server.listen(2323, done)
})

after((done) => server.close(done))
after(done => server.close(done))

it('exec_string_shell_prompt', (done) => {
it('exec_string_shell_prompt', done => {
const connection = new Telnet()
const params = {
host: '127.0.0.1',
Expand All @@ -31,8 +31,8 @@ describe('busybox', () => {
timeout: 1500
}

connection.on('ready', function () {
connection.exec('uptime', function (_err, resp) {
connection.on('ready', () => {
connection.exec('uptime', (_err, resp) => {
connection.end().finally()

expect(resp).to.equal('23:14 up 1 day, 21:50, 6 users, load averages: 1.41 1.43 1.41\n')
Expand All @@ -43,7 +43,7 @@ describe('busybox', () => {
connection.connect(params).finally()
})

it('exec_regex_shell_prompt', (done) => {
it('exec_regex_shell_prompt', done => {
const connection = new Telnet()
const params = {
host: '127.0.0.1',
Expand All @@ -52,8 +52,8 @@ describe('busybox', () => {
timeout: 1500
}

connection.on('ready', function () {
connection.exec('uptime', function (_err, resp) {
connection.on('ready', () => {
connection.exec('uptime', (_err, resp) => {
connection.end().finally()

expect(resp).to.equal('23:14 up 1 day, 21:50, 6 users, load averages: 1.41 1.43 1.41\n')
Expand Down
8 changes: 4 additions & 4 deletions test/003_server_push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { createServer, Server, Socket } from 'net'
let server: Server

describe('server_push', () => {
before((done) => {
before(done => {
server = createServer((c: Socket) => {
c.write(Buffer.from('BusyBox v1.19.2 () built-in shell (ash)\n'
+ "Enter 'help' for a list of built-in commands.\n\n/ # ", 'ascii'))
Expand All @@ -18,9 +18,9 @@ describe('server_push', () => {
server.listen(2323, done)
})

after((done) => server.close(done))
after(done => server.close(done))

it('receive_pushed_data', (done) => {
it('receive_pushed_data', done => {
const connection = new Telnet()
const params = {
host: '127.0.0.1',
Expand All @@ -30,7 +30,7 @@ describe('server_push', () => {
newlineReplace: '\n'
}

connection.on('data', function (data) {
connection.on('data', data => {
connection.end().finally()

expect(data.toString()).to.equal('Hello,\nclient!')
Expand Down
22 changes: 11 additions & 11 deletions test/004_negotiation_optional.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { createServer, Server, Socket } from 'net'
let server: Server

describe('negotiation_optional', () => {
before((done) => {
before(done => {
server = createServer((c: Socket) => {
c.on('data', () => {
c.write(Buffer.from('Hello, user.\n'))
Expand All @@ -15,21 +15,21 @@ describe('negotiation_optional', () => {
server.listen(2323, done)
})

after((done) => server.close(done))
after(done => server.close(done))

it('send_data', (done) => {
it('send_data', done => {
const connection = new Telnet()
const params = {
host: '127.0.0.1',
port: 2323,
negotiationMandatory: false
}

connection.on('connect', function () {
connection.on('connect', () => {
connection.send('Hello, server.', {
ors: '\r\n',
waitFor: '\n'
}, function (_error, data) {
}, (_error, data) => {
expect(data?.toString()).to.equal('Hello, user.\n')
connection.end().finally()
done()
Expand All @@ -39,7 +39,7 @@ describe('negotiation_optional', () => {
connection.connect(params).finally()
})

it('send_data_without_options', (done) => {
it('send_data_without_options', done => {
const connection = new Telnet()
const params = {
host: '127.0.0.1',
Expand All @@ -48,8 +48,8 @@ describe('negotiation_optional', () => {
sendTimeout: 100
}

connection.on('connect', function () {
connection.send('Hello, server.', function (_error, data) {
connection.on('connect', () => {
connection.send('Hello, server.', (_error, data) => {
expect(data?.toString()).to.equal('Hello, user.\n')
connection.end().finally()
done()
Expand All @@ -59,7 +59,7 @@ describe('negotiation_optional', () => {
connection.connect(params).finally()
})

it('send_data_without_options_promise', (done) => {
it('send_data_without_options_promise', done => {
const connection = new Telnet()
const params = {
host: '127.0.0.1',
Expand All @@ -68,8 +68,8 @@ describe('negotiation_optional', () => {
sendTimeout: 100
}

connection.connect(params).then(function () {
connection.send('Hello, server.').then(function (data) {
connection.connect(params).then(() => {
connection.send('Hello, server.').then(data => {
expect(data?.toString()).to.equal('Hello, user.\n')
connection.end().finally()
done()
Expand Down
18 changes: 9 additions & 9 deletions test/005_login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import { createServer, Server, Socket } from 'net'
let server: Server

describe('login', () => {
before((done) => {
before(done => {
server = createServer((c: Socket) => {
let logged_in = false

c.write(Buffer.from('Enter your username:\n\nUserName:', 'ascii'))

c.on('data', (data) => {
c.on('data', data => {
if (!logged_in) {
if (data.toString().replace(/\n$/, '') !== 'andy') {
c.write(Buffer.from('Invalid username', 'ascii'))
Expand All @@ -30,9 +30,9 @@ describe('login', () => {
server.listen(2323, done)
})

after((done) => server.close(done))
after(done => server.close(done))

it('ok', (done) => {
it('ok', done => {
const connection = new Telnet()
const params = {
host: '127.0.0.1',
Expand All @@ -44,8 +44,8 @@ describe('login', () => {
timeout: 1500
}

connection.on('ready', function () {
connection.exec('uptime', function (_err, resp) {
connection.on('ready', () => {
connection.exec('uptime', (_err, resp) => {
connection.end().finally()

expect(resp).to.equal('23:14 up 1 day, 21:50, 6 users, load averages: 1.41 1.43 1.41\n')
Expand All @@ -56,7 +56,7 @@ describe('login', () => {
connection.connect(params).finally()
})

it('fail', (done) => {
it('fail', done => {
const connection = new Telnet()
const params = {
host: '127.0.0.1',
Expand All @@ -68,8 +68,8 @@ describe('login', () => {
timeout: 1500
}

connection.on('ready', function () {
connection.exec('uptime', function (_err, resp) {
connection.on('ready', () => {
connection.exec('uptime', (_err, resp) => {
connection.end().finally()

expect(resp).to.equal('23:14 up 1 day, 21:50, 6 users, load averages: 1.41 1.43 1.41\n')
Expand Down
14 changes: 6 additions & 8 deletions test/006_stress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,22 @@ let server: any
let interval: any = null

describe('stress', () => {
before((done) => {
before(done => {
server = telnet_server.createServer((c: any) => {
c.write(Buffer.from('BusyBox v1.19.2 () built-in shell (ash)\n'
+ "Enter 'help' for a list of built-in commands.\n\n/ # ", 'ascii'))

c.on('data', () => {
interval = setInterval(function () {
c.write(Buffer.alloc(100000, '23r23g32g2g3g'))
}, 1)
interval = setInterval(() => c.write(Buffer.alloc(100000, '23r23g32g2g3g')), 1)
})
})

server.listen(2323, done)
})

after((done) => server.close(done))
after(done => server.close(done))

it('buffer_exceeded', (done) => {
it('buffer_exceeded', done => {
const connection = new Telnet()
const params = {
host: '127.0.0.1',
Expand All @@ -35,8 +33,8 @@ describe('stress', () => {
maxEndWait: 300
}

connection.on('ready', function () {
connection.exec('tailme', function (_error, resp) {
connection.on('ready', () => {
connection.exec('tailme', (_error, resp) => {
clearInterval(interval)
connection.end().finally()

Expand Down
10 changes: 5 additions & 5 deletions test/007_streams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import telnet_server from 'telnet'
let server: any

describe('streams', () => {
before((done) => {
before(done => {
server = telnet_server.createServer((c: any) => {
c.write(Buffer.from('BusyBox v1.19.2 () built-in shell (ash)\n'
+ "Enter 'help' for a list of built-in commands.\n\n/ # ", 'ascii'))
Expand All @@ -27,9 +27,9 @@ describe('streams', () => {
server.listen(2323, done)
})

after((done) => server.close(done))
after(done => server.close(done))

it('shell', (done) => {
it('shell', done => {
const connection = new Telnet()
const params = {
host: '127.0.0.1',
Expand All @@ -38,8 +38,8 @@ describe('streams', () => {
timeout: 1500
}

connection.on('ready', function () {
connection.shell(function (error, stream) {
connection.on('ready', () => {
connection.shell((error, stream) => {
let buffered = ''
const expected = '23:14 up 1 day, 21:50, 6 users, load averages: 1.41 1.43 1.41\r\n/ # /dev/disk1 112Gi 87Gi 25Gi 78% 1913034 4293054245 0% /\r\n/ # '
const cb = (data: any): string => buffered += data.toString()
Expand Down

0 comments on commit ce2bb8e

Please sign in to comment.