summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitreview1
-rw-r--r--addons/ooh323c/src/ooCalls.c2
-rw-r--r--configs/samples/features.conf.sample4
-rw-r--r--include/asterisk/cli.h26
-rw-r--r--main/asterisk.c258
-rw-r--r--main/cli.c78
-rw-r--r--res/ari/resource_bridges.c13
-rw-r--r--res/res_rtp_asterisk.c49
-rw-r--r--tests/test_substitution.c19
-rw-r--r--third-party/pjproject/patches/0040-183_without_to_tag.patch17
10 files changed, 266 insertions, 201 deletions
diff --git a/.gitreview b/.gitreview
index f9ef0502a..32bad967c 100644
--- a/.gitreview
+++ b/.gitreview
@@ -2,3 +2,4 @@
host=gerrit.asterisk.org
port=29418
project=asterisk.git
+defaultbranch=15
diff --git a/addons/ooh323c/src/ooCalls.c b/addons/ooh323c/src/ooCalls.c
index 26dc63eab..c920e6a23 100644
--- a/addons/ooh323c/src/ooCalls.c
+++ b/addons/ooh323c/src/ooCalls.c
@@ -29,6 +29,7 @@
#include "ooGkClient.h"
#include "ooh323ep.h"
#include "ooCalls.h"
+#include "ooCmdChannel.h"
/** Global endpoint structure */
extern OOH323EndPoint gH323ep;
@@ -173,6 +174,7 @@ OOH323CallData* ooCreateCall(char* type, char*callToken)
call->msdRetries = 0;
call->pFastStartRes = NULL;
call->usrData = NULL;
+ ooCreateCallCmdConnection(call);
OOTRACEINFO3("Created a new call (%s, %s)\n", call->callType,
call->callToken);
/* Add new call to calllist */
diff --git a/configs/samples/features.conf.sample b/configs/samples/features.conf.sample
index 223d69358..5806e4c04 100644
--- a/configs/samples/features.conf.sample
+++ b/configs/samples/features.conf.sample
@@ -72,8 +72,8 @@
; means run the application on the opposite channel from the one that
; has activated the feature.
; ActivatedBy -> ActivatedBy is no longer honored. The feature is activated by which
-; channel DYNAMIC_FEATURES includes the feature is on. Use predial
-; to set different values of DYNAMIC_FEATURES on the channels.
+; channel DYNAMIC_FEATURES includes the feature is on. Use a pre-dial
+; handler to set different values for DYNAMIC_FEATURES on the channels.
; Historic values are: "caller", "callee", and "both".
; Application -> This is the application to execute.
; AppArguments -> These are the arguments to be passed into the application. If you need
diff --git a/include/asterisk/cli.h b/include/asterisk/cli.h
index 3ed88eb61..c75fc295d 100644
--- a/include/asterisk/cli.h
+++ b/include/asterisk/cli.h
@@ -287,6 +287,9 @@ int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len);
* Useful for readline, that's about it
* \retval 0 on success
* \retval -1 on failure
+ *
+ * Only call this function to proxy the CLI generator to
+ * another.
*/
char *ast_cli_generator(const char *, const char *, int);
@@ -302,6 +305,9 @@ int ast_cli_generatornummatches(const char *, const char *);
* Subsequent entries are all possible values, followed by a NULL.
* All strings and the array itself are malloc'ed and must be freed
* by the caller.
+ *
+ * \warning This function cannot be called recursively so it will always
+ * fail if called from a CLI_GENERATE callback.
*/
char **ast_cli_completion_matches(const char *, const char *);
@@ -323,10 +329,30 @@ char **ast_cli_completion_matches(const char *, const char *);
* by the caller.
*
* \note The vector is sorted and does not contain any duplicates.
+ *
+ * \warning This function cannot be called recursively so it will always
+ * fail if called from a CLI_GENERATE callback.
*/
struct ast_vector_string *ast_cli_completion_vector(const char *text, const char *word);
/*!
+ * \brief Add a result to a request for completion options.
+ *
+ * \param value A completion option text.
+ *
+ * \retval 0 Success
+ * \retval -1 Failure
+ *
+ * This is an alternative to returning individual values from CLI_GENERATE. Instead
+ * of repeatedly being asked for the next match and having to start over, you can
+ * call this function repeatedly from your own stateful loop. When all matches have
+ * been added you can return NULL from the CLI_GENERATE function.
+ *
+ * \note This function always eventually results in calling ast_free on \a value.
+ */
+int ast_cli_completion_add(char *value);
+
+/*!
* \brief Command completion for the list of active channels.
*
* This can be called from a CLI command completion function that wants to
diff --git a/main/asterisk.c b/main/asterisk.c
index c4ed9093f..2c86d1ebc 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -3009,121 +3009,70 @@ static char *cli_prompt(EditLine *editline)
return ast_str_buffer(prompt);
}
-static void destroy_match_list(char **match_list, int matches)
+static struct ast_vector_string *ast_el_strtoarr(char *buf)
{
- if (match_list) {
- int idx;
+ char *retstr;
+ struct ast_vector_string *vec = ast_calloc(1, sizeof(*vec));
- for (idx = 0; idx < matches; ++idx) {
- ast_free(match_list[idx]);
- }
- ast_free(match_list);
+ if (!vec) {
+ return NULL;
}
-}
-
-static char **ast_el_strtoarr(char *buf)
-{
- char *retstr;
- char **match_list = NULL;
- char **new_list;
- size_t match_list_len = 1;
- int matches = 0;
while ((retstr = strsep(&buf, " "))) {
if (!strcmp(retstr, AST_CLI_COMPLETE_EOF)) {
break;
}
- if (matches + 1 >= match_list_len) {
- match_list_len <<= 1;
- new_list = ast_realloc(match_list, match_list_len * sizeof(char *));
- if (!new_list) {
- destroy_match_list(match_list, matches);
- return NULL;
- }
- match_list = new_list;
+
+ /* Older daemons sent duplicates. */
+ if (AST_VECTOR_GET_CMP(vec, retstr, strcasecmp)) {
+ continue;
}
retstr = ast_strdup(retstr);
- if (!retstr) {
- destroy_match_list(match_list, matches);
- return NULL;
+ /* Older daemons sent unsorted. */
+ if (!retstr || AST_VECTOR_ADD_SORTED(vec, retstr, strcasecmp)) {
+ ast_free(retstr);
+ goto vector_cleanup;
}
- match_list[matches++] = retstr;
}
- if (!match_list) {
- return NULL;
+ if (!AST_VECTOR_SIZE(vec)) {
+ goto vector_cleanup;
}
- if (matches >= match_list_len) {
- new_list = ast_realloc(match_list, (match_list_len + 1) * sizeof(char *));
- if (!new_list) {
- destroy_match_list(match_list, matches);
- return NULL;
- }
- match_list = new_list;
- }
+ return vec;
- match_list[matches] = NULL;
+vector_cleanup:
+ AST_VECTOR_CALLBACK_VOID(vec, ast_free);
+ AST_VECTOR_PTR_FREE(vec);
- return match_list;
-}
-
-static int ast_el_sort_compare(const void *i1, const void *i2)
-{
- char *s1, *s2;
-
- s1 = ((char **)i1)[0];
- s2 = ((char **)i2)[0];
-
- return strcasecmp(s1, s2);
+ return NULL;
}
-static int ast_cli_display_match_list(char **matches, int len, int max)
+static void ast_cli_display_match_list(struct ast_vector_string *matches, int max)
{
- int i, idx, limit, count;
- int screenwidth = 0;
- int numoutput = 0, numoutputline = 0;
-
- screenwidth = ast_get_termcols(STDOUT_FILENO);
-
+ int idx = 1;
/* find out how many entries can be put on one line, with two spaces between strings */
- limit = screenwidth / (max + 2);
- if (limit == 0)
- limit = 1;
-
- /* how many lines of output */
- count = len / limit;
- if (count * limit < len)
- count++;
+ int limit = ast_get_termcols(STDOUT_FILENO) / (max + 2);
- idx = 1;
-
- qsort(&matches[0], (size_t)(len), sizeof(char *), ast_el_sort_compare);
-
- for (; count > 0; count--) {
- numoutputline = 0;
- for (i = 0; i < limit && matches[idx]; i++, idx++) {
+ if (limit == 0) {
+ limit = 1;
+ }
- /* Don't print dupes */
- if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
- i--;
- ast_free(matches[idx]);
- matches[idx] = NULL;
- continue;
- }
+ for (;;) {
+ int numoutputline;
- numoutput++;
+ for (numoutputline = 0; numoutputline < limit && idx < AST_VECTOR_SIZE(matches); idx++) {
numoutputline++;
- fprintf(stdout, "%-*s ", max, matches[idx]);
- ast_free(matches[idx]);
- matches[idx] = NULL;
+ fprintf(stdout, "%-*s ", max, AST_VECTOR_GET(matches, idx));
+ }
+
+ if (!numoutputline) {
+ break;
}
- if (numoutputline > 0)
- fprintf(stdout, "\n");
- }
- return numoutput;
+ fprintf(stdout, "\n");
+ }
}
@@ -3131,10 +3080,9 @@ static char *cli_complete(EditLine *editline, int ch)
{
int len = 0;
char *ptr;
- int nummatches = 0;
- char **matches;
+ struct ast_vector_string *matches;
int retval = CC_ERROR;
- char buf[2048], savechr;
+ char savechr;
int res;
LineInfo *lf = (LineInfo *)el_line(editline);
@@ -3155,96 +3103,90 @@ static char *cli_complete(EditLine *editline, int ch)
len = lf->cursor - ptr;
if (ast_opt_remote) {
- snprintf(buf, sizeof(buf), "_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr);
- fdsend(ast_consock, buf);
- if ((res = read(ast_consock, buf, sizeof(buf) - 1)) < 0) {
- return (char*)(CC_ERROR);
+#define CMD_MATCHESARRAY "_COMMAND MATCHESARRAY \"%s\" \"%s\""
+ char *mbuf;
+ char *new_mbuf;
+ int mlen = 0, maxmbuf = 2048;
+
+ /* Start with a 2048 byte buffer */
+ mbuf = ast_malloc(maxmbuf);
+
+ /* This will run snprintf twice at most. */
+ while (mbuf && (mlen = snprintf(mbuf, maxmbuf, CMD_MATCHESARRAY, lf->buffer, ptr)) > maxmbuf) {
+ /* Return value does not include space for NULL terminator. */
+ maxmbuf = mlen + 1;
+ ast_free(mbuf);
+ mbuf = ast_malloc(maxmbuf);
}
- buf[res] = '\0';
- nummatches = atoi(buf);
-
- if (nummatches > 0) {
- char *mbuf;
- char *new_mbuf;
- int mlen = 0, maxmbuf = 2048;
-
- /* Start with a 2048 byte buffer */
- if (!(mbuf = ast_malloc(maxmbuf))) {
- *((char *) lf->cursor) = savechr;
- return (char *)(CC_ERROR);
- }
- snprintf(buf, sizeof(buf), "_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr);
- fdsend(ast_consock, buf);
- res = 0;
- mbuf[0] = '\0';
- while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
- if (mlen + 1024 > maxmbuf) {
- /* Every step increment buffer 1024 bytes */
- maxmbuf += 1024;
- new_mbuf = ast_realloc(mbuf, maxmbuf);
- if (!new_mbuf) {
- ast_free(mbuf);
- *((char *) lf->cursor) = savechr;
- return (char *)(CC_ERROR);
- }
- mbuf = new_mbuf;
+
+ if (!mbuf) {
+ *((char *) lf->cursor) = savechr;
+
+ return (char *)(CC_ERROR);
+ }
+
+ fdsend(ast_consock, mbuf);
+ res = 0;
+ mlen = 0;
+ mbuf[0] = '\0';
+
+ while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
+ if (mlen + 1024 > maxmbuf) {
+ /* Expand buffer to the next 1024 byte increment. */
+ maxmbuf = mlen + 1024;
+ new_mbuf = ast_realloc(mbuf, maxmbuf);
+ if (!new_mbuf) {
+ ast_free(mbuf);
+ *((char *) lf->cursor) = savechr;
+
+ return (char *)(CC_ERROR);
}
- /* Only read 1024 bytes at a time */
- res = read(ast_consock, mbuf + mlen, 1024);
- if (res > 0)
- mlen += res;
+ mbuf = new_mbuf;
}
- mbuf[mlen] = '\0';
+ /* Only read 1024 bytes at a time */
+ res = read(ast_consock, mbuf + mlen, 1024);
+ if (res > 0) {
+ mlen += res;
+ }
+ }
+ mbuf[mlen] = '\0';
- matches = ast_el_strtoarr(mbuf);
- ast_free(mbuf);
- } else
- matches = (char **) NULL;
+ matches = ast_el_strtoarr(mbuf);
+ ast_free(mbuf);
} else {
- char **p, *oldbuf=NULL;
- nummatches = 0;
- matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
- for (p = matches; p && *p; p++) {
- if (!oldbuf || strcmp(*p,oldbuf))
- nummatches++;
- oldbuf = *p;
- }
+ matches = ast_cli_completion_vector((char *)lf->buffer, ptr);
}
if (matches) {
int i;
- int matches_num, maxlen, match_len;
+ int maxlen, match_len;
+ const char *best_match = AST_VECTOR_GET(matches, 0);
- if (matches[0][0] != '\0') {
+ if (!ast_strlen_zero(best_match)) {
el_deletestr(editline, (int) len);
- el_insertstr(editline, matches[0]);
+ el_insertstr(editline, best_match);
retval = CC_REFRESH;
}
- if (nummatches == 1) {
+ if (AST_VECTOR_SIZE(matches) == 2) {
/* Found an exact match */
el_insertstr(editline, " ");
retval = CC_REFRESH;
} else {
/* Must be more than one match */
- for (i = 1, maxlen = 0; matches[i]; i++) {
- match_len = strlen(matches[i]);
- if (match_len > maxlen)
+ for (i = 1, maxlen = 0; i < AST_VECTOR_SIZE(matches); i++) {
+ match_len = strlen(AST_VECTOR_GET(matches, i));
+ if (match_len > maxlen) {
maxlen = match_len;
+ }
}
- matches_num = i - 1;
- if (matches_num >1) {
- fprintf(stdout, "\n");
- ast_cli_display_match_list(matches, nummatches, maxlen);
- retval = CC_REDISPLAY;
- } else {
- el_insertstr(editline," ");
- retval = CC_REFRESH;
- }
+
+ fprintf(stdout, "\n");
+ ast_cli_display_match_list(matches, maxlen);
+ retval = CC_REDISPLAY;
}
- for (i = 0; matches[i]; i++)
- ast_free(matches[i]);
- ast_free(matches);
+ AST_VECTOR_CALLBACK_VOID(matches, ast_free);
+ AST_VECTOR_PTR_FREE(matches);
}
*((char *) lf->cursor) = savechr;
diff --git a/main/cli.c b/main/cli.c
index eae14adc4..0f023b29f 100644
--- a/main/cli.c
+++ b/main/cli.c
@@ -2475,18 +2475,17 @@ static char *parse_args(const char *s, int *argc, const char *argv[], int max, i
/*! \brief Return the number of unique matches for the generator */
int ast_cli_generatornummatches(const char *text, const char *word)
{
- int matches = 0, i = 0;
- char *buf = NULL, *oldbuf = NULL;
-
- while ((buf = ast_cli_generator(text, word, i++))) {
- if (!oldbuf || strcmp(buf,oldbuf))
- matches++;
- if (oldbuf)
- ast_free(oldbuf);
- oldbuf = buf;
- }
- if (oldbuf)
- ast_free(oldbuf);
+ int matches;
+ struct ast_vector_string *vec = ast_cli_completion_vector(text, word);
+
+ if (!vec) {
+ return 0;
+ }
+
+ matches = AST_VECTOR_SIZE(vec) - 1;
+ AST_VECTOR_CALLBACK_VOID(vec, ast_free);
+ AST_VECTOR_PTR_FREE(vec);
+
return matches;
}
@@ -2513,6 +2512,44 @@ char **ast_cli_completion_matches(const char *text, const char *word)
return match_list;
}
+AST_THREADSTORAGE_RAW(completion_storage);
+
+/*!
+ * \internal
+ * \brief Add a value to the vector.
+ *
+ * \param vec Vector to add \a value to. Must be from threadstorage.
+ * \param value The value to add.
+ *
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+static int cli_completion_vector_add(struct ast_vector_string *vec, char *value)
+{
+ if (!value) {
+ return 0;
+ }
+
+ if (!vec || AST_VECTOR_ADD_SORTED(vec, value, strcasecmp)) {
+ if (vec) {
+ ast_threadstorage_set_ptr(&completion_storage, NULL);
+
+ AST_VECTOR_CALLBACK_VOID(vec, ast_free);
+ AST_VECTOR_FREE(vec);
+ }
+ ast_free(value);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+int ast_cli_completion_add(char *value)
+{
+ return cli_completion_vector_add(ast_threadstorage_get_ptr(&completion_storage), value);
+}
+
struct ast_vector_string *ast_cli_completion_vector(const char *text, const char *word)
{
char *retstr, *prevstr;
@@ -2520,13 +2557,23 @@ struct ast_vector_string *ast_cli_completion_vector(const char *text, const char
size_t which = 0;
struct ast_vector_string *vec = ast_calloc(1, sizeof(*vec));
+ /* Recursion into this function is a coding error. */
+ ast_assert(!ast_threadstorage_get_ptr(&completion_storage));
+
if (!vec) {
return NULL;
}
+ if (ast_threadstorage_set_ptr(&completion_storage, vec)) {
+ ast_log(LOG_ERROR, "Failed to initialize threadstorage for completion.\n");
+ ast_free(vec);
+
+ return NULL;
+ }
+
while ((retstr = ast_cli_generator(text, word, which)) != NULL) {
- if (AST_VECTOR_ADD_SORTED(vec, retstr, strcasecmp)) {
- ast_free(retstr);
+ if (cli_completion_vector_add(vec, retstr)) {
+ ast_threadstorage_set_ptr(&completion_storage, NULL);
goto vector_cleanup;
}
@@ -2534,6 +2581,8 @@ struct ast_vector_string *ast_cli_completion_vector(const char *text, const char
++which;
}
+ ast_threadstorage_set_ptr(&completion_storage, NULL);
+
if (!AST_VECTOR_SIZE(vec)) {
AST_VECTOR_PTR_FREE(vec);
@@ -2572,6 +2621,7 @@ struct ast_vector_string *ast_cli_completion_vector(const char *text, const char
retstr = ast_strndup(AST_VECTOR_GET(vec, 0), max_equal);
if (!retstr || AST_VECTOR_INSERT_AT(vec, 0, retstr)) {
ast_free(retstr);
+
goto vector_cleanup;
}
diff --git a/res/ari/resource_bridges.c b/res/ari/resource_bridges.c
index e08df7d8b..019cdea22 100644
--- a/res/ari/resource_bridges.c
+++ b/res/ari/resource_bridges.c
@@ -962,13 +962,12 @@ void ast_ari_bridges_create_with_id(struct ast_variable *headers,
if (bridge) {
/* update */
- if (!ast_strlen_zero(args->name)) {
- if (!strcmp(args->name, bridge->name)) {
- ast_ari_response_error(
- response, 500, "Internal Error",
- "Changing bridge name is not implemented");
- return;
- }
+ if (!ast_strlen_zero(args->name)
+ && strcmp(args->name, bridge->name)) {
+ ast_ari_response_error(
+ response, 500, "Internal Error",
+ "Changing bridge name is not implemented");
+ return;
}
if (!ast_strlen_zero(args->type)) {
ast_ari_response_error(
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 839753e41..273061124 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -113,6 +113,20 @@
#define ZFONE_PROFILE_ID 0x505a
#define DEFAULT_LEARNING_MIN_SEQUENTIAL 4
+/*!
+ * \brief Calculate the min learning duration in ms.
+ *
+ * \details
+ * The min supported packet size represents 10 ms and we need to account
+ * for some jitter and fast clocks while learning. Some messed up devices
+ * have very bad jitter for a small packet sample size. Jitter can also
+ * be introduced by the network itself.
+ *
+ * So we'll allow packets to come in every 9ms on average for fast clocking
+ * with the last one coming in 5ms early for jitter.
+ */
+#define CALC_LEARNING_MIN_DURATION(count) (((count) - 1) * 9 - 5)
+#define DEFAULT_LEARNING_MIN_DURATION CALC_LEARNING_MIN_DURATION(DEFAULT_LEARNING_MIN_SEQUENTIAL)
#define SRTP_MASTER_KEY_LEN 16
#define SRTP_MASTER_SALT_LEN 14
@@ -151,6 +165,7 @@ static int nochecksums;
#endif
static int strictrtp = DEFAULT_STRICT_RTP; /*!< Only accept RTP frames from a defined source. If we receive an indication of a changing source, enter learning mode. */
static int learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL; /*!< Number of sequential RTP frames needed from a single source during learning mode to accept new source. */
+static int learning_min_duration = DEFAULT_LEARNING_MIN_DURATION; /*!< Lowest acceptable timeout between the first and the last sequential RTP frame. */
#ifdef HAVE_PJPROJECT
static int icesupport = DEFAULT_ICESUPPORT;
static struct sockaddr_in stunaddr;
@@ -231,7 +246,7 @@ static AST_RWLIST_HEAD_STATIC(host_candidates, ast_ice_host_candidate);
struct rtp_learning_info {
struct ast_sockaddr proposed_address; /*!< Proposed remote address for strict RTP */
struct timeval start; /*!< The time learning mode was started */
- struct timeval received; /*!< The time of the last received packet */
+ struct timeval received; /*!< The time of the first received packet */
int max_seq; /*!< The highest sequence number received */
int packets; /*!< The number of remaining packets before the source is accepted */
};
@@ -3065,25 +3080,28 @@ static void rtp_learning_seq_init(struct rtp_learning_info *info, uint16_t seq)
*/
static int rtp_learning_rtp_seq_update(struct rtp_learning_info *info, uint16_t seq)
{
- /*
- * During the learning mode the minimum amount of media we'll accept is
- * 10ms so give a reasonable 5ms buffer just in case we get it sporadically.
- */
- if (!ast_tvzero(info->received) && ast_tvdiff_ms(ast_tvnow(), info->received) < 5) {
- /*
- * Reject a flood of packets as acceptable for learning.
- * Reset the needed packets.
- */
- info->packets = learning_min_sequential - 1;
- } else if (seq == (uint16_t) (info->max_seq + 1)) {
+ if (seq == (uint16_t) (info->max_seq + 1)) {
/* packet is in sequence */
info->packets--;
} else {
/* Sequence discontinuity; reset */
info->packets = learning_min_sequential - 1;
+ info->received = ast_tvnow();
+ }
+
+ /*
+ * Protect against packet floods by checking that we
+ * received the packet sequence in at least the minimum
+ * allowed time.
+ */
+ if (ast_tvzero(info->received)) {
+ info->received = ast_tvnow();
+ } else if (!info->packets && (ast_tvdiff_ms(ast_tvnow(), info->received) < learning_min_duration )) {
+ /* Packet flood; reset */
+ info->packets = learning_min_sequential - 1;
+ info->received = ast_tvnow();
}
info->max_seq = seq;
- info->received = ast_tvnow();
return info->packets;
}
@@ -7153,6 +7171,7 @@ static int rtp_reload(int reload)
dtmftimeout = DEFAULT_DTMF_TIMEOUT;
strictrtp = DEFAULT_STRICT_RTP;
learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL;
+ learning_min_duration = DEFAULT_LEARNING_MIN_DURATION;
/** This resource is not "reloaded" so much as unloaded and loaded again.
* In the case of the TURN related variables, the memory referenced by a
@@ -7217,10 +7236,12 @@ static int rtp_reload(int reload)
strictrtp = ast_true(s);
}
if ((s = ast_variable_retrieve(cfg, "general", "probation"))) {
- if ((sscanf(s, "%d", &learning_min_sequential) <= 0) || learning_min_sequential <= 0) {
+ if ((sscanf(s, "%d", &learning_min_sequential) != 1) || learning_min_sequential <= 1) {
ast_log(LOG_WARNING, "Value for 'probation' could not be read, using default of '%d' instead\n",
DEFAULT_LEARNING_MIN_SEQUENTIAL);
+ learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL;
}
+ learning_min_duration = CALC_LEARNING_MIN_DURATION(learning_min_sequential);
}
#ifdef HAVE_PJPROJECT
if ((s = ast_variable_retrieve(cfg, "general", "icesupport"))) {
diff --git a/tests/test_substitution.c b/tests/test_substitution.c
index 3a1dc1fba..8b9a164aa 100644
--- a/tests/test_substitution.c
+++ b/tests/test_substitution.c
@@ -43,6 +43,7 @@
#include "asterisk/stringfields.h"
#include "asterisk/threadstorage.h"
#include "asterisk/test.h"
+#include "asterisk/vector.h"
static enum ast_test_result_state test_chan_integer(struct ast_test *test,
struct ast_channel *c, int *ifield, const char *expression)
@@ -225,6 +226,7 @@ AST_TEST_DEFINE(test_substitution)
struct ast_channel *c;
int i;
enum ast_test_result_state res = AST_TEST_PASS;
+ struct ast_vector_string *funcs;
switch (cmd) {
case TEST_INIT:
@@ -302,11 +304,12 @@ AST_TEST_DEFINE(test_substitution)
#undef TEST
/* For testing dialplan functions */
- for (i = 0; ; i++) {
- char *cmd = ast_cli_generator("core show function", "", i);
- if (cmd == NULL) {
- break;
- }
+ funcs = ast_cli_completion_vector("core show function", "");
+
+ /* Skip "best match" element 0 */
+ for (i = 1; funcs && i < AST_VECTOR_SIZE(funcs); i++) {
+ char *cmd = AST_VECTOR_GET(funcs, i);
+
if (strcmp(cmd, "CHANNEL") && strcmp(cmd, "CALLERID") && strncmp(cmd, "CURL", 4) &&
strncmp(cmd, "AES", 3) && strncmp(cmd, "BASE64", 6) &&
strcmp(cmd, "CDR") && strcmp(cmd, "ENV") && strcmp(cmd, "GLOBAL") &&
@@ -321,10 +324,14 @@ AST_TEST_DEFINE(test_substitution)
}
}
}
- ast_free(cmd);
}
+ if (funcs) {
+ AST_VECTOR_CALLBACK_VOID(funcs, ast_free);
+ AST_VECTOR_PTR_FREE(funcs);
+ }
ast_hangup(c);
+
return res;
}
diff --git a/third-party/pjproject/patches/0040-183_without_to_tag.patch b/third-party/pjproject/patches/0040-183_without_to_tag.patch
new file mode 100644
index 000000000..e8692fe1b
--- /dev/null
+++ b/third-party/pjproject/patches/0040-183_without_to_tag.patch
@@ -0,0 +1,17 @@
+diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c
+index c9686a0..fc52a63 100644
+--- a/pjsip/src/pjsip-ua/sip_inv.c
++++ b/pjsip/src/pjsip-ua/sip_inv.c
+@@ -4156,9 +4156,10 @@ static void inv_on_state_calling( pjsip_inv_session *inv, pjsip_event *e)
+ status = pjsip_inv_send_msg(inv, cancel);
+ }
+
+- if (dlg->remote.info->tag.slen) {
++ if (tsx->status_code != 100) {
+
+- inv_set_state(inv, PJSIP_INV_STATE_EARLY, e);
++ if (dlg->remote.info->tag.slen)
++ inv_set_state(inv, PJSIP_INV_STATE_EARLY, e);
+
+ inv_check_sdp_in_incoming_msg(inv, tsx,
+ e->body.tsx_state.src.rdata);