ARI Nodejs Bridge-dial
extensions.conf
exten => _1777,1,NoOp() same => n,Stasis(bridge-dial) same => n,Hangup()
bridge-dial.js
/*jshint node:true*/ 'use strict'; var ari = require('ari-client'); var util = require('util'); // ensure endpoint was passed in to script if (!process.argv[2]) { console.error('usage: node bridge-dial.js endpoint'); process.exit(1); } ari.connect('http://localhost:8088', 'ari_user', 'ari_password', clientLoaded); // handler for client being loaded function clientLoaded (err, client) { if (err) { throw err; } // handler for StasisStart event function stasisStart(event, channel) { // ensure the channel is not a dialed channel var dialed = event.args[0] === 'dialed'; if (!dialed) { channel.answer(function(err) { if (err) { throw err; } console.log('Channel %s has entered our application', channel.name); var playback = client.Playback(); channel.play({media: 'sound:pls-wait-connect-call'}, playback, function(err, playback) { if (err) { throw err; } }); originate(channel); }); } } function originate(channel) { var dialed = client.Channel(); channel.on('StasisEnd', function(event, channel) { hangupDialed(channel, dialed); }); dialed.on('ChannelDestroyed', function(event, dialed) { hangupOriginal(channel, dialed); }); dialed.on('StasisStart', function(event, dialed) { joinMixingBridge(channel, dialed); }); dialed.originate( {endpoint: process.argv[2], app: 'bridge-dial', appArgs: 'dialed'}, function(err, dialed) { if (err) { throw err; } }); } // handler for original channel hanging up so we can gracefully hangup the // other end function hangupDialed(channel, dialed) { console.log( 'Channel %s left our application, hanging up dialed channel %s', channel.name, dialed.name); // hangup the other end dialed.hangup(function(err) { // ignore error since dialed channel could have hung up, causing the // original channel to exit Stasis }); } // handler for the dialed channel hanging up so we can gracefully hangup the // other end function hangupOriginal(channel, dialed) { console.log('Dialed channel %s has been hung up, hanging up channel %s', dialed.name, channel.name); // hangup the other end channel.hangup(function(err) { // ignore error since original channel could have hung up, causing the // dialed channel to exit Stasis }); } // handler for dialed channel entering Stasis function joinMixingBridge(channel, dialed) { var bridge = client.Bridge(); dialed.on('StasisEnd', function(event, dialed) { dialedExit(dialed, bridge); }); dialed.answer(function(err) { if (err) { throw err; } }); bridge.create({type: 'mixing'}, function(err, bridge) { if (err) { throw err; } console.log('Created bridge %s', bridge.id); addChannelsToBridge(channel, dialed, bridge); }); } // handler for the dialed channel leaving Stasis function dialedExit(dialed, bridge) { console.log( 'Dialed channel %s has left our application, destroying bridge %s', dialed.name, bridge.id); bridge.destroy(function(err) { if (err) { throw err; } }); } // handler for new mixing bridge ready for channels to be added to it function addChannelsToBridge(channel, dialed, bridge) { console.log('Adding channel %s and dialed channel %s to bridge %s', channel.name, dialed.name, bridge.id); bridge.addChannel({channel: [channel.id, dialed.id]}, function(err) { if (err) { throw err; } }); } client.on('StasisStart', stasisStart); client.start('bridge-dial'); }
# node bridge-dial.js Local/1777@from-internal
1777 - queue
Call 1777.
]# node bridge-dial.js Local/1777@from-internal Channel SIP/nec-00001021 has entered our application Created bridge c4d94ba1-a443-42f8-9c93-897f0e6f8373 Adding channel SIP/nec-00001021 and dialed channel Local/1777@from-internal-00000018;1 to bridge c4d94ba1-a443-42f8-9c93-897f0e6f8373
cli
-- Executing [1777@from-nec:1] Goto("SIP/nec-0000102a", "from-test,1777,1") in new stack -- Goto (from-test,1777,1) -- Executing [1777@from-test:1] NoOp("SIP/nec-0000102a", "") in new stack -- Executing [1777@from-test:2] Stasis("SIP/nec-0000102a", "bridge-dial") in new stack