[Asterisk-Dev] Changing Asterisk's module invocation
Juan Jose Comellas
juanjo at comellas.com.ar
Thu Sep 16 08:23:32 MST 2004
Thanks for all your recommendations. The immediate objective of the project
I'm working on is to use Asterisk to replace another product in a telephony
server. The previous version was based on Envox and ran on Windows with a DLL
that acted as a bridge between Envox and the Java code that implemented most
of the functionality for a lot of services (complex conferencing and
voicemail and a lot of additional services not found in Asterisk). We want to
reuse all the code we can from the previous version, so I'm trying to provide
a similar interface to the other system in an Asterisk module.
Initially we planned to use normal dialplans, but we have a highly dynamic
system, which has thousands of extensions and is updated constantly, and
reloading Asterisk's configuration frequently has some problems. In our
tests, reloading the dialplan took about 30 seconds and during that time new
connections failed. That is completely unacceptable for the service we
provide, so we decided to manage our own dialplan and reuse the functionality
of the previous version by writing a module that could act as a bridge
between Asterisk and the previous software (in Java). That seemed to be the
simplest solution because it allowed us to reuse what we already had
developed for the previous version.
When we first studied Asterisk we thought about using the Manager Interface,
but it did not seem stable enough to be able to make thousands of calls all
the time. Has this changed recently?
On Wednesday 15 September 2004 20:38, David Pollak wrote:
> Juan Jose,
>
> You should only have 1 JVM instance. You can put a pointer to your JVM
> instance in a static (I forgot the C name for statics... sorry) variable
> that can be accessed by any caller into your app.
>
> You do a lookup for the "cookie" (the void * that you proposed in your
> suggested change) based on the unique ID of the channel.
>
> My strong recommendation for destroying the cookie when you destroy the
> channel comes from making sure that there's no memory leak in the JVM
> (or more specifically, no reference leak.) The cookie that you're
> storing probably corresponds to a Java Object. That Object is marked as
> referred to by an external JNI program (thus it will not be garbage
> collected from the JVM.) Once the channel in Asterisk is destroyed,
> you'll have to let the JVM know that the corresponding Java Object (and
> its referenced object) can be garbage collected.
>
> With all that being said, I'd recommend against running a JVM in the
> Asterisk process. First, the JVM is not as stable as Asterisk. (As a
> side-note, I'm a huge fan of Java. I was the first technologist to use
> Java in a production system -- WebLogic ran NetGuide Live [the 11th most
> trafficked site on the Internet] back in 1996. I wrote the worlds
> fastest spreadsheet in Java. I think Java and the JVM are the best
> combination for doing non-realtime systems. On the other hand, I'm
> realistic about Java's weaknesses as well.) If the JVM goes down (and
> JVMs go down in production once or twice a month), the Asterisk process
> goes down. That's bad. Second, I don't know if the Sun JVM uses the
> same thread primitives as Asterisk. If it doesn't, there'll be lots of
> weird memory corruption, etc. Third, when the JVM does garbage
> collection, it halts the current thread (and any other thread that's
> doing a memory allocation -- which is all the time in a JVM.) Asterisk
> mixes the media and logic on the same thread. You *have* to respond to
> the media demands every 20ms. If the JVM is doing garbage collection
> that takes more than 20ms, you're going to have bad sound quality.
>
> With all that being said, why not use an external Java process that
> communicates over AGI and/or the Manager API to control the channel?
> What kind of application are you writing?
>
> Thanks,
>
> David
>
> Juan Jose Comellas wrote:
> >But if I do what you propose, each Java module would be created and
> > destroyed when each channel is created and destroyed. I want to have Java
> > modules that last as long as C modules do and that are not tied to
> > specific channels.
> >
> >The problem I'm facing is that I need to map the C callback for each
> >application to multiple Java classes in order to have only one instance of
> >the JVM for all the Java modules. The configuration file would look like
> >this:
> >
> >--- java.conf
> >[commands]
> >JavaTransfer = org.asterisk.JavaTransferModule
> >JavaConference = org.asterisk.JavaConferenceModule
> >JavaDirectory = org.asterisk.JavaDirectoryModule
> >
> >So, whenever the any of the commands is found in the dialplan and Asterisk
> >invokes the C callback for my bridge module I would like to invoke a
> > method of the corresponding Java class.
> >
> >The reason for doing it this way is that I want to be able to dynamically
> > set the Java applications without having to write different C entry
> > points for the different Java Asterisk applications. Do you think this is
> > feasible with the current functionality in Asterisk?
> >
> >BTW, how can I set up some kind of hook to be notified when Asterisk
> > creates and destroys a channel?
> >
> >Thanks for your help.
> >
> >On Tuesday 14 September 2004 19:34, David Pollak wrote:
> >>Juan Jose,
> >>
> >>You don't need to change Asterisk. In your glue layer between SWIG and
> >>Asterisk, you can determine the unique identifier of the channel. Based
> >>on this unique ID, you can look up the void * data structure in your own
> >>store. Put another way, you manage your own cookies and use the
> >>channel's unique ID as the lookup for the cookie. The only additional
> >>bit of work is that you'll have to monitor to see when a channel is
> >>destroyed so you can free the cookie entry for the destroyed channel.
> >>
> >>Depending on exactly what you're using Java for, you might want to take
> >>a look at a patch I made (enclosed) to Asterisk. This patch merges AGI
> >>with the Manager API. It's useful to have a single socket open between
> >>a Java app server and Asterisk and control all the Asterisk channels
> >>through that socket.
> >>
> >>If you've got more questions, please feel free to ping me.
> >>
> >>Thanks,
> >>
> >>David
> >>
> >>Juan Jose Comellas wrote:
> >>>I am writing Java bindings for the Asterisk API using SWIG
> >>>(http://www.swig.org) so that I can create Asterisk modules written in
> >>>Java. The main problem I'm having is that in order to make this process
> >>>efficient I need to have more than one application per module (I load
> >>>only one instance of the JVM). To be able to build a generic solution
> >>>(where I don't have to add one entry point in C per Java application), I
> >>>need to make a slight change to the ast_register_application() function
> >>>and to the code that invokes each application's callback function.
> >>>Currently all application callbacks follow the following prototype:
> >>>
> >>>int (*execute)(struct ast_channel *, void *data);
> >>>
> >>>The problem is that when building Java modules this function acts as a
> >>>bridge to the Java invocation and I need extra data to be able to map
> >>> the call into a Java class/method. To solve this problem I need to make
> >>> the following changes to Asterisk's public interface:
> >>>
> >>>1) Add one argument to the application callback to be able to pass the
> >>>"cookie" that will let me map to the Java class/method:
> >>>
> >>>int (*execute)(struct ast_channel *, void *data, void *cookie);
> >>>
> >>>2) Change the ast_app struct to be able to store the "cookie". With my
> >>>changes it looks like this:
> >>>
> >>>struct ast_app {
> >>>char name[AST_MAX_APP]; /* Name of the application */
> >>>int (*execute)(struct ast_channel *chan, void *data, void *cookie);
> >>>char *synopsis; /* Synopsis text for 'show applications' */
> >>>char *description; /* Description (help text) for 'show application
> >>><name>' */
> >>>void *cookie; /* Data used to map the call when using Java modules */
> >>>struct ast_app *next; /* Next app in list */
> >>>};
> >>>
> >>>3) Change the ast_register_application() function to pass the cookie to
> >>>the ast_app struct:
> >>>
> >>>int ast_register_application(char *app, int (*execute)(struct
> >>> ast_channel *, void *data, void *cookie), char *synopsis, char
> >>> *description, void *cookie);
> >>>
> >>>Do these modifications have any chance of being accepted into Asterisk?
--
Juan Jose Comellas
(juanjo at comellas.com.ar)
More information about the asterisk-dev
mailing list