- new plugin_regex: apply an extended regular expression

to the SIP 'To' URI and rewrite the target (outgoing
  calls only)
This commit is contained in:
Thomas Ries 2011-06-19 15:37:55 +00:00
parent dd94e02127
commit 08d3eabe7e
3 changed files with 92 additions and 49 deletions

View File

@ -1,5 +1,8 @@
0.8.1
=====
19-Jun-2011: - new plugin_regex: apply an extended regular expression
to the SIP 'To' URI and rewrite the target (outgoing
calls only)
17-Jun-2011: - plugin_prefix: correct handling of outgoing ACKs
(could lead to calls being aborted by one side)
- generic set of "redirect cache" that can be used by

View File

@ -91,8 +91,6 @@ user = nobody
# If you don't know what I'm saying above, do not enable this setting!
# USE AT YOUR OWN RISK!
# Too small stack size may lead to unexplainable crashes!
# Improper use may make siproxd eat your dog and vandalize
# your garden.
#thread_stack_size = 512
######################################################################
@ -335,6 +333,7 @@ load_plugin=plugin_logcall.la
#load_plugin=plugin_fix_bogus_via.la
#load_plugin=plugin_stun.la
#load_plugin=plugin_prefix.la
#load_plugin=plugin_regex.la
######################################################################
@ -394,10 +393,31 @@ plugin_stun_port = 3478
# period in seconds to request IP info from STUN server
plugin_stun_period = 300
######################################################################
# Plugin_prefix
#
# unconditionally prefixes all outgoing calls with the
# "akey" prefix specified below.
plugin_prefix_akey = 0
######################################################################
# Plugin_regex
#
# Applies an extended regular expression to the 'To' URI. A typical
# SIP URI looks like (port number is optional):
# sip:12345@some.provider.net
# sips:12345@some.provider.net:5061
#
# Backreferences \1 .. \9 are supported.
#
plugin_regex_desc = Test Regex 1
plugin_regex_pattern = ^sip:00
plugin_regex_replace = +
plugin_regex_desc = Test Regex 2
plugin_regex_pattern = ^sip:01
plugin_regex_replace = +a
plugin_regex_desc = Test Regex 3
plugin_regex_pattern = ^(sips?):01
plugin_regex_replace = \1:001

View File

