<analog_spans>
<span id="1">
<param name="tonegroup" value="us"/>
- <param name="digit_timeout" value="2000"/>
- <param name="max_digits" value="11"/>
+ <param name="digit-timeout" value="2000"/>
+ <param name="max-digits" value="11"/>
<param name="dialplan" value="XML"/>
<param name="context" value="default"/>
+ <!-- regex to stop dialing when it matches -->
+ <!--<param name="dial-regex" value="5555"/>-->
+ <!-- regex to stop dialing when it does not match -->
+ <!--<param name="fail-dial-regex" value="^5"/>-->
</span>
</analog_spans>
</configuration>
#include "zap_isdn.h"
SWITCH_MODULE_LOAD_FUNCTION(mod_openzap_load);
-SWITCH_MODULE_DEFINITION(mod_openzap, mod_openzap_load, NULL, NULL);
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_openzap_shutdown);
+SWITCH_MODULE_DEFINITION(mod_openzap, mod_openzap_load, mod_openzap_shutdown, NULL);
switch_endpoint_interface_t *openzap_endpoint_interface;
zap_span_t *span;
char dialplan[80];
char context[80];
+ char dial_regex[256];
+ char fail_dial_regex[256];
+
};
static struct span_config SPAN_CONFIG[ZAP_MAX_SPANS_INTERFACE] = {0};
cycle_foreground(sigmsg->channel, 1);
}
break;
+
+ case ZAP_SIGEVENT_COLLECTED_DIGIT:
+ {
+ char *dtmf = sigmsg->raw_data;
+ char *regex = SPAN_CONFIG[sigmsg->channel->span->span_id].dial_regex;
+ char *fail_regex = SPAN_CONFIG[sigmsg->channel->span->span_id].fail_dial_regex;
+
+ if (switch_strlen_zero(regex)) {
+ regex = NULL;
+ }
+
+ if (switch_strlen_zero(fail_regex)) {
+ fail_regex = NULL;
+ }
+
+ if ((regex || fail_regex) && !switch_strlen_zero(dtmf)) {
+ switch_regex_t *re = NULL;
+ int ovector[30];
+ int match = 0;
+
+ if (fail_regex) {
+ match = switch_regex_perform(dtmf, fail_regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0]));
+ status = match ? ZAP_SUCCESS : ZAP_BREAK;
+ switch_regex_safe_free(re);
+ }
+
+ if (status == ZAP_SUCCESS && regex) {
+ match = switch_regex_perform(dtmf, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0]));
+ status = match ? ZAP_BREAK : ZAP_SUCCESS;
+ }
+
+ switch_regex_safe_free(re);
+ }
+
+ }
+ break;
}
return status;
static ZIO_SIGNAL_CB_FUNCTION(on_analog_signal)
{
+ switch_status_t status;
+
switch (sigmsg->channel->type) {
case ZAP_CHAN_TYPE_FXO:
{
- on_fxo_signal(sigmsg);
+ status = on_fxo_signal(sigmsg);
}
break;
case ZAP_CHAN_TYPE_FXS:
{
- on_fxs_signal(sigmsg);
+ status = on_fxs_signal(sigmsg);
}
break;
default:
break;
}
- return ZAP_SUCCESS;
+ return status;
}
static void zap_logger(char *file, const char *func, int line, int level, char *fmt, ...)
char *tonegroup = NULL;
char *digit_timeout = NULL;
char *max_digits = NULL;
+ char *dial_regex = NULL;
+ char *fail_dial_regex = NULL;
uint32_t span_id = 0, to = 0, max = 0;
zap_span_t *span = NULL;
if (!strcasecmp(var, "tonegroup")) {
tonegroup = val;
- } else if (!strcasecmp(var, "digit_timeout")) {
+ } else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "digit-timeout")) {
digit_timeout = val;
} else if (!strcasecmp(var, "context")) {
context = val;
} else if (!strcasecmp(var, "dialplan")) {
dialplan = val;
- } else if (!strcasecmp(var, "max_digits")) {
+ } else if (!strcasecmp(var, "dial-regex")) {
+ dial_regex = val;
+ } else if (!strcasecmp(var, "fail-dial-regex")) {
+ fail_dial_regex = val;
+ } else if (!strcasecmp(var, "max_digits") || !strcasecmp(var, "max-digits")) {
digit_timeout = val;
}
}
}
SPAN_CONFIG[span->span_id].span = span;
- switch_copy_string(SPAN_CONFIG[span->span_id].context, context, sizeof(SPAN_CONFIG[span->span_id].context));
- switch_copy_string(SPAN_CONFIG[span->span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span->span_id].dialplan));
+ switch_set_string(SPAN_CONFIG[span->span_id].context, context);
+ switch_set_string(SPAN_CONFIG[span->span_id].dialplan, dialplan);
+
+ if (dial_regex) {
+ switch_set_string(SPAN_CONFIG[span->span_id].dial_regex, dial_regex);
+ }
+
+ if (fail_dial_regex) {
+ switch_set_string(SPAN_CONFIG[span->span_id].fail_dial_regex, fail_dial_regex);
+ }
-
zap_analog_start(span);
}
}
return SWITCH_STATUS_SUCCESS;
}
-
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_openzap_shutdown)
+{
+ zap_global_destroy();
+ return SWITCH_STATUS_SUCCESS;
+}
/* For Emacs:
* Local Variables:
void print_hex_bytes(uint8_t *data, zap_size_t dlen, char *buf, zap_size_t blen);
int zap_hash_equalkeys(void *k1, void *k2);
uint32_t zap_hash_hashfromstring(void *ky);
+uint32_t zap_running(void);
+
ZIO_CODEC_FUNCTION(zio_slin2ulaw);
ZIO_CODEC_FUNCTION(zio_ulaw2slin);
ZIO_CODEC_FUNCTION(zio_slin2alaw);
ZAP_SIGEVENT_ALARM_TRAP,
ZAP_SIGEVENT_ALARM_CLEAR,
ZAP_SIGEVENT_MISC,
+ ZAP_SIGEVENT_COLLECTED_DIGIT,
ZAP_SIGEVENT_INVALID
} zap_signal_event_t;
#define SIGNAL_STRINGS "START", "STOP", "TRANSFER", "ANSWER", "UP", "FLASH", "PROGRESS", \
- "PROGRESS_MEDIA", "NOTIFY", "TONE_DETECTED", "ALARM_TRAP", "ALARM_CLEAR", "MISC", "INVALID"
+ "PROGRESS_MEDIA", "NOTIFY", "TONE_DETECTED", "ALARM_TRAP", "ALARM_CLEAR", "MISC", "COLLECTED_DIGIT", "INVALID"
ZAP_STR2ENUM_P(zap_str2zap_signal_event, zap_signal_event2str, zap_signal_event_t)
typedef enum {
ZAP_TIMEOUT,
ZAP_NOTIMPL,
ZAP_CHECKSUM_ERROR,
- ZAP_STATUS_COUNT
+ ZAP_STATUS_COUNT,
+ ZAP_BREAK
} zap_status_t;
typedef enum {
zap_size_t dtmf_offset = 0;
zap_analog_data_t *analog_data = zchan->span->signal_data;
zap_channel_t *closed_chan;
- uint32_t state_counter = 0, elapsed = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = 30000;
+ uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = 30000;
zap_sigmsg_t sig;
zap_status_t status;
zap_log(ZAP_LOG_DEBUG, "DTMF %s\n", dtmf + dtmf_offset);
if (zchan->state == ZAP_CHANNEL_STATE_DIALTONE) {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_COLLECT);
+ collecting = 1;
}
dtmf_offset = strlen(dtmf);
last_digit = elapsed;
+ sig.event_id = ZAP_SIGEVENT_COLLECTED_DIGIT;
+ sig.raw_data = dtmf;
+ if (analog_data->sig_cb(&sig) == ZAP_BREAK) {
+ collecting = 0;
+ }
}
}
- if (last_digit && ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) > analog_data->max_dialstr)) {
+ if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) > analog_data->max_dialstr))) {
zap_log(ZAP_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_IDLE);
last_digit = 0;
+ collecting = 0;
}
if (zap_channel_wait(zchan, &flags, interval * 2) != ZAP_SUCCESS) {
zap_log(ZAP_LOG_DEBUG, "ANALOG thread starting.\n");
- while(zap_test_flag(analog_data, ZAP_ANALOG_RUNNING)) {
+ while(zap_running() && zap_test_flag(analog_data, ZAP_ANALOG_RUNNING)) {
int waitms = 10;
zap_status_t status;
zap_mutex_t *mutex;
struct zap_span spans[ZAP_MAX_SPANS_INTERFACE];
uint32_t span_index;
+ uint32_t running;
} globals;
}
if (load_config() == ZAP_SUCCESS) {
+ globals.running = 1;
return ZAP_SUCCESS;
}
return ZAP_FAIL;
}
+uint32_t zap_running(void)
+{
+ return globals.running;
+}
zap_status_t zap_global_destroy(void)
time_end();
zap_span_close_all();
+ globals.running = 0;
+ zap_sleep(200);
for(i = 1; i <= globals.span_index; i++) {
zap_span_t *cur_span = &globals.spans[i];
break;
case ZAP_FAIL:
{
- zap_log(ZAP_LOG_DEBUG, "Event Failure!\n");
+ zap_log(ZAP_LOG_DEBUG, "Event Failure! %d\n", zap_running());
}
break;
default:
Q921Start(&isdn_data->q921);
- while(zap_test_flag(isdn_data, ZAP_ISDN_RUNNING)) {
+ while(zap_running() && zap_test_flag(isdn_data, ZAP_ISDN_RUNNING)) {
zap_wait_flag_t flags = ZAP_READ;
zap_status_t status = zap_channel_wait(isdn_data->dchan, &flags, 100);