UNPKG

asterisk-ami-connector

Version:
127 lines (108 loc) 3.94 kB
/** * Created by Alex Voronyansky <belirafon@gmail.com> * Date: 26.04.2016 * Time: 13:47 */ "use strict"; const co = require('co'); const net = require('net'); const AmiConnection = require('./AmiConnection'); const AmiAuthError = require('./errors/AmiAuthError'); const AmiEventsStream = require('asterisk-ami-events-stream'); const amiUtils = require('asterisk-ami-event-utils'); const debugLog = require('debug')('amiConnector'); const errorLog = require('debug')('amiConnector:error'); /** * * @param login * @param secret * @param connectionOptions * @returns {Promise} */ function createAmiConnection(login, secret, connectionOptions){ return new Promise((resolve, reject) => { let amiDataStream = new AmiEventsStream(), authCommand = { Action: 'login', Username: login, Secret: secret, ActionID: `__auth_${Date.now()}__` }, amiSocket = null; debugLog('connecting to asterisk ami...'); amiSocket = net.connect(connectionOptions, () => { debugLog('connection established'); amiSocket.pipe(amiDataStream) .once('error', reject) .once('close', () => reject(new AmiAuthError('ami auth error'))) .on('amiResponse', response => { if(response.ActionID !== authCommand.ActionID){ return; } if(response.Response !== 'Success'){ reject(new AmiAuthError(`AMI message: ${response.Message}`)); return; } debugLog('authontificated successfull'); amiSocket .removeAllListeners('error') .removeAllListeners('close') .unpipe(amiDataStream); amiDataStream .removeAllListeners('error') .removeAllListeners('close') .removeAllListeners('amiResponse'); resolve(new AmiConnection(amiSocket)); debugLog('asterisk\'s ami connection ready to work'); }); debugLog(`authontification [username:${authCommand.Username}]...`); amiSocket.write(amiUtils.fromObject(authCommand)); }) .once('error', reject) .once('close', reject); }); } /** * * @param maxAttemptsCount * @param attemptsDelay * @returns {Function} */ function wrapper(maxAttemptsCount, attemptsDelay){ return function(login, password, options){ return co(function* (){ let currAttemptIndex = 0; while(maxAttemptsCount === null || ++currAttemptIndex <= maxAttemptsCount){ try{ return yield createAmiConnection(login, password, options); }catch (error){ if(error instanceof AmiAuthError) throw error; errorLog(error.message); yield sleep(attemptsDelay); } if(maxAttemptsCount === null){ debugLog(`attempt of reconnecting...`); }else{ debugLog(`attempt [${currAttemptIndex} of ${maxAttemptsCount}] of reconnecting...`); } } throw new Error('Reconnection error after max count attempts.'); }); } } /** * * @param delay * @returns {Promise} */ function sleep(delay){ return new Promise(resolve => setTimeout(resolve, delay)); } module.exports = function(options){ options = Object.assign({ reconnect: false, maxAttemptsCount: null, attemptsDelay: 1000 }, options || {}); return { connect: !options.reconnect ? createAmiConnection : wrapper(options.maxAttemptsCount, options.attemptsDelay) }; };