mod_perl is supported as of RC4.
Keep in mind that if you just want to execute perl scripts (or talk to FreeSWITCH using sockets through perl) you do not need mod_perl. Generally the only time you will need mod_perl support is if you want to interact with a live session from a script executed by FreeSWITCH (see examples below). For more details on using Perl without mod_perl see the Perl page.
First beware that for mod_perl support you must have perl compiled with threads/multiplicity (generally once you compile for threads this is enabled). If you are not sure if you have perl compiled with multiplicity (the FreeSWITCH install will _not_ check this for you) or if you are looking for tips on recompiling perl with this support please see the section on the perl multiplicity requirement at the end of this page.
Once you have multiplicity support working you can continue:
- Uncomment the mod_perl line in modules.conf in the build root of FreeSWITCH
- (re)compile freeswitch
- issue "make mod_perl-install" from the shell
- Uncomment the mod_perl load line in modules.conf.xml
- Mod perl will now load and work correctly
On RHEL / CentOS, gdbm-devel and db4-devel packages must be installed.
Issue with SUSE Linux
FreeSWITCH will compile mod_perl on Suse 10.3, 11.0, and 11.1 however it appears that it will coredump. I resolved this by recompiling perl 5, (and upgrading to 5.10.0 in the process) which seems to have gotten this bug resolved. If you're not sufficiently skilled to re-compile perl yourself, contact your Distribution vendor and ask them to stop fixing things that aren't broken.
I have not tried FreeSWITCH on earlier Suse distributions, your mileage may vary...
Perl Multiplicity Requirement
As FreeSWITCH is multithreaded it requires mod_perl to be multithreaded this can be a bit of a task to get working if it is not already compiled with this support.
While there is a check in the makefile for this it doesn't actually execute currently so it is best to verify this yourself. At a command line run:
perl -V | grep -oP "usemultiplicity=[a-z]+"
you should get back something like: usemultiplicity=define however if you get back usemultiplicity=undef you are in bad shape. If this happens to you you will need to recompile perl to make mod_perl for FreeSWITCH load correctly. Keep in mind that in addition to recompiling some (many) of your perl modules may need to be reinstalled to work correctly along with some apps that may require in with perl/libperl. You should test this on a non-production system before trying to convert a production system.
For gentoo do the following:
Add ithreads to the perl and libperl use flags recompile perl and libperl perl-cleaner reallyall
That should help to ensure everything that could be effected is recompiled but it may not get everything (specifically manually compiled apps or cpan installed modules).
A script to help ensure all modules are reinstalled for your new version of perl can be found at: http://mitchcapper.com/missing_modules.pl.txt
Once you have enabled mod_perl in the modules config, you are ready to start using it. If you want to call it as part of a dial plan you just have to call your script using:
<action application="perl" data="/path/to/your/script.pl"/>
You can pass arguments to the script by just placing them at the end of the data string (separated by spaces).
The script receives
$session variable which represents the session object.
mod_perl will automatically import the
freeswitch Perl module, but nothing is imported into the global namespace. This means if you want to access a non-instance function from the class, say
consoleLog, it is
Your script should always end with a line of '
1;', or if you are returning out of the script make sure you use '
return 1' not just '
Keep in mind that your Perl script gets full control of the session, and nothing is happening to the session if the script is waiting for something. You cannot, for example, play music to the session and perform some bulky lookups in external databases.
In case of inline execution, in addition to
$session variable as described above, the script receives a predefined
$stream variable which allows you to write the output:
Also the variable
$env represents an event object.
XML dialplan generation
If you want to use mod_perl to call a perl script to generate XML for a dialplan however you want to do a few additional things:
The file conf/autoload_configs/perl.conf.xml is used in the default FreeSWITCH™ setup.
Here is a minimum configuration file, it will fetch a dialplan from perl script:
The startup-script values represent perl scripts (located inside the scripts/ directory) that are launched when FreeSWITCH is started. The scripts live in their own thread. You can use them to run simple tasks (and then let them finish) or looping forever, watching (for example) for events, generating calls or whatever you like.
The xml-handler-bindings value can assume the following values:
See Mod xml curl for more informations. Mod_perl behaves the same identical way.
The handler script receives two hashes that are populated for you by freeswitch:
It also receives $params that is a wrapped switch event.
You should return a valid XML dialplan in the $XML_STRING variable before exiting your code.
See the following example to start experimenting. The code will dump all the data to the console:
Programming with mod_perl
Functions and classes
Useful commands that may help get a list of functions and classes from mod_perl source files:
grep -o -P "^(\*[^=]+|############# Class.+)" freeswitch.pm
grep -o -P 'Usage: ([^"]+)' mod_perl_wrap.cpp
Some tips for programming with mod_perl
Most instance functions have 'this' as the first parameter, you don't actually pass 'this', it is automatically passed when you call a function, for example:
will pass $session as the this automatically.
It is important to know that the perl->c++ conversion is not always perfect. Passing functions is done by passing the function name as a string, rather than the standard dereferencing:
$session->setHangupHook( 'on_hangup' ); # BAD
$session->setHangupHook( \&on_hangup );
In addition a function that takes a string argument you should not pass it a number, so:
Generally if you pass an invalid argument it will give you an error when you run it, with an error of "No matching function for overloaded".
var hangup_cause = session.cause
In Perl, you would do:
$hangup_cause = $session->hangupCause();
Finally functions can behave a little bit different than expected, for example consoleLog does not append a newline at the end of the log message automatically, and may not flush it to the console until a new line is printed.
Executing an API from within mod_perl
Sometimes you need to execute an API (like 'show channels' or 'fifo list') while processing in your script. You need to create an API object:
my $api = new freeswitch::API;
Then use the execute or executeString method and capture the return value:
my $res = $api->executeString("show channels");
Here's a very simple example that calls version and prints the value in the debug log.
FreeSWITCH's api_hangup_hook is a handy tool for post-processing on a call. While many use Lua for this (because it is lightweight and easy) there are valid reasons for using Perl. For example, Lua does not natively support directory operations (create file, delete file, etc.). Also, Perl has many CPAN modules that can be leveraged for post processing.
Setting a hook is simple:
<action application="set" data="api_hangup_hook=perl hook.pl"/>
The above hook will run
perl hook.pl when the channel hangs up.
our $env; open(FILEOUT,'>','/tmp/hookdata.txt'); print FILEOUT $env->serialize; close(FILEOUT);
A dump of hookdata.txt will show you what is available. Note that this particular hook ran after a successful rxfax application:
Individual items can be accessed using the getHeader method:
print FILEOUT "UUID: " . $env->getHeader('uuid') . "\n"; print FILEOUT "Caller: " . $env->getHeader('caller_id') . "\n"; print FILEOUT "Fax result: " $env->getHeader('fax_result_text') . "\n"; print FILEOUT "Fax pages: " . $env->getHeader('fax_document_transferred_pages') . "\n";
Once you have the values you need you simply build a perl script and do whatever you wish to do.
The following is an example of dialplan extension that executes a Perl script after a fax is received: