Merge "res_pjsip_pubsub: Prune subs with reliable transports at startup"
authorGeorge Joseph <gjoseph@digium.com>
Thu, 1 Feb 2018 17:26:49 +0000 (11:26 -0600)
committerGerrit Code Review <gerrit2@gerrit.digium.api>
Thu, 1 Feb 2018 17:26:49 +0000 (11:26 -0600)
19 files changed:
CHANGES
README.md
apps/app_voicemail.c
configs/samples/modules.conf.sample
configure
configure.ac
contrib/scripts/install_prereq
include/asterisk/autoconfig.h.in
include/asterisk/file.h
include/asterisk/lock.h
include/asterisk/pbx.h
main/Makefile
main/loader.c
main/pbx_variables.c
main/utils.c
res/res_pjsip_registrar.c
res/res_pjsip_registrar_expire.c [deleted file]
res/res_pjsip_session.c
utils/check_expr.c

diff --git a/CHANGES b/CHANGES
index 8caec82..b9d8032 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -54,6 +54,11 @@ res_pjsip
  * A new AMI action, PJSIPShowContacts, has been added which displays information
    about all configured PJSIP Contacts.
 
+res_pjsip_registrar_expire
+------------------
+ * The res_pjsip_registrar_expire module has been removed.  The functionality has
+   been moved into res_pjsip_registrar.
+
 cdr_syslog
 ------------------
  * The cdr_syslog module is now deprecated and by default it is no longer
index 153c4f3..10158b3 100644 (file)
--- a/README.md
+++ b/README.md
@@ -69,7 +69,7 @@ list of new features in this version of Asterisk, see the [CHANGES] file.
 
   Ensure that your system contains a compatible compiler and development
 libraries.  Asterisk requires either the GNU Compiler Collection (GCC) version
-3.0 or higher, or a compiler that supports the C99 specification and some of
+4.1 or higher, or a compiler that supports the C99 specification and some of
 the gcc language extensions.  In addition, your system needs to have the C
 library headers available, and the headers and libraries for ncurses.
 
