UNPKG

@qnext/iso-on-tcp

Version:

ISO-on-TCP Protocol implementation

296 lines (273 loc) 8.47 kB
//@ts-check /* Copyright: (c) 2018-2020, ST-One Ltda. GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) */ const { expect } = require('chai'); const ISOOnTCPClient = require('../src/client.js'); const constants = require('../src/constants.json'); const { Duplex } = require('stream'); const makeDuplexPair = require('./duplexPair'); describe('ISO-on-TCP Client', () => { it('should throw without a source stream', () => { //@ts-ignore expect(() => new ISOOnTCPClient()).to.throw(); }); it('should setup a basic communication', (done) => { let opts = { sourceRef: 1, srcTSAP: 0x1000, dstTSAP: 0x2700, }; let stream = new Duplex({ read(size) {}, write(chunk, encoding, cb) { expect(chunk.toString('hex')).to.be.equal( '0300001611e00000000100c0010ac1021000c2022700' ); this.push( Buffer.from('0300001611d00001a0e300c00109c1021000c2022700', 'hex') ); }, }); let client = new ISOOnTCPClient(stream, opts); client.on('connect', () => { expect(client.destinationReference).to.be.equals( 0xa0e3, 'Destination reference does not match' ); expect(client.negotiatedTpduSize).to.be.equals( 512, 'Failed to negotiate tpdu size' ); done(); }); client.on('error', (e) => { throw e; }); client.connect(); }); it('should send data only after connecting', (done) => { let opts = { sourceRef: 1, srcTSAP: 0x1000, dstTSAP: 0x2700, }; let streamState = 1; let stream = new Duplex({ read(size) {}, write(chunk, encoding, cb) { switch (streamState) { case 1: streamState++; expect(chunk.toString('hex')).to.be.equal( '0300001611e00000000100c0010ac1021000c2022700' ); this.push( Buffer.from('0300001611d00001a0e300c00109c1021000c2022700', 'hex') ); break; case 2: streamState++; expect(chunk.toString('hex')).to.be.equal( '0300001902f08032010000040000080000f0000001000101e0' ); this.push( Buffer.from( '0300001b02f080320300000400000800000000f0000001000100f0', 'hex' ) ); break; } cb(); }, }); let client = new ISOOnTCPClient(stream, opts); client.write(Buffer.from('32010000040000080000f0000001000101e0', 'hex')); client.on('connect', () => { expect(client.destinationReference).to.be.equals( 0xa0e3, 'Destination reference does not match' ); expect(client.negotiatedTpduSize).to.be.equals( 512, 'Failed to negotiate tpdu size' ); }); client.on('data', (d) => { expect(d.toString('hex')).to.be.equals( '320300000400000800000000f0000001000100f0' ); done(); }); client.on('error', (e) => { throw e; }); client.connect(); }); it('should group DT telegrams', (done) => { let opts = { sourceRef: 1, srcTSAP: 0x1000, dstTSAP: 0x2700, }; let streamState = 1; let stream = new Duplex({ read(size) {}, write(chunk, encoding, cb) { switch (streamState) { case 1: streamState++; expect(chunk.toString('hex')).to.be.equal( '0300001611e00000000100c0010ac1021000c2022700' ); this.push( Buffer.from('0300001611d00001a0e300c00109c1021000c2022700', 'hex') ); break; case 2: streamState++; expect(chunk.toString('hex')).to.be.equal( '0300001902f08032010000040000080000f0000001000101e0' ); this.push(Buffer.from('0300000702f000', 'hex')); setTimeout( () => this.push( Buffer.from( '0300001b02f080320300000400000800000000f0000001000100f0', 'hex' ) ), 10 ); break; } cb(); }, }); let client = new ISOOnTCPClient(stream, opts); client.write(Buffer.from('32010000040000080000f0000001000101e0', 'hex')); client.on('connect', () => { expect(client.destinationReference).to.be.equals( 0xa0e3, 'Destination reference does not match' ); expect(client.negotiatedTpduSize).to.be.equals( 512, 'Failed to negotiate tpdu size' ); }); client.on('data', (d) => { expect(d.toString('hex')).to.be.equals( '320300000400000800000000f0000001000100f0' ); done(); }); client.on('error', (e) => { throw e; }); client.connect(); }); it('should be able to be a server for itself - uint16 TSAP', (done) => { let opts = { sourceRef: 1, srcTSAP: 0x1000, dstTSAP: 0x2700, }; let testDataClient = Buffer.from('hello server'); let testDataServer = Buffer.from('hello client'); let clientConnected = false; let serverConnected = false; let serverClosed = false; let { clientSide, serverSide } = makeDuplexPair(); let client = new ISOOnTCPClient(clientSide, opts); let server = new ISOOnTCPClient(serverSide); //['connect', 'data', 'close', 'finish', 'end'].forEach(evt => client.on(evt, d => console.log(`CLIENT #${evt}`, d))); //['connect', 'data', 'close', 'finish', 'end'].forEach(evt => server.on(evt, d => console.log(`SERVER #${evt}`, d))); client.on('data', (d) => { expect(d.toString('hex')).to.be.equals(testDataServer.toString('hex')); expect(clientConnected, "client didn't connect").to.be.true; expect(serverConnected, "server didn't connect").to.be.true; client.close(); }); client.on('close', () => { process.nextTick(() => { expect(serverClosed, 'server closed').to.be.false; done(); }); }); client.on('connect', () => { clientConnected = true; client.write(testDataClient); }); client.on('error', (e) => { throw e; }); server.on('data', (d) => { expect(d.toString('hex')).to.be.equals(testDataClient.toString('hex')); server.write(testDataServer); }); server.on('close', () => { serverClosed = true; }); server.on('connect', () => { serverConnected = true; }); server.on('error', (e) => { throw e; }); client.connect(); }); it('should be able to be a server for itself - string TSAP', (done) => { let opts = { sourceRef: 1, srcTSAP: 'abcd1234', dstTSAP: 'efgh5678', }; let testDataClient = Buffer.from('hello server'); let testDataServer = Buffer.from('hello client'); let clientConnected = false; let serverConnected = false; let serverClosed = false; let { clientSide, serverSide } = makeDuplexPair(); let client = new ISOOnTCPClient(clientSide, opts); let server = new ISOOnTCPClient(serverSide); //['connect', 'data', 'close', 'finish', 'end'].forEach(evt => client.on(evt, d => console.log(`CLIENT #${evt}`, d))); //['connect', 'data', 'close', 'finish', 'end'].forEach(evt => server.on(evt, d => console.log(`SERVER #${evt}`, d))); client.on('data', (d) => { expect(d.toString('hex')).to.be.equals(testDataServer.toString('hex')); expect(clientConnected, "client didn't connect").to.be.true; expect(serverConnected, "server didn't connect").to.be.true; client.close(); }); client.on('close', () => { process.nextTick(() => { expect(serverClosed, 'server closed').to.be.false; done(); }); }); client.on('connect', () => { clientConnected = true; client.write(testDataClient); }); client.on('error', (e) => { throw e; }); server.on('data', (d) => { expect(d.toString('hex')).to.be.equals(testDataClient.toString('hex')); server.write(testDataServer); }); server.on('close', () => { serverClosed = true; }); server.on('connect', () => { serverConnected = true; }); server.on('error', (e) => { throw e; }); client.connect(); }); });