UNPKG

asterisk-ami-events-stream

Version:
195 lines (166 loc) 4.32 kB
/** * Developer: Alex Voronyansky <belirafon@gmail.com> * Date: 14.11.2014 * Time: 12:28 */ "use strict"; const Transform = require('stream').Transform; const eventUtils = require('asterisk-ami-event-utils'); const COMMAND_END = '--END COMMAND--'; /** * Ami Event Emitter */ class AmiEventsStream extends Transform{ constructor(){ super(); Object.assign(this, { _parser: eventUtils.toObject, _rawData: [], _sawFirstCrLf: false, _buffer: null, _lastAmiEvent: null, _lastAmiResponse: null, _lastAmiAction: null, _isEmitted: true }); } /** * * @returns {*} */ getLastEvent(){ return this._lastAmiEvent; } /** * * @returns {*} */ get lastEvent(){ return this.getLastEvent(); } /** * * @returns {null} */ getLastResponse(){ return this._lastAmiResponse; } /** * * @returns {null} */ get lastResponse(){ return this.getLastResponse(); } /** * * @returns {*} */ getLastAction(){ return this._lastAmiAction; } /** * * @returns {null} */ get lastAction(){ return this.getLastAction(); } /** * * @param chunk * @param encoding * @param done * @private */ _transform(chunk, encoding, done){ let chunkSlice = chunk; if(this._rawData.length){ chunkSlice = Buffer.concat(this._rawData.concat([chunkSlice])); this._rawData = []; } let parseGen = this._parse(chunkSlice); while(chunkSlice){ chunkSlice = parseGen.next(chunkSlice).value; } done(); } /** * * @param chunk * @private */ _analyzeSimple(chunk){ let chunkLength = chunk.length; for (let i = 0; i < chunkLength; i++) { if (chunk[i] === 13 && i + 1 < chunkLength && chunk[i + 1] === 10){ i++; if (this._sawFirstCrLf){ this._buffer = chunk.slice(0, i); this._emission(this._buffer); this._sawFirstCrLf = false; return chunk.slice(i); }else{ this._sawFirstCrLf = true; } }else{ this._sawFirstCrLf = false; } } this._rawData.push(chunk.slice(0)); return null; } /** * * @param chunk * @private */ _analyzeExtend(chunk){ let chunkStr = eventUtils.toString(chunk), indexOfEnd = chunkStr.indexOf(COMMAND_END); if(chunkStr === ''){ return null; } if(~indexOfEnd){ this._emission(chunk.slice(0, indexOfEnd + COMMAND_END.length + 1)); return chunk.slice(indexOfEnd + COMMAND_END.length + 1); } this._rawData.push(chunk); return null; } /** * * @returns {null} * @private */ * _parse(chunk){ let chunkSlice = chunk; while(chunkSlice){ chunkSlice = this._isEmitted && !/^Response:\sFollows/i.test(eventUtils.toString(chunkSlice)) ? yield this._analyzeSimple(chunkSlice) : yield this._analyzeExtend(chunkSlice); } return null; } /** * * @param eventBuffer * @private */ _emission(eventBuffer){ let eventStr = eventUtils.toString(eventBuffer); if(eventStr.length){ if(/^Event/i.test(eventStr)){ this._lastAmiEvent = this._parser(eventBuffer); this.emit('amiEvent', this._lastAmiEvent); }else if(/^Action/i.test(eventStr)){ this._lastAmiAction = this._parser(eventBuffer); this.emit('amiAction', this._lastAmiAction); }else{ this._lastAmiResponse = this._parser(eventBuffer); this.emit('amiResponse', this._lastAmiResponse); } this.push(eventUtils.fromString(eventStr)); } this._isEmitted = true; return this; } } module.exports = AmiEventsStream;