[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