ENUM Support

mod_enum can be used as a dialplan app, an api call from the console or as a dialplan interface.


Dialplan Interface:
put enum as the dialplan parameter in an endpoint module
i.e. instead of "XML" set it to "enum" or "enum,XML" for fall through.

Dialplan App:
This example will do a lookup and set the a variable that is the proper
dialstring to call all of the possible routes in order of preference according to 
the lookup and the order of the routes in the enum.conf section.

<extension name="tollfree">
  <condition field="destination_number" expression="^(18(0{2}|8{2}|7{2}|6{2})\d{7})$">
    <action application="enum" data="$1"/>
    <action application="bridge" data="${enum_auto_route}"/>
  </condition>
</extension>

You can also pick an alrernate root:
<action application="enum" data="$1 myroot.org"/>	


API command:
at the console you can say:
enum <number> [<root>]

The root always defaults to the one in the enum.conf section.




git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3494 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale
2006-11-30 21:28:32 +00:00
parent 90ddec83d9
commit 60434decf5
36 changed files with 7886 additions and 157 deletions
+2
View File
@@ -86,6 +86,8 @@ SWITCH_BEGIN_EXTERN_C
#define SWITCH_LOCAL_MEDIA_PORT_VARIABLE "_local_media_port_"
#define SWITCH_REMOTE_MEDIA_IP_VARIABLE "_remote_media_ip_"
#define SWITCH_REMOTE_MEDIA_PORT_VARIABLE "_remote_media_port_"
#define SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE "hangup_after_bridge"
#define SWITCH_SPEECH_KEY "_speech_"
#define SWITCH_UUID_BRIDGE "_uuid_bridge_"
#define SWITCH_BITS_PER_BYTE 8
+8
View File
@@ -39,6 +39,7 @@
#define SWITCH_UTILS_H
#include <switch.h>
#include <pcre.h>
SWITCH_BEGIN_EXTERN_C
@@ -231,8 +232,15 @@ SWITCH_DECLARE(int) switch_socket_waitfor(switch_pollfd_t *poll, int ms);
*/
SWITCH_DECLARE(char *) switch_cut_path(char *in);
#define switch_clean_re(re) if (re) {\
pcre_free(re);\
re = NULL;\
}
SWITCH_DECLARE(char *) switch_string_replace(const char *string, const char *search, const char *replace);
SWITCH_DECLARE(switch_status_t) switch_string_match(const char *string, size_t string_len, const char *search, size_t search_len);
SWITCH_DECLARE(int) switch_perform_regex(char *field, char *expression, pcre **new_re, int *ovector, uint32_t olen);
SWITCH_DECLARE(void) switch_perform_substitution(pcre *re, int match_count, char *data, char *field_data, char *substituted, uint32_t len, int *ovector);
#define SWITCH_READ_ACCEPTABLE(status) status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK
SWITCH_DECLARE(size_t) switch_url_encode(char *url, char *buf, size_t len);
@@ -45,6 +45,10 @@ static void audio_bridge_function(switch_core_session_t *session, char *data)
uint8_t no_media_bridge = 0;
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
if (switch_strlen_zero(data)) {
return;
}
caller_channel = switch_core_session_get_channel(session);
assert(caller_channel != NULL);
+1 -1
View File
@@ -135,7 +135,7 @@ static switch_status_t switch_gsm_decode(switch_codec_t *codec, switch_codec_t *
static const switch_codec_implementation_t gsm_8k_implementation = {
/*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 3,
/*.iananame */ "gsm",
/*.iananame */ "GSM",
/*.fmtp */ NULL,
/*.samples_per_second */ 8000,
/*.bits_per_second */ 13200,
@@ -37,96 +37,8 @@
static const char modname[] = "mod_dialplan_xml";
#define cleanre(re) if (re) {\
pcre_free(re);\
re = NULL;\
}
static int perform_regex(switch_channel_t *channel, char *field, char *expression, pcre **new_re, int *ovector, uint32_t olen)
{
const char *error = NULL;
int erroffset = 0;
pcre *re = NULL;
int match_count = 0;
if (!(field && expression)) {
return 0;
}
re = pcre_compile(expression, /* the pattern */
0, /* default options */
&error, /* for error message */
&erroffset, /* for error offset */
NULL); /* use default character tables */
if (error) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "COMPILE ERROR: %d [%s]\n", erroffset, error);
cleanre(re);
return 0;
}
match_count = pcre_exec(re, /* result of pcre_compile() */
NULL, /* we didn't study the pattern */
field, /* the subject string */
(int) strlen(field), /* the length of the subject string */
0, /* start at offset 0 in the subject */
0, /* default options */
ovector, /* vector of integers for substring information */
olen); /* number of elements (NOT size in bytes) */
if (match_count <= 0) {
cleanre(re);
match_count = 0;
}
*new_re = re;
return match_count;
}
static void perform_substitution(pcre *re, int match_count, char *data, char *field_data, char *substituted, uint32_t len, int *ovector)
{
char index[10] = "";
char replace[1024] = "";
uint32_t x, y = 0, z = 0, num = 0;
for (x = 0; x < (len-1) && x < strlen(data);) {
if (data[x] == '$') {
x++;
if (!(data[x] > 47 && data[x] < 58)) {
substituted[y++] = data[x-1];
continue;
}
while (data[x] > 47 && data[x] < 58) {
index[z++] = data[x];
x++;
}
index[z++] = '\0';
z = 0;
num = atoi(index);
if (pcre_copy_substring(field_data,
ovector,
match_count,
num,
replace,
sizeof(replace)) > 0) {
unsigned int r;
for (r = 0; r < strlen(replace); r++) {
substituted[y++] = replace[r];
}
}
} else {
substituted[y++] = data[x];
x++;
}
}
substituted[y++] = '\0';
}
typedef enum {
BREAK_ON_TRUE,
BREAK_ON_FALSE,
@@ -197,7 +109,7 @@ static int parse_exten(switch_core_session_t *session, switch_xml_t xexten, swit
field_data = "";
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "test conditions %s(%s) =~ /%s/\n", field, field_data, expression);
if (!(proceed = perform_regex(channel, field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
if (!(proceed = switch_perform_regex(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Regex mismatch\n");
for (xaction = switch_xml_child(xcond, "anti-action"); xaction; xaction = xaction->next) {
@@ -232,7 +144,7 @@ static int parse_exten(switch_core_session_t *session, switch_xml_t xexten, swit
char *app_data = NULL;
if (field && strchr(expression, '(')) {
perform_substitution(re, proceed, data, field_data, substituted, sizeof(substituted), ovector);
switch_perform_substitution(re, proceed, data, field_data, substituted, sizeof(substituted), ovector);
app_data = substituted;
} else {
app_data = data;
@@ -249,7 +161,7 @@ static int parse_exten(switch_core_session_t *session, switch_xml_t xexten, swit
switch_caller_extension_add_application(session, *extension, application, app_data);
}
cleanre(re);
switch_clean_re(re);
if (do_break_i == BREAK_ON_TRUE || do_break_i == BREAK_ALWAYS) {
break;
+64 -63
View File
@@ -137,7 +137,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session)
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_channel_t *channel;
switch_frame_t *frame;
int stream_id;
int stream_id = 0;
switch_event_t *event;
channel = switch_core_session_get_channel(session);
@@ -152,19 +152,18 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session)
switch_channel_set_flag(channel, CF_CONTROLLED);
while (switch_channel_ready(channel)) {
for (stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) {
if ((status = switch_core_session_read_frame(session, &frame, -1, stream_id)) == SWITCH_STATUS_SUCCESS) {
if (!SWITCH_READ_ACCEPTABLE(status)) {
break;
}
if (switch_core_session_dequeue_private_event(session, &event) == SWITCH_STATUS_SUCCESS) {
switch_ivr_parse_event(session, event);
switch_event_destroy(&event);
}
}
}
if ((status = switch_core_session_read_frame(session, &frame, -1, stream_id)) == SWITCH_STATUS_SUCCESS) {
if (!SWITCH_READ_ACCEPTABLE(status)) {
break;
}
if (switch_core_session_dequeue_private_event(session, &event) == SWITCH_STATUS_SUCCESS) {
switch_ivr_parse_event(session, event);
switch_event_destroy(&event);
}
}
}
switch_channel_clear_flag(channel, CF_CONTROLLED);
@@ -966,7 +965,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
switch_codec_t codec;
switch_memory_pool_t *pool = switch_core_session_get_pool(session);
char *codec_name;
int stream_id;
int stream_id = 0;
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_file_handle_t lfh;
switch_codec_t *read_codec = switch_core_session_get_read_codec(session);
@@ -975,11 +974,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
uint8_t asis = 0;
char *ext;
if (fh->samples > 0) {
sample_start = fh->samples;
fh->samples = 0;
}
if (file) {
if ((ext = strrchr(file, '.'))) {
ext++;
@@ -1000,6 +994,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
memset(fh, 0, sizeof(lfh));
}
if (fh->samples > 0) {
sample_start = fh->samples;
fh->samples = 0;
}
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
@@ -1259,21 +1260,23 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
if (!asis) {switch_swap_linear(write_frame.data, (int) write_frame.datalen / 2);}
#endif
#endif
for (stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) {
status = switch_core_session_write_frame(session, &write_frame, -1, stream_id);
stream_id = 0;
if (status == SWITCH_STATUS_MORE_DATA) {
status = SWITCH_STATUS_SUCCESS;
continue;
} else if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Bad Write\n");
done = 1;
break;
}
if (done) {
break;
}
}
status = switch_core_session_write_frame(session, &write_frame, -1, stream_id);
if (status == SWITCH_STATUS_MORE_DATA) {
status = SWITCH_STATUS_SUCCESS;
continue;
} else if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Bad Write\n");
done = 1;
break;
}
if (done) {
break;
}
if (timer_name) {
if (switch_core_timer_next(&timer) < 0) {
@@ -1487,7 +1490,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
switch_size_t ilen = 0;
switch_frame_t write_frame = {0};
int x;
int stream_id;
int stream_id = 0;
int done = 0;
int lead_in_out = 10;
switch_status_t status = SWITCH_STATUS_SUCCESS;
@@ -1522,13 +1525,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
write_frame.codec = codec;
for( x = 0; !done && x < lead_in_out; x++) {
for (stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) {
if (switch_core_session_write_frame(session, &write_frame, -1, stream_id) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Bad Write\n");
done = 1;
break;
}
}
if (switch_core_session_write_frame(session, &write_frame, -1, stream_id) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Bad Write\n");
done = 1;
break;
}
}
ilen = len;
@@ -1606,13 +1607,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
if (status != SWITCH_STATUS_SUCCESS) {
for( x = 0; !done && x < lead_in_out; x++) {
for (stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) {
if (switch_core_session_write_frame(session, &write_frame, -1, stream_id) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Bad Write\n");
done = 1;
break;
}
}
if (switch_core_session_write_frame(session, &write_frame, -1, stream_id) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Bad Write\n");
done = 1;
break;
}
}
if (status == SWITCH_STATUS_BREAK) {
status = SWITCH_STATUS_SUCCESS;
@@ -1627,17 +1626,15 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
write_frame.datalen = (uint32_t)ilen;
write_frame.samples = (uint32_t)(ilen / 2);
for (stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) {
if (switch_core_session_write_frame(session, &write_frame, -1, stream_id) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Bad Write\n");
done = 1;
break;
}
if (switch_core_session_write_frame(session, &write_frame, -1, stream_id) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Bad Write\n");
done = 1;
break;
}
if (done) {
break;
}
}
if (done) {
break;
}
if (timer) {
if ((x = switch_core_timer_next(timer)) < 0) {
@@ -1686,7 +1683,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses
switch_codec_t codec;
switch_memory_pool_t *pool = switch_core_session_get_pool(session);
char *codec_name;
int stream_id;
int stream_id = 0;
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_speech_handle_t sh;
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
@@ -3130,8 +3127,6 @@ static const switch_state_handler_table_t signal_bridge_state_handlers = {
/*.on_hibernate*/ signal_bridge_on_hibernate
};
SWITCH_DECLARE(switch_status_t) switch_ivr_signal_bridge(switch_core_session_t *session, switch_core_session_t *peer_session)
{
switch_channel_t *caller_channel, *peer_channel;
@@ -3319,9 +3314,15 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
switch_channel_get_name(peer_channel)
);
switch_channel_hangup(peer_channel, SWITCH_CAUSE_NO_ANSWER);
}
}
done:
if (switch_channel_get_state(caller_channel) < CS_HANGUP &&
switch_true(switch_channel_get_variable(caller_channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE))) {
switch_channel_hangup(caller_channel, SWITCH_CAUSE_NORMAL_CLEARING);
}
return status;
}
+86
View File
@@ -35,6 +35,92 @@
#include <stdlib.h>
SWITCH_DECLARE(int) switch_perform_regex(char *field, char *expression, pcre **new_re, int *ovector, uint32_t olen)
{
const char *error = NULL;
int erroffset = 0;
pcre *re = NULL;
int match_count = 0;
if (!(field && expression)) {
return 0;
}
re = pcre_compile(expression, /* the pattern */
0, /* default options */
&error, /* for error message */
&erroffset, /* for error offset */
NULL); /* use default character tables */
if (error) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "COMPILE ERROR: %d [%s]\n", erroffset, error);
switch_clean_re(re);
return 0;
}
match_count = pcre_exec(re, /* result of pcre_compile() */
NULL, /* we didn't study the pattern */
field, /* the subject string */
(int) strlen(field), /* the length of the subject string */
0, /* start at offset 0 in the subject */
0, /* default options */
ovector, /* vector of integers for substring information */
olen); /* number of elements (NOT size in bytes) */
if (match_count <= 0) {
switch_clean_re(re);
match_count = 0;
}
*new_re = re;
return match_count;
}
SWITCH_DECLARE(void) switch_perform_substitution(pcre *re, int match_count, char *data, char *field_data, char *substituted, uint32_t len, int *ovector)
{
char index[10] = "";
char replace[1024] = "";
uint32_t x, y = 0, z = 0, num = 0;
for (x = 0; x < (len-1) && x < strlen(data);) {
if (data[x] == '$') {
x++;
if (!(data[x] > 47 && data[x] < 58)) {
substituted[y++] = data[x-1];
continue;
}
while (data[x] > 47 && data[x] < 58) {
index[z++] = data[x];
x++;
}
index[z++] = '\0';
z = 0;
num = atoi(index);
if (pcre_copy_substring(field_data,
ovector,
match_count,
num,
replace,
sizeof(replace)) > 0) {
unsigned int r;
for (r = 0; r < strlen(replace); r++) {
substituted[y++] = replace[r];
}
}
} else {
substituted[y++] = data[x];
x++;
}
}
substituted[y++] = '\0';
}
SWITCH_DECLARE(char *) switch_priority_name(switch_priority_t priority)
{
switch(priority) { /*lol*/