@ -60,12 +60,14 @@ extern struct siproxd_config configuration;
/* plugin configuration storage */
static struct plugin_config {
stringa_t regex_desc;
stringa_t regex_pattern;
stringa_t regex_replace;
} plugin_cfg;
/* Instructions for config parser */
static cfgopts_t plugin_cfg_opts[] = {
{ "plugin_regex_desc", TYP_STRINGA,&plugin_cfg.regex_desc, {0, NULL} },
{ "plugin_regex_pattern", TYP_STRINGA,&plugin_cfg.regex_pattern, {0, NULL} },
{ "plugin_regex_replace", TYP_STRINGA,&plugin_cfg.regex_replace, {0, NULL} },
{0, 0, 0}
@ -103,7 +105,7 @@ int PLUGIN_INIT(plugin_def_t *plugin_def) {
return STS_FAILURE;
}
return plugin_regex_init();;
return plugin_regex_init();
}
/* Processing */
@ -138,11 +140,19 @@ int plugin_regex_init(void) {
return STS_FAILURE;
}
if (plugin_cfg.regex_pattern.used != plugin_cfg.regex_desc.used) {
ERROR("Plugin '%s': number of search patterns (%i) and number of "
"descriptions (%i) differ!", name,
plugin_cfg.regex_pattern.used, plugin_cfg.regex_desc.used);
return STS_FAILURE;
}
/* allocate space for regexes and compile them */
num_entries = plugin_cfg.regex_pattern.used;
re = malloc(num_entries*sizeof(re[0]));
for (i=0; i < num_entries; i++) {
sts = regcomp (&re[i], plugin_cfg.regex_pattern.string[i], REG_ICASE);
sts = regcomp (&re[i], plugin_cfg.regex_pattern.string[i],
REG_ICASE|REG_EXTENDED);
if (sts != 0) {
regerror(sts, &re[i], errbuf, sizeof(errbuf));
ERROR("Regular expression [%s] failed to compile: %s",
@ -240,22 +250,31 @@ static int plugin_regex_process(sip_ticket_t *ticket) {
/* private plugin code */
static int plugin_regex_redirect(sip_ticket_t *ticket) {
osip_uri_t *to_url=ticket->sipmsg->to->url;
char *to_user=to_url->username;
char *new_to_user=NULL;
char *url_string=NULL;
osip_uri_t *new_to_url;
int i, sts;
size_t username_len;
osip_contact_t *contact = NULL;
/* character workspaces for regex */
#define WORKSPACE_SIZE 128
static char in[WORKSPACE_SIZE+1], rp[WORKSPACE_SIZE+1];
/* do apply to full To URI... */
sts = osip_uri_to_str(to_url, &url_string);
if (sts != 0) {
ERROR("osip_uri_to_str() failed");
return STS_FAILURE;
}
DEBUGC(DBCLASS_BABBLE, "To URI string: [%s]", url_string);
/* perform search and replace of the regexes, first match hits */
for (i = 0; i < plugin_cfg.regex_pattern.used; i++) {
regmatch_t *pmatch = NULL;
pmatch = rmatch(to_user, WORKSPACE_SIZE, &re[i]);
pmatch = rmatch(url_string, WORKSPACE_SIZE, &re[i]);
if (pmatch == NULL) continue; /* no match, next */
/* have a match, do the replacement */
strncpy (in, to_user, WORKSPACE_SIZE);
INFO("Matched rexec rule: %s",plugin_cfg.regex_desc.string[i] );
strncpy (in, url_string, WORKSPACE_SIZE);
in[WORKSPACE_SIZE]='\0';
strncpy (rp, plugin_cfg.regex_replace.string[i], WORKSPACE_SIZE);
rp[WORKSPACE_SIZE]='\0';
@ -265,31 +284,33 @@ for (i = 0; i < plugin_cfg.regex_pattern.used; i++) {
ERROR("regex replace failed: pattern:[%s] replace:[%s]",
plugin_cfg.regex_pattern.string[i],
plugin_cfg.regex_replace.string[i]);
osip_free(url_string);
return STS_FAILURE;
}
/* only do first match */
break;
}
if (i >= plugin_cfg.regex_pattern.used) {
// no match
/* no match */
osip_free(url_string);
return STS_SUCCESS;
}
/* in: contains the new string */
// in: contains the new string
/* including \0 + leading character(s) */
username_len=strlen(in) + 1;
new_to_user = osip_malloc(username_len); /* *_len excluding \0 */
if (!new_to_user) return STS_SUCCESS;
/* only copy the part that really belongs to the username */
snprintf(new_to_user, username_len, "%s", in );
/* strncpy may not terminate - do it manually to be sure */
new_to_user[username_len-1]='\0';
sts = osip_uri_init(&new_to_url);
if (sts != 0) {
ERROR("Unable to initialize URI");
osip_free(url_string);
return STS_FAILURE;
}
sts = osip_uri_parse(new_to_url, in);
if (sts != 0) {
ERROR("Unable to parse To URI: %s", in);
osip_uri_free(new_to_url);
osip_free(url_string);
return STS_FAILURE;
}
/* use a "302 Moved temporarily" response back to the client */
/* new target is within the Contact Header */
@ -305,12 +326,11 @@ if (i >= plugin_cfg.regex_pattern.used) {
/* insert one new Contact header containing the new target address */
osip_contact_init(&contact);
osip_uri_clone(to_url, &contact->url);
osip_list_add(&(ticket->sipmsg->contacts),contact,0);
/* USER part is always present, put new_to_user in contact URL */
osip_free(contact->url->username);
contact->url->username=new_to_user;
/* link the new_to_url into the Contact list */
contact->url = new_to_url;
new_to_url = NULL;
/*
* Add the 'REDIRECTED_TAG=REDIRECTED_VAL' parameter to URI. Required to figure out
@ -321,12 +341,14 @@ if (i >= plugin_cfg.regex_pattern.used) {
osip_uri_param_add(&(contact->url->url_params), osip_strdup(REDIRECTED_TAG),
osip_strdup(REDIRECTED_VAL));
INFO("redirecting %s -> %s", to_user, new_to_user);
INFO("redirecting %s -> %s", url_string, in);
/* sent redirect message back to local client */
add_to_redirected_cache(&redirected_cache, ticket);
sip_gen_response(ticket, 302 /*Moved temporarily*/);
/* release resources and return */
osip_free(url_string);
return STS_SIP_SENT;
}
@ -353,10 +375,8 @@ regmatch_t * rmatch (char *buf, int size, regex_t *re) {
/* perform the match */
if (regexec (re, buf, NMATCHES, pm, 0)) {
DEBUGC(DBCLASS_PLUGIN,"no match found.");
return NULL;
}
DEBUGC(DBCLASS_PLUGIN,"match found.");
return &pm[0];
}