[-]
[+]
|
Changed |
asterisk.changes
|
|
[-]
[+]
|
Changed |
asterisk.spec
^
|
|
[-]
[+]
|
Deleted |
asterisk-1.8.19.1.tar.xz/asterisk-1.8.19.1-summary.html
^
|
@@ -1,80 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /><title>Release Summary - asterisk-1.8.19.1</title></head>
-<body>
-<h1 align="center"><a name="top">Release Summary</a></h1>
-<h3 align="center">asterisk-1.8.19.1</h3>
-<h3 align="center">Date: 2013-01-02</h3>
-<h3 align="center"><asteriskteam@digium.com></h3>
-<hr/>
-<h2 align="center">Table of Contents</h2>
-<ol>
- <li><a href="#summary">Summary</a></li>
- <li><a href="#contributors">Contributors</a></li>
- <li><a href="#commits">Other Changes</a></li>
- <li><a href="#diffstat">Diffstat</a></li>
-</ol>
-<hr/>
-<a name="summary"><h2 align="center">Summary</h2></a>
-<center><a href="#top">[Back to Top]</a></center><br/><p>This release has been made to address one or more security vulnerabilities that have been identified. A security advisory document has been published for each vulnerability that includes additional information. Users of versions of Asterisk that are affected are strongly encouraged to review the advisories and determine what action they should take to protect their systems from these issues.</p>
-<p>Security Advisories: <a href="http://downloads.asterisk.org/pub/security/AST-2012-014.html">AST-2012-014</a>, <a href="http://downloads.asterisk.org/pub/security/AST-2012-015.html">AST-2012-015</a></p>
-<p>The data in this summary reflects changes that have been made since the previous release, asterisk-1.8.19.0.</p>
-<hr/>
-<a name="contributors"><h2 align="center">Contributors</h2></a>
-<center><a href="#top">[Back to Top]</a></center><br/><p>This table lists the people who have submitted code, those that have tested patches, as well as those that reported issues on the issue tracker that were resolved in this release. For coders, the number is how many of their patches (of any size) were committed into this release. For testers, the number is the number of times their name was listed as assisting with testing a patch. Finally, for reporters, the number is the number of issues that they reported that were closed by commits that went into this release.</p>
-<table width="100%" border="0">
-<tr>
-<td width="33%"><h3>Coders</h3></td>
-<td width="33%"><h3>Testers</h3></td>
-<td width="33%"><h3>Reporters</h3></td>
-</tr>
-<tr valign="top">
-<td>
-2 bebuild<br/>
-</td>
-<td>
-</td>
-<td>
-</td>
-</tr>
-</table>
-<hr/>
-<a name="commits"><h2 align="center">Commits Not Associated with an Issue</h2></a>
-<center><a href="#top">[Back to Top]</a></center><br/><p>This is a list of all changes that went into this release that did not directly close an issue from the issue tracker. The commits may have been marked as being related to an issue. If that is the case, the issue numbers are listed here, as well.</p>
-<table width="100%" border="1">
-<tr><td><b>Revision</b></td><td><b>Author</b></td><td><b>Summary</b></td><td><b>Issues Referenced</b></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/tags/1.8.19.1?view=revision&revision=378336">378336</a></td><td>bebuild</td><td>Create 1.8.19.1</td>
-<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/tags/1.8.19.1?view=revision&revision=378341">378341</a></td><td>bebuild</td><td>Merge 378269, 378303 for 1.8.19.1</td>
-<td></td></tr></table>
-<hr/>
-<a name="diffstat"><h2 align="center">Diffstat Results</h2></a>
-<center><a href="#top">[Back to Top]</a></center><br/><p>This is a summary of the changes to the source code that went into this release that was generated using the diffstat utility.</p>
-<pre>
-.version | 2
-ChangeLog | 43 ++++
-apps/app_confbridge.c | 4
-apps/app_meetme.c | 16 -
-asterisk-1.8.19.0-summary.html | 273 ------------------------------
-asterisk-1.8.19.0-summary.txt | 363 -----------------------------------------
-channels/chan_agent.c | 12 -
-channels/chan_dahdi.c | 7
-channels/chan_iax2.c | 31 ++-
-channels/chan_local.c | 3
-channels/chan_sip.c | 76 +++++---
-channels/chan_skinny.c | 16 -
-channels/sip/include/sip.h | 1
-funcs/func_devstate.c | 6
-include/asterisk/channel.h | 6
-include/asterisk/devicestate.h | 16 +
-include/asterisk/event_defs.h | 8
-main/channel.c | 5
-main/devicestate.c | 51 +++--
-main/event.c | 1
-main/features.c | 2
-main/http.c | 20 +-
-res/res_calendar.c | 8
-res/res_jabber.c | 66 +++++--
-24 files changed, 281 insertions(+), 755 deletions(-)
-</pre><br/>
-<hr/>
-</body>
-</html>
|
[-]
[+]
|
Deleted |
asterisk-1.8.19.1.tar.xz/asterisk-1.8.19.1-summary.txt
^
|
@@ -1,109 +0,0 @@
- Release Summary
-
- asterisk-1.8.19.1
-
- Date: 2013-01-02
-
- <asteriskteam@digium.com>
-
- ----------------------------------------------------------------------
-
- Table of Contents
-
- 1. Summary
- 2. Contributors
- 3. Other Changes
- 4. Diffstat
-
- ----------------------------------------------------------------------
-
- Summary
-
- [Back to Top]
-
- This release has been made to address one or more security vulnerabilities
- that have been identified. A security advisory document has been published
- for each vulnerability that includes additional information. Users of
- versions of Asterisk that are affected are strongly encouraged to review
- the advisories and determine what action they should take to protect their
- systems from these issues.
-
- Security Advisories: AST-2012-014, AST-2012-015
-
- The data in this summary reflects changes that have been made since the
- previous release, asterisk-1.8.19.0.
-
- ----------------------------------------------------------------------
-
- Contributors
-
- [Back to Top]
-
- This table lists the people who have submitted code, those that have
- tested patches, as well as those that reported issues on the issue tracker
- that were resolved in this release. For coders, the number is how many of
- their patches (of any size) were committed into this release. For testers,
- the number is the number of times their name was listed as assisting with
- testing a patch. Finally, for reporters, the number is the number of
- issues that they reported that were closed by commits that went into this
- release.
-
- Coders Testers Reporters
- 2 bebuild
-
- ----------------------------------------------------------------------
-
- Commits Not Associated with an Issue
-
- [Back to Top]
-
- This is a list of all changes that went into this release that did not
- directly close an issue from the issue tracker. The commits may have been
- marked as being related to an issue. If that is the case, the issue
- numbers are listed here, as well.
-
- +------------------------------------------------------------------------+
- | Revision | Author | Summary | Issues Referenced |
- |----------+---------+-------------------------------+-------------------|
- | 378336 | bebuild | Create 1.8.19.1 | |
- |----------+---------+-------------------------------+-------------------|
- | 378341 | bebuild | Merge 378269, 378303 for | |
- | | | 1.8.19.1 | |
- +------------------------------------------------------------------------+
-
- ----------------------------------------------------------------------
-
- Diffstat Results
-
- [Back to Top]
-
- This is a summary of the changes to the source code that went into this
- release that was generated using the diffstat utility.
-
- .version | 2
- ChangeLog | 43 ++++
- apps/app_confbridge.c | 4
- apps/app_meetme.c | 16 -
- asterisk-1.8.19.0-summary.html | 273 ------------------------------
- asterisk-1.8.19.0-summary.txt | 363 -----------------------------------------
- channels/chan_agent.c | 12 -
- channels/chan_dahdi.c | 7
- channels/chan_iax2.c | 31 ++-
- channels/chan_local.c | 3
- channels/chan_sip.c | 76 +++++---
- channels/chan_skinny.c | 16 -
- channels/sip/include/sip.h | 1
- funcs/func_devstate.c | 6
- include/asterisk/channel.h | 6
- include/asterisk/devicestate.h | 16 +
- include/asterisk/event_defs.h | 8
- main/channel.c | 5
- main/devicestate.c | 51 +++--
- main/event.c | 1
- main/features.c | 2
- main/http.c | 20 +-
- res/res_calendar.c | 8
- res/res_jabber.c | 66 +++++--
- 24 files changed, 281 insertions(+), 755 deletions(-)
-
- ----------------------------------------------------------------------
|
[-]
[+]
|
Deleted |
asterisk-1.8.19.1.tar.xz/utils/hashtest.c
^
|
@@ -1,410 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2007, Steve Murphy
- *
- * Steve Murphy <murf@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-/*! \file
- *
- * \brief A program to thoroughly thrash a hash table, testing
- * out locking safety, and making sure all functionality
- * is functioning. Run with 5 or more threads to get that
- * fully intense firestorm of activity. If your
- * hash tables don't crash, lock up, or go weird, it must
- * be good code! Even features some global counters
- * that will get slightly behind because they aren't lock-protected.
- *
- * \author Steve Murphy <murf@digium.com>
- */
-
-/*** MODULEINFO
- <support_level>extended</support_level>
- ***/
-
-#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
-
-#include <pthread.h>
-#include <sys/stat.h>
-#include <signal.h>
-#include <errno.h>
-#include "asterisk/lock.h"
-#include "asterisk/hashtab.h"
-#include "asterisk/channel.h"
-#include "asterisk/utils.h"
-#include "asterisk/module.h"
-int testno = 1;
-
-/* stuff we need to make this work with the hashtab stuff */
-#if !defined(LOW_MEMORY)
-int64_t ast_mark(int prof_id, int x)
-{
- return 0;
-}
-#endif
-
-void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used);
-void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used)
-{
-}
-
-struct ht_element
-{
- char *key;
- char *val;
-};
-
-static int hashtab_compare_strings_nocase(const void *a, const void *b)
-{
- const struct ht_element *ae = a, *be = b;
- return ast_hashtab_compare_strings_nocase(ae->key, be->key);
-}
-
-#if 0
-static int hashtab_compare_strings(const void *a, const void *b)
-{
- const struct ht_element *ae = a, *be = b;
- return ast_hashtab_compare_strings(ae->key, be->key);
-}
-
-static unsigned int hashtab_hash_string(const void *obj)
-{
- const struct ht_element *o = obj;
- return ast_hashtab_hash_string((const void *)o->key);
-}
-#endif
-
-static unsigned int hashtab_hash_string_nocase(const void *obj)
-{
- const struct ht_element *o = obj;
- return ast_hashtab_hash_string_nocase((const void*)o->key);
-}
-
-/* random numbers */
-
-static int my_rand(int incl_low, int incl_high, unsigned int *seedp)
-{
- if (incl_high == 0)
- return 0;
-
- return incl_low + (rand_r(seedp) % incl_high);
-}
-
-
-
-
-/* the testing routines */
-
-static int glob_highwater = 0;
-struct ast_hashtab *glob_hashtab = 0;
-unsigned int glob_seed = 0;
-int els_removed = 0;
-int els_added = 0;
-int els_lookedup = 0;
-int els_found = 0;
-int els_traversals = 0;
-
-/* all the operations to perform on the hashtab */
-
-static void add_element(void)
-{
- char keybuf[100];
- struct ht_element *x = malloc(sizeof(struct ht_element));
- sprintf(keybuf,"key%08d", glob_highwater++);
- x->key = strdup(keybuf);
- x->val = strdup("interesting data");
- ast_hashtab_insert_immediate(glob_hashtab, x);
- els_added++;
-}
-
-static void traverse_elements(void)
-{
- struct ht_element *el;
- int c=0;
- struct ast_hashtab_iter *it = ast_hashtab_start_write_traversal(glob_hashtab);
-#ifdef DEBUG
- printf("Traverse hashtab\n");
-#endif
- while ((el = ast_hashtab_next(it))) {
- c++;
- }
- ast_hashtab_end_traversal(it);
- els_traversals++; /* unprotected, sometimes off, but, not really important, either */
-}
-
-static void * del_element(unsigned int *seedp)
-{
- char keybuf[100];
- struct ht_element *el, lookup;
- int x;
-
- /* pick a random element from 0 to highwater-1 */
- x = my_rand(0,glob_highwater-1,seedp);
- sprintf(keybuf, "key%08d", x);
-#ifdef DEBUG
- printf("Removing %s", keybuf);
-#endif
- lookup.key = keybuf;
- el = ast_hashtab_remove_object_via_lookup(glob_hashtab, &lookup);
-
- if (el) {
-#ifdef DEBUG
- printf("...YES (el=%x)\n", (unsigned long)el);
-#endif
- free(el->key);
- free(el->val);
- free(el);
- els_removed++;
- } else {
-#ifdef DEBUG
- printf("...NO.\n");
-#endif
- return 0;
- }
-
-
- return el;
-}
-
-static int lookup_element(unsigned int *seedp)
-{
- char keybuf[100];
- struct ht_element *el, lookup;
- int x;
-
- /* pick a random element from 0 to highwater-1 */
- x = my_rand(0,glob_highwater-1,seedp);
- sprintf(keybuf, "key%08d", x);
- lookup.key = keybuf;
- el = ast_hashtab_lookup(glob_hashtab, &lookup);
- els_lookedup++;
- if (el)
- els_found++;
- if (el)
- return 1;
- return 0;
-}
-
-
-static void *hashtest(void *data)
-{
- int my_els_removed = 0;
- int my_els_added = 0;
- int my_els_lookedup = 0;
- int my_els_found = 0;
- int my_els_traversals = 0;
- int my_testno = testno++;
- int its;
-
- /* data will be a random number == use as a seed for random numbers */
- unsigned long seed = (unsigned long)data;
-
- printf("hashtest thread created... test beginning\n");
-
- /* main test routine-- a global hashtab exists, pound it like crazy */
- for(its=0;its<100000;its++)
- {
- void *seed2 = &seed;
- int op = my_rand(0,100, seed2);
- if (op<60) {
- my_els_lookedup++;
-#ifdef DEBUG
- printf("%d[%d]: LOOKUP\n", my_testno, its);
-#endif
- if ((my_els_lookedup%1000)==0) {
- printf(".");
- fflush(stdout);
- }
- if (lookup_element(seed2))
- my_els_found++;
- } else if (op < 61) { /* make this 61 and it'll take 15 minutes to run */
-#ifdef DEBUG
- printf("%d[%d]: TRAVERSE\n", my_testno, its);
-#endif
- traverse_elements();
- my_els_traversals++;
-
- } else if (op < 80) {
-#ifdef DEBUG
- printf("%d[%d]: REMOVE\n", my_testno, its);
-#endif
- if (del_element(seed2))
- my_els_removed++;
- } else {
- my_els_added++;
-#ifdef DEBUG
- printf("%d[%d]: ADD\n", my_testno, its);
-#endif
- add_element();
- }
- }
- printf("\nhashtest thread %d exiting.... lookups=%d/%d, added=%d, removed=%d, traversals=%d;\n",
- my_testno, my_els_found, my_els_lookedup, my_els_added, my_els_removed, my_els_traversals);
- printf("\ntotals..................... lookups=%d/%d, added=%d, removed=%d, traversals=%d;\n",
- els_found, els_lookedup, els_added, els_removed,els_traversals);
- pthread_exit(0);
-}
-
-static void run_hashtest(int numthr)
-{
- pthread_t thr[numthr];
- void *thrres[numthr];
- int i, biggest, resize_cnt, numobjs, numbuckets;
-
- /* init a single global hashtab, then... */
- glob_hashtab = ast_hashtab_create(180000, hashtab_compare_strings_nocase, ast_hashtab_resize_java, ast_hashtab_newsize_java, hashtab_hash_string_nocase, 1);
- printf("starting with %d elements in the hashtable...\n", ast_hashtab_capacity(glob_hashtab));
- /* set a random seed */
- glob_seed = (unsigned int)time(0);
- srand(glob_seed);
-
- /* create threads, each running hashtest */
- for(i=0;i<numthr;i++)
- {
- unsigned long z = rand();
-
- printf("starting hashtest thread %d....\n",i+1);
- if (ast_pthread_create(&thr[i], NULL, hashtest, (void*)z)) {
- printf("Sorry, couldn't create thread #%d\n", i+1);
- }
- printf("hashtest thread spawned.... \n");
- }
- /* collect threads, each running hashtest */
- for(i=0;i<numthr;i++)
- {
- printf("waiting for thread %d....\n", i+1);
- if (pthread_join(thr[i], &thrres[i])) {
- printf("Sorry, couldn't join thread #%d\n", i+1);
- }
- printf("hashtest thread %d done.... \n",i+1);
- }
- /* user has to kill/intr the process to stop the test? */
- ast_hashtab_get_stats(glob_hashtab, &biggest, &resize_cnt, &numobjs, &numbuckets);
- printf("Some stats: longest bucket chain: %d; number of resizes: %d; number of objects: %d; capacity: %d\n",
- biggest, resize_cnt, numobjs, numbuckets);
-}
-
-
-int main(int argc,char **argv)
-{
- if (argc < 2 || argc > 2 || atoi(argv[1]) < 1)
- {
- printf("Usage: hashtest <number of threads>\n");
- exit(1);
- }
-
- /* one arg == number of threads to create */
- run_hashtest(atoi(argv[1]));
-
- return 0;
-}
-#if !defined(LOW_MEMORY)
-int ast_add_profile(const char *x, uint64_t scale)
-{
- return 0;
-}
-#endif
-
-int ast_loader_register(int (*updater)(void))
-{
- return 1;
-}
-
-int ast_loader_unregister(int (*updater)(void))
-{
- return 1;
-}
-void ast_module_register(const struct ast_module_info *x)
-{
-}
-
-void ast_module_unregister(const struct ast_module_info *x)
-{
-}
-
-
-void ast_register_file_version(const char *file, const char *version);
-void ast_register_file_version(const char *file, const char *version)
-{
-}
-
-void ast_unregister_file_version(const char *file);
-void ast_unregister_file_version(const char *file)
-{
-
-}
-
-void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
-{
- va_list vars;
- va_start(vars,fmt);
- printf("LOG: lev:%d file:%s line:%d func: %s ",
- level, file, line, function);
- vprintf(fmt, vars);
- fflush(stdout);
- va_end(vars);
-}
-
-void __ast_verbose(const char *file, int line, const char *func, const char *fmt, ...)
-{
- va_list vars;
- va_start(vars,fmt);
-
- printf("VERBOSE: ");
- vprintf(fmt, vars);
- fflush(stdout);
- va_end(vars);
-}
-
-void ast_register_thread(char *name)
-{
-
-}
-
-void ast_unregister_thread(void *id)
-{
-}
-
-#ifdef HAVE_BKTR
-struct ast_bt *ast_bt_create(void);
-struct ast_bt *ast_bt_create(void)
-{
- return NULL;
-}
-
-int ast_bt_get_addresses(struct ast_bt *bt);
-int ast_bt_get_addresses(struct ast_bt *bt)
-{
- return 0;
-}
-
-char **ast_bt_get_symbols(void **addresses, size_t num_frames);
-char **ast_bt_get_symbols(void **addresses, size_t num_frames)
-{
- char **foo = calloc(num_frames, sizeof(char *) + 1);
- if (foo) {
- int i;
- for (i = 0; i < num_frames; i++) {
- foo[i] = (char *) foo + sizeof(char *) * num_frames;
- }
- }
- return foo;
-}
-
-void *ast_bt_destroy(struct ast_bt *bt);
-void *ast_bt_destroy(struct ast_bt *bt)
-{
- return NULL;
-}
-#endif
|
[-]
[+]
|
Deleted |
asterisk-1.8.19.1.tar.xz/utils/hashtest2.c
^
|
@@ -1,418 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2007, Steve Murphy
- *
- * Steve Murphy <murf@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-/*! \file
- *
- * \brief A program to thoroughly thrash a hash table, testing
- * out locking safety, and making sure all functionality
- * is functioning. Run with 5 or more threads to get that
- * fully intense firestorm of activity. If your
- * hash tables don't crash, lock up, or go weird, it must
- * be good code! Even features some global counters
- * that will get slightly behind because they aren't lock-protected.
- *
- * \author Steve Murphy <murf@digium.com>
- */
-
-/*** MODULEINFO
- <support_level>extended</support_level>
- ***/
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
-
-#include <pthread.h>
-#include <sys/stat.h>
-#include <signal.h>
-
-#include "asterisk/lock.h"
-#include "asterisk/astobj2.h"
-#include "asterisk/channel.h"
-#include "asterisk/utils.h"
-#include "asterisk/module.h"
-
-int testno = 2;
-
-/* stuff we need to make this work with the astobj2 stuff */
-#if !defined(LOW_MEMORY)
-int64_t ast_mark(int prof_id, int x)
-{
- return 0;
-}
-#endif
-
-/* my OBJECT */
-struct ht_element
-{
- char *key;
- char *val;
-};
-
-char *pbx_substitute_variables_helper_full(struct ast_channel *chan, struct varshead *head, const char *cp1, char *cp2, int maxlen, size_t *used);
-char *pbx_substitute_variables_helper_full(struct ast_channel *chan, struct varshead *head, const char *cp1, char *cp2, int maxlen, size_t *used)
-{
- return NULL;
-}
-
-static int hash_string(const void *obj, const int flags)
-{
- char *str = ((struct ht_element*)obj)->key;
- int total;
-
- for (total=0; *str; str++)
- {
- unsigned int tmp = total;
- total <<= 1; /* multiply by 2 */
- total += tmp; /* multiply by 3 */
- total <<= 2; /* multiply by 12 */
- total += tmp; /* multiply by 13 */
-
- total += ((unsigned int)(*str));
- }
- if (total < 0)
- total = -total;
- return total;
-}
-
-static int hashtab_compare_strings(void *a, void *b, int flags)
-{
- const struct ht_element *ae = a, *be = b;
- return !strcmp(ae->key, be->key) ? CMP_MATCH | CMP_STOP : 0;
-}
-
-/* random numbers */
-
-static int my_rand(int incl_low, int incl_high, unsigned int *seedp)
-{
- if (incl_high == 0)
- return 0;
-
- return incl_low + (rand_r(seedp) % incl_high);
-}
-
-
-
-
-/* the testing routines */
-
-static int glob_highwater = 0;
-struct ao2_container *glob_hashtab = 0;
-unsigned int glob_seed = 0;
-int els_removed = 0;
-int els_added = 0;
-int els_lookedup = 0;
-int els_found = 0;
-int els_traversals = 0;
-
-/* all the operations to perform on the hashtab */
-
-static void ht_destroy(void *obj)
-{
- const struct ht_element *o = obj;
- if (o->key)
- free(o->key);
- if (o->val)
- free(o->val);
-}
-
-
-static void add_element(void)
-{
- char keybuf[100];
- struct ht_element *x = ao2_alloc(sizeof(struct ht_element), ht_destroy);
- sprintf(keybuf,"key%08d", glob_highwater++);
- x->key = strdup(keybuf);
- x->val = strdup("interesting data");
-#ifdef DEBUG
- printf("+ %s\n", keybuf);
-#endif
- ao2_link(glob_hashtab, x);
-
- els_added++; /* unprotected, sometimes off, but, not really important, either */
-}
-
-static int do_nothing_cb(void *obj, void *arg, int flags)
-{
- return 0;
-}
-
-static void traverse_elements(void)
-{
-#ifdef DEBUG
- printf("Traverse hashtab\n");
-#endif
- ao2_callback(glob_hashtab, OBJ_NODATA, do_nothing_cb, NULL);
- els_traversals++; /* unprotected, sometimes off, but, not really important, either */
-}
-
-static void * del_element(unsigned int *seedp)
-{
- char keybuf[100];
- struct ht_element *el, lookup;
- int x;
-
- /* pick a random element from 0 to highwater-1 */
- x = my_rand(0,glob_highwater-1,seedp);
- sprintf(keybuf, "key%08d", x);
-#ifdef DEBUG
- printf("- %s", keybuf);
-#endif
- lookup.key = keybuf;
- el = ao2_find(glob_hashtab, &lookup, OBJ_POINTER);
- if (el) {
-#ifdef DEBUG
- printf("...YES (el=%x)\n", (unsigned long)el);
-#endif
- ao2_unlink(glob_hashtab, el); /* mistakenly tried to use ao2_ref(c,-2) here to unlink. Bad Boy! */
- els_removed++;
- } else {
-#ifdef DEBUG
- printf("...NO.\n");
-#endif
- return 0;
- }
- return el;
-}
-
-static int lookup_element(unsigned int *seedp)
-{
- char keybuf[100];
- struct ht_element *el, lookup;
- int x;
-
- /* pick a random element from 0 to highwater-1 */
- x = my_rand(0,glob_highwater-1,seedp);
- sprintf(keybuf, "key%08d", x);
- lookup.key = keybuf;
- el = ao2_find(glob_hashtab, &lookup, OBJ_POINTER);
- els_lookedup++;
- if (el) {
- els_found++;
- ao2_ref(el, -1); /* toss out this ref, no longer needed */
- return 1;
- } else {
- return 0;
- }
-}
-
-
-static void *hashtest(void *data)
-{
- int my_els_removed = 0;
- int my_els_added = 0;
- int my_els_lookedup = 0;
- int my_els_found = 0;
- int my_els_traversals = 0;
- int my_testno = testno++;
- int its;
-
- /* data will be a random number == use as a seed for random numbers */
- unsigned long seed = (unsigned long)data;
- printf("hashtest thread created... test beginning\n");
-
- /* main test routine-- a global hashtab exists, pound it like crazy */
- for(its=0;its<100000;its++)
- {
- void *seed2 = &seed;
- int op = my_rand(0,100, seed2);
- if (op<60) {
- my_els_lookedup++;
-#ifdef DEBUG
- printf("%d[%d]: LOOKUP\n", my_testno, its);
-#endif
- if ((my_els_lookedup%1000)==0) {
- printf(".");
- fflush(stdout);
- }
- if (lookup_element(seed2))
- my_els_found++;
- } else if (op < 61) { /* make this 61 and it'll take 16 minutes to run */
-#ifdef DEBUG
- printf("%d[%d]: TRAVERSE\n", my_testno, its);
-#endif
- traverse_elements();
- my_els_traversals++;
-
- } else if (op < 80) {
-#ifdef DEBUG
- printf("%d[%d]: REMOVE\n", my_testno, its);
-#endif
- if (del_element(seed2))
- my_els_removed++;
- } else {
- my_els_added++;
-#ifdef DEBUG
- printf("%d[%d]: ADD\n", my_testno, its);
-#endif
- add_element();
- }
- }
- printf("\nhashtest thread %d exiting.... lookups=%d/%d, added=%d, removed=%d, traversals=%d;\n",
- my_testno, my_els_found, my_els_lookedup, my_els_added, my_els_removed, my_els_traversals);
- printf("\ntotals..................... lookups=%d/%d, added=%d, removed=%d; traversals=%d\n",
- els_found, els_lookedup, els_added, els_removed, els_traversals);
- pthread_exit(0);
- return NULL;
-}
-
-static void run_hashtest(int numthr)
-{
- pthread_t thr[numthr];
- void *thrres[numthr];
- int i;
-
- /* init a single global hashtab, then... */
- glob_hashtab = ao2_container_alloc(180000, hash_string, hashtab_compare_strings);
-
- /* set a random seed */
- glob_seed = (unsigned int)time(0);
- srand(glob_seed);
-
- /* create threads, each running hashtest */
- for(i=0;i<numthr;i++)
- {
- unsigned long z = rand();
-
- printf("starting hashtest thread %d....\n",i+1);
- if (ast_pthread_create(&thr[i], NULL, hashtest, (void*)z)) {
- printf("Sorry, couldn't create thread #%d\n", i+1);
- }
- printf("hashtest thread spawned.... \n");
- }
- /* collect threads, each running hashtest */
- for(i=0;i<numthr;i++)
- {
- printf("waiting for thread %d....\n", i+1);
- if (pthread_join(thr[i], &thrres[i])) {
- printf("Sorry, couldn't join thread #%d\n", i+1);
- }
- printf("hashtest thread %d done.... \n",i+1);
- }
- /* user has to kill/intr the process to stop the test? */
-}
-
-
-int main(int argc,char **argv)
-{
- if (argc < 2 || argc > 2 || atoi(argv[1]) < 1)
- {
- printf("Usage: hashtest <number of threads>\n");
- exit(1);
- }
-
- /* one arg == number of threads to create */
- run_hashtest(atoi(argv[1]));
-
- return 0;
-}
-
-#if !defined(LOW_MEMORY)
-int ast_add_profile(const char *x, uint64_t scale)
-{
- return 0;
-}
-#endif
-
-int ast_loader_register(int (*updater)(void))
-{
- return 1;
-}
-
-int ast_loader_unregister(int (*updater)(void))
-{
- return 1;
-}
-void ast_module_register(const struct ast_module_info *x)
-{
-}
-
-void ast_module_unregister(const struct ast_module_info *x)
-{
-}
-
-
-void ast_register_file_version(const char *file, const char *version);
-void ast_register_file_version(const char *file, const char *version)
-{
-}
-
-void ast_unregister_file_version(const char *file);
-void ast_unregister_file_version(const char *file)
-{
-
-}
-
-void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
-{
- va_list vars;
- va_start(vars,fmt);
- printf("LOG: lev:%d file:%s line:%d func: %s ",
- level, file, line, function);
- vprintf(fmt, vars);
- fflush(stdout);
- va_end(vars);
-}
-
-void __ast_verbose(const char *file, int line, const char *func, const char *fmt, ...)
-{
- va_list vars;
- va_start(vars,fmt);
-
- printf("VERBOSE: ");
- vprintf(fmt, vars);
- fflush(stdout);
- va_end(vars);
-}
-
-void ast_register_thread(char *name)
-{
-
-}
-
-void ast_unregister_thread(void *id)
-{
-}
-
-#ifdef HAVE_BKTR
-struct ast_bt* ast_bt_create(void)
-{
- return NULL;
-}
-
-int ast_bt_get_addresses(struct ast_bt *bt)
-{
- return -1;
-}
-
-char **ast_bt_get_symbols(void **addresses, size_t num_frames)
-{
- char **foo = calloc(num_frames, sizeof(char *) + 1);
- if (foo) {
- int i;
- for (i = 0; i < num_frames; i++) {
- foo[i] = (char *) foo + sizeof(char *) * num_frames;
- }
- }
- return foo;
-}
-
-void *ast_bt_destroy(struct ast_bt *bt)
-{
- return NULL;
-}
-#endif
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/.cleancount
^
|
@@ -1,3 +1 @@
-39
-
-
+40
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/.lastclean
^
|
@@ -1,3 +1 @@
-39
-
-
+40
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/.version
^
|
@@ -1 +1 @@
-1.8.19.1
+1.8.20.0
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/ChangeLog
^
|
@@ -1,8 +1,12 @@
-2013-01-02 Asterisk Development Team <asteriskteam@digium.com>
+2013-01-14 Asterisk Development Team <asteriskteam@digium.com>
- * Asterisk 1.8.19.1 Released.
+ * Asterisk 1.8.20.0 Released.
- * AST-2012-015: Resolve crashes due to large stack allocations when
+2013-01-09 Asterisk Development Team <asteriskteam@digium.com>
+
+ * Asterisk 1.8.20.0-rc2 Released.
+
+ * AST-2012-014: Resolve crashes due to large stack allocations when
using TCP
Asterisk had several places where messages received over various
@@ -14,33 +18,571 @@
This patch modifies those portions of Asterisk using TCP to either
favor heap allocations or use an upper bound to ensure that the
stack will not overflow:
- * For SIP, the allocation now has an upper limit
- * For HTTP, the allocation is now a heap allocation instead of a
- stack allocation
- * For XMPP (in res_jabber), the allocation has been eliminated
- since it was unnecesary.
+ * For SIP, the allocation now has an upper limit
+ * For HTTP, the allocation is now a heap allocation instead of a
+ stack allocation
+ * For XMPP, the allocation has been eliminated since it was
+ unnecessary.
- * AST-2012-014: Prevent exhaustion of system resources through
- exploitation of event cache
+ * AST-2012-015: Prevent exhaustion of system resources through
+ exploitation of event cache
Asterisk maintains an internal cache for devices in the event
subsystem. The device state cache holds the state of each device
known to Asterisk, such that consumers of device state information
can query for the last known state for a particular device, even if
- it is not part of an active call. The concept of a device in Asterisk
- can include entities that do not have a physical representation. One
- way that this occurred was when anonymous calls are allowed in
- Asterisk. A device was automatically created and stored in the cache
- for each anonymous call that occurred; this was possible in the SIP
- and IAX2 channel drivers and through channel drivers that utilized
- the res_jabber/res_xmpp resource modules (Gtalk, Jingle, and Motif).
- These devices are never removed from the system, allowing anonymous
- calls to potentially exhaust a system's resources.
+ it is not part of an active call. The concept of a device in
+ Asterisk can include entities that do not have a physical
+ representation. One way that this occurred was when anonymous calls
+ are allowed in Asterisk. A device was automatically created and
+ stored in the cache for each anonymous call that occurred; this was
+ possible in the SIP and IAX2 channel drivers and through channel
+ drivers that utilized the res_jabber/res_xmpp resource modules (Gtalk,
+ Jingle, and Motif). These devices are never removed from the system,
+ allowing anonymous call to potentially exhaust a system's resources.
This patch changes the event cache subsystem and device state
management to no longer cache devices that are not associated with a
physical entity.
+ * Revert bad ringinuse=no patch.
+
+ With the option ringinuse=no set, the patch committed previous for
+ ASTERISK-16115 causes non-SIP queue members to never be called
+ because the device state is checked after a channel is created to
+ determine if the member is busy. These queue members always get the
+ "Member %s is busy, cannot dial" message.
+
+ Most channel drivers other than chan_sip use the default device
+ state handling. The default device state is considered in use or
+ unknown if the channel exists or not, respectively.
+
+ * Fix multiple calls to a queue member that is only in queue.
+
+ When ringinuse=no queue members can receive more than one call if
+ these calls happen at nearly the same time. This patch fixes it so a
+ queu member does not receive more than one call from a queue. note
+ that this fix does not prevent multiple calls to a member if hte
+ member is in more than one queue (see ASTERISK-16115).
+
+2012-12-10 Asterisk Development Team <asteriskteam@digium.com>
+
+ * Asterisk 1.8.20.0-rc1 Released.
+
+2012-12-10 01:38 +0000 [r377487-377509] Tilghman Lesher <tilghman@meg.abyt.es>
+
+ * main/xmldoc.c: Improve documentation by making all of the colors
+ used readable, no matter what the background color is. Dark blue
+ on a black background is unreadable, as is yellow on a light
+ background. This patch turns on the bright attribute for colors
+ when on a dark background and turns *off* the bright attribute
+ when the -W command line option is used (indicating a _light_
+ background). This ensures that text is readable in both cases.
+ Patch by: tilghman Review:
+ https://reviewboard.asterisk.org/r/2224
+
+ * addons/cdr_mysql.c: Remove some dead code and additionally handle
+ a case that wasn't handled.
+
+2012-12-08 00:28 +0000 [r377398-377431] Richard Mudgett <rmudgett@digium.com>
+
+ * contrib/realtime/mysql/sippeers.sql: Fix order of SIP
+ allow/disallow in MySQL contrib script. Using the contrib
+ sippeers.sql script to create the sippeers MySQL table would
+ result in being unable to place calls if you set the disallow
+ value to all. (closes issue ASTERISK-20756) Reported by: Andre
+ Luis Patches: sippeers.patch patch uploaded by Andre Luis
+
+ * main/astmm.c: MALLOC_DEBUG: Only wait if we want atexit
+ allocation dumps.
+
+2012-12-05 16:48 +0000 [r377257] Joshua Colp <jcolp@digium.com>
+
+ * channels/chan_sip.c: Fix a SIP request memory leak with TLS
+ connections. During the TLS re-work in chan_sip some TLS specific
+ code was moved into a separate function. This function operates
+ on a copy of the incoming SIP request. This copy was never
+ deinitialized causing a memory leak for each request processed.
+ This function is now given a SIP request structure which it can
+ use to copy the incoming request into. This reduces the amount of
+ memory allocations done since the internal allocated components
+ are reused between packets and also ensures the SIP request
+ structure is deinitialized when the TLS connection is torn down.
+ (closes issue ASTERISK-20763) Reported by: deti
+
+2012-12-05 16:46 +0000 [r377256] Jonathan Rose <jrose@digium.com>
+
+ * res/res_srtp.c: res_srtp: Fix a crash caused by srtp_dealloc on
+ an already dealloced session When srtp_create fails, the session
+ may be dealloced or just not alloced. At the same time though,
+ the session pointer might not be set to NULL in this process and
+ attempting to srtp_dealloc it again will cause a segfault. This
+ patch checks for failure of srtp_create and sets the session
+ pointer to NULL if it fails. (closes issue ASTERISK-20499)
+ Reported by: tootai Review:
+ https://reviewboard.asterisk.org/r/2228/
+
+2012-12-03 22:51 +0000 [r377037-377165] Richard Mudgett <rmudgett@digium.com>
+
+ * main/asterisk.c: Cleanup ast_run_atexits() atexits list. *
+ Convert atexits list to a mutex instead of a rd/wr lock. The lock
+ is only write locked. * Move CLI verbose Asterisk ending message
+ to where AMI message is output in really_quit() to avoid further
+ surprises about using stuff already shutdown. (issue
+ ASTERISK-20649) Reported by: Corey Farrell
+
+ * include/asterisk/_private.h, main/stdtime/localtime.c,
+ main/asterisk.c: Cleanup core main on exit. * Cleanup time zones
+ on exit. * Make exit clean/unclean report consistent for AMI and
+ CLI in really_quit(). (issue ASTERISK-20649) Reported by: Corey
+ Farrell Patches: core-cleanup-1_8-10.patch (license #5909) patch
+ uploaded by Corey Farrell core-cleanup-11-trunk.patch (license
+ #5909) patch uploaded by Corey Farrell Modified
+
+ * main/config.c: Cleanup config cache on exit. (issue
+ ASTERISK-20649) Reported by: Corey Farrell Patches:
+ config-cleanup-all.patch (license #5909) patch uploaded by Corey
+ Farrell
+
+ * main/cli.c: Cleanup CLI resources on exit and CLI command
+ registration errors. (issue ASTERISK-20649) Reported by: Corey
+ Farrell Patches: cli-leaks-1_8-10.patch (license #5909) patch
+ uploaded by Corey Farrell cli-leaks-11-trunk.patch (license
+ #5909) patch uploaded by Corey Farrell Modified
+
+ * main/cdr.c: Cleanup CDR resources on exit. * Simplify do_reload()
+ return handling since it never returned anything other than 0.
+ (issue ASTERISK-20649) Reported by: Corey Farrell Patches:
+ cdr-cleanup-1_8.patch (license #5909) patch uploaded by Corey
+ Farrell cdr-cleanup-10-11-trunk.patch (license #5909) patch
+ uploaded by Corey Farrell Modified
+
+ * main/ccss.c: Fix CCSS CLI commands and logger level not
+ unregistered. (issue ASTERISK-20649) Reported by: Corey Farrell
+ Patches: ccss-cleanup-all.patch (license #5909) patch uploaded by
+ Corey Farrell
+
+2012-11-30 21:30 +0000 [r376950] Richard Mudgett <rmudgett@digium.com>
+
+ * channels/misdn/isdn_lib.c: chan_misdn: Fix sending
+ RELEASE_COMPLETE in response to SETUP. Fix sending a
+ RELEASE_COMPLETE in response to a SETUP if chan_misdn does not
+ have a B channel available to assign to the call. (closes issue
+ ABE-2869) Reported by: Guenther Kelleter Patches:
+ setup-reject_2.diff (license #6372) patch uploaded by Guenther
+ Kelleter Modified ........ Merged revision 376949 from
+ https://origsvn.digium.com/svn/asterisk/be/branches/C.3-bier
+
+2012-11-30 17:04 +0000 [r376919] Sean Bright <sean@malleable.com>
+
+ * funcs/func_volume.c: Minor spelling fix to the VOLUME
+ documentation.
+
+2012-11-30 16:12 +0000 [r376901] Mark Michelson <mmichelson@digium.com>
+
+ * channels/chan_sip.c: Fix potential crashes during SIP attended
+ transfers. The principal behind this patch is simple. During a
+ transfer, we manipulate channels that are owned by a separate
+ thread than the one we currently are running in, so it makes
+ sense that we need to grab a reference to the channels so that
+ they cannot disappear out from under us. In the wild, crashes
+ were sometimes seen when the transferring party would hang up the
+ call before the transfer target answered the call. The most
+ common place to see the crash occur was when attempting to send a
+ connected line update to the transferer channel. (closes issue
+ ASTERISK-20226) Reported by Jared Smith Patches:
+ ASTERISK-20226.patch uploaded by Mark Michelson (License #5049)
+ Tested by: Jared Smith
+
+2012-11-29 22:55 +0000 [r376864-376868] Richard Mudgett <rmudgett@digium.com>
+
+ * channels/chan_local.c: chan_local: Fix local_pvt ref leak in
+ local_devicestate(). Regression introduced by ASTERISK-20390 fix.
+ (closes issue ASTERISK-20769) Reported by: rmudgett Tested by:
+ rmudgett
+
+ * channels/chan_sip.c: Fix compile error. (issue ASTERISK-20724)
+
+2012-11-29 21:49 +0000 [r376834] Michael L. Young <elgueromexicano@gmail.com>
+
+ * channels/chan_sip.c: Improve Code Readability And Fix Setting
+ natdetected Flag For 1.8, 10, 11 and trunk we are are improving
+ the code readability. For 11 and trunk, auto nat detection was
+ added. The natdetected flag was being set to 1 when the host
+ address in the VIA header did not specifiy a port. This patch
+ fixes this by setting the port on the temporary sock address used
+ to SIP_STANDARD_PORT in order for the sock address comparison to
+ work properly. (closes issue ASTERISK-20724) Reported by: Michael
+ L. Young Patches: asterisk-20724-set-port-v2.diff uploaded by
+ Michael L. Young (license 5026) Review:
+ https://reviewboard.asterisk.org/r/2206/
+
+2012-11-29 00:42 +0000 [r376758-376788] Richard Mudgett <rmudgett@digium.com>
+
+ * main/astmm.c, main/asterisk.c: Add MALLOC_DEBUG atexit unreleased
+ malloc memory summary. * Adds the following CLI commands to
+ control MALLOC_DEBUG reporting of unreleased malloc memory when
+ Asterisk is shut down. memory atexit list on memory atexit list
+ off memory atexit summary byline memory atexit summary byfunc
+ memory atexit summary byfile memory atexit summary off * Made
+ check all remaining allocated region blocks atexit for fence
+ violations. * Increased the allocated region hash table size by
+ about three times. It still isn't large enough considering the
+ number of malloced blocks Asterisk uses. * Made CLI "memory show
+ allocations anomalies" use regions_check_all_fences(). Review:
+ https://reviewboard.asterisk.org/r/2196/
+
+ * main/astmm.c: Enhance MALLOC_DEBUG CLI commands. * Fixed CLI
+ "memory show allocations" misspelling of anomalies option. The
+ command will still accept the original misspelling. *
+ Miscellaneous tweaks to CLI "memory show allocations" command
+ output format. * Made CLI "memory show summary" summarize by line
+ number instead of by function if a filename is given. * Made CLI
+ "memory show summary" sort its output by filename or
+ function-name/line-number depending upon request. * Miscellaneous
+ tweaks to CLI "memory show summary" command output format.
+
+2012-11-28 16:23 +0000 [r376725] Jonathan Rose <jrose@digium.com>
+
+ * main/manager.c: manager: Make challenge work with
+ allowmultiplelogin=no Prior to this patch, challenge would yield
+ a multiple logins error if used without providing the username
+ (which isn't really supposed to be an argument to challenge) if
+ allowmultiplelogin was set to no because allowmultiplelogin finds
+ a user with a zero length login name. This check is simply
+ disabled for the challenge action when the username is empty by
+ this patch. (closes issue ASTERISK-20677) Reported by: Vladimir
+ Patches: challenge_action_nomultiplelogin.diff uploaded by
+ Jonathan Rose (license 6182)
+
+2012-11-27 23:47 +0000 [r376627-376688] Richard Mudgett <rmudgett@digium.com>
+
+ * UPGRADE.txt, main/pbx.c: Fix extension matching with the '-'
+ char. The '-' char is supposed to be ignored by the dialplan
+ extension matching. Unfortunately, it's treatment is not handled
+ consistently throughout the extension matching code. * Made the
+ old exten matching code consistently ignore '-' chars. * Made the
+ old exten matching code consistently handle case in the matching.
+ * Made ignore empty character sets. * Fixed ast_extension_cmp()
+ to return -1, 0, or 1 as documented. The only user of it in
+ pbx_lua.c was testing for -1. It was originally returning the
+ strcmp() value for less than which is not usually going to be -1.
+ * Fix character set sorting if the sets have the same number of
+ characters and start with the same character. Character set [0-9]
+ now sorts before [02-9a] as originally intended. * Updated some
+ extension label and priority already in use warnings to also
+ indicate if the extension is aliased. (closes issue
+ ASTERISK-19205) Reported by: Philippe Lindheimer, Birger "WIMPy"
+ Harzenetter Tested by: rmudgett Review:
+ https://reviewboard.asterisk.org/r/2201/
+
+ * pbx/pbx_dundi.c, addons/res_config_mysql.c,
+ apps/app_celgenuserevent.c: Remove unnecessary channel module
+ references. * Removed call to ast_module_user_hangup_all() in
+ res_config_mysql.c since it is effectively a noop. No channels
+ can attach a reference to that module. * Removed call to
+ ast_module_user_hangup_all() in app_celgenuserevent.c. The caller
+ of unload_module() has already called it. * Removed redundant
+ channel module references in pbx_dundi.c. The registered dialplan
+ function callback dispatchers for the read/read2/write callbacks
+ already reference the module before calling. * pbx_dundi: Moved
+ unregistering CLI commands, DUNDi switch, and dialplan functions
+ to the first thing the unload_module() does. This will reduce the
+ chance of new channels using DUNDi services while the module is
+ being torn down.
+
+ * include/asterisk/linkedlists.h: Made AST_LIST_REMOVE() simpler
+ and use better names. * Update doxygen of AST_LIST_REMOVE().
+
+2012-11-22 23:51 +0000 [r376586] Matthew Jordan <mjordan@digium.com>
+
+ * include/asterisk/lock.h, main/lock.c, main/logger.c:
+ Re-initialize logmsgs mutex upon logger initialization to prevent
+ lock errors Similar to the patch that moved the fork earlier in
+ the startup sequence to prevent mutex errors in the recursive
+ mutex surrounding the read/write thread registration lock, this
+ patch re-initializes the logmsgs mutex. Part of the start up
+ sequence before forking the process into the background includes
+ reading asterisk.conf; this has to occur prior to the call to
+ daemon in order to read startup parameters. When reading in a
+ conf file, log statements can be generated. Since this can't be
+ avoided, the mutex instead is re-initialized to ensure a reset of
+ any thread tracking information. This patch also includes some
+ additional debugging to catch errors when locking or unlocking
+ the recursive mutex that surrounds locks when the DEBUG_THREADS
+ build option is enabled. DO_CRASH or THREAD_CRASH will cause an
+ abort() if a mutex error is detected. (issue ASTERISK-19463)
+ Reported by: mjordan Tesetd by: mjordan
+
+2012-11-20 16:45 +0000 [r376521] Mark Michelson <mmichelson@digium.com>
+
+ * channels/sip/include/sip.h, channels/chan_sip.c: Add "Require:
+ timer" to 200 OK responses when appropriate. The method by which
+ the Require header is added to 200 responses is inspired by the
+ method that Olle Johansson uses in his darjeeling-prack branch.
+ (closes issue ASTERISK-20570) Reported by Matt Jordan, at the
+ behest of Olle Johansson Review:
+ https://reviewboard.asterisk.org/r/2172
+
+2012-11-19 19:30 +0000 [r376469] Walter Doekes <walter+asterisk@wjd.nu>
+
+ * main/indications.c, channels/chan_sip.c, main/security_events.c:
+ Fix most leftover non-opaque ast_str uses. Instead of calling
+ str->str, one should use ast_str_buffer(str). Same goes for
+ str->used as ast_str_strlen(str) and str->len as
+ ast_str_size(str). Review:
+ https://reviewboard.asterisk.org/r/2198
+
+2012-11-18 20:11 +0000 [r376428] Matthew Jordan <mjordan@digium.com>
+
+ * main/utils.c, main/stdtime/localtime.c, main/asterisk.c: Reorder
+ startup sequence to prevent lockups when process is sent to
+ background Although it is very rare and timing dependent, the
+ potential exists for the call to 'daemon' to cause what appears
+ to be a deadlock in Asterisk during startup. This can occur when
+ a recursive mutex is obtained prior to the daemon call executing.
+ Since daemon uses fork to send the process into the background,
+ any threading primitives are unsafe to re-use after the call.
+ Implementations of pthread recursive mutexes are highly likely to
+ store the thread identifier of the thread that previously
+ obtained the mutex. If the mutex was locked prior to the fork, a
+ subsequent unlock operation will potentially fail as the thread
+ identifier is no longer valid. Since the mutex is still locked,
+ all subsequent attempts to grab the mutex by other threads will
+ block. This behavior exhibited itself most often when
+ DEBUG_THREADS was enabled, as this compile time option surrounds
+ the mutexes in Asterisk with another recursive mutex that
+ protects the storage of thread related information. This made it
+ much more likely that a recursive mutex would be obtained prior
+ to daemon and unlocked after the call. This patch does the
+ following: a) It backports a patch from Asterisk 11 that prevents
+ the spawning of the localtime monitoring thread. This thread is
+ now spawned after Asterisk has fully booted. b) It re-orders the
+ startup sequence to call daemon earlier during Asterisk startup.
+ This limits the potential of threading primitives being accessed
+ by initialization calls before daemon is called. c) It removes
+ calls to ast_verbose/ast_log/etc. prior to daemon being called.
+ Developers should send error messages directly to stderr prior to
+ daemon, as calls to ast_log may access recursive mutexes that
+ store thread related information. d) It reorganizes when thread
+ local storage is created for storing lock information during the
+ creation of threads. Prior to this patch, the read/write lock
+ protecting the list of threads in ast_register_thread would
+ utilize the lock in the thread local storage prior to it being
+ initialized; this patch prevents that. On a very related note,
+ this patch will *greatly* improve the stability of the Asterisk
+ Test Suite. Review: https://reviewboard.asterisk.org/r/2197
+ (closes issue ASTERISK-19463) Reported by: mjordan Tested by:
+ mjordan
+
+2012-11-16 19:31 +0000 [r376389] Jonathan Rose <jrose@digium.com>
+
+ * res/res_monitor.c: monitor: prevent attempts to move/remove
+ recordings skipped with 'i' and 'o'. The i and o options for
+ monitor skip the input and output sides of a recording
+ respectively. This patch addresses a problem in those options
+ when monitor is called without specifying a specific filename
+ where monitor will try to move the recording that was skipped.
+ Since this usually doesn't exist when these options are used, it
+ would produce a warning when it does this in most cases, but it
+ is conceivable that there are use cases where this could result
+ in moving/removing a file unintentionally. (closes issue
+ ASTERISK-20641) Reported by: Jonathan Rose Review:
+ https://reviewboard.asterisk.org/r/2190/
+
+2012-11-15 23:58 +0000 [r376340] David M. Lee <dlee@digium.com>
+
+ * utils/extconf.c: Fixed extconf.c breakage introduced in r376306.
+ To quote wdoekes: > Note that I'm not confirming legitimacy of
+ having that file in tree at > all. Is anyone using
+ aelparse/conf2ael?
+
+2012-11-15 22:40 +0000 [r376307] Jonathan Rose <jrose@digium.com>
+
+ * apps/app_meetme.c: app_meetme: Fix channels lingering when hung
+ up under certain conditions Channels would get stuck and MeetMe
+ would repeatedly display an Unable to write frame to channel
+ error in the conf_run function if hung up during certain sound
+ prompts such as during user count announcements. This patch fixes
+ that by reintroducing a hangup check in the meetme's main loop
+ (also in conf_run). (closes issue ASTERISK-20486) Reported by:
+ Michael Cargile Review: https://reviewboard.asterisk.org/r/2187/
+ Patches: meetme_hangup_patch_ASTERISK-20486_v3.diff uploaded by
+ Jonathan Rose (license 6182)
+
+2012-11-15 22:27 +0000 [r376306] David M. Lee <dlee@digium.com>
+
+ * tests/test_hashtab_thrash.c (added), utils/hashtest2.c (removed),
+ include/asterisk/hashtab.h, utils/Makefile,
+ tests/test_astobj2_thrash.c (added), utils/utils.xml,
+ utils/hashtest.c (removed): Migrate hashtest/hashtest2 to be unit
+ tests. Both hashtest and hashtest2 are manual testing apps that
+ thrash hash tables (hashtab and ao2 containers, respectively), by
+ spinning up several threads that randomly insert, delete, lookup
+ and iterate over the hash table. If the app doesn't crash, the
+ hash table probably passes the test. Those utils are not a part
+ of the typical Asterisk build, so they do not usually get
+ compiled. This all makes them less that useful. This patch
+ removes those manual test programs and replaces them with
+ Asterisk unit test modules (test_{hashtab,astobj2}_thrash.so). It
+ also attempts to make the tests more deterministic. * Rather than
+ spinning up some number of threads that operate on the hash table
+ randomly, spin up four threads that concurrenly add, remove,
+ lookup and iterate over the hash table. * Each thread checks the
+ state of the hash table both during and after execution, and
+ indicates a test failure if things are not as expected. * Each
+ thread times out after 60 seconds to prevent deadlocking the unit
+ test run. (closes issue ASTERISK-20505) Reported by: Matt Jordan
+ Review: https://reviewboard.asterisk.org/r/2189/
+
+2012-11-15 01:43 +0000 [r376262] Rusty Newton <rnewton@digium.com>
+
+ * apps/app_voicemail.c: Patch to play correct sound file when a
+ voicemail's urgent status is removed We were attempting to play
+ "vm-urgent-removed", which didn't exist. Now we play
+ "vm-marked-nonurgent" which exists and is the correct sound file.
+ Previous behavior was silence and a warning on the CLI. (issue
+ ASTERISK-20280) (closes issue ASTERISK-20280) Reported by: Tomo
+ Takebe Tested by: Rusty Newton Patches: asterisk20280.patch
+ uploaded by Rusty Newton (license 5829)
+
+2012-11-14 19:48 +0000 [r376232] Richard Mudgett <rmudgett@digium.com>
+
+ * pbx/pbx_spool.c: Fix call files when astspooldir is relative.
+ Future dated call files are ignored when astspooldir is relative
+ to the current directory. The queue_file() assumed that the qdir
+ needed to be prepended if the given filename did not start with a
+ '/'. If astspooldir is relative it is not going to start from the
+ root directory obviously so it will not start with a '/'. The
+ filename used in queue_file() ultimately results in qdir
+ prepended multiple times. * Made queue_file() not prepend qdir if
+ the filename contains a '/'. (closes issue ASTERISK-20593)
+ Reported by: James Le Cuirot Patches:
+ 0004-Fix-future-call-files-from-relative-directories.patch
+ (license #6439) patch uploaded by James Le Cuirot
+
+2012-11-13 18:10 +0000 [r376199] Brent Eagles <beagles@digium.com>
+
+ * main/channel.c: Patch to prevent stopping the active generator
+ when it is not the silence generator. This patch introduces an
+ internal helper function to safely check whether the current
+ generator is the one that is expected before deactivating it. The
+ current externally accessible ast_channel_stop_generator()
+ function has been modified to be implemented in terms of the new
+ function. (closes issue ASTERISK-19918) Reported by: Eduardo Abad
+
+2012-11-12 20:44 +0000 [r376166] Joshua Colp <jcolp@digium.com>
+
+ * main/pbx.c: Properly check if the "Context" and "Extension"
+ headers are empty in a ShowDialPlan action. The code which
+ handles the ShowDialPlan action wrongly assumed that a non-NULL
+ return value from the function which retrieves headers from an
+ action indicates that the header has a value. This is incorrect
+ and the contents must be checked to see if they are blank.
+ (closes issue ASTERISK-20628) Reported by: jkroon Patches:
+ asterisk-showdialplan-incorrect-error.patch uploaded by jkroon
+
+2012-11-12 20:13 +0000 [r376142] Michael L. Young <elgueromexicano@gmail.com>
+
+ * main/pbx.c: Fix Dynamic Hints Variable Substition - Underscore
+ Problem When adding a dynamic hint, if an extension contains an
+ underscore no variable subsitution is being performed. This patch
+ changes from checking if the extension contains an underscore to
+ checking if the extension begins with an underscore. (closes
+ issue ASTERISK-20639) Reported by: Steven T. Wheeler Tested by:
+ Steven T. Wheeler, Michael L. Young Patches:
+ asterisk-20639-dynamic-hint-underscore.diff uploaded by Michael
+ L. Young (license 5026) Review:
+ https://reviewboard.asterisk.org/r/2188/
+
+2012-11-08 21:56 +0000 [r376087] Mark Michelson <mmichelson@digium.com>
+
+ * res/res_fax.c: Fix a "set but not used" warning on newer gccs.
+ Turns out the "helpful" setting of ms and res in this macro is
+ completely useless after the timeout antipattern fix. If you're a
+ new guy looking to write code, don't write a macro like this one.
+
+2012-11-08 21:05 +0000 [r376029-376058] Richard Mudgett <rmudgett@digium.com>
+
+ * channels/sig_ss7.c: chan_dahdi/SS7: Made reject incoming call for
+ an in-alarm or blocked channel. If a SS7 call comes in requesting
+ a CIC that is in-alarm, the call is accepted and connects if the
+ extension exists in the dialplan. The call does not have any
+ audio. * Made release the call immediately with circuit
+ congestion cause. (closes issue ASTERISK-20204) Reported by: Tuan
+ Le Patches: jira_asterisk_20204_v1.8.patch (license #5621) patch
+ uploaded by rmudgett
+
+ * main/utils.c, main/astmm.c, main/asterisk.c,
+ include/asterisk/utils.h, include/asterisk/astmm.h: Add
+ MALLOC_DEBUG enhancements. * Makes malloc() behave like calloc().
+ It will return a memory block filled with 0x55. A nonzero value.
+ * Makes free() fill the released memory block and boundary
+ fence's with 0xdeaddead. Any pointer use after free is going to
+ have a pointer pointing to 0xdeaddead. The 0xdeaddead pointer is
+ usually an invalid memory address so a crash is expected. * Puts
+ the freed memory block into a circular array so it is not reused
+ immediately. * When the circular array rotates out a memory block
+ to the heap it checks that the memory has not been altered from
+ 0xdeaddead. * Made the astmm_log message wording better. * Made
+ crash if the DO_CRASH menuselect option is enabled and something
+ is found. * Fixed a potential alignment issue on 64 bit systems.
+ struct ast_region.data[] should now be aligned correctly for all
+ platforms. * Extracted region_check_fences() from
+ __ast_free_region() and handle_memory_show(). * Updated
+ handle_memory_show() CLI usage help. Review:
+ https://reviewboard.asterisk.org/r/2182/
+
+2012-11-07 17:08 +0000 [r375993-375994] Mark Michelson <mmichelson@digium.com>
+
+ * channels/chan_sip.c: Remove some debugging that accidentally made
+ it in the last commit.
+
+ * main/utils.c, include/asterisk/channel.h, apps/app_queue.c,
+ channels/sig_pri.c, channels/chan_iax2.c, main/channel.c,
+ channels/chan_dahdi.c, channels/sig_analog.c,
+ apps/app_waitforring.c, include/asterisk/time.h, apps/app_jack.c,
+ apps/app_dial.c, main/pbx.c, main/rtp_engine.c,
+ channels/chan_sip.c, apps/app_meetme.c, res/res_fax.c,
+ apps/app_record.c, channels/chan_agent.c: Fix misuses of timeouts
+ throughout the code. Prior to this change, a common method for
+ determining if a timeout was reached was to call a function such
+ as ast_waitfor_n() and inspect the out parameter that told how
+ many milliseconds were left, then use that as the input to
+ ast_waitfor_n() on the next go-around. The problem with this is
+ that in some cases, submillisecond timeouts can occur, resulting
+ in the out parameter not decreasing any. When this happens
+ thousands of times, the result is that the timeout takes much
+ longer than intended to be reached. As an example, I had a
+ situation where a 3 second timeout took multiple days to finally
+ end since most wakeups from ast_waitfor_n() were under a
+ millisecond. This patch seeks to fix this pattern throughout the
+ code. Now we log the time when an operation began and find the
+ difference in wall clock time between now and when the event
+ started. This means that sub-millisecond timeouts now cannot play
+ havoc when trying to determine if something has timed out. Part
+ of this fix also includes changing the function ast_waitfor() so
+ that it is possible for it to return less than zero when a
+ negative timeout is given to it. This makes it actually possible
+ to detect errors in ast_waitfor() when there is no timeout.
+ (closes issue ASTERISK-20414) reported by David M. Lee Review:
+ https://reviewboard.asterisk.org/r/2135/
+
+2012-11-06 18:18 +0000 [r375964] Richard Mudgett <rmudgett@digium.com>
+
+ * include/asterisk/channel.h, .cleancount,
+ include/asterisk/features.h, main/channel.c, main/features.c: Fix
+ stuck DTMF when bridge is broken. When a bridge is broken by an
+ AMI Redirect action or the ChannelRedirect application, an in
+ progress DTMF digit could be stuck sending forever. * Made
+ simulate a DTMF end event when a bridge is broken and a DTMF
+ digit was in progress. (closes issue ASTERISK-20492) Reported by:
+ Jeremiah Gowdy Patches: bridge_end_dtmf-v3.patch.txt (license
+ #6358) patch uploaded by Jeremiah Gowdy Modified to
+ jira_asterisk_20492_v1.8.patch jira_asterisk_20492_v1.8.patch
+ (license #5621) patch uploaded by rmudgett Tested by: rmudgett
+ Review: https://reviewboard.asterisk.org/r/2169/
+
2012-12-10 Asterisk Development Team <asteriskteam@digium.com>
* Asterisk 1.8.19.0 Released.
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/UPGRADE.txt
^
|
@@ -17,6 +17,11 @@
=== UPGRADE-1.6.txt -- Upgrade info for 1.4 to 1.6
===
===========================================================
+from 1.8.19 to 1.8.20:
+* Asterisk has always had code to ignore dash '-' characters that are not
+ part of a character set in the dialplan extensions. The code now
+ consistently ignores these characters when matching dialplan extensions.
+
from 1.8.18 to 1.8.19:
* Queue strategy rrmemory now has a predictable order similar to strategy
rrordered. Members will be called in the order that they are added to the
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/addons/cdr_mysql.c
^
|
@@ -42,7 +42,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 360712 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 377487 $")
#include <mysql/mysql.h>
#include <mysql/errmsg.h>
@@ -430,6 +430,9 @@
int res;
struct ast_config *cfg;
struct ast_variable *var;
+ /* CONFIG_STATUS_FILEUNCHANGED is impossible when config_flags is always 0,
+ * and it has to be zero, so a reload can be sent to tell the driver to
+ * rescan the table layout. */
struct ast_flags config_flags = { 0 };
struct column *entry;
char *temp;
@@ -445,11 +448,13 @@
* have changed, which is not detectable by config file change detection,
* but should still cause the configuration to be re-parsed. */
cfg = ast_config_load(config, config_flags);
- if (!cfg) {
+ if (cfg == CONFIG_STATUS_FILEMISSING) {
ast_log(LOG_WARNING, "Unable to load config for mysql CDR's: %s\n", config);
return AST_MODULE_LOAD_SUCCESS;
- } else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
- return AST_MODULE_LOAD_SUCCESS;
+ } else if (cfg == CONFIG_STATUS_FILEINVALID) {
+ ast_log(LOG_ERROR, "Unable to load configuration file '%s'\n", config);
+ return AST_MODULE_LOAD_DECLINE;
+ }
if (reload) {
AST_RWLIST_WRLOCK(&columns);
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/addons/res_config_mysql.c
^
|
@@ -30,7 +30,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 370642 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376657 $")
#include <sys/stat.h>
@@ -1395,9 +1395,6 @@
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime unloaded.\n");
- ast_module_user_hangup_all();
-
- usleep(1);
AST_RWLIST_WRLOCK(&databases);
while ((cur = AST_RWLIST_REMOVE_HEAD(&databases, list))) {
mysql_close(&cur->handle);
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/apps/app_celgenuserevent.c
^
|
@@ -29,7 +29,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 340863 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376657 $")
#include "asterisk/module.h"
#include "asterisk/app.h"
@@ -80,13 +80,8 @@
static int unload_module(void)
{
- int res;
-
- res = ast_unregister_application(app);
-
- ast_module_user_hangup_all();
-
- return res;
+ ast_unregister_application(app);
+ return 0;
}
static int load_module(void)
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/apps/app_confbridge.c
^
|
@@ -32,7 +32,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378341 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#include <stdio.h>
#include <stdlib.h>
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/apps/app_dial.c
^
|
@@ -33,7 +33,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 375025 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 375993 $")
#include <sys/time.h>
#include <sys/signal.h>
@@ -1055,6 +1055,7 @@
int is_cc_recall;
int cc_frame_received = 0;
int num_ringing = 0;
+ struct timeval start = ast_tvnow();
ast_party_connected_line_init(&connected_caller);
if (single) {
@@ -1095,7 +1096,7 @@
ast_poll_channel_add(in, epollo->chan);
#endif
- while (*to && !peer) {
+ while ((*to = ast_remaining_ms(start, orig)) && !peer) {
struct chanlist *o;
int pos = 0; /* how many channels do we handle */
int numlines = prestart;
@@ -1626,10 +1627,13 @@
skip_frame:;
ast_frfree(f);
}
- if (!*to)
- ast_verb(3, "Nobody picked up in %d ms\n", orig);
- if (!*to || ast_check_hangup(in))
- ast_cdr_noanswer(in->cdr);
+ }
+
+ if (!*to) {
+ ast_verb(3, "Nobody picked up in %d ms\n", orig);
+ }
+ if (!*to || ast_check_hangup(in)) {
+ ast_cdr_noanswer(in->cdr);
}
#ifdef HAVE_EPOLL
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/apps/app_jack.c
^
|
@@ -42,7 +42,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 360360 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 375993 $")
#include <limits.h>
@@ -768,7 +768,9 @@
while (!jack_data->stop) {
struct ast_frame *f;
- ast_waitfor(chan, -1);
+ if (ast_waitfor(chan, -1) < 0) {
+ break;
+ }
f = ast_read(chan);
if (!f) {
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/apps/app_meetme.c
^
|
@@ -36,7 +36,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378341 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#include <dahdi/user.h>
@@ -1869,7 +1869,7 @@
/* when no frames are available, this will wait
for 1 millisecond maximum
*/
- while (ast_waitfor(chan, 1)) {
+ while (ast_waitfor(chan, 1) > 0) {
f = ast_read(chan);
if (f)
ast_frfree(f);
@@ -3209,6 +3209,11 @@
break;
}
+ /* Perform a hangup check here since ast_waitfor_nandfds will not always be able to get a channel after a hangup has occurred */
+ if (ast_check_hangup(chan)) {
+ break;
+ }
+
c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
if (c) {
@@ -3293,12 +3298,12 @@
}
if (musiconhold) {
- ast_moh_stop(chan);
+ ast_moh_stop(chan);
}
if (menu8_active) {
/* *8 Submenu */
dtmf = f->subclass.integer;
- if (dtmf) {
+ if (dtmf > 0) {
int keepplaying;
int playednamerec;
struct ao2_iterator user_iter;
@@ -3457,7 +3462,7 @@
} else {
dtmf = f->subclass.integer;
}
- if (dtmf) {
+ if (dtmf > 0) {
switch(dtmf) {
case '1': /* Un/Mute */
menu_active = 0;
@@ -3564,7 +3569,7 @@
} else {
dtmf = f->subclass.integer;
}
- if (dtmf) {
+ if (dtmf > 0) {
switch (dtmf) {
case '1': /* Un/Mute */
menu_active = 0;
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/apps/app_queue.c
^
|
@@ -63,7 +63,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 375450 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#include <sys/time.h>
#include <sys/signal.h>
@@ -1046,6 +1046,7 @@
struct call_queue *lastqueue; /*!< Last queue we received a call */
unsigned int dead:1; /*!< Used to detect members deleted in realtime */
unsigned int delme:1; /*!< Flag to delete entry on reload */
+ unsigned int call_pending:1; /*!< TRUE if the Q is attempting to place a call to the member. */
char rt_uniqueid[80]; /*!< Unique id of realtime member entry */
};
@@ -3079,6 +3080,112 @@
return vars;
}
+/*!
+ * \internal
+ * \brief Check if the member status is available.
+ *
+ * \param status Member status to check if available.
+ *
+ * \retval non-zero if the member status is available.
+ */
+static int member_status_available(int status)
+{
+ return status == AST_DEVICE_NOT_INUSE || status == AST_DEVICE_UNKNOWN;
+}
+
+/*!
+ * \internal
+ * \brief Clear the member call pending flag.
+ *
+ * \param mem Queue member.
+ *
+ * \return Nothing
+ */
+static void member_call_pending_clear(struct member *mem)
+{
+ ao2_lock(mem);
+ mem->call_pending = 0;
+ ao2_unlock(mem);
+}
+
+/*!
+ * \internal
+ * \brief Set the member call pending flag.
+ *
+ * \param mem Queue member.
+ *
+ * \retval non-zero if call pending flag was already set.
+ */
+static int member_call_pending_set(struct member *mem)
+{
+ int old_pending;
+
+ ao2_lock(mem);
+ old_pending = mem->call_pending;
+ mem->call_pending = 1;
+ ao2_unlock(mem);
+
+ return old_pending;
+}
+
+/*!
+ * \internal
+ * \brief Determine if can ring a queue entry.
+ *
+ * \param qe Queue entry to check.
+ * \param call Member call attempt.
+ *
+ * \retval non-zero if an entry can be called.
+ */
+static int can_ring_entry(struct queue_ent *qe, struct callattempt *call)
+{
+ if (call->member->paused) {
+ ast_debug(1, "%s paused, can't receive call\n", call->interface);
+ return 0;
+ }
+
+ if (!qe->parent->ringinuse && !member_status_available(call->member->status)) {
+ ast_debug(1, "%s not available, can't receive call\n", call->interface);
+ return 0;
+ }
+
+ if ((call->lastqueue && call->lastqueue->wrapuptime && (time(NULL) - call->lastcall < call->lastqueue->wrapuptime))
+ || (!call->lastqueue && qe->parent->wrapuptime && (time(NULL) - call->lastcall < qe->parent->wrapuptime))) {
+ ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
+ (call->lastqueue ? call->lastqueue->name : qe->parent->name),
+ call->interface);
+ return 0;
+ }
+
+ if (use_weight && compare_weight(qe->parent, call->member)) {
+ ast_debug(1, "Priority queue delaying call to %s:%s\n",
+ qe->parent->name, call->interface);
+ return 0;
+ }
+
+ if (!qe->parent->ringinuse) {
+ if (member_call_pending_set(call->member)) {
+ ast_debug(1, "%s has another call pending, can't receive call\n",
+ call->interface);
+ return 0;
+ }
+
+ /*
+ * The queue member is available. Get current status to be sure
+ * because the device state and extension state callbacks may
+ * not have updated the status yet.
+ */
+ if (!member_status_available(get_queue_member_status(call->member))) {
+ ast_debug(1, "%s actually not available, can't receive call\n",
+ call->interface);
+ member_call_pending_clear(call->member);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
/*!
* \brief Part 2 of ring_one
*
@@ -3102,42 +3209,15 @@
const char *macrocontext, *macroexten;
/* on entry here, we know that tmp->chan == NULL */
- if ((tmp->lastqueue && tmp->lastqueue->wrapuptime && (time(NULL) - tmp->lastcall < tmp->lastqueue->wrapuptime)) ||
- (!tmp->lastqueue && qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime))) {
- ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
- (tmp->lastqueue ? tmp->lastqueue->name : qe->parent->name), tmp->interface);
- if (qe->chan->cdr)
- ast_cdr_busy(qe->chan->cdr);
- tmp->stillgoing = 0;
- (*busies)++;
- return 0;
- }
-
- if (!qe->parent->ringinuse && (tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
- ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
- if (qe->chan->cdr)
- ast_cdr_busy(qe->chan->cdr);
- tmp->stillgoing = 0;
- (*busies)++;
- return 0;
- }
-
- if (tmp->member->paused) {
- ast_debug(1, "%s paused, can't receive call\n", tmp->interface);
- if (qe->chan->cdr)
- ast_cdr_busy(qe->chan->cdr);
- tmp->stillgoing = 0;
- (*busies)++;
- return 0;
- }
- if (use_weight && compare_weight(qe->parent,tmp->member)) {
- ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
- if (qe->chan->cdr)
+ if (!can_ring_entry(qe, tmp)) {
+ if (qe->chan->cdr) {
ast_cdr_busy(qe->chan->cdr);
+ }
tmp->stillgoing = 0;
- (*busies)++;
+ ++*busies;
return 0;
}
+ ast_assert(qe->parent->ringinuse || tmp->member->call_pending);
ast_copy_string(tech, tmp->interface, sizeof(tech));
if ((location = strchr(tech, '/')))
@@ -3148,17 +3228,18 @@
/* Request the peer */
tmp->chan = ast_request(tech, qe->chan->nativeformats, qe->chan, location, &status);
if (!tmp->chan) { /* If we can't, just go on to the next call */
- if (qe->chan->cdr)
- ast_cdr_busy(qe->chan->cdr);
- tmp->stillgoing = 0;
-
ao2_lock(qe->parent);
- update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
qe->parent->rrpos++;
qe->linpos++;
ao2_unlock(qe->parent);
- (*busies)++;
+ member_call_pending_clear(tmp->member);
+
+ if (qe->chan->cdr) {
+ ast_cdr_busy(qe->chan->cdr);
+ }
+ tmp->stillgoing = 0;
+ ++*busies;
return 0;
}
@@ -3228,25 +3309,17 @@
ast_channel_unlock(tmp->chan);
ast_channel_unlock(qe->chan);
- ao2_lock(tmp->member);
- update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
- if (!qe->parent->ringinuse && (tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
- ast_verb(1, "Member %s is busy, cannot dial", tmp->member->interface);
- res = -1;
- }
- else {
- /* Place the call, but don't wait on the answer */
- res = ast_call(tmp->chan, location, 0);
- }
- ao2_unlock(tmp->member);
- if (res) {
+ /* Place the call, but don't wait on the answer */
+ if ((res = ast_call(tmp->chan, location, 0))) {
/* Again, keep going even if there's an error */
ast_verb(3, "Couldn't call %s\n", tmp->interface);
do_hang(tmp);
- (*busies)++;
- update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
+ member_call_pending_clear(tmp->member);
+ ++*busies;
return 0;
- } else if (qe->parent->eventwhencalled) {
+ }
+
+ if (qe->parent->eventwhencalled) {
char vars[2048];
ast_channel_lock_both(tmp->chan, qe->chan);
@@ -3280,7 +3353,7 @@
ast_verb(3, "Called %s\n", tmp->interface);
}
- update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
+ member_call_pending_clear(tmp->member);
return 1;
}
@@ -3556,6 +3629,7 @@
#endif
struct ast_party_connected_line connected_caller;
char *inchan_name;
+ struct timeval start_time_tv = ast_tvnow();
ast_party_connected_line_init(&connected_caller);
@@ -3570,8 +3644,8 @@
ast_poll_channel_add(in, epollo->chan);
}
#endif
-
- while (*to && !peer) {
+
+ while ((*to = ast_remaining_ms(start_time_tv, orig)) && !peer) {
int numlines, retry, pos = 1;
struct ast_channel *watchers[AST_MAX_WATCHERS];
watchers[0] = in;
@@ -3827,10 +3901,11 @@
endtime -= starttime;
rna(endtime * 1000, qe, on, membername, 0);
if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
- if (qe->parent->timeoutrestart)
- *to = orig;
+ if (qe->parent->timeoutrestart) {
+ start_time_tv = ast_tvnow();
+ }
/* Have enough time for a queue member to answer? */
- if (*to > 500) {
+ if (ast_remaining_ms(start_time_tv, orig) > 500) {
ring_one(qe, outgoing, &numbusies);
starttime = (long) time(NULL);
}
@@ -3846,9 +3921,10 @@
rna(endtime * 1000, qe, on, membername, 0);
do_hang(o);
if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
- if (qe->parent->timeoutrestart)
- *to = orig;
- if (*to > 500) {
+ if (qe->parent->timeoutrestart) {
+ start_time_tv = ast_tvnow();
+ }
+ if (ast_remaining_ms(start_time_tv, orig) > 500) {
ring_one(qe, outgoing, &numbusies);
starttime = (long) time(NULL);
}
@@ -3935,9 +4011,10 @@
rna(endtime * 1000, qe, on, membername, 1);
do_hang(o);
if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
- if (qe->parent->timeoutrestart)
- *to = orig;
- if (*to > 500) {
+ if (qe->parent->timeoutrestart) {
+ start_time_tv = ast_tvnow();
+ }
+ if (ast_remaining_ms(start_time_tv, orig) > 500) {
ring_one(qe, outgoing, &numbusies);
starttime = (long) time(NULL);
}
@@ -4008,9 +4085,11 @@
ast_frfree(f);
}
- if (!*to) {
- for (o = start; o; o = o->call_next)
- rna(orig, qe, o->interface, o->member->membername, 1);
+ }
+
+ if (!*to) {
+ for (o = start; o; o = o->call_next) {
+ rna(orig, qe, o->interface, o->member->membername, 1);
}
}
@@ -7476,7 +7555,7 @@
while ((mem = ao2_iterator_next(&mem_iter))) {
if ((mem->status != AST_DEVICE_UNAVAILABLE) && (mem->status != AST_DEVICE_INVALID)) {
++qmemcount;
- if (((mem->status == AST_DEVICE_NOT_INUSE) || (mem->status == AST_DEVICE_UNKNOWN)) && !(mem->paused)) {
+ if (member_status_available(mem->status) && !mem->paused) {
++qmemavail;
}
}
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/apps/app_record.c
^
|
@@ -31,7 +31,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 366880 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 375993 $")
#include "asterisk/file.h"
#include "asterisk/pbx.h"
@@ -160,7 +160,6 @@
int terminator = '#';
int rfmt = 0;
int ioflags;
- int waitres;
struct ast_silence_generator *silgen = NULL;
struct ast_flags flags = { 0, };
AST_DECLARE_APP_ARGS(args,
@@ -169,7 +168,9 @@
AST_APP_ARG(maxduration);
AST_APP_ARG(options);
);
-
+ int ms;
+ struct timeval start;
+
/* The next few lines of code parse out the filename and header from the input string */
if (ast_strlen_zero(data)) { /* no data implies no filename or anything is present */
ast_log(LOG_WARNING, "Record requires an argument (filename)\n");
@@ -330,14 +331,15 @@
if (maxduration <= 0)
maxduration = -1;
- while ((waitres = ast_waitfor(chan, maxduration)) > -1) {
- if (maxduration > 0) {
- if (waitres == 0) {
- gottimeout = 1;
- pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "TIMEOUT");
- break;
- }
- maxduration = waitres;
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, maxduration))) {
+ ms = ast_waitfor(chan, ms);
+ if (ms < 0) {
+ break;
+ }
+
+ if (maxduration > 0 && ms == 0) {
+ break;
}
f = ast_read(chan);
@@ -389,6 +391,12 @@
}
ast_frfree(f);
}
+
+ if (maxduration > 0 && !ms) {
+ gottimeout = 1;
+ pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "TIMEOUT");
+ }
+
if (!f) {
ast_debug(1, "Got hangup\n");
res = -1;
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/apps/app_voicemail.c
^
|
@@ -91,7 +91,7 @@
#endif
#endif
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 373735 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376262 $")
#include "asterisk/paths.h" /* use ast_config_AST_SPOOL_DIR */
#include <sys/time.h>
@@ -13574,7 +13574,7 @@
strcpy(flag, "Urgent");
} else if (flag) {
ast_verbose(VERBOSE_PREFIX_3 "UNmarking message as Urgent\n");
- res = ast_play_and_wait(chan, "vm-urgent-removed");
+ res = ast_play_and_wait(chan, "vm-marked-nonurgent");
strcpy(flag, "");
} else {
ast_play_and_wait(chan, "vm-sorry");
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/apps/app_waitforring.c
^
|
@@ -31,7 +31,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 375993 $")
#include "asterisk/file.h"
#include "asterisk/channel.h"
@@ -63,22 +63,29 @@
struct ast_silence_generator *silgen = NULL;
int res = 0;
double s;
+ int timeout_ms;
int ms;
+ struct timeval start = ast_tvnow();
if (!data || (sscanf(data, "%30lg", &s) != 1)) {
ast_log(LOG_WARNING, "WaitForRing requires an argument (minimum seconds)\n");
return 0;
}
+ if (s < 0.0) {
+ ast_log(LOG_WARNING, "Invalid timeout provided for WaitForRing (%lg)\n", s);
+ return 0;
+ }
+
if (ast_opt_transmit_silence) {
silgen = ast_channel_start_silence_generator(chan);
}
- ms = s * 1000.0;
- while (ms > 0) {
+ timeout_ms = s * 1000.0;
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
ms = ast_waitfor(chan, ms);
if (ms < 0) {
- res = ms;
+ res = -1;
break;
}
if (ms > 0) {
@@ -95,14 +102,12 @@
}
/* Now we're really ready for the ring */
if (!res) {
- ms = 99999999;
- while(ms > 0) {
- ms = ast_waitfor(chan, ms);
- if (ms < 0) {
- res = ms;
+ for (;;) {
+ int wait_res = ast_waitfor(chan, -1);
+ if (wait_res < 0) {
+ res = -1;
break;
- }
- if (ms > 0) {
+ } else {
f = ast_read(chan);
if (!f) {
res = -1;
|
[-]
[+]
|
Added |
asterisk-1.8.20.0.tar.xz/asterisk-1.8.20.0-summary.html
^
|
@@ -0,0 +1,357 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /><title>Release Summary - asterisk-1.8.20.0</title></head>
+<body>
+<h1 align="center"><a name="top">Release Summary</a></h1>
+<h3 align="center">asterisk-1.8.20.0</h3>
+<h3 align="center">Date: 2013-01-14</h3>
+<h3 align="center"><asteriskteam@digium.com></h3>
+<hr/>
+<h2 align="center">Table of Contents</h2>
+<ol>
+ <li><a href="#summary">Summary</a></li>
+ <li><a href="#contributors">Contributors</a></li>
+ <li><a href="#issues">Closed Issues</a></li>
+ <li><a href="#commits">Other Changes</a></li>
+ <li><a href="#diffstat">Diffstat</a></li>
+</ol>
+<hr/>
+<a name="summary"><h2 align="center">Summary</h2></a>
+<center><a href="#top">[Back to Top]</a></center><br/><p>This release includes only bug fixes. The changes included were made only to address problems that have been identified in this release series. Users should be able to safely upgrade to this version if this release series is already in use. Users considering upgrading from a previous release series are strongly encouraged to review the UPGRADE.txt document as well as the CHANGES document for information about upgrading to this release series.</p>
+<p>The data in this summary reflects changes that have been made since the previous release, asterisk-1.8.19.0.</p>
+<hr/>
+<a name="contributors"><h2 align="center">Contributors</h2></a>
+<center><a href="#top">[Back to Top]</a></center><br/><p>This table lists the people who have submitted code, those that have tested patches, as well as those that reported issues on the issue tracker that were resolved in this release. For coders, the number is how many of their patches (of any size) were committed into this release. For testers, the number is the number of times their name was listed as assisting with testing a patch. Finally, for reporters, the number is the number of issues that they reported that were closed by commits that went into this release.</p>
+<table width="100%" border="0">
+<tr>
+<td width="33%"><h3>Coders</h3></td>
+<td width="33%"><h3>Testers</h3></td>
+<td width="33%"><h3>Reporters</h3></td>
+</tr>
+<tr valign="top">
+<td>
+18 rmudgett<br/>
+5 mmichelson<br/>
+4 jrose<br/>
+3 bebuild<br/>
+2 dlee<br/>
+2 elguero<br/>
+2 mjordan<br/>
+2 tilghman<br/>
+1 Andre Luis<br/>
+1 beagles<br/>
+1 James Le Cuirot<br/>
+1 jcolp<br/>
+1 Jeremiah Gowdy<br/>
+1 jkroon<br/>
+1 Rusty Newton<br/>
+1 seanbright<br/>
+1 wdoekes<br/>
+</td>
+<td>
+3 rmudgett<br/>
+1 elguero<br/>
+1 Jared Smith<br/>
+1 mjordan<br/>
+1 Rusty Newton<br/>
+1 Steven T. Wheeler<br/>
+</td>
+<td>
+3 mjordan<br/>
+1 andrel<br/>
+1 chewi<br/>
+1 deti<br/>
+1 dlee<br/>
+1 eabad<br/>
+1 elguero<br/>
+1 jgowdy<br/>
+1 jkroon<br/>
+1 jrose<br/>
+1 jsmith<br/>
+1 mcargile<br/>
+1 p_lindheimer<br/>
+1 rmudgett<br/>
+1 supertle<br/>
+1 swheeler<br/>
+1 tomo1657<br/>
+1 tootai<br/>
+1 vldmr<br/>
+</td>
+</tr>
+</table>
+<hr/>
+<a name="issues"><h2 align="center">Closed Issues</h2></a>
+<center><a href="#top">[Back to Top]</a></center><br/><p>This is a list of all issues from the issue tracker that were closed by changes that went into this release.</p>
+<h3>Category: Applications/app_meetme</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20486">ASTERISK-20486</a>: MeetMe Unable to write frame to channel after SIP channel hangs up.<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376307">376307</a><br/>
+Reporter: mcargile<br/>
+Coders: jrose<br/>
+<br/>
+<h3>Category: Applications/app_queue</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-19918">ASTERISK-19918</a>: MoH (Music on Hold) is stopped after call in a queue is terminated<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376199">376199</a><br/>
+Reporter: eabad<br/>
+Coders: beagles<br/>
+<br/>
+<h3>Category: Applications/app_voicemail</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20280">ASTERISK-20280</a>: In app_voicemail we attempt to play the sound "vm-urgent-removed", which should be "vm-marked-nonurgent"<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376262">376262</a><br/>
+Reporter: tomo1657<br/>
+Testers: Rusty Newton<br/>
+Coders: Rusty Newton<br/>
+<br/>
+<h3>Category: Channels/General</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20414">ASTERISK-20414</a>: Timeout antipattern using ast_waitfor_nandfds<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=375993">375993</a><br/>
+Reporter: dlee<br/>
+Coders: mmichelson<br/>
+<br/>
+<h3>Category: Channels/chan_bridge</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20492">ASTERISK-20492</a>: Stuck DTMF when using ChannelRedirect to split a two channel bridge<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=375964">375964</a><br/>
+Reporter: jgowdy<br/>
+Testers: rmudgett<br/>
+Coders: Jeremiah Gowdy, rmudgett<br/>
+<br/>
+<h3>Category: Channels/chan_dahdi/SS7</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20204">ASTERISK-20204</a>: Asterisk not rejecting call setup on CIC that is down<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376058">376058</a><br/>
+Reporter: supertle<br/>
+Coders: rmudgett<br/>
+<br/>
+<h3>Category: Channels/chan_local</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20769">ASTERISK-20769</a>: Memory leak of local_pvt in chan_local.<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376868">376868</a><br/>
+Reporter: rmudgett<br/>
+Testers: rmudgett<br/>
+Coders: rmudgett<br/>
+<br/>
+<h3>Category: Channels/chan_sip/General</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20226">ASTERISK-20226</a>: Segfault in chan_sip while performing connected line update<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376901">376901</a><br/>
+Reporter: jsmith<br/>
+Testers: Jared Smith<br/>
+Coders: mmichelson<br/>
+<br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20486">ASTERISK-20486</a>: MeetMe Unable to write frame to channel after SIP channel hangs up.<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376307">376307</a><br/>
+Reporter: mcargile<br/>
+Coders: jrose<br/>
+<br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20570">ASTERISK-20570</a>: Asterisk, when acting as the UAS in Session Timer negotiation, fails to add required header in 200 response ("Require: timer")<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376521">376521</a><br/>
+Reporter: mjordan<br/>
+Coders: mmichelson<br/>
+<br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20724">ASTERISK-20724</a>: Fix natdetected flag being set when VIA doesn't include port in address<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376834">376834</a><br/>
+Reporter: elguero<br/>
+Coders: elguero<br/>
+<br/>
+<h3>Category: Channels/chan_sip/SRTP</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20499">ASTERISK-20499</a>: Crash in libsrtp srtp_unprotect_rtcp when SIP channel is bridged with non-optimizing Local channel<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=377256">377256</a><br/>
+Reporter: tootai<br/>
+Coders: jrose<br/>
+<br/>
+<h3>Category: Channels/chan_sip/TCP-TLS</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20763">ASTERISK-20763</a>: Memory Leak in chan_sip with TLS enabled clients<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=377257">377257</a><br/>
+Reporter: deti<br/>
+Coders: jcolp<br/>
+<br/>
+<h3>Category: Contrib/General</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20756">ASTERISK-20756</a>: Asterisk sippeers.sql columns place error cause peer to be without codecs when setting disallow=all under MySQL<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=377431">377431</a><br/>
+Reporter: andrel<br/>
+Coders: Andre Luis<br/>
+<br/>
+<h3>Category: Core/Channels</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20492">ASTERISK-20492</a>: Stuck DTMF when using ChannelRedirect to split a two channel bridge<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=375964">375964</a><br/>
+Reporter: jgowdy<br/>
+Testers: rmudgett<br/>
+Coders: Jeremiah Gowdy, rmudgett<br/>
+<br/>
+<h3>Category: Core/ManagerInterface</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20677">ASTERISK-20677</a>: Action Challenge not working with allowmultiplelogin=no<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376725">376725</a><br/>
+Reporter: vldmr<br/>
+Coders: jrose<br/>
+<br/>
+<h3>Category: Core/PBX</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-19205">ASTERISK-19205</a>: Most Unique pattern matching broken when trailing "-" is part of extension<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376688">376688</a><br/>
+Reporter: p_lindheimer<br/>
+Testers: rmudgett<br/>
+Coders: rmudgett<br/>
+<br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20639">ASTERISK-20639</a>: Dynamic hints are not properly initialized when the extension contains an underscore.<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376142">376142</a><br/>
+Reporter: swheeler<br/>
+Testers: Steven T. Wheeler, elguero<br/>
+Coders: elguero<br/>
+<br/>
+<h3>Category: General</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-19463">ASTERISK-19463</a>: Asterisk deadlocks during startup with mutex errors<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376428">376428</a><br/>
+Reporter: mjordan<br/>
+Testers: mjordan<br/>
+Coders: mjordan<br/>
+<br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20226">ASTERISK-20226</a>: Segfault in chan_sip while performing connected line update<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376901">376901</a><br/>
+Reporter: jsmith<br/>
+Testers: Jared Smith<br/>
+Coders: mmichelson<br/>
+<br/>
+<h3>Category: PBX/General</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20628">ASTERISK-20628</a>: [patch] - main/pbx.c - ShowDialPlan generates with error if no Exten: was presented and there are no exten => lines present<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376166">376166</a><br/>
+Reporter: jkroon<br/>
+Coders: jkroon<br/>
+<br/>
+<h3>Category: PBX/pbx_spool</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20593">ASTERISK-20593</a>: [patch] Future-dated call files are ignored when astspooldir is relative<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376232">376232</a><br/>
+Reporter: chewi<br/>
+Coders: James Le Cuirot<br/>
+<br/>
+<h3>Category: Resources/res_monitor</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20641">ASTERISK-20641</a>: Erroneous error messages from Monitor when using options 'i' and 'o'<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376389">376389</a><br/>
+Reporter: jrose<br/>
+Coders: jrose<br/>
+<br/>
+<h3>Category: Tests/testsuite</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-19463">ASTERISK-19463</a>: Asterisk deadlocks during startup with mutex errors<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376428">376428</a><br/>
+Reporter: mjordan<br/>
+Testers: mjordan<br/>
+Coders: mjordan<br/>
+<br/>
+<h3>Category: Utilities/General</h3><br/>
+<a href="https://issues.asterisk.org/jira/browse/ASTERISK-20505">ASTERISK-20505</a>: Migrate hashtest/hashtest2 to be unit tests<br/>
+Revision: <a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376306">376306</a><br/>
+Reporter: mjordan<br/>
+Coders: dlee<br/>
+<br/>
+<hr/>
+<a name="commits"><h2 align="center">Commits Not Associated with an Issue</h2></a>
+<center><a href="#top">[Back to Top]</a></center><br/><p>This is a list of all changes that went into this release that did not directly close an issue from the issue tracker. The commits may have been marked as being related to an issue. If that is the case, the issue numbers are listed here, as well.</p>
+<table width="100%" border="1">
+<tr><td><b>Revision</b></td><td><b>Author</b></td><td><b>Summary</b></td><td><b>Issues Referenced</b></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=375994">375994</a></td><td>mmichelson</td><td>Remove some debugging that accidentally made it in the last commit.</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376029">376029</a></td><td>rmudgett</td><td>Add MALLOC_DEBUG enhancements.</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376087">376087</a></td><td>mmichelson</td><td>Fix a "set but not used" warning on newer gccs.</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376340">376340</a></td><td>dlee</td><td>Fixed extconf.c breakage introduced in r376306.</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376469">376469</a></td><td>wdoekes</td><td>Fix most leftover non-opaque ast_str uses.</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376586">376586</a></td><td>mjordan</td><td>Re-initialize logmsgs mutex upon logger initialization to prevent lock errors</td>
+<td><a href="https://issues.asterisk.org/jira/browse/ASTERISK-19463">ASTERISK-19463</a></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376627">376627</a></td><td>rmudgett</td><td>Made AST_LIST_REMOVE() simpler and use better names.</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376657">376657</a></td><td>rmudgett</td><td>Remove unnecessary channel module references.</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376758">376758</a></td><td>rmudgett</td><td>Enhance MALLOC_DEBUG CLI commands.</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376788">376788</a></td><td>rmudgett</td><td>Add MALLOC_DEBUG atexit unreleased malloc memory summary.</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376864">376864</a></td><td>rmudgett</td><td>Fix compile error.</td>
+<td><a href="https://issues.asterisk.org/jira/browse/ASTERISK-20724">ASTERISK-20724</a></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376919">376919</a></td><td>seanbright</td><td>Minor spelling fix to the VOLUME documentation.</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=376950">376950</a></td><td>rmudgett</td><td>chan_misdn: Fix sending RELEASE_COMPLETE in response to SETUP.</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=377037">377037</a></td><td>rmudgett</td><td>Fix CCSS CLI commands and logger level not unregistered.</td>
+<td><a href="https://issues.asterisk.org/jira/browse/ASTERISK-20649">ASTERISK-20649</a></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=377069">377069</a></td><td>rmudgett</td><td>Cleanup CDR resources on exit.</td>
+<td><a href="https://issues.asterisk.org/jira/browse/ASTERISK-20649">ASTERISK-20649</a></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=377073">377073</a></td><td>rmudgett</td><td>Cleanup CLI resources on exit and CLI command registration errors.</td>
+<td><a href="https://issues.asterisk.org/jira/browse/ASTERISK-20649">ASTERISK-20649</a></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=377104">377104</a></td><td>rmudgett</td><td>Cleanup config cache on exit.</td>
+<td><a href="https://issues.asterisk.org/jira/browse/ASTERISK-20649">ASTERISK-20649</a></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=377135">377135</a></td><td>rmudgett</td><td>Cleanup core main on exit.</td>
+<td><a href="https://issues.asterisk.org/jira/browse/ASTERISK-20649">ASTERISK-20649</a></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=377165">377165</a></td><td>rmudgett</td><td>Cleanup ast_run_atexits() atexits list.</td>
+<td><a href="https://issues.asterisk.org/jira/browse/ASTERISK-20649">ASTERISK-20649</a></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=377398">377398</a></td><td>rmudgett</td><td>MALLOC_DEBUG: Only wait if we want atexit allocation dumps.</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=377487">377487</a></td><td>tilghman</td><td>Remove some dead code and additionally handle a case that wasn't handled.</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=377509">377509</a></td><td>tilghman</td><td>Improve documentation by making all of the colors used readable,</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=378719">378719</a></td><td>bebuild</td><td>Create 1.8.20.0-rc2</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=378781">378781</a></td><td>bebuild</td><td>Merge changes for 1.8.20.0-rc2</td>
+<td></td></tr><tr><td><a href="http://svn.digium.com/view/asterisk/branches/1.8?view=revision&revision=378786">378786</a></td><td>bebuild</td><td>Importing release summary for 1.8.20.0-rc2 release.</td>
+<td></td></tr></table>
+<hr/>
+<a name="diffstat"><h2 align="center">Diffstat Results</h2></a>
+<center><a href="#top">[Back to Top]</a></center><br/><p>This is a summary of the changes to the source code that went into this release that was generated using the diffstat utility.</p>
+<pre>
+.cleancount | 4
+.version | 2
+ChangeLog | 63 +
+UPGRADE.txt | 5
+addons/cdr_mysql.c | 11
+addons/res_config_mysql.c | 3
+apps/app_celgenuserevent.c | 9
+apps/app_confbridge.c | 4
+apps/app_dial.c | 14
+apps/app_jack.c | 4
+apps/app_meetme.c | 31
+apps/app_queue.c | 217 ++++--
+apps/app_record.c | 28
+apps/app_voicemail.c | 2
+apps/app_waitforring.c | 25
+asterisk-1.8.20.0-rc1-summary.html | 337 ---------
+asterisk-1.8.20.0-rc1-summary.txt | 438 ------------
+asterisk-1.8.20.0-rc2-summary.html | 80 ++
+asterisk-1.8.20.0-rc2-summary.txt | 109 +++
+channels/chan_agent.c | 26
+channels/chan_dahdi.c | 49 +
+channels/chan_iax2.c | 45 -
+channels/chan_local.c | 24
+channels/chan_sip.c | 261 ++++---
+channels/chan_skinny.c | 16
+channels/misdn/isdn_lib.c | 17
+channels/sig_analog.c | 22
+channels/sig_pri.c | 12
+channels/sig_ss7.c | 49 -
+channels/sip/include/sip.h | 2
+contrib/realtime/mysql/sippeers.sql | 2
+funcs/func_devstate.c | 6
+funcs/func_volume.c | 2
+include/asterisk/_private.h | 1
+include/asterisk/astmm.h | 3
+include/asterisk/channel.h | 12
+include/asterisk/devicestate.h | 16
+include/asterisk/event_defs.h | 8
+include/asterisk/features.h | 12
+include/asterisk/hashtab.h | 3
+include/asterisk/linkedlists.h | 58 -
+include/asterisk/lock.h | 16
+include/asterisk/time.h | 14
+include/asterisk/utils.h | 29
+main/asterisk.c | 356 ++++++----
+main/astmm.c | 1255 ++++++++++++++++++++++++++++++------
+main/ccss.c | 2
+main/cdr.c | 46 -
+main/channel.c | 157 +++-
+main/cli.c | 43 +
+main/config.c | 14
+main/devicestate.c | 51 -
+main/event.c | 1
+main/features.c | 29
+main/http.c | 20
+main/indications.c | 2
+main/lock.c | 2
+main/logger.c | 11
+main/manager.c | 2
+main/pbx.c | 532 +++++++++++----
+main/rtp_engine.c | 16
+main/security_events.c | 2
+main/stdtime/localtime.c | 23
+main/utils.c | 69 +
+main/xmldoc.c | 8
+pbx/pbx_dundi.c | 31
+pbx/pbx_spool.c | 2
+res/res_calendar.c | 8
+res/res_fax.c | 128 ++-
+res/res_jabber.c | 66 +
+res/res_monitor.c | 32
+res/res_srtp.c | 4
+tests/test_astobj2_thrash.c | 353 ++++++++++
+tests/test_hashtab_thrash.c | 321 +++++++++
+utils/Makefile | 7
+utils/extconf.c | 1
+utils/hashtest.c | 410 -----------
+utils/hashtest2.c | 418 -----------
+utils/utils.xml | 8
+79 files changed, 3848 insertions(+), 2673 deletions(-)
+</pre><br/>
+<hr/>
+</body>
+</html>
|
[-]
[+]
|
Added |
asterisk-1.8.20.0.tar.xz/asterisk-1.8.20.0-summary.txt
^
|
@@ -0,0 +1,462 @@
+ Release Summary
+
+ asterisk-1.8.20.0
+
+ Date: 2013-01-14
+
+ <asteriskteam@digium.com>
+
+ ----------------------------------------------------------------------
+
+ Table of Contents
+
+ 1. Summary
+ 2. Contributors
+ 3. Closed Issues
+ 4. Other Changes
+ 5. Diffstat
+
+ ----------------------------------------------------------------------
+
+ Summary
+
+ [Back to Top]
+
+ This release includes only bug fixes. The changes included were made only
+ to address problems that have been identified in this release series.
+ Users should be able to safely upgrade to this version if this release
+ series is already in use. Users considering upgrading from a previous
+ release series are strongly encouraged to review the UPGRADE.txt document
+ as well as the CHANGES document for information about upgrading to this
+ release series.
+
+ The data in this summary reflects changes that have been made since the
+ previous release, asterisk-1.8.19.0.
+
+ ----------------------------------------------------------------------
+
+ Contributors
+
+ [Back to Top]
+
+ This table lists the people who have submitted code, those that have
+ tested patches, as well as those that reported issues on the issue tracker
+ that were resolved in this release. For coders, the number is how many of
+ their patches (of any size) were committed into this release. For testers,
+ the number is the number of times their name was listed as assisting with
+ testing a patch. Finally, for reporters, the number is the number of
+ issues that they reported that were closed by commits that went into this
+ release.
+
+ Coders Testers Reporters
+ 18 rmudgett 3 rmudgett 3 mjordan
+ 5 mmichelson 1 elguero 1 andrel
+ 4 jrose 1 Jared Smith 1 chewi
+ 3 bebuild 1 mjordan 1 deti
+ 2 dlee 1 Rusty Newton 1 dlee
+ 2 elguero 1 Steven T. Wheeler 1 eabad
+ 2 mjordan 1 elguero
+ 2 tilghman 1 jgowdy
+ 1 Andre Luis 1 jkroon
+ 1 beagles 1 jrose
+ 1 James Le Cuirot 1 jsmith
+ 1 jcolp 1 mcargile
+ 1 Jeremiah Gowdy 1 p_lindheimer
+ 1 jkroon 1 rmudgett
+ 1 Rusty Newton 1 supertle
+ 1 seanbright 1 swheeler
+ 1 wdoekes 1 tomo1657
+ 1 tootai
+ 1 vldmr
+
+ ----------------------------------------------------------------------
+
+ Closed Issues
+
+ [Back to Top]
+
+ This is a list of all issues from the issue tracker that were closed by
+ changes that went into this release.
+
+ Category: Applications/app_meetme
+
+ ASTERISK-20486: MeetMe Unable to write frame to channel after SIP channel
+ hangs up.
+ Revision: 376307
+ Reporter: mcargile
+ Coders: jrose
+
+ Category: Applications/app_queue
+
+ ASTERISK-19918: MoH (Music on Hold) is stopped after call in a queue is
+ terminated
+ Revision: 376199
+ Reporter: eabad
+ Coders: beagles
+
+ Category: Applications/app_voicemail
+
+ ASTERISK-20280: In app_voicemail we attempt to play the sound
+ "vm-urgent-removed", which should be "vm-marked-nonurgent"
+ Revision: 376262
+ Reporter: tomo1657
+ Testers: Rusty Newton
+ Coders: Rusty Newton
+
+ Category: Channels/General
+
+ ASTERISK-20414: Timeout antipattern using ast_waitfor_nandfds
+ Revision: 375993
+ Reporter: dlee
+ Coders: mmichelson
+
+ Category: Channels/chan_bridge
+
+ ASTERISK-20492: Stuck DTMF when using ChannelRedirect to split a two
+ channel bridge
+ Revision: 375964
+ Reporter: jgowdy
+ Testers: rmudgett
+ Coders: Jeremiah Gowdy, rmudgett
+
+ Category: Channels/chan_dahdi/SS7
+
+ ASTERISK-20204: Asterisk not rejecting call setup on CIC that is down
+ Revision: 376058
+ Reporter: supertle
+ Coders: rmudgett
+
+ Category: Channels/chan_local
+
+ ASTERISK-20769: Memory leak of local_pvt in chan_local.
+ Revision: 376868
+ Reporter: rmudgett
+ Testers: rmudgett
+ Coders: rmudgett
+
+ Category: Channels/chan_sip/General
+
+ ASTERISK-20226: Segfault in chan_sip while performing connected line
+ update
+ Revision: 376901
+ Reporter: jsmith
+ Testers: Jared Smith
+ Coders: mmichelson
+
+ ASTERISK-20486: MeetMe Unable to write frame to channel after SIP channel
+ hangs up.
+ Revision: 376307
+ Reporter: mcargile
+ Coders: jrose
+
+ ASTERISK-20570: Asterisk, when acting as the UAS in Session Timer
+ negotiation, fails to add required header in 200 response ("Require:
+ timer")
+ Revision: 376521
+ Reporter: mjordan
+ Coders: mmichelson
+
+ ASTERISK-20724: Fix natdetected flag being set when VIA doesn't include
+ port in address
+ Revision: 376834
+ Reporter: elguero
+ Coders: elguero
+
+ Category: Channels/chan_sip/SRTP
+
+ ASTERISK-20499: Crash in libsrtp srtp_unprotect_rtcp when SIP channel is
+ bridged with non-optimizing Local channel
+ Revision: 377256
+ Reporter: tootai
+ Coders: jrose
+
+ Category: Channels/chan_sip/TCP-TLS
+
+ ASTERISK-20763: Memory Leak in chan_sip with TLS enabled clients
+ Revision: 377257
+ Reporter: deti
+ Coders: jcolp
+
+ Category: Contrib/General
+
+ ASTERISK-20756: Asterisk sippeers.sql columns place error cause peer to be
+ without codecs when setting disallow=all under MySQL
+ Revision: 377431
+ Reporter: andrel
+ Coders: Andre Luis
+
+ Category: Core/Channels
+
+ ASTERISK-20492: Stuck DTMF when using ChannelRedirect to split a two
+ channel bridge
+ Revision: 375964
+ Reporter: jgowdy
+ Testers: rmudgett
+ Coders: Jeremiah Gowdy, rmudgett
+
+ Category: Core/ManagerInterface
+
+ ASTERISK-20677: Action Challenge not working with allowmultiplelogin=no
+ Revision: 376725
+ Reporter: vldmr
+ Coders: jrose
+
+ Category: Core/PBX
+
+ ASTERISK-19205: Most Unique pattern matching broken when trailing "-" is
+ part of extension
+ Revision: 376688
+ Reporter: p_lindheimer
+ Testers: rmudgett
+ Coders: rmudgett
+
+ ASTERISK-20639: Dynamic hints are not properly initialized when the
+ extension contains an underscore.
+ Revision: 376142
+ Reporter: swheeler
+ Testers: Steven T. Wheeler, elguero
+ Coders: elguero
+
+ Category: General
+
+ ASTERISK-19463: Asterisk deadlocks during startup with mutex errors
+ Revision: 376428
+ Reporter: mjordan
+ Testers: mjordan
+ Coders: mjordan
+
+ ASTERISK-20226: Segfault in chan_sip while performing connected line
+ update
+ Revision: 376901
+ Reporter: jsmith
+ Testers: Jared Smith
+ Coders: mmichelson
+
+ Category: PBX/General
+
+ ASTERISK-20628: [patch] - main/pbx.c - ShowDialPlan generates with error
+ if no Exten: was presented and there are no exten => lines present
+ Revision: 376166
+ Reporter: jkroon
+ Coders: jkroon
+
+ Category: PBX/pbx_spool
+
+ ASTERISK-20593: [patch] Future-dated call files are ignored when
+ astspooldir is relative
+ Revision: 376232
+ Reporter: chewi
+ Coders: James Le Cuirot
+
+ Category: Resources/res_monitor
+
+ ASTERISK-20641: Erroneous error messages from Monitor when using options
+ 'i' and 'o'
+ Revision: 376389
+ Reporter: jrose
+ Coders: jrose
+
+ Category: Tests/testsuite
+
+ ASTERISK-19463: Asterisk deadlocks during startup with mutex errors
+ Revision: 376428
+ Reporter: mjordan
+ Testers: mjordan
+ Coders: mjordan
+
+ Category: Utilities/General
+
+ ASTERISK-20505: Migrate hashtest/hashtest2 to be unit tests
+ Revision: 376306
+ Reporter: mjordan
+ Coders: dlee
+
+ ----------------------------------------------------------------------
+
+ Commits Not Associated with an Issue
+
+ [Back to Top]
+
+ This is a list of all changes that went into this release that did not
+ directly close an issue from the issue tracker. The commits may have been
+ marked as being related to an issue. If that is the case, the issue
+ numbers are listed here, as well.
+
+ +------------------------------------------------------------------------+
+ | Revision | Author | Summary | Issues Referenced |
+ |----------+------------+----------------------------+-------------------|
+ | | | Remove some debugging that | |
+ | 375994 | mmichelson | accidentally made it in | |
+ | | | the last commit. | |
+ |----------+------------+----------------------------+-------------------|
+ | 376029 | rmudgett | Add MALLOC_DEBUG | |
+ | | | enhancements. | |
+ |----------+------------+----------------------------+-------------------|
+ | 376087 | mmichelson | Fix a "set but not used" | |
+ | | | warning on newer gccs. | |
+ |----------+------------+----------------------------+-------------------|
+ | 376340 | dlee | Fixed extconf.c breakage | |
+ | | | introduced in r376306. | |
+ |----------+------------+----------------------------+-------------------|
+ | 376469 | wdoekes | Fix most leftover | |
+ | | | non-opaque ast_str uses. | |
+ |----------+------------+----------------------------+-------------------|
+ | | | Re-initialize logmsgs | |
+ | 376586 | mjordan | mutex upon logger | ASTERISK-19463 |
+ | | | initialization to prevent | |
+ | | | lock errors | |
+ |----------+------------+----------------------------+-------------------|
+ | | | Made AST_LIST_REMOVE() | |
+ | 376627 | rmudgett | simpler and use better | |
+ | | | names. | |
+ |----------+------------+----------------------------+-------------------|
+ | 376657 | rmudgett | Remove unnecessary channel | |
+ | | | module references. | |
+ |----------+------------+----------------------------+-------------------|
+ | 376758 | rmudgett | Enhance MALLOC_DEBUG CLI | |
+ | | | commands. | |
+ |----------+------------+----------------------------+-------------------|
+ | | | Add MALLOC_DEBUG atexit | |
+ | 376788 | rmudgett | unreleased malloc memory | |
+ | | | summary. | |
+ |----------+------------+----------------------------+-------------------|
+ | 376864 | rmudgett | Fix compile error. | ASTERISK-20724 |
+ |----------+------------+----------------------------+-------------------|
+ | 376919 | seanbright | Minor spelling fix to the | |
+ | | | VOLUME documentation. | |
+ |----------+------------+----------------------------+-------------------|
+ | | | chan_misdn: Fix sending | |
+ | 376950 | rmudgett | RELEASE_COMPLETE in | |
+ | | | response to SETUP. | |
+ |----------+------------+----------------------------+-------------------|
+ | | | Fix CCSS CLI commands and | |
+ | 377037 | rmudgett | logger level not | ASTERISK-20649 |
+ | | | unregistered. | |
+ |----------+------------+----------------------------+-------------------|
+ | 377069 | rmudgett | Cleanup CDR resources on | ASTERISK-20649 |
+ | | | exit. | |
+ |----------+------------+----------------------------+-------------------|
+ | | | Cleanup CLI resources on | |
+ | 377073 | rmudgett | exit and CLI command | ASTERISK-20649 |
+ | | | registration errors. | |
+ |----------+------------+----------------------------+-------------------|
+ | 377104 | rmudgett | Cleanup config cache on | ASTERISK-20649 |
+ | | | exit. | |
+ |----------+------------+----------------------------+-------------------|
+ | 377135 | rmudgett | Cleanup core main on exit. | ASTERISK-20649 |
+ |----------+------------+----------------------------+-------------------|
+ | 377165 | rmudgett | Cleanup ast_run_atexits() | ASTERISK-20649 |
+ | | | atexits list. | |
+ |----------+------------+----------------------------+-------------------|
+ | | | MALLOC_DEBUG: Only wait if | |
+ | 377398 | rmudgett | we want atexit allocation | |
+ | | | dumps. | |
+ |----------+------------+----------------------------+-------------------|
+ | | | Remove some dead code and | |
+ | 377487 | tilghman | additionally handle a case | |
+ | | | that wasn't handled. | |
+ |----------+------------+----------------------------+-------------------|
+ | | | Improve documentation by | |
+ | 377509 | tilghman | making all of the colors | |
+ | | | used readable, | |
+ |----------+------------+----------------------------+-------------------|
+ | 378719 | bebuild | Create 1.8.20.0-rc2 | |
+ |----------+------------+----------------------------+-------------------|
+ | 378781 | bebuild | Merge changes for | |
+ | | | 1.8.20.0-rc2 | |
+ |----------+------------+----------------------------+-------------------|
+ | 378786 | bebuild | Importing release summary | |
+ | | | for 1.8.20.0-rc2 release. | |
+ +------------------------------------------------------------------------+
+
+ ----------------------------------------------------------------------
+
+ Diffstat Results
+
+ [Back to Top]
+
+ This is a summary of the changes to the source code that went into this
+ release that was generated using the diffstat utility.
+
+ .cleancount | 4
+ .version | 2
+ ChangeLog | 63 +
+ UPGRADE.txt | 5
+ addons/cdr_mysql.c | 11
+ addons/res_config_mysql.c | 3
+ apps/app_celgenuserevent.c | 9
+ apps/app_confbridge.c | 4
+ apps/app_dial.c | 14
+ apps/app_jack.c | 4
+ apps/app_meetme.c | 31
+ apps/app_queue.c | 217 ++++--
+ apps/app_record.c | 28
+ apps/app_voicemail.c | 2
+ apps/app_waitforring.c | 25
+ asterisk-1.8.20.0-rc1-summary.html | 337 ---------
+ asterisk-1.8.20.0-rc1-summary.txt | 438 ------------
+ asterisk-1.8.20.0-rc2-summary.html | 80 ++
+ asterisk-1.8.20.0-rc2-summary.txt | 109 +++
+ channels/chan_agent.c | 26
+ channels/chan_dahdi.c | 49 +
+ channels/chan_iax2.c | 45 -
+ channels/chan_local.c | 24
+ channels/chan_sip.c | 261 ++++---
+ channels/chan_skinny.c | 16
+ channels/misdn/isdn_lib.c | 17
+ channels/sig_analog.c | 22
+ channels/sig_pri.c | 12
+ channels/sig_ss7.c | 49 -
+ channels/sip/include/sip.h | 2
+ contrib/realtime/mysql/sippeers.sql | 2
+ funcs/func_devstate.c | 6
+ funcs/func_volume.c | 2
+ include/asterisk/_private.h | 1
+ include/asterisk/astmm.h | 3
+ include/asterisk/channel.h | 12
+ include/asterisk/devicestate.h | 16
+ include/asterisk/event_defs.h | 8
+ include/asterisk/features.h | 12
+ include/asterisk/hashtab.h | 3
+ include/asterisk/linkedlists.h | 58 -
+ include/asterisk/lock.h | 16
+ include/asterisk/time.h | 14
+ include/asterisk/utils.h | 29
+ main/asterisk.c | 356 ++++++----
+ main/astmm.c | 1255 ++++++++++++++++++++++++++++++------
+ main/ccss.c | 2
+ main/cdr.c | 46 -
+ main/channel.c | 157 +++-
+ main/cli.c | 43 +
+ main/config.c | 14
+ main/devicestate.c | 51 -
+ main/event.c | 1
+ main/features.c | 29
+ main/http.c | 20
+ main/indications.c | 2
+ main/lock.c | 2
+ main/logger.c | 11
+ main/manager.c | 2
+ main/pbx.c | 532 +++++++++++----
+ main/rtp_engine.c | 16
+ main/security_events.c | 2
+ main/stdtime/localtime.c | 23
+ main/utils.c | 69 +
+ main/xmldoc.c | 8
+ pbx/pbx_dundi.c | 31
+ pbx/pbx_spool.c | 2
+ res/res_calendar.c | 8
+ res/res_fax.c | 128 ++-
+ res/res_jabber.c | 66 +
+ res/res_monitor.c | 32
+ res/res_srtp.c | 4
+ tests/test_astobj2_thrash.c | 353 ++++++++++
+ tests/test_hashtab_thrash.c | 321 +++++++++
+ utils/Makefile | 7
+ utils/extconf.c | 1
+ utils/hashtest.c | 410 -----------
+ utils/hashtest2.c | 418 -----------
+ utils/utils.xml | 8
+ 79 files changed, 3848 insertions(+), 2673 deletions(-)
+
+ ----------------------------------------------------------------------
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/channels/chan_agent.c
^
|
@@ -38,7 +38,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378341 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#include <sys/socket.h>
#include <fcntl.h>
@@ -1045,6 +1045,8 @@
int res=0;
int to = 1000;
struct ast_frame *f;
+ struct timeval start = ast_tvnow();
+ int ms;
/* Wait a second and look for something */
@@ -1052,12 +1054,14 @@
if (!p->chan)
return -1;
- for(;;) {
- to = ast_waitfor(p->chan, to);
- if (to < 0)
+ while ((ms = ast_remaining_ms(start, to))) {
+ ms = ast_waitfor(p->chan, ms);
+ if (ms < 0) {
return -1;
- if (!to)
+ }
+ if (ms == 0) {
return 0;
+ }
f = ast_read(p->chan);
if (!f)
return -1;
@@ -1077,7 +1081,7 @@
ast_mutex_unlock(&p->lock);
res = 0;
}
- return res;
+ return 0;
}
static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge)
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/channels/chan_dahdi.c
^
|
@@ -49,7 +49,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378341 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#if defined(__NetBSD__) || defined(__FreeBSD__)
#include <pthread.h>
@@ -6062,6 +6062,7 @@
if (res == 0) {
continue;
}
+ res = 0;
f = ast_read(chan);
if (!f) {
ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
@@ -7233,6 +7234,7 @@
int priority = 0;
struct ast_channel *oc0, *oc1;
enum ast_bridge_result res;
+ struct timeval start = ast_tvnow();
#ifdef PRI_2BCT
int triedtopribridge = 0;
q931_call *q931c0;
@@ -7454,6 +7456,7 @@
for (;;) {
struct ast_channel *c0_priority[2] = {c0, c1};
struct ast_channel *c1_priority[2] = {c1, c0};
+ int ms;
/* Here's our main loop... Start by locking things, looking for private parts,
and then balking if anything is wrong */
@@ -7473,8 +7476,8 @@
ast_channel_unlock(c0);
ast_channel_unlock(c1);
-
- if (!timeoutms ||
+ ms = ast_remaining_ms(start, timeoutms);
+ if (!ms ||
(op0 != p0) ||
(op1 != p1) ||
(ofd0 != c0->fds[0]) ||
@@ -7522,7 +7525,7 @@
}
#endif
- who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
+ who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
if (!who) {
ast_debug(1, "Ooh, empty read...\n");
continue;
@@ -10510,6 +10513,9 @@
/* If set to use DTMF CID signalling, listen for DTMF */
if (p->cid_signalling == CID_SIG_DTMF) {
int k = 0;
+ int off_ms;
+ struct timeval start = ast_tvnow();
+ int ms;
cs = NULL;
ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
dahdi_setlinear(p->subs[idx].dfd, 0);
@@ -10520,10 +10526,12 @@
* can drop some of them.
*/
ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
- res = 4000;/* This is a typical OFF time between rings. */
+ off_ms = 4000;/* This is a typical OFF time between rings. */
for (;;) {
struct ast_frame *f;
- res = ast_waitfor(chan, res);
+
+ ms = ast_remaining_ms(start, off_ms);
+ res = ast_waitfor(chan, ms);
if (res <= 0) {
/*
* We do not need to restore the dahdi_setlinear()
@@ -10543,7 +10551,7 @@
dtmfbuf[k++] = f->subclass.integer;
}
ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
- res = 4000;/* This is a typical OFF time between rings. */
+ start = ast_tvnow();
}
ast_frfree(f);
if (chan->_state == AST_STATE_RING ||
@@ -10566,6 +10574,9 @@
} else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
cs = callerid_new(p->cid_signalling);
if (cs) {
+ int off_ms;
+ struct timeval start;
+ int ms;
samples = 0;
#if 1
bump_gains(p);
@@ -10642,10 +10653,13 @@
}
/* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
- res = 4000;/* This is a typical OFF time between rings. */
+ start = ast_tvnow();
+ off_ms = 4000;/* This is a typical OFF time between rings. */
for (;;) {
struct ast_frame *f;
- res = ast_waitfor(chan, res);
+
+ ms = ast_remaining_ms(start, off_ms);
+ res = ast_waitfor(chan, ms);
if (res <= 0) {
ast_log(LOG_WARNING, "CID timed out waiting for ring. "
"Exiting simple switch\n");
@@ -10773,12 +10787,18 @@
} else if (p->use_callerid && p->cid_start == CID_START_RING) {
if (p->cid_signalling == CID_SIG_DTMF) {
int k = 0;
+ int off_ms;
+ struct timeval start;
+ int ms;
cs = NULL;
dahdi_setlinear(p->subs[idx].dfd, 0);
- res = 2000;
+ off_ms = 2000;
+ start = ast_tvnow();
for (;;) {
struct ast_frame *f;
- res = ast_waitfor(chan, res);
+
+ ms = ast_remaining_ms(start, off_ms);
+ res = ast_waitfor(chan, ms);
if (res <= 0) {
ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
"Exiting simple switch\n");
@@ -10794,7 +10814,7 @@
if (f->frametype == AST_FRAME_DTMF) {
dtmfbuf[k++] = f->subclass.integer;
ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
- res = 2000;
+ start = ast_tvnow();
}
ast_frfree(f);
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/channels/chan_iax2.c
^
|
@@ -38,7 +38,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378341 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#include <sys/mman.h>
#include <dirent.h>
@@ -5558,6 +5558,11 @@
}
to = 1000;
who = ast_waitfor_n(cs, 2, &to);
+ /* XXX This will need to be updated to calculate
+ * timeout correctly once timeoutms is allowed to be
+ * > 0. Right now, this can go badly if the waitfor
+ * times out in less than a millisecond
+ */
if (timeoutms > -1) {
timeoutms -= (1000 - to);
if (timeoutms < 0)
@@ -13713,6 +13718,8 @@
/* By here we must have a dp */
if (dp->flags & CACHE_FLAG_PENDING) {
+ struct timeval start;
+ int ms;
/* Okay, here it starts to get nasty. We need a pipe now to wait
for a reply to come back so long as it's pending */
for (x = 0; x < ARRAY_LEN(dp->waiters); x++) {
@@ -13737,8 +13744,9 @@
if (chan)
old = ast_channel_defer_dtmf(chan);
doabort = 0;
- while(timeout) {
- c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout);
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout))) {
+ c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &ms);
if (outfd > -1)
break;
if (!c)
@@ -13749,7 +13757,7 @@
}
ast_frfree(f);
}
- if (!timeout) {
+ if (!ms) {
ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten);
}
AST_LIST_LOCK(&dpcache);
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/channels/chan_local.c
^
|
@@ -31,7 +31,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378341 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#include <fcntl.h>
#include <sys/signal.h>
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/channels/chan_sip.c
^
|
@@ -209,7 +209,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378341 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#include <signal.h>
#include <sys/signal.h>
@@ -3676,16 +3676,16 @@
int res = 0;
const struct ast_sockaddr *dst = sip_real_dst(p);
- ast_debug(2, "Trying to put '%.11s' onto %s socket destined for %s\n", data->str, get_transport_pvt(p), ast_sockaddr_stringify(dst));
+ ast_debug(2, "Trying to put '%.11s' onto %s socket destined for %s\n", ast_str_buffer(data), get_transport_pvt(p), ast_sockaddr_stringify(dst));
if (sip_prepare_socket(p) < 0) {
return XMIT_ERROR;
}
if (p->socket.type == SIP_TRANSPORT_UDP) {
- res = ast_sendto(p->socket.fd, data->str, ast_str_strlen(data), 0, dst);
+ res = ast_sendto(p->socket.fd, ast_str_buffer(data), ast_str_strlen(data), 0, dst);
} else if (p->socket.tcptls_session) {
- res = sip_tcptls_write(p->socket.tcptls_session, data->str, ast_str_strlen(data));
+ res = sip_tcptls_write(p->socket.tcptls_session, ast_str_buffer(data), ast_str_strlen(data));
} else {
ast_debug(2, "Socket type is TCP but no tcptls_session is present to write to\n");
return XMIT_ERROR;
@@ -3943,10 +3943,10 @@
ast_verbose("Retransmitting #%d (%s) to %s:\n%s\n---\n",
pkt->retrans, sip_nat_mode(pkt->owner),
ast_sockaddr_stringify(dst),
- pkt->data->str);
+ ast_str_buffer(pkt->data));
}
- append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data->str);
+ append_history(pkt->owner, "ReTx", "%d %s", reschedule, ast_str_buffer(pkt->data));
xmitres = __sip_xmit(pkt->owner, pkt->data);
/* If there was no error during the network transmission, schedule the next retransmission,
@@ -4104,7 +4104,7 @@
ast_free(pkt);
return AST_FAILURE;
}
- ast_str_set(&pkt->data, 0, "%s%s", data->str, "\0");
+ ast_str_set(&pkt->data, 0, "%s%s", ast_str_buffer(data), "\0");
/* copy other parameters from the caller */
pkt->method = sipmethod;
pkt->seqno = seqno;
@@ -4377,7 +4377,7 @@
return;
}
cur = p->packets;
- method = (cur->method) ? cur->method : find_sip_method(cur->data->str);
+ method = (cur->method) ? cur->method : find_sip_method(ast_str_buffer(cur->data));
__sip_ack(p, cur->seqno, cur->is_resp, method);
}
}
@@ -4390,7 +4390,7 @@
for (cur = p->packets; cur; cur = cur->next) {
if (cur->seqno == seqno && cur->is_resp == resp &&
- (cur->is_resp || method_match(sipmethod, cur->data->str))) {
+ (cur->is_resp || method_match(sipmethod, ast_str_buffer(cur->data)))) {
/* this is our baby */
if (cur->retransid > -1) {
if (sipdebug)
@@ -4491,6 +4491,34 @@
with_sdp ? send_provisional_keepalive_with_sdp : send_provisional_keepalive, dialog_ref(pvt, "Increment refcount to pass dialog pointer to sched callback"));
}
+static void add_required_respheader(struct sip_request *req)
+{
+ struct ast_str *str;
+ int i;
+
+ if (!req->reqsipoptions) {
+ return;
+ }
+
+ str = ast_str_create(32);
+
+ for (i = 0; i < ARRAY_LEN(sip_options); ++i) {
+ if (!(req->reqsipoptions & sip_options[i].id)) {
+ continue;
+ }
+ if (ast_str_strlen(str) > 0) {
+ ast_str_append(&str, 0, ", ");
+ }
+ ast_str_append(&str, 0, "%s", sip_options[i].text);
+ }
+
+ if (ast_str_strlen(str) > 0) {
+ add_header(req, "Require", ast_str_buffer(str));
+ }
+
+ ast_free(str);
+}
+
/*! \brief Transmit response on SIP request*/
static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, uint32_t seqno)
{
@@ -4504,12 +4532,12 @@
ast_verbose("\n<--- %sTransmitting (%s) to %s --->\n%s\n<------------>\n",
reliable ? "Reliably " : "", sip_nat_mode(p),
ast_sockaddr_stringify(dst),
- req->data->str);
+ ast_str_buffer(req->data));
}
if (p->do_history) {
struct sip_request tmp = { .rlPart1 = 0, };
parse_copy(&tmp, req);
- append_history(p, reliable ? "TxRespRel" : "TxResp", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"),
+ append_history(p, reliable ? "TxRespRel" : "TxResp", "%s / %s - %s", ast_str_buffer(tmp.data), get_header(&tmp, "CSeq"),
(tmp.method == SIP_RESPONSE || tmp.method == SIP_UNKNOWN) ? REQ_OFFSET_TO_STR(&tmp, rlPart2) : sip_methods[tmp.method].text);
deinit_req(&tmp);
}
@@ -4549,15 +4577,15 @@
add_blank(req);
if (sip_debug_test_pvt(p)) {
if (ast_test_flag(&p->flags[0], SIP_NAT_FORCE_RPORT)) {
- ast_verbose("%sTransmitting (NAT) to %s:\n%s\n---\n", reliable ? "Reliably " : "", ast_sockaddr_stringify(&p->recv), req->data->str);
+ ast_verbose("%sTransmitting (NAT) to %s:\n%s\n---\n", reliable ? "Reliably " : "", ast_sockaddr_stringify(&p->recv), ast_str_buffer(req->data));
} else {
- ast_verbose("%sTransmitting (no NAT) to %s:\n%s\n---\n", reliable ? "Reliably " : "", ast_sockaddr_stringify(&p->sa), req->data->str);
+ ast_verbose("%sTransmitting (no NAT) to %s:\n%s\n---\n", reliable ? "Reliably " : "", ast_sockaddr_stringify(&p->sa), ast_str_buffer(req->data));
}
}
if (p->do_history) {
struct sip_request tmp = { .rlPart1 = 0, };
parse_copy(&tmp, req);
- append_history(p, reliable ? "TxReqRel" : "TxReq", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"), sip_methods[tmp.method].text);
+ append_history(p, reliable ? "TxReqRel" : "TxReq", "%s / %s - %s", ast_str_buffer(tmp.data), get_header(&tmp, "CSeq"), sip_methods[tmp.method].text);
deinit_req(&tmp);
}
res = (reliable) ?
@@ -6688,7 +6716,7 @@
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
/* Start the process if it's not already started */
- if (!p->alreadygone && p->initreq.data && !ast_strlen_zero(p->initreq.data->str)) {
+ if (!p->alreadygone && p->initreq.data && ast_str_strlen(p->initreq.data)) {
if (needcancel) { /* Outgoing call, not up */
if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
/* if we can't send right now, mark it pending */
@@ -6702,7 +6730,7 @@
struct sip_pkt *cur;
for (cur = p->packets; cur; cur = cur->next) {
- __sip_semi_ack(p, cur->seqno, cur->is_resp, cur->method ? cur->method : find_sip_method(cur->data->str));
+ __sip_semi_ack(p, cur->seqno, cur->is_resp, cur->method ? cur->method : find_sip_method(ast_str_buffer(cur->data)));
}
p->invitestate = INV_CANCELLED;
/* Send a new request: CANCEL */
@@ -8868,8 +8896,8 @@
*c = '\0';
} else if (*c == '\n') { /* end of this line */
*c = '\0';
- current_header_offset = (c + 1) - req->data->str;
- previous_header = req->data->str + dst[i];
+ current_header_offset = (c + 1) - ast_str_buffer(req->data);
+ previous_header = ast_str_buffer(req->data) + dst[i];
if (skipping_headers) {
/* check to see if this line is blank; if so, turn off
the skipping flag, so the next line will be processed
@@ -8915,7 +8943,7 @@
if we've already reached the maximum number of lines for portion of the message
we were parsing, we can't accept any more, so just ignore it.
*/
- previous_header = req->data->str + dst[i];
+ previous_header = ast_str_buffer(req->data) + dst[i];
if ((i < lim) && !ast_strlen_zero(previous_header)) {
if (sipdebug) {
ast_debug(4, "%7s %2d [%3d]: %s\n",
@@ -9056,7 +9084,7 @@
holdstate ? "On" : "Off",
dialog->owner->name,
dialog->owner->uniqueid);
- append_history(dialog, holdstate ? "Hold" : "Unhold", "%s", req->data->str);
+ append_history(dialog, holdstate ? "Hold" : "Unhold", "%s", ast_str_buffer(req->data));
if (!holdstate) { /* Put off remote hold */
ast_clear_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD); /* Clear both flags */
return;
@@ -10679,11 +10707,26 @@
add_supported_header(p, resp);
/* If this is an invite, add Session-Timers related headers if the feature is active for this session */
- if (p->method == SIP_INVITE && p->stimer && p->stimer->st_active == TRUE && p->stimer->st_active_peer_ua == TRUE) {
+ if (p->method == SIP_INVITE && p->stimer && p->stimer->st_active == TRUE) {
char se_hdr[256];
snprintf(se_hdr, sizeof(se_hdr), "%d;refresher=%s", p->stimer->st_interval,
p->stimer->st_ref == SESSION_TIMER_REFRESHER_US ? "uas" : "uac");
add_header(resp, "Session-Expires", se_hdr);
+ /* RFC 2048, Section 9
+ * If the refresher parameter in the Session-Expires header field in the
+ * 2xx response has a value of 'uac', the UAS MUST place a Require
+ * header field into the response with the value 'timer'.
+ * ...
+ * If the refresher parameter in
+ * the 2xx response has a value of 'uas' and the Supported header field
+ * in the request contained the value 'timer', the UAS SHOULD place a
+ * Require header field into the response with the value 'timer'
+ */
+ if (p->stimer->st_ref == SESSION_TIMER_REFRESHER_THEM ||
+ (p->stimer->st_ref == SESSION_TIMER_REFRESHER_US &&
+ p->stimer->st_active_peer_ua == TRUE)) {
+ resp->reqsipoptions |= SIP_OPT_TIMER;
+ }
}
if (msg[0] == '2' && (p->method == SIP_SUBSCRIBE || p->method == SIP_REGISTER || p->method == SIP_PUBLISH)) {
@@ -11902,9 +11945,9 @@
if (min_text_packet_size)
ast_str_append(&a_text, 0, "a=ptime:%d\r\n", min_text_packet_size);
- if (m_audio->len - m_audio->used < 2 || m_video->len - m_video->used < 2 ||
- m_text->len - m_text->used < 2 || a_text->len - a_text->used < 2 ||
- a_audio->len - a_audio->used < 2 || a_video->len - a_video->used < 2)
+ if (ast_str_size(m_audio) - ast_str_strlen(m_audio) < 2 || ast_str_size(m_video) - ast_str_strlen(m_video) < 2 ||
+ ast_str_size(m_text) - ast_str_strlen(m_text) < 2 || ast_str_size(a_text) - ast_str_strlen(a_text) < 2 ||
+ ast_str_size(a_audio) - ast_str_strlen(a_audio) < 2 || ast_str_size(a_video) - ast_str_strlen(a_video) < 2)
ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n");
}
@@ -11994,8 +12037,8 @@
for (i = 1; i <= 3; i++) {
if (p->offered_media[SDP_AUDIO].order_offered == i) {
if (needaudio) {
- add_content(resp, m_audio->str);
- add_content(resp, a_audio->str);
+ add_content(resp, ast_str_buffer(m_audio));
+ add_content(resp, ast_str_buffer(a_audio));
add_content(resp, hold);
if (a_crypto) {
add_content(resp, a_crypto);
@@ -12006,8 +12049,8 @@
}
} else if (p->offered_media[SDP_VIDEO].order_offered == i) {
if (needvideo) { /* only if video response is appropriate */
- add_content(resp, m_video->str);
- add_content(resp, a_video->str);
+ add_content(resp, ast_str_buffer(m_video));
+ add_content(resp, ast_str_buffer(a_video));
add_content(resp, hold); /* Repeat hold for the video stream */
if (v_a_crypto) {
add_content(resp, v_a_crypto);
@@ -12018,8 +12061,8 @@
}
} else if (p->offered_media[SDP_TEXT].order_offered == i) {
if (needtext) { /* only if text response is appropriate */
- add_content(resp, m_text->str);
- add_content(resp, a_text->str);
+ add_content(resp, ast_str_buffer(m_text));
+ add_content(resp, ast_str_buffer(a_text));
add_content(resp, hold); /* Repeat hold for the text stream */
if (t_a_crypto) {
add_content(resp, t_a_crypto);
@@ -12030,8 +12073,8 @@
}
} else if (p->offered_media[SDP_IMAGE].order_offered == i) {
if (add_t38) {
- add_content(resp, m_modem->str);
- add_content(resp, a_modem->str);
+ add_content(resp, ast_str_buffer(m_modem));
+ add_content(resp, ast_str_buffer(a_modem));
} else {
add_content(resp, "m=image 0 udptl t38\r\n");
}
@@ -12040,32 +12083,32 @@
} else {
/* generate new SDP from scratch, no offers */
if (needaudio) {
- add_content(resp, m_audio->str);
- add_content(resp, a_audio->str);
+ add_content(resp, ast_str_buffer(m_audio));
+ add_content(resp, ast_str_buffer(a_audio));
add_content(resp, hold);
if (a_crypto) {
add_content(resp, a_crypto);
}
}
if (needvideo) { /* only if video response is appropriate */
- add_content(resp, m_video->str);
- add_content(resp, a_video->str);
+ add_content(resp, ast_str_buffer(m_video));
+ add_content(resp, ast_str_buffer(a_video));
add_content(resp, hold); /* Repeat hold for the video stream */
if (v_a_crypto) {
add_content(resp, v_a_crypto);
}
}
if (needtext) { /* only if text response is appropriate */
- add_content(resp, m_text->str);
- add_content(resp, a_text->str);
+ add_content(resp, ast_str_buffer(m_text));
+ add_content(resp, ast_str_buffer(a_text));
add_content(resp, hold); /* Repeat hold for the text stream */
if (t_a_crypto) {
add_content(resp, t_a_crypto);
}
}
if (add_t38) {
- add_content(resp, m_modem->str);
- add_content(resp, a_modem->str);
+ add_content(resp, ast_str_buffer(m_modem));
+ add_content(resp, ast_str_buffer(a_modem));
}
}
@@ -12193,6 +12236,7 @@
ast_log(LOG_ERROR, "Can't add SDP to response, since we have no RTP session allocated. Call-ID %s\n", p->callid);
if (reliable && !p->pendinginvite)
p->pendinginvite = seqno; /* Buggy clients sends ACK on RINGING too */
+ add_required_respheader(&resp);
return send_response(p, &resp, reliable, seqno);
}
@@ -12459,7 +12503,7 @@
/* This is the request URI, which is the next hop of the call
which may or may not be the destination of the call
*/
- ast_string_field_set(p, uri, invite->str);
+ ast_string_field_set(p, uri, ast_str_buffer(invite));
if (!ast_strlen_zero(p->todnid)) {
/*! \todo Need to add back the VXML URL here at some point, possibly use build_string for all this junk */
@@ -13253,7 +13297,7 @@
break;
}
- add_content(&req, tmp->str);
+ add_content(&req, ast_str_buffer(tmp));
p->pendinginvite = p->ocseq; /* Remember that we have a pending NOTIFY in order not to confuse the NOTIFY subsystem */
@@ -13309,7 +13353,7 @@
}
}
- add_content(&req, out->str);
+ add_content(&req, ast_str_buffer(out));
if (!p->initreq.headers) {
initialize_initreq(p, &req);
@@ -16360,10 +16404,12 @@
if (ast_sockaddr_resolve_first(&tmp, c, 0)) {
ast_log(LOG_WARNING, "Could not resolve socket address for '%s'\n", c);
+ port = STANDARD_SIP_PORT;
+ } else if (!(port = ast_sockaddr_port(&tmp))) {
+ port = STANDARD_SIP_PORT;
}
- port = ast_sockaddr_port(&tmp);
- ast_sockaddr_set_port(&p->sa,
- port != 0 ? port : STANDARD_SIP_PORT);
+
+ ast_sockaddr_set_port(&p->sa, port);
if (sip_debug_test_pvt(p)) {
ast_verbose("Sending to %s (%s)\n",
@@ -17968,7 +18014,7 @@
print_group(fd, peer->pickupgroup, 0);
peer_mailboxes_to_str(&mailbox_str, peer);
ast_cli(fd, " MOH Suggest : %s\n", peer->mohsuggest);
- ast_cli(fd, " Mailbox : %s\n", mailbox_str->str);
+ ast_cli(fd, " Mailbox : %s\n", ast_str_buffer(mailbox_str));
ast_cli(fd, " VM Extension : %s\n", peer->vmexten);
ast_cli(fd, " LastMsgsSent : %d/%d\n", (peer->lastmsgssent & 0x7fff0000) >> 16, peer->lastmsgssent & 0xffff);
ast_cli(fd, " Call limit : %d\n", peer->call_limit);
@@ -18081,7 +18127,7 @@
astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->pickupgroup));
astman_append(s, "MOHSuggest: %s\r\n", peer->mohsuggest);
peer_mailboxes_to_str(&mailbox_str, peer);
- astman_append(s, "VoiceMailbox: %s\r\n", mailbox_str->str);
+ astman_append(s, "VoiceMailbox: %s\r\n", ast_str_buffer(mailbox_str));
astman_append(s, "TransferMode: %s\r\n", transfermode2str(peer->allowtransfer));
astman_append(s, "LastMsgsSent: %d\r\n", peer->lastmsgssent);
astman_append(s, "Maxforwards: %d\r\n", peer->maxforwards);
@@ -18310,7 +18356,7 @@
ast_cli(a->fd, "\n");
ast_sched_report(sched, &cbuf, &cbnames);
- ast_cli(a->fd, "%s", cbuf->str);
+ ast_cli(a->fd, "%s", ast_str_buffer(cbuf));
return CLI_SUCCESS;
}
@@ -18842,7 +18888,7 @@
cur->subscribed == MWI_NOTIFICATION ? "--" : cur->subscribeuri,
cur->subscribed == MWI_NOTIFICATION ? "<none>" : ast_extension_state2str(cur->laststate),
subscription_type2str(cur->subscribed),
- cur->subscribed == MWI_NOTIFICATION ? S_OR(mailbox_str->str, "<none>") : "<none>",
+ cur->subscribed == MWI_NOTIFICATION ? S_OR(ast_str_buffer(mailbox_str), "<none>") : "<none>",
cur->expiry
);
arg->numchans++;
@@ -19954,7 +20000,7 @@
} else if (!strcasecmp(colname, "mailbox")) {
struct ast_str *mailbox_str = ast_str_alloca(512);
peer_mailboxes_to_str(&mailbox_str, peer);
- ast_copy_string(buf, mailbox_str->str, len);
+ ast_copy_string(buf, ast_str_buffer(mailbox_str), len);
} else if (!strcasecmp(colname, "context")) {
ast_copy_string(buf, peer->context, len);
} else if (!strcasecmp(colname, "expire")) {
@@ -22649,12 +22695,12 @@
ast_str_set(&str, 0, "%s@%s", extension, sip_cfg.notifycid == IGNORE_CONTEXT ? "PICKUPMARK" : context);
- ast_debug(2, "About to call Pickup(%s)\n", str->str);
+ ast_debug(2, "About to call Pickup(%s)\n", ast_str_buffer(str));
/* There is no point in capturing the return value since pickup_exec
doesn't return anything meaningful unless the passed data is an empty
string (which in our case it will not be) */
- pbx_exec(channel, pickup, str->str);
+ pbx_exec(channel, pickup, ast_str_buffer(str));
return 0;
}
@@ -23387,7 +23433,7 @@
st_active = TRUE;
st_interval = st_get_se(p, TRUE);
tmp_st_ref = SESSION_TIMER_REFRESHER_US;
- p->stimer->st_active_peer_ua = FALSE;
+ p->stimer->st_active_peer_ua = (p->sipoptions & SIP_OPT_TIMER) ? TRUE : FALSE;
break;
default:
@@ -23667,8 +23713,11 @@
}
/* We have a channel, find the bridge */
- target.chan1 = targetcall_pvt->owner; /* Transferer to Asterisk */
+ target.chan1 = ast_channel_ref(targetcall_pvt->owner); /* Transferer to Asterisk */
target.chan2 = ast_bridged_channel(targetcall_pvt->owner); /* Asterisk to target */
+ if (target.chan2) {
+ ast_channel_ref(target.chan2);
+ }
if (!target.chan2 || !(target.chan2->_state == AST_STATE_UP || target.chan2->_state == AST_STATE_RINGING) ) {
/* Wrong state of new channel */
@@ -23807,6 +23856,10 @@
/* at this point if the transfer is successful only the transferer pvt should be locked. */
ast_party_connected_line_free(&connected_to_target);
ast_party_connected_line_free(&connected_to_transferee);
+ ast_channel_unref(target.chan1);
+ if (target.chan2) {
+ ast_channel_unref(target.chan2);
+ }
if (targetcall_pvt)
ao2_t_ref(targetcall_pvt, -1, "drop targetcall_pvt");
return 1;
@@ -25893,7 +25946,7 @@
lws2sws(req->data); /* Fix multiline headers */
if (req->debug) {
ast_verbose("\n<--- SIP read from %s:%s --->\n%s\n<------------->\n",
- get_transport(req->socket.type), ast_sockaddr_stringify(addr), req->data->str);
+ get_transport(req->socket.type), ast_sockaddr_stringify(addr), ast_str_buffer(req->data));
}
if (parse_request(req) == -1) { /* Bad packet, can't parse */
@@ -25934,7 +25987,7 @@
}
if (p->do_history) /* This is a request or response, note what it was for */
- append_history(p, "Rx", "%s / %s / %s", req->data->str, get_header(req, "CSeq"), REQ_OFFSET_TO_STR(req, rlPart2));
+ append_history(p, "Rx", "%s / %s / %s", ast_str_buffer(req->data), get_header(req, "CSeq"), REQ_OFFSET_TO_STR(req, rlPart2));
if (handle_incoming(p, req, addr, &recount, &nounlock) == -1) {
/* Request failed */
@@ -26221,11 +26274,11 @@
peer_mailboxes_to_str(&mailbox_str, peer);
ao2_unlock(peer);
/* If there is no mailbox do nothing */
- if (ast_strlen_zero(mailbox_str->str)) {
+ if (!ast_str_strlen(mailbox_str)) {
update_peer_lastmsgssent(peer, -1, 0);
return 0;
}
- ast_app_inboxcount(mailbox_str->str, &newmsgs, &oldmsgs);
+ ast_app_inboxcount(ast_str_buffer(mailbox_str), &newmsgs, &oldmsgs);
ao2_lock(peer);
}
@@ -28217,7 +28270,7 @@
ast_str_reset(fullcontact);
}
/* Reconstruct field, because realtime separates our value at the ';' */
- if (fullcontact->used > 0) {
+ if (ast_str_strlen(fullcontact) > 0) {
ast_str_append(&fullcontact, 0, ";%s", v->value);
} else {
ast_str_set(&fullcontact, 0, "%s", v->value);
@@ -28318,7 +28371,7 @@
/* XXX May need to revisit the final argument; does the realtime DB store whether
* the original contact was over TLS or not? XXX */
if (!ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) || ast_sockaddr_isnull(&peer->addr)) {
- __set_address_from_contact(fullcontact->str, &peer->addr, 0);
+ __set_address_from_contact(ast_str_buffer(fullcontact), &peer->addr, 0);
}
}
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/channels/chan_skinny.c
^
|
@@ -31,7 +31,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378341 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#include <sys/socket.h>
#include <netinet/in.h>
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/channels/misdn/isdn_lib.c
^
|
@@ -2700,6 +2700,10 @@
dummybc.l3_id = frm->dinfo;
bc = &dummybc;
+ /* set a reasonable cause */
+ bc->out_cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
+ /* if we want to send something the flag must be set! */
+ bc->need_release_complete = 1;
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
free_msg(msg);
@@ -4066,14 +4070,19 @@
if (bc)
send_msg(glob_mgr->midev, bc, msg);
else {
+ struct misdn_bchannel dummybc;
+
+ misdn_make_dummy(&dummybc, stack->port, frm->dinfo, stack->nt, 0);
if (frm->dinfo == MISDN_ID_GLOBAL || frm->dinfo == MISDN_ID_DUMMY ) {
- struct misdn_bchannel dummybc;
cb_log(5,0," --> GLOBAL/DUMMY\n");
- misdn_make_dummy(&dummybc, stack->port, frm->dinfo, stack->nt, 0);
- send_msg(glob_mgr->midev, &dummybc, msg);
} else {
- cb_log(0,0,"No bc for Message\n");
+ /*
+ * We need to be able to at least answer with RELEASE_COMPLETE
+ * on SETUP|INDICATION errors so use a dummy bc.
+ */
+ cb_log(0,0,"No bc for Message. Using dummy_bc\n");
}
+ send_msg(glob_mgr->midev, &dummybc, msg);
}
}
}
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/channels/sig_analog.c
^
|
@@ -2386,6 +2386,9 @@
if (p->cid_signalling == CID_SIG_DTMF) {
int k = 0;
int oldlinearity;
+ int timeout_ms;
+ int ms;
+ struct timeval start = ast_tvnow();
cs = NULL;
ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
@@ -2398,10 +2401,12 @@
* can drop some of them.
*/
ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
- res = 4000;/* This is a typical OFF time between rings. */
+ timeout_ms = 4000;/* This is a typical OFF time between rings. */
for (;;) {
struct ast_frame *f;
- res = ast_waitfor(chan, res);
+
+ ms = ast_remaining_ms(start, timeout_ms);
+ res = ast_waitfor(chan, ms);
if (res <= 0) {
/*
* We do not need to restore the analog_set_linear_mode()
@@ -2422,7 +2427,7 @@
dtmfbuf[k++] = f->subclass.integer;
}
ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
- res = 4000;/* This is a typical OFF time between rings. */
+ start = ast_tvnow();
}
ast_frfree(f);
if (chan->_state == AST_STATE_RING ||
@@ -2456,6 +2461,9 @@
numbuf[0] = 0;
if (!analog_start_cid_detect(p, p->cid_signalling)) {
+ int off_ms;
+ int ms;
+ struct timeval off_start;
while (1) {
res = analog_get_callerid(p, namebuf, numbuf, &ev, timeout - ast_tvdiff_ms(ast_tvnow(), start));
@@ -2493,10 +2501,12 @@
}
/* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
- res = 4000;/* This is a typical OFF time between rings. */
- for (;;) {
+ off_start = ast_tvnow();
+ off_ms = 4000;/* This is a typical OFF time between rings. */
+ while ((ms = ast_remaining_ms(off_start, off_ms))) {
struct ast_frame *f;
- res = ast_waitfor(chan, res);
+
+ res = ast_waitfor(chan, ms);
if (res <= 0) {
ast_log(LOG_WARNING, "CID timed out waiting for ring. "
"Exiting simple switch\n");
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/channels/sig_pri.c
^
|
@@ -1831,7 +1831,9 @@
struct ast_frame *f;
char ex[80];
/* Wait up to 30 seconds for an answer */
- int newms, ms = 30000;
+ int timeout_ms = 30000;
+ int ms;
+ struct timeval start;
ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
@@ -1840,7 +1842,12 @@
ast_hangup(chan);
return NULL;
}
- while ((newms = ast_waitfor(chan, ms)) > 0) {
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
+ if (ast_waitfor(chan, ms) <= 0) {
+ break;
+ }
+
f = ast_read(chan);
if (!f) {
/* Got hangup */
@@ -1866,7 +1873,6 @@
};
}
ast_frfree(f);
- ms = newms;
}
/* Hangup the channel since nothing happend */
ast_hangup(chan);
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/channels/sig_ss7.c
^
|
@@ -281,6 +281,24 @@
/*!
* \internal
+ * \brief Determine if a private channel structure is available.
+ *
+ * \param pvt Channel to determine if available.
+ *
+ * \return TRUE if the channel is available.
+ */
+static int sig_ss7_is_chan_available(struct sig_ss7_chan *pvt)
+{
+ if (!pvt->inalarm && !pvt->owner && !pvt->ss7call
+ && pvt->call_level == SIG_SS7_CALL_LEVEL_IDLE
+ && !pvt->locallyblocked && !pvt->remotelyblocked) {
+ return 1;
+ }
+ return 0;
+}
+
+/*!
+ * \internal
* \brief Obtain the sig_ss7 owner channel lock if the owner exists.
* \since 1.8
*
@@ -547,7 +565,7 @@
ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
ast_mutex_lock(&linkset->lock);
sig_ss7_lock_private(p);
- isup_rel(linkset->ss7, p->ss7call, -1);
+ isup_rel(linkset->ss7, p->ss7call, AST_CAUSE_SWITCH_CONGESTION);
p->call_level = SIG_SS7_CALL_LEVEL_IDLE;
p->alreadyhungup = 1;
return;
@@ -894,11 +912,11 @@
* We have not sent our IAM yet and we never will at this point.
*/
p->alreadyhungup = 1;
- isup_rel(ss7, e->iam.call, -1);
+ isup_rel(ss7, e->iam.call, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION);
}
p->call_level = SIG_SS7_CALL_LEVEL_GLARE;
if (p->owner) {
- p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING;
+ p->owner->hangupcause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
ast_channel_unlock(p->owner);
}
@@ -911,6 +929,13 @@
*/
ast_assert(!p->owner);
+ if (!sig_ss7_is_chan_available(p)) {
+ /* Circuit is likely blocked or in alarm. */
+ isup_rel(ss7, e->iam.call, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION);
+ sig_ss7_unlock_private(p);
+ break;
+ }
+
/* Mark channel as in use so no outgoing call will steal it. */
p->call_level = SIG_SS7_CALL_LEVEL_ALLOCATED;
p->ss7call = e->iam.call;
@@ -1349,24 +1374,6 @@
return 0;
}
-/*!
- * \internal
- * \brief Determine if a private channel structure is available.
- *
- * \param pvt Channel to determine if available.
- *
- * \return TRUE if the channel is available.
- */
-static int sig_ss7_is_chan_available(struct sig_ss7_chan *pvt)
-{
- if (!pvt->inalarm && !pvt->owner && !pvt->ss7call
- && pvt->call_level == SIG_SS7_CALL_LEVEL_IDLE
- && !pvt->locallyblocked && !pvt->remotelyblocked) {
- return 1;
- }
- return 0;
-}
-
/*!
* \brief Determine if the specified channel is available for an outgoing call.
* \since 1.8
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/channels/sip/include/sip.h
^
|
@@ -770,6 +770,7 @@
/* XXX Do we need to unref socket.ser when the request goes away? */
struct sip_socket socket; /*!< The socket used for this request */
AST_LIST_ENTRY(sip_request) next;
+ unsigned int reqsipoptions; /*!< Items needed for Required header in responses */
};
/* \brief given a sip_request and an offset, return the char * that resides there
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/contrib/realtime/mysql/sippeers.sql
^
|
@@ -28,8 +28,8 @@
`callgroup` varchar(40) DEFAULT NULL,
`pickupgroup` varchar(40) DEFAULT NULL,
`language` varchar(40) DEFAULT NULL,
- `allow` varchar(40) DEFAULT NULL,
`disallow` varchar(40) DEFAULT NULL,
+ `allow` varchar(40) DEFAULT NULL,
`insecure` varchar(40) DEFAULT NULL,
`trustrpid` enum('yes','no') DEFAULT NULL,
`progressinband` enum('yes','no','never') DEFAULT NULL,
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/funcs/func_devstate.c
^
|
@@ -36,7 +36,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378341 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#include "asterisk/module.h"
#include "asterisk/channel.h"
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/funcs/func_volume.c
^
|
@@ -32,7 +32,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 368898 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376919 $")
#include "asterisk/module.h"
#include "asterisk/channel.h"
@@ -65,7 +65,7 @@
<para>Set(VOLUME(TX)=3)</para>
<para>Set(VOLUME(RX)=2)</para>
<para>Set(VOLUME(TX,p)=3)</para>
- <para>Set(VOLUME(RX,p)=3></para>
+ <para>Set(VOLUME(RX,p)=3)</para>
</description>
</function>
***/
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/include/asterisk/_private.h
^
|
@@ -19,6 +19,7 @@
int load_pbx(void); /*!< Provided by pbx.c */
int init_logger(void); /*!< Provided by logger.c */
void close_logger(void); /*!< Provided by logger.c */
+void clean_time_zones(void); /*!< Provided by localtime.c */
int init_framer(void); /*!< Provided by frame.c */
int ast_term_init(void); /*!< Provided by term.c */
int astdb_init(void); /*!< Provided by db.c */
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/include/asterisk/astmm.h
^
|
@@ -65,7 +65,8 @@
__attribute__((format(printf, 5, 6)));
int __ast_vasprintf(char **strp, const char *format, va_list ap, const char *file, int lineno, const char *func)
__attribute__((format(printf, 2, 0)));
-void __ast_mm_init(void);
+void __ast_mm_init_phase_1(void);
+void __ast_mm_init_phase_2(void);
/* Provide our own definitions */
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/include/asterisk/channel.h
^
|
@@ -870,6 +870,8 @@
char macrocontext[AST_MAX_CONTEXT]; /*!< Macro: Current non-macro context. See app_macro.c */
char macroexten[AST_MAX_EXTENSION]; /*!< Macro: Current non-macro extension. See app_macro.c */
char emulate_dtmf_digit; /*!< Digit being emulated */
+ char sending_dtmf_digit; /*!< Digit this channel is currently sending out. (zero if not sending) */
+ struct timeval sending_dtmf_tv; /*!< The time this channel started sending the current digit. (Invalid if sending_dtmf_digit is zero.) */
};
/*! \brief ast_channel_tech Properties */
@@ -1692,7 +1694,7 @@
/*!
* \brief Wait for a specified amount of time, looking for hangups
* \param chan channel to wait for
- * \param ms length of time in milliseconds to sleep
+ * \param ms length of time in milliseconds to sleep. This should never be less than zero.
* \details
* Waits for a specified amount of time, servicing the channel as required.
* \return returns -1 on hangup, otherwise 0.
@@ -1702,7 +1704,7 @@
/*!
* \brief Wait for a specified amount of time, looking for hangups and a condition argument
* \param chan channel to wait for
- * \param ms length of time in milliseconds to sleep
+ * \param ms length of time in milliseconds to sleep.
* \param cond a function pointer for testing continue condition
* \param data argument to be passed to the condition test function
* \return returns -1 on hangup, otherwise 0.
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/include/asterisk/features.h
^
|
@@ -169,6 +169,18 @@
/*! \brief Determine system call pickup extension */
const char *ast_pickup_ext(void);
+/*!
+ * \brief Simulate a DTMF end on a broken bridge channel.
+ *
+ * \param chan Channel sending DTMF that has not ended.
+ * \param digit DTMF digit to stop.
+ * \param start DTMF digit start time.
+ * \param why Reason bridge broken.
+ *
+ * \return Nothing
+ */
+void ast_bridge_end_dtmf(struct ast_channel *chan, char digit, struct timeval start, const char *why);
+
/*! \brief Bridge a call, optionally allowing redirection */
int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer,struct ast_bridge_config *config);
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/include/asterisk/hashtab.h
^
|
@@ -23,6 +23,9 @@
* \brief Generic (perhaps overly so) hashtable implementation
* \ref AstHash
*/
+
+#include "asterisk/lock.h"
+
/*! \page AstHash Hash Table support in Asterisk
A hash table is a structure that allows for an exact-match search
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/include/asterisk/linkedlists.h
^
|
@@ -834,34 +834,38 @@
* \param elm This is a pointer to the entry to be removed.
* \param field This is the name of the field (declared using AST_LIST_ENTRY())
* used to link entries of this list together.
- * \warning The removed entry is \b not freed nor modified in any way.
+ * \retval elm if elm was in the list.
+ * \retval NULL if elm was not in the list or elm was NULL.
+ * \warning The removed entry is \b not freed.
*/
-#define AST_LIST_REMOVE(head, elm, field) ({ \
- __typeof(elm) __res = NULL; \
- __typeof(elm) __tmp = elm; \
- if (!__tmp) { \
- __res = NULL; \
- } else if ((head)->first == (elm)) { \
- __res = (head)->first; \
- (head)->first = (elm)->field.next; \
- if ((head)->last == (elm)) \
- (head)->last = NULL; \
- } else { \
- typeof(elm) curelm = (head)->first; \
- while (curelm && (curelm->field.next != (elm))) \
- curelm = curelm->field.next; \
- if (curelm) { \
- __res = (elm); \
- curelm->field.next = (elm)->field.next; \
- if ((head)->last == (elm)) \
- (head)->last = curelm; \
- } \
- } \
- if (__res) { \
- (__res)->field.next = NULL; \
- } \
- (__res); \
-})
+#define AST_LIST_REMOVE(head, elm, field) \
+ ({ \
+ __typeof(elm) __elm = (elm); \
+ if (__elm) { \
+ if ((head)->first == __elm) { \
+ (head)->first = __elm->field.next; \
+ __elm->field.next = NULL; \
+ if ((head)->last == __elm) { \
+ (head)->last = NULL; \
+ } \
+ } else { \
+ typeof(elm) __prev = (head)->first; \
+ while (__prev && __prev->field.next != __elm) { \
+ __prev = __prev->field.next; \
+ } \
+ if (__prev) { \
+ __prev->field.next = __elm->field.next; \
+ __elm->field.next = NULL; \
+ if ((head)->last == __elm) { \
+ (head)->last = __prev; \
+ } \
+ } else { \
+ __elm = NULL; \
+ } \
+ } \
+ } \
+ __elm; \
+ })
#define AST_RWLIST_REMOVE AST_LIST_REMOVE
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/include/asterisk/lock.h
^
|
@@ -428,12 +428,24 @@
static inline void ast_reentrancy_lock(struct ast_lock_track *lt)
{
- pthread_mutex_lock(<->reentr_mutex);
+ int res;
+ if ((res = pthread_mutex_lock(<->reentr_mutex))) {
+ fprintf(stderr, "ast_reentrancy_lock failed: '%s' (%d)\n", strerror(res), res);
+#if defined(DO_CRASH) || defined(THREAD_CRASH)
+ abort();
+#endif
+ }
}
static inline void ast_reentrancy_unlock(struct ast_lock_track *lt)
{
- pthread_mutex_unlock(<->reentr_mutex);
+ int res;
+ if ((res = pthread_mutex_unlock(<->reentr_mutex))) {
+ fprintf(stderr, "ast_reentrancy_unlock failed: '%s' (%d)\n", strerror(res), res);
+#if defined(DO_CRASH) || defined(THREAD_CRASH)
+ abort();
+#endif
+ }
}
static inline void ast_reentrancy_init(struct ast_lock_track **plt)
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/include/asterisk/time.h
^
|
@@ -152,6 +152,20 @@
struct timeval ast_tvsub(struct timeval a, struct timeval b);
/*!
+ * \brief Calculate remaining milliseconds given a starting timestamp
+ * and upper bound
+ *
+ * If the upper bound is negative, then this indicates that there is no
+ * upper bound on the amount of time to wait. This will result in a
+ * negative return.
+ *
+ * \param start When timing started being calculated
+ * \param max_ms The maximum number of milliseconds to wait from start. May be negative.
+ * \return The number of milliseconds left to wait for. May be negative.
+ */
+int ast_remaining_ms(struct timeval start, int max_ms);
+
+/*!
* \brief Returns a timeval from sec, usec
*/
AST_INLINE_API(
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/include/asterisk/utils.h
^
|
@@ -706,32 +706,27 @@
#ifdef AST_DEVMODE
+void __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function);
#define ast_assert(a) _ast_assert(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
-static void force_inline _ast_assert(int condition, const char *condition_str,
- const char *file, int line, const char *function)
+static void force_inline _ast_assert(int condition, const char *condition_str, const char *file, int line, const char *function)
{
if (__builtin_expect(!condition, 1)) {
- /* Attempt to put it into the logger, but hope that at least someone saw the
- * message on stderr ... */
- ast_log(__LOG_ERROR, file, line, function, "FRACK!, Failed assertion %s (%d)\n",
- condition_str, condition);
- fprintf(stderr, "FRACK!, Failed assertion %s (%d) at line %d in %s of %s\n",
- condition_str, condition, line, function, file);
- /* Give the logger a chance to get the message out, just in case we abort(), or
- * Asterisk crashes due to whatever problem just happened after we exit ast_assert(). */
- usleep(1);
-#ifdef DO_CRASH
- abort();
- /* Just in case abort() doesn't work or something else super silly,
- * and for Qwell's amusement. */
- *((int*)0)=0;
-#endif
+ __ast_assert_failed(condition, condition_str, file, line, function);
}
}
#else
#define ast_assert(a)
#endif
+/*!
+ * \brief Force a crash if DO_CRASH is defined.
+ *
+ * \note If DO_CRASH is not defined then the function returns.
+ *
+ * \return Nothing
+ */
+void ast_do_crash(void);
+
#include "asterisk/strings.h"
/*!
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/asterisk.c
^
|
@@ -65,7 +65,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 374230 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 377165 $")
#include "asterisk/_private.h"
@@ -209,10 +209,10 @@
struct ast_atexit {
void (*func)(void);
- AST_RWLIST_ENTRY(ast_atexit) list;
+ AST_LIST_ENTRY(ast_atexit) list;
};
-static AST_RWLIST_HEAD_STATIC(atexits, ast_atexit);
+static AST_LIST_HEAD_STATIC(atexits, ast_atexit);
struct timeval ast_startuptime;
struct timeval ast_lastreloadtime;
@@ -294,6 +294,7 @@
static pthread_t mon_sig_flags;
static int canary_pid = 0;
static char canary_filename[128];
+static int multi_thread_safe;
static char randompool[256];
@@ -402,6 +403,8 @@
if (!new)
return;
+
+ ast_assert(multi_thread_safe);
new->id = pthread_self();
new->name = name; /* steal the allocated memory for the thread name */
AST_RWLIST_WRLOCK(&thread_list);
@@ -942,39 +945,57 @@
#endif /* ! LOW_MEMORY */
+static void ast_run_atexits(void)
+{
+ struct ast_atexit *ae;
+
+ AST_LIST_LOCK(&atexits);
+ while ((ae = AST_LIST_REMOVE_HEAD(&atexits, list))) {
+ if (ae->func) {
+ ae->func();
+ }
+ ast_free(ae);
+ }
+ AST_LIST_UNLOCK(&atexits);
+}
+
+static void __ast_unregister_atexit(void (*func)(void))
+{
+ struct ast_atexit *ae;
+
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&atexits, ae, list) {
+ if (ae->func == func) {
+ AST_LIST_REMOVE_CURRENT(list);
+ ast_free(ae);
+ break;
+ }
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+}
+
int ast_register_atexit(void (*func)(void))
{
struct ast_atexit *ae;
- if (!(ae = ast_calloc(1, sizeof(*ae))))
+ ae = ast_calloc(1, sizeof(*ae));
+ if (!ae) {
return -1;
-
+ }
ae->func = func;
- ast_unregister_atexit(func);
-
- AST_RWLIST_WRLOCK(&atexits);
- AST_RWLIST_INSERT_HEAD(&atexits, ae, list);
- AST_RWLIST_UNLOCK(&atexits);
+ AST_LIST_LOCK(&atexits);
+ __ast_unregister_atexit(func);
+ AST_LIST_INSERT_HEAD(&atexits, ae, list);
+ AST_LIST_UNLOCK(&atexits);
return 0;
}
void ast_unregister_atexit(void (*func)(void))
{
- struct ast_atexit *ae = NULL;
-
- AST_RWLIST_WRLOCK(&atexits);
- AST_RWLIST_TRAVERSE_SAFE_BEGIN(&atexits, ae, list) {
- if (ae->func == func) {
- AST_RWLIST_REMOVE_CURRENT(list);
- break;
- }
- }
- AST_RWLIST_TRAVERSE_SAFE_END;
- AST_RWLIST_UNLOCK(&atexits);
-
- free(ae);
+ AST_LIST_LOCK(&atexits);
+ __ast_unregister_atexit(func);
+ AST_LIST_UNLOCK(&atexits);
}
/* Sending commands from consoles back to the daemon requires a terminating NULL */
@@ -1502,7 +1523,7 @@
int res;
ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
if (ast_consock < 0) {
- ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
+ fprintf(stderr, "Unable to create socket: %s\n", strerror(errno));
return 0;
}
memset(&sunaddr, 0, sizeof(sunaddr));
@@ -1646,17 +1667,6 @@
return 0;
}
-static void ast_run_atexits(void)
-{
- struct ast_atexit *ae;
- AST_RWLIST_RDLOCK(&atexits);
- AST_RWLIST_TRAVERSE(&atexits, ae, list) {
- if (ae->func)
- ae->func();
- }
- AST_RWLIST_UNLOCK(&atexits);
-}
-
static int can_safely_quit(shutdown_nice_t niceness, int restart);
static void really_quit(int num, shutdown_nice_t niceness, int restart);
@@ -1735,8 +1745,11 @@
return 1;
}
+/*! Called when exiting is certain. */
static void really_quit(int num, shutdown_nice_t niceness, int restart)
{
+ int active_channels;
+
if (niceness >= SHUTDOWN_NICE) {
ast_module_shutdown();
}
@@ -1763,21 +1776,24 @@
}
}
}
+ active_channels = ast_active_channels();
/* The manager event for shutdown must happen prior to ast_run_atexits, as
* the manager interface will dispose of its sessions as part of its
* shutdown.
*/
manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\n"
"Restart: %s\r\n",
- ast_active_channels() ? "Uncleanly" : "Cleanly",
+ active_channels ? "Uncleanly" : "Cleanly",
restart ? "True" : "False");
+ if (option_verbose && ast_opt_console) {
+ ast_verbose("Asterisk %s ending (%d).\n",
+ active_channels ? "uncleanly" : "cleanly", num);
+ }
if (option_verbose)
ast_verbose("Executing last minute cleanups\n");
ast_run_atexits();
- /* Called on exit */
- if (option_verbose && ast_opt_console)
- ast_verbose("Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num);
+
ast_debug(1, "Asterisk ending (%d).\n", num);
if (ast_socket > -1) {
pthread_cancel(lthread);
@@ -1804,6 +1820,7 @@
/* close logger */
close_logger();
+ clean_time_zones();
/* If there is a consolethread running send it a SIGHUP
so it can execvp, otherwise we can do it ourselves */
@@ -1817,6 +1834,7 @@
} else {
/* close logger */
close_logger();
+ clean_time_zones();
}
exit(0);
@@ -2215,14 +2233,25 @@
#define ASTERISK_PROMPT2 "%s*CLI> "
-static struct ast_cli_entry cli_asterisk[] = {
- AST_CLI_DEFINE(handle_abort_shutdown, "Cancel a running shutdown"),
+/*!
+ * \brief Shutdown Asterisk CLI commands.
+ *
+ * \note These CLI commands cannot be unregistered at shutdown
+ * because one of them is likely the reason for the shutdown.
+ * The CLI generates a warning if a command is in-use when it is
+ * unregistered.
+ */
+static struct ast_cli_entry cli_asterisk_shutdown[] = {
AST_CLI_DEFINE(handle_stop_now, "Shut down Asterisk immediately"),
AST_CLI_DEFINE(handle_stop_gracefully, "Gracefully shut down Asterisk"),
AST_CLI_DEFINE(handle_stop_when_convenient, "Shut down Asterisk at empty call volume"),
AST_CLI_DEFINE(handle_restart_now, "Restart Asterisk immediately"),
AST_CLI_DEFINE(handle_restart_gracefully, "Restart Asterisk gracefully"),
AST_CLI_DEFINE(handle_restart_when_convenient, "Restart Asterisk at empty call volume"),
+};
+
+static struct ast_cli_entry cli_asterisk[] = {
+ AST_CLI_DEFINE(handle_abort_shutdown, "Cancel a running shutdown"),
AST_CLI_DEFINE(show_warranty, "Show the warranty (if any) for this copy of Asterisk"),
AST_CLI_DEFINE(show_license, "Show the license(s) for this copy of Asterisk"),
AST_CLI_DEFINE(handle_version, "Display version info"),
@@ -2264,7 +2293,7 @@
break;
if (errno == EINTR)
continue;
- ast_log(LOG_ERROR, "poll failed: %s\n", strerror(errno));
+ fprintf(stderr, "poll failed: %s\n", strerror(errno));
break;
}
@@ -2978,10 +3007,12 @@
if (ast_opt_override_config) {
cfg = ast_config_load2(ast_config_AST_CONFIG_FILE, "" /* core, can't reload */, config_flags);
- if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID)
- ast_log(LOG_WARNING, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
- } else
+ if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
+ fprintf(stderr, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
+ }
+ } else {
cfg = ast_config_load2(config, "" /* core, can't reload */, config_flags);
+ }
/* init with buildtime config */
ast_copy_string(cfg_paths.config_dir, DEFAULT_CONFIG_DIR, sizeof(cfg_paths.config_dir));
@@ -3187,7 +3218,7 @@
for (v = ast_variable_browse(cfg, "compat"); v; v = v->next) {
float version;
if (sscanf(v->value, "%30f", &version) != 1) {
- ast_log(LOG_WARNING, "Compatibility version for option '%s' is not a number: '%s'\n", v->name, v->value);
+ fprintf(stderr, "Compatibility version for option '%s' is not a number: '%s'\n", v->name, v->value);
continue;
}
if (!strcasecmp(v->name, "app_set")) {
@@ -3302,6 +3333,28 @@
setenv("AST_VERSION", ast_get_version(), 1);
}
+static void print_intro_message(const char *runuser, const char *rungroup)
+{
+ if (ast_opt_console || option_verbose) {
+ if (ast_register_verbose(console_verboser)) {
+ fprintf(stderr, "Unable to register console verboser?\n");
+ return;
+ }
+ WELCOME_MESSAGE;
+ if (runuser) {
+ ast_verbose("Running as user '%s'\n", runuser);
+ }
+ if (rungroup) {
+ ast_verbose("Running under group '%s'\n", rungroup);
+ }
+ }
+}
+
+static void main_atexit(void)
+{
+ ast_cli_unregister_multiple(cli_asterisk, ARRAY_LEN(cli_asterisk));
+}
+
int main(int argc, char *argv[])
{
int c;
@@ -3339,15 +3392,6 @@
if (gethostname(hostname, sizeof(hostname)-1))
ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
ast_mainpid = getpid();
- ast_ulaw_init();
- ast_alaw_init();
- callerid_init();
- ast_builtins_init();
- ast_utils_init();
- tdd_init();
- ast_tps_init();
- ast_fd_init();
- ast_pbx_init();
if (getenv("HOME"))
snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
@@ -3468,16 +3512,6 @@
}
}
- if (ast_opt_console || option_verbose || (ast_opt_remote && !ast_opt_exec)) {
- if (ast_register_verbose(console_verboser)) {
- ast_log(LOG_WARNING, "Unable to register console verboser?\n");
- }
- WELCOME_MESSAGE;
- }
-
- if (ast_opt_console && !option_verbose)
- ast_verbose("[ Booting...\n");
-
/* For remote connections, change the name of the remote connection.
* We do this for the benefit of init scripts (which need to know if/when
* the main asterisk process has died yet). */
@@ -3488,21 +3522,18 @@
}
}
- if (ast_opt_console && !option_verbose) {
- ast_verbose("[ Reading Master Configuration ]\n");
- }
-
ast_readconfig();
env_init();
if (ast_opt_remote && remotesock != NULL)
ast_copy_string((char *) cfg_paths.socket_path, remotesock, sizeof(cfg_paths.socket_path));
- if (!ast_language_is_prefix && !ast_opt_remote)
- ast_log(LOG_WARNING, "The 'languageprefix' option in asterisk.conf is deprecated; in a future release it will be removed, and your sound files will need to be organized in the 'new style' language layout.\n");
+ if (!ast_language_is_prefix && !ast_opt_remote) {
+ fprintf(stderr, "The 'languageprefix' option in asterisk.conf is deprecated; in a future release it will be removed, and your sound files will need to be organized in the 'new style' language layout.\n");
+ }
if (ast_opt_always_fork && (ast_opt_remote || ast_opt_console)) {
- ast_log(LOG_WARNING, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
+ fprintf(stderr, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
ast_clear_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
}
@@ -3511,12 +3542,12 @@
l.rlim_cur = RLIM_INFINITY;
l.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_CORE, &l)) {
- ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n", strerror(errno));
+ fprintf(stderr, "Unable to disable core size resource limit: %s\n", strerror(errno));
}
}
if (getrlimit(RLIMIT_NOFILE, &l)) {
- ast_log(LOG_WARNING, "Unable to check file descriptor limit: %s\n", strerror(errno));
+ fprintf(stderr, "Unable to check file descriptor limit: %s\n", strerror(errno));
}
#if !defined(CONFIGURE_RAN_AS_ROOT)
@@ -3533,13 +3564,13 @@
}
if (!(fd = open("/dev/null", O_RDONLY))) {
- ast_log(LOG_ERROR, "Cannot open a file descriptor at boot? %s\n", strerror(errno));
+ fprintf(stderr, "Cannot open a file descriptor at boot? %s\n", strerror(errno));
break; /* XXX Should we exit() here? XXX */
}
fd2 = (l.rlim_cur > sizeof(readers) * 8 ? sizeof(readers) * 8 : l.rlim_cur) - 1;
if (dup2(fd, fd2) < 0) {
- ast_log(LOG_WARNING, "Cannot open maximum file descriptor %d at boot? %s\n", fd2, strerror(errno));
+ fprintf(stderr, "Cannot open maximum file descriptor %d at boot? %s\n", fd2, strerror(errno));
close(fd);
break;
}
@@ -3547,7 +3578,7 @@
FD_ZERO(&readers);
FD_SET(fd2, &readers);
if (ast_select(fd2 + 1, &readers, NULL, NULL, &tv) < 0) {
- ast_log(LOG_WARNING, "Maximum select()able file descriptor is %d\n", FD_SETSIZE);
+ fprintf(stderr, "Maximum select()able file descriptor is %d\n", FD_SETSIZE);
}
ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
close(fd);
@@ -3573,7 +3604,7 @@
if (errno == EEXIST) {
rundir_exists = 1;
} else {
- ast_log(LOG_WARNING, "Unable to create socket file directory. Remote consoles will not be able to connect! (%s)\n", strerror(x));
+ fprintf(stderr, "Unable to create socket file directory. Remote consoles will not be able to connect! (%s)\n", strerror(x));
}
}
@@ -3587,22 +3618,20 @@
struct group *gr;
gr = getgrnam(rungroup);
if (!gr) {
- ast_log(LOG_WARNING, "No such group '%s'!\n", rungroup);
+ fprintf(stderr, "No such group '%s'!\n", rungroup);
exit(1);
}
if (!rundir_exists && chown(ast_config_AST_RUN_DIR, -1, gr->gr_gid)) {
- ast_log(LOG_WARNING, "Unable to chgrp run directory to %d (%s)\n", (int) gr->gr_gid, rungroup);
+ fprintf(stderr, "Unable to chgrp run directory to %d (%s)\n", (int) gr->gr_gid, rungroup);
}
if (setgid(gr->gr_gid)) {
- ast_log(LOG_WARNING, "Unable to setgid to %d (%s)\n", (int)gr->gr_gid, rungroup);
+ fprintf(stderr, "Unable to setgid to %d (%s)\n", (int)gr->gr_gid, rungroup);
exit(1);
}
if (setgroups(0, NULL)) {
- ast_log(LOG_WARNING, "Unable to drop unneeded groups\n");
+ fprintf(stderr, "Unable to drop unneeded groups\n");
exit(1);
}
- if (option_verbose)
- ast_verbose("Running as group '%s'\n", rungroup);
}
if (runuser && !ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)) {
@@ -3612,11 +3641,11 @@
struct passwd *pw;
pw = getpwnam(runuser);
if (!pw) {
- ast_log(LOG_WARNING, "No such user '%s'!\n", runuser);
+ fprintf(stderr, "No such user '%s'!\n", runuser);
exit(1);
}
if (chown(ast_config_AST_RUN_DIR, pw->pw_uid, -1)) {
- ast_log(LOG_WARNING, "Unable to chown run directory to %d (%s)\n", (int) pw->pw_uid, runuser);
+ fprintf(stderr, "Unable to chown run directory to %d (%s)\n", (int) pw->pw_uid, runuser);
}
#ifdef HAVE_CAP
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
@@ -3625,36 +3654,35 @@
}
#endif /* HAVE_CAP */
if (!isroot && pw->pw_uid != geteuid()) {
- ast_log(LOG_ERROR, "Asterisk started as nonroot, but runuser '%s' requested.\n", runuser);
+ fprintf(stderr, "Asterisk started as nonroot, but runuser '%s' requested.\n", runuser);
exit(1);
}
if (!rungroup) {
if (setgid(pw->pw_gid)) {
- ast_log(LOG_WARNING, "Unable to setgid to %d!\n", (int)pw->pw_gid);
+ fprintf(stderr, "Unable to setgid to %d!\n", (int)pw->pw_gid);
exit(1);
}
if (isroot && initgroups(pw->pw_name, pw->pw_gid)) {
- ast_log(LOG_WARNING, "Unable to init groups for '%s'\n", runuser);
+ fprintf(stderr, "Unable to init groups for '%s'\n", runuser);
exit(1);
}
}
if (setuid(pw->pw_uid)) {
- ast_log(LOG_WARNING, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
+ fprintf(stderr, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
exit(1);
}
- if (option_verbose)
- ast_verbose("Running as user '%s'\n", runuser);
#ifdef HAVE_CAP
if (has_cap) {
cap_t cap;
cap = cap_from_text("cap_net_admin=eip");
- if (cap_set_proc(cap))
- ast_log(LOG_WARNING, "Unable to install capabilities.\n");
-
- if (cap_free(cap))
- ast_log(LOG_WARNING, "Unable to drop capabilities.\n");
+ if (cap_set_proc(cap)) {
+ fprintf(stderr, "Unable to install capabilities.\n");
+ }
+ if (cap_free(cap)) {
+ fprintf(stderr, "Unable to drop capabilities.\n");
+ }
}
#endif /* HAVE_CAP */
}
@@ -3664,7 +3692,7 @@
#ifdef linux
if (geteuid() && ast_opt_dump_core) {
if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
- ast_log(LOG_WARNING, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
+ fprintf(stderr, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
}
}
#endif
@@ -3676,93 +3704,74 @@
#endif
char dir[PATH_MAX];
if (!getcwd(dir, sizeof(dir)) || eaccess(dir, R_OK | X_OK | F_OK)) {
- ast_log(LOG_ERROR, "Unable to access the running directory (%s). Changing to '/' for compatibility.\n", strerror(errno));
+ fprintf(stderr, "Unable to access the running directory (%s). Changing to '/' for compatibility.\n", strerror(errno));
/* If we cannot access the CWD, then we couldn't dump core anyway,
* so chdir("/") won't break anything. */
if (chdir("/")) {
/* chdir(/) should never fail, so this ends up being a no-op */
- ast_log(LOG_ERROR, "chdir(\"/\") failed?!! %s\n", strerror(errno));
+ fprintf(stderr, "chdir(\"/\") failed?!! %s\n", strerror(errno));
}
} else
#endif /* defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS) */
if (!ast_opt_no_fork && !ast_opt_dump_core) {
/* Backgrounding, but no cores, so chdir won't break anything. */
if (chdir("/")) {
- ast_log(LOG_ERROR, "Unable to chdir(\"/\") ?!! %s\n", strerror(errno));
+ fprintf(stderr, "Unable to chdir(\"/\") ?!! %s\n", strerror(errno));
}
}
}
- ast_term_init();
- printf("%s", term_end());
- fflush(stdout);
-
- if (ast_opt_console && !option_verbose)
- ast_verbose("[ Initializing Custom Configuration Options ]\n");
- /* custom config setup */
- register_config_cli();
- read_config_maps();
-
- if (ast_opt_console) {
- if (el_hist == NULL || el == NULL)
- ast_el_initialize();
-
- if (!ast_strlen_zero(filename))
- ast_el_read_history(filename);
- }
-
if (ast_tryconnect()) {
/* One is already running */
if (ast_opt_remote) {
+ multi_thread_safe = 1;
if (ast_opt_exec) {
ast_remotecontrol(xarg);
quit_handler(0, SHUTDOWN_FAST, 0);
exit(0);
}
+ print_intro_message(runuser, rungroup);
printf("%s", term_quit());
ast_remotecontrol(NULL);
quit_handler(0, SHUTDOWN_FAST, 0);
exit(0);
} else {
- ast_log(LOG_ERROR, "Asterisk already running on %s. Use 'asterisk -r' to connect.\n", ast_config_AST_SOCKET);
+ fprintf(stderr, "Asterisk already running on %s. Use 'asterisk -r' to connect.\n", ast_config_AST_SOCKET);
printf("%s", term_quit());
exit(1);
}
} else if (ast_opt_remote || ast_opt_exec) {
- ast_log(LOG_ERROR, "Unable to connect to remote asterisk (does %s exist?)\n", ast_config_AST_SOCKET);
+ fprintf(stderr, "Unable to connect to remote asterisk (does %s exist?)\n", ast_config_AST_SOCKET);
printf("%s", term_quit());
exit(1);
}
- /* Blindly write pid file since we couldn't connect */
- unlink(ast_config_AST_PID);
- f = fopen(ast_config_AST_PID, "w");
- if (f) {
- fprintf(f, "%ld\n", (long)getpid());
- fclose(f);
- } else
- ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
+ /* This needs to remain as high up in the initial start up as possible.
+ * daemon causes a fork to occur, which has all sorts of unintended
+ * consequences for things that interact with threads. This call *must*
+ * occur before anything in Asterisk spawns or manipulates thread related
+ * primitives. */
#if HAVE_WORKING_FORK
if (ast_opt_always_fork || !ast_opt_no_fork) {
#ifndef HAVE_SBIN_LAUNCHD
if (daemon(1, 0) < 0) {
- ast_log(LOG_ERROR, "daemon() failed: %s\n", strerror(errno));
+ fprintf(stderr, "daemon() failed: %s\n", strerror(errno));
}
- ast_mainpid = getpid();
- /* Blindly re-write pid file since we are forking */
- unlink(ast_config_AST_PID);
- f = fopen(ast_config_AST_PID, "w");
- if (f) {
- fprintf(f, "%ld\n", (long)ast_mainpid);
- fclose(f);
- } else
- ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
#else
- ast_log(LOG_WARNING, "Mac OS X detected. Use 'launchctl load /Library/LaunchDaemon/org.asterisk.asterisk.plist'.\n");
+ fprintf(stderr, "Mac OS X detected. Use 'launchctl load /Library/LaunchDaemon/org.asterisk.asterisk.plist'.\n");
#endif
}
#endif
+ /* At this point everything has been forked successfully,
+ * we have determined that we aren't attempting to connect to
+ * an Asterisk instance, and that there isn't one already running. */
+ multi_thread_safe = 1;
+
+#if defined(__AST_DEBUG_MALLOC)
+ __ast_mm_init_phase_1();
+#endif /* defined(__AST_DEBUG_MALLOC) */
+
/* Spawning of astcanary must happen AFTER the call to daemon(3) */
if (isroot && ast_opt_high_priority) {
snprintf(canary_filename, sizeof(canary_filename), "%s/alt.asterisk.canary.tweet.tweet.tweet", ast_config_AST_RUN_DIR);
@@ -3802,6 +3811,67 @@
ast_register_atexit(canary_exit);
}
+ /* Blindly write the PID file. */
+ ast_mainpid = getpid();
+ unlink(ast_config_AST_PID);
+ f = fopen(ast_config_AST_PID, "w");
+ if (f) {
+ fprintf(f, "%ld\n", (long)getpid());
+ fclose(f);
+ } else {
+ fprintf(stderr, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
+ }
+
+ /* Initialize the terminal. Since all processes have been forked,
+ * we can now start using the standard log messages.
+ */
+ ast_term_init();
+ printf("%s", term_end());
+ fflush(stdout);
+
+ print_intro_message(runuser, rungroup);
+
+ if (ast_opt_console && !option_verbose) {
+ ast_verbose("[ Initializing Custom Configuration Options ]\n");
+ }
+ /* custom config setup */
+ register_config_cli();
+ read_config_maps();
+
+ if (ast_opt_console) {
+ if (el_hist == NULL || el == NULL)
+ ast_el_initialize();
+
+ if (!ast_strlen_zero(filename))
+ ast_el_read_history(filename);
+ }
+
+ ast_ulaw_init();
+ ast_alaw_init();
+ tdd_init();
+ callerid_init();
+ ast_builtins_init();
+
+ if (ast_utils_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
+
+ if (ast_tps_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
+
+ if (ast_fd_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
+
+ if (ast_pbx_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
+
if (ast_event_init()) {
printf("%s", term_quit());
exit(1);
@@ -3981,12 +4051,14 @@
pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
-#ifdef __AST_DEBUG_MALLOC
- __ast_mm_init();
-#endif
+#if defined(__AST_DEBUG_MALLOC)
+ __ast_mm_init_phase_2();
+#endif /* defined(__AST_DEBUG_MALLOC) */
ast_lastreloadtime = ast_startuptime = ast_tvnow();
+ ast_cli_register_multiple(cli_asterisk_shutdown, ARRAY_LEN(cli_asterisk_shutdown));
ast_cli_register_multiple(cli_asterisk, ARRAY_LEN(cli_asterisk));
+ ast_register_atexit(main_atexit);
run_startup_commands();
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/astmm.c
^
|
@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 1999 - 2006, Digium, Inc.
+ * Copyright (C) 1999 - 2012, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
@@ -21,6 +21,7 @@
* \brief Memory Management
*
* \author Mark Spencer <markster@digium.com>
+ * \author Richard Mudgett <rmudgett@digium.com>
*/
/*** MODULEINFO
@@ -29,9 +30,9 @@
#include "asterisk.h"
-#ifdef __AST_DEBUG_MALLOC
+#if defined(__AST_DEBUG_MALLOC)
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 372655 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 377398 $")
#include "asterisk/paths.h" /* use ast_config_AST_LOG_DIR */
#include <stddef.h>
@@ -42,7 +43,12 @@
#include "asterisk/strings.h"
#include "asterisk/unaligned.h"
-#define SOME_PRIME 563
+/*!
+ * The larger the number the faster memory can be freed.
+ * However, more memory then is used for the regions[] hash
+ * table.
+ */
+#define SOME_PRIME 1567
enum func_type {
FUNC_CALLOC = 1,
@@ -64,36 +70,79 @@
#undef vasprintf
#undef asprintf
-#define FENCE_MAGIC 0xdeadbeef
+#define FENCE_MAGIC 0xdeadbeef /*!< Allocated memory high/low fence overwrite check. */
+#define FREED_MAGIC 0xdeaddead /*!< Freed memory wipe filler. */
+#define MALLOC_FILLER 0x55 /*!< Malloced memory filler. Must not be zero. */
static FILE *mmlog;
-/* NOTE: Be EXTREMELY careful with modifying this structure; the total size of this structure
- must result in 'automatic' alignment so that the 'fence' field lands exactly at the end of
- the structure in memory (and thus immediately before the allocated region the fence is
- supposed to be used to monitor). In other words, we cannot allow the compiler to insert
- any padding between this structure and anything following it, so add up the sizes of all the
- fields and compare to sizeof(struct ast_region)... if they don't match, then the compiler
- is padding the structure and either the fields need to be rearranged to eliminate internal
- padding, or a dummy field will need to be inserted before the 'fence' field to push it to
- the end of the actual space it will consume. Note that this must be checked for both 32-bit
- and 64-bit platforms, as the sizes of pointers and 'size_t' differ on these platforms.
-*/
-
-static struct ast_region {
- struct ast_region *next;
+struct ast_region {
+ AST_LIST_ENTRY(ast_region) node;
size_t len;
- char file[64];
- char func[40];
+ unsigned int cache; /* region was allocated as part of a cache pool */
unsigned int lineno;
enum func_type which;
- unsigned int cache; /* region was allocated as part of a cache pool */
+ char file[64];
+ char func[40];
+
+ /*!
+ * \brief Lower guard fence.
+ *
+ * \note Must be right before data[].
+ *
+ * \note Padding between fence and data[] is irrelevent because
+ * data[] is used to fill in the lower fence check value and not
+ * the fence member. The fence member is to ensure that there
+ * is space reserved for the fence check value.
+ */
unsigned int fence;
- unsigned char data[0];
-} *regions[SOME_PRIME];
+ /*!
+ * \brief Location of the requested malloc block to return.
+ *
+ * \note Must have the same alignment that malloc returns.
+ * i.e., It is suitably aligned for any kind of varible.
+ */
+ unsigned char data[0] __attribute__((aligned));
+};
+
+/*! Hash table of lists of active allocated memory regions. */
+static struct ast_region *regions[SOME_PRIME];
+
+/*! Number of freed regions to keep around to delay actually freeing them. */
+#define FREED_MAX_COUNT 1500
-#define HASH(a) \
- (((unsigned long)(a)) % SOME_PRIME)
+/*! Maximum size of a minnow block */
+#define MINNOWS_MAX_SIZE 50
+
+struct ast_freed_regions {
+ /*! Memory regions that have been freed. */
+ struct ast_region *regions[FREED_MAX_COUNT];
+ /*! Next index into freed regions[] to use. */
+ int index;
+};
+
+/*! Large memory blocks that have been freed. */
+static struct ast_freed_regions whales;
+/*! Small memory blocks that have been freed. */
+static struct ast_freed_regions minnows;
+
+enum summary_opts {
+ /*! No summary at exit. */
+ SUMMARY_OFF,
+ /*! Bit set if summary by line at exit. */
+ SUMMARY_BY_LINE = (1 << 0),
+ /*! Bit set if summary by function at exit. */
+ SUMMARY_BY_FUNC = (1 << 1),
+ /*! Bit set if summary by file at exit. */
+ SUMMARY_BY_FILE = (1 << 2),
+};
+
+/*! Summary options of unfreed regions at exit. */
+static enum summary_opts atexit_summary;
+/*! Nonzero if the unfreed regions are listed at exit. */
+static int atexit_list;
+
+#define HASH(a) (((unsigned long)(a)) % ARRAY_LEN(regions))
/*! Tracking this mutex will cause infinite recursion, as the mutex tracking
* code allocates memory */
@@ -108,153 +157,398 @@
} \
} while (0)
-static inline void *__ast_alloc_region(size_t size, const enum func_type which, const char *file, int lineno, const char *func, unsigned int cache)
+/*!
+ * \internal
+ *
+ * \note If DO_CRASH is not defined then the function returns.
+ *
+ * \return Nothing
+ */
+static void my_do_crash(void)
+{
+ /*
+ * Give the logger a chance to get the message out, just in case
+ * we abort(), or Asterisk crashes due to whatever problem just
+ * happened.
+ */
+ usleep(1);
+ ast_do_crash();
+}
+
+static void *__ast_alloc_region(size_t size, const enum func_type which, const char *file, int lineno, const char *func, unsigned int cache)
{
struct ast_region *reg;
- void *ptr = NULL;
unsigned int *fence;
int hash;
if (!(reg = malloc(size + sizeof(*reg) + sizeof(*fence)))) {
- astmm_log("Memory Allocation Failure - '%d' bytes in function %s "
- "at line %d of %s\n", (int) size, func, lineno, file);
+ astmm_log("Memory Allocation Failure - '%d' bytes at %s %s() line %d\n",
+ (int) size, file, func, lineno);
return NULL;
}
- ast_copy_string(reg->file, file, sizeof(reg->file));
- ast_copy_string(reg->func, func, sizeof(reg->func));
- reg->lineno = lineno;
reg->len = size;
- reg->which = which;
reg->cache = cache;
- ptr = reg->data;
- hash = HASH(ptr);
- reg->fence = FENCE_MAGIC;
- fence = (ptr + reg->len);
+ reg->lineno = lineno;
+ reg->which = which;
+ ast_copy_string(reg->file, file, sizeof(reg->file));
+ ast_copy_string(reg->func, func, sizeof(reg->func));
+
+ /*
+ * Init lower fence.
+ *
+ * We use the bytes just preceeding reg->data and not reg->fence
+ * because there is likely to be padding between reg->fence and
+ * reg->data for reg->data alignment.
+ */
+ fence = (unsigned int *) (reg->data - sizeof(*fence));
+ *fence = FENCE_MAGIC;
+
+ /* Init higher fence. */
+ fence = (unsigned int *) (reg->data + reg->len);
put_unaligned_uint32(fence, FENCE_MAGIC);
+ hash = HASH(reg->data);
ast_mutex_lock(®lock);
- reg->next = regions[hash];
+ AST_LIST_NEXT(reg, node) = regions[hash];
regions[hash] = reg;
ast_mutex_unlock(®lock);
- return ptr;
+ return reg->data;
}
-static inline size_t __ast_sizeof_region(void *ptr)
+/*!
+ * \internal
+ * \brief Wipe the region payload data with a known value.
+ *
+ * \param reg Region block to be wiped.
+ *
+ * \return Nothing
+ */
+static void region_data_wipe(struct ast_region *reg)
{
- int hash = HASH(ptr);
- struct ast_region *reg;
- size_t len = 0;
-
- ast_mutex_lock(®lock);
- for (reg = regions[hash]; reg; reg = reg->next) {
- if (reg->data == ptr) {
- len = reg->len;
+ void *end;
+ unsigned int *pos;
+
+ /*
+ * Wipe the lower fence, the payload, and whatever amount of the
+ * higher fence that falls into alignment with the payload.
+ */
+ end = reg->data + reg->len;
+ for (pos = ®->fence; (void *) pos <= end; ++pos) {
+ *pos = FREED_MAGIC;
+ }
+}
+
+/*!
+ * \internal
+ * \brief Check the region payload data for memory corruption.
+ *
+ * \param reg Region block to be checked.
+ *
+ * \return Nothing
+ */
+static void region_data_check(struct ast_region *reg)
+{
+ void *end;
+ unsigned int *pos;
+
+ /*
+ * Check the lower fence, the payload, and whatever amount of
+ * the higher fence that falls into alignment with the payload.
+ */
+ end = reg->data + reg->len;
+ for (pos = ®->fence; (void *) pos <= end; ++pos) {
+ if (*pos != FREED_MAGIC) {
+ astmm_log("WARNING: Memory corrupted after free of %p allocated at %s %s() line %d\n",
+ reg->data, reg->file, reg->func, reg->lineno);
+ my_do_crash();
break;
}
}
+}
+
+/*!
+ * \internal
+ * \brief Flush the circular array of freed regions.
+ *
+ * \param freed Already freed region blocks storage.
+ *
+ * \return Nothing
+ */
+static void freed_regions_flush(struct ast_freed_regions *freed)
+{
+ int idx;
+ struct ast_region *old;
+
+ ast_mutex_lock(®lock);
+ for (idx = 0; idx < ARRAY_LEN(freed->regions); ++idx) {
+ old = freed->regions[idx];
+ freed->regions[idx] = NULL;
+ if (old) {
+ region_data_check(old);
+ free(old);
+ }
+ }
+ freed->index = 0;
+ ast_mutex_unlock(®lock);
+}
+
+/*!
+ * \internal
+ * \brief Delay freeing a region block.
+ *
+ * \param freed Already freed region blocks storage.
+ * \param reg Region block to be freed.
+ *
+ * \return Nothing
+ */
+static void region_free(struct ast_freed_regions *freed, struct ast_region *reg)
+{
+ struct ast_region *old;
+
+ region_data_wipe(reg);
+
+ ast_mutex_lock(®lock);
+ old = freed->regions[freed->index];
+ freed->regions[freed->index] = reg;
+
+ ++freed->index;
+ if (ARRAY_LEN(freed->regions) <= freed->index) {
+ freed->index = 0;
+ }
ast_mutex_unlock(®lock);
- return len;
+ if (old) {
+ region_data_check(old);
+ free(old);
+ }
}
-static void __ast_free_region(void *ptr, const char *file, int lineno, const char *func)
+/*!
+ * \internal
+ * \brief Remove a region from the active regions.
+ *
+ * \param ptr Region payload data pointer.
+ *
+ * \retval region on success.
+ * \retval NULL if not found.
+ */
+static struct ast_region *region_remove(void *ptr)
{
int hash;
- struct ast_region *reg, *prev = NULL;
- unsigned int *fence;
-
- if (!ptr)
- return;
+ struct ast_region *reg;
+ struct ast_region *prev = NULL;
hash = HASH(ptr);
ast_mutex_lock(®lock);
- for (reg = regions[hash]; reg; reg = reg->next) {
+ for (reg = regions[hash]; reg; reg = AST_LIST_NEXT(reg, node)) {
if (reg->data == ptr) {
- if (prev)
- prev->next = reg->next;
- else
- regions[hash] = reg->next;
+ if (prev) {
+ AST_LIST_NEXT(prev, node) = AST_LIST_NEXT(reg, node);
+ } else {
+ regions[hash] = AST_LIST_NEXT(reg, node);
+ }
break;
}
prev = reg;
}
ast_mutex_unlock(®lock);
+ return reg;
+}
+
+/*!
+ * \internal
+ * \brief Check the fences of a region.
+ *
+ * \param reg Region block to check.
+ *
+ * \return Nothing
+ */
+static void region_check_fences(struct ast_region *reg)
+{
+ unsigned int *fence;
+
+ /*
+ * We use the bytes just preceeding reg->data and not reg->fence
+ * because there is likely to be padding between reg->fence and
+ * reg->data for reg->data alignment.
+ */
+ fence = (unsigned int *) (reg->data - sizeof(*fence));
+ if (*fence != FENCE_MAGIC) {
+ astmm_log("WARNING: Low fence violation of %p allocated at %s %s() line %d\n",
+ reg->data, reg->file, reg->func, reg->lineno);
+ my_do_crash();
+ }
+ fence = (unsigned int *) (reg->data + reg->len);
+ if (get_unaligned_uint32(fence) != FENCE_MAGIC) {
+ astmm_log("WARNING: High fence violation of %p allocated at %s %s() line %d\n",
+ reg->data, reg->file, reg->func, reg->lineno);
+ my_do_crash();
+ }
+}
+
+/*!
+ * \internal
+ * \brief Check the fences of all regions currently allocated.
+ *
+ * \return Nothing
+ */
+static void regions_check_all_fences(void)
+{
+ int idx;
+ struct ast_region *reg;
+
+ ast_mutex_lock(®lock);
+ for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
+ for (reg = regions[idx]; reg; reg = AST_LIST_NEXT(reg, node)) {
+ region_check_fences(reg);
+ }
+ }
+ ast_mutex_unlock(®lock);
+}
+
+static void __ast_free_region(void *ptr, const char *file, int lineno, const char *func)
+{
+ struct ast_region *reg;
+
+ if (!ptr) {
+ return;
+ }
+
+ reg = region_remove(ptr);
if (reg) {
- fence = (unsigned int *)(reg->data + reg->len);
- if (reg->fence != FENCE_MAGIC) {
- astmm_log("WARNING: Low fence violation at %p, in %s of %s, "
- "line %d\n", reg->data, reg->func, reg->file, reg->lineno);
- }
- if (get_unaligned_uint32(fence) != FENCE_MAGIC) {
- astmm_log("WARNING: High fence violation at %p, in %s of %s, "
- "line %d\n", reg->data, reg->func, reg->file, reg->lineno);
+ region_check_fences(reg);
+
+ if (reg->len <= MINNOWS_MAX_SIZE) {
+ region_free(&minnows, reg);
+ } else {
+ region_free(&whales, reg);
}
- free(reg);
} else {
- astmm_log("WARNING: Freeing unused memory at %p, in %s of %s, line %d\n",
- ptr, func, file, lineno);
+ /*
+ * This memory region is not registered. It could be because of
+ * a double free or the memory block was not allocated by the
+ * malloc debug code.
+ */
+ astmm_log("WARNING: Freeing unregistered memory %p by %s %s() line %d\n",
+ ptr, file, func, lineno);
+ my_do_crash();
}
}
-void *__ast_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
+void *__ast_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
{
void *ptr;
- if ((ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 0)))
+ ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 0);
+ if (ptr) {
memset(ptr, 0, size * nmemb);
+ }
return ptr;
}
-void *__ast_calloc_cache(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
+void *__ast_calloc_cache(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
{
void *ptr;
- if ((ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 1)))
+ ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 1);
+ if (ptr) {
memset(ptr, 0, size * nmemb);
+ }
return ptr;
}
-void *__ast_malloc(size_t size, const char *file, int lineno, const char *func)
+void *__ast_malloc(size_t size, const char *file, int lineno, const char *func)
{
- return __ast_alloc_region(size, FUNC_MALLOC, file, lineno, func, 0);
+ void *ptr;
+
+ ptr = __ast_alloc_region(size, FUNC_MALLOC, file, lineno, func, 0);
+ if (ptr) {
+ /* Make sure that the malloced memory is not zero. */
+ memset(ptr, MALLOC_FILLER, size);
+ }
+
+ return ptr;
}
-void __ast_free(void *ptr, const char *file, int lineno, const char *func)
+void __ast_free(void *ptr, const char *file, int lineno, const char *func)
{
__ast_free_region(ptr, file, lineno, func);
}
-void *__ast_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func)
+/*!
+ * \note reglock must be locked before calling.
+ */
+static struct ast_region *region_find(void *ptr)
{
- void *tmp;
- size_t len = 0;
+ int hash;
+ struct ast_region *reg;
- if (ptr && !(len = __ast_sizeof_region(ptr))) {
- astmm_log("WARNING: Realloc of unalloced memory at %p, in %s of %s, "
- "line %d\n", ptr, func, file, lineno);
- return NULL;
+ hash = HASH(ptr);
+ for (reg = regions[hash]; reg; reg = AST_LIST_NEXT(reg, node)) {
+ if (reg->data == ptr) {
+ break;
+ }
}
- if (!(tmp = __ast_alloc_region(size, FUNC_REALLOC, file, lineno, func, 0)))
- return NULL;
+ return reg;
+}
+
+void *__ast_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func)
+{
+ size_t len;
+ struct ast_region *found;
+ void *new_mem;
- if (len > size)
- len = size;
if (ptr) {
- memcpy(tmp, ptr, len);
+ ast_mutex_lock(®lock);
+ found = region_find(ptr);
+ if (!found) {
+ ast_mutex_unlock(®lock);
+ astmm_log("WARNING: Realloc of unregistered memory %p by %s %s() line %d\n",
+ ptr, file, func, lineno);
+ my_do_crash();
+ return NULL;
+ }
+ len = found->len;
+ ast_mutex_unlock(®lock);
+ } else {
+ found = NULL;
+ len = 0;
+ }
+
+ if (!size) {
__ast_free_region(ptr, file, lineno, func);
+ return NULL;
+ }
+
+ new_mem = __ast_alloc_region(size, FUNC_REALLOC, file, lineno, func, 0);
+ if (new_mem) {
+ if (found) {
+ /* Copy the old data to the new malloced memory. */
+ if (size <= len) {
+ memcpy(new_mem, ptr, size);
+ } else {
+ memcpy(new_mem, ptr, len);
+ /* Make sure that the added memory is not zero. */
+ memset(new_mem + len, MALLOC_FILLER, size - len);
+ }
+ __ast_free_region(ptr, file, lineno, func);
+ } else {
+ /* Make sure that the malloced memory is not zero. */
+ memset(new_mem, MALLOC_FILLER, size);
+ }
}
-
- return tmp;
+
+ return new_mem;
}
-char *__ast_strdup(const char *s, const char *file, int lineno, const char *func)
+char *__ast_strdup(const char *s, const char *file, int lineno, const char *func)
{
size_t len;
void *ptr;
@@ -269,7 +563,7 @@
return ptr;
}
-char *__ast_strndup(const char *s, size_t n, const char *file, int lineno, const char *func)
+char *__ast_strndup(const char *s, size_t n, const char *file, int lineno, const char *func)
{
size_t len;
char *ptr;
@@ -308,7 +602,7 @@
return size;
}
-int __ast_vasprintf(char **strp, const char *fmt, va_list ap, const char *file, int lineno, const char *func)
+int __ast_vasprintf(char **strp, const char *fmt, va_list ap, const char *file, int lineno, const char *func)
{
int size;
va_list ap2;
@@ -327,125 +621,277 @@
return size;
}
-static char *handle_memory_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+static char *handle_memory_atexit_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "memory atexit list";
+ e->usage =
+ "Usage: memory atexit list {on|off}\n"
+ " Enable dumping a list of still allocated memory segments at exit.\n";
+ return NULL;
+ case CLI_GENERATE:
+ if (a->pos == 3) {
+ const char * const options[] = { "off", "on", NULL };
+
+ return ast_cli_complete(a->word, options, a->n);
+ }
+ return NULL;
+ }
+
+ if (a->argc != 4) {
+ return CLI_SHOWUSAGE;
+ }
+
+ if (ast_true(a->argv[3])) {
+ atexit_list = 1;
+ } else if (ast_false(a->argv[3])) {
+ atexit_list = 0;
+ } else {
+ return CLI_SHOWUSAGE;
+ }
+
+ ast_cli(a->fd, "The atexit list is: %s\n", atexit_list ? "On" : "Off");
+
+ return CLI_SUCCESS;
+}
+
+static char *handle_memory_atexit_summary(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ char buf[80];
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "memory atexit summary";
+ e->usage =
+ "Usage: memory atexit summary {off|byline|byfunc|byfile}\n"
+ " Summary of still allocated memory segments at exit options.\n"
+ " off - Disable at exit summary.\n"
+ " byline - Enable at exit summary by file line number.\n"
+ " byfunc - Enable at exit summary by function name.\n"
+ " byfile - Enable at exit summary by file.\n"
+ "\n"
+ " Note: byline, byfunc, and byfile are cumulative enables.\n";
+ return NULL;
+ case CLI_GENERATE:
+ if (a->pos == 3) {
+ const char * const options[] = { "off", "byline", "byfunc", "byfile", NULL };
+
+ return ast_cli_complete(a->word, options, a->n);
+ }
+ return NULL;
+ }
+
+ if (a->argc != 4) {
+ return CLI_SHOWUSAGE;
+ }
+
+ if (ast_false(a->argv[3])) {
+ atexit_summary = SUMMARY_OFF;
+ } else if (!strcasecmp(a->argv[3], "byline")) {
+ atexit_summary |= SUMMARY_BY_LINE;
+ } else if (!strcasecmp(a->argv[3], "byfunc")) {
+ atexit_summary |= SUMMARY_BY_FUNC;
+ } else if (!strcasecmp(a->argv[3], "byfile")) {
+ atexit_summary |= SUMMARY_BY_FILE;
+ } else {
+ return CLI_SHOWUSAGE;
+ }
+
+ if (atexit_summary) {
+ buf[0] = '\0';
+ if (atexit_summary & SUMMARY_BY_LINE) {
+ strcat(buf, "byline");
+ }
+ if (atexit_summary & SUMMARY_BY_FUNC) {
+ if (buf[0]) {
+ strcat(buf, " | ");
+ }
+ strcat(buf, "byfunc");
+ }
+ if (atexit_summary & SUMMARY_BY_FILE) {
+ if (buf[0]) {
+ strcat(buf, " | ");
+ }
+ strcat(buf, "byfile");
+ }
+ } else {
+ strcpy(buf, "Off");
+ }
+ ast_cli(a->fd, "The atexit summary is: %s\n", buf);
+
+ return CLI_SUCCESS;
+}
+
+static char *handle_memory_show_allocations(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
const char *fn = NULL;
struct ast_region *reg;
- unsigned int x;
+ unsigned int idx;
unsigned int len = 0;
unsigned int cache_len = 0;
unsigned int count = 0;
- unsigned int *fence;
switch (cmd) {
case CLI_INIT:
e->command = "memory show allocations";
e->usage =
- "Usage: memory show allocations [<file>]\n"
- " Dumps a list of all segments of allocated memory, optionally\n"
- " limited to those from a specific file\n";
+ "Usage: memory show allocations [<file>|anomalies]\n"
+ " Dumps a list of segments of allocated memory.\n"
+ " Defaults to listing all memory allocations.\n"
+ " <file> - Restricts output to memory allocated by the file.\n"
+ " anomalies - Only check for fence violations.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
-
- if (a->argc > 3)
+ if (a->argc == 4) {
fn = a->argv[3];
+ } else if (a->argc != 3) {
+ return CLI_SHOWUSAGE;
+ }
+
+ /* Look for historical misspelled option as well. */
+ if (fn && (!strcasecmp(fn, "anomalies") || !strcasecmp(fn, "anomolies"))) {
+ regions_check_all_fences();
+ ast_cli(a->fd, "Anomaly check complete.\n");
+ return CLI_SUCCESS;
+ }
ast_mutex_lock(®lock);
- for (x = 0; x < SOME_PRIME; x++) {
- for (reg = regions[x]; reg; reg = reg->next) {
- if (!fn || !strcasecmp(fn, reg->file) || !strcasecmp(fn, "anomolies")) {
- fence = (unsigned int *)(reg->data + reg->len);
- if (reg->fence != FENCE_MAGIC) {
- astmm_log("WARNING: Low fence violation at %p, "
- "in %s of %s, line %d\n", reg->data,
- reg->func, reg->file, reg->lineno);
- }
- if (get_unaligned_uint32(fence) != FENCE_MAGIC) {
- astmm_log("WARNING: High fence violation at %p, in %s of %s, "
- "line %d\n", reg->data, reg->func, reg->file, reg->lineno);
- }
+ for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
+ for (reg = regions[idx]; reg; reg = AST_LIST_NEXT(reg, node)) {
+ if (fn && strcasecmp(fn, reg->file)) {
+ continue;
}
- if (!fn || !strcasecmp(fn, reg->file)) {
- ast_cli(a->fd, "%10d bytes allocated%s in %20s at line %5d of %s\n",
- (int) reg->len, reg->cache ? " (cache)" : "",
- reg->func, reg->lineno, reg->file);
- len += reg->len;
- if (reg->cache)
- cache_len += reg->len;
- count++;
+
+ region_check_fences(reg);
+
+ ast_cli(a->fd, "%10u bytes allocated%s by %20s() line %5u of %s\n",
+ (unsigned int) reg->len, reg->cache ? " (cache)" : "",
+ reg->func, reg->lineno, reg->file);
+
+ len += reg->len;
+ if (reg->cache) {
+ cache_len += reg->len;
}
+ ++count;
}
}
ast_mutex_unlock(®lock);
-
- if (cache_len)
- ast_cli(a->fd, "%d bytes allocated (%d in caches) in %d allocations\n", len, cache_len, count);
- else
- ast_cli(a->fd, "%d bytes allocated in %d allocations\n", len, count);
-
+
+ if (cache_len) {
+ ast_cli(a->fd, "%u bytes allocated (%u in caches) in %u allocations\n",
+ len, cache_len, count);
+ } else {
+ ast_cli(a->fd, "%u bytes allocated in %u allocations\n", len, count);
+ }
+
return CLI_SUCCESS;
}
static char *handle_memory_show_summary(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
+#define my_max(a, b) ((a) >= (b) ? (a) : (b))
+
const char *fn = NULL;
- int x;
+ int idx;
+ int cmp;
struct ast_region *reg;
unsigned int len = 0;
unsigned int cache_len = 0;
- int count = 0;
+ unsigned int count = 0;
struct file_summary {
- char fn[80];
- int len;
- int cache_len;
- int count;
struct file_summary *next;
- } *list = NULL, *cur;
-
+ unsigned int len;
+ unsigned int cache_len;
+ unsigned int count;
+ unsigned int lineno;
+ char name[my_max(sizeof(reg->file), sizeof(reg->func))];
+ } *list = NULL, *cur, **prev;
+
switch (cmd) {
case CLI_INIT:
e->command = "memory show summary";
e->usage =
"Usage: memory show summary [<file>]\n"
" Summarizes heap memory allocations by file, or optionally\n"
- "by function, if a file is specified\n";
+ " by line, if a file is specified.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
- if (a->argc > 3)
+ if (a->argc == 4) {
fn = a->argv[3];
+ } else if (a->argc != 3) {
+ return CLI_SHOWUSAGE;
+ }
ast_mutex_lock(®lock);
- for (x = 0; x < SOME_PRIME; x++) {
- for (reg = regions[x]; reg; reg = reg->next) {
- if (fn && strcasecmp(fn, reg->file))
- continue;
+ for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
+ for (reg = regions[idx]; reg; reg = AST_LIST_NEXT(reg, node)) {
+ if (fn) {
+ if (strcasecmp(fn, reg->file)) {
+ continue;
+ }
- for (cur = list; cur; cur = cur->next) {
- if ((!fn && !strcmp(cur->fn, reg->file)) || (fn && !strcmp(cur->fn, reg->func)))
+ /* Sort list by func/lineno. Find existing or place to insert. */
+ for (prev = &list; (cur = *prev); prev = &cur->next) {
+ cmp = strcmp(cur->name, reg->func);
+ if (cmp < 0) {
+ continue;
+ }
+ if (cmp > 0) {
+ /* Insert before current */
+ cur = NULL;
+ break;
+ }
+ cmp = cur->lineno - reg->lineno;
+ if (cmp < 0) {
+ continue;
+ }
+ if (cmp > 0) {
+ /* Insert before current */
+ cur = NULL;
+ }
break;
+ }
+ } else {
+ /* Sort list by filename. Find existing or place to insert. */
+ for (prev = &list; (cur = *prev); prev = &cur->next) {
+ cmp = strcmp(cur->name, reg->file);
+ if (cmp < 0) {
+ continue;
+ }
+ if (cmp > 0) {
+ /* Insert before current */
+ cur = NULL;
+ }
+ break;
+ }
}
+
if (!cur) {
cur = ast_alloca(sizeof(*cur));
memset(cur, 0, sizeof(*cur));
- ast_copy_string(cur->fn, fn ? reg->func : reg->file, sizeof(cur->fn));
- cur->next = list;
- list = cur;
+ cur->lineno = reg->lineno;
+ ast_copy_string(cur->name, fn ? reg->func : reg->file, sizeof(cur->name));
+
+ cur->next = *prev;
+ *prev = cur;
}
cur->len += reg->len;
- if (reg->cache)
+ if (reg->cache) {
cur->cache_len += reg->len;
- cur->count++;
+ }
+ ++cur->count;
}
}
ast_mutex_unlock(®lock);
-
+
/* Dump the whole list */
for (cur = list; cur; cur = cur->next) {
len += cur->len;
@@ -453,55 +899,512 @@
count += cur->count;
if (cur->cache_len) {
if (fn) {
- ast_cli(a->fd, "%10d bytes (%10d cache) in %d allocations in function '%s' of '%s'\n",
- cur->len, cur->cache_len, cur->count, cur->fn, fn);
+ ast_cli(a->fd, "%10u bytes (%10u cache) in %10u allocations by %20s() line %5u of %s\n",
+ cur->len, cur->cache_len, cur->count, cur->name, cur->lineno, fn);
} else {
- ast_cli(a->fd, "%10d bytes (%10d cache) in %d allocations in file '%s'\n",
- cur->len, cur->cache_len, cur->count, cur->fn);
+ ast_cli(a->fd, "%10u bytes (%10u cache) in %10u allocations in file %s\n",
+ cur->len, cur->cache_len, cur->count, cur->name);
}
} else {
if (fn) {
- ast_cli(a->fd, "%10d bytes in %d allocations in function '%s' of '%s'\n",
- cur->len, cur->count, cur->fn, fn);
+ ast_cli(a->fd, "%10u bytes in %10u allocations by %20s() line %5u of %s\n",
+ cur->len, cur->count, cur->name, cur->lineno, fn);
} else {
- ast_cli(a->fd, "%10d bytes in %d allocations in file '%s'\n",
- cur->len, cur->count, cur->fn);
+ ast_cli(a->fd, "%10u bytes in %10u allocations in file %s\n",
+ cur->len, cur->count, cur->name);
}
}
}
- if (cache_len)
- ast_cli(a->fd, "%d bytes allocated (%d in caches) in %d allocations\n", len, cache_len, count);
- else
- ast_cli(a->fd, "%d bytes allocated in %d allocations\n", len, count);
+ if (cache_len) {
+ ast_cli(a->fd, "%u bytes allocated (%u in caches) in %u allocations\n",
+ len, cache_len, count);
+ } else {
+ ast_cli(a->fd, "%u bytes allocated in %u allocations\n", len, count);
+ }
return CLI_SUCCESS;
}
static struct ast_cli_entry cli_memory[] = {
- AST_CLI_DEFINE(handle_memory_show, "Display outstanding memory allocations"),
+ AST_CLI_DEFINE(handle_memory_atexit_list, "Enable memory allocations not freed at exit list."),
+ AST_CLI_DEFINE(handle_memory_atexit_summary, "Enable memory allocations not freed at exit summary."),
+ AST_CLI_DEFINE(handle_memory_show_allocations, "Display outstanding memory allocations"),
AST_CLI_DEFINE(handle_memory_show_summary, "Summarize outstanding memory allocations"),
};
-void __ast_mm_init(void)
+AST_LIST_HEAD_NOLOCK(region_list, ast_region);
+
+/*!
+ * \internal
+ * \brief Convert the allocated regions hash table to a list.
+ *
+ * \param list Fill list with the allocated regions.
+ *
+ * \details
+ * Take all allocated regions from the regions[] and put them
+ * into the list.
+ *
+ * \note reglock must be locked before calling.
+ *
+ * \note This function is destructive to the regions[] lists.
+ *
+ * \return Length of list created.
+ */
+static size_t mm_atexit_hash_list(struct region_list *list)
{
- char filename[PATH_MAX];
- size_t pad = sizeof(struct ast_region) - offsetof(struct ast_region, data);
+ struct ast_region *reg;
+ size_t total_length;
+ int idx;
+
+ total_length = 0;
+ for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
+ while ((reg = regions[idx])) {
+ regions[idx] = AST_LIST_NEXT(reg, node);
+ AST_LIST_NEXT(reg, node) = NULL;
+ AST_LIST_INSERT_HEAD(list, reg, node);
+ ++total_length;
+ }
+ }
+ return total_length;
+}
+
+/*!
+ * \internal
+ * \brief Put the regions list into the allocated regions hash table.
+ *
+ * \param list List to put into the allocated regions hash table.
+ *
+ * \note reglock must be locked before calling.
+ *
+ * \return Nothing
+ */
+static void mm_atexit_hash_restore(struct region_list *list)
+{
+ struct ast_region *reg;
+ int hash;
+
+ while ((reg = AST_LIST_REMOVE_HEAD(list, node))) {
+ hash = HASH(reg->data);
+ AST_LIST_NEXT(reg, node) = regions[hash];
+ regions[hash] = reg;
+ }
+}
+
+/*!
+ * \internal
+ * \brief Sort regions comparision.
+ *
+ * \param left Region to compare.
+ * \param right Region to compare.
+ *
+ * \retval <0 if left < right
+ * \retval =0 if left == right
+ * \retval >0 if left > right
+ */
+static int mm_atexit_cmp(struct ast_region *left, struct ast_region *right)
+{
+ int cmp;
+ ptrdiff_t cmp_ptr;
+ ssize_t cmp_size;
+
+ /* Sort by filename. */
+ cmp = strcmp(left->file, right->file);
+ if (cmp) {
+ return cmp;
+ }
+
+ /* Sort by line number. */
+ cmp = left->lineno - right->lineno;
+ if (cmp) {
+ return cmp;
+ }
+
+ /* Sort by allocated size. */
+ cmp_size = left->len - right->len;
+ if (cmp_size) {
+ if (cmp_size < 0) {
+ return -1;
+ }
+ return 1;
+ }
+
+ /* Sort by allocated pointers just because. */
+ cmp_ptr = left->data - right->data;
+ if (cmp_ptr) {
+ if (cmp_ptr < 0) {
+ return -1;
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+/*!
+ * \internal
+ * \brief Merge the given sorted sublists into sorted order onto the end of the list.
+ *
+ * \param list Merge sublists onto this list.
+ * \param sub1 First sublist to merge.
+ * \param sub2 Second sublist to merge.
+ *
+ * \return Nothing
+ */
+static void mm_atexit_list_merge(struct region_list *list, struct region_list *sub1, struct region_list *sub2)
+{
+ struct ast_region *reg;
+
+ for (;;) {
+ if (AST_LIST_EMPTY(sub1)) {
+ /* The remaining sublist goes onto the list. */
+ AST_LIST_APPEND_LIST(list, sub2, node);
+ break;
+ }
+ if (AST_LIST_EMPTY(sub2)) {
+ /* The remaining sublist goes onto the list. */
+ AST_LIST_APPEND_LIST(list, sub1, node);
+ break;
+ }
+
+ if (mm_atexit_cmp(AST_LIST_FIRST(sub1), AST_LIST_FIRST(sub2)) <= 0) {
+ reg = AST_LIST_REMOVE_HEAD(sub1, node);
+ } else {
+ reg = AST_LIST_REMOVE_HEAD(sub2, node);
+ }
+ AST_LIST_INSERT_TAIL(list, reg, node);
+ }
+}
+
+/*!
+ * \internal
+ * \brief Take sublists off of the given list.
+ *
+ * \param list Source list to remove sublists from the beginning of list.
+ * \param sub Array of sublists to fill. (Lists are empty on entry.)
+ * \param num_lists Number of lists to remove from the source list.
+ * \param size Size of the sublists to remove.
+ * \param remaining Remaining number of elements on the source list.
+ *
+ * \return Nothing
+ */
+static void mm_atexit_list_split(struct region_list *list, struct region_list sub[], size_t num_lists, size_t size, size_t *remaining)
+{
+ int idx;
+
+ for (idx = 0; idx < num_lists; ++idx) {
+ size_t count;
+
+ if (*remaining < size) {
+ /* The remaining source list goes onto the sublist. */
+ AST_LIST_APPEND_LIST(&sub[idx], list, node);
+ *remaining = 0;
+ break;
+ }
+
+ /* Take a sublist off the beginning of the source list. */
+ *remaining -= size;
+ for (count = size; count--;) {
+ struct ast_region *reg;
+
+ reg = AST_LIST_REMOVE_HEAD(list, node);
+ AST_LIST_INSERT_TAIL(&sub[idx], reg, node);
+ }
+ }
+}
+
+/*!
+ * \internal
+ * \brief Sort the regions list using mergesort.
+ *
+ * \param list Allocated regions list to sort.
+ * \param length Length of the list.
+ *
+ * \return Nothing
+ */
+static void mm_atexit_list_sort(struct region_list *list, size_t length)
+{
+ /*! Semi-sorted merged list. */
+ struct region_list merged = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
+ /*! Sublists to merge. (Can only merge two sublists at this time.) */
+ struct region_list sub[2] = {
+ AST_LIST_HEAD_NOLOCK_INIT_VALUE,
+ AST_LIST_HEAD_NOLOCK_INIT_VALUE
+ };
+ /*! Sublist size. */
+ size_t size = 1;
+ /*! Remaining elements in the list. */
+ size_t remaining;
+ /*! Number of sublist merge passes to process the list. */
+ int passes;
+
+ for (;;) {
+ remaining = length;
+
+ passes = 0;
+ while (!AST_LIST_EMPTY(list)) {
+ mm_atexit_list_split(list, sub, ARRAY_LEN(sub), size, &remaining);
+ mm_atexit_list_merge(&merged, &sub[0], &sub[1]);
+ ++passes;
+ }
+ AST_LIST_APPEND_LIST(list, &merged, node);
+ if (passes <= 1) {
+ /* The list is now sorted. */
+ break;
+ }
+
+ /* Double the sublist size to remove for next round. */
+ size <<= 1;
+ }
+}
+
+/*!
+ * \internal
+ * \brief List all regions currently allocated.
+ *
+ * \param alloced regions list.
+ *
+ * \return Nothing
+ */
+static void mm_atexit_regions_list(struct region_list *alloced)
+{
+ struct ast_region *reg;
+
+ AST_LIST_TRAVERSE(alloced, reg, node) {
+ astmm_log("%s %s() line %u: %u bytes%s at %p\n",
+ reg->file, reg->func, reg->lineno,
+ (unsigned int) reg->len, reg->cache ? " (cache)" : "", reg->data);
+ }
+}
+
+/*!
+ * \internal
+ * \brief Summarize all regions currently allocated.
+ *
+ * \param alloced Sorted regions list.
+ *
+ * \return Nothing
+ */
+static void mm_atexit_regions_summary(struct region_list *alloced)
+{
+ struct ast_region *reg;
+ struct ast_region *next;
+ struct {
+ unsigned int count;
+ unsigned int len;
+ unsigned int cache_len;
+ } by_line, by_func, by_file, total;
+
+ by_line.count = 0;
+ by_line.len = 0;
+ by_line.cache_len = 0;
+
+ by_func.count = 0;
+ by_func.len = 0;
+ by_func.cache_len = 0;
+
+ by_file.count = 0;
+ by_file.len = 0;
+ by_file.cache_len = 0;
+
+ total.count = 0;
+ total.len = 0;
+ total.cache_len = 0;
+
+ AST_LIST_TRAVERSE(alloced, reg, node) {
+ next = AST_LIST_NEXT(reg, node);
+
+ ++by_line.count;
+ by_line.len += reg->len;
+ if (reg->cache) {
+ by_line.cache_len += reg->len;
+ }
+ if (next && !strcmp(reg->file, next->file) && reg->lineno == next->lineno) {
+ continue;
+ }
+ if (atexit_summary & SUMMARY_BY_LINE) {
+ if (by_line.cache_len) {
+ astmm_log("%10u bytes (%u in caches) in %u allocations. %s %s() line %u\n",
+ by_line.len, by_line.cache_len, by_line.count, reg->file, reg->func, reg->lineno);
+ } else {
+ astmm_log("%10u bytes in %5u allocations. %s %s() line %u\n",
+ by_line.len, by_line.count, reg->file, reg->func, reg->lineno);
+ }
+ }
+
+ by_func.count += by_line.count;
+ by_func.len += by_line.len;
+ by_func.cache_len += by_line.cache_len;
+ by_line.count = 0;
+ by_line.len = 0;
+ by_line.cache_len = 0;
+ if (next && !strcmp(reg->file, next->file) && !strcmp(reg->func, next->func)) {
+ continue;
+ }
+ if (atexit_summary & SUMMARY_BY_FUNC) {
+ if (by_func.cache_len) {
+ astmm_log("%10u bytes (%u in caches) in %u allocations. %s %s()\n",
+ by_func.len, by_func.cache_len, by_func.count, reg->file, reg->func);
+ } else {
+ astmm_log("%10u bytes in %5u allocations. %s %s()\n",
+ by_func.len, by_func.count, reg->file, reg->func);
+ }
+ }
+
+ by_file.count += by_func.count;
+ by_file.len += by_func.len;
+ by_file.cache_len += by_func.cache_len;
+ by_func.count = 0;
+ by_func.len = 0;
+ by_func.cache_len = 0;
+ if (next && !strcmp(reg->file, next->file)) {
+ continue;
+ }
+ if (atexit_summary & SUMMARY_BY_FILE) {
+ if (by_file.cache_len) {
+ astmm_log("%10u bytes (%u in caches) in %u allocations. %s\n",
+ by_file.len, by_file.cache_len, by_file.count, reg->file);
+ } else {
+ astmm_log("%10u bytes in %5u allocations. %s\n",
+ by_file.len, by_file.count, reg->file);
+ }
+ }
- if (pad) {
- ast_log(LOG_ERROR, "struct ast_region has %d bytes of padding! This must be eliminated for low-fence checking to work properly!\n", (int) pad);
+ total.count += by_file.count;
+ total.len += by_file.len;
+ total.cache_len += by_file.cache_len;
+ by_file.count = 0;
+ by_file.len = 0;
+ by_file.cache_len = 0;
}
+ if (total.cache_len) {
+ astmm_log("%u bytes (%u in caches) in %u allocations.\n",
+ total.len, total.cache_len, total.count);
+ } else {
+ astmm_log("%u bytes in %u allocations.\n", total.len, total.count);
+ }
+}
+
+/*!
+ * \internal
+ * \brief Dump the memory allocations atexit.
+ *
+ * \note reglock must be locked before calling.
+ *
+ * \return Nothing
+ */
+static void mm_atexit_dump(void)
+{
+ struct region_list alloced_atexit = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
+ size_t length;
+
+ length = mm_atexit_hash_list(&alloced_atexit);
+ if (!length) {
+ /* Wow! This is amazing! */
+ astmm_log("Exiting with all memory freed.\n");
+ return;
+ }
+
+ mm_atexit_list_sort(&alloced_atexit, length);
+
+ astmm_log("Exiting with the following memory not freed:\n");
+ if (atexit_list) {
+ mm_atexit_regions_list(&alloced_atexit);
+ }
+ if (atexit_summary) {
+ mm_atexit_regions_summary(&alloced_atexit);
+ }
+
+ /*
+ * Put the alloced list back into regions[].
+ *
+ * We have do do this because we can get called before all other
+ * threads have terminated.
+ */
+ mm_atexit_hash_restore(&alloced_atexit);
+}
+
+/*!
+ * \internal
+ * \return Nothing
+ */
+static void mm_atexit_final(void)
+{
+ FILE *log;
+
+ /* Only wait if we want atexit allocation dumps. */
+ if (atexit_list || atexit_summary) {
+ fprintf(stderr, "Waiting 10 seconds to let other threads die.\n");
+ sleep(10);
+ }
+
+ regions_check_all_fences();
+
+ /* Flush all delayed memory free circular arrays. */
+ freed_regions_flush(&whales);
+ freed_regions_flush(&minnows);
+
+ /* Peform atexit allocation dumps. */
+ if (atexit_list || atexit_summary) {
+ ast_mutex_lock(®lock);
+ mm_atexit_dump();
+ ast_mutex_unlock(®lock);
+ }
+
+ /* Close the log file. */
+ log = mmlog;
+ mmlog = NULL;
+ if (log) {
+ fclose(log);
+ }
+}
+
+/*!
+ * \brief Initialize malloc debug phase 1.
+ *
+ * \note Must be called first thing in main().
+ *
+ * \return Nothing
+ */
+void __ast_mm_init_phase_1(void)
+{
+ atexit(mm_atexit_final);
+}
+
+/*!
+ * \internal
+ * \return Nothing
+ */
+static void mm_atexit_ast(void)
+{
+ ast_cli_unregister_multiple(cli_memory, ARRAY_LEN(cli_memory));
+}
+
+/*!
+ * \brief Initialize malloc debug phase 2.
+ *
+ * \return Nothing
+ */
+void __ast_mm_init_phase_2(void)
+{
+ char filename[PATH_MAX];
+
ast_cli_register_multiple(cli_memory, ARRAY_LEN(cli_memory));
-
+
snprintf(filename, sizeof(filename), "%s/mmlog", ast_config_AST_LOG_DIR);
-
+
ast_verb(1, "Asterisk Malloc Debugger Started (see %s))\n", filename);
-
- if ((mmlog = fopen(filename, "a+"))) {
- fprintf(mmlog, "%ld - New session\n", (long)time(NULL));
+
+ mmlog = fopen(filename, "a+");
+ if (mmlog) {
+ fprintf(mmlog, "%ld - New session\n", (long) time(NULL));
fflush(mmlog);
+ } else {
+ ast_log(LOG_ERROR, "Could not open malloc debug log file: %s\n", filename);
}
+
+ ast_register_atexit(mm_atexit_ast);
}
-#endif
+#endif /* defined(__AST_DEBUG_MALLOC) */
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/ccss.c
^
|
@@ -27,7 +27,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 375658 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 377037 $")
#include "asterisk/astobj2.h"
#include "asterisk/strings.h"
@@ -4317,6 +4317,8 @@
ast_cc_monitor_unregister(&generic_monitor_cbs);
ast_unregister_application(cccancel_app);
ast_unregister_application(ccreq_app);
+ ast_logger_unregister_level(CC_LOGGER_LEVEL_NAME);
+ ast_cli_unregister_multiple(cc_cli, ARRAY_LEN(cc_cli));
if (cc_sched_thread) {
cc_sched_thread = ast_sched_thread_destroy(cc_sched_thread);
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/cdr.c
^
|
@@ -37,7 +37,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 375727 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 377069 $")
#include <signal.h>
@@ -1481,7 +1481,7 @@
static struct ast_cli_entry cli_submit = AST_CLI_DEFINE(handle_cli_submit, "Posts all pending batched CDR data");
static struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the CDR status");
-static int do_reload(int reload)
+static void do_reload(int reload)
{
struct ast_config *config;
const char *enabled_value;
@@ -1497,11 +1497,10 @@
int cfg_time;
int was_enabled;
int was_batchmode;
- int res=0;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
if ((config = ast_config_load2("cdr.conf", "cdr", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
- return 0;
+ return;
}
ast_mutex_lock(&cdr_batch_lock);
@@ -1519,7 +1518,7 @@
if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
ast_mutex_unlock(&cdr_batch_lock);
- return 0;
+ return;
}
/* don't run the next scheduled CDR posting while reloading */
@@ -1582,7 +1581,6 @@
} else {
ast_cli_register(&cli_submit);
ast_register_atexit(ast_cdr_engine_term);
- res = 0;
}
/* if this reload disabled the CDR and/or batch mode and there is a background thread,
kill it */
@@ -1595,27 +1593,39 @@
ast_cond_destroy(&cdr_pending_cond);
ast_cli_unregister(&cli_submit);
ast_unregister_atexit(ast_cdr_engine_term);
- res = 0;
/* if leaving batch mode, then post the CDRs in the batch,
and don't reschedule, since we are stopping CDR logging */
if (!batchmode && was_batchmode) {
ast_cdr_engine_term();
}
- } else {
- res = 0;
}
ast_mutex_unlock(&cdr_batch_lock);
ast_config_destroy(config);
manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: CDR\r\nMessage: CDR subsystem reload requested\r\n");
+}
- return res;
+static void cdr_engine_shutdown(void)
+{
+ if (cdr_thread != AST_PTHREADT_NULL) {
+ /* wake up the thread so it will exit */
+ pthread_cancel(cdr_thread);
+ pthread_kill(cdr_thread, SIGURG);
+ pthread_join(cdr_thread, NULL);
+ cdr_thread = AST_PTHREADT_NULL;
+ ast_cond_destroy(&cdr_pending_cond);
+ }
+ ast_cli_unregister(&cli_submit);
+
+ ast_cli_unregister(&cli_status);
+ sched_context_destroy(sched);
+ sched = NULL;
+ ast_free(batch);
+ batch = NULL;
}
int ast_cdr_engine_init(void)
{
- int res;
-
sched = sched_context_create();
if (!sched) {
ast_log(LOG_ERROR, "Unable to create schedule context.\n");
@@ -1623,15 +1633,10 @@
}
ast_cli_register(&cli_status);
+ do_reload(0);
+ ast_register_atexit(cdr_engine_shutdown);
- res = do_reload(0);
- if (res) {
- ast_mutex_lock(&cdr_batch_lock);
- res = init_batch();
- ast_mutex_unlock(&cdr_batch_lock);
- }
-
- return res;
+ return 0;
}
/* \note This actually gets called a couple of times at shutdown. Once, before we start
@@ -1643,7 +1648,8 @@
int ast_cdr_engine_reload(void)
{
- return do_reload(1);
+ do_reload(1);
+ return 0;
}
int ast_cdr_data_add_structure(struct ast_data *tree, struct ast_cdr *cdr, int recur)
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/channel.c
^
|
@@ -29,7 +29,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378341 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#include "asterisk/_private.h"
@@ -71,6 +71,7 @@
#include "asterisk/stringfields.h"
#include "asterisk/global_datastores.h"
#include "asterisk/data.h"
+#include "asterisk/features.h"
#ifdef HAVE_EPOLL
#include <sys/epoll.h>
@@ -1837,11 +1838,13 @@
}
/*! \brief Wait, look for hangups and condition arg */
-int ast_safe_sleep_conditional(struct ast_channel *chan, int ms, int (*cond)(void*), void *data)
+int ast_safe_sleep_conditional(struct ast_channel *chan, int timeout_ms, int (*cond)(void*), void *data)
{
struct ast_frame *f;
struct ast_silence_generator *silgen = NULL;
int res = 0;
+ struct timeval start;
+ int ms;
AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames;
AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames);
@@ -1851,8 +1854,10 @@
silgen = ast_channel_start_silence_generator(chan);
}
- while (ms > 0) {
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
struct ast_frame *dup_f = NULL;
+
if (cond && ((*cond)(data) == 0)) {
break;
}
@@ -2989,12 +2994,15 @@
do {
AST_LIST_HEAD_NOLOCK(, ast_frame) frames;
struct ast_frame *cur, *new;
- int ms = MAX(delay, 500);
+ int timeout_ms = MAX(delay, 500);
unsigned int done = 0;
+ struct timeval start;
AST_LIST_HEAD_INIT_NOLOCK(&frames);
+ start = ast_tvnow();
for (;;) {
+ int ms = ast_remaining_ms(start, timeout_ms);
ms = ast_waitfor(chan, ms);
if (ms < 0) {
ast_log(LOG_WARNING, "Error condition occurred when polling channel %s for a voice frame: %s\n", chan->name, strerror(errno));
@@ -3111,7 +3119,11 @@
res = generate(chan, tmp, 0, ast_format_rate(chan->writeformat & AST_FORMAT_AUDIO_MASK) / 50);
- chan->generatordata = tmp;
+ ast_channel_lock(chan);
+ if (chan->generator && generate == chan->generator->generate) {
+ chan->generatordata = tmp;
+ }
+ ast_channel_unlock(chan);
if (res) {
ast_debug(1, "Auto-deactivating generator\n");
@@ -3509,11 +3521,14 @@
int ast_waitfor(struct ast_channel *c, int ms)
{
- int oldms = ms; /* -1 if no timeout */
-
- ast_waitfor_nandfds(&c, 1, NULL, 0, NULL, NULL, &ms);
- if ((ms < 0) && (oldms < 0))
- ms = 0;
+ if (ms < 0) {
+ do {
+ ms = 100000;
+ ast_waitfor_nandfds(&c, 1, NULL, 0, NULL, NULL, &ms);
+ } while (!ms);
+ } else {
+ ast_waitfor_nandfds(&c, 1, NULL, 0, NULL, NULL, &ms);
+ }
return ms;
}
@@ -3568,6 +3583,7 @@
int ast_waitfordigit_full(struct ast_channel *c, int timeout_ms, int audiofd, int cmdfd)
{
struct timeval start = ast_tvnow();
+ int ms;
/* Stop if we're a zombie or need a soft hangup */
if (ast_test_flag(c, AST_FLAG_ZOMBIE) || ast_check_hangup(c))
@@ -3579,19 +3595,9 @@
/* Wait for a digit, no more than timeout_ms milliseconds total.
* Or, wait indefinitely if timeout_ms is <0.
*/
- while (ast_tvdiff_ms(ast_tvnow(), start) < timeout_ms || timeout_ms < 0) {
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
struct ast_channel *rchan;
- int outfd=-1;
- int ms;
-
- if (timeout_ms < 0) {
- ms = timeout_ms;
- } else {
- ms = timeout_ms - ast_tvdiff_ms(ast_tvnow(), start);
- if (ms < 0) {
- ms = 0;
- }
- }
+ int outfd = -1;
errno = 0;
/* While ast_waitfor_nandfds tries to help by reducing the timeout by how much was waited,
@@ -4597,25 +4603,32 @@
char *ast_recvtext(struct ast_channel *chan, int timeout)
{
- int res, done = 0;
+ int res;
char *buf = NULL;
-
- while (!done) {
+ struct timeval start = ast_tvnow();
+ int ms;
+
+ while ((ms = ast_remaining_ms(start, timeout))) {
struct ast_frame *f;
- if (ast_check_hangup(chan))
+
+ if (ast_check_hangup(chan)) {
break;
- res = ast_waitfor(chan, timeout);
- if (res <= 0) /* timeout or error */
+ }
+ res = ast_waitfor(chan, ms);
+ if (res <= 0) {/* timeout or error */
break;
- timeout = res; /* update timeout */
+ }
f = ast_read(chan);
- if (f == NULL)
+ if (f == NULL) {
break; /* no frame */
- if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP)
- done = 1; /* force a break */
- else if (f->frametype == AST_FRAME_TEXT) { /* what we want */
+ }
+ if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
+ ast_frfree(f);
+ break;
+ } else if (f->frametype == AST_FRAME_TEXT) { /* what we want */
buf = ast_strndup((char *) f->data.ptr, f->datalen); /* dup and break */
- done = 1;
+ ast_frfree(f);
+ break;
}
ast_frfree(f);
}
@@ -4666,6 +4679,11 @@
if (!chan->tech->send_digit_begin)
return 0;
+ ast_channel_lock(chan);
+ chan->sending_dtmf_digit = digit;
+ chan->sending_dtmf_tv = ast_tvnow();
+ ast_channel_unlock(chan);
+
if (!chan->tech->send_digit_begin(chan, digit))
return 0;
@@ -4689,6 +4707,12 @@
{
int res = -1;
+ ast_channel_lock(chan);
+ if (chan->sending_dtmf_digit == digit) {
+ chan->sending_dtmf_digit = 0;
+ }
+ ast_channel_unlock(chan);
+
if (chan->tech->send_digit_end)
res = chan->tech->send_digit_end(chan, digit, duration);
@@ -5455,18 +5479,19 @@
if (ast_call(chan, data, 0)) { /* ast_call failed... */
ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
} else {
+ struct timeval start = ast_tvnow();
res = 1; /* mark success in case chan->_state is already AST_STATE_UP */
while (timeout && chan->_state != AST_STATE_UP) {
struct ast_frame *f;
- res = ast_waitfor(chan, timeout);
+ int ms = ast_remaining_ms(start, timeout);
+
+ res = ast_waitfor(chan, ms);
if (res == 0) { /* timeout, treat it like ringing */
*outstate = AST_CONTROL_RINGING;
break;
}
if (res < 0) /* error or done */
break;
- if (timeout > -1)
- timeout = res;
if (!ast_strlen_zero(chan->call_forward)) {
if (!(chan = ast_call_forward(NULL, chan, NULL, format, oh, outstate))) {
return NULL;
@@ -6496,6 +6521,8 @@
char orig[AST_CHANNEL_NAME];
char masqn[AST_CHANNEL_NAME];
char zombn[AST_CHANNEL_NAME];
+ char clone_sending_dtmf_digit;
+ struct timeval clone_sending_dtmf_tv;
/* XXX This operation is a bit odd. We're essentially putting the guts of
* the clone channel into the original channel. Start by killing off the
@@ -6605,6 +6632,10 @@
free_translation(clonechan);
free_translation(original);
+ /* Save the current DTMF digit being sent if any. */
+ clone_sending_dtmf_digit = clonechan->sending_dtmf_digit;
+ clone_sending_dtmf_tv = clonechan->sending_dtmf_tv;
+
/* Save the original name */
ast_copy_string(orig, original->name, sizeof(orig));
/* Save the new name */
@@ -6849,6 +6880,15 @@
ast_channel_unlock(clonechan);
+ if (clone_sending_dtmf_digit) {
+ /*
+ * The clonechan was sending a DTMF digit that was not completed
+ * before the masquerade.
+ */
+ ast_bridge_end_dtmf(original, clone_sending_dtmf_digit, clone_sending_dtmf_tv,
+ "masquerade");
+ }
+
/*
* If an indication is currently playing, maintain it on the
* channel that is taking the place of original.
@@ -8187,18 +8227,46 @@
return state;
}
+static int internal_deactivate_generator(struct ast_channel *chan, void* generator)
+{
+ ast_channel_lock(chan);
+
+ if (!chan->generatordata) {
+ ast_debug(1, "Trying to stop silence generator when there is no "
+ "generator on '%s'\n", chan->name);
+ ast_channel_unlock(chan);
+ return 0;
+ }
+ if (chan->generator != generator) {
+ ast_debug(1, "Trying to stop silence generator when it is not the current "
+ "generator on '%s'\n", chan->name);
+ ast_channel_unlock(chan);
+ return 0;
+ }
+ if (chan->generator && chan->generator->release) {
+ chan->generator->release(chan, chan->generatordata);
+ }
+ chan->generatordata = NULL;
+ chan->generator = NULL;
+ ast_channel_set_fd(chan, AST_GENERATOR_FD, -1);
+ ast_clear_flag(chan, AST_FLAG_WRITE_INT);
+ ast_settimeout(chan, 0, NULL, NULL);
+ ast_channel_unlock(chan);
+
+ return 1;
+}
+
void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
{
if (!state)
return;
- ast_deactivate_generator(chan);
-
- ast_debug(1, "Stopped silence generator on '%s'\n", chan->name);
-
- if (ast_set_write_format(chan, state->old_write_format) < 0)
- ast_log(LOG_ERROR, "Could not return write format to its original state\n");
+ if (internal_deactivate_generator(chan, &silence_generator)) {
+ ast_debug(1, "Stopped silence generator on '%s'\n", chan->name);
+ if (ast_set_write_format(chan, state->old_write_format) < 0)
+ ast_log(LOG_ERROR, "Could not return write format to its original state\n");
+ }
ast_free(state);
}
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/cli.c
^
|
@@ -29,7 +29,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 369001 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 377073 $")
#include "asterisk/_private.h"
#include "asterisk/paths.h" /* use ast_config_AST_MODULE_DIR */
@@ -1871,10 +1871,16 @@
return 0;
}
+static void cli_shutdown(void)
+{
+ ast_cli_unregister_multiple(cli_cli, ARRAY_LEN(cli_cli));
+}
+
/*! \brief initialize the _full_cmd string in * each of the builtins. */
void ast_builtins_init(void)
{
ast_cli_register_multiple(cli_cli, ARRAY_LEN(cli_cli));
+ ast_register_atexit(cli_shutdown);
}
/*!
@@ -2039,6 +2045,18 @@
return cmdline;
}
+static int cli_is_registered(struct ast_cli_entry *e)
+{
+ struct ast_cli_entry *cur = NULL;
+
+ while ((cur = cli_next(cur))) {
+ if (cur == e) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
static int __ast_cli_unregister(struct ast_cli_entry *e, struct ast_cli_entry *ed)
{
if (e->inuse) {
@@ -2070,6 +2088,15 @@
char **dst = (char **)e->cmda; /* need to cast as the entry is readonly */
char *s;
+ AST_RWLIST_WRLOCK(&helpers);
+
+ if (cli_is_registered(e)) {
+ ast_log(LOG_WARNING, "Command '%s' already registered (the same ast_cli_entry)\n",
+ S_OR(e->_full_cmd, e->command));
+ ret = 0; /* report success */
+ goto done;
+ }
+
memset(&a, '\0', sizeof(a));
e->handler(e, CLI_INIT, &a);
/* XXX check that usage and command are filled up */
@@ -2084,15 +2111,17 @@
s = ast_skip_blanks(s);
}
*dst++ = NULL;
-
- AST_RWLIST_WRLOCK(&helpers);
-
+
if (find_cli(e->cmda, 1)) {
- ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n", S_OR(e->_full_cmd, e->command));
+ ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n",
+ S_OR(e->_full_cmd, e->command));
goto done;
}
- if (set_full_cmd(e))
+ if (set_full_cmd(e)) {
+ ast_log(LOG_WARNING, "Error registering CLI Command '%s'\n",
+ S_OR(e->_full_cmd, e->command));
goto done;
+ }
lf = e->cmdlen;
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&helpers, cur, list) {
@@ -2112,6 +2141,10 @@
done:
AST_RWLIST_UNLOCK(&helpers);
+ if (ret) {
+ ast_free(e->command);
+ e->command = NULL;
+ }
return ret;
}
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/config.c
^
|
@@ -32,7 +32,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 371392 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 377104 $")
#include "asterisk/paths.h" /* use ast_config_AST_CONFIG_DIR */
#include "asterisk/network.h" /* we do some sockaddr manipulation here */
@@ -2952,8 +2952,22 @@
AST_CLI_DEFINE(handle_cli_config_list, "Show all files that have loaded a configuration file"),
};
+static void config_shutdown(void)
+{
+ struct cache_file_mtime *cfmtime;
+
+ AST_LIST_LOCK(&cfmtime_head);
+ while ((cfmtime = AST_LIST_REMOVE_HEAD(&cfmtime_head, list))) {
+ ast_free(cfmtime);
+ }
+ AST_LIST_UNLOCK(&cfmtime_head);
+
+ ast_cli_unregister_multiple(cli_config, ARRAY_LEN(cli_config));
+}
+
int register_config_cli(void)
{
ast_cli_register_multiple(cli_config, ARRAY_LEN(cli_config));
+ ast_register_atexit(config_shutdown);
return 0;
}
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/devicestate.c
^
|
@@ -119,7 +119,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378341 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#include "asterisk/_private.h"
#include "asterisk/channel.h"
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/event.c
^
|
@@ -29,7 +29,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378341 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#include "asterisk/_private.h"
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/features.c
^
|
@@ -29,7 +29,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378341 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#include "asterisk/_private.h"
@@ -3896,6 +3896,24 @@
ast_channel_unlock(chan);
}
+void ast_bridge_end_dtmf(struct ast_channel *chan, char digit, struct timeval start, const char *why)
+{
+ int dead;
+ long duration;
+
+ ast_channel_lock(chan);
+ dead = ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan);
+ ast_channel_unlock(chan);
+ if (dead) {
+ return;
+ }
+
+ duration = ast_tvdiff_ms(ast_tvnow(), start);
+ ast_senddigit_end(chan, digit, duration);
+ ast_log(LOG_DTMF, "DTMF end '%c' simulated on %s due to %s, duration %ld ms\n",
+ digit, chan->name, why, duration);
+}
+
/*!
* \brief bridge the call and set CDR
*
@@ -4342,6 +4360,15 @@
ast_cel_report_event(chan, AST_CEL_BRIDGE_END, NULL, NULL, peer);
before_you_go:
+ if (chan->sending_dtmf_digit) {
+ ast_bridge_end_dtmf(chan, chan->sending_dtmf_digit, chan->sending_dtmf_tv,
+ "bridge end");
+ }
+ if (peer->sending_dtmf_digit) {
+ ast_bridge_end_dtmf(peer, peer->sending_dtmf_digit, peer->sending_dtmf_tv,
+ "bridge end");
+ }
+
/* Just in case something weird happened and we didn't clean up the silence generator... */
if (silgen) {
ast_channel_stop_silence_generator(who == chan ? peer : chan, silgen);
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/http.c
^
|
@@ -36,7 +36,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378341 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#include <time.h>
#include <sys/time.h>
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/indications.c
^
|
@@ -29,7 +29,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 374177 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376469 $")
#include <math.h>
@@ -873,7 +873,7 @@
(j == tz->nrringcadence - 1) ? "" : ",");
}
ast_str_append(&buf, 0, "\n");
- ast_cli(a->fd, "%s", buf->str);
+ ast_cli(a->fd, "%s", ast_str_buffer(buf));
AST_LIST_TRAVERSE(&tz->tones, ts, entry) {
ast_cli(a->fd, "%-7.7s %-15.15s %s\n", tz->country, ts->name, ts->data);
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/lock.c
^
|
@@ -27,7 +27,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 371718 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376586 $")
#include "asterisk/lock.h"
@@ -51,8 +51,8 @@
int res;
pthread_mutexattr_t attr;
- t->track = NULL;
#ifdef DEBUG_THREADS
+ t->track = NULL;
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
/*
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/logger.c
^
|
@@ -31,7 +31,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 370642 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376586 $")
/* When we include logger.h again it will trample on some stuff in syslog.h, but
* nothing we care about in here. */
@@ -1133,8 +1133,17 @@
/* auto rotate if sig SIGXFSZ comes a-knockin */
sigaction(SIGXFSZ, &handle_SIGXFSZ, NULL);
- /* start logger thread */
+ /* Re-initialize the logmsgs mutex. The recursive mutex can be accessed prior
+ * to Asterisk being forked into the background, which can cause the thread
+ * ID tracked by the underlying pthread mutex to be different than the ID of
+ * the thread that unlocks the mutex. Since init_logger is called after the
+ * fork, it is safe to initialize the mutex here for future accesses.
+ */
+ ast_mutex_destroy(&logmsgs.lock);
+ ast_mutex_init(&logmsgs.lock);
ast_cond_init(&logcond, NULL);
+
+ /* start logger thread */
if (ast_pthread_create(&logthread, NULL, logger_thread, NULL) < 0) {
ast_cond_destroy(&logcond);
return -1;
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/manager.c
^
|
@@ -47,7 +47,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 375800 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376725 $")
#include "asterisk/_private.h"
#include "asterisk/paths.h" /* use various ast_config_AST_* */
@@ -4696,7 +4696,7 @@
|| !strcasecmp(action, "Challenge"))) {
user = astman_get_header(m, "Username");
- if (check_manager_session_inuse(user)) {
+ if (!ast_strlen_zero(user) && check_manager_session_inuse(user)) {
report_session_limit(s);
sleep(1);
mansession_lock(s);
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/pbx.c
^
|
@@ -29,7 +29,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 374758 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376688 $")
#include "asterisk/_private.h"
#include "asterisk/paths.h" /* use ast_config_AST_SYSTEM_NAME */
@@ -2282,10 +2282,122 @@
ast_free(pattern_tree);
}
+/*!
+ * \internal
+ * \brief Get the length of the exten string.
+ *
+ * \param str Exten to get length.
+ *
+ * \retval strlen of exten.
+ */
+static int ext_cmp_exten_strlen(const char *str)
+{
+ int len;
+
+ len = 0;
+ for (;;) {
+ /* Ignore '-' chars as eye candy fluff. */
+ while (*str == '-') {
+ ++str;
+ }
+ if (!*str) {
+ break;
+ }
+ ++str;
+ ++len;
+ }
+ return len;
+}
+
+/*!
+ * \internal
+ * \brief Partial comparison of non-pattern extens.
+ *
+ * \param left Exten to compare.
+ * \param right Exten to compare. Also matches if this string ends first.
+ *
+ * \retval <0 if left < right
+ * \retval =0 if left == right
+ * \retval >0 if left > right
+ */
+static int ext_cmp_exten_partial(const char *left, const char *right)
+{
+ int cmp;
+
+ for (;;) {
+ /* Ignore '-' chars as eye candy fluff. */
+ while (*left == '-') {
+ ++left;
+ }
+ while (*right == '-') {
+ ++right;
+ }
+
+ if (!*right) {
+ /*
+ * Right ended first for partial match or both ended at the same
+ * time for a match.
+ */
+ cmp = 0;
+ break;
+ }
+
+ cmp = *left - *right;
+ if (cmp) {
+ break;
+ }
+ ++left;
+ ++right;
+ }
+ return cmp;
+}
+
+/*!
+ * \internal
+ * \brief Comparison of non-pattern extens.
+ *
+ * \param left Exten to compare.
+ * \param right Exten to compare.
+ *
+ * \retval <0 if left < right
+ * \retval =0 if left == right
+ * \retval >0 if left > right
+ */
+static int ext_cmp_exten(const char *left, const char *right)
+{
+ int cmp;
+
+ for (;;) {
+ /* Ignore '-' chars as eye candy fluff. */
+ while (*left == '-') {
+ ++left;
+ }
+ while (*right == '-') {
+ ++right;
+ }
+
+ cmp = *left - *right;
+ if (cmp) {
+ break;
+ }
+ if (!*left) {
+ /*
+ * Get here only if both strings ended at the same time. cmp
+ * would be non-zero if only one string ended.
+ */
+ break;
+ }
+ ++left;
+ ++right;
+ }
+ return cmp;
+}
+
/*
* Special characters used in patterns:
* '_' underscore is the leading character of a pattern.
* In other position it is treated as a regular char.
+ * '-' The '-' is a separator and ignored. Why? So patterns like NXX-XXX-XXXX work.
* . one or more of any character. Only allowed at the end of
* a pattern.
* ! zero or more of anything. Also impacts the result of CANMATCH
@@ -2314,144 +2426,227 @@
*/
/*!
- * \brief helper functions to sort extensions and patterns in the desired way,
+ * \brief helper functions to sort extension patterns in the desired way,
* so that more specific patterns appear first.
*
- * ext_cmp1 compares individual characters (or sets of), returning
+ * \details
+ * The function compares individual characters (or sets of), returning
* an int where bits 0-7 are the ASCII code of the first char in the set,
- * while bit 8-15 are the cardinality of the set minus 1.
- * This way more specific patterns (smaller cardinality) appear first.
+ * bits 8-15 are the number of characters in the set, and bits 16-20 are
+ * for special cases.
+ * This way more specific patterns (smaller character sets) appear first.
* Wildcards have a special value, so that we can directly compare them to
* sets by subtracting the two values. In particular:
- * 0x000xx one character, xx
- * 0x0yyxx yy character set starting with xx
- * 0x10000 '.' (one or more of anything)
- * 0x20000 '!' (zero or more of anything)
- * 0x30000 NUL (end of string)
- * 0x40000 error in set.
+ * 0x001xx one character, character set starting with xx
+ * 0x0yyxx yy characters, character set starting with xx
+ * 0x18000 '.' (one or more of anything)
+ * 0x28000 '!' (zero or more of anything)
+ * 0x30000 NUL (end of string)
+ * 0x40000 error in set.
* The pointer to the string is advanced according to needs.
* NOTES:
- * 1. the empty set is equivalent to NUL.
- * 2. given that a full set has always 0 as the first element,
- * we could encode the special cases as 0xffXX where XX
- * is 1, 2, 3, 4 as used above.
- */
-static int ext_cmp1(const char **p, unsigned char *bitwise)
-{
- int c, cmin = 0xff, count = 0;
+ * 1. the empty set is ignored.
+ * 2. given that a full set has always 0 as the first element,
+ * we could encode the special cases as 0xffXX where XX
+ * is 1, 2, 3, 4 as used above.
+ */
+static int ext_cmp_pattern_pos(const char **p, unsigned char *bitwise)
+{
+#define BITS_PER 8 /* Number of bits per unit (byte). */
+ unsigned char c;
+ unsigned char cmin;
+ int count;
const char *end;
- /* load value and advance pointer */
- c = *(*p)++;
+ do {
+ /* Get character and advance. (Ignore '-' chars as eye candy fluff.) */
+ do {
+ c = *(*p)++;
+ } while (c == '-');
- /* always return unless we have a set of chars */
- switch (toupper(c)) {
- default: /* ordinary character */
- bitwise[c / 8] = 1 << (c % 8);
- return 0x0100 | (c & 0xff);
-
- case 'N': /* 2..9 */
- bitwise[6] = 0xfc;
- bitwise[7] = 0x03;
- return 0x0800 | '2';
-
- case 'X': /* 0..9 */
- bitwise[6] = 0xff;
- bitwise[7] = 0x03;
- return 0x0A00 | '0';
-
- case 'Z': /* 1..9 */
- bitwise[6] = 0xfe;
- bitwise[7] = 0x03;
- return 0x0900 | '1';
-
- case '.': /* wildcard */
- return 0x18000;
-
- case '!': /* earlymatch */
- return 0x28000; /* less specific than NULL */
-
- case '\0': /* empty string */
- *p = NULL;
- return 0x30000;
+ /* always return unless we have a set of chars */
+ switch (c) {
+ default:
+ /* ordinary character */
+ bitwise[c / BITS_PER] = 1 << ((BITS_PER - 1) - (c % BITS_PER));
+ return 0x0100 | c;
- case '[': /* pattern */
- break;
- }
- /* locate end of set */
- end = strchr(*p, ']');
+ case 'n':
+ case 'N':
+ /* 2..9 */
+ bitwise[6] = 0x3f;
+ bitwise[7] = 0xc0;
+ return 0x0800 | '2';
- if (end == NULL) {
- ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
- return 0x40000; /* XXX make this entry go last... */
- }
-
- for (; *p < end ; (*p)++) {
- unsigned char c1, c2; /* first-last char in range */
- c1 = (unsigned char)((*p)[0]);
- if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
- c2 = (unsigned char)((*p)[2]);
- *p += 2; /* skip a total of 3 chars */
- } else { /* individual character */
- c2 = c1;
- }
- if (c1 < cmin) {
- cmin = c1;
- }
- for (; c1 <= c2; c1++) {
- unsigned char mask = 1 << (c1 % 8);
- /*!\note If two patterns score the same, the one with the lowest
- * ascii values will compare as coming first. */
- /* Flag the character as included (used) and count it. */
- if (!(bitwise[ c1 / 8 ] & mask)) {
- bitwise[ c1 / 8 ] |= mask;
- count += 0x100;
+ case 'x':
+ case 'X':
+ /* 0..9 */
+ bitwise[6] = 0xff;
+ bitwise[7] = 0xc0;
+ return 0x0A00 | '0';
+
+ case 'z':
+ case 'Z':
+ /* 1..9 */
+ bitwise[6] = 0x7f;
+ bitwise[7] = 0xc0;
+ return 0x0900 | '1';
+
+ case '.':
+ /* wildcard */
+ return 0x18000;
+
+ case '!':
+ /* earlymatch */
+ return 0x28000; /* less specific than '.' */
+
+ case '\0':
+ /* empty string */
+ *p = NULL;
+ return 0x30000;
+
+ case '[':
+ /* char set */
+ break;
+ }
+ /* locate end of set */
+ end = strchr(*p, ']');
+
+ if (!end) {
+ ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
+ return 0x40000; /* XXX make this entry go last... */
+ }
+
+ count = 0;
+ cmin = 0xFF;
+ for (; *p < end; ++*p) {
+ unsigned char c1; /* first char in range */
+ unsigned char c2; /* last char in range */
+
+ c1 = (*p)[0];
+ if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
+ c2 = (*p)[2];
+ *p += 2; /* skip a total of 3 chars */
+ } else { /* individual character */
+ c2 = c1;
+ }
+ if (c1 < cmin) {
+ cmin = c1;
+ }
+ for (; c1 <= c2; ++c1) {
+ unsigned char mask = 1 << ((BITS_PER - 1) - (c1 % BITS_PER));
+
+ /*
+ * Note: If two character sets score the same, the one with the
+ * lowest ASCII values will compare as coming first. Must fill
+ * in most significant bits for lower ASCII values to accomplish
+ * the desired sort order.
+ */
+ if (!(bitwise[c1 / BITS_PER] & mask)) {
+ /* Add the character to the set. */
+ bitwise[c1 / BITS_PER] |= mask;
+ count += 0x100;
+ }
}
}
- }
- (*p)++;
- return count == 0 ? 0x30000 : (count | cmin);
+ ++*p;
+ } while (!count);/* While the char set was empty. */
+ return count | cmin;
}
/*!
- * \brief the full routine to compare extensions in rules.
+ * \internal
+ * \brief Comparison of exten patterns.
+ *
+ * \param left Pattern to compare.
+ * \param right Pattern to compare.
+ *
+ * \retval <0 if left < right
+ * \retval =0 if left == right
+ * \retval >0 if left > right
*/
-static int ext_cmp(const char *a, const char *b)
+static int ext_cmp_pattern(const char *left, const char *right)
{
- /* make sure non-patterns come first.
- * If a is not a pattern, it either comes first or
- * we do a more complex pattern comparison.
- */
- int ret = 0;
+ int cmp;
+ int left_pos;
+ int right_pos;
- if (a[0] != '_')
- return (b[0] == '_') ? -1 : strcmp(a, b);
+ for (;;) {
+ unsigned char left_bitwise[32] = { 0, };
+ unsigned char right_bitwise[32] = { 0, };
- /* Now we know a is a pattern; if b is not, a comes first */
- if (b[0] != '_')
- return 1;
+ left_pos = ext_cmp_pattern_pos(&left, left_bitwise);
+ right_pos = ext_cmp_pattern_pos(&right, right_bitwise);
+ cmp = left_pos - right_pos;
+ if (!cmp) {
+ /*
+ * Are the character sets different, even though they score the same?
+ *
+ * Note: Must swap left and right to get the sense of the
+ * comparison correct. Otherwise, we would need to multiply by
+ * -1 instead.
+ */
+ cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise));
+ }
+ if (cmp) {
+ break;
+ }
+ if (!left) {
+ /*
+ * Get here only if both patterns ended at the same time. cmp
+ * would be non-zero if only one pattern ended.
+ */
+ break;
+ }
+ }
+ return cmp;
+}
- /* ok we need full pattern sorting routine.
- * skip past the underscores */
- ++a; ++b;
- do {
- unsigned char bitwise[2][32] = { { 0, } };
- ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]);
- if (ret == 0) {
- /* Are the classes different, even though they score the same? */
- ret = memcmp(bitwise[0], bitwise[1], 32);
+/*!
+ * \internal
+ * \brief Comparison of dialplan extens for sorting purposes.
+ *
+ * \param left Exten/pattern to compare.
+ * \param right Exten/pattern to compare.
+ *
+ * \retval <0 if left < right
+ * \retval =0 if left == right
+ * \retval >0 if left > right
+ */
+static int ext_cmp(const char *left, const char *right)
+{
+ /* Make sure non-pattern extens come first. */
+ if (left[0] != '_') {
+ if (right[0] == '_') {
+ return -1;
}
- } while (!ret && a && b);
- if (ret == 0) {
- return 0;
- } else {
- return (ret > 0) ? 1 : -1;
+ /* Compare two non-pattern extens. */
+ return ext_cmp_exten(left, right);
}
+ if (right[0] != '_') {
+ return 1;
+ }
+
+ /*
+ * OK, we need full pattern sorting routine.
+ *
+ * Skip past the underscores
+ */
+ return ext_cmp_pattern(left + 1, right + 1);
}
int ast_extension_cmp(const char *a, const char *b)
{
- return ext_cmp(a, b);
+ int cmp;
+
+ cmp = ext_cmp(a, b);
+ if (cmp < 0) {
+ return -1;
+ }
+ if (cmp > 0) {
+ return 1;
+ }
+ return 0;
}
/*!
@@ -2474,15 +2669,9 @@
ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode);
#endif
- if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */
-#ifdef NEED_DEBUG_HERE
- ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n");
-#endif
- return 1;
- }
-
if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
- int ld = strlen(data), lp = strlen(pattern);
+ int lp = ext_cmp_exten_strlen(pattern);
+ int ld = ext_cmp_exten_strlen(data);
if (lp < ld) { /* pattern too short, cannot match */
#ifdef NEED_DEBUG_HERE
@@ -2493,11 +2682,11 @@
/* depending on the mode, accept full or partial match or both */
if (mode == E_MATCH) {
#ifdef NEED_DEBUG_HERE
- ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data);
+ ast_log(LOG_NOTICE,"return (!ext_cmp_exten(%s,%s) when mode== E_MATCH)\n", pattern, data);
#endif
- return !strcmp(pattern, data); /* 1 on match, 0 on fail */
+ return !ext_cmp_exten(pattern, data); /* 1 on match, 0 on fail */
}
- if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */
+ if (ld == 0 || !ext_cmp_exten_partial(pattern, data)) { /* partial or full match */
#ifdef NEED_DEBUG_HERE
ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld);
#endif
@@ -2509,26 +2698,60 @@
return 0;
}
}
- pattern++; /* skip leading _ */
+ if (mode == E_MATCH && data[0] == '_') {
+ /*
+ * XXX It is bad design that we don't know if we should be
+ * comparing data and pattern as patterns or comparing data if
+ * it conforms to pattern when the function is called. First,
+ * assume they are both patterns. If they don't match then try
+ * to see if data conforms to the given pattern.
+ *
+ * note: if this test is left out, then _x. will not match _x. !!!
+ */
+#ifdef NEED_DEBUG_HERE
+ ast_log(LOG_NOTICE, "Comparing as patterns first. pattern:%s data:%s\n", pattern, data);
+#endif
+ if (!ext_cmp_pattern(pattern + 1, data + 1)) {
+#ifdef NEED_DEBUG_HERE
+ ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n");
+#endif
+ return 1;
+ }
+ }
+
+ ++pattern; /* skip leading _ */
/*
* XXX below we stop at '/' which is a separator for the CID info. However we should
* not store '/' in the pattern at all. When we insure it, we can remove the checks.
*/
- while (*data && *pattern && *pattern != '/') {
+ for (;;) {
const char *end;
- if (*data == '-') { /* skip '-' in data (just a separator) */
- data++;
- continue;
+ /* Ignore '-' chars as eye candy fluff. */
+ while (*data == '-') {
+ ++data;
+ }
+ while (*pattern == '-') {
+ ++pattern;
}
- switch (toupper(*pattern)) {
+ if (!*data || !*pattern || *pattern == '/') {
+ break;
+ }
+
+ switch (*pattern) {
case '[': /* a range */
- end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */
- if (end == NULL) {
+ ++pattern;
+ end = strchr(pattern, ']'); /* XXX should deal with escapes ? */
+ if (!end) {
ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
return 0; /* unconditional failure */
}
- for (pattern++; pattern != end; pattern++) {
+ if (pattern == end) {
+ /* Ignore empty character sets. */
+ ++pattern;
+ continue;
+ }
+ for (; pattern < end; ++pattern) {
if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
if (*data >= pattern[0] && *data <= pattern[2])
break; /* match found */
@@ -2539,34 +2762,37 @@
} else if (*data == pattern[0])
break; /* match found */
}
- if (pattern == end) {
+ if (pattern >= end) {
#ifdef NEED_DEBUG_HERE
- ast_log(LOG_NOTICE,"return (0) when pattern==end\n");
+ ast_log(LOG_NOTICE,"return (0) when pattern>=end\n");
#endif
return 0;
}
pattern = end; /* skip and continue */
break;
+ case 'n':
case 'N':
if (*data < '2' || *data > '9') {
#ifdef NEED_DEBUG_HERE
- ast_log(LOG_NOTICE,"return (0) N is matched\n");
+ ast_log(LOG_NOTICE,"return (0) N is not matched\n");
#endif
return 0;
}
break;
+ case 'x':
case 'X':
if (*data < '0' || *data > '9') {
#ifdef NEED_DEBUG_HERE
- ast_log(LOG_NOTICE,"return (0) X is matched\n");
+ ast_log(LOG_NOTICE,"return (0) X is not matched\n");
#endif
return 0;
}
break;
+ case 'z':
case 'Z':
if (*data < '1' || *data > '9') {
#ifdef NEED_DEBUG_HERE
- ast_log(LOG_NOTICE,"return (0) Z is matched\n");
+ ast_log(LOG_NOTICE,"return (0) Z is not matched\n");
#endif
return 0;
}
@@ -2581,10 +2807,6 @@
ast_log(LOG_NOTICE, "return (2) when '!' is matched\n");
#endif
return 2;
- case ' ':
- case '-': /* Ignore these in patterns */
- data--; /* compensate the final data++ */
- break;
default:
if (*data != *pattern) {
#ifdef NEED_DEBUG_HERE
@@ -2592,9 +2814,10 @@
#endif
return 0;
}
+ break;
}
- data++;
- pattern++;
+ ++data;
+ ++pattern;
}
if (*data) /* data longer than pattern, no match */ {
#ifdef NEED_DEBUG_HERE
@@ -2604,7 +2827,7 @@
}
/*
- * match so far, but ran off the end of the data.
+ * match so far, but ran off the end of data.
* Depending on what is next, determine match or not.
*/
if (*pattern == '\0' || *pattern == '/') { /* exact match */
@@ -6880,17 +7103,17 @@
manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
- if (context && !counters.context_existence) {
+ if (!ast_strlen_zero(context) && !counters.context_existence) {
char errorbuf[BUFSIZ];
snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
astman_send_error(s, m, errorbuf);
return 0;
}
- if (exten && !counters.extension_existence) {
+ if (!ast_strlen_zero(exten) && !counters.extension_existence) {
char errorbuf[BUFSIZ];
- if (context)
+ if (!ast_strlen_zero(context))
snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
else
snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
@@ -6898,6 +7121,10 @@
return 0;
}
+ if (!counters.total_items) {
+ manager_dpsendack(s, m);
+ }
+
astman_append(s, "Event: ShowDialPlanComplete\r\n"
"EventList: Complete\r\n"
"ListItems: %d\r\n"
@@ -8308,8 +8535,15 @@
for (ep = NULL; e ; ep = e, e = e->peer) {
if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
- ast_log(LOG_WARNING, "Extension '%s', priority %d in '%s', label '%s' already in use at "
- "priority %d\n", tmp->exten, tmp->priority, con->name, tmp->label, e->priority);
+ if (strcmp(e->exten, tmp->exten)) {
+ ast_log(LOG_WARNING,
+ "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n",
+ tmp->exten, tmp->priority, con->name, tmp->label, e->exten, e->priority);
+ } else {
+ ast_log(LOG_WARNING,
+ "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n",
+ tmp->exten, tmp->priority, con->name, tmp->label, e->priority);
+ }
repeated_label = 1;
}
if (e->priority >= tmp->priority) {
@@ -8334,7 +8568,15 @@
/* Can't have something exactly the same. Is this a
replacement? If so, replace, otherwise, bonk. */
if (!replace) {
- ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
+ if (strcmp(e->exten, tmp->exten)) {
+ ast_log(LOG_WARNING,
+ "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n",
+ tmp->exten, tmp->priority, con->name, e->exten);
+ } else {
+ ast_log(LOG_WARNING,
+ "Unable to register extension '%s' priority %d in '%s', already in use\n",
+ tmp->exten, tmp->priority, con->name);
+ }
if (tmp->datad) {
tmp->datad(tmp->data);
/* if you free this, null it out */
@@ -8522,7 +8764,7 @@
}
/* If we are adding a hint evalulate in variables and global variables */
- if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) {
+ if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') {
struct ast_channel *c = ast_dummy_channel_alloc();
if (c) {
@@ -8721,13 +8963,15 @@
int res;
struct ast_frame *f;
struct ast_app *app;
+ struct timeval start = ast_tvnow();
+ int ms;
- while (timeout && (chan->_state != AST_STATE_UP)) {
- res = ast_waitfor(chan, timeout);
+ while ((ms = ast_remaining_ms(start, timeout)) &&
+ chan->_state != AST_STATE_UP) {
+ res = ast_waitfor(chan, ms);
if (res < 1)
break;
- if (timeout > -1)
- timeout = res;
+
f = ast_read(chan);
if (!f)
break;
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/rtp_engine.c
^
|
@@ -29,7 +29,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 369001 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 375993 $")
#include <math.h>
@@ -810,6 +810,7 @@
enum ast_bridge_result res = AST_BRIDGE_FAILED;
struct ast_channel *who = NULL, *other = NULL, *cs[3] = { NULL, };
struct ast_frame *fr = NULL;
+ struct timeval start;
/* Start locally bridging both instances */
if (instance0->engine->local_bridge && instance0->engine->local_bridge(instance0, instance1)) {
@@ -840,7 +841,9 @@
cs[0] = c0;
cs[1] = c1;
cs[2] = NULL;
+ start = ast_tvnow();
for (;;) {
+ int ms;
/* If the underlying formats have changed force this bridge to break */
if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
ast_debug(1, "rtp-engine-local-bridge: Oooh, formats changed, backing out\n");
@@ -865,8 +868,9 @@
break;
}
/* Wait on a channel to feed us a frame */
- if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
- if (!timeoutms) {
+ ms = ast_remaining_ms(start, timeoutms);
+ if (!(who = ast_waitfor_n(cs, 2, &ms))) {
+ if (!ms) {
res = AST_BRIDGE_RETRY;
break;
}
@@ -985,6 +989,7 @@
struct ast_sockaddr ac1 = {{0,}}, vac1 = {{0,}}, tac1 = {{0,}}, ac0 = {{0,}}, vac0 = {{0,}}, tac0 = {{0,}};
struct ast_sockaddr t1 = {{0,}}, vt1 = {{0,}}, tt1 = {{0,}}, t0 = {{0,}}, vt0 = {{0,}}, tt0 = {{0,}};
struct ast_frame *fr = NULL;
+ struct timeval start;
/* Test the first channel */
if (!(glue0->update_peer(c0, instance1, vinstance1, tinstance1, codec1, 0))) {
@@ -1024,7 +1029,9 @@
cs[0] = c0;
cs[1] = c1;
cs[2] = NULL;
+ start = ast_tvnow();
for (;;) {
+ int ms;
/* Check if anything changed */
if ((c0->tech_pvt != pvt0) ||
(c1->tech_pvt != pvt1) ||
@@ -1115,9 +1122,10 @@
oldcodec0 = codec0;
}
+ ms = ast_remaining_ms(start, timeoutms);
/* Wait for frame to come in on the channels */
- if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
- if (!timeoutms) {
+ if (!(who = ast_waitfor_n(cs, 2, &ms))) {
+ if (!ms) {
res = AST_BRIDGE_RETRY;
break;
}
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/security_events.c
^
|
@@ -30,7 +30,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 369001 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376469 $")
#include "asterisk/utils.h"
#include "asterisk/strings.h"
@@ -440,7 +440,7 @@
return ast_event_new(AST_EVENT_SECURITY,
AST_EVENT_IE_SECURITY_EVENT, AST_EVENT_IE_PLTYPE_UINT, sec->event_type,
AST_EVENT_IE_EVENT_VERSION, AST_EVENT_IE_PLTYPE_UINT, sec->version,
- AST_EVENT_IE_EVENT_TV, AST_EVENT_IE_PLTYPE_STR, str->str,
+ AST_EVENT_IE_EVENT_TV, AST_EVENT_IE_PLTYPE_STR, ast_str_buffer(str),
AST_EVENT_IE_SERVICE, AST_EVENT_IE_PLTYPE_STR, sec->service,
AST_EVENT_IE_SEVERITY, AST_EVENT_IE_PLTYPE_STR, severity_str,
AST_EVENT_IE_END);
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/stdtime/localtime.c
^
|
@@ -50,7 +50,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 369001 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 377135 $")
#include <signal.h>
#include <sys/stat.h>
@@ -71,6 +71,7 @@
#include "private.h"
#include "tzfile.h"
+#include "asterisk/_private.h"
#include "asterisk/lock.h"
#include "asterisk/localtime.h"
#include "asterisk/strings.h"
@@ -427,7 +428,7 @@
closedir(sp->dir);
}
#endif
- free(sp);
+ ast_free(sp);
/* Just in case the signal was sent late */
AST_LIST_LOCK(&zonelist);
@@ -707,7 +708,14 @@
return -1;
if ((fid = open(name, OPEN_MODE)) == -1)
return -1;
- add_notify(sp, name);
+ if (ast_fully_booted) {
+ /* If we don't wait until Asterisk is fully booted, it's possible
+ * that the watcher thread gets started in the parent process,
+ * before daemon(3) is called, and the thread won't propagate to
+ * the child. Given that bootup only takes a few seconds, it's
+ * reasonable to only start the watcher later. */
+ add_notify(sp, name);
+ }
}
nread = read(fid, u.buf, sizeof u.buf);
if (close(fid) < 0 || nread <= 0)
@@ -1410,6 +1418,17 @@
return -1;
}
+void clean_time_zones(void)
+{
+ struct state *sp;
+
+ AST_LIST_LOCK(&zonelist);
+ while ((sp = AST_LIST_REMOVE_HEAD(&zonelist, list))) {
+ ast_free(sp);
+ }
+ AST_LIST_UNLOCK(&zonelist);
+}
+
static const struct state *ast_tzset(const char *zone)
{
struct state *sp;
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/utils.c
^
|
@@ -29,7 +29,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 371690 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376428 $")
#include <ctype.h>
#include <sys/stat.h>
@@ -981,18 +981,7 @@
#ifdef DEBUG_THREADS
struct thr_lock_info *lock_info;
pthread_mutexattr_t mutex_attr;
-#endif
-
- /* note that even though data->name is a pointer to allocated memory,
- we are not freeing it here because ast_register_thread is going to
- keep a copy of the pointer and then ast_unregister_thread will
- free the memory
- */
- ast_free(data);
- ast_register_thread(a.name);
- pthread_cleanup_push(ast_unregister_thread, (void *) pthread_self());
-#ifdef DEBUG_THREADS
if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
return NULL;
@@ -1009,6 +998,15 @@
pthread_mutex_unlock(&lock_infos_lock.mutex); /* Intentionally not the wrapper */
#endif /* DEBUG_THREADS */
+ /* note that even though data->name is a pointer to allocated memory,
+ we are not freeing it here because ast_register_thread is going to
+ keep a copy of the pointer and then ast_unregister_thread will
+ free the memory
+ */
+ ast_free(data);
+ ast_register_thread(a.name);
+ pthread_cleanup_push(ast_unregister_thread, (void *) pthread_self());
+
ret = a.start_routine(a.data);
pthread_cleanup_pop(1);
@@ -1432,6 +1430,23 @@
}
return a;
}
+
+int ast_remaining_ms(struct timeval start, int max_ms)
+{
+ int ms;
+
+ if (max_ms < 0) {
+ ms = max_ms;
+ } else {
+ ms = max_ms - ast_tvdiff_ms(ast_tvnow(), start);
+ if (ms < 0) {
+ ms = 0;
+ }
+ }
+
+ return ms;
+}
+
#undef ONE_MILLION
/*! \brief glibc puts a lock inside random(3), so that the results are thread-safe.
@@ -2137,3 +2152,35 @@
return NULL;
}
+void ast_do_crash(void)
+{
+#if defined(DO_CRASH)
+ abort();
+ /*
+ * Just in case abort() doesn't work or something else super
+ * silly, and for Qwell's amusement.
+ */
+ *((int *) 0) = 0;
+#endif /* defined(DO_CRASH) */
+}
+
+#if defined(AST_DEVMODE)
+void __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function)
+{
+ /*
+ * Attempt to put it into the logger, but hope that at least
+ * someone saw the message on stderr ...
+ */
+ ast_log(__LOG_ERROR, file, line, function, "FRACK!, Failed assertion %s (%d)\n",
+ condition_str, condition);
+ fprintf(stderr, "FRACK!, Failed assertion %s (%d) at line %d in %s of %s\n",
+ condition_str, condition, line, function, file);
+ /*
+ * Give the logger a chance to get the message out, just in case
+ * we abort(), or Asterisk crashes due to whatever problem just
+ * happened after we exit ast_assert().
+ */
+ usleep(1);
+ ast_do_crash();
+}
+#endif /* defined(AST_DEVMODE) */
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/main/xmldoc.c
^
|
@@ -29,7 +29,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 375758 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 377509 $")
#include "asterisk/_private.h"
#include "asterisk/paths.h"
@@ -354,7 +354,13 @@
/* Setup color */
if (withcolors) {
- ast_term_color_code(&colorized, colorized_tags[c].colorfg, 0);
+ if (ast_opt_light_background) {
+ /* Turn off *bright* colors */
+ ast_term_color_code(&colorized, colorized_tags[c].colorfg & 0x7f, 0);
+ } else {
+ /* Turn on *bright* colors */
+ ast_term_color_code(&colorized, colorized_tags[c].colorfg | 0x80, 0);
+ }
if (!colorized) {
return NULL;
}
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/pbx/pbx_dundi.c
^
|
@@ -29,7 +29,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 372417 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376657 $")
#include "asterisk/network.h"
#include <sys/ioctl.h>
@@ -3886,7 +3886,6 @@
{
int results;
int x;
- struct ast_module_user *u;
struct dundi_result dr[MAX_RESULTS];
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(number);
@@ -3903,8 +3902,6 @@
return -1;
}
- u = ast_module_user_add(chan);
-
parse = ast_strdupa(num);
AST_STANDARD_APP_ARGS(args, parse);
@@ -3927,8 +3924,6 @@
}
}
- ast_module_user_remove(u);
-
return 0;
}
@@ -3967,7 +3962,6 @@
static int dundi_query_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
- struct ast_module_user *u;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(number);
AST_APP_ARG(context);
@@ -3978,17 +3972,13 @@
struct dundi_result_datastore *drds;
struct ast_datastore *datastore;
- u = ast_module_user_add(chan);
-
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "DUNDIQUERY requires an argument (number)\n");
- ast_module_user_remove(u);
return -1;
}
if (!chan) {
ast_log(LOG_ERROR, "DUNDIQUERY can not be used without a channel!\n");
- ast_module_user_remove(u);
return -1;
}
@@ -4003,7 +3993,6 @@
args.context = "e164";
if (!(drds = ast_calloc(1, sizeof(*drds)))) {
- ast_module_user_remove(u);
return -1;
}
@@ -4012,7 +4001,6 @@
if (!(datastore = ast_datastore_alloc(&dundi_result_datastore_info, buf))) {
drds_destroy(drds);
- ast_module_user_remove(u);
return -1;
}
@@ -4028,8 +4016,6 @@
ast_channel_datastore_add(chan, datastore);
ast_channel_unlock(chan);
- ast_module_user_remove(u);
-
return 0;
}
@@ -4040,7 +4026,6 @@
static int dundi_result_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
- struct ast_module_user *u;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(id);
AST_APP_ARG(resultnum);
@@ -4051,8 +4036,6 @@
struct ast_datastore *datastore;
int res = -1;
- u = ast_module_user_add(chan);
-
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "DUNDIRESULT requires an argument (id and resultnum)\n");
goto finish;
@@ -4107,8 +4090,6 @@
ast_log(LOG_WARNING, "Result number %u is not valid for DUNDi query results for ID %s!\n", num, args.id);
finish:
- ast_module_user_remove(u);
-
return res;
}
@@ -4776,7 +4757,12 @@
static int unload_module(void)
{
pthread_t previous_netthreadid = netthreadid, previous_precachethreadid = precachethreadid, previous_clearcachethreadid = clearcachethreadid;
- ast_module_user_hangup_all();
+
+ ast_cli_unregister_multiple(cli_dundi, ARRAY_LEN(cli_dundi));
+ ast_unregister_switch(&dundi_switch);
+ ast_custom_function_unregister(&dundi_function);
+ ast_custom_function_unregister(&dundi_query_function);
+ ast_custom_function_unregister(&dundi_result_function);
/* Stop all currently running threads */
dundi_shutdown = 1;
@@ -4793,11 +4779,6 @@
pthread_join(previous_clearcachethreadid, NULL);
}
- ast_cli_unregister_multiple(cli_dundi, ARRAY_LEN(cli_dundi));
- ast_unregister_switch(&dundi_switch);
- ast_custom_function_unregister(&dundi_function);
- ast_custom_function_unregister(&dundi_query_function);
- ast_custom_function_unregister(&dundi_result_function);
close(netsocket);
io_context_destroy(io);
sched_context_destroy(sched);
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/pbx/pbx_spool.c
^
|
@@ -28,7 +28,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 374686 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376232 $")
#include <sys/stat.h>
#include <time.h>
@@ -492,7 +492,7 @@
int res;
time_t now = time(NULL);
- if (filename[0] != '/') {
+ if (!strchr(filename, '/')) {
char *fn = ast_alloca(strlen(qdir) + strlen(filename) + 2);
sprintf(fn, "%s/%s", qdir, filename); /* SAFE */
filename = fn;
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/res/res_calendar.c
^
|
@@ -29,7 +29,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378341 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#include "asterisk/_private.h"
#include "asterisk/calendar.h"
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/res/res_fax.c
^
|
@@ -37,7 +37,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 368738 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376087 $")
#include "asterisk/io.h"
#include "asterisk/file.h"
@@ -1018,7 +1018,6 @@
#define GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason) \
do { \
GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason); \
- res = ms = -1; \
} while (0)
#define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason) \
@@ -1084,9 +1083,11 @@
static int disable_t38(struct ast_channel *chan)
{
- int ms;
+ int timeout_ms;
struct ast_frame *frame = NULL;
struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, };
+ struct timeval start;
+ int ms;
ast_debug(1, "Shutting down T.38 on %s\n", chan->name);
if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) {
@@ -1095,20 +1096,19 @@
}
/* wait up to five seconds for negotiation to complete */
- ms = 5000;
-
- while (ms > 0) {
+ timeout_ms = 5000;
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
ms = ast_waitfor(chan, ms);
+
+ if (ms == 0) {
+ break;
+ }
if (ms < 0) {
ast_debug(1, "error while disabling T.38 on channel '%s'\n", chan->name);
return -1;
}
- if (ms == 0) { /* all done, nothing happened */
- ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", chan->name);
- break;
- }
-
if (!(frame = ast_read(chan))) {
return -1;
}
@@ -1136,6 +1136,10 @@
ast_frfree(frame);
}
+ if (ms == 0) { /* all done, nothing happened */
+ ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", chan->name);
+ }
+
return 0;
}
@@ -1151,7 +1155,7 @@
{
int ms;
int timeout = RES_FAX_TIMEOUT;
- int res = 0, chancount;
+ int chancount;
unsigned int expected_frametype = -1;
union ast_frame_subclass expected_framesubclass = { .integer = -1 };
unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED);
@@ -1161,6 +1165,8 @@
struct ast_frame *frame = NULL;
struct ast_channel *c = chan;
unsigned int orig_write_format = 0, orig_read_format = 0;
+ int remaining_time;
+ struct timeval start;
chancount = 1;
@@ -1239,8 +1245,9 @@
ast_debug(5, "channel %s will wait on FAX fd %d\n", chan->name, fax->fd);
/* handle frames for the session */
- ms = 1000;
- while ((res > -1) && (ms > -1) && (timeout > 0)) {
+ remaining_time = timeout;
+ start = ast_tvnow();
+ while (remaining_time > 0) {
struct ast_channel *ready_chan;
int ofd, exception;
@@ -1257,7 +1264,7 @@
GENERIC_FAX_EXEC_SET_VARS(fax, chan, "HANGUP", "remote channel hungup");
c = NULL;
chancount = 0;
- timeout -= (1000 - ms);
+ remaining_time = ast_remaining_ms(start, timeout);
fax->tech->cancel_session(fax);
if (fax->tech->generate_silence) {
fax->tech->generate_silence(fax);
@@ -1326,7 +1333,7 @@
fax->tech->write(fax, frame);
fax->frames_received++;
}
- timeout = RES_FAX_TIMEOUT;
+ start = ast_tvnow();
}
ast_frfree(frame);
} else if (ofd == fax->fd) {
@@ -1343,36 +1350,30 @@
ast_write(chan, frame);
fax->frames_sent++;
ast_frfree(frame);
- timeout = RES_FAX_TIMEOUT;
+ start = ast_tvnow();
} else {
if (ms && (ofd < 0)) {
if ((errno == 0) || (errno == EINTR)) {
- timeout -= (1000 - ms);
- if (timeout <= 0)
+ remaining_time = ast_remaining_ms(start, timeout);
+ if (remaining_time <= 0)
GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
continue;
} else {
ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", chan->name);
GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "error polling data");
- res = ms;
break;
}
} else {
/* nothing happened */
- if (timeout > 0) {
- timeout -= 1000;
- if (timeout <= 0)
- GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
- continue;
- } else {
- ast_log(LOG_WARNING, "channel '%s' timed-out during the FAX transmission.\n", chan->name);
+ remaining_time = ast_remaining_ms(start, timeout);
+ if (remaining_time <= 0) {
GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
break;
}
}
}
}
- ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, ms: %d, res: %d }\n", chan->name, timeout, ms, res);
+ ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", chan->name, timeout, remaining_time);
set_channel_variables(chan, details);
@@ -1407,9 +1408,11 @@
static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
{
- int ms;
+ int timeout_ms;
struct ast_frame *frame = NULL;
struct ast_control_t38_parameters t38_parameters;
+ struct timeval start;
+ int ms;
t38_parameters_ast_to_fax(&details->our_t38_parameters, &our_t38_parameters);
@@ -1421,9 +1424,11 @@
return -1;
}
- ms = 3000;
- while (ms > 0) {
+ timeout_ms = 3000;
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
ms = ast_waitfor(chan, ms);
+
if (ms < 0) {
ast_log(LOG_ERROR, "error while generating CED tone on %s\n", chan->name);
ast_playtones_stop(chan);
@@ -1480,7 +1485,7 @@
ast_debug(1, "Negotiating T.38 for receive on %s\n", chan->name);
/* wait up to five seconds for negotiation to complete */
- ms = 5000;
+ timeout_ms = 5000;
/* set parameters based on the session's parameters */
t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
@@ -1489,13 +1494,15 @@
return -1;
}
- while (ms > 0) {
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
+ int break_loop = 0;
+
ms = ast_waitfor(chan, ms);
if (ms < 0) {
ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
return -1;
}
-
if (ms == 0) { /* all done, nothing happened */
ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", chan->name);
details->caps &= ~AST_FAX_TECH_T38;
@@ -1523,21 +1530,24 @@
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
details->caps &= ~AST_FAX_TECH_AUDIO;
report_fax_status(chan, details, "T.38 Negotiated");
- ms = 0;
+ break_loop = 1;
break;
case AST_T38_REFUSED:
ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", chan->name);
details->caps &= ~AST_FAX_TECH_T38;
- ms = 0;
+ break_loop = 1;
break;
default:
ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", chan->name);
details->caps &= ~AST_FAX_TECH_T38;
- ms = 0;
+ break_loop = 1;
break;
}
}
ast_frfree(frame);
+ if (break_loop) {
+ break;
+ }
}
/* if T.38 was negotiated, we are done initializing */
@@ -1805,9 +1815,11 @@
static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
{
- int ms;
+ int timeout_ms;
struct ast_frame *frame = NULL;
struct ast_control_t38_parameters t38_parameters;
+ struct timeval start;
+ int ms;
t38_parameters_ast_to_fax(&details->our_t38_parameters, &our_t38_parameters);
@@ -1817,7 +1829,7 @@
*
* 10500 is enough time for 3 CNG tones
*/
- ms = 10500;
+ timeout_ms = 10500;
/* don't send any audio if we've already received a T.38 reinvite */
if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) {
@@ -1827,8 +1839,11 @@
}
}
- while (ms > 0) {
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
+ int break_loop = 0;
ms = ast_waitfor(chan, ms);
+
if (ms < 0) {
ast_log(LOG_ERROR, "error while generating CNG tone on %s\n", chan->name);
ast_playtones_stop(chan);
@@ -1865,13 +1880,16 @@
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
details->caps &= ~AST_FAX_TECH_AUDIO;
report_fax_status(chan, details, "T.38 Negotiated");
- ms = 0;
+ break_loop = 1;
break;
default:
break;
}
}
ast_frfree(frame);
+ if (break_loop) {
+ break;
+ }
}
ast_playtones_stop(chan);
@@ -1885,7 +1903,7 @@
ast_debug(1, "Negotiating T.38 for send on %s\n", chan->name);
/* wait up to five seconds for negotiation to complete */
- ms = 5000;
+ timeout_ms = 5000;
/* set parameters based on the session's parameters */
t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
@@ -1894,13 +1912,15 @@
return -1;
}
- while (ms > 0) {
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
+ int break_loop = 0;
+
ms = ast_waitfor(chan, ms);
if (ms < 0) {
ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
return -1;
}
-
if (ms == 0) { /* all done, nothing happened */
ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", chan->name);
details->caps &= ~AST_FAX_TECH_T38;
@@ -1928,21 +1948,24 @@
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
details->caps &= ~AST_FAX_TECH_AUDIO;
report_fax_status(chan, details, "T.38 Negotiated");
- ms = 0;
+ break_loop = 1;
break;
case AST_T38_REFUSED:
ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", chan->name);
details->caps &= ~AST_FAX_TECH_T38;
- ms = 0;
+ break_loop = 1;
break;
default:
ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", chan->name);
details->caps &= ~AST_FAX_TECH_T38;
- ms = 0;
+ break_loop = 1;
break;
}
}
ast_frfree(frame);
+ if (break_loop) {
+ break;
+ }
}
/* if T.38 was negotiated, we are done initializing */
@@ -1958,15 +1981,17 @@
return -1;
}
- ms = 3500;
- while (ms > 0) {
+ timeout_ms = 3500;
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
+ int break_loop = 0;
+
ms = ast_waitfor(chan, ms);
if (ms < 0) {
ast_log(LOG_ERROR, "error while generating second CNG tone on %s\n", chan->name);
ast_playtones_stop(chan);
return -1;
}
-
if (ms == 0) { /* all done, nothing happened */
break;
}
@@ -1997,13 +2022,16 @@
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
details->caps &= ~AST_FAX_TECH_AUDIO;
report_fax_status(chan, details, "T.38 Negotiated");
- ms = 0;
+ break_loop = 1;
break;
default:
break;
}
}
ast_frfree(frame);
+ if (break_loop) {
+ break;
+ }
}
ast_playtones_stop(chan);
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/res/res_jabber.c
^
|
@@ -38,7 +38,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378341 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378781 $")
#include <ctype.h>
#include <iksemel.h>
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/res/res_monitor.c
^
|
@@ -29,7 +29,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 366167 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376389 $")
#include <sys/stat.h>
#include <libgen.h>
@@ -451,24 +451,28 @@
}
if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) {
- if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) {
- snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base);
- if (ast_fileexists(filename, NULL, NULL) > 0) {
- ast_filedelete(filename, NULL);
+ if (chan->monitor->read_stream) {
+ if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) {
+ snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base);
+ if (ast_fileexists(filename, NULL, NULL) > 0) {
+ ast_filedelete(filename, NULL);
+ }
+ ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format);
+ } else {
+ ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename);
}
- ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format);
- } else {
- ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename);
}
- if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) {
- snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base);
- if (ast_fileexists(filename, NULL, NULL) > 0) {
- ast_filedelete(filename, NULL);
+ if (chan->monitor->write_stream) {
+ if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) {
+ snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base);
+ if (ast_fileexists(filename, NULL, NULL) > 0) {
+ ast_filedelete(filename, NULL);
+ }
+ ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format);
+ } else {
+ ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename);
}
- ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format);
- } else {
- ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename);
}
}
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/res/res_srtp.c
^
|
@@ -37,7 +37,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 366880 $")
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 377256 $")
#include <srtp/srtp.h>
@@ -383,6 +383,8 @@
retry++;
ao2_iterator_destroy(&it);
goto tryagain;
+ } else {
+ srtp->session = NULL;
}
ao2_t_ref(policy, -1, "Unreffing first policy after srtp_create failed");
}
@@ -437,6 +439,8 @@
/* Any failures after this point can use ast_srtp_destroy to destroy the instance */
if (srtp_create(&temp->session, &policy->sp) != err_status_ok) {
+ /* Session either wasn't created or was created and dealloced. */
+ temp->session = NULL;
ast_srtp_destroy(temp);
return -1;
}
|
[-]
[+]
|
Added |
asterisk-1.8.20.0.tar.xz/tests/test_astobj2_thrash.c
^
|
@@ -0,0 +1,353 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2012, David M. Lee, II
+ *
+ * David M. Lee, II <dlee@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*
+ *! \file \brief Thrash a astobj2 container, for fun and profit.
+ *
+ * \author\verbatim David M. Lee, II <dlee@digium.com> \endverbatim
+ *
+ * Inspired by the original hashtest2.c by Steve Murphy <murf@digium.com>. This test runs
+ * several threads manipulatings a concurrent astobj2 container to see if they maintain
+ * consistency. While the tests attempt to check consistency and error normally, threading
+ * errors often result in segfaults.
+ * \ingroup tests
+ */
+
+/*** MODULEINFO
+ <depend>TEST_FRAMEWORK</depend>
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376306 $")
+#include <pthread.h>
+#include "asterisk/astobj2.h"
+#include "asterisk/hashtab.h"
+#include "asterisk/lock.h"
+#include "asterisk/module.h"
+#include "asterisk/test.h"
+#include "asterisk/time.h"
+#include "asterisk/utils.h"
+
+#define MAX_HASH_ENTRIES 15000
+#define MAX_TEST_SECONDS 60
+
+struct hash_test {
+ /*! Unit under test */
+ struct ao2_container *to_be_thrashed;
+ /*! Number of entries to insert in the grow thread. */
+ int max_grow;
+ /*! Number of enteries added by the grow thread. */
+ int grow_count;
+ /*! Entries preloaded into the hashtab; to be deleted by the shrink thread */
+ int preload;
+ /*! When to give up on the tests */
+ struct timeval deadline;
+};
+
+static int alloc_count = 0;
+
+static int is_timed_out(struct hash_test const *data) {
+ return ast_tvdiff_us(data->deadline, ast_tvnow()) < 0;
+}
+
+/*! /brief Free test element */
+static void ht_delete(void *obj)
+{
+ ast_atomic_fetchadd_int(&alloc_count, -1);
+}
+
+/*! /brief Create test element */
+static char *ht_new(int i)
+{
+ const int buflen = 12;
+ char *keybuf = ao2_alloc(buflen, ht_delete);
+ int needed;
+ if (keybuf == NULL) {
+ return NULL;
+ }
+ needed = snprintf(keybuf, buflen, "key%08x", i);
+ ast_atomic_fetchadd_int(&alloc_count, 1);
+ ast_assert(needed + 1 <= buflen);
+ return keybuf;
+}
+
+/*! /brief Grow the hash data as specified */
+static void *hash_test_grow(void *d)
+{
+ struct hash_test *data = d;
+ int i;
+
+ for (i = 0; i < data->max_grow; ++i) {
+ char *ht;
+ if (is_timed_out(data)) {
+ printf("Growth timed out at %d\n", i);
+ return "Growth timed out";
+ }
+ ht = ht_new(i);
+ if (ht == NULL) {
+ return "Allocation failed";
+ }
+ ao2_link(data->to_be_thrashed, ht);
+ ao2_ref(ht, -1);
+ ast_atomic_fetchadd_int(&data->grow_count, 1);
+ }
+ return NULL;
+}
+
+/*! Randomly lookup data in the hash */
+static void *hash_test_lookup(void *d)
+{
+ struct hash_test *data = d;
+ int max;
+ unsigned seed = time(NULL);
+
+ /* ast_atomic_fetchadd_int provide a memory fence so that the optimizer doesn't
+ * optimize away reads.
+ */
+ while ((max = ast_atomic_fetchadd_int(&data->grow_count, 0)) < data->max_grow) {
+ int i;
+ char *obj;
+ char *from_ao2;
+
+ if (is_timed_out(data)) {
+ return "Lookup timed out";
+ }
+
+ if (max == 0) {
+ /* No data yet; yield and try again */
+ sched_yield();
+ continue;
+ }
+
+ /* Randomly lookup one object from the hash */
+ i = rand_r(&seed) % max;
+ obj = ht_new(i);
+ if (obj == NULL) {
+ return "Allocation failed";
+ }
+ from_ao2 = ao2_find(data->to_be_thrashed, obj, OBJ_POINTER);
+ ao2_ref(obj, -1);
+ ao2_ref(from_ao2, -1);
+ if (from_ao2 == NULL) {
+ return "Key unexpectedly missing";
+ }
+ }
+
+ return NULL;
+}
+
+/*! Delete entries from the hash */
+static void *hash_test_shrink(void *d)
+{
+ const struct hash_test *data = d;
+ int i;
+
+ for (i = 1; i < data->preload; ++i) {
+ char *obj = ht_new(-i);
+ char *from_ao2;
+
+ if (obj == NULL) {
+ return "Allocation failed";
+ }
+ from_ao2 = ao2_find(data->to_be_thrashed, obj, OBJ_UNLINK | OBJ_POINTER);
+
+ ao2_ref(obj, -1);
+ if (from_ao2) {
+ ao2_ref(from_ao2, -1);
+ } else {
+ return "Could not find object to delete";
+ }
+
+ if (is_timed_out(data)) {
+ return "Shrink timed out";
+ }
+ }
+
+ return NULL;
+}
+
+/*! ao2_callback for hash_test_count */
+static int increment_count(void *obj, void *arg, int flags) {
+ char *ht = obj;
+ int *count = arg;
+ if (strncmp(ht, "key0", 4) == 0) {
+ ++(*count);
+ }
+ return 0;
+}
+
+/*! Continuously iterate through all the entries in the hash */
+static void *hash_test_count(void *d)
+{
+ const struct hash_test *data = d;
+ int count = 0;
+ int last_count = 0;
+
+ while (count < data->max_grow) {
+ last_count = count;
+ count = 0;
+ ao2_callback(data->to_be_thrashed, OBJ_MULTIPLE, increment_count, &count);
+
+ if (last_count == count) {
+ /* Allow other threads to run. */
+ sched_yield();
+ } else if (last_count > count) {
+ /* Make sure the ao2 container never shrinks */
+ return "ao2 container unexpectedly shrank";
+ }
+
+ if (is_timed_out(data)) {
+ return "Count timed out";
+ }
+ }
+
+ /* Successfully iterated over all of the expected elements */
+ return NULL;
+}
+
+static int hash_string(const void *obj, const int flags)
+{
+ return ast_hashtab_hash_string_nocase(obj);
+}
+
+static int compare_strings(void *lhs, void *rhs, int flags)
+{
+ const char *lhs_str = lhs;
+ const char *rhs_str = rhs;
+ if (strcasecmp(lhs_str, rhs_str) == 0) {
+ return CMP_MATCH | CMP_STOP;
+ } else {
+ return 0;
+ }
+}
+
+AST_TEST_DEFINE(hash_test)
+{
+ enum ast_test_result_state res = AST_TEST_PASS;
+ struct hash_test data = {};
+ pthread_t grow_thread, count_thread, lookup_thread, shrink_thread;
+ void *thread_results;
+ int i;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "thrash";
+ info->category = "/main/astobj2/";
+ info->summary = "Testing astobj2 container concurrency";
+ info->description = "Test astobj2 container concurrency correctness.";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ ast_test_status_update(test, "Executing hash concurrency test...\n");
+ data.preload = MAX_HASH_ENTRIES / 2;
+ data.max_grow = MAX_HASH_ENTRIES - data.preload;
+ data.deadline = ast_tvadd(ast_tvnow(), ast_tv(MAX_TEST_SECONDS, 0));
+ data.to_be_thrashed = ao2_container_alloc(MAX_HASH_ENTRIES / 100, hash_string,
+ compare_strings);
+
+ if (data.to_be_thrashed == NULL) {
+ ast_test_status_update(test, "Allocation failed\n");
+ /* Nothing needs to be freed; early return is fine */
+ return AST_TEST_FAIL;
+ }
+
+ /* preload with data to delete */
+ for (i = 1; i < data.preload; ++i) {
+ char *ht = ht_new(-i);
+ if (ht == NULL) {
+ ast_test_status_update(test, "Allocation failed\n");
+ ao2_ref(data.to_be_thrashed, -1);
+ return AST_TEST_FAIL;
+ }
+ ao2_link(data.to_be_thrashed, ht);
+ ao2_ref(ht, -1);
+ }
+
+ /* add data.max_grow entries to the ao2 container */
+ ast_pthread_create(&grow_thread, NULL, hash_test_grow, &data);
+ /* continually count the keys added by the grow thread */
+ ast_pthread_create(&count_thread, NULL, hash_test_count, &data);
+ /* continually lookup keys added by the grow thread */
+ ast_pthread_create(&lookup_thread, NULL, hash_test_lookup, &data);
+ /* delete all keys preloaded into the ao2 container */
+ ast_pthread_create(&shrink_thread, NULL, hash_test_shrink, &data);
+
+ pthread_join(grow_thread, &thread_results);
+ if (thread_results != NULL) {
+ ast_test_status_update(test, "Growth thread failed: %s\n",
+ (char *)thread_results);
+ res = AST_TEST_FAIL;
+ }
+
+ pthread_join(count_thread, &thread_results);
+ if (thread_results != NULL) {
+ ast_test_status_update(test, "Count thread failed: %s\n",
+ (char *)thread_results);
+ res = AST_TEST_FAIL;
+ }
+
+ pthread_join(lookup_thread, &thread_results);
+ if (thread_results != NULL) {
+ ast_test_status_update(test, "Lookup thread failed: %s\n",
+ (char *)thread_results);
+ res = AST_TEST_FAIL;
+ }
+
+ pthread_join(shrink_thread, &thread_results);
+ if (thread_results != NULL) {
+ ast_test_status_update(test, "Shrink thread failed: %s\n",
+ (char *)thread_results);
+ res = AST_TEST_FAIL;
+ }
+
+ if (ao2_container_count(data.to_be_thrashed) != data.max_grow) {
+ ast_test_status_update(test,
+ "Invalid ao2 container size. Expected: %d, Actual: %d\n",
+ data.max_grow, ao2_container_count(data.to_be_thrashed));
+ res = AST_TEST_FAIL;
+ }
+
+ ao2_ref(data.to_be_thrashed, -1);
+
+ /* check for object leaks */
+ if (ast_atomic_fetchadd_int(&alloc_count, 0) != 0) {
+ ast_test_status_update(test, "Leaked %d objects!\n",
+ ast_atomic_fetchadd_int(&alloc_count, 0));
+ res = AST_TEST_FAIL;
+ }
+
+ return res;
+}
+
+static int unload_module(void)
+{
+ AST_TEST_UNREGISTER(hash_test);
+ return 0;
+}
+
+static int load_module(void)
+{
+ AST_TEST_REGISTER(hash_test);
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "astobj2 container thrash test");
|
[-]
[+]
|
Added |
asterisk-1.8.20.0.tar.xz/tests/test_hashtab_thrash.c
^
|
@@ -0,0 +1,321 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2012, David M. Lee, II
+ *
+ * David M. Lee, II <dlee@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*
+ *! \file \brief Thrash a hash table, for fun and profit.
+ *
+ * \author\verbatim David M. Lee, II <dlee@digium.com> \endverbatim
+ *
+ * Inspired by the original hashtest.c by Steve Murphy <murf@digium.com>. This test runs
+ * several threads manipulatings a concurrent hastab to see if they maintain
+ * consistency. While the tests attempt to check consistency and error normally, threading
+ * errors often result in segfaults.
+ * \ingroup tests
+ */
+
+/*** MODULEINFO
+ <depend>TEST_FRAMEWORK</depend>
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 376306 $")
+#include <pthread.h>
+#include "asterisk/hashtab.h"
+#include "asterisk/lock.h"
+#include "asterisk/module.h"
+#include "asterisk/test.h"
+#include "asterisk/time.h"
+#include "asterisk/utils.h"
+
+#define MAX_HASH_ENTRIES 30000
+#define MAX_TEST_SECONDS 60
+
+struct hash_test {
+ /*! Unit under test */
+ struct ast_hashtab *to_be_thrashed;
+ /*! Number of entries to insert in the grow thread. */
+ int max_grow;
+ /*! Number of enteries added by the grow thread. */
+ int grow_count;
+ /*! Entries preloaded into the hashtab; to be deleted by the shrink thread */
+ int preload;
+ /*! When to give up on the tests */
+ struct timeval deadline;
+};
+
+static int is_timed_out(struct hash_test const *data) {
+ return ast_tvdiff_us(data->deadline, ast_tvnow()) < 0;
+}
+
+/*! /brief Create test element */
+static char *ht_new(int i)
+{
+ const int buflen = 12;
+ char *keybuf = ast_malloc(buflen);
+ int needed;
+ if (keybuf == NULL) {
+ return NULL;
+ }
+ needed = snprintf(keybuf, buflen, "key%08x", i);
+ ast_assert(needed + 1 <= buflen);
+ return keybuf;
+}
+
+/*! /brief Free test element */
+static void ht_delete(void *obj)
+{
+ ast_free(obj);
+}
+
+/*! /brief Grow the hash data as specified */
+static void *hash_test_grow(void *d)
+{
+ struct hash_test *data = d;
+ int i;
+
+ for (i = 0; i < data->max_grow; ++i) {
+ char *obj;
+ if (is_timed_out(data)) {
+ return "Growth timed out";
+ }
+ obj = ht_new(i);
+ if (obj == NULL) {
+ return "Allocation failed";
+ }
+ ast_hashtab_insert_immediate(data->to_be_thrashed, obj);
+ ast_atomic_fetchadd_int(&data->grow_count, 1);
+ }
+ return NULL;
+}
+
+/*! Randomly lookup data in the hash */
+static void *hash_test_lookup(void *d)
+{
+ struct hash_test *data = d;
+ int max;
+ unsigned seed = time(NULL);
+
+ /* ast_atomic_fetchadd_int provide a memory fence so that the optimizer doesn't
+ * optimize away reads.
+ */
+ while ((max = ast_atomic_fetchadd_int(&data->grow_count, 0)) < data->max_grow) {
+ int i;
+ char *obj;
+ int is_in_hashtab;
+
+ if (is_timed_out(data)) {
+ return "Lookup timed out";
+ }
+
+ if (max == 0) {
+ /* No data yet; yield and try again */
+ sched_yield();
+ continue;
+ }
+
+ /* Randomly lookup one object from the hash */
+ i = rand_r(&seed) % max;
+ obj = ht_new(i);
+ if (obj == NULL) {
+ return "Allocation failed.";
+ }
+ is_in_hashtab = (ast_hashtab_lookup(data->to_be_thrashed, obj) != NULL);
+ ht_delete(obj);
+ if (!is_in_hashtab) {
+ return "key unexpectedly missing";
+ }
+ }
+
+ return NULL;
+}
+
+/*! Delete entries from the hash */
+static void *hash_test_shrink(void *d)
+{
+ const struct hash_test *data = d;
+ int i;
+
+ for (i = 1; i < data->preload; ++i) {
+ char *obj = ht_new(-i);
+ char *from_hashtab;
+ int deleted;
+
+ if (obj == NULL) {
+ return "Allocation failed";
+ }
+ from_hashtab = ast_hashtab_remove_object_via_lookup(data->to_be_thrashed, obj);
+ deleted = from_hashtab != NULL;
+
+ ht_delete(obj);
+ ht_delete(from_hashtab);
+ if (!deleted) {
+ return "could not delete object";
+ }
+ if (is_timed_out(data)) {
+ return "Shrink timed out";
+ }
+ }
+ return NULL;
+}
+
+/*! Continuously iterate through all the entries in the hash */
+static void *hash_test_count(void *d)
+{
+ const struct hash_test *data = d;
+ int count = 0;
+ int last_count = 0;
+
+ while (count < data->max_grow) {
+ struct ast_hashtab_iter *it = ast_hashtab_start_write_traversal(data->to_be_thrashed);
+ char *ht = ast_hashtab_next(it);
+ last_count = count;
+ count = 0;
+ while (ht) {
+ /* only count keys added by grow thread */
+ if (strncmp(ht, "key0", 4) == 0) {
+ ++count;
+ }
+ ht = ast_hashtab_next(it);
+ }
+ ast_hashtab_end_traversal(it);
+
+ if (last_count == count) {
+ /* Allow other threads to run. */
+ sched_yield();
+ } else if (last_count > count) {
+ /* Make sure the hashtable never shrinks */
+ return "hashtab unexpectedly shrank";
+ }
+
+ if (is_timed_out(data)) {
+ return "Count timed out";
+ }
+ }
+
+ /* Successfully iterated over all of the expected elements */
+ return NULL;
+}
+
+AST_TEST_DEFINE(hash_test)
+{
+ enum ast_test_result_state res = AST_TEST_PASS;
+ struct hash_test data = {};
+ pthread_t grow_thread, count_thread, lookup_thread, shrink_thread;
+ void *thread_results;
+ int i;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "thrash";
+ info->category = "/main/hashtab/";
+ info->summary = "Testing hashtab concurrency";
+ info->description = "Test hashtab concurrency correctness.";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ ast_test_status_update(test, "Executing hash concurrency test...\n");
+ data.preload = MAX_HASH_ENTRIES / 2;
+ data.max_grow = MAX_HASH_ENTRIES - data.preload;
+ data.deadline = ast_tvadd(ast_tvnow(), ast_tv(MAX_TEST_SECONDS, 0));
+ data.to_be_thrashed = ast_hashtab_create(MAX_HASH_ENTRIES / 100,
+ ast_hashtab_compare_strings_nocase, ast_hashtab_resize_java,
+ ast_hashtab_newsize_java, ast_hashtab_hash_string_nocase, 1);
+
+ if (data.to_be_thrashed == NULL) {
+ ast_test_status_update(test, "Allocation failed\n");
+ /* Nothing needs to be freed; early return is fine */
+ return AST_TEST_FAIL;
+ }
+
+
+ /* preload with data to delete */
+ for (i = 1; i < data.preload; ++i) {
+ char *obj = ht_new(-i);
+ if (obj == NULL) {
+ ast_test_status_update(test, "Allocation failed\n");
+ ast_hashtab_destroy(data.to_be_thrashed, ht_delete);
+ return AST_TEST_FAIL;
+ }
+ ast_hashtab_insert_immediate(data.to_be_thrashed, obj);
+ }
+
+ /* add data.max_grow entries to the hashtab */
+ ast_pthread_create(&grow_thread, NULL, hash_test_grow, &data);
+ /* continually count the keys added by the grow thread */
+ ast_pthread_create(&count_thread, NULL, hash_test_count, &data);
+ /* continually lookup keys added by the grow thread */
+ ast_pthread_create(&lookup_thread, NULL, hash_test_lookup, &data);
+ /* delete all keys preloaded into the hashtab */
+ ast_pthread_create(&shrink_thread, NULL, hash_test_shrink, &data);
+
+ pthread_join(grow_thread, &thread_results);
+ if (thread_results != NULL) {
+ ast_test_status_update(test, "Growth thread failed: %s\n",
+ (char *)thread_results);
+ res = AST_TEST_FAIL;
+ }
+
+ pthread_join(count_thread, &thread_results);
+ if (thread_results != NULL) {
+ ast_test_status_update(test, "Count thread failed: %s\n",
+ (char *)thread_results);
+ res = AST_TEST_FAIL;
+ }
+
+ pthread_join(lookup_thread, &thread_results);
+ if (thread_results != NULL) {
+ ast_test_status_update(test, "Lookup thread failed: %s\n",
+ (char *)thread_results);
+ res = AST_TEST_FAIL;
+ }
+
+ pthread_join(shrink_thread, &thread_results);
+ if (thread_results != NULL) {
+ ast_test_status_update(test, "Shrink thread failed: %s\n",
+ (char *)thread_results);
+ res = AST_TEST_FAIL;
+ }
+
+ if (ast_hashtab_size(data.to_be_thrashed) != data.max_grow) {
+ ast_test_status_update(test,
+ "Invalid hashtab size. Expected: %d, Actual: %d\n",
+ data.max_grow, ast_hashtab_size(data.to_be_thrashed));
+ res = AST_TEST_FAIL;
+ }
+
+ ast_hashtab_destroy(data.to_be_thrashed, ht_delete);
+ return res;
+}
+
+static int unload_module(void)
+{
+ AST_TEST_UNREGISTER(hash_test);
+ return 0;
+}
+
+static int load_module(void)
+{
+ AST_TEST_REGISTER(hash_test);
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Hash test");
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/utils/Makefile
^
|
@@ -88,7 +88,7 @@
rm -f *.s *.i
rm -f md5.c strcompat.c ast_expr2.c ast_expr2.h ast_expr2f.c pbx_ael.c pval.c hashtab.c lock.c
rm -f aelparse.c aelbison.c conf2ael
- rm -f utils.c strings.c threadstorage.c sha1.c astobj2.c hashtest2 hashtest refcounter
+ rm -f utils.c strings.c threadstorage.c sha1.c astobj2.c refcounter
md5.c: $(ASTTOPDIR)/main/md5.c
$(ECHO_PREFIX) echo " [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@"
@@ -173,11 +173,6 @@
$(ECHO_PREFIX) echo " [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@"
$(CMD_PREFIX) cp "$<" "$@"
-hashtest2.o: _ASTCFLAGS+=-O0
-hashtest2: hashtest2.o md5.o lock.o utils.o strings.o astobj2.o sha1.o strcompat.o threadstorage.o clicompat.o poll.o
-
-hashtest: hashtest.o md5.o hashtab.o lock.o utils.o strings.o sha1.o strcompat.o threadstorage.o clicompat.o poll.o
-hashtest.o: _ASTCFLAGS+=-O0
refcounter: refcounter.o md5.o hashtab.o lock.o utils.o strings.o sha1.o strcompat.o threadstorage.o clicompat.o poll.o
refcounter.o: _ASTCFLAGS+=-O0
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/utils/extconf.c
^
|
@@ -153,6 +153,7 @@
#define LOG_DTMF __LOG_DTMF, _A_
/* lock.h */
+#define _ASTERISK_LOCK_H /* A small indication that this is horribly wrong. */
#ifndef HAVE_MTX_PROFILE
#define __MTX_PROF(a) return pthread_mutex_lock((a))
|
[-]
[+]
|
Changed |
asterisk-1.8.20.0.tar.xz/utils/utils.xml
^
|
@@ -24,14 +24,6 @@
<defaultenabled>no</defaultenabled>
<support_level>extended</support_level>
</member>
- <member name="hashtest">
- <defaultenabled>no</defaultenabled>
- <support_level>extended</support_level>
- </member>
- <member name="hashtest2">
- <defaultenabled>no</defaultenabled>
- <support_level>extended</support_level>
- </member>
<member name="muted">
<defaultenabled>no</defaultenabled>
<support_level>extended</support_level>
|