summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configs/samples/dsp.conf.sample28
-rw-r--r--contrib/ast-db-manage/config/versions/ef7efc2d3964_ps_contacts_add_endpoint_and_modify_.py4
-rw-r--r--contrib/scripts/sip_to_pjsip/astconfigparser.py24
-rw-r--r--funcs/func_cdr.c10
-rw-r--r--include/asterisk/pbx.h12
-rw-r--r--main/dsp.c504
-rw-r--r--main/pbx.c12
-rw-r--r--main/pbx_functions.c19
-rw-r--r--main/rtp_engine.c14
9 files changed, 583 insertions, 44 deletions
diff --git a/configs/samples/dsp.conf.sample b/configs/samples/dsp.conf.sample
index 08c5a5715..55951582e 100644
--- a/configs/samples/dsp.conf.sample
+++ b/configs/samples/dsp.conf.sample
@@ -8,28 +8,28 @@
; DTMF Reverse Twist and Normal Twist is the difference in power between the row and column energies.
;
-; Normal Twist is where the Column energy is greater than the Row energy
-; Reverse Twist is where the Row energy is greater.
+; Normal Twist is where the row energy is greater than the column energy.
+; Reverse Twist is where the column energy is greater.
;
; Power level difference between frequencies for different Administrations/RPOAs
-; Power Gain equiv
-; normal reverse dB's
-; AT&T(default) 6.31 2.51 8dB(normal), 4dB(reverse)
-; NTT 3.16 3.16 Max. 5dB
-; Danish 3.98 3.98 Max. 6dB
-; Australian 10.0 10.0 Max. 10dB
-; Brazilian 7.94 7.94 Max. 9dB
-; ETSI 3.98 3.98 Max. 6dB
+; Power Gain equiv
+; normal reverse dB's
+; AT&T(default) 6.31 2.51 8dB(normal), 4dB(reverse)
+; NTT 3.16 3.16 Max. 5dB
+; Danish 3.98 3.98 Max. 6dB
+; Australian 10.0 10.0 Max. 10dB
+; Brazilian 7.94 7.94 Max. 9dB
+; ETSI 3.98 3.98 Max. 6dB
;previous version compatible AT&T values
; RADIO_RELAX disabled, and relaxdtmf=no
-; 6.30 2.50 7.99dB(normal), 3.98dB(reverse)
+; 6.30 2.50 7.99dB(normal), 3.98dB(reverse)
; RADIO_RELAX disabled, and relaxdtmf=yes
-; 6.30 4.00 7.99dB(normal), 6.02dB(reverse)
+; 6.30 4.00 7.99dB(normal), 6.02dB(reverse)
; RADIO_RELAX enabled, and relaxdtmf=no
-; 6.30 2.50 7.99dB(normal), 3.984dB(reverse)
+; 6.30 2.50 7.99dB(normal), 3.984dB(reverse)
; RADIO_RELAX enabled, and relaxdtmf=yes
-; 6.30 6.50 7.99dB(normal), 8.13dB(reverse)
+; 6.30 6.50 7.99dB(normal), 8.13dB(reverse)
;If you don't know what these mean, don't change them.
;dtmf_normal_twist=6.31
diff --git a/contrib/ast-db-manage/config/versions/ef7efc2d3964_ps_contacts_add_endpoint_and_modify_.py b/contrib/ast-db-manage/config/versions/ef7efc2d3964_ps_contacts_add_endpoint_and_modify_.py
index ff1834329..43d4028f2 100644
--- a/contrib/ast-db-manage/config/versions/ef7efc2d3964_ps_contacts_add_endpoint_and_modify_.py
+++ b/contrib/ast-db-manage/config/versions/ef7efc2d3964_ps_contacts_add_endpoint_and_modify_.py
@@ -24,10 +24,10 @@ def upgrade():
else:
op.execute('ALTER TABLE ps_contacts ALTER COLUMN expiration_time TYPE BIGINT USING expiration_time::bigint')
- op.create_index('ps_contacts_qualifyfreq_exptime', 'ps_contacts', ['qualify_frequency', 'expiration_time'])
+ op.create_index('ps_contacts_qualifyfreq_exp', 'ps_contacts', ['qualify_frequency', 'expiration_time'])
op.create_index('ps_aors_qualifyfreq_contact', 'ps_aors', ['qualify_frequency', 'contact'])
def downgrade():
op.drop_index('ps_aors_qualifyfreq_contact')
- op.drop_index('ps_contacts_qualifyfreq_exptime')
+ op.drop_index('ps_contacts_qualifyfreq_exp')
op.drop_column('ps_contacts', 'endpoint')
op.alter_column('ps_contacts', 'expiration_time', type_=sa.String(40))
diff --git a/contrib/scripts/sip_to_pjsip/astconfigparser.py b/contrib/scripts/sip_to_pjsip/astconfigparser.py
index b207b0d7c..46f4fb484 100644
--- a/contrib/scripts/sip_to_pjsip/astconfigparser.py
+++ b/contrib/scripts/sip_to_pjsip/astconfigparser.py
@@ -1,3 +1,10 @@
+"""
+Copyright (C) 2016, Digium, Inc.
+
+This program is free software, distributed under the terms of
+the GNU General Public License Version 2.
+"""
+
import re
import itertools
@@ -44,6 +51,12 @@ class Section(MultiOrderedDict):
"""
return cmp(self.id, other.id)
+ def __eq__(self, other):
+ """
+ Use self.id as means of determining equality
+ """
+ return self.id == other.id
+
def get(self, key, from_self=True, from_templates=True,
from_defaults=True):
"""
@@ -184,9 +197,14 @@ def remove_comment(line, is_comment):
# otherwise it was an embedded comment so combine
return ''.join([part[0].strip(), ' ', line]).rstrip(), False
- # check for eol comment
- return line.partition(COMMENT)[0].strip(), False
+ # find the first occurence of a comment that is not escaped
+ match = re.match(r'.*?([^\\];)', line)
+
+ if match:
+ # the end of where the real string is is where the comment starts
+ line = line[0:(match.end()-1)]
+ return line.replace("\\", "").strip(), False
def try_include(line):
"""
@@ -224,7 +242,7 @@ def try_section(line):
def try_option(line):
"""Parses the line as an option, returning the key/value pair."""
- data = re.split('=>?', line)
+ data = re.split('=>?', line, 1)
# should split in two (key/val), but either way use first two elements
return data[0].rstrip(), data[1].lstrip()
diff --git a/funcs/func_cdr.c b/funcs/func_cdr.c
index dc865934f..e67bca318 100644
--- a/funcs/func_cdr.c
+++ b/funcs/func_cdr.c
@@ -223,9 +223,11 @@ STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_prop_write_message_type);
static struct timeval cdr_retrieve_time(struct ast_channel *chan, const char *time_name)
{
- struct timeval time;
+ struct timeval time = { 0 };
char *value = NULL;
char tempbuf[128];
+ long int tv_sec;
+ long int tv_usec;
if (ast_strlen_zero(ast_channel_name(chan))) {
/* Format request on a dummy channel */
@@ -234,7 +236,11 @@ static struct timeval cdr_retrieve_time(struct ast_channel *chan, const char *ti
ast_cdr_getvar(ast_channel_name(chan), time_name, tempbuf, sizeof(tempbuf));
}
- if (sscanf(tempbuf, "%ld.%ld", &time.tv_sec, &time.tv_usec) != 2) {
+ /* time.tv_usec is suseconds_t, which could be int or long */
+ if (sscanf(tempbuf, "%ld.%ld", &tv_sec, &tv_usec) == 2) {
+ time.tv_sec = tv_sec;
+ time.tv_usec = tv_usec;
+ } else {
ast_log(AST_LOG_WARNING, "Failed to fully extract '%s' from CDR\n", time_name);
}
diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h
index d722e123f..1fc8df8c9 100644
--- a/include/asterisk/pbx.h
+++ b/include/asterisk/pbx.h
@@ -1598,6 +1598,18 @@ void pbx_live_dangerously(int new_live_dangerously);
*/
int ast_thread_inhibit_escalations(void);
+/*!
+ * \brief Swap the current thread escalation inhibit setting.
+ * \since 11.24.0
+ *
+ * \param inhibit New setting. Non-zero to inhibit.
+ *
+ * \retval 1 if dangerous function execution was inhibited.
+ * \retval 0 if dangerous function execution was allowed.
+ * \retval -1 on error.
+ */
+int ast_thread_inhibit_escalations_swap(int inhibit);
+
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
diff --git a/main/dsp.c b/main/dsp.c
index 087416358..840a839bd 100644
--- a/main/dsp.c
+++ b/main/dsp.c
@@ -68,6 +68,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/utils.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
+#include "asterisk/test.h"
/*! Number of goertzels for progress detect */
enum gsamp_size {
@@ -171,8 +172,7 @@ enum gsamp_thresh {
*/
#define DTMF_THRESHOLD 8.0e7
-#define FAX_THRESHOLD 8.0e7
-#define FAX_2ND_HARMONIC 2.0 /* 4dB */
+#define TONE_THRESHOLD 7.8e7
#define DEF_DTMF_NORMAL_TWIST 6.31 /* 8.0dB */
#define DEF_RELAX_DTMF_NORMAL_TWIST 6.31 /* 8.0dB */
@@ -187,8 +187,6 @@ enum gsamp_thresh {
#define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */
#define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */
-#define DTMF_2ND_HARMONIC_ROW (relax ? 1.7 : 2.5) /* 4dB normal */
-#define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */
#define DTMF_TO_TOTAL_ENERGY 42.0
#define BELL_MF_THRESHOLD 1.6e9
@@ -203,7 +201,7 @@ enum gsamp_thresh {
* followed by a 3 second silent (2100 Hz OFF) period.
*/
#define FAX_TONE_CNG_FREQ 1100
-#define FAX_TONE_CNG_DURATION 500
+#define FAX_TONE_CNG_DURATION 500 /* ms */
#define FAX_TONE_CNG_DB 16
/* This signal may be sent by the Terminating FAX machine anywhere between
@@ -211,7 +209,7 @@ enum gsamp_thresh {
* of a 2100 Hz tone that is from 2.6 to 4 seconds in duration.
*/
#define FAX_TONE_CED_FREQ 2100
-#define FAX_TONE_CED_DURATION 2600
+#define FAX_TONE_CED_DURATION 2600 /* ms */
#define FAX_TONE_CED_DB 16
#define DEFAULT_SAMPLE_RATE 8000
@@ -241,9 +239,13 @@ static const int DEFAULT_SILENCE_THRESHOLD = 256;
#define CONFIG_FILE_NAME "dsp.conf"
typedef struct {
+ /*! The previous previous sample calculation (No binary point just plain int) */
int v2;
+ /*! The previous sample calculation (No binary point just plain int) */
int v3;
+ /*! v2 and v3 power of two exponent to keep value in int range */
int chunky;
+ /*! 15 bit fixed point goertzel coefficient = 2 * cos(2 * pi * freq / sample_rate) */
int fac;
} goertzel_state_t;
@@ -329,12 +331,22 @@ static inline void goertzel_sample(goertzel_state_t *s, short sample)
{
int v1;
+ /*
+ * Shift previous values so
+ * v1 is previous previous value
+ * v2 is previous value
+ * until the new v3 is calculated.
+ */
v1 = s->v2;
s->v2 = s->v3;
+ /* Discard the binary fraction introduced by s->fac */
s->v3 = (s->fac * s->v2) >> 15;
+ /* Scale sample to match previous values */
s->v3 = s->v3 - v1 + (sample >> s->chunky);
- if (abs(s->v3) > 32768) {
+
+ if (abs(s->v3) > (1 << 15)) {
+ /* The result is now too large so increase the chunky power. */
s->chunky++;
s->v3 = s->v3 >> 1;
s->v2 = s->v2 >> 1;
@@ -344,21 +356,26 @@ static inline void goertzel_sample(goertzel_state_t *s, short sample)
static inline float goertzel_result(goertzel_state_t *s)
{
goertzel_result_t r;
+
r.value = (s->v3 * s->v3) + (s->v2 * s->v2);
r.value -= ((s->v2 * s->v3) >> 15) * s->fac;
+ /*
+ * We have to double the exponent because we multiplied the
+ * previous sample calculation values together.
+ */
r.power = s->chunky * 2;
return (float)r.value * (float)(1 << r.power);
}
static inline void goertzel_init(goertzel_state_t *s, float freq, unsigned int sample_rate)
{
- s->v2 = s->v3 = s->chunky = 0.0;
+ s->v2 = s->v3 = s->chunky = 0;
s->fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / sample_rate));
}
static inline void goertzel_reset(goertzel_state_t *s)
{
- s->v2 = s->v3 = s->chunky = 0.0;
+ s->v2 = s->v3 = s->chunky = 0;
}
typedef struct {
@@ -581,10 +598,11 @@ static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp
tone_energy *= 2.0;
s->energy *= s->block_size;
- ast_debug(10, "tone %d, Ew=%.2E, Et=%.2E, s/n=%10.2f\n", s->freq, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
+ ast_debug(10, "%d Hz tone %2d Ew=%.4E, Et=%.4E, s/n=%10.2f\n", s->freq, s->hit_count, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
hit = 0;
- if (tone_energy > s->energy * s->threshold) {
- ast_debug(10, "Hit! count=%d\n", s->hit_count);
+ if (TONE_THRESHOLD <= tone_energy
+ && tone_energy > s->energy * s->threshold) {
+ ast_debug(10, "%d Hz tone Hit! %2d Ew=%.4E, Et=%.4E, s/n=%10.2f\n", s->freq, s->hit_count, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
hit = 1;
}
@@ -603,7 +621,7 @@ static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp
}
if (s->hit_count == s->hits_required) {
- ast_debug(1, "%d Hz done detected\n", s->freq);
+ ast_debug(1, "%d Hz tone detected\n", s->freq);
res = 1;
}
@@ -716,6 +734,10 @@ static int dtmf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp
best_col = i;
}
}
+ ast_debug(10, "DTMF best '%c' Erow=%.4E Ecol=%.4E Erc=%.4E Et=%.4E\n",
+ dtmf_positions[(best_row << 2) + best_col],
+ row_energy[best_row], col_energy[best_col],
+ row_energy[best_row] + col_energy[best_col], s->td.dtmf.energy);
hit = 0;
/* Basic signal level test and the twist test */
if (row_energy[best_row] >= DTMF_THRESHOLD &&
@@ -736,6 +758,7 @@ static int dtmf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp
(row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY * s->td.dtmf.energy) {
/* Got a hit */
hit = dtmf_positions[(best_row << 2) + best_col];
+ ast_debug(10, "DTMF hit '%c'\n", hit);
}
}
@@ -1622,7 +1645,7 @@ done:
for (x = 0; x < len; x++) {
odata[x] = AST_LIN2MU((unsigned short) shortdata[x]);
}
- } else if (ast_format_cmp(af->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
+ } else if (ast_format_cmp(af->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
for (x = 0; x < len; x++) {
odata[x] = AST_LIN2A((unsigned short) shortdata[x]);
}
@@ -1929,9 +1952,460 @@ int ast_dsp_get_threshold_from_settings(enum threshold which)
return thresholds[which];
}
+#ifdef TEST_FRAMEWORK
+static void test_tone_sample_gen(short *slin_buf, int samples, int rate, int freq, short amplitude)
+{
+ int idx;
+ double sample_step = 2.0 * M_PI * freq / rate;/* radians per step */
+
+ for (idx = 0; idx < samples; ++idx) {
+ slin_buf[idx] = amplitude * sin(sample_step * idx);
+ }
+}
+#endif
+
+#ifdef TEST_FRAMEWORK
+static void test_tone_sample_gen_add(short *slin_buf, int samples, int rate, int freq, short amplitude)
+{
+ int idx;
+ double sample_step = 2.0 * M_PI * freq / rate;/* radians per step */
+
+ for (idx = 0; idx < samples; ++idx) {
+ slin_buf[idx] += amplitude * sin(sample_step * idx);
+ }
+}
+#endif
+
+#ifdef TEST_FRAMEWORK
+static void test_dual_sample_gen(short *slin_buf, int samples, int rate, int f1, short a1, int f2, short a2)
+{
+ test_tone_sample_gen(slin_buf, samples, rate, f1, a1);
+ test_tone_sample_gen_add(slin_buf, samples, rate, f2, a2);
+}
+#endif
+
+#ifdef TEST_FRAMEWORK
+#define TONE_AMPLITUDE_MAX 0x7fff /* Max signed linear amplitude */
+#define TONE_AMPLITUDE_MIN 80 /* Min signed linear amplitude detectable */
+
+static int test_tone_amplitude_sweep(struct ast_test *test, struct ast_dsp *dsp, tone_detect_state_t *tone_state)
+{
+ short slin_buf[tone_state->block_size];
+ int result;
+ int idx;
+ struct {
+ short amp_val;
+ int detect;
+ } amp_tests[] = {
+ { .amp_val = TONE_AMPLITUDE_MAX, .detect = 1, },
+ { .amp_val = 10000, .detect = 1, },
+ { .amp_val = 1000, .detect = 1, },
+ { .amp_val = 100, .detect = 1, },
+ { .amp_val = TONE_AMPLITUDE_MIN, .detect = 1, },
+ { .amp_val = 75, .detect = 0, },
+ { .amp_val = 10, .detect = 0, },
+ { .amp_val = 1, .detect = 0, },
+ };
+
+ result = 0;
+
+ for (idx = 0; idx < ARRAY_LEN(amp_tests); ++idx) {
+ int detected;
+ int duration;
+
+ ast_debug(1, "Test %d Hz at amplitude %d\n",
+ tone_state->freq, amp_tests[idx].amp_val);
+ test_tone_sample_gen(slin_buf, tone_state->block_size, DEFAULT_SAMPLE_RATE,
+ tone_state->freq, amp_tests[idx].amp_val);
+
+ detected = 0;
+ for (duration = 0; !detected && duration < tone_state->hits_required + 3; ++duration) {
+ detected = tone_detect(dsp, tone_state, slin_buf, tone_state->block_size) ? 1 : 0;
+ }
+ if (amp_tests[idx].detect != detected) {
+ /*
+ * Both messages are needed. ast_debug for when figuring out
+ * what went wrong and the test update for normal output before
+ * you start debugging. The different logging methods are not
+ * synchronized.
+ */
+ ast_debug(1,
+ "Test %d Hz at amplitude %d failed. Detected: %s\n",
+ tone_state->freq, amp_tests[idx].amp_val,
+ detected ? "yes" : "no");
+ ast_test_status_update(test,
+ "Test %d Hz at amplitude %d failed. Detected: %s\n",
+ tone_state->freq, amp_tests[idx].amp_val,
+ detected ? "yes" : "no");
+ result = -1;
+ }
+ tone_state->hit_count = 0;
+ }
+
+ return result;
+}
+#endif
+
+#ifdef TEST_FRAMEWORK
+static int test_dtmf_amplitude_sweep(struct ast_test *test, struct ast_dsp *dsp, int digit_index)
+{
+ short slin_buf[DTMF_GSIZE];
+ int result;
+ int row;
+ int column;
+ int idx;
+ struct {
+ short amp_val;
+ int digit;
+ } amp_tests[] = {
+ /*
+ * XXX Since there is no current DTMF level detection issue. This test
+ * just checks the current detection levels.
+ */
+ { .amp_val = TONE_AMPLITUDE_MAX/2, .digit = dtmf_positions[digit_index], },
+ { .amp_val = 10000, .digit = dtmf_positions[digit_index], },
+ { .amp_val = 1000, .digit = dtmf_positions[digit_index], },
+ { .amp_val = 500, .digit = dtmf_positions[digit_index], },
+ { .amp_val = 250, .digit = dtmf_positions[digit_index], },
+ { .amp_val = 200, .digit = dtmf_positions[digit_index], },
+ { .amp_val = 180, .digit = dtmf_positions[digit_index], },
+ /* Various digits detect and not detect in this range */
+ { .amp_val = 170, .digit = 0, },
+ { .amp_val = 100, .digit = 0, },
+ /*
+ * Amplitudes below TONE_AMPLITUDE_MIN start having questionable detection
+ * over quantization and background noise.
+ */
+ { .amp_val = TONE_AMPLITUDE_MIN, .digit = 0, },
+ { .amp_val = 75, .digit = 0, },
+ { .amp_val = 10, .digit = 0, },
+ { .amp_val = 1, .digit = 0, },
+ };
+
+ row = (digit_index >> 2) & 0x03;
+ column = digit_index & 0x03;
+
+ result = 0;
+
+ for (idx = 0; idx < ARRAY_LEN(amp_tests); ++idx) {
+ int digit;
+ int duration;
+
+ ast_debug(1, "Test '%c' at amplitude %d\n",
+ dtmf_positions[digit_index], amp_tests[idx].amp_val);
+ test_dual_sample_gen(slin_buf, ARRAY_LEN(slin_buf), DEFAULT_SAMPLE_RATE,
+ (int) dtmf_row[row], amp_tests[idx].amp_val,
+ (int) dtmf_col[column], amp_tests[idx].amp_val);
+
+ digit = 0;
+ for (duration = 0; !digit && duration < 3; ++duration) {
+ digit = dtmf_detect(dsp, &dsp->digit_state, slin_buf, ARRAY_LEN(slin_buf),
+ 0, 0);
+ }
+ if (amp_tests[idx].digit != digit) {
+ /*
+ * Both messages are needed. ast_debug for when figuring out
+ * what went wrong and the test update for normal output before
+ * you start debugging. The different logging methods are not
+ * synchronized.
+ */
+ ast_debug(1,
+ "Test '%c' at amplitude %d failed. Detected Digit: '%c'\n",
+ dtmf_positions[digit_index], amp_tests[idx].amp_val,
+ digit ?: ' ');
+ ast_test_status_update(test,
+ "Test '%c' at amplitude %d failed. Detected Digit: '%c'\n",
+ dtmf_positions[digit_index], amp_tests[idx].amp_val,
+ digit ?: ' ');
+ result = -1;
+ }
+ ast_dsp_digitreset(dsp);
+ }
+
+ return result;
+}
+#endif
+
+#ifdef TEST_FRAMEWORK
+static int test_dtmf_twist_sweep(struct ast_test *test, struct ast_dsp *dsp, int digit_index)
+{
+ short slin_buf[DTMF_GSIZE];
+ int result;
+ int row;
+ int column;
+ int idx;
+ struct {
+ short amp_row;
+ short amp_col;
+ int digit;
+ } twist_tests[] = {
+ /*
+ * XXX Since there is no current DTMF twist detection issue. This test
+ * just checks the current detection levels.
+ *
+ * Normal twist has the column higher than the row amplitude.
+ * Reverse twist is the other way.
+ */
+ { .amp_row = 1000 + 1800, .amp_col = 1000 + 0, .digit = 0, },
+ { .amp_row = 1000 + 1700, .amp_col = 1000 + 0, .digit = 0, },
+ /* Various digits detect and not detect in this range */
+ { .amp_row = 1000 + 1400, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
+ { .amp_row = 1000 + 1300, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
+ { .amp_row = 1000 + 1200, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
+ { .amp_row = 1000 + 1100, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
+ { .amp_row = 1000 + 1000, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
+ { .amp_row = 1000 + 100, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
+ { .amp_row = 1000 + 0, .amp_col = 1000 + 100, .digit = dtmf_positions[digit_index], },
+ { .amp_row = 1000 + 0, .amp_col = 1000 + 200, .digit = dtmf_positions[digit_index], },
+ { .amp_row = 1000 + 0, .amp_col = 1000 + 300, .digit = dtmf_positions[digit_index], },
+ { .amp_row = 1000 + 0, .amp_col = 1000 + 400, .digit = dtmf_positions[digit_index], },
+ { .amp_row = 1000 + 0, .amp_col = 1000 + 500, .digit = dtmf_positions[digit_index], },
+ { .amp_row = 1000 + 0, .amp_col = 1000 + 550, .digit = dtmf_positions[digit_index], },
+ /* Various digits detect and not detect in this range */
+ { .amp_row = 1000 + 0, .amp_col = 1000 + 650, .digit = 0, },
+ { .amp_row = 1000 + 0, .amp_col = 1000 + 700, .digit = 0, },
+ { .amp_row = 1000 + 0, .amp_col = 1000 + 800, .digit = 0, },
+ };
+ float save_normal_twist;
+ float save_reverse_twist;
+
+ save_normal_twist = dtmf_normal_twist;
+ save_reverse_twist = dtmf_reverse_twist;
+ dtmf_normal_twist = DEF_DTMF_NORMAL_TWIST;
+ dtmf_reverse_twist = DEF_DTMF_REVERSE_TWIST;
+
+ row = (digit_index >> 2) & 0x03;
+ column = digit_index & 0x03;
+
+ result = 0;
+
+ for (idx = 0; idx < ARRAY_LEN(twist_tests); ++idx) {
+ int digit;
+ int duration;
+
+ ast_debug(1, "Test '%c' twist row %d col %d amplitudes\n",
+ dtmf_positions[digit_index],
+ twist_tests[idx].amp_row, twist_tests[idx].amp_col);
+ test_dual_sample_gen(slin_buf, ARRAY_LEN(slin_buf), DEFAULT_SAMPLE_RATE,
+ (int) dtmf_row[row], twist_tests[idx].amp_row,
+ (int) dtmf_col[column], twist_tests[idx].amp_col);
+
+ digit = 0;
+ for (duration = 0; !digit && duration < 3; ++duration) {
+ digit = dtmf_detect(dsp, &dsp->digit_state, slin_buf, ARRAY_LEN(slin_buf),
+ 0, 0);
+ }
+ if (twist_tests[idx].digit != digit) {
+ /*
+ * Both messages are needed. ast_debug for when figuring out
+ * what went wrong and the test update for normal output before
+ * you start debugging. The different logging methods are not
+ * synchronized.
+ */
+ ast_debug(1,
+ "Test '%c' twist row %d col %d amplitudes failed. Detected Digit: '%c'\n",
+ dtmf_positions[digit_index],
+ twist_tests[idx].amp_row, twist_tests[idx].amp_col,
+ digit ?: ' ');
+ ast_test_status_update(test,
+ "Test '%c' twist row %d col %d amplitudes failed. Detected Digit: '%c'\n",
+ dtmf_positions[digit_index],
+ twist_tests[idx].amp_row, twist_tests[idx].amp_col,
+ digit ?: ' ');
+ result = -1;
+ }
+ ast_dsp_digitreset(dsp);
+ }
+
+ dtmf_normal_twist = save_normal_twist;
+ dtmf_reverse_twist = save_reverse_twist;
+
+ return result;
+}
+#endif
+
+#ifdef TEST_FRAMEWORK
+static int test_tone_freq_sweep(struct ast_test *test, struct ast_dsp *dsp, tone_detect_state_t *tone_state, short amplitude)
+{
+ short slin_buf[tone_state->block_size];
+ int result;
+ int freq;
+ int lower_freq;
+ int upper_freq;
+
+ /* Calculate detection frequency range */
+ lower_freq = tone_state->freq - 4;
+ upper_freq = tone_state->freq + 4;
+
+ result = 0;
+
+ /* Sweep frequencies loop. */
+ for (freq = 100; freq <= 3500; freq += 1) {
+ int detected;
+ int duration;
+ int expect_detection;
+
+ if (freq == tone_state->freq) {
+ /* This case is done by the amplitude sweep. */
+ continue;
+ }
+
+ expect_detection = (lower_freq <= freq && freq <= upper_freq) ? 1 : 0;
+
+ ast_debug(1, "Test %d Hz detection given %d Hz tone at amplitude %d. Range:%d-%d Expect detect: %s\n",
+ tone_state->freq, freq, amplitude, lower_freq, upper_freq,
+ expect_detection ? "yes" : "no");
+ test_tone_sample_gen(slin_buf, tone_state->block_size, DEFAULT_SAMPLE_RATE, freq,
+ amplitude);
+
+ detected = 0;
+ for (duration = 0; !detected && duration < tone_state->hits_required + 3; ++duration) {
+ detected = tone_detect(dsp, tone_state, slin_buf, tone_state->block_size) ? 1 : 0;
+ }
+ if (expect_detection != detected) {
+ /*
+ * Both messages are needed. ast_debug for when figuring out
+ * what went wrong and the test update for normal output before
+ * you start debugging. The different logging methods are not
+ * synchronized.
+ */
+ ast_debug(1,
+ "Test %d Hz detection given %d Hz tone at amplitude %d failed. Range:%d-%d Detected: %s\n",
+ tone_state->freq, freq, amplitude, lower_freq, upper_freq,
+ detected ? "yes" : "no");
+ ast_test_status_update(test,
+ "Test %d Hz detection given %d Hz tone at amplitude %d failed. Range:%d-%d Detected: %s\n",
+ tone_state->freq, freq, amplitude, lower_freq, upper_freq,
+ detected ? "yes" : "no");
+ result = -1;
+ }
+ tone_state->hit_count = 0;
+ }
+
+ return result;
+}
+#endif
+
+#ifdef TEST_FRAMEWORK
+AST_TEST_DEFINE(test_dsp_fax_detect)
+{
+ struct ast_dsp *dsp;
+ enum ast_test_result_state result;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "fax";
+ info->category = "/main/dsp/";
+ info->summary = "DSP fax tone detect unit test";
+ info->description =
+ "Tests fax tone detection code.";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ dsp = ast_dsp_new();
+ if (!dsp) {
+ return AST_TEST_FAIL;
+ }
+
+ result = AST_TEST_PASS;
+
+ /* Test CNG tone amplitude detection */
+ if (test_tone_amplitude_sweep(test, dsp, &dsp->cng_tone_state)) {
+ result = AST_TEST_FAIL;
+ }
+
+ /* Test CED tone amplitude detection */
+ if (test_tone_amplitude_sweep(test, dsp, &dsp->ced_tone_state)) {
+ result = AST_TEST_FAIL;
+ }
+
+ /* Test CNG tone frequency detection */
+ if (test_tone_freq_sweep(test, dsp, &dsp->cng_tone_state, TONE_AMPLITUDE_MAX)) {
+ result = AST_TEST_FAIL;
+ }
+ if (test_tone_freq_sweep(test, dsp, &dsp->cng_tone_state, TONE_AMPLITUDE_MIN)) {
+ result = AST_TEST_FAIL;
+ }
+
+ /* Test CED tone frequency detection */
+ if (test_tone_freq_sweep(test, dsp, &dsp->ced_tone_state, TONE_AMPLITUDE_MAX)) {
+ result = AST_TEST_FAIL;
+ }
+ if (test_tone_freq_sweep(test, dsp, &dsp->ced_tone_state, TONE_AMPLITUDE_MIN)) {
+ result = AST_TEST_FAIL;
+ }
+
+ ast_dsp_free(dsp);
+ return result;
+}
+#endif
+
+#ifdef TEST_FRAMEWORK
+AST_TEST_DEFINE(test_dsp_dtmf_detect)
+{
+ int idx;
+ struct ast_dsp *dsp;
+ enum ast_test_result_state result;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "dtmf";
+ info->category = "/main/dsp/";
+ info->summary = "DSP DTMF detect unit test";
+ info->description =
+ "Tests DTMF detection code.";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ dsp = ast_dsp_new();
+ if (!dsp) {
+ return AST_TEST_FAIL;
+ }
+
+ result = AST_TEST_PASS;
+
+ for (idx = 0; dtmf_positions[idx]; ++idx) {
+ if (test_dtmf_amplitude_sweep(test, dsp, idx)) {
+ result = AST_TEST_FAIL;
+ }
+ }
+
+ for (idx = 0; dtmf_positions[idx]; ++idx) {
+ if (test_dtmf_twist_sweep(test, dsp, idx)) {
+ result = AST_TEST_FAIL;
+ }
+ }
+
+ ast_dsp_free(dsp);
+ return result;
+}
+#endif
+
+#ifdef TEST_FRAMEWORK
+static void test_dsp_shutdown(void)
+{
+ AST_TEST_UNREGISTER(test_dsp_fax_detect);
+ AST_TEST_UNREGISTER(test_dsp_dtmf_detect);
+}
+#endif
+
int ast_dsp_init(void)
{
- return _dsp_init(0);
+ int res = _dsp_init(0);
+
+#ifdef TEST_FRAMEWORK
+ if (!res) {
+ AST_TEST_REGISTER(test_dsp_fax_detect);
+ AST_TEST_REGISTER(test_dsp_dtmf_detect);
+
+ ast_register_cleanup(test_dsp_shutdown);
+ }
+#endif
+ return res;
}
int ast_dsp_reload(void)
diff --git a/main/pbx.c b/main/pbx.c
index 5bafee337..822336d36 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -7095,13 +7095,25 @@ static int ast_add_extension2_lockopt(struct ast_context *con,
/* If we are adding a hint evalulate in variables and global variables */
if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') {
+ int inhibited;
struct ast_channel *c = ast_dummy_channel_alloc();
if (c) {
ast_channel_exten_set(c, extension);
ast_channel_context_set(c, con->name);
}
+
+ /*
+ * We can allow dangerous functions when adding a hint since
+ * altering dialplan is itself a privileged activity. Otherwise,
+ * we could never execute dangerous functions.
+ */
+ inhibited = ast_thread_inhibit_escalations_swap(0);
pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
+ if (0 < inhibited) {
+ ast_thread_inhibit_escalations();
+ }
+
application = expand_buf;
if (c) {
ast_channel_unref(c);
diff --git a/main/pbx_functions.c b/main/pbx_functions.c
index bc738b043..558be461f 100644
--- a/main/pbx_functions.c
+++ b/main/pbx_functions.c
@@ -482,7 +482,6 @@ int ast_thread_inhibit_escalations(void)
thread_inhibit_escalations = ast_threadstorage_get(
&thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
-
if (thread_inhibit_escalations == NULL) {
ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n");
return -1;
@@ -492,6 +491,23 @@ int ast_thread_inhibit_escalations(void)
return 0;
}
+int ast_thread_inhibit_escalations_swap(int inhibit)
+{
+ int *thread_inhibit_escalations;
+ int orig;
+
+ thread_inhibit_escalations = ast_threadstorage_get(
+ &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
+ if (thread_inhibit_escalations == NULL) {
+ ast_log(LOG_ERROR, "Error swapping privilege escalations inhibit for current thread\n");
+ return -1;
+ }
+
+ orig = *thread_inhibit_escalations;
+ *thread_inhibit_escalations = !!inhibit;
+ return orig;
+}
+
/*!
* \brief Indicates whether the current thread inhibits the execution of
* dangerous functions.
@@ -505,7 +521,6 @@ static int thread_inhibits_escalations(void)
thread_inhibit_escalations = ast_threadstorage_get(
&thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
-
if (thread_inhibit_escalations == NULL) {
ast_log(LOG_ERROR, "Error checking thread's ability to run dangerous functions\n");
/* On error, assume that we are inhibiting */
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index 8d46bfdcc..50398a5c6 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -737,6 +737,7 @@ int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs,
} else {
new_type->format = t->payload_type.format;
}
+
if (new_type->format) {
/* SDP parsing automatically increases the reference count */
new_type->format = ast_format_parse_sdp_fmtp(new_type->format, "");
@@ -1773,7 +1774,11 @@ static void add_static_payload(int map, struct ast_format *format, int rtp_code)
int x;
struct ast_rtp_payload_type *type;
- ast_assert(map < ARRAY_LEN(static_RTP_PT));
+ /*
+ * ARRAY_LEN's result is cast to an int so 'map' is not autocast to a size_t,
+ * which if negative would cause an assertion.
+ */
+ ast_assert(map < (int)ARRAY_LEN(static_RTP_PT));
ast_rwlock_wrlock(&static_RTP_PT_lock);
if (map < 0) {
@@ -1784,6 +1789,7 @@ static void add_static_payload(int map, struct ast_format *format, int rtp_code)
break;
}
}
+
if (map < 0) {
if (format) {
ast_log(LOG_WARNING, "No Dynamic RTP mapping available for format %s\n",
@@ -1815,14 +1821,10 @@ static void add_static_payload(int map, struct ast_format *format, int rtp_code)
int ast_rtp_engine_load_format(struct ast_format *format)
{
- char *codec_name = ast_strdupa(ast_format_get_name(format));
-
- codec_name = ast_str_to_upper(codec_name);
-
set_next_mime_type(format,
0,
ast_codec_media_type2str(ast_format_get_type(format)),
- codec_name,
+ ast_format_get_codec_name(format),
ast_format_get_sample_rate(format));
add_static_payload(-1, format, 0);