- 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

@@ -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,56 +250,67 @@ 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];
/* 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]);
if (pmatch == NULL) continue; /* no match, next */
/* have a match, do the replacement */
strncpy (in, to_user, WORKSPACE_SIZE);
in[WORKSPACE_SIZE]='\0';
strncpy (rp, plugin_cfg.regex_replace.string[i], WORKSPACE_SIZE);
rp[WORKSPACE_SIZE]='\0';
sts = rreplace(in, WORKSPACE_SIZE, &re[i], pmatch, rp);
if (sts != STS_SUCCESS) {
ERROR("regex replace failed: pattern:[%s] replace:[%s]",
plugin_cfg.regex_pattern.string[i],
plugin_cfg.regex_replace.string[i]);
/* 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;
}
break;
}
if (i >= plugin_cfg.regex_pattern.used) {
// no match
return STS_SUCCESS;
}
DEBUGC(DBCLASS_BABBLE, "To URI string: [%s]", url_string);
// in: contains the new 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(url_string, WORKSPACE_SIZE, &re[i]);
if (pmatch == NULL) continue; /* no match, next */
/* 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';
/* have a match, do the replacement */
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';
sts = rreplace(in, WORKSPACE_SIZE, &re[i], pmatch, rp);
if (sts != STS_SUCCESS) {
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 */
osip_free(url_string);
return STS_SUCCESS;
}
/* in: contains the new string */
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];
}