summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES27
-rw-r--r--addons/chan_mobile.c13
-rwxr-xr-xbuild_tools/download_externals4
-rw-r--r--channels/chan_pjsip.c9
-rw-r--r--channels/chan_sip.c14
-rw-r--r--codecs/codec_dahdi.c2
-rw-r--r--configs/samples/pjproject.conf.sample25
-rwxr-xr-xconfigure2
-rw-r--r--configure.ac2
-rw-r--r--include/asterisk/channel.h15
-rw-r--r--include/asterisk/format.h18
-rw-r--r--include/asterisk/options.h14
-rw-r--r--include/asterisk/tcptls.h4
-rw-r--r--include/asterisk/utils.h9
-rw-r--r--main/Makefile4
-rw-r--r--main/asterisk.c34
-rw-r--r--main/channel.c51
-rw-r--r--main/dns.c2
-rw-r--r--main/dns_core.c22
-rw-r--r--main/dns_naptr.c13
-rw-r--r--main/dns_srv.c8
-rw-r--r--main/format.c13
-rw-r--r--main/iostream.c13
-rw-r--r--main/libasteriskpj.c2
-rw-r--r--main/libasteriskssl.c4
-rw-r--r--main/rtp_engine.c2
-rw-r--r--main/tcptls.c88
-rw-r--r--main/utils.c12
-rw-r--r--pbx/pbx_lua.c28
-rw-r--r--res/res_calendar_caldav.c4
-rw-r--r--res/res_format_attr_opus.c8
-rw-r--r--res/res_pjproject.c145
-rw-r--r--res/res_pjsip.c16
-rw-r--r--res/res_pjsip/pjsip_resolver.c32
-rw-r--r--res/res_pjsip_outbound_registration.c21
-rw-r--r--res/res_pjsip_sdp_rtp.c7
-rw-r--r--res/res_pjsip_t38.c7
-rw-r--r--res/res_pjsip_transport_websocket.c5
-rw-r--r--res/res_rtp_asterisk.c51
-rw-r--r--third-party/pjproject/patches/config_site.h2
40 files changed, 622 insertions, 130 deletions
diff --git a/CHANGES b/CHANGES
index 448657def..df0834d11 100644
--- a/CHANGES
+++ b/CHANGES
@@ -69,7 +69,30 @@ app_originate
allows for adding variables to newly created channel or, e.g. setting callerid.
------------------------------------------------------------------------------
---- Functionality changes from Asterisk 14.1.0 to Asterisk 14.2.0 ----------
+--- Functionality changes from Asterisk 14.2.0 to Asterisk 14.3.0 ------------
+------------------------------------------------------------------------------
+
+res_pjproject
+------------------
+ * Added new CLI command "pjproject set log level". The new command allows
+ the maximum PJPROJECT log levels to be adjusted dynamically and
+ independently from the set debug logging level like many other similar
+ module debug logging commands.
+
+ * Added new companion CLI command "pjproject show log level" to allow the
+ user to see the current maximum pjproject logging level.
+
+ * Added new pjproject.conf startup section "log_level' option to set the
+ initial maximum PJPROJECT logging level.
+
+res_pjsip_outbound_registration
+------------------
+ * Statsd no longer logs redundant status PJSIP.registrations.state changes
+ for internal state transitions that don't change the reported public status
+ state.
+
+------------------------------------------------------------------------------
+--- Functionality changes from Asterisk 14.1.0 to Asterisk 14.2.0 ------------
------------------------------------------------------------------------------
AMI
@@ -149,7 +172,7 @@ res_ari
ARI event.
------------------------------------------------------------------------------
---- Functionality changes from Asterisk 14.0.0 to Asterisk 14.1.0 ----------
+--- Functionality changes from Asterisk 14.0.0 to Asterisk 14.1.0 ------------
------------------------------------------------------------------------------
Build System
diff --git a/addons/chan_mobile.c b/addons/chan_mobile.c
index dc2efd4db..bd39bee64 100644
--- a/addons/chan_mobile.c
+++ b/addons/chan_mobile.c
@@ -3853,10 +3853,7 @@ static void *do_monitor_phone(void *data)
}
if ((at_msg = at_read_full(hfp->rsock, buf, sizeof(buf))) < 0) {
- /* XXX gnu specific strerror_r is assummed here, this
- * is not really safe. See the strerror(3) man page
- * for more info. */
- ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror_r(errno, buf, sizeof(buf)), errno);
+ ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror(errno), errno);
break;
}
@@ -3993,7 +3990,7 @@ static void *do_monitor_phone(void *data)
ast_debug(1, "[%s] error parsing message\n", pvt->id);
goto e_cleanup;
case AT_READ_ERROR:
- ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror_r(errno, buf, sizeof(buf)), errno);
+ ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror(errno), errno);
goto e_cleanup;
default:
break;
@@ -4071,11 +4068,7 @@ static void *do_monitor_headset(void *data)
continue;
if ((at_msg = at_read_full(pvt->rfcomm_socket, buf, sizeof(buf))) < 0) {
- if (strerror_r(errno, buf, sizeof(buf)))
- ast_debug(1, "[%s] error reading from device\n", pvt->id);
- else
- ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, buf, errno);
-
+ ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror(errno), errno);
goto e_cleanup;
}
ast_debug(1, "[%s] %s\n", pvt->id, buf);
diff --git a/build_tools/download_externals b/build_tools/download_externals
index 2bc357c29..d2e2e4fff 100755
--- a/build_tools/download_externals
+++ b/build_tools/download_externals
@@ -45,11 +45,11 @@ if [[ -z ${cache_dir} ]] ; then
fi
version=$(${ASTTOPDIR}/build_tools/make_version ${ASTTOPDIR})
-if [[ ! ${version} =~ ^(GIT-)?([^.-]+)[.-].* ]] ; then
+if [[ ! ${version} =~ ^(GIT-)?(certified/)?([^.-]+)[.-].* ]] ; then
echo "${module_name}: Couldn't parse version ${version}"
exit 1
fi
-major_version=${BASH_REMATCH[2]}
+major_version=${BASH_REMATCH[3]}
if [[ "${major_version}" == "master" ]] ; then
echo "${module_name}: External module downloading is not available in the 'master' git branch. Please disable in menuselect and download manually."
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index d4a7d618d..4aae15ce9 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -677,7 +677,11 @@ static struct ast_frame *chan_pjsip_cng_tone_detected(struct ast_sip_session *se
return f;
}
-/*! \brief Function called by core to read any waiting frames */
+/*!
+ * \brief Function called by core to read any waiting frames
+ *
+ * \note The channel is already locked.
+ */
static struct ast_frame *chan_pjsip_read(struct ast_channel *ast)
{
struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
@@ -735,8 +739,7 @@ static struct ast_frame *chan_pjsip_read(struct ast_channel *ast)
ast_debug(1, "Oooh, got a frame with format of %s on channel '%s' when we're sending '%s', switching to match\n",
ast_format_get_name(f->subclass.format), ast_channel_name(ast),
ast_format_get_name(ast_channel_rawwriteformat(ast)));
- ast_channel_set_rawwriteformat(ast, f->subclass.format);
- ast_set_write_format(ast, ast_channel_writeformat(ast));
+ ast_set_write_format_path(ast, ast_channel_writeformat(ast), f->subclass.format);
if (ast_channel_is_bridged(ast)) {
ast_channel_set_unbridged_nolock(ast, 1);
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 870b53edf..44693ef32 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -2957,6 +2957,7 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s
if (!(me = sip_threadinfo_create(tcptls_session, ast_iostream_get_ssl(tcptls_session->stream) ? AST_TRANSPORT_TLS : AST_TRANSPORT_TCP))) {
goto cleanup;
}
+ me->threadid = pthread_self();
ao2_t_ref(me, +1, "Adding threadinfo ref for tcp_helper_thread");
} else {
struct sip_threadinfo tmp = {
@@ -2964,8 +2965,13 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s
};
if ((!(ca = tcptls_session->parent)) ||
- (!(me = ao2_t_find(threadt, &tmp, OBJ_POINTER, "ao2_find, getting sip_threadinfo in tcp helper thread"))) ||
- (!(tcptls_session = ast_tcptls_client_start(tcptls_session)))) {
+ (!(me = ao2_t_find(threadt, &tmp, OBJ_POINTER, "ao2_find, getting sip_threadinfo in tcp helper thread")))) {
+ goto cleanup;
+ }
+
+ me->threadid = pthread_self();
+
+ if (!(tcptls_session = ast_tcptls_client_start(tcptls_session))) {
goto cleanup;
}
}
@@ -2976,7 +2982,6 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s
goto cleanup;
}
- me->threadid = pthread_self();
ast_debug(2, "Starting thread for %s server\n", ast_iostream_get_ssl(tcptls_session->stream) ? "TLS" : "TCP");
/* set up pollfd to watch for reads on both the socket and the alert_pipe */
@@ -14153,6 +14158,7 @@ static void build_contact(struct sip_pvt *p, struct sip_request *req, int incomi
char tmp[SIPBUFSIZE];
char *user = ast_uri_encode(p->exten, tmp, sizeof(tmp), ast_uri_sip_user);
int use_sips;
+ char *transport = ast_strdupa(sip_get_transport(p->socket.type));
if (incoming) {
use_sips = uas_sips_contact(req);
@@ -14167,7 +14173,7 @@ static void build_contact(struct sip_pvt *p, struct sip_request *req, int incomi
} else {
ast_string_field_build(p, our_contact, "<%s:%s%s%s;transport=%s>",
use_sips ? "sips" : "sip", user, ast_strlen_zero(user) ? "" : "@",
- ast_sockaddr_stringify_remote(&p->ourip), sip_get_transport(p->socket.type));
+ ast_sockaddr_stringify_remote(&p->ourip), ast_str_to_lower(transport));
}
}
diff --git a/codecs/codec_dahdi.c b/codecs/codec_dahdi.c
index 2d08d36cd..efb016853 100644
--- a/codecs/codec_dahdi.c
+++ b/codecs/codec_dahdi.c
@@ -34,11 +34,11 @@
#include "asterisk.h"
#include <stdbool.h>
+#include <poll.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
-#include <sys/poll.h>
#include <dahdi/user.h>
#include "asterisk/lock.h"
diff --git a/configs/samples/pjproject.conf.sample b/configs/samples/pjproject.conf.sample
index 97af7345f..82c81a1f6 100644
--- a/configs/samples/pjproject.conf.sample
+++ b/configs/samples/pjproject.conf.sample
@@ -1,15 +1,36 @@
; Common pjproject options
;
+;[startup]
+; NOTES: The name of this section in the pjproject.conf configuration file must
+; remain startup or the configuration will not be applied.
+;
+;log_level=default ; Initial maximum pjproject logging level to log
+ ; Valid values are: 0-6, and default
+ ;
+ ; Note: This option is needed very early in the startup
+ ; process so it can only be read from config files because
+ ; the modules for other methods have not been loaded yet.
+;type= ; Must be of type startup (default: "")
+
;========================LOG_MAPPINGS SECTION OPTIONS===============================
;[log_mappings]
; SYNOPSIS: Provides pjproject to Asterisk log level mappings.
; NOTES: The name of this section in the pjproject.conf configuration file must
; remain log_mappings or the configuration will not be applied.
; The defaults mentioned below only apply if this file or the 'log_mappings'
-; object can'tbe found. If the object is found, there are no defaults. If
+; object can't be found. If the object is found, there are no defaults. If
; you don't specify an entry, nothing will be logged for that level.
;
+; These logging level meanings are typically used by pjproject:
+; - 0: fatal error
+; - 1: error
+; - 2: warning
+; - 3: info
+; - 4: debug
+; - 5: trace
+; - 6: more detailed trace
+;
;asterisk_error = ; A comma separated list of pjproject log levels to map to
; Asterisk errors.
; (default: "0,1")
@@ -24,5 +45,5 @@
; (default: "")
;asterisk_debug = ; A comma separated list of pjproject log levels to map to
; Asterisk debug
- ; (default: "3,4,5")
+ ; (default: "3,4,5,6")
;type= ; Must be of type log_mappings (default: "")
diff --git a/configure b/configure
index c7821cc29..523f7652e 100755
--- a/configure
+++ b/configure
@@ -4938,7 +4938,7 @@ case "${host_os}" in
OSARCH=cygwin
PBX_WINARCH=1
;;
- linux-gnueabi* | linux-gnuspe)
+ linux-gnu*)
OSARCH=linux-gnu
;;
linux-musl*)
diff --git a/configure.ac b/configure.ac
index 0f9b3442b..161ccab5f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -178,7 +178,7 @@ case "${host_os}" in
OSARCH=cygwin
PBX_WINARCH=1
;;
- linux-gnueabi* | linux-gnuspe)
+ linux-gnu*)
OSARCH=linux-gnu
;;
linux-musl*)
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 5c73c777e..6f220271a 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -1993,6 +1993,21 @@ int ast_prod(struct ast_channel *chan);
int ast_set_read_format_path(struct ast_channel *chan, struct ast_format *raw_format, struct ast_format *core_format);
/*!
+ * \brief Set specific write path on channel.
+ * \since 13.13.0
+ *
+ * \param chan Channel to setup write path.
+ * \param core_format What the core wants to write.
+ * \param raw_format Raw write format.
+ *
+ * \pre chan is locked
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int ast_set_write_format_path(struct ast_channel *chan, struct ast_format *core_format, struct ast_format *raw_format);
+
+/*!
* \brief Sets read format on channel chan from capabilities
* Set read format for channel to whichever component of "format" is best.
* \param chan channel to change
diff --git a/include/asterisk/format.h b/include/asterisk/format.h
index a5ca03818..b01592d16 100644
--- a/include/asterisk/format.h
+++ b/include/asterisk/format.h
@@ -299,6 +299,24 @@ void ast_format_set_attribute_data(struct ast_format *format, void *attribute_da
const char *ast_format_get_name(const struct ast_format *format);
/*!
+ * \brief Get the channel count on a format
+ *
+ * \param The media format
+ *
+ * \return Currently set channel count
+ */
+unsigned int ast_format_get_channel_count(const struct ast_format *format);
+
+/*!
+ * \brief Set the channel count on a format
+ *
+ * \param format The media format
+ * \param channel_count The number of audio channels used
+ *
+ */
+void ast_format_set_channel_count(struct ast_format *format, unsigned int channel_count);
+
+/*!
* \brief Get the codec associated with a format
*
* \param format The media format
diff --git a/include/asterisk/options.h b/include/asterisk/options.h
index 345bacf6c..ff35c16c4 100644
--- a/include/asterisk/options.h
+++ b/include/asterisk/options.h
@@ -132,6 +132,20 @@ enum ast_option_flags {
#define ast_opt_generic_plc ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC)
#define ast_opt_ref_debug ast_test_flag(&ast_options, AST_OPT_FLAG_REF_DEBUG)
+/*! Maximum log level defined by PJPROJECT. */
+#define MAX_PJ_LOG_MAX_LEVEL 6
+/*!
+ * Normal PJPROJECT active log level used by Asterisk.
+ *
+ * These levels are usually mapped to Error and
+ * Warning Asterisk log levels which shouldn't
+ * normally be suppressed.
+ */
+#define DEFAULT_PJ_LOG_MAX_LEVEL 2
+
+/*! Current pjproject logging level */
+extern int ast_option_pjproject_log_level;
+
extern struct ast_flags ast_options;
extern int option_verbose;
diff --git a/include/asterisk/tcptls.h b/include/asterisk/tcptls.h
index 883cb9229..1e3a7524b 100644
--- a/include/asterisk/tcptls.h
+++ b/include/asterisk/tcptls.h
@@ -94,6 +94,9 @@ struct ast_tls_config {
char *capath;
struct ast_flags flags;
SSL_CTX *ssl_ctx;
+ char certhash[41];
+ char pvthash[41];
+ char cahash[41];
};
/*! \page AstTlsOverview TLS Implementation Overview
@@ -138,6 +141,7 @@ struct ast_tcptls_session_args {
void (*periodic_fn)(void *);/*!< something we may want to run before after select on the accept socket */
void *(*worker_fn)(void *); /*!< the function in charge of doing the actual work */
const char *name;
+ struct ast_tls_config *old_tls_cfg; /*!< copy of the SSL configuration to determine whether changes have been made */
};
/*! \brief
diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h
index 2378c6971..423d73b26 100644
--- a/include/asterisk/utils.h
+++ b/include/asterisk/utils.h
@@ -1126,4 +1126,13 @@ int ast_file_is_readable(const char *filename);
*/
int ast_compare_versions(const char *version1, const char *version2);
+/*
+ * \brief Test that an OS supports IPv6 Networking.
+ * \since 13.14.0
+ *
+ * \return True (non-zero) if the IPv6 supported.
+ * \return False (zero) if the OS doesn't support IPv6.
+ */
+int ast_check_ipv6(void);
+
#endif /* _ASTERISK_UTILS_H */
diff --git a/main/Makefile b/main/Makefile
index 0c1b11ed8..95c3c70c6 100644
--- a/main/Makefile
+++ b/main/Makefile
@@ -287,7 +287,7 @@ endif
$(ASTPJ_LIB).$(ASTPJ_SO_VERSION): _ASTLDFLAGS+=-Wl,-soname=$(ASTPJ_LIB) $(PJ_LDFLAGS)
$(ASTPJ_LIB).$(ASTPJ_SO_VERSION): _ASTCFLAGS+=-fPIC -DAST_MODULE=\"asteriskpj\" -DAST_NOT_MODULE $(PJ_CFLAGS)
-$(ASTPJ_LIB).$(ASTPJ_SO_VERSION): LIBS+=$(PJPROJECT_LDLIBS) -lssl -lcrypto -luuid -lm -lpthread
+$(ASTPJ_LIB).$(ASTPJ_SO_VERSION): LIBS+=$(PJPROJECT_LDLIBS) -lssl -lcrypto -luuid -lm -lpthread $(RT_LIB)
ifeq ($(GNU_LD),1)
$(ASTPJ_LIB).$(ASTPJ_SO_VERSION): SO_SUPPRESS_SYMBOLS=-Wl,--version-script,libasteriskpj.exports,--warn-common
endif
@@ -312,7 +312,7 @@ ASTPJ_LIB:=libasteriskpj.dylib
# /lib or /usr/lib
$(ASTPJ_LIB): _ASTLDFLAGS+=-dynamiclib -install_name $(ASTLIBDIR)/$(ASTPJ_LIB) $(PJ_LDFLAGS)
$(ASTPJ_LIB): _ASTCFLAGS+=-fPIC -DAST_MODULE=\"asteriskpj\" $(PJ_CFLAGS) -DAST_NOT_MODULE
-$(ASTPJ_LIB): LIBS+=$(PJPROJECT_LIBS) -lssl -lcrypto -luuid -lm -lrt -lpthread
+$(ASTPJ_LIB): LIBS+=$(PJPROJECT_LIBS) -lssl -lcrypto -luuid -lm -lpthread $(RT_LIB)
$(ASTPJ_LIB): SOLINK=$(DYLINK)
# Special rules for building a shared library (not a dynamically loadable module)
diff --git a/main/asterisk.c b/main/asterisk.c
index 4a6567f73..338c1f53b 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -330,6 +330,7 @@ int ast_verb_sys_level;
int option_verbose; /*!< Verbosity level */
int option_debug; /*!< Debug level */
+int ast_option_pjproject_log_level;
double ast_option_maxload; /*!< Max load avg on system */
int ast_option_maxcalls; /*!< Max number of active calls */
int ast_option_maxfiles; /*!< Max number of open file handles (files, sockets) */
@@ -1669,7 +1670,6 @@ static void _urg_handler(int num)
static struct sigaction urg_handler = {
.sa_handler = _urg_handler,
- .sa_flags = SA_RESTART,
};
static void _hup_handler(int num)
@@ -3758,6 +3758,37 @@ static void ast_readconfig(void)
ast_config_destroy(cfg);
}
+static void read_pjproject_startup_options(void)
+{
+ struct ast_config *cfg;
+ struct ast_variable *v;
+ struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE | CONFIG_FLAG_NOREALTIME };
+
+ ast_option_pjproject_log_level = DEFAULT_PJ_LOG_MAX_LEVEL;
+
+ cfg = ast_config_load2("pjproject.conf", "" /* core, can't reload */, config_flags);
+ if (!cfg
+ || cfg == CONFIG_STATUS_FILEUNCHANGED
+ || cfg == CONFIG_STATUS_FILEINVALID) {
+ /* We'll have to use defaults */
+ return;
+ }
+
+ for (v = ast_variable_browse(cfg, "startup"); v; v = v->next) {
+ if (!strcasecmp(v->name, "log_level")) {
+ if (sscanf(v->value, "%30d", &ast_option_pjproject_log_level) != 1) {
+ ast_option_pjproject_log_level = DEFAULT_PJ_LOG_MAX_LEVEL;
+ } else if (ast_option_pjproject_log_level < 0) {
+ ast_option_pjproject_log_level = 0;
+ } else if (MAX_PJ_LOG_MAX_LEVEL < ast_option_pjproject_log_level) {
+ ast_option_pjproject_log_level = MAX_PJ_LOG_MAX_LEVEL;
+ }
+ }
+ }
+
+ ast_config_destroy(cfg);
+}
+
static void *monitor_sig_flags(void *unused)
{
for (;;) {
@@ -4514,6 +4545,7 @@ static void asterisk_daemon(int isroot, const char *runuser, const char *rungrou
check_init(ast_timing_init(), "Timing");
check_init(ast_ssl_init(), "SSL");
+ read_pjproject_startup_options();
check_init(ast_pj_init(), "Embedded PJProject");
check_init(app_init(), "App Core");
check_init(devstate_init(), "Device State Core");
diff --git a/main/channel.c b/main/channel.c
index bd5f35172..00cfa31aa 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -1070,16 +1070,15 @@ void ast_channel_start_defer_frames(struct ast_channel *chan, int defer_hangups)
void ast_channel_stop_defer_frames(struct ast_channel *chan)
{
+ struct ast_frame *f;
+
ast_clear_flag(ast_channel_flags(chan), AST_FLAG_DEFER_FRAMES);
/* Move the deferred frames onto the channel read queue, ahead of other queued frames */
- ast_queue_frame_head(chan, AST_LIST_FIRST(ast_channel_deferred_readq(chan)));
- /* ast_frfree will mosey down the list and free them all */
- if (!AST_LIST_EMPTY(ast_channel_deferred_readq(chan))) {
- ast_frfree(AST_LIST_FIRST(ast_channel_deferred_readq(chan)));
+ while ((f = AST_LIST_REMOVE_HEAD(ast_channel_deferred_readq(chan), frame_list))) {
+ ast_queue_frame_head(chan, f);
+ ast_frfree(f);
}
- /* Reset the list to be empty */
- AST_LIST_HEAD_INIT_NOLOCK(ast_channel_deferred_readq(chan));
}
static int __ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int head, struct ast_frame *after)
@@ -3901,10 +3900,10 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
struct ast_frame *dup;
dup = ast_frdup(f);
- AST_LIST_INSERT_TAIL(ast_channel_deferred_readq(chan), dup, frame_list);
+ AST_LIST_INSERT_HEAD(ast_channel_deferred_readq(chan), dup, frame_list);
}
} else {
- AST_LIST_INSERT_TAIL(ast_channel_deferred_readq(chan), f, frame_list);
+ AST_LIST_INSERT_HEAD(ast_channel_deferred_readq(chan), f, frame_list);
AST_LIST_REMOVE_CURRENT(frame_list);
}
}
@@ -5474,6 +5473,42 @@ int ast_set_read_format_path(struct ast_channel *chan, struct ast_format *raw_fo
return 0;
}
+int ast_set_write_format_path(struct ast_channel *chan, struct ast_format *core_format, struct ast_format *raw_format)
+{
+ struct ast_trans_pvt *trans_old;
+ struct ast_trans_pvt *trans_new;
+
+ if (ast_format_cmp(ast_channel_rawwriteformat(chan), raw_format) == AST_FORMAT_CMP_EQUAL
+ && ast_format_cmp(ast_channel_writeformat(chan), core_format) == AST_FORMAT_CMP_EQUAL) {
+ /* Nothing to setup */
+ return 0;
+ }
+
+ ast_debug(1, "Channel %s setting write format path: %s -> %s\n",
+ ast_channel_name(chan),
+ ast_format_get_name(core_format),
+ ast_format_get_name(raw_format));
+
+ /* Setup new translation path. */
+ if (ast_format_cmp(raw_format, core_format) != AST_FORMAT_CMP_EQUAL) {
+ trans_new = ast_translator_build_path(raw_format, core_format);
+ if (!trans_new) {
+ return -1;
+ }
+ } else {
+ /* No translation needed. */
+ trans_new = NULL;
+ }
+ trans_old = ast_channel_writetrans(chan);
+ if (trans_old) {
+ ast_translator_free_path(trans_old);
+ }
+ ast_channel_writetrans_set(chan, trans_new);
+ ast_channel_set_rawwriteformat(chan, raw_format);
+ ast_channel_set_writeformat(chan, core_format);
+ return 0;
+}
+
struct set_format_access {
const char *direction;
struct ast_trans_pvt *(*get_trans)(const struct ast_channel *chan);
diff --git a/main/dns.c b/main/dns.c
index 3b198a0f3..76f8075e5 100644
--- a/main/dns.c
+++ b/main/dns.c
@@ -555,7 +555,7 @@ enum ast_dns_search_result ast_search_dns_ex(void *context, const char *dname, i
if (dns_response_len < 0) {
ast_debug(1, "DNS search failed for %s\n", dname);
- response_handler(context, (unsigned char *)"", 0, ns_r_nxdomain);
+ response_handler(context, (unsigned char *)"", 0, NXDOMAIN);
return AST_DNS_SEARCH_FAILURE;
}
diff --git a/main/dns_core.c b/main/dns_core.c
index e1cbc2191..a243b4bdd 100644
--- a/main/dns_core.c
+++ b/main/dns_core.c
@@ -112,7 +112,7 @@ int ast_dns_result_get_lowest_ttl(const struct ast_dns_result *result)
int ttl = 0;
const struct ast_dns_record *record;
- if (ast_dns_result_get_rcode(result) == ns_r_nxdomain) {
+ if (ast_dns_result_get_rcode(result) == NXDOMAIN) {
return 0;
}
@@ -195,7 +195,7 @@ struct ast_dns_query *dns_query_alloc(const char *name, int rr_type, int rr_clas
if (ast_strlen_zero(name)) {
ast_log(LOG_WARNING, "Could not perform asynchronous resolution, no name provided\n");
return NULL;
- } else if (rr_type > ns_t_max) {
+ } else if (rr_type > 65536) {
ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', resource record type '%d' exceeds maximum\n",
name, rr_type);
return NULL;
@@ -203,7 +203,7 @@ struct ast_dns_query *dns_query_alloc(const char *name, int rr_type, int rr_clas
ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', invalid resource record type '%d'\n",
name, rr_type);
return NULL;
- } else if (rr_class > ns_c_max) {
+ } else if (rr_class > 65536) {
ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', resource record class '%d' exceeds maximum\n",
name, rr_class);
return NULL;
@@ -317,7 +317,7 @@ int ast_dns_resolve(const char *name, int rr_type, int rr_class, struct ast_dns_
if (ast_strlen_zero(name)) {
ast_log(LOG_WARNING, "Could not perform synchronous resolution, no name provided\n");
return -1;
- } else if (rr_type > ns_t_max) {
+ } else if (rr_type > 65536) {
ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', resource record type '%d' exceeds maximum\n",
name, rr_type);
return -1;
@@ -325,7 +325,7 @@ int ast_dns_resolve(const char *name, int rr_type, int rr_class, struct ast_dns_
ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', invalid resource record type '%d'\n",
name, rr_type);
return -1;
- } else if (rr_class > ns_c_max) {
+ } else if (rr_class > 65536) {
ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', resource record class '%d' exceeds maximum\n",
name, rr_class);
return -1;
@@ -443,8 +443,8 @@ static struct ast_dns_record *generic_record_alloc(struct ast_dns_query *query,
typedef struct ast_dns_record *(*dns_alloc_fn)(struct ast_dns_query *query, const char *data, const size_t size);
static dns_alloc_fn dns_alloc_table [] = {
- [ns_t_naptr] = dns_naptr_alloc,
- [ns_t_srv] = dns_srv_alloc,
+ [T_NAPTR] = dns_naptr_alloc,
+ [T_SRV] = dns_srv_alloc,
};
static struct ast_dns_record *allocate_dns_record(int rr_type, struct ast_dns_query *query, const char *data, const size_t size)
@@ -462,7 +462,7 @@ int ast_dns_resolver_add_record(struct ast_dns_query *query, int rr_type, int rr
ast_debug(2, "Query '%p': Could not add record, invalid resource record type '%d'\n",
query, rr_type);
return -1;
- } else if (rr_type > ns_t_max) {
+ } else if (rr_type > 65536) {
ast_debug(2, "Query '%p': Could not add record, resource record type '%d' exceeds maximum\n",
query, rr_type);
return -1;
@@ -470,7 +470,7 @@ int ast_dns_resolver_add_record(struct ast_dns_query *query, int rr_type, int rr
ast_debug(2, "Query '%p': Could not add record, invalid resource record class '%d'\n",
query, rr_class);
return -1;
- } else if (rr_class > ns_c_max) {
+ } else if (rr_class > 65536) {
ast_debug(2, "Query '%p': Could not add record, resource record class '%d' exceeds maximum\n",
query, rr_class);
return -1;
@@ -507,8 +507,8 @@ int ast_dns_resolver_add_record(struct ast_dns_query *query, int rr_type, int rr
typedef void (*dns_sort_fn)(struct ast_dns_result *result);
static dns_sort_fn dns_sort_table [] = {
- [ns_t_naptr] = dns_naptr_sort,
- [ns_t_srv] = dns_srv_sort,
+ [T_NAPTR] = dns_naptr_sort,
+ [T_SRV] = dns_srv_sort,
};
static void sort_result(int rr_type, struct ast_dns_result *result)
diff --git a/main/dns_naptr.c b/main/dns_naptr.c
index d24e1b5f4..5490b5568 100644
--- a/main/dns_naptr.c
+++ b/main/dns_naptr.c
@@ -30,6 +30,7 @@
#include "asterisk.h"
#include <arpa/nameser.h>
+#include <netinet/in.h>
#include <resolv.h>
#include <regex.h>
@@ -590,7 +591,7 @@ const char *ast_dns_naptr_get_flags(const struct ast_dns_record *record)
{
struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
- ast_assert(ast_dns_record_get_rr_type(record) == ns_t_naptr);
+ ast_assert(ast_dns_record_get_rr_type(record) == T_NAPTR);
return naptr->flags;
}
@@ -598,7 +599,7 @@ const char *ast_dns_naptr_get_service(const struct ast_dns_record *record)
{
struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
- ast_assert(ast_dns_record_get_rr_type(record) == ns_t_naptr);
+ ast_assert(ast_dns_record_get_rr_type(record) == T_NAPTR);
return naptr->service;
}
@@ -606,7 +607,7 @@ const char *ast_dns_naptr_get_regexp(const struct ast_dns_record *record)
{
struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
- ast_assert(ast_dns_record_get_rr_type(record) == ns_t_naptr);
+ ast_assert(ast_dns_record_get_rr_type(record) == T_NAPTR);
return naptr->regexp;
}
@@ -614,7 +615,7 @@ const char *ast_dns_naptr_get_replacement(const struct ast_dns_record *record)
{
struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
- ast_assert(ast_dns_record_get_rr_type(record) == ns_t_naptr);
+ ast_assert(ast_dns_record_get_rr_type(record) == T_NAPTR);
return naptr->replacement;
}
@@ -622,7 +623,7 @@ unsigned short ast_dns_naptr_get_order(const struct ast_dns_record *record)
{
struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
- ast_assert(ast_dns_record_get_rr_type(record) == ns_t_naptr);
+ ast_assert(ast_dns_record_get_rr_type(record) == T_NAPTR);
return naptr->order;
}
@@ -630,6 +631,6 @@ unsigned short ast_dns_naptr_get_preference(const struct ast_dns_record *record)
{
struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
- ast_assert(ast_dns_record_get_rr_type(record) == ns_t_naptr);
+ ast_assert(ast_dns_record_get_rr_type(record) == T_NAPTR);
return naptr->preference;
}
diff --git a/main/dns_srv.c b/main/dns_srv.c
index 9d36fb61f..b562e3257 100644
--- a/main/dns_srv.c
+++ b/main/dns_srv.c
@@ -183,7 +183,7 @@ const char *ast_dns_srv_get_host(const struct ast_dns_record *record)
{
struct ast_dns_srv_record *srv = (struct ast_dns_srv_record *) record;
- ast_assert(ast_dns_record_get_rr_type(record) == ns_t_srv);
+ ast_assert(ast_dns_record_get_rr_type(record) == T_SRV);
return srv->host;
}
@@ -191,7 +191,7 @@ unsigned short ast_dns_srv_get_priority(const struct ast_dns_record *record)
{
struct ast_dns_srv_record *srv = (struct ast_dns_srv_record *) record;
- ast_assert(ast_dns_record_get_rr_type(record) == ns_t_srv);
+ ast_assert(ast_dns_record_get_rr_type(record) == T_SRV);
return srv->priority;
}
@@ -199,7 +199,7 @@ unsigned short ast_dns_srv_get_weight(const struct ast_dns_record *record)
{
struct ast_dns_srv_record *srv = (struct ast_dns_srv_record *) record;
- ast_assert(ast_dns_record_get_rr_type(record) == ns_t_srv);
+ ast_assert(ast_dns_record_get_rr_type(record) == T_SRV);
return srv->weight;
}
@@ -207,6 +207,6 @@ unsigned short ast_dns_srv_get_port(const struct ast_dns_record *record)
{
struct ast_dns_srv_record *srv = (struct ast_dns_srv_record *) record;
- ast_assert(ast_dns_record_get_rr_type(record) == ns_t_srv);
+ ast_assert(ast_dns_record_get_rr_type(record) == T_SRV);
return srv->port;
}
diff --git a/main/format.c b/main/format.c
index b5e577913..5ae5ad986 100644
--- a/main/format.c
+++ b/main/format.c
@@ -49,6 +49,8 @@ struct ast_format {
void *attribute_data;
/*! \brief Pointer to the optional format interface */
const struct ast_format_interface *interface;
+ /*! \brief The number if audio channels used, if more than one an interleaved format is required */
+ unsigned int channel_count;
};
/*! \brief Structure used when registering a format interface */
@@ -175,6 +177,16 @@ void ast_format_set_attribute_data(struct ast_format *format, void *attribute_da
format->attribute_data = attribute_data;
}
+unsigned int ast_format_get_channel_count(const struct ast_format *format)
+{
+ return format->channel_count;
+}
+
+void ast_format_set_channel_count(struct ast_format *format, unsigned int channel_count)
+{
+ format->channel_count = channel_count;
+}
+
/*! \brief Destructor for media formats */
static void format_destroy(void *obj)
{
@@ -199,6 +211,7 @@ struct ast_format *ast_format_create_named(const char *format_name, struct ast_c
}
format->name = format_name;
format->codec = ao2_bump(codec);
+ format->channel_count = 1;
format_interface = ao2_find(interfaces, codec->name, OBJ_SEARCH_KEY);
if (format_interface) {
diff --git a/main/iostream.c b/main/iostream.c
index 46abc18a5..a20a04896 100644
--- a/main/iostream.c
+++ b/main/iostream.c
@@ -16,10 +16,11 @@
* at the top of the source tree.
*/
+#include "asterisk.h"
+
#include <fcntl.h>
#include <stdarg.h>
-#include "asterisk.h"
#include "asterisk/utils.h"
#include "asterisk/astobj2.h"
#include "asterisk/iostream.h"
@@ -461,9 +462,19 @@ int ast_iostream_close(struct ast_iostream *stream)
SSL_get_error(stream->ssl, res));
}
+#if defined(OPENSSL_API_COMPAT) && OPENSSL_API_COMPAT >= 0x10100000L
+ if (!SSL_is_server(stream->ssl)) {
+#else
if (!stream->ssl->server) {
+#endif
/* For client threads, ensure that the error stack is cleared */
+#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+ ERR_remove_thread_state(NULL);
+#else
ERR_remove_state(0);
+#endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L */
+#endif /* !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L */
}
SSL_free(stream->ssl);
diff --git a/main/libasteriskpj.c b/main/libasteriskpj.c
index 22660e686..0f893a2cf 100644
--- a/main/libasteriskpj.c
+++ b/main/libasteriskpj.c
@@ -35,6 +35,7 @@
#include <pjlib.h>
#endif
+#include "asterisk/options.h"
#include "asterisk/_private.h" /* ast_pj_init() */
/*!
@@ -44,6 +45,7 @@
int ast_pj_init(void)
{
#ifdef HAVE_PJPROJECT_BUNDLED
+ pj_log_set_level(ast_option_pjproject_log_level);
pj_init();
#endif
return 0;
diff --git a/main/libasteriskssl.c b/main/libasteriskssl.c
index 16a1aa739..9905b150c 100644
--- a/main/libasteriskssl.c
+++ b/main/libasteriskssl.c
@@ -65,13 +65,14 @@ static void ssl_lock(int mode, int n, const char *file, int line)
return;
}
- if (mode & CRYPTO_LOCK) {
+ if (mode & 0x1) {
ast_mutex_lock(&ssl_locks[n]);
} else {
ast_mutex_unlock(&ssl_locks[n]);
}
}
+#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L
int SSL_library_init(void)
{
#if defined(AST_DEVMODE)
@@ -113,6 +114,7 @@ void ERR_free_strings(void)
{
/* we can't allow this to be called, ever */
}
+#endif /* !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L */
#endif /* HAVE_OPENSSL */
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index 4fc1414f0..3ef2d876b 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -2493,7 +2493,7 @@ static struct ast_manager_event_blob *rtcp_report_to_ami(struct stasis_message *
if (type == AST_RTP_RTCP_SR) {
ast_str_append(&packet_string, 0, "SentNTP: %lu.%06lu\r\n",
(unsigned long)payload->report->sender_information.ntp_timestamp.tv_sec,
- (unsigned long)payload->report->sender_information.ntp_timestamp.tv_usec * 4096);
+ (unsigned long)payload->report->sender_information.ntp_timestamp.tv_usec);
ast_str_append(&packet_string, 0, "SentRTP: %u\r\n",
payload->report->sender_information.rtp_timestamp);
ast_str_append(&packet_string, 0, "SentPackets: %u\r\n",
diff --git a/main/tcptls.c b/main/tcptls.c
index c8ebab434..b20e04ef8 100644
--- a/main/tcptls.c
+++ b/main/tcptls.c
@@ -36,6 +36,7 @@
#endif
#include <signal.h>
+#include <sys/stat.h>
#include "asterisk/compat.h"
#include "asterisk/tcptls.h"
@@ -46,6 +47,7 @@
#include "asterisk/manager.h"
#include "asterisk/astobj2.h"
#include "asterisk/pbx.h"
+#include "asterisk/app.h"
static void session_instance_destructor(void *obj)
{
@@ -310,7 +312,7 @@ static int __ssl_setup(struct ast_tls_config *cfg, int client)
}
if (client) {
-#ifndef OPENSSL_NO_SSL2
+#if !defined(OPENSSL_NO_SSL2) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
if (ast_test_flag(&cfg->flags, AST_SSL_SSLV2_CLIENT)) {
ast_log(LOG_WARNING, "Usage of SSLv2 is discouraged due to known vulnerabilities. Please use 'tlsv1' or leave the TLS method unspecified!\n");
cfg->ssl_ctx = SSL_CTX_new(SSLv2_client_method());
@@ -588,9 +590,64 @@ void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
{
int flags;
int x = 1;
+ int tls_changed = 0;
+
+ if (desc->tls_cfg) {
+ char hash[41];
+ char *str = NULL;
+ struct stat st;
+
+ /* Store the hashes of the TLS certificate etc. */
+ if (stat(desc->tls_cfg->certfile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->certfile))) {
+ memset(hash, 0, 41);
+ } else {
+ ast_sha1_hash(hash, str);
+ }
+ ast_free(str);
+ str = NULL;
+ memcpy(desc->tls_cfg->certhash, hash, 41);
+ if (stat(desc->tls_cfg->pvtfile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->pvtfile))) {
+ memset(hash, 0, 41);
+ } else {
+ ast_sha1_hash(hash, str);
+ }
+ ast_free(str);
+ str = NULL;
+ memcpy(desc->tls_cfg->pvthash, hash, 41);
+ if (stat(desc->tls_cfg->cafile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->cafile))) {
+ memset(hash, 0, 41);
+ } else {
+ ast_sha1_hash(hash, str);
+ }
+ ast_free(str);
+ str = NULL;
+ memcpy(desc->tls_cfg->cahash, hash, 41);
+
+ /* Check whether TLS configuration has changed */
+ if (!desc->old_tls_cfg) { /* No previous configuration */
+ tls_changed = 1;
+ desc->old_tls_cfg = ast_calloc(1, sizeof(*desc->old_tls_cfg));
+ } else if (memcmp(desc->tls_cfg->certhash, desc->old_tls_cfg->certhash, 41)) {
+ tls_changed = 1;
+ } else if (memcmp(desc->tls_cfg->pvthash, desc->old_tls_cfg->pvthash, 41)) {
+ tls_changed = 1;
+ } else if (strcmp(desc->tls_cfg->cipher, desc->old_tls_cfg->cipher)) {
+ tls_changed = 1;
+ } else if (memcmp(desc->tls_cfg->cahash, desc->old_tls_cfg->cahash, 41)) {
+ tls_changed = 1;
+ } else if (strcmp(desc->tls_cfg->capath, desc->old_tls_cfg->capath)) {
+ tls_changed = 1;
+ } else if (memcmp(&desc->tls_cfg->flags, &desc->old_tls_cfg->flags, sizeof(desc->tls_cfg->flags))) {
+ tls_changed = 1;
+ }
+
+ if (tls_changed) {
+ ast_debug(1, "Changed parameters for %s found\n", desc->name);
+ }
+ }
/* Do nothing if nothing has changed */
- if (!ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) {
+ if (!tls_changed && !ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) {
ast_debug(1, "Nothing changed in %s\n", desc->name);
return;
}
@@ -646,6 +703,22 @@ void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
/* Set current info */
ast_sockaddr_copy(&desc->old_address, &desc->local_address);
+ if (desc->old_tls_cfg) {
+ ast_free(desc->old_tls_cfg->certfile);
+ ast_free(desc->old_tls_cfg->pvtfile);
+ ast_free(desc->old_tls_cfg->cipher);
+ ast_free(desc->old_tls_cfg->cafile);
+ ast_free(desc->old_tls_cfg->capath);
+ desc->old_tls_cfg->certfile = ast_strdup(desc->tls_cfg->certfile);
+ desc->old_tls_cfg->pvtfile = ast_strdup(desc->tls_cfg->pvtfile);
+ desc->old_tls_cfg->cipher = ast_strdup(desc->tls_cfg->cipher);
+ desc->old_tls_cfg->cafile = ast_strdup(desc->tls_cfg->cafile);
+ desc->old_tls_cfg->capath = ast_strdup(desc->tls_cfg->capath);
+ memcpy(desc->old_tls_cfg->certhash, desc->tls_cfg->certhash, 41);
+ memcpy(desc->old_tls_cfg->pvthash, desc->tls_cfg->pvthash, 41);
+ memcpy(desc->old_tls_cfg->cahash, desc->tls_cfg->cahash, 41);
+ memcpy(&desc->old_tls_cfg->flags, &desc->tls_cfg->flags, sizeof(desc->old_tls_cfg->flags));
+ }
return;
@@ -676,6 +749,17 @@ void ast_tcptls_server_stop(struct ast_tcptls_session_args *desc)
close(desc->accept_fd);
}
desc->accept_fd = -1;
+
+ if (desc->old_tls_cfg) {
+ ast_free(desc->old_tls_cfg->certfile);
+ ast_free(desc->old_tls_cfg->pvtfile);
+ ast_free(desc->old_tls_cfg->cipher);
+ ast_free(desc->old_tls_cfg->cafile);
+ ast_free(desc->old_tls_cfg->capath);
+ ast_free(desc->old_tls_cfg);
+ desc->old_tls_cfg = NULL;
+ }
+
ast_debug(2, "Stopped server :: %s\n", desc->name);
}
diff --git a/main/utils.c b/main/utils.c
index 2c56af3cd..2033664b8 100644
--- a/main/utils.c
+++ b/main/utils.c
@@ -2391,6 +2391,18 @@ char *ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size)
return NULL;
}
+int ast_check_ipv6(void)
+{
+ int udp6_socket = socket(AF_INET6, SOCK_DGRAM, 0);
+
+ if (udp6_socket < 0) {
+ return 0;
+ }
+
+ close(udp6_socket);
+ return 1;
+}
+
void DO_CRASH_NORETURN ast_do_crash(void)
{
#if defined(DO_CRASH)
diff --git a/pbx/pbx_lua.c b/pbx/pbx_lua.c
index 01f468de0..0754990d6 100644
--- a/pbx/pbx_lua.c
+++ b/pbx/pbx_lua.c
@@ -60,7 +60,7 @@ static char *registrar = "pbx_lua";
* applications might return */
#define LUA_GOTO_DETECTED 5
-static char *lua_read_extensions_file(lua_State *L, long *size);
+static char *lua_read_extensions_file(lua_State *L, long *size, int *file_not_openable);
static int lua_load_extensions(lua_State *L, struct ast_channel *chan);
static int lua_reload_extensions(lua_State *L);
static void lua_free_extensions(void);
@@ -1070,12 +1070,13 @@ static int lua_extension_cmp(lua_State *L)
*
* \param L the lua_State to use
* \param size a pointer to store the size of the buffer
+ * \param file_not_openable a pointer to store if config file could be opened
*
* \note The caller is expected to free the buffer at some point.
*
* \return a pointer to the buffer
*/
-static char *lua_read_extensions_file(lua_State *L, long *size)
+static char *lua_read_extensions_file(lua_State *L, long *size, int *file_not_openable)
{
FILE *f;
int error_func;
@@ -1090,6 +1091,8 @@ static char *lua_read_extensions_file(lua_State *L, long *size)
lua_pushstring(L, strerror(errno));
lua_concat(L, 4);
+ *file_not_openable = 1;
+
return NULL;
}
@@ -1199,10 +1202,14 @@ static int lua_reload_extensions(lua_State *L)
{
long size = 0;
char *data = NULL;
+ int file_not_openable = 0;
luaL_openlibs(L);
- if (!(data = lua_read_extensions_file(L, &size))) {
+ if (!(data = lua_read_extensions_file(L, &size, &file_not_openable))) {
+ if (file_not_openable) {
+ return -1;
+ }
return 1;
}
@@ -1621,17 +1628,24 @@ static struct ast_switch lua_switch = {
static int load_or_reload_lua_stuff(void)
{
int res = AST_MODULE_LOAD_SUCCESS;
+ int loaded = 0;
lua_State *L = luaL_newstate();
if (!L) {
ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
- return AST_MODULE_LOAD_DECLINE;
+ return AST_MODULE_LOAD_FAILURE;
}
- if (lua_reload_extensions(L)) {
+ loaded = lua_reload_extensions(L);
+ if (loaded) {
const char *error = lua_tostring(L, -1);
ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
- res = AST_MODULE_LOAD_DECLINE;
+
+ if (loaded < 0) {
+ res = AST_MODULE_LOAD_DECLINE;
+ } else {
+ res = AST_MODULE_LOAD_FAILURE;
+ }
}
if (!res) {
@@ -1664,7 +1678,7 @@ static int load_module(void)
if (ast_register_switch(&lua_switch)) {
ast_log(LOG_ERROR, "Unable to register LUA PBX switch\n");
- return AST_MODULE_LOAD_DECLINE;
+ return AST_MODULE_LOAD_FAILURE;
}
return AST_MODULE_LOAD_SUCCESS;
diff --git a/res/res_calendar_caldav.c b/res/res_calendar_caldav.c
index 11650375b..8a603cf47 100644
--- a/res/res_calendar_caldav.c
+++ b/res/res_calendar_caldav.c
@@ -480,7 +480,7 @@ static void handle_start_element(void *data, const xmlChar *fullname, const xmlC
{
struct xmlstate *state = data;
- if (!xmlStrcasecmp(fullname, BAD_CAST "C:calendar-data")) {
+ if (!xmlStrcasecmp(fullname, BAD_CAST "C:calendar-data") || !xmlStrcasecmp(fullname, BAD_CAST "caldav:calendar-data")) {
state->in_caldata = 1;
ast_str_reset(state->cdata);
}
@@ -494,7 +494,7 @@ static void handle_end_element(void *data, const xmlChar *name)
icalcomponent *iter;
icalcomponent *comp;
- if (xmlStrcasecmp(name, BAD_CAST "C:calendar-data")) {
+ if (xmlStrcasecmp(name, BAD_CAST "C:calendar-data") && xmlStrcasecmp(name, BAD_CAST "caldav:calendar-data")) {
return;
}
diff --git a/res/res_format_attr_opus.c b/res/res_format_attr_opus.c
index 81a07a1f6..45aa5e5c6 100644
--- a/res/res_format_attr_opus.c
+++ b/res/res_format_attr_opus.c
@@ -94,6 +94,7 @@ static int opus_clone(const struct ast_format *src, struct ast_format *dst)
ao2_bump(attr->data);
ast_format_set_attribute_data(dst, attr);
+ ast_format_set_channel_count(dst, ast_format_get_channel_count(src));
return 0;
}
@@ -145,6 +146,9 @@ static struct ast_format *opus_parse_sdp_fmtp(const struct ast_format *format, c
sdp_fmtp_get(attributes, CODEC_OPUS_ATTR_PTIME, &attr->ptime);
sdp_fmtp_get(attributes, CODEC_OPUS_ATTR_MAX_AVERAGE_BITRATE, &attr->maxbitrate);
sdp_fmtp_get(attributes, CODEC_OPUS_ATTR_STEREO, &attr->stereo);
+ if (attr->stereo) {
+ ast_format_set_channel_count(cloned, 2);
+ }
sdp_fmtp_get(attributes, CODEC_OPUS_ATTR_SPROP_STEREO, &attr->spropstereo);
sdp_fmtp_get(attributes, CODEC_OPUS_ATTR_CBR, &attr->cbr);
sdp_fmtp_get(attributes, CODEC_OPUS_ATTR_FEC, &attr->fec);
@@ -238,6 +242,10 @@ static struct ast_format *opus_getjoint(const struct ast_format *format1, const
if (!jointformat) {
return NULL;
}
+
+ if (ast_format_get_channel_count(format1) == 2 || ast_format_get_channel_count(format2) == 2) {
+ ast_format_set_channel_count(jointformat, 2);
+ }
attr_res = ast_format_get_attribute_data(jointformat);
attr_res->dtx = attr1->dtx || attr2->dtx ? 1 : 0;
diff --git a/res/res_pjproject.c b/res/res_pjproject.c
index 66c95f2b7..476defb41 100644
--- a/res/res_pjproject.c
+++ b/res/res_pjproject.c
@@ -41,6 +41,27 @@
<configInfo name="res_pjproject" language="en_US">
<synopsis>pjproject common configuration</synopsis>
<configFile name="pjproject.conf">
+ <configObject name="startup">
+ <synopsis>Asterisk startup time options for PJPROJECT</synopsis>
+ <description>
+ <note><para>The id of this object, as well as its type, must be
+ 'startup' or it won't be found.</para></note>
+ </description>
+ <configOption name="type">
+ <synopsis>Must be of type 'startup'.</synopsis>
+ </configOption>
+ <configOption name="log_level" default="2">
+ <synopsis>Initial maximum pjproject logging level to log.</synopsis>
+ <description>
+ <para>Valid values are: 0-6, and default</para>
+ <note><para>
+ This option is needed very early in the startup process
+ so it can only be read from config files because the
+ modules for other methods have not been loaded yet.
+ </para></note>
+ </description>
+ </configOption>
+ </configObject>
<configObject name="log_mappings">
<synopsis>PJPROJECT to Asterisk Log Level Mapping</synopsis>
<description><para>Warnings and errors in the pjproject libraries are generally handled
@@ -64,7 +85,7 @@
<configOption name="asterisk_notice" default="">
<synopsis>A comma separated list of pjproject log levels to map to Asterisk LOG_NOTICE.</synopsis>
</configOption>
- <configOption name="asterisk_debug" default="3,4,5">
+ <configOption name="asterisk_debug" default="3,4,5,6">
<synopsis>A comma separated list of pjproject log levels to map to Asterisk LOG_DEBUG.</synopsis>
</configOption>
<configOption name="asterisk_verbose" default="">
@@ -82,6 +103,7 @@
#include <pjsip.h>
#include <pj/log.h>
+#include "asterisk/options.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/cli.h"
@@ -144,9 +166,11 @@ static struct log_mappings *get_log_mappings(void)
static int get_log_level(int pj_level)
{
- RAII_VAR(struct log_mappings *, mappings, get_log_mappings(), ao2_cleanup);
+ int mapped_level;
unsigned char l;
+ struct log_mappings *mappings;
+ mappings = get_log_mappings();
if (!mappings) {
return __LOG_ERROR;
}
@@ -154,18 +178,21 @@ static int get_log_level(int pj_level)
l = '0' + fmin(pj_level, 9);
if (strchr(mappings->asterisk_error, l)) {
- return __LOG_ERROR;
+ mapped_level = __LOG_ERROR;
} else if (strchr(mappings->asterisk_warning, l)) {
- return __LOG_WARNING;
+ mapped_level = __LOG_WARNING;
} else if (strchr(mappings->asterisk_notice, l)) {
- return __LOG_NOTICE;
+ mapped_level = __LOG_NOTICE;
} else if (strchr(mappings->asterisk_verbose, l)) {
- return __LOG_VERBOSE;
+ mapped_level = __LOG_VERBOSE;
} else if (strchr(mappings->asterisk_debug, l)) {
- return __LOG_DEBUG;
+ mapped_level = __LOG_DEBUG;
+ } else {
+ mapped_level = __LOG_SUPPRESS;
}
- return __LOG_SUPPRESS;
+ ao2_ref(mappings, -1);
+ return mapped_level;
}
static void log_forwarder(int level, const char *data, int len)
@@ -192,13 +219,6 @@ static void log_forwarder(int level, const char *data, int len)
return;
}
- if (ast_level == __LOG_DEBUG) {
- /* Obey the debug level for res_pjproject */
- if (!DEBUG_ATLEAST(level)) {
- return;
- }
- }
-
/* PJPROJECT uses indention to indicate function call depth. We'll prepend
* log statements with a tab so they'll have a better shot at lining
* up */
@@ -349,9 +369,95 @@ static char *handle_pjproject_show_log_mappings(struct ast_cli_entry *e, int cmd
return CLI_SUCCESS;
}
+struct max_pjproject_log_level_check {
+ /*!
+ * Compile time sanity check to determine if
+ * MAX_PJ_LOG_MAX_LEVEL matches CLI syntax.
+ */
+ char check[1 / (6 == MAX_PJ_LOG_MAX_LEVEL)];
+};
+
+static char *handle_pjproject_set_log_level(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ int level_new;
+ int level_old;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "pjproject set log level {default|0|1|2|3|4|5|6}";
+ e->usage =
+ "Usage: pjproject set log level {default|<level>}\n"
+ "\n"
+ " Set the maximum active pjproject logging level.\n"
+ " See pjproject.conf.sample for additional information\n"
+ " about the various levels pjproject uses.\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (a->argc != 5) {
+ return CLI_SHOWUSAGE;
+ }
+
+ if (!strcasecmp(a->argv[4], "default")) {
+ level_new = DEFAULT_PJ_LOG_MAX_LEVEL;
+ } else {
+ if (sscanf(a->argv[4], "%30d", &level_new) != 1
+ || level_new < 0 || MAX_PJ_LOG_MAX_LEVEL < level_new) {
+ return CLI_SHOWUSAGE;
+ }
+ }
+
+ /* Update pjproject logging level */
+ level_old = ast_option_pjproject_log_level;
+ if (level_old == level_new) {
+ ast_cli(a->fd, "pjproject log level is still %d.\n", level_old);
+ } else {
+ ast_cli(a->fd, "pjproject log level was %d and is now %d.\n",
+ level_old, level_new);
+ pj_log_set_level(level_new);
+ }
+ ast_option_pjproject_log_level = pj_log_get_level();
+ if (ast_option_pjproject_log_level != level_new) {
+ ast_log(LOG_WARNING, "Asterisk built with pjproject PJ_LOG_MAX_LEVEL set too low.\n");
+ }
+
+ return CLI_SUCCESS;
+}
+
+static char *handle_pjproject_show_log_level(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "pjproject show log level";
+ e->usage =
+ "Usage: pjproject show log level\n"
+ "\n"
+ " Show the current maximum active pjproject logging level.\n"
+ " See pjproject.conf.sample for additional information\n"
+ " about the various levels pjproject uses.\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (a->argc != 4) {
+ return CLI_SHOWUSAGE;
+ }
+
+ ast_cli(a->fd, "pjproject log level is %d.%s\n",
+ ast_option_pjproject_log_level,
+ ast_option_pjproject_log_level == DEFAULT_PJ_LOG_MAX_LEVEL ? " (default)" : "");
+
+ return CLI_SUCCESS;
+}
+
static struct ast_cli_entry pjproject_cli[] = {
+ AST_CLI_DEFINE(handle_pjproject_set_log_level, "Set the maximum active pjproject logging level"),
AST_CLI_DEFINE(handle_pjproject_show_buildopts, "Show the compiled config of the pjproject in use"),
AST_CLI_DEFINE(handle_pjproject_show_log_mappings, "Show pjproject to Asterisk log mappings"),
+ AST_CLI_DEFINE(handle_pjproject_show_log_level, "Show the maximum active pjproject logging level"),
};
static int load_module(void)
@@ -385,10 +491,11 @@ static int load_module(void)
}
ast_string_field_set(default_log_mappings, asterisk_error, "0,1");
ast_string_field_set(default_log_mappings, asterisk_warning, "2");
- ast_string_field_set(default_log_mappings, asterisk_debug, "3,4,5");
+ ast_string_field_set(default_log_mappings, asterisk_debug, "3,4,5,6");
ast_sorcery_load(pjproject_sorcery);
+ pj_log_set_level(ast_option_pjproject_log_level);
pj_init();
decor_orig = pj_log_get_decor();
@@ -403,9 +510,15 @@ static int load_module(void)
*/
pj_log_set_log_func(capture_buildopts_cb);
pj_log_set_decor(0);
+ pj_log_set_level(MAX_PJ_LOG_MAX_LEVEL);/* Set level to guarantee the dump output. */
pj_dump_config();
+ pj_log_set_level(ast_option_pjproject_log_level);
pj_log_set_decor(PJ_LOG_HAS_SENDER | PJ_LOG_HAS_INDENT);
pj_log_set_log_func(log_forwarder);
+ if (!AST_VECTOR_SIZE(&buildopts)
+ || ast_option_pjproject_log_level != pj_log_get_level()) {
+ ast_log(LOG_WARNING, "Asterisk built or linked with pjproject PJ_LOG_MAX_LEVEL set too low.\n");
+ }
ast_cli_register_multiple(pjproject_cli, ARRAY_LEN(pjproject_cli));
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 98530cb7b..8c2d37137 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -925,14 +925,14 @@
On outbound requests, force the user portion of the Contact header to this value.
</para></description>
</configOption>
- <configOption name="asymmetric_rtp_codec" default="no">
- <synopsis>Allow the sending and receiving RTP codec to differ</synopsis>
- <description><para>
- When set to "yes" the codec in use for sending will be allowed to differ from
- that of the received one. PJSIP will not automatically switch the sending one
- to the receiving one.
- </para></description>
- </configOption>
+ <configOption name="asymmetric_rtp_codec" default="no">
+ <synopsis>Allow the sending and receiving RTP codec to differ</synopsis>
+ <description><para>
+ When set to "yes" the codec in use for sending will be allowed to differ from
+ that of the received one. PJSIP will not automatically switch the sending one
+ to the receiving one.
+ </para></description>
+ </configOption>
</configObject>
<configObject name="auth">
<synopsis>Authentication type</synopsis>
diff --git a/res/res_pjsip/pjsip_resolver.c b/res/res_pjsip/pjsip_resolver.c
index 5a902466e..d6646d503 100644
--- a/res/res_pjsip/pjsip_resolver.c
+++ b/res/res_pjsip/pjsip_resolver.c
@@ -253,7 +253,7 @@ static int sip_resolve_handle_naptr(struct sip_resolve *resolve, const struct as
return -1;
}
- return sip_resolve_add(resolve, ast_dns_naptr_get_replacement(record), ns_t_srv, ns_c_in,
+ return sip_resolve_add(resolve, ast_dns_naptr_get_replacement(record), T_SRV, C_IN,
transport, 0);
}
@@ -304,12 +304,12 @@ static void sip_resolve_callback(const struct ast_dns_query_set *query_set)
target = AST_VECTOR_GET_ADDR(&resolving, idx);
for (record = ast_dns_result_get_records(result); record; record = ast_dns_record_get_next(record)) {
- if (ast_dns_record_get_rr_type(record) == ns_t_a ||
- ast_dns_record_get_rr_type(record) == ns_t_aaaa) {
+ if (ast_dns_record_get_rr_type(record) == T_A ||
+ ast_dns_record_get_rr_type(record) == T_AAAA) {
/* If NAPTR or SRV records exist the subsequent results from them take preference */
if (have_naptr || have_srv) {
ast_debug(2, "[%p] %s record being skipped on target '%s' because NAPTR or SRV record exists\n",
- resolve, ast_dns_record_get_rr_type(record) == ns_t_a ? "A" : "AAAA",
+ resolve, ast_dns_record_get_rr_type(record) == T_A ? "A" : "AAAA",
ast_dns_query_get_name(query));
continue;
}
@@ -322,7 +322,7 @@ static void sip_resolve_callback(const struct ast_dns_query_set *query_set)
resolve->addresses.entry[address_count].type = target->transport;
/* Populate address information for the new address entry */
- if (ast_dns_record_get_rr_type(record) == ns_t_a) {
+ if (ast_dns_record_get_rr_type(record) == T_A) {
ast_debug(2, "[%p] A record received on target '%s'\n", resolve, ast_dns_query_get_name(query));
resolve->addresses.entry[address_count].addr_len = sizeof(pj_sockaddr_in);
pj_sockaddr_init(pj_AF_INET(), &resolve->addresses.entry[address_count].addr, NULL,
@@ -338,7 +338,7 @@ static void sip_resolve_callback(const struct ast_dns_query_set *query_set)
}
address_count++;
- } else if (ast_dns_record_get_rr_type(record) == ns_t_srv) {
+ } else if (ast_dns_record_get_rr_type(record) == T_SRV) {
if (have_naptr) {
ast_debug(2, "[%p] SRV record being skipped on target '%s' because NAPTR record exists\n",
resolve, ast_dns_query_get_name(query));
@@ -350,22 +350,22 @@ static void sip_resolve_callback(const struct ast_dns_query_set *query_set)
/* If an explicit IPv6 target transport has been requested look for only AAAA records */
if (target->transport & PJSIP_TRANSPORT_IPV6) {
- sip_resolve_add(resolve, ast_dns_srv_get_host(record), ns_t_aaaa, ns_c_in, target->transport,
+ sip_resolve_add(resolve, ast_dns_srv_get_host(record), T_AAAA, C_IN, target->transport,
ast_dns_srv_get_port(record));
have_srv = 1;
} else if (sip_transport_is_available(target->transport + PJSIP_TRANSPORT_IPV6)) {
- sip_resolve_add(resolve, ast_dns_srv_get_host(record), ns_t_aaaa, ns_c_in, target->transport + PJSIP_TRANSPORT_IPV6,
+ sip_resolve_add(resolve, ast_dns_srv_get_host(record), T_AAAA, C_IN, target->transport + PJSIP_TRANSPORT_IPV6,
ast_dns_srv_get_port(record));
have_srv = 1;
}
if (!(target->transport & PJSIP_TRANSPORT_IPV6) &&
sip_transport_is_available(target->transport)) {
- sip_resolve_add(resolve, ast_dns_srv_get_host(record), ns_t_a, ns_c_in, target->transport,
+ sip_resolve_add(resolve, ast_dns_srv_get_host(record), T_A, C_IN, target->transport,
ast_dns_srv_get_port(record));
have_srv = 1;
}
- } else if (ast_dns_record_get_rr_type(record) == ns_t_naptr) {
+ } else if (ast_dns_record_get_rr_type(record) == T_NAPTR) {
int added = -1;
ast_debug(2, "[%p] NAPTR record received on target '%s'\n", resolve, ast_dns_query_get_name(query));
@@ -561,39 +561,39 @@ static void sip_resolve(pjsip_resolver_t *resolver, pj_pool_t *pool, const pjsip
* explicitly and only looks for IPv6 records.
*/
- res |= sip_resolve_add(resolve, host, ns_t_naptr, ns_c_in, type, 0);
+ res |= sip_resolve_add(resolve, host, T_NAPTR, C_IN, type, 0);
if (type == PJSIP_TRANSPORT_UNSPECIFIED ||
(type == PJSIP_TRANSPORT_TLS && sip_transport_is_available(PJSIP_TRANSPORT_TLS)) ||
(type == PJSIP_TRANSPORT_TLS6 && sip_transport_is_available(PJSIP_TRANSPORT_TLS6))) {
snprintf(srv, sizeof(srv), "_sips._tcp.%s", host);
- res |= sip_resolve_add(resolve, srv, ns_t_srv, ns_c_in,
+ res |= sip_resolve_add(resolve, srv, T_SRV, C_IN,
type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_TLS : type, 0);
}
if (type == PJSIP_TRANSPORT_UNSPECIFIED ||
(type == PJSIP_TRANSPORT_TCP && sip_transport_is_available(PJSIP_TRANSPORT_TCP)) ||
(type == PJSIP_TRANSPORT_TCP6 && sip_transport_is_available(PJSIP_TRANSPORT_TCP6))) {
snprintf(srv, sizeof(srv), "_sip._tcp.%s", host);
- res |= sip_resolve_add(resolve, srv, ns_t_srv, ns_c_in,
+ res |= sip_resolve_add(resolve, srv, T_SRV, C_IN,
type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_TCP : type, 0);
}
if (type == PJSIP_TRANSPORT_UNSPECIFIED ||
(type == PJSIP_TRANSPORT_UDP && sip_transport_is_available(PJSIP_TRANSPORT_UDP)) ||
(type == PJSIP_TRANSPORT_UDP6 && sip_transport_is_available(PJSIP_TRANSPORT_UDP6))) {
snprintf(srv, sizeof(srv), "_sip._udp.%s", host);
- res |= sip_resolve_add(resolve, srv, ns_t_srv, ns_c_in,
+ res |= sip_resolve_add(resolve, srv, T_SRV, C_IN,
type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP : type, 0);
}
}
if ((type == PJSIP_TRANSPORT_UNSPECIFIED && sip_transport_is_available(PJSIP_TRANSPORT_UDP6)) ||
sip_transport_is_available(type + PJSIP_TRANSPORT_IPV6)) {
- res |= sip_resolve_add(resolve, host, ns_t_aaaa, ns_c_in, (type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP6 : type + PJSIP_TRANSPORT_IPV6), target->addr.port);
+ res |= sip_resolve_add(resolve, host, T_AAAA, C_IN, (type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP6 : type + PJSIP_TRANSPORT_IPV6), target->addr.port);
}
if ((type == PJSIP_TRANSPORT_UNSPECIFIED && sip_transport_is_available(PJSIP_TRANSPORT_UDP)) ||
sip_transport_is_available(type)) {
- res |= sip_resolve_add(resolve, host, ns_t_a, ns_c_in, (type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP : type), target->addr.port);
+ res |= sip_resolve_add(resolve, host, T_A, C_IN, (type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP : type), target->addr.port);
}
if (res) {
diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c
index 29701a13c..d486ccd63 100644
--- a/res/res_pjsip_outbound_registration.c
+++ b/res/res_pjsip_outbound_registration.c
@@ -627,15 +627,30 @@ static void schedule_registration(struct sip_outbound_registration_client_state
static void update_client_state_status(struct sip_outbound_registration_client_state *client_state, enum sip_outbound_registration_status status)
{
+ const char *status_old;
+ const char *status_new;
+
if (client_state->status == status) {
+ /* Status state did not change at all. */
+ return;
+ }
+
+ status_old = sip_outbound_registration_status_str(client_state->status);
+ status_new = sip_outbound_registration_status_str(status);
+ client_state->status = status;
+
+ if (!strcmp(status_old, status_new)) {
+ /*
+ * The internal status state may have changed but the status
+ * state we tell the world did not change at all.
+ */
return;
}
ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "-1", 1.0,
- sip_outbound_registration_status_str(client_state->status));
+ status_old);
ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "+1", 1.0,
- sip_outbound_registration_status_str(status));
- client_state->status = status;
+ status_new);
}
/*! \brief Callback function for unregistering (potentially) and destroying state */
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index 7fd4f9abc..4d6a1a168 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -38,6 +38,7 @@
#include <pjmedia.h>
#include <pjlib.h>
+#include "asterisk/utils.h"
#include "asterisk/module.h"
#include "asterisk/format.h"
#include "asterisk/format_cap.h"
@@ -1514,7 +1515,11 @@ static int load_module(void)
{
CHECK_PJSIP_SESSION_MODULE_LOADED();
- ast_sockaddr_parse(&address_rtp, "::", 0);
+ if (ast_check_ipv6()) {
+ ast_sockaddr_parse(&address_rtp, "::", 0);
+ } else {
+ ast_sockaddr_parse(&address_rtp, "0.0.0.0", 0);
+ }
if (!(sched = ast_sched_context_create())) {
ast_log(LOG_ERROR, "Unable to create scheduler context.\n");
diff --git a/res/res_pjsip_t38.c b/res/res_pjsip_t38.c
index adc99c30d..79dc9c324 100644
--- a/res/res_pjsip_t38.c
+++ b/res/res_pjsip_t38.c
@@ -37,6 +37,7 @@
#include <pjmedia.h>
#include <pjlib.h>
+#include "asterisk/utils.h"
#include "asterisk/module.h"
#include "asterisk/udptl.h"
#include "asterisk/netsock2.h"
@@ -916,7 +917,11 @@ static int load_module(void)
{
CHECK_PJSIP_SESSION_MODULE_LOADED();
- ast_sockaddr_parse(&address, "::", 0);
+ if (ast_check_ipv6()) {
+ ast_sockaddr_parse(&address, "::", 0);
+ } else {
+ ast_sockaddr_parse(&address, "0.0.0.0", 0);
+ }
if (ast_sip_session_register_supplement(&t38_supplement)) {
ast_log(LOG_ERROR, "Unable to register T.38 session supplement\n");
diff --git a/res/res_pjsip_transport_websocket.c b/res/res_pjsip_transport_websocket.c
index b9d94ea3c..a9f526884 100644
--- a/res/res_pjsip_transport_websocket.c
+++ b/res/res_pjsip_transport_websocket.c
@@ -378,7 +378,6 @@ static void websocket_cb(struct ast_websocket *session, struct ast_variable *par
static pj_bool_t websocket_on_rx_msg(pjsip_rx_data *rdata)
{
static const pj_str_t STR_WS = { "ws", 2 };
- static const pj_str_t STR_WSS = { "wss", 3 };
pjsip_contact_hdr *contact;
long type = rdata->tp_info.transport->key.type;
@@ -395,7 +394,7 @@ static pj_bool_t websocket_on_rx_msg(pjsip_rx_data *rdata)
uri->port = rdata->pkt_info.src_port;
ast_debug(4, "Re-wrote Contact URI host/port to %.*s:%d\n",
(int)pj_strlen(&uri->host), pj_strbuf(&uri->host), uri->port);
- pj_strdup(rdata->tp_info.pool, &uri->transport_param, (type == (long)transport_type_ws) ? &STR_WS : &STR_WSS);
+ pj_strdup(rdata->tp_info.pool, &uri->transport_param, &STR_WS);
}
rdata->msg_info.via->rport_param = 0;
@@ -431,7 +430,7 @@ static int load_module(void)
CHECK_PJSIP_MODULE_LOADED();
pjsip_transport_register_type(PJSIP_TRANSPORT_RELIABLE, "WS", 5060, &transport_type_ws);
- pjsip_transport_register_type(PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE, "WSS", 5060, &transport_type_wss);
+ pjsip_transport_register_type(PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE, "WS", 5060, &transport_type_wss);
if (ast_sip_register_service(&websocket_module) != PJ_SUCCESS) {
return AST_MODULE_LOAD_DECLINE;
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index a88203320..58c217ecb 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -52,6 +52,7 @@
#include <ifaddrs.h>
#endif
+#include "asterisk/options.h"
#include "asterisk/stun.h"
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
@@ -3084,7 +3085,26 @@ static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw)
unsigned int sec, usec, frac;
sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
usec = tv.tv_usec;
- frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
+ /*
+ * Convert usec to 0.32 bit fixed point without overflow.
+ *
+ * = usec * 2^32 / 10^6
+ * = usec * 2^32 / (2^6 * 5^6)
+ * = usec * 2^26 / 5^6
+ *
+ * The usec value needs 20 bits to represent 999999 usec. So
+ * splitting the 2^26 to get the most precision using 32 bit
+ * values gives:
+ *
+ * = ((usec * 2^12) / 5^6) * 2^14
+ *
+ * Splitting the division into two stages preserves all the
+ * available significant bits of usec over doing the division
+ * all at once.
+ *
+ * = ((((usec * 2^12) / 5^3) * 2^7) / 5^3) * 2^7
+ */
+ frac = ((((usec << 12) / 125) << 7) / 125) << 7;
*msw = sec;
*lsw = frac;
}
@@ -3092,7 +3112,8 @@ static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw)
static void ntp2timeval(unsigned int msw, unsigned int lsw, struct timeval *tv)
{
tv->tv_sec = msw - 2208988800u;
- tv->tv_usec = ((lsw << 6) / 3650) - (lsw >> 12) - (lsw >> 8);
+ /* Reverse the sequence in timeval2ntp() */
+ tv->tv_usec = ((((lsw >> 7) * 125) >> 7) * 125) >> 12;
}
static void calculate_lost_packet_statistics(struct ast_rtp *rtp,
@@ -3277,9 +3298,9 @@ static int ast_rtcp_write_report(struct ast_rtp_instance *instance, int sr)
ast_sockaddr_stringify(&remote_address), ice ? " (via ICE)" : "");
ast_verbose(" Our SSRC: %u\n", rtcp_report->ssrc);
if (sr) {
- ast_verbose(" Sent(NTP): %u.%010u\n",
+ ast_verbose(" Sent(NTP): %u.%06u\n",
(unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_sec,
- (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_usec * 4096);
+ (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_usec);
ast_verbose(" Sent(RTP): %u\n", rtcp_report->sender_information.rtp_timestamp);
ast_verbose(" Sent packets: %u\n", rtcp_report->sender_information.packet_count);
ast_verbose(" Sent octets: %u\n", rtcp_report->sender_information.octet_count);
@@ -4016,9 +4037,22 @@ static int update_rtt_stats(struct ast_rtp *rtp, unsigned int lsr, unsigned int
lsr_a = ((msw & 0x0000ffff) << 16) | ((lsw & 0xffff0000) >> 16);
rtt = lsr_a - lsr - dlsr;
rtt_msw = (rtt & 0xffff0000) >> 16;
- rtt_lsw = (rtt & 0x0000ffff) << 16;
+ rtt_lsw = (rtt & 0x0000ffff);
rtt_tv.tv_sec = rtt_msw;
- rtt_tv.tv_usec = ((rtt_lsw << 6) / 3650) - (rtt_lsw >> 12) - (rtt_lsw >> 8);
+ /*
+ * Convert 16.16 fixed point rtt_lsw to usec without
+ * overflow.
+ *
+ * = rtt_lsw * 10^6 / 2^16
+ * = rtt_lsw * (2^6 * 5^6) / 2^16
+ * = rtt_lsw * 5^6 / 2^10
+ *
+ * The rtt_lsw value is in 16.16 fixed point format and 5^6
+ * requires 14 bits to represent. We have enough space to
+ * directly do the conversion because there is no integer
+ * component in rtt_lsw.
+ */
+ rtt_tv.tv_usec = (rtt_lsw * 15625) >> 10;
rtp->rtcp->rtt = (double)rtt_tv.tv_sec + ((double)rtt_tv.tv_usec / 1000000);
if (lsr_a - dlsr < lsr) {
return 1;
@@ -4214,9 +4248,9 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
&rtcp_report->sender_information.ntp_timestamp);
rtcp_report->sender_information.rtp_timestamp = ntohl(rtcpheader[i + 2]);
if (rtcp_debug_test_addr(&addr)) {
- ast_verbose("NTP timestamp: %u.%010u\n",
+ ast_verbose("NTP timestamp: %u.%06u\n",
(unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_sec,
- (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_usec * 4096);
+ (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_usec);
ast_verbose("RTP timestamp: %u\n", rtcp_report->sender_information.rtp_timestamp);
ast_verbose("SPC: %u\tSOC: %u\n",
rtcp_report->sender_information.packet_count,
@@ -5632,6 +5666,7 @@ static int load_module(void)
#ifdef HAVE_PJPROJECT
pj_lock_t *lock;
+ pj_log_set_level(ast_option_pjproject_log_level);
if (pj_init() != PJ_SUCCESS) {
return AST_MODULE_LOAD_DECLINE;
}
diff --git a/third-party/pjproject/patches/config_site.h b/third-party/pjproject/patches/config_site.h
index 1a48695bf..66e8e84d3 100644
--- a/third-party/pjproject/patches/config_site.h
+++ b/third-party/pjproject/patches/config_site.h
@@ -34,7 +34,7 @@
#define PJ_SCANNER_USE_BITWISE 0
#define PJ_OS_HAS_CHECK_STACK 0
-#define PJ_LOG_MAX_LEVEL 3
+#define PJ_LOG_MAX_LEVEL 6
#define PJ_ENABLE_EXTRA_CHECK 1
#define PJSIP_MAX_TSX_COUNT ((64*1024)-1)
#define PJSIP_MAX_DIALOG_COUNT ((64*1024)-1)