Implementing a Perl plugin Print
Monday, 11 March 2013

This document describes how to implement a EMG plugin in Perl.

If you do not already have EMG, now is the time to install it:

http://www.nordicmessaging.se/files/docs/emg53-ug/html-installation.html

Setup a separate Perl installation according to description here:

http://www.nordicmessaging.se/tech-notes/emg/emg-526-and-perl-plugins.html

Adding a Perl plugin to EMG configuration

Plugins are defined in a PLUGIN section in server.cfg. Syntax is same as for C plugin but EMG will check if file given by LIBRARY keyword ends in ".pl" and if that is the case handle it as a Perl plugin.

The defined plugin can then be used for one or more connectors using the PLUGIN keyword in the connector section.

Sample configuration:

PLUGIN perl-reject <
LIBRARY=/etc/emg/plugins/reject.pl
CONFIG=config parameter
INSTANCES=1
>

CONNECTOR smpp-in1 <
...
PLUGIN=perl-reject
...
>

When referencing the plugin in connector section the plugin name can optionally be followed by ":" and a string which can be retrieved from request object in function calls. This is useful when using the same plugin on different connectors.

CONNECTOR smpp-in1 <
...
PLUGIN=perl-reject:smpp
...
>

CONNECTOR ucp-in1 <
...
PLUGIN=perl-reject:ucp
...
>

Plugin lifecycle

When emgd is started one perl interpretator is created for each plugin instance and the "create_config" hook, if present, is executed for each instance.

Since a separate perl interpretator is created for each instance different instances cannot share data easily. It requires using "shared memory" or similar mechanism.

Each interpretator brings some overhead and if for example 100 MB of data is loaded in "create_config" the amount of memory used will be 500 MB if the plugin has 5 instances.

Plugins are loaded on emgd startup. Any changes to the plugin source code requires a emgd restart to take effect.

Plugin hooks

There are several hooks defined in EMG. For each hook the corresponding function in the plugin will be called, if present.

The plugin hooks are:

# Executed on emgd start when plugins are loaded
sub create_config

{
  my ($plugin_name, $config) = @_;
  my $myconfig = "dummy";
  return $myconfig;
}

# Executed when a message has been received, but before response is sent back

sub before_receive
{
  my ($request, $response) = @_;
  my $myconfig = $request->{'config'};
  # Accept message
  my $status = 0;
  return $status;
}

# Executed before routing logic is applied
sub route
{
  my ($request, $response) = @_;
  $response->{'route'} = 'smpp-out2';
  # Use 'route'
  return 0;
}

# Executed before message send operation
sub before_send
{
  my ($request, $response) = @_;
  return 0;
}

# Executed after message send operation
sub after_send
{
  my ($request, $response) = @_;
  my $status = $request->{'result'};
}

# Executed after a delivery report (DLR) has been received
sub after_dlr
{
my ($request, $response) = @_;
}

It is possible to modify message options in all plugin hooks.

Plugin hooks sequence diagram

emg-plugincalls

About route hook

If route returns 0 and $response->route is set to a string with length > 0 then that string is used as the route target connector and no other routing logic is applied.

For other cases normal routing logic will be applied.

Plugin objects

The following objects (perl hashes) are used in EMG Perl Plugin API:

Object $request

config - Object returned in create_config

connector - A connector object

ccarg - The string optionally specified when referencing plugin in connector config

name - Plugin name

qe - Message object

result - Set to 0 if send operation was successful, otherwise set to non-zero (after_send only)

Object $response

errorcode - Numeric error code (used by "before_*" hooks when return value is non-zero)

errormessage - Error text (used by "before_*" hooks when return value is non-zero)

route - Target connector (only used by "route" hook)

Object connector

name - Connector name

instance - Connector instance number (starting at 0)

loglevel - Connector log level

username - Username (outgoing connectors only)

password - Password (outgoing connectors only)

Object message (qe)

All message options as key-value pairs with MGP names as key.

The message options can be modified from any plugin hook and will take effect regardless of return value.

Sample code:

sub before_receive
{
my ($request, $response) = @_;

my $qe = ${$request}{'qe'};
$qe->{'SOURCEADDR'} = 'sender';
return 0;
}

Sample plugins

Some sample plugins can be found here:

http://www.nordicmessaging.se/tech-notes/emg/sample-perl-plugins.html