index 4853a53..72e3e59 100644 (file)
@@ -3499,7 +3499,7 @@ static struct vm_state *get_vm_state_by_imapuser(const char *user, int interacti
        if (interactive) {
                struct vm_state *vms;
                pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
-               if ((vms = pthread_getspecific(ts_vmstate.key)) && vms->imapuser && !strcmp(vms->imapuser, user)) {
+               if ((vms = pthread_getspecific(ts_vmstate.key)) && !strcmp(vms->imapuser, user)) {
                        return vms;
                }
        }
@@ -3513,10 +3513,6 @@ static struct vm_state *get_vm_state_by_imapuser(const char *user, int interacti
                if (vlist->vms->imapversion != imapversion) {
                        continue;
                }
-               if (!vlist->vms->imapuser) {
-                       ast_debug(3, "error: imapuser is NULL for %s\n", user);
-                       continue;
-               }
 
                if (!strcmp(vlist->vms->imapuser, user) && (interactive == 2 || vlist->vms->interactive == interactive)) {
                        AST_LIST_UNLOCK(&vmstates);
@@ -3539,7 +3535,7 @@ static struct vm_state *get_vm_state_by_mailbox(const char *mailbox, const char
        if (interactive) {
                struct vm_state *vms;
                pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
-               if ((vms = pthread_getspecific(ts_vmstate.key)) && vms->username && vms->context &&
+               if ((vms = pthread_getspecific(ts_vmstate.key)) &&
                    !strcmp(vms->username,mailbox) && !strcmp(vms->context, local_context)) {
                        return vms;
                }
@@ -3554,10 +3550,6 @@ static struct vm_state *get_vm_state_by_mailbox(const char *mailbox, const char
                if (vlist->vms->imapversion != imapversion) {
                        continue;
                }
-               if (!vlist->vms->username || !vlist->vms->context) {
-                       ast_debug(3, "error: username is NULL for %s\n", mailbox);
-                       continue;
-               }
 
                ast_debug(3, "comparing mailbox %s@%s (i=%d) to vmstate mailbox %s@%s (i=%d)\n", mailbox, local_context, interactive, vlist->vms->username, vlist->vms->context, vlist->vms->interactive);
 
index 38e33e1..431a0a8 100644 (file)
@@ -29,12 +29,7 @@ autoload=yes
 ; If you want you can combine with preload
 ; preload-require = res_odbc.so
 ;
-; If you want, load the GTK console right away.
-;
-noload => pbx_gtkconsole.so
-;load => pbx_gtkconsole.so
-;
-load => res_musiconhold.so
+;load => res_musiconhold.so
 ;
 ; Load one of: chan_oss, alsa, or console (portaudio).
 ; By default, load chan_oss only (automatically).
index 867643e..f6e83d9 100755 (executable)
--- a/configure
+++ b/configure
@@ -17893,8 +17893,8 @@ fi
 done
 
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiler atomic operations" >&5
-$as_echo_n "checking for compiler atomic operations... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiler sync operations" >&5
+$as_echo_n "checking for compiler sync operations... " >&6; }
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -17909,6 +17909,7 @@ _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
+ax_cv_have_gcc_atomics=1
 
 $as_echo "#define HAVE_GCC_ATOMICS 1" >>confdefs.h
 
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiler atomic operations" >&5
+$as_echo_n "checking for compiler atomic operations... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+int foo1; int foo2 = __atomic_fetch_add(&foo1, 1, __ATOMIC_RELAXED);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ax_cv_have_c_atomics=1
+
+$as_echo "#define HAVE_C_ATOMICS 1" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+if test -z $ax_cv_have_c_atomics$ax_cv_have_gcc_atomics; then
+       as_fn_error $? "*** Atomic operations are not supported by your compiler." "$LINENO" 5
+fi
+
 # glibc, AFAIK, is the only C library that makes printing a NULL to a string safe.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if your system printf is NULL-safe." >&5
 $as_echo_n "checking if your system printf is NULL-safe.... " >&6; }
@@ -19330,17 +19363,6 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 
 
-ac_fn_c_check_header_mongrel "$LINENO" "libkern/OSAtomic.h" "ac_cv_header_libkern_OSAtomic_h" "$ac_includes_default"
-if test "x$ac_cv_header_libkern_OSAtomic_h" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_OSX_ATOMICS 1
-_ACEOF
-
-fi
-
-
-
 # The cast to long int works around a bug in the HP C Compiler
 # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
 # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
index c590c6b..4b91883 100644 (file)
@@ -1,12 +1,4 @@
-# Process this file with autoconf to produce a configure script.
-#
-# Make sure we use autoconf 2.60 to generate the "configure" script,
-# in case we want to commit it. Other than that, version 2.59 is
-# perfectly fine for our purposes, so people who want to modify
-# this file just have to remember to set the AC_PREREQ argument
-# to something that suits their needs.
-
-AC_PREREQ(2.60)
+AC_PREREQ(2.60a)
 
 AC_INIT([asterisk], [trunk], [https://issues.asterisk.org])
 
@@ -1070,14 +1062,28 @@ AC_LINK_IFELSE(
 # for FreeBSD thr_self
 AC_CHECK_HEADERS([sys/thr.h])
 
-AC_MSG_CHECKING(for compiler atomic operations)
+AC_MSG_CHECKING(for compiler sync operations)
 AC_LINK_IFELSE(
 [AC_LANG_PROGRAM([], [int foo1; int foo2 = __sync_fetch_and_add(&foo1, 1);])],
 AC_MSG_RESULT(yes)
-AC_DEFINE([HAVE_GCC_ATOMICS], 1, [Define to 1 if your GCC C compiler provides atomic operations.]),
+ax_cv_have_gcc_atomics=1
+AC_DEFINE([HAVE_GCC_ATOMICS], 1, [Define to 1 if your GCC C compiler provides __sync atomic operations.]),
+AC_MSG_RESULT(no)
+)
+
+AC_MSG_CHECKING(for compiler atomic operations)
+AC_LINK_IFELSE(
+[AC_LANG_PROGRAM([], [int foo1; int foo2 = __atomic_fetch_add(&foo1, 1, __ATOMIC_RELAXED);])],
+AC_MSG_RESULT(yes)
+ax_cv_have_c_atomics=1
+AC_DEFINE([HAVE_C_ATOMICS], 1, [Define to 1 if your C compiler provides __atomic operations.]),
 AC_MSG_RESULT(no)
 )
 
+if test -z $ax_cv_have_c_atomics$ax_cv_have_gcc_atomics; then
+       AC_MSG_ERROR([*** Atomic operations are not supported by your compiler.])
+fi
+
 # glibc, AFAIK, is the only C library that makes printing a NULL to a string safe.
 AC_MSG_CHECKING([if your system printf is NULL-safe.])
 AC_RUN_IFELSE(
@@ -1405,9 +1411,6 @@ AST_C_DEFINE_CHECK([RTLD_NOLOAD], [RTLD_NOLOAD], [dlfcn.h])
 
 AST_C_DEFINE_CHECK([IP_MTU_DISCOVER], [IP_MTU_DISCOVER], [netinet/in.h])
 
-AC_CHECK_HEADER([libkern/OSAtomic.h],
-                [AC_DEFINE_UNQUOTED([HAVE_OSX_ATOMICS], 1, [Define to 1 if OSX atomic operations are supported.])])
-
 AC_CHECK_SIZEOF([int])
 AC_CHECK_SIZEOF([long])
 AC_CHECK_SIZEOF([long long])
index 86b9a4d..19da358 100755 (executable)
@@ -34,11 +34,21 @@ PACKAGES_DEBIAN="$PACKAGES_DEBIAN wget subversion"
 # Asterisk: for ./configure --with-pjproject-bundled:
 PACKAGES_DEBIAN="$PACKAGES_DEBIAN bzip2 patch python-dev"
 
-PACKAGES_RH="automake bzip2 gcc gcc-c++ patch ncurses-devel openssl-devel libxml2-devel unixODBC-devel libcurl-devel libogg-devel libvorbis-devel speex-devel"
-PACKAGES_RH="$PACKAGES_RH spandsp-devel freetds-devel net-snmp-devel iksemel-devel corosynclib-devel newt-devel popt-devel libtool-ltdl-devel lua-devel"
-PACKAGES_RH="$PACKAGES_RH sqlite-devel libsqlite3x-devel radiusclient-ng-devel portaudio-devel postgresql-devel libresample-devel neon-devel libical-devel"
-PACKAGES_RH="$PACKAGES_RH openldap-devel gmime22-devel sqlite2-devel mysql-devel bluez-libs-devel jack-audio-connection-kit-devel gsm-devel libedit-devel libuuid-devel"
-PACKAGES_RH="$PACKAGES_RH jansson-devel libsrtp-devel pjproject-devel subversion git libxslt-devel python-devel"
+# Basic build system:
+PACKAGES_RH="make gcc gcc-c++ pkgconfig"
+# Asterisk: basic requirements:
+PACKAGES_RH="$PACKAGES_RH libedit-devel jansson-devel libuuid-devel sqlite-devel libxml2-devel"
+# Asterisk: for addons:
+PACKAGES_RH="$PACKAGES_RH speex-devel speexdsp-devel libogg-devel libvorbis-devel alsa-lib-devel portaudio-devel libcurl-devel xmlstarlet bison flex"
+PACKAGES_RH="$PACKAGES_RH postgresql-devel unixODBC-devel libtool-ltdl-devel neon-devel gmime-devel lua-devel uriparser-devel libxslt-devel openssl-devel"
+PACKAGES_RH="$PACKAGES_RH mysql-devel bluez-libs-devel radcli-devel freetds-devel jack-audio-connection-kit-devel bash"
+PACKAGES_RH="$PACKAGES_RH net-snmp-devel iksemel-devel corosynclib-devel newt-devel popt-devel libical-devel spandsp-devel"
+PACKAGES_RH="$PACKAGES_RH libresample-devel uw-imap-devel binutils-devel libsrtp-devel gsm-devel doxygen graphviz zlib-devel openldap-devel hoard"
+PACKAGES_RH="$PACKAGES_RH codec2-devel fftw-devel libsndfile-devel unbound-devel"
+# Asterisk: for the unpackaged below:
+PACKAGES_RH="$PACKAGES_RH wget subversion"
+# Asterisk: for ./configure --with-pjproject-bundled:
+PACKAGES_RH="$PACKAGES_RH bzip2 patch python-devel"
 
 PACKAGES_OBSD="popt gmake wget libxml libogg libvorbis curl iksemel spandsp speex iodbc freetds-0.63p1-msdblib mysql-client gmime sqlite sqlite3 jack libxslt"
 PACKAGES_FBSD="autoconf gcc binutils popt gmake wget libxml2 libogg libvorbis curl iksemel spandsp speex unixODBC freetds-devel mysql55-client gmime2 sqlite"
index f8bd0e3..b95d526 100644 (file)
 /* Define to 1 if you have the curses library. */
 #undef HAVE_CURSES
 
+/* Define to 1 if your C compiler provides __atomic operations. */
+#undef HAVE_C_ATOMICS
+
 /* Define if your system has the DAHDI headers. */
 #undef HAVE_DAHDI
 
 /* Define to 1 if you have the `ftruncate' function. */
 #undef HAVE_FTRUNCATE
 
-/* Define to 1 if your GCC C compiler provides atomic operations. */
+/* Define to 1 if your GCC C compiler provides __sync atomic operations. */
 #undef HAVE_GCC_ATOMICS
 
 /* Define to 1 if you have the `getcwd' function. */
 /* Define to 1 if you have the Open Sound System library. */
 #undef HAVE_OSS
 
-/* Define to 1 if OSX atomic operations are supported. */
-#undef HAVE_OSX_ATOMICS
-
 /* Define to 1 if your system defines the file flag O_EVTONLY in fcntl.h */
 #undef HAVE_O_EVTONLY
 
index 453dc07..c17cb32 100644 (file)
@@ -143,6 +143,11 @@ int ast_filecopy(const char *oldname, const char *newname, const char *fmt);
  * \param filename the name of the file
  * \param obj user data object
  * \return non-zero to stop reading, otherwise zero to continue
+ *
+ * \note dir_name is not processed by realpath or other functions,
+ *       symbolic links are not resolved.  This ensures dir_name
+ *       always starts with the exact string originally passed to
+ *       \ref ast_file_read_dir or \ref ast_file_read_dirs.
  */
 typedef int (*ast_file_on_file)(const char *dir_name, const char *filename, void *obj);
 
index 58c9a83..a46d047 100644 (file)
@@ -617,97 +617,130 @@ static void  __attribute__((destructor)) fini_##rwlock(void) \
 #define pthread_create __use_ast_pthread_create_instead__
 #endif
 
-/*
- * Support for atomic instructions.
- * For platforms that have it, use the native cpu instruction to
- * implement them. For other platforms, resort to a 'slow' version
- * (defined in utils.c) that protects the atomic instruction with
- * a single lock.
- * The slow versions is always available, for testing purposes,
- * as ast_atomic_fetchadd_int_slow()
+/*!
+ * \brief Support for atomic instructions.
+ *
+ * These macros implement a uniform interface to use built-in atomic functionality.
+ * If available __atomic built-ins are prefered.  Legacy __sync built-ins are used
+ * as a fallback for older compilers.
+ *
+ * Detailed documentation can be found in the GCC manual, all API's are modeled after
+ * the __atomic interfaces but using the namespace ast_atomic.
+ *
+ * The memorder argument is always ignored by legacy __sync functions.  Invalid
+ * memorder arguments do not produce errors unless __atomic functions are supported
+ * as the argument is erased by the preprocessor.
+ *
+ * \note ast_atomic_fetch_nand and ast_atomic_nand_fetch purposely do not exist.
+ *       It's implementation was broken prior to gcc-4.4.
+ *
+ * @{
  */
 
-int ast_atomic_fetchadd_int_slow(volatile int *p, int v);
-
 #include "asterisk/inline_api.h"
 
-#if defined(HAVE_OSX_ATOMICS)
-#include "libkern/OSAtomic.h"
+#if defined(HAVE_C_ATOMICS)
+/*! Atomic += */
+#define ast_atomic_fetch_add(ptr, val, memorder)  __atomic_fetch_add((ptr), (val), (memorder))
+#define ast_atomic_add_fetch(ptr, val, memorder)  __atomic_add_fetch((ptr), (val), (memorder))
+
+/*! Atomic -= */
+#define ast_atomic_fetch_sub(ptr, val, memorder)  __atomic_fetch_sub((ptr), (val), (memorder))
+#define ast_atomic_sub_fetch(ptr, val, memorder)  __atomic_sub_fetch((ptr), (val), (memorder))
+
+/*! Atomic &= */
+#define ast_atomic_fetch_and(ptr, val, memorder)  __atomic_fetch_and((ptr), (val), (memorder))
+#define ast_atomic_and_fetch(ptr, val, memorder)  __atomic_and_fetch((ptr), (val), (memorder))
+
+/*! Atomic |= */
+#define ast_atomic_fetch_or(ptr, val, memorder)   __atomic_fetch_or((ptr), (val), (memorder))
+#define ast_atomic_or_fetch(ptr, val, memorder)   __atomic_or_fetch((ptr), (val), (memorder))
+
+/*! Atomic xor = */
+#define ast_atomic_fetch_xor(ptr, val, memorder)  __atomic_fetch_xor((ptr), (val), (memorder))
+#define ast_atomic_xor_fetch(ptr, val, memorder)  __atomic_xor_fetch((ptr), (val), (memorder))
+
+#if 0
+/* Atomic compare and swap
+ *
+ * See comments near the __atomic implementation for why this is disabled.
+ */
+#define ast_atomic_compare_exchange_n(ptr, expected, desired, success_memorder, failure_memorder) \
+       __atomic_compare_exchange_n((ptr), (expected), (desired), 0, success_memorder, failure_memorder)
+
+#define ast_atomic_compare_exchange(ptr, expected, desired, success_memorder, failure_memorder) \
+       __atomic_compare_exchange((ptr), (expected), (desired), 0, success_memorder, failure_memorder)
 #endif
 
-/*! \brief Atomically add v to *p and return * the previous value of *p.
- * This can be used to handle reference counts, and the return value
- * can be used to generate unique identifiers.
+#elif defined(HAVE_GCC_ATOMICS)
+/*! Atomic += */
+#define ast_atomic_fetch_add(ptr, val, memorder)  __sync_fetch_and_add((ptr), (val))
+#define ast_atomic_add_fetch(ptr, val, memorder)  __sync_add_and_fetch((ptr), (val))
+
+/*! Atomic -= */
+#define ast_atomic_fetch_sub(ptr, val, memorder)  __sync_fetch_and_sub((ptr), (val))
+#define ast_atomic_sub_fetch(ptr, val, memorder)  __sync_sub_and_fetch((ptr), (val))
+
+/*! Atomic &= */
+#define ast_atomic_fetch_and(ptr, val, memorder)  __sync_fetch_and_and((ptr), (val))
+#define ast_atomic_and_fetch(ptr, val, memorder)  __sync_and_and_fetch((ptr), (val))
+
+/*! Atomic |= */
+#define ast_atomic_fetch_or(ptr, val, memorder)  __sync_fetch_and_or((ptr), (val))
+#define ast_atomic_or_fetch(ptr, val, memorder)  __sync_or_and_fetch((ptr), (val))
+
+/*! Atomic xor = */
+#define ast_atomic_fetch_xor(ptr, val, memorder)  __sync_fetch_and_xor((ptr), (val))
+#define ast_atomic_xor_fetch(ptr, val, memorder)  __sync_xor_and_fetch((ptr), (val))
+
+#if 0
+/* Atomic compare and swap
+ *
+ * The \a expected argument is a pointer, I'm guessing __atomic built-ins
+ * perform all memory reads/writes in a single atomic operation.  I don't
+ * believe this is possible to exactly replicate using __sync built-ins.
+ * Will need to determine potential use cases of this feature and write a
+ * wrapper which provides consistant behavior between __sync and __atomic
+ * implementations.
  */
+#define ast_atomic_compare_exchange_n(ptr, expected, desired, success_memorder, failure_memorder) \
+       __sync_bool_compare_and_swap((ptr), *(expected), (desired))
 
-#if defined(HAVE_GCC_ATOMICS)
-AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
-{
-       return __sync_fetch_and_add(p, v);
-})
-#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
-AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
-{
-       return OSAtomicAdd32(v, (int32_t *) p) - v;
-})
-#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
-AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
-{
-       return OSAtomicAdd64(v, (int64_t *) p) - v;
-})
-#elif defined (__i386__) || defined(__x86_64__)
-#ifdef sun
-AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
-{
-       __asm __volatile (
-       "       lock;  xaddl   %0, %1 ;        "
-       : "+r" (v),                     /* 0 (result) */
-         "=m" (*p)                     /* 1 */
-       : "m" (*p));                    /* 2 */
-       return (v);
-})
-#else /* ifndef sun */
-AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
-{
-       __asm __volatile (
-       "       lock   xaddl   %0, %1 ;        "
-       : "+r" (v),                     /* 0 (result) */
-         "=m" (*p)                     /* 1 */
-       : "m" (*p));                    /* 2 */
-       return (v);
-})
+#define ast_atomic_compare_exchange(ptr, expected, desired, success_memorder, failure_memorder) \
+       __sync_bool_compare_and_swap((ptr), *(expected), *(desired))
+#endif
+
+#else
+#error "Atomics not available."
 #endif
-#else   /* low performance version in utils.c */
+
+/*! Atomic flag set */
+#define ast_atomic_flag_set(ptr, val, memorder)   ast_atomic_fetch_or((ptr), (val), (memorder))
+
+/*! Atomic flag clear */
+#define ast_atomic_flag_clear(ptr, val, memorder) ast_atomic_fetch_and((ptr), ~(val), (memorder))
+
+/*!
+ * \brief Atomically add v to *p and return the previous value of *p.
+ *
+ * This can be used to handle reference counts, and the return value
+ * can be used to generate unique identifiers.
+ */
 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
 {
-       return ast_atomic_fetchadd_int_slow(p, v);
+       return ast_atomic_fetch_add(p, v, __ATOMIC_RELAXED);
 })
-#endif
 
-/*! \brief decrement *p by 1 and return true if the variable has reached 0.
+/*!
+ * \brief decrement *p by 1 and return true if the variable has reached 0.
+ *
  * Useful e.g. to check if a refcount has reached 0.
  */
-#if defined(HAVE_GCC_ATOMICS)
-AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
-{
-       return __sync_sub_and_fetch(p, 1) == 0;
-})
-#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
-AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
-{
-       return OSAtomicAdd32( -1, (int32_t *) p) == 0;
-})
-#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
-AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
-{
-       return OSAtomicAdd64( -1, (int64_t *) p) == 0;
-})
-#else
 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
 {
-       int a = ast_atomic_fetchadd_int(p, -1);
-       return a == 1; /* true if the value is 0 now (so it was 1 previously) */
+       return ast_atomic_sub_fetch(p, 1, __ATOMIC_RELAXED) == 0;
 })
