From 54664b3dabf2b55f209693b0fa183d139032a027 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Sat, 14 Jan 2006 16:01:52 +0000 Subject: [PATCH] fix iax and add regex dialplan git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@381 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- libs/iax/src/iax.c | 2 +- modules.conf | 1 + src/include/switch_config.h | 2 + src/mod/dialplans/mod_pcre/mod_pcre.c | 102 +++++++++++++++++++++++--- src/mod/endpoints/mod_iax/mod_iax.c | 63 ++++++++-------- src/switch_config.c | 1 + 6 files changed, 130 insertions(+), 41 deletions(-) diff --git a/libs/iax/src/iax.c b/libs/iax/src/iax.c index e4490b737e..a483c4f4c2 100644 --- a/libs/iax/src/iax.c +++ b/libs/iax/src/iax.c @@ -66,7 +66,7 @@ void gettimeofday(struct timeval *tv, void /*struct timezone*/ *tz); #include "jitterbuf.h" #endif -typedef long time_in_ms_t; +typedef int64_t time_in_ms_t; #include "iax-client.h" #include "md5.h" diff --git a/modules.conf b/modules.conf index 2f555ca908..6d12cc441d 100644 --- a/modules.conf +++ b/modules.conf @@ -17,3 +17,4 @@ endpoints/mod_woomera event_handlers/mod_xmpp_event formats/mod_sndfile timers/mod_softtimer +dialplans/mod_pcre diff --git a/src/include/switch_config.h b/src/include/switch_config.h index b2aa64135a..8976ce3948 100644 --- a/src/include/switch_config.h +++ b/src/include/switch_config.h @@ -74,6 +74,8 @@ struct switch_config { char buf[1024]; /*! current line number in file */ int lineno; + /*! current category number in file */ + int catno; }; /*! diff --git a/src/mod/dialplans/mod_pcre/mod_pcre.c b/src/mod/dialplans/mod_pcre/mod_pcre.c index cc3a3e3fe9..1c807aec1a 100644 --- a/src/mod/dialplans/mod_pcre/mod_pcre.c +++ b/src/mod/dialplans/mod_pcre/mod_pcre.c @@ -33,26 +33,33 @@ #include #include #include - +#include static const char modname[] = "mod_pcre"; +#define cleanre() if (re) {\ + pcre_free(re);\ + re = NULL;\ + } switch_caller_extension *dialplan_hunt(switch_core_session *session) { switch_caller_profile *caller_profile; switch_caller_extension *extension = NULL; switch_channel *channel; - char *cf = "extensions.conf"; + char *cf = "regextensions.conf"; switch_config cfg; char *var, *val; - char app[1024]; + char app[1024] = ""; + int catno = -1; + char *regex = NULL; + char *exten_name = NULL; + pcre *re = NULL; channel = switch_core_session_get_channel(session); caller_profile = switch_channel_get_caller_profile(channel); - //switch_channel_set_variable(channel, "pleasework", "yay"); - switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hello %s You Dialed %s!\n", caller_profile->caller_id_name, caller_profile->destination_number); + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Processing %s->%s!\n", caller_profile->caller_id_name, caller_profile->destination_number); if (!switch_config_open_file(&cfg, cf)) { switch_console_printf(SWITCH_CHANNEL_CONSOLE, "open of %s failed\n", cf); @@ -61,12 +68,80 @@ switch_caller_extension *dialplan_hunt(switch_core_session *session) } while (switch_config_next_pair(&cfg, &var, &val)) { - if (!strcasecmp(cfg.category, "extensions")) { - if (!strcmp(var, caller_profile->destination_number) && val) { + if (cfg.catno != catno) { /* new category */ + regex = NULL; + catno = cfg.catno; + exten_name = cfg.category; + } + + + + if (!strcasecmp(var, "regex")) { + const char *error = NULL; + int erroffset = 0; + + cleanre(); + re = pcre_compile( + val, /* the pattern */ + 0, /* default options */ + &error, /* for error message */ + &erroffset, /* for error offset */ + NULL); /* use default character tables */ + if (error) { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "ERROR: %d %s\n", erroffset, error); + cleanre(); + return NULL; + } + } else if (!strcasecmp(var, "match")) { + int rc; + int ovector[30]; + + rc = pcre_exec( + re, /* result of pcre_compile() */ + NULL, /* we didn't study the pattern */ + caller_profile->destination_number, /* the subject string */ + strlen(caller_profile->destination_number), /* the length of the subject string */ + 0, /* start at offset 0 in the subject */ + 0, /* default options */ + ovector, /* vector of integers for substring information */ + sizeof(ovector) / sizeof(ovector[0])); /* number of elements (NOT size in bytes) */ + + + if (rc > 0) { + char newval[1024] = ""; + char index[10] = ""; + char replace[128] = ""; + int x, y=0, z=0, num = 0; char *data; + + for (x = 0; x < sizeof(newval) && x < strlen(val);) { + if (val[x] == '$') { + x++; + + while(val[x] > 47 && val[x] < 58) { + index[z++] = val[x]; + x++; + } + index[z++] = '\0'; + z = 0; + num = atoi(index); + + if (pcre_copy_substring(caller_profile->destination_number, ovector, rc, num, replace, sizeof(replace)) > 0) { + int r; + for(r = 0; r < strlen(replace); r++) { + newval[y++] = replace[r]; + } + } + } else { + newval[y++] = val[x]; + x++; + } + } + newval[y++] = '\0'; + memset(app, 0, sizeof(app)); - strncpy(app, val, sizeof(app)); + switch_copy_string(app, newval, sizeof(app)); if ((data = strchr(app, ' '))) { *data = '\0'; @@ -75,16 +150,20 @@ switch_caller_extension *dialplan_hunt(switch_core_session *session) switch_console_printf(SWITCH_CHANNEL_CONSOLE, "invalid extension on line %d\n", cfg.lineno); continue; } + + if (!extension) { - if (!(extension = switch_caller_extension_new(session, caller_profile->destination_number, caller_profile->destination_number))) { + if (!(extension = switch_caller_extension_new(session, exten_name, caller_profile->destination_number))) { switch_console_printf(SWITCH_CHANNEL_CONSOLE, "memory error!\n"); break; } } switch_caller_extension_add_application(session, extension, app, data); - } + } + } + } switch_config_close_file(&cfg); @@ -95,12 +174,13 @@ switch_caller_extension *dialplan_hunt(switch_core_session *session) switch_channel_hangup(channel); } + cleanre(); return extension; } static const switch_dialplan_interface dialplan_interface = { - /*.interface_name =*/ "demo", + /*.interface_name =*/ "pcre", /*.hunt_function = */ dialplan_hunt /*.next = NULL */ }; diff --git a/src/mod/endpoints/mod_iax/mod_iax.c b/src/mod/endpoints/mod_iax/mod_iax.c index 352252b185..4f1bd7cac9 100644 --- a/src/mod/endpoints/mod_iax/mod_iax.c +++ b/src/mod/endpoints/mod_iax/mod_iax.c @@ -88,7 +88,7 @@ struct private_object { unsigned int codecs; unsigned short samprate; switch_mutex_t *mutex; - switch_thread_cond_t *cond; + //switch_thread_cond_t *cond; }; SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan) @@ -434,8 +434,8 @@ static switch_status channel_on_init(switch_core_session *session) switch_set_flag(tech_pvt, TFLAG_IO); switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); - switch_thread_cond_create(&tech_pvt->cond, switch_core_session_get_pool(session)); - switch_mutex_lock(tech_pvt->mutex); + //switch_thread_cond_create(&tech_pvt->cond, switch_core_session_get_pool(session)); + //switch_mutex_lock(tech_pvt->mutex); /* Move Channel's State Machine to RING */ switch_channel_set_state(channel, CS_RING); @@ -489,7 +489,8 @@ static switch_status channel_on_hangup(switch_core_session *session) assert(tech_pvt != NULL); switch_clear_flag(tech_pvt, TFLAG_IO); - switch_thread_cond_signal(tech_pvt->cond); + switch_clear_flag(tech_pvt, TFLAG_VOICE); + //switch_thread_cond_signal(tech_pvt->cond); if (tech_pvt->read_codec.implementation) { switch_core_codec_destroy(&tech_pvt->read_codec); @@ -526,7 +527,7 @@ static switch_status channel_kill_channel(switch_core_session *session, int sig) switch_clear_flag(tech_pvt, TFLAG_IO); switch_clear_flag(tech_pvt, TFLAG_VOICE); switch_channel_hangup(channel); - switch_thread_cond_signal(tech_pvt->cond); + //switch_thread_cond_signal(tech_pvt->cond); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s CHANNEL KILL\n", switch_channel_get_name(channel)); @@ -663,25 +664,26 @@ static switch_status channel_read_frame(switch_core_session *session, switch_fra tech_pvt = switch_core_session_get_private(session); assert(tech_pvt != NULL); - for(;;) { - if (switch_test_flag(tech_pvt, TFLAG_IO)) { - switch_thread_cond_wait(tech_pvt->cond, tech_pvt->mutex); - if (!switch_test_flag(tech_pvt, TFLAG_IO)) { - return SWITCH_STATUS_FALSE; - } - if (switch_test_flag(tech_pvt, TFLAG_IO)) { - switch_clear_flag(tech_pvt, TFLAG_VOICE); - if(!tech_pvt->read_frame.datalen) { - continue; - } - - *frame = &tech_pvt->read_frame; - return SWITCH_STATUS_SUCCESS; - } + while (switch_test_flag(tech_pvt, TFLAG_IO)) { + //switch_thread_cond_wait(tech_pvt->cond, tech_pvt->mutex); + if (!switch_test_flag(tech_pvt, TFLAG_IO)) { + return SWITCH_STATUS_FALSE; } - break; + + if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) { + switch_clear_flag(tech_pvt, TFLAG_VOICE); + if(!tech_pvt->read_frame.datalen) { + continue; + } + + *frame = &tech_pvt->read_frame; + return SWITCH_STATUS_SUCCESS; + } + switch_yield(1000); } + + return SWITCH_STATUS_FALSE; } @@ -999,7 +1001,7 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void) switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hangup %s\n", switch_channel_get_name(channel)); switch_set_flag(tech_pvt, TFLAG_HANGUP); switch_channel_hangup(channel); - switch_thread_cond_signal(tech_pvt->cond); + //switch_thread_cond_signal(tech_pvt->cond); iaxevent->session = NULL; } else { switch_console_printf(SWITCH_CHANNEL_CONSOLE, "No Session? %s\n", switch_test_flag(tech_pvt, TFLAG_VOICE) ? "yes" : "no"); @@ -1012,13 +1014,16 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void) break; case IAX_EVENT_VOICE: if (tech_pvt && (tech_pvt->read_frame.datalen = iaxevent->datalen)) { - int bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame; - int frames = (int)(tech_pvt->read_frame.datalen / bytes); - tech_pvt->read_frame.samples = frames * tech_pvt->read_codec.implementation->samples_per_frame; - memcpy(tech_pvt->read_frame.data, iaxevent->data, iaxevent->datalen); - /* wake up the i/o thread*/ - switch_set_flag(tech_pvt, TFLAG_VOICE); - switch_thread_cond_signal(tech_pvt->cond); + switch_channel *channel; + if ((channel = switch_core_session_get_channel(tech_pvt->session)) && switch_channel_get_state(channel) <= CS_HANGUP) { + int bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame; + int frames = (int)(tech_pvt->read_frame.datalen / bytes); + tech_pvt->read_frame.samples = frames * tech_pvt->read_codec.implementation->samples_per_frame; + memcpy(tech_pvt->read_frame.data, iaxevent->data, iaxevent->datalen); + /* wake up the i/o thread*/ + switch_set_flag(tech_pvt, TFLAG_VOICE); + //switch_thread_cond_signal(tech_pvt->cond); + } } break; case IAX_EVENT_TRANSFER: diff --git a/src/switch_config.c b/src/switch_config.c index e3014be383..78b70f9fb5 100644 --- a/src/switch_config.c +++ b/src/switch_config.c @@ -97,6 +97,7 @@ SWITCH_DECLARE(int) switch_config_next_pair(switch_config *cfg, char **var, char *end = '\0'; (*var)++; switch_copy_string(cfg->category, *var, sizeof(cfg->category)); + cfg->catno++; continue; }