- new plugin API (dynamically loadable plugins)
This commit is contained in:
+14
-1
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user