-#endif
+
+/*! @} */
 
 #endif /* _ASTERISK_LOCK_H */
index c8c171a..a40c6a4 100644 (file)
@@ -1432,7 +1432,7 @@ void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen,
  * \param c Channel variables from which to extract values, and channel to pass to any dialplan functions.
  * \param headp If no channel is specified, a channel list from which to extract variable values
  * \param templ Variable template to expand.
- * \param used Number of bytes read from the template.
+ * \param used Number of bytes read from the template.  (May be NULL)
  */
 void ast_str_substitute_variables_full(struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used);
 /*! @} */
index b148b6f..7e9624e 100644 (file)
@@ -154,7 +154,6 @@ endif
 
 db.o: _ASTCFLAGS+=$(SQLITE3_INCLUDE)
 asterisk.o: _ASTCFLAGS+=$(LIBEDIT_INCLUDE)
-loader.o: _ASTCFLAGS+=$(LIBEDIT_INCLUDE)
 json.o: _ASTCFLAGS+=$(JANSSON_INCLUDE)
 bucket.o: _ASTCFLAGS+=$(URIPARSER_INCLUDE)
 crypt.o: _ASTCFLAGS+=$(CRYPT_INCLUDE)
index 159014e..6b29f0e 100644 (file)
@@ -36,7 +36,6 @@
 #include "asterisk/_private.h"
 #include "asterisk/paths.h"    /* use ast_config_AST_MODULE_DIR */
 #include <dirent.h>
