- new plugin API (dynamically loadable plugins)

This commit is contained in:
Thomas Ries
2008-01-27 16:29:35 +00:00
parent 4a2062f7e0
commit 82563a17ee
17 changed files with 1045 additions and 727 deletions
+14 -1
View File
@@ -30,9 +30,22 @@ siproxd_SOURCES = siproxd.c proxy.c register.c sock.c utils.c \
sip_utils.c sip_layer.c log.c readconf.c rtpproxy.c \
rtpproxy_relay.c accessctl.c route_processing.c \
security.c auth.c fwapi.c resolve.c \
plugin_shortdial.c dejitter.c
dejitter.c plugins.c
# addrcache.c
#
# Plugin modules, installed in "pkglib" directory ($prefix/lib/siproxd/)
#
pkglib_LTLIBRARIES = plugin_demo.la \
plugin_shortdial.la
#
plugin_demo_la_SOURCES = plugin_demo.c
plugin_demo_la_LDFLAGS = -module
#
plugin_shortdial_la_SOURCES = plugin_shortdial.c
plugin_shortdial_la_LDFLAGS = -module
#
# an example for a custom firewall control module
# that can be linked into siproxd (--with-custom-fwmodule)
+83
View File
@@ -0,0 +1,83 @@
/*
Copyright (C) 2008 Thomas Ries <tries@gmx.net>
This file is part of Siproxd.
Siproxd is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Siproxd is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warrantry of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Siproxd; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <osipparser2/osip_parser.h>
#include "siproxd.h"
#include "log.h"
#include "plugins.h"
static char const ident[]="$Id$";
/* configuration storage */
extern struct siproxd_config configuration;
/*
* Initialization.
* Called once suring siproxd startup.
*/
int plugin_init(plugin_def_t *plugin_def) {
/* API version number of siproxd that this plugin is built against.
* This constant will change whenever changes to the API are made
* that require adaptions in the plugin. */
plugin_def->api_version=SIPROXD_API_VERSION;
/* Name and descriptive text of the plugin */
plugin_def->name=strdup("plugin_demo");
plugin_def->desc=strdup("This is just a demo plugin without any purpose");
/* Execution mask - during what stages of SIP processing shall
* the plugin be called. */
plugin_def->exe_mask=PLUGIN_DETERMINE_TARGET|PLUGIN_PRE_PROXY;
INFO("plugin_demo is initialized");
return STS_SUCCESS;
}
/*
* Processing.
*
*/
int plugin_process(int stage, sip_ticket_t *ticket){
/* stage contains the PLUGIN_* value - the stage of SIP processing. */
INFO("plugin_demo: processing - stage %i",stage);
return STS_SUCCESS;
}
/*
* De-Initialization.
* Called during shutdown of siproxd. Gives the plugin the chance
* to clean up its mess (e.g. dynamic memory allocation, database
* connections, whatever the plugin messes around with)
*/
int plugin_end(void){
INFO("plugin_demo ends here");
return STS_SUCCESS;
}
+38 -3
View File
@@ -24,11 +24,13 @@
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <osipparser2/osip_parser.h>
#include "siproxd.h"
#include "log.h"
#include "plugins.h"
static char const ident[]="$Id$";
@@ -37,17 +39,50 @@ extern struct siproxd_config configuration;
/* local prototypes */
static int plugin_shortdial_redirect(sip_ticket_t *ticket, int shortcut_no);
static int plugin_shortdial(sip_ticket_t *ticket);
/*
* Plugin API functions code
*/
/* Initialization */
int plugin_init(plugin_def_t *plugin_def) {
plugin_def->api_version=SIPROXD_API_VERSION;
plugin_def->name=strdup("plugin_shortdial");
plugin_def->desc=strdup("Handles Dial shortcuts as defined in config file");
plugin_def->exe_mask=PLUGIN_DETERMINE_TARGET;
return STS_SUCCESS;
}
/* Processing */
int plugin_process(int stage, sip_ticket_t *ticket){
int sts;
sts=plugin_shortdial(ticket);
return sts;
}
/* De-Initialization */
int plugin_end(void){
return STS_SUCCESS;
}
/*
* Workload code
*/
/* returns STS_SIP_SENT if processing is to be terminated,
* otherwise STS_SUCCESS (go on with processing) */
/* code (entry point) */
int plugin_shortdial(sip_ticket_t *ticket) {
static int plugin_shortdial(sip_ticket_t *ticket) {
int sts=STS_SUCCESS;
osip_uri_t *req_url;
int shortcut_no=0;
if (!ticket || !ticket->sipmsg) return STS_FAILURE;
/* plugin loaded and not configured, return with success */
if (configuration.pi_shortdial_akey==NULL) return STS_SUCCESS;
if (configuration.pi_shortdial_entry.used==0) return STS_SUCCESS;
DEBUGC(DBCLASS_PLUGIN,"plugin entered");
req_url=osip_message_get_uri(ticket->sipmsg);
@@ -105,7 +140,7 @@ int plugin_shortdial(sip_ticket_t *ticket) {
}
/* private code */
/* private plugin code */
static int plugin_shortdial_redirect(sip_ticket_t *ticket, int shortcut_no) {
osip_uri_t *to_url=ticket->sipmsg->to->url;
char *to_user=to_url->username;
+57 -2
View File
@@ -20,7 +20,62 @@
/* $Id$ */
#include <ltdl.h>
/* Plugins must return STS_SUCCESS / SUCCESS_FAILURE */
/* short Dial plugin */
int plugin_shortdial(sip_ticket_t *ticket);
/*
* Processing stages for Plugins
*/
/* Validation of SIP packet */
#define PLUGIN_VALIDATE 0x00000010
/* Determining Request Targets */
/* may end the current SIP processing in siproxd by returning STS_SIP_SENT
* see plugin_shortcut that sends a redirect back to the client */
#define PLUGIN_DETERMINE_TARGET 0x00000020 /* Determining Request Targets */
/* SIP package before siproxd starts the proxying process */
#define PLUGIN_PRE_PROXY 0x00000040 /* */
/* to/from unregistered UA */
#define PLUGIN_PROXY_UNK 0x00000080 /* e.g. incoming call to unknown UA */
/* before sending the SIP message */
#define PLUGIN_POST_PROXY 0x00000100 /* */
/* Plugin "database" */
typedef struct {
void *next; /* link to next plugin element, NULL if last */
int api_version; /* API version that PLUGIN uses */
char *name; /* Plugn name */
char *desc; /* Description */
int exe_mask; /* bitmask for activation of different processing
stages during SIP processing that a plugin wants
to be called */
lt_ptr plugin_process;/* Plugin processing entry point */
lt_ptr plugin_end; /* de-initialization function */
lt_ptr dlhandle; /* handle returned by dlopen() */
} plugin_def_t;
#define SIPROXD_API_VERSION 0x0100
/* The plugin must provide the following entry points */
/* Plugin is responsable for its dynamic memory management.
- Storage allocated in _init must be released in _end.
- manipulation of SIP messages (sip_ticket structure) must
be made in a way to ensure that no memleaks do exist.
If you want to change a field, first osip_malloc() new space,
move the pointer in the osip structure to the new place and then
osip_free() the old area.
*/
/* plugin_init must define the following fields of the plugin_def_t structure:
- api_version (= SIPROXD_API_VERSION)
- name
- desc
- exe_mask
The rest will be initialized by siproxd and must not be fumbled with.
*/
int plugin_init(plugin_def_t *plugin_def);
int plugin_process(int stage, sip_ticket_t *ticket);
int plugin_end(void);
+26 -8
View File
@@ -34,6 +34,7 @@
#include <osipparser2/sdp_message.h>
#include "siproxd.h"
#include "plugins.h"
#include "log.h"
static char const ident[]="$Id$";
@@ -108,6 +109,8 @@ int proxy_request (sip_ticket_t *ticket) {
sip_find_direction(ticket, &i);
type = ticket->direction;
/*&&&& PLUGIN_PRE_PROXY */
call_plugins(PLUGIN_PRE_PROXY, ticket);
/*
* logging of passing calls
*/
@@ -288,6 +291,8 @@ sts=sip_obscure_callid(ticket);
* How about "408 Request Timeout" ?
*
*/
/*&&&& PLUGIN_PROXY_UNK */
call_plugins(PLUGIN_PROXY_UNK, ticket);
sip_gen_response(ticket, 408 /* Request Timeout */);
return STS_FAILURE;
@@ -406,6 +411,10 @@ sts=sip_obscure_callid(ticket);
DEBUGC(DBCLASS_PROXY, "proxy_request: have Route header to %s:%i",
utils_inet_ntoa(sendto_addr), port);
#else
/*
* Route present?
* If so, fetch address from topmost Route: header and remove it.
*/
if ((type == REQTYP_OUTGOING) &&
(!osip_list_eol(&(request->routes), 0))) {
sts=route_determine_nexthop(ticket, &sendto_addr, &port);
@@ -419,10 +428,6 @@ sts=sip_obscure_callid(ticket);
(sip_find_outbound_proxy(ticket, &sendto_addr, &port) == STS_SUCCESS)) {
DEBUGC(DBCLASS_PROXY, "proxy_request: have outbound proxy %s:%i",
utils_inet_ntoa(sendto_addr), port);
/*
* Route present?
* If so, fetch address from topmost Route: header and remove it.
*/
#endif
/*
* destination from SIP URI
@@ -469,6 +474,9 @@ sts=sip_obscure_callid(ticket);
*/
/* not necessary, already in message and we do not support TCP */
/*&&&& PLUGIN_POST_PROXY */
call_plugins(PLUGIN_POST_PROXY, ticket);
/*
* RFC 3261, Section 16.6 step 10
* Proxy Behavior - Forward the new request
@@ -550,6 +558,8 @@ int proxy_response (sip_ticket_t *ticket) {
*/
sip_find_direction(ticket, NULL);
type = ticket->direction;
/*&&&& PLUGIN_PRE_PROXY */
call_plugins(PLUGIN_PRE_PROXY, ticket);
/*
* ok, we got a response that we are allowed to process.
@@ -679,6 +689,8 @@ sts=sip_obscure_callid(ticket);
DEBUGC(DBCLASS_PROXY, "response from/to unregistered UA (%s@%s)",
response->from->url->username? response->from->url->username:"*NULL*",
response->from->url->host? response->from->url->host : "*NULL*");
/*&&&& PLUGIN_PROXY_UNK */
call_plugins(PLUGIN_PROXY_UNK, ticket);
return STS_FAILURE;
}
@@ -730,6 +742,10 @@ sts=sip_obscure_callid(ticket);
DEBUGC(DBCLASS_PROXY, "proxy_response: have Route header to %s:%i",
utils_inet_ntoa(sendto_addr), port);
#else
/*
* Route present?
* If so, fetch address from topmost Route: header and remove it.
*/
if ((type == RESTYP_OUTGOING) &&
(!osip_list_eol(&(response->routes), 0))) {
sts=route_determine_nexthop(ticket, &sendto_addr, &port);
@@ -743,10 +759,6 @@ sts=sip_obscure_callid(ticket);
(sip_find_outbound_proxy(ticket, &sendto_addr, &port) == STS_SUCCESS)) {
DEBUGC(DBCLASS_PROXY, "proxy_response: have outbound proxy %s:%i",
utils_inet_ntoa(sendto_addr), port);
/*
* Route present?
* If so, fetch address from topmost Route: header and remove it.
*/
#endif
} else {
/* get target address and port from VIA header */
@@ -771,6 +783,12 @@ sts=sip_obscure_callid(ticket);
}
}
/*&&&& PLUGIN_POST_PROXY */
call_plugins(PLUGIN_POST_PROXY, ticket);
/*
* Proxy Behavior - Forward the response
*/
sts = sip_message_to_str(response, &buffer, &buflen);
if (sts != 0) {
ERROR("proxy_response: sip_message_to_str failed");
+2 -1
View File
@@ -180,12 +180,13 @@ static int parse_config (FILE *configfile) {
{ "pid_file", TYP_STRING, &configuration.pid_file },
{ "default_expires", TYP_INT4, &configuration.default_expires },
{ "autosave_registrations",TYP_INT4, &configuration.autosave_registrations },
{ "pi_shortdial_enable", TYP_INT4, &configuration.pi_shortdial },
{ "pi_shortdial_akey", TYP_STRING, &configuration.pi_shortdial_akey },
{ "pi_shortdial_entry", TYP_STRINGA,&configuration.pi_shortdial_entry },
{ "ua_string", TYP_STRING, &configuration.ua_string },
{ "use_rport", TYP_INT4, &configuration.use_rport },
{ "obscure_loops", TYP_INT4, &configuration.obscure_loops },
{ "plugin_dir", TYP_STRING, &configuration.plugin_dir },
{ "load_plugin", TYP_STRINGA,&configuration.load_plugin },
{0, 0, 0}
};
+18 -7
View File
@@ -236,6 +236,14 @@ int main (int argc, char *argv[])
INFO("daemonized, pid=%i", getpid());
}
/* load and initialize the plugins */
sts=load_plugins();
/* if error, abort siproxd */
if (sts != STS_SUCCESS) {
ERROR("Error while loading and initializing plug-ins - aborting");
exit(1);
}
/* prepare for creating PID file */
if (pidfilename == NULL) pidfilename = configuration.pid_file;
@@ -380,6 +388,7 @@ int main (int argc, char *argv[])
* (check request URI and refuse with 416 if not understood)
*/
/* NOT IMPLEMENTED */
/*&&& PLUGIN_VALIDATE */
/*
* RFC 3261, Section 16.3 step 3
@@ -448,14 +457,13 @@ int main (int argc, char *argv[])
* The message did pass all the
* tests above and is now ready
* to be proxied.
* Before we do so, we apply some
* additional preprocessing
* Feed to the plugins. If a plugin decides
* to end processing and terminate the ongoing
* dialog (STS_SIP_SENT), then just free
* the allocated resources.
*********************************/
/* Dial shortcuts */
if (configuration.pi_shortdial) {
sts = plugin_shortdial(&ticket);
if (sts == STS_SIP_SENT) goto end_loop;
}
sts = call_plugins(PLUGIN_DETERMINE_TARGET, &ticket);
if (sts == STS_SIP_SENT) goto end_loop;
/*********************************
@@ -583,6 +591,9 @@ int main (int argc, char *argv[])
}
}
/* unload the plugins */
unload_plugins();
/* END */
log_end();
return 0;
+8 -2
View File
@@ -91,12 +91,13 @@ struct siproxd_config {
char *pid_file;
int default_expires;
int autosave_registrations;
int pi_shortdial;
char *pi_shortdial_akey;
stringa_t pi_shortdial_entry;
char *ua_string;
int use_rport;
int obscure_loops;
char *plugin_dir;
stringa_t load_plugin;
};
/*
@@ -236,6 +237,10 @@ int sip_message_to_str(osip_message_t * sip, char **dest, size_t *len);
int sip_body_to_str(const osip_body_t * body, char **dest, size_t *len);
int sip_message_set_body(osip_message_t * sip, const char *buf, size_t len);
/* plugins.c */
int load_plugins (void);
int call_plugins(int stage, sip_ticket_t *ticket);
int unload_plugins(void);
/*
* some constant definitions
@@ -258,6 +263,7 @@ int sip_message_set_body(osip_message_t * sip, const char *buf, size_t len);
#define RTP_BUFFER_SIZE 1520 /* max size of an RTP frame */
/* (assume approx one Ethernet MTU) */
#define PATH_STRING_SIZE 256 /* max size of an file path */
#define URL_STRING_SIZE 128 /* max size of an URL/URI string */
#define STATUSCODE_SIZE 5 /* size of string representation of status */
#define DNS_CACHE_SIZE 256 /* number of entries in internal DNS cache */
@@ -297,7 +303,7 @@ int sip_message_set_body(osip_message_t * sip, const char *buf, size_t len);
#define STS_FAILURE 1 /* FAILURE */
#define STS_FALSE 1 /* FALSE */
#define STS_NEED_AUTH 1001 /* need authentication */
#define STS_SIP_SENT 2001 /* SIP packet is already sent */
#define STS_SIP_SENT 2001 /* SIP packet is already sent, end of dialog */
/* symbolic direction of data */
#define DIR_INCOMING 1