diff options
40 files changed, 622 insertions, 130 deletions
@@ -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: "") @@ -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) |