-#include <editline/readline.h>
 
 #include "asterisk/dlinkedlists.h"
 #include "asterisk/module.h"
@@ -56,6 +55,7 @@
 #include "asterisk/app.h"
 #include "asterisk/test.h"
 #include "asterisk/sounds_index.h"
+#include "asterisk/cli.h"
 
 #include <dlfcn.h>
 
@@ -1036,57 +1036,55 @@ static int module_matches_helper_type(struct ast_module *mod, enum ast_module_he
        }
 }
 
-static char *module_load_helper(const char *word, int state)
+struct module_load_word {
+       const char *word;
+       size_t len;
+       size_t moddir_len;
+};
+
+static int module_load_helper_on_file(const char *dir_name, const char *filename, void *obj)
 {
+       struct module_load_word *word = obj;
        struct ast_module *mod;
-       int which = 0;
-       char *name;
-       char *ret = NULL;
-       char *editline_ret;
-       char fullpath[PATH_MAX];
-       int idx = 0;
-       /* This is needed to avoid listing modules that are already running. */
-       AST_VECTOR(, char *) running_modules;
+       char *filename_merged = NULL;
 
-       AST_VECTOR_INIT(&running_modules, 200);
+       /* dir_name will never be shorter than word->moddir_len. */
+       dir_name += word->moddir_len;
+       if (!ast_strlen_zero(dir_name)) {
+               ast_assert(dir_name[0] == '/');
 
-       AST_DLLIST_LOCK(&module_list);
-       AST_DLLIST_TRAVERSE(&module_list, mod, entry) {
-               if (mod->flags.running) {
-                       AST_VECTOR_APPEND(&running_modules, mod->resource);
+               dir_name += 1;
+               if (ast_asprintf(&filename_merged, "%s/%s", dir_name, filename) < 0) {
+                       /* If we can't allocate the string just give up! */
+                       return -1;
                }
+               filename = filename_merged;
        }
 
-       if (word[0] == '/') {
-               /* BUGBUG: we should not support this. */
-               ast_copy_string(fullpath, word, sizeof(fullpath));
-       } else {
-               snprintf(fullpath, sizeof(fullpath), "%s/%s", ast_config_AST_MODULE_DIR, word);
+       if (!strncasecmp(filename, word->word, word->len)) {
+               /* Don't list files that are already loaded! */
+               mod = find_resource(filename, 0);
+               if (!mod || !mod->flags.running) {
+                       ast_cli_completion_add(ast_strdup(filename));
+               }
        }
 
-       /*
-        * This is ugly that we keep calling filename_completion_function.
-        * The only way to avoid this would be to make a copy of the function
-        * that skips matches found in the running_modules vector.
-        */
-       while (!ret && (name = editline_ret = filename_completion_function(fullpath, idx++))) {
-               if (word[0] != '/') {
-                       name += (strlen(ast_config_AST_MODULE_DIR) + 1);
-               }
+       ast_free(filename_merged);
 
-               /* Don't list files that are already loaded! */
-               if (!AST_VECTOR_GET_CMP(&running_modules, name, !strcasecmp) && ++which > state) {
-                       ret = ast_strdup(name);
-               }
+       return 0;
+}
 
-               ast_std_free(editline_ret);
-       }
+static void module_load_helper(const char *word)
+{
+       struct module_load_word word_l = {
+               .word = word,
+               .len = strlen(word),
+               .moddir_len = strlen(ast_config_AST_MODULE_DIR),
+       };
 
-       /* Do not clean-up the elements, they belong to module_list. */
-       AST_VECTOR_FREE(&running_modules);
+       AST_DLLIST_LOCK(&module_list);
+       ast_file_read_dirs(ast_config_AST_MODULE_DIR, module_load_helper_on_file, &word_l, -1);
        AST_DLLIST_UNLOCK(&module_list);
-
-       return ret;
 }
 
 char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, enum ast_module_helper_type type)
@@ -1101,7 +1099,9 @@ char *ast_module_helper(const char *line, const char *word, int pos, int state,
        }
 
        if (type == AST_MODULE_HELPER_LOAD) {
-               return module_load_helper(word, state);
+               module_load_helper(word);
+
+               return NULL;
        }
 
        if (type == AST_MODULE_HELPER_RELOAD) {
index eede213..1dc0fc0 100644 (file)
@@ -396,51 +396,74 @@ const char *ast_str_retrieve_variable(struct ast_str **str, ssize_t maxlen, stru
 void ast_str_substitute_variables_full(struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used)
 {
        /* Substitutes variables into buf, based on string templ */
-       char *cp4 = NULL;
        const char *whereweare;
-       int orig_size = 0;
-       int offset, offset2, isfunction;
-       const char *nextvar, *nextexp, *nextthing;
-       const char *vars, *vare;
-       char *finalvars;
-       int pos, brackets, needsub, len;
-       struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
+       struct ast_str *substr1 = ast_str_create(16);
+       struct ast_str *substr2 = NULL;
+       struct ast_str *substr3 = ast_str_create(16);
 
        ast_str_reset(*buf);
+
+       if (!substr1 || !substr3) {
+               if (used) {
+                       *used = ast_str_strlen(*buf);
+               }
+               ast_free(substr1);
+               ast_free(substr3);
+               return;
+       }
+
        whereweare = templ;
        while (!ast_strlen_zero(whereweare)) {
+               const char *nextvar = NULL;
+               const char *nextexp = NULL;
+               const char *nextthing;
+               const char *vars;
+               const char *vare;
+               char *finalvars;
+               int pos;
+               int brackets;
+               int needsub;
+               int len;
+
                /* reset our buffer */
                ast_str_reset(substr3);
 
-               /* Assume we're copying the whole remaining string */
-               pos = strlen(whereweare);
-               nextvar = NULL;
-               nextexp = NULL;
+               /* Determine how much simply needs to be copied to the output buf. */
                nextthing = strchr(whereweare, '$');
                if (nextthing) {
+                       pos = nextthing - whereweare;
                        switch (nextthing[1]) {
                        case '{':
+                               /* Variable substitution */
                                nextvar = nextthing;
-                               pos = nextvar - whereweare;
                                break;
                        case '[':
+                               /* Expression substitution */
                                nextexp = nextthing;
-                               pos = nextexp - whereweare;
                                break;
                        default:
-                               pos = 1;
+                               /* '$' is not part of a substitution so include it too. */
+                               ++pos;
+                               break;
                        }
+               } else {
+                       /* We're copying the whole remaining string */
+                       pos = strlen(whereweare);
                }
 
                if (pos) {
                        /* Copy that many bytes */
                        ast_str_append_substr(buf, maxlen, whereweare, pos);
 
-                       templ += pos;
                        whereweare += pos;
                }
 
                if (nextvar) {
+                       int offset;
+                       int offset2;
+                       int isfunction;
+                       int res;
+
                        /* We have a variable.  Find the start and end, and determine
                           if we are going to have to recursively call ourselves on the
                           contents */
@@ -452,33 +475,42 @@ void ast_str_substitute_variables_full(struct ast_str **buf, ssize_t maxlen, str
                        while (brackets && *vare) {
                                if ((vare[0] == '$') && (vare[1] == '{')) {
                                        needsub++;
+                                       brackets++;
+                                       vare++;
                                } else if (vare[0] == '{') {
                                        brackets++;
                                } else if (vare[0] == '}') {
                                        brackets--;
-                               } else if ((vare[0] == '$') && (vare[1] == '['))
+                               } else if ((vare[0] == '$') && (vare[1] == '[')) {
                                        needsub++;
+                                       vare++;
+                               }
                                vare++;
                        }
-                       if (brackets)
+                       len = vare - vars;
+                       if (brackets) {
                                ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
-                       len = vare - vars - 1;
+                       } else {
+                               /* Don't count the closing '}' in the length. */
+                               --len;
+                       }
 
                        /* Skip totally over variable string */
-                       whereweare += (len + 3);
+                       whereweare = vare;
 
-                       /* Store variable name (and truncate) */
+                       /* Store variable name expression to lookup. */
                        ast_str_set_substr(&substr1, 0, vars, len);
                        ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
 
                        /* Substitute if necessary */
                        if (needsub) {
-                               size_t my_used;
-
                                if (!substr2) {
                                        substr2 = ast_str_create(16);
+                                       if (!substr2) {
+                                               continue;
+                                       }
                                }
-                               ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &my_used);
+                               ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), NULL);
                                finalvars = ast_str_buffer(substr2);
                        } else {
                                finalvars = ast_str_buffer(substr1);
@@ -488,28 +520,32 @@ void ast_str_substitute_variables_full(struct ast_str **buf, ssize_t maxlen, str
                        if (isfunction) {
                                /* Evaluate function */
                                if (c || !headp) {
-                                       cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
+                                       res = ast_func_read2(c, finalvars, &substr3, 0);
                                } else {
                                        struct varshead old;
-                                       struct ast_channel *bogus = ast_dummy_channel_alloc();
+                                       struct ast_channel *bogus;
+
+                                       bogus = ast_dummy_channel_alloc();
                                        if (bogus) {
-                                               memcpy(&old, ast_channel_varshead(bogus), sizeof(old));
-                                               memcpy(ast_channel_varshead(bogus), headp, sizeof(*ast_channel_varshead(bogus)));
-                                               cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
+                                               old = *ast_channel_varshead(bogus);
+                                               *ast_channel_varshead(bogus) = *headp;
+                                               res = ast_func_read2(bogus, finalvars, &substr3, 0);
                                                /* Don't deallocate the varshead that was passed in */
-                                               memcpy(ast_channel_varshead(bogus), &old, sizeof(*ast_channel_varshead(bogus)));
+                                               *ast_channel_varshead(bogus) = old;
                                                ast_channel_unref(bogus);
                                        } else {
-                                               ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
+                                               ast_log(LOG_ERROR, "Unable to allocate bogus channel for function value substitution.\n");
+                                               res = -1;
                                        }
                                }
-                               ast_debug(2, "Function %s result is '%s'\n", finalvars, cp4 ? cp4 : "(null)");
+                               ast_debug(2, "Function %s result is '%s'\n",
+                                       finalvars, res ? "" : ast_str_buffer(substr3));
                        } else {
                                /* Retrieve variable value */
                                ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
-                               cp4 = ast_str_buffer(substr3);
+                               res = 0;
                        }
-                       if (cp4) {
+                       if (!res) {
                                ast_str_substring(substr3, offset, offset2);
                                ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
                        }
@@ -537,24 +573,29 @@ void ast_str_substitute_variables_full(struct ast_str **buf, ssize_t maxlen, str
                                }
                                vare++;
                        }
-                       if (brackets)
+                       len = vare - vars;
+                       if (brackets) {
                                ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
-                       len = vare - vars - 1;
+                       } else {
+                               /* Don't count the closing ']' in the length. */
+                               --len;
+                       }
 
                        /* Skip totally over expression */
-                       whereweare += (len + 3);
+                       whereweare = vare;
 
-                       /* Store variable name (and truncate) */
+                       /* Store expression to evaluate. */
                        ast_str_set_substr(&substr1, 0, vars, len);
 
                        /* Substitute if necessary */
                        if (needsub) {
-                               size_t my_used;
-
                                if (!substr2) {
                                        substr2 = ast_str_create(16);
+                                       if (!substr2) {
+                                               continue;
+                                       }
                                }
-                               ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &my_used);
+                               ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), NULL);
                                finalvars = ast_str_buffer(substr2);
                        } else {
                                finalvars = ast_str_buffer(substr1);
@@ -566,7 +607,9 @@ void ast_str_substitute_variables_full(struct ast_str **buf, ssize_t maxlen, str
                        ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
                }
        }
-       *used = ast_str_strlen(*buf) - orig_size;
+       if (used) {
+               *used = ast_str_strlen(*buf);
+       }
        ast_free(substr1);
        ast_free(substr2);
        ast_free(substr3);
@@ -574,49 +617,58 @@ void ast_str_substitute_variables_full(struct ast_str **buf, ssize_t maxlen, str
 
 void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
 {
-       size_t used;
-       ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
+       ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, NULL);
 }
 
 void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
 {
-       size_t used;
-       ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
+       ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, NULL);
 }
 
 void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
 {
        /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
-       char *cp4 = NULL;
-       const char *whereweare, *orig_cp2 = cp2;
-       int length, offset, offset2, isfunction;
+       const char *whereweare;
+       const char *orig_cp2 = cp2;
        char *workspace = NULL;
-       char *ltmp = NULL, *var = NULL;
-       char *nextvar, *nextexp, *nextthing;
-       char *vars, *vare;
-       int pos, brackets, needsub, len;
+       char *ltmp = NULL;
+       char *var = NULL;
 
        *cp2 = 0; /* just in case nothing ends up there */
        whereweare = cp1;
        while (!ast_strlen_zero(whereweare) && count) {
-               /* Assume we're copying the whole remaining string */
-               pos = strlen(whereweare);
-               nextvar = NULL;
-               nextexp = NULL;
+               char *nextvar = NULL;
+               char *nextexp = NULL;
+               char *nextthing;
+               char *vars;
+               char *vare;
+               int length;
+               int pos;
+               int brackets;
+               int needsub;
+               int len;
+
+               /* Determine how much simply needs to be copied to the output buf. */
                nextthing = strchr(whereweare, '$');
                if (nextthing) {
+                       pos = nextthing - whereweare;
                        switch (nextthing[1]) {
                        case '{':
+                               /* Variable substitution */
                                nextvar = nextthing;
-                               pos = nextvar - whereweare;
                                break;
                        case '[':
+                               /* Expression substitution */
                                nextexp = nextthing;
-                               pos = nextexp - whereweare;
                                break;
                        default:
-                               pos = 1;
+                               /* '$' is not part of a substitution so include it too. */
+                               ++pos;
+                               break;
                        }
+               } else {
+                       /* We're copying the whole remaining string */
+                       pos = strlen(whereweare);
                }
 
                if (pos) {
@@ -634,6 +686,11 @@ void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead
                }
 
                if (nextvar) {
+                       int offset;
+                       int offset2;
+                       int isfunction;
+                       char *cp4;
+
                        /* We have a variable.  Find the start and end, and determine
                           if we are going to have to recursively call ourselves on the
                           contents */
@@ -645,35 +702,41 @@ void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead
                        while (brackets && *vare) {
                                if ((vare[0] == '$') && (vare[1] == '{')) {
                                        needsub++;
+                                       brackets++;
+                                       vare++;
                                } else if (vare[0] == '{') {
                                        brackets++;
                                } else if (vare[0] == '}') {
                                        brackets--;
-                               } else if ((vare[0] == '$') && (vare[1] == '['))
+                               } else if ((vare[0] == '$') && (vare[1] == '[')) {
                                        needsub++;
+                                       vare++;
+                               }
                                vare++;
                        }
-                       if (brackets)
+                       len = vare - vars;
+                       if (brackets) {
                                ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
-                       len = vare - vars - 1;
+                       } else {
+                               /* Don't count the closing '}' in the length. */
+                               --len;
+                       }
 
                        /* Skip totally over variable string */
-                       whereweare += (len + 3);
+                       whereweare = vare;
 
                        if (!var)
                                var = ast_alloca(VAR_BUF_SIZE);
 
-                       /* Store variable name (and truncate) */
+                       /* Store variable name expression to lookup (and truncate). */
                        ast_copy_string(var, vars, len + 1);
 
                        /* Substitute if necessary */
                        if (needsub) {
-                               size_t my_used;
-
                                if (!ltmp) {
                                        ltmp = ast_alloca(VAR_BUF_SIZE);
                                }
-                               pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &my_used);
+                               pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, NULL);
                                vars = ltmp;
                        } else {
                                vars = var;
@@ -691,16 +754,19 @@ void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead
                                        cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
                                else {
                                        struct varshead old;
-                                       struct ast_channel *c = ast_dummy_channel_alloc();
-                                       if (c) {
-                                               memcpy(&old, ast_channel_varshead(c), sizeof(old));
-                                               memcpy(ast_channel_varshead(c), headp, sizeof(*ast_channel_varshead(c)));
-                                               cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
+                                       struct ast_channel *bogus;
+
+                                       bogus = ast_dummy_channel_alloc();
+                                       if (bogus) {
+                                               old = *ast_channel_varshead(bogus);
+                                               *ast_channel_varshead(bogus) = *headp;
+                                               cp4 = ast_func_read(bogus, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
                                                /* Don't deallocate the varshead that was passed in */
-                                               memcpy(ast_channel_varshead(c), &old, sizeof(*ast_channel_varshead(c)));
-                                               c = ast_channel_unref(c);
+                                               *ast_channel_varshead(bogus) = old;
+                                               ast_channel_unref(bogus);
                                        } else {
-                                               ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
+                                               ast_log(LOG_ERROR, "Unable to allocate bogus channel for function value substitution.\n");
+                                               cp4 = NULL;
                                        }
                                }
                                ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)");
@@ -743,34 +809,35 @@ void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead
                                }
                                vare++;
                        }
-                       if (brackets)
+                       len = vare - vars;
+                       if (brackets) {
                                ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
-                       len = vare - vars - 1;
+                       } else {
+                               /* Don't count the closing ']' in the length. */
+                               --len;
+                       }
 
                        /* Skip totally over expression */
-                       whereweare += (len + 3);
+                       whereweare = vare;
 
                        if (!var)
                                var = ast_alloca(VAR_BUF_SIZE);
 
-                       /* Store variable name (and truncate) */
+                       /* Store expression to evaluate (and truncate). */
                        ast_copy_string(var, vars, len + 1);
 
                        /* Substitute if necessary */
                        if (needsub) {
-                               size_t my_used;
-
                                if (!ltmp) {
                                        ltmp = ast_alloca(VAR_BUF_SIZE);
                                }
-                               pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &my_used);
+                               pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, NULL);
                                vars = ltmp;
                        } else {
                                vars = var;
                        }
 
                        length = ast_expr(vars, cp2, count, c);
