Friday, October 22, 2010

Do admins and savvy programmers not remember how to use the shell?

I stumbled upon this blog page when googling info on how to use meld as a git diff tool.


In short he says you do this if you want to use meld as your diff tool for git:

My response: are you kidding me? Did you never think, "Hmm, I wonder if the shell I use every day for executing commands would be good for..." wait for it, "Executing a command!".


Maybe this is better instead of writing a whole python script to swap command line arguments around:

If you are using git I'm assuming you are a developer or an administrator on some level. And, if you are using meld I'm also going to assume that using a variant of UNIX; which means, that the first and most powerful tool you have at your disposal is your shell. So really guys, stop thinking that you absolutely must use an interpreted scripting language for everything and just start thinking. Because honestly if I put this on a qualification test to see if I would hire you and you used a python script to modify the argument order of a system call: I wouldn't hire you.

Thursday, October 21, 2010

Capturing stdio for a (AGI) Perl process.

I found myself debugging a weird issue the other day with an AGI script that caused me to believe Asterisk::AGI was being confused (as in not doing it properly) about blocking on STDIN for the responses to "GET DATA" requests. Which in turn reminded me that I needed to start capturing a large set of AGI protocol data to write tests around once I have a functioning version of the "Asterisk::MAGI" package I intend on starting soon.

Now multiplexing the input and output of a FileHandle in Perl isn't a difficult thing to accomplish when you have complete control of the FileHandle you want to multiplex. This however is not the case in some (maybe a lot) of Perl packages. They like to do evil things like interacting directly and statically to STDIN, STDOUT, STDERR. Sometimes they even give you the glimmer of hope by allowing you to pass a FileHandle to the constructor or a method but almost willfully ignore the idea of persisting any FileHandle you would like to operate on; spaghetti monster forbid you want to use an "old school" Perl package with a Socket or an IO::Handle object (in memory FileHandles for testing anyone?).

At first when trying to tackle this problem I fooled around with manipulating IO layers using PerlIO (which is neat in it's own right) but found that marshaling read data from an input FileHandle to write's on another FileHandle a bit tricky. It seems that things like the multplexing PerlIO utility layer "tee" worked well on FileHandles being written to (STDOUT) but not for reads. Then, I started hacking around this by trying to insert a "filter" CODE reference hook as a layer for my input FileHandle using PerlIO::code - but this seemed kludgey and a lot of code for a seemingly simple task.

Frustrated and suffering my lack of knowledge regarding PerlIO in general I turned to IRC at which point Matt Trout gave me a perfectly simple and elegant solution to my problem: strace

Why bother with a whole slew of code to do "magic" with FileHandles when I could just trace the system calls for the process in question and capture read and write calls to the file descriptors in question.

The result was this little snippet that I modified from his example:



Which will take input like this:



And gives you this:



Since the whole point of this little exercise was to allow me to capture a lot of IO data between Asterisk and a   Perl AGI script I decided that a system() call to strace would be good as calling strace from a dialplan is a bit of a pain:



Just do the above in a BEGIN block and you are set as the -s flag tells strace to keep a large string buffer and the -ff option tells strace to name it's -o output file by pid.

Tuesday, October 5, 2010

Asterisk::AGI

I have found Asterisk::AGI to be the standard tool that most programmers seem to reach for when developing simple AGI applications (at least in Perl) for Asterisk. Such as grabbing a bit of digits entered info and forwarding it onto a web service.

I have my own reservations regarding Asterisk::AGI all the way from it's camel case method names to it's stubborn inflexibility and so on and so forth. I plan to create a new AGI API using Moose and in the process separate the high level application framework elements away from an AGI "session" and the underlying transport layer (fastagi, vs plain ol' system() agi). Hopefully, the result will be a nice framework that developers can extend to present a business specific API for their Asterisk interaction needs.

Here is a bit of code I seem to write a lot:


The implementation of SCALAR ref and CODE ref callbacks were a convention of the specific code-base I was having to "fix". As you can see though, this does the basic fetching of information from an Asterisk daemon while returning a boolean value allowing us to easily loop around it. With a simple routine like this:


And as a result a sample agi script using this for a prompt would go something like this:


Now this is fine for simple bit of IVR logic - but something much larger must be developed in the same way you would develop a larger application; This is something I think Asterisk::AGI lacks but Moose has in spades.

Maybe something more like this (I'm thinking about calling my currently unwritten AGI API Asterisk::MGI)?


This may seem to be a long winded way of accomplishing such a simple task (and admittedly the interface was mocked up off the top of my head) but I think the real power is in the possible use and extension of different transport layers that interact with io in different ways via using a response and request model.

Danga socket anyone?


Of course these are some ruff ideas - I will be sorting out the initial interface soon.