[Asterisk-Dev] AGI via Asterisk Manager API
David Pollak
dpp-asterisk at projectsinmotion.com
Wed Mar 16 20:47:05 MST 2005
Folks,
7 months ago, I made some modifications to Asterisk to allow AGI
commands to be passed via the Manager API. The advantage over AGI and
FastAGI is the reduced number of sockets to monitor on the controlling
machine. If there are 200 channels open on 10 machines that are all
being managed from a single control machine, that's 2,000 open sockets
(a lot for a kernel to handle) and lots of threads listening to those
open sockets. By sending all the commands (AGI and Manager) through a
single socket, there are fewer open sockets and a single place to manage
all the interactions with Asterisk.
I've had systems in production for the last 7 months running the MAGI
(Manager AGI) code. There hasn't been a single failure or problem.
I've got Java code running on my application server managing the
Asterisk instances. All works like a charm.
I've had a couple of requests for the code. I figure I'll make it
available to everyone. Maybe if enough people use it, we'll be able to
get the mods into the main Asterisk distribution.
You can download a tarball of Asterisk (it's the source from about a
week ago with the MAGI mods) plus Java code that allows you to control
Asterisk. In addition, I'm enclosing a sample Java class that answers
the call and plays "12345" to the caller.
You can download the tarball from:
http://www.projectsinmotion.com/ast_with_magi.tgz
To access, MAGI, put the following in your dialplan:
exten => 4157380662,1,MAGI(DOSTUFF|${EXTEN})
The code that follows is example Java code.
I hope folks out there find the code valuable. If you've got any
questions, please let me know. If you've got enhancements or
suggestions for improvement, I'd love to see them.
Thanks,
David
*Place this method someplace so that the connection to Asterisk gets
initialized and the right factories vend the right instances. I have
this code executed as part of a class static {} in a class that's loaded
when my app server starts.*
private static void startAsterisk() {
// fire off the Asterisk manager
AstManager.setChannelFactory(new AstManager.ICreateChannel() {
public AstChannel create(String chanNum, String chanId,
AstConnection conn) {
return new MyAstChannel(chanNum, chanId,
(MyAstConnection) conn);
}
});
AstManager.setConnectionFactory(new AstManager.ICreateConnection() {
public AstConnection create(String host, int port,
AstConnection.IUserNamePassword pwd) throws
IOException {
return new MyAstConnection(host, port, pwd);
}
});
Thread t = new Thread(new Runnable() {
public void run() {
AstManager man = new AstManager();
man.start(new AstManager.IConnected() {
public void connectedToAsterisk(AstConnection conn) {
System.out.println("Dude... we're connected");
}
public void failedToConnect() {
run();
}
}, "localhost", 5038, new
AstConnection.IUserNamePassword() {
public String getUsername() {
return "foo";
}
public String getPassword() {
return "bar";
}
});
}
});
t.start();
}
*MyAstChannel: This class handles the current channel. The key thing is
it subclasses runNAExec which is called when the MAGI command is called
in Asterisk on the given channel. It answers the line, waits 2 seconds,
and then runs "SAY DIGITS" with 12345.*
/*
* Created on Aug 11, 2004
*
* (c) 2004-2005 David Pollak
*/
package net.maxvox.mvasterisk;
import java.net.URLDecoder;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import net.maxvox.asterisk.AstChannel;
import net.maxvox.asterisk.INameValuePair;
import net.maxvox.asterisk.IServerCommand;
import net.maxvox.asterisk.IVRUtils;
import net.maxvox.asterisk.NameValuePairImpl;
import net.maxvox.asterisk.ServerCommandImpl;
/**
* @author dpp
*
* Represents a channel in the Asterisk
*/
public class MyAstChannel extends AstChannel {
public MyAstChannel(String name, String uniqueId, MyAstConnection
conn) {
super(name, uniqueId, conn);
}
protected void runNAExec(HashMap<String, String> params,
HashMap<String, String> results) {
super.runNAExec(params, results);
this.answer(new IServerCommand.ICommandStringCallback() {
public void complete(int code, IServerCommand command, String
result) {
try {
Thread.sleep(2000);
} catch (InterruptedException ie) {
// ignore
}
sayDigits("12345");
}
});
}
}
*MyAstConnection: There's 1 instance of this class per Asterisk server
connection. No real reason to subclass it, but I did anyway... :-)*
/*
* Created on Aug 9, 2004
*
* (c) 2004-2005 David Pollak
*/
package net.maxvox.mvasterisk;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
import org.jendo.base.SmartBaseObject;
import org.jendo.base.SmartException;
import org.jendo.util.Diag;
import net.maxvox.asterisk.AstChannel;
import net.maxvox.asterisk.AstConnection;
import net.maxvox.asterisk.INameValuePair;
import net.maxvox.asterisk.IServerCommand;
import net.maxvox.asterisk.NameValuePairImpl;
import net.maxvox.asterisk.SelectChannelMonitor;
import net.maxvox.asterisk.ServerCommandImpl;
import net.maxvox.asterisk.AstConnection.IUserNamePassword;
/**
* @author dpp
*
* Connection to an Asterisk Server's Manager API
*/
public class MYAstConnection extends AstConnection {
public MyAstConnection(String host, int port, IUserNamePassword pwd)
throws IOException {
super(host, port, pwd);
}
public static MyAstConnection instance() {
AstConnection conn = AstConnection.instance();
if (conn != null && conn instanceof MyAstConnection) {
return (MyAstConnection) conn;
}
return null;
}
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.digium.com/pipermail/asterisk-dev/attachments/20050316/bc02c040/attachment.htm
More information about the asterisk-dev
mailing list