-
                        if (length) {
                                ast_debug(1, "Expression result is '%s'\n", cp2);
                                count -= length;
@@ -779,19 +846,19 @@ void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead
                        }
                }
        }
-       *used = cp2 - orig_cp2;
+       if (used) {
+               *used = cp2 - orig_cp2;
+       }
 }
 
 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
 {
-       size_t used;
-       pbx_substitute_variables_helper_full(c, (c) ? ast_channel_varshead(c) : NULL, cp1, cp2, count, &used);
+       pbx_substitute_variables_helper_full(c, (c) ? ast_channel_varshead(c) : NULL, cp1, cp2, count, NULL);
 }
 
 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
 {
-       size_t used;
-       pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
+       pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, NULL);
 }
 
 /*! \brief CLI support for listing global variables in a parseable way */
index 85228c1..7f74f40 100644 (file)
@@ -1985,18 +1985,6 @@ char *ast_to_camel_case_delim(const char *s, const char *delim)
        return res;
 }
 
-AST_MUTEX_DEFINE_STATIC(fetchadd_m); /* used for all fetc&add ops */
-
-int ast_atomic_fetchadd_int_slow(volatile int *p, int v)
-{
-       int ret;
-       ast_mutex_lock(&fetchadd_m);
-       ret = *p;
-       *p += v;
-       ast_mutex_unlock(&fetchadd_m);
-       return ret;
-}
-
 /*! \brief
  * get values from config variables.
  */
index 2e519b7..bdee91f 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "asterisk.h"
 
+#include <signal.h>
 #include <pjsip.h>
 #include <pjsip_ua.h>
 
diff --git a/res/res_pjsip_registrar_expire.c b/res/res_pjsip_registrar_expire.c
deleted file mode 100644 (file)
index 4c21895..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2013, Digium, Inc.
- *
- * Joshua Colp <jcolp@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.
- */
-
-/*** MODULEINFO
-       <depend>pjproject</depend>
-       <depend>res_pjsip</depend>
-       <support_level>extended</support_level>
- ***/
-
-/*
- * This module has been refactored into res_pjsip_registrar
- */
-
-#include "asterisk.h"
-
-#include "asterisk/module.h"
-
-static int unload_module(void)
-{
-       return 0;
-}
-
-static int load_module(void)
-{
-       return AST_MODULE_LOAD_SUCCESS;
-}
-
-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "OBSOLETE PJSIP Contact Auto-Expiration",
-       .support_level = AST_MODULE_SUPPORT_EXTENDED,
-       .load = load_module,
-       .unload = unload_module,
-       .load_pri = AST_MODPRI_APP_DEPEND,
-       .requires = "res_pjsip",
-);
index 4d4ed47..5a9134b 100644 (file)
@@ -3425,9 +3425,13 @@ static void handle_incoming_before_media(pjsip_inv_session *inv,
 
 static void session_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
 {
-       struct ast_sip_session *session = inv->mod_data[session_module.id];
+       struct ast_sip_session *session;
        pjsip_event_id_e type;
 
+       if (ast_shutdown_final()) {
+               return;
+       }
+
        if (e) {
                print_debug_details(inv, NULL, e);
                type = e->type;
@@ -3435,6 +3439,7 @@ static void session_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
                type = PJSIP_EVENT_UNKNOWN;
        }
 
+       session = inv->mod_data[session_module.id];
        if (!session) {
                return;
        }
@@ -3536,13 +3541,7 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
        struct ast_sip_session *session;
        pjsip_tx_data *tdata;
 
-       /*
-        * A race condition exists at shutdown where the res_pjsip_session can be
-        * unloaded but this callback may still get called afterwards. In this case
-        * the id may end up being -1 which is useless to us. To work around this
-        * we store the current value and check/use it.
-        */
-       if (id < 0) {
+       if (ast_shutdown_final()) {
                return;
        }
 
@@ -3991,9 +3990,14 @@ static struct pjmedia_sdp_session *create_local_sdp(pjsip_inv_session *inv, stru
 
 static void session_inv_on_rx_offer(pjsip_inv_session *inv, const pjmedia_sdp_session *offer)
 {
-       struct ast_sip_session *session = inv->mod_data[session_module.id];
+       struct ast_sip_session *session;
        pjmedia_sdp_session *answer;
 
+       if (ast_shutdown_final()) {
+               return;
+       }
+
+       session = inv->mod_data[session_module.id];
        if (handle_incoming_sdp(session, offer)) {
                return;
        }
@@ -4012,9 +4016,14 @@ static void session_inv_on_create_offer(pjsip_inv_session *inv, pjmedia_sdp_sess
 
 static void session_inv_on_media_update(pjsip_inv_session *inv, pj_status_t status)
 {
-       struct ast_sip_session *session = inv->mod_data[session_module.id];
+       struct ast_sip_session *session;
        const pjmedia_sdp_session *local, *remote;
 
+       if (ast_shutdown_final()) {
+               return;
+       }
+
+       session = inv->mod_data[session_module.id];
        if (!session || !session->channel) {
                /*
                 * If we don't have a session or channel then we really
@@ -4037,10 +4046,15 @@ static void session_inv_on_media_update(pjsip_inv_session *inv, pj_status_t stat
 
 static pjsip_redirect_op session_inv_on_redirected(pjsip_inv_session *inv, const pjsip_uri *target, const pjsip_event *e)
 {
-       struct ast_sip_session *session = inv->mod_data[session_module.id];
+       struct ast_sip_session *session;
        const pjsip_sip_uri *uri;
 
-       if (!session->channel) {
+       if (ast_shutdown_final()) {
+               return PJSIP_REDIRECT_STOP;
+       }
+
+       session = inv->mod_data[session_module.id];
+       if (!session || !session->channel) {
                return PJSIP_REDIRECT_STOP;
        }
 
index e15705e..1e4b9d1 100644 (file)
@@ -143,13 +143,6 @@ int check_eval(char *buffer, char *error_report);
 void parse_file(const char *fname);
 
 int ast_add_profile(const char *x, uint64_t scale) { return 0;}
-int ast_atomic_fetchadd_int_slow(volatile int *p, int v)
-{
-        int ret;
-        ret = *p;
-        *p += v;
-        return ret;
-}
 
 char *find_var(const char *varname) /* the list should be pretty short, if there's any list at all */
 {