summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES5
-rw-r--r--apps/app_queue.c20
-rw-r--r--apps/app_transfer.c2
-rw-r--r--channels/chan_pjsip.c46
-rw-r--r--channels/chan_sip.c1
-rw-r--r--configs/samples/confbridge.conf.sample4
-rw-r--r--configs/samples/rtp.conf.sample14
-rw-r--r--include/asterisk/module.h2
-rw-r--r--include/asterisk/rtp_engine.h10
-rw-r--r--main/asterisk.c49
-rw-r--r--main/cdr.c17
-rw-r--r--main/loader.c374
-rw-r--r--main/rtp_engine.c19
-rw-r--r--res/res_clialiases.c8
-rw-r--r--res/res_hep.c2
-rw-r--r--res/res_musiconhold.c4
-rw-r--r--res/res_rtp_asterisk.c45
-rw-r--r--res/res_smdi.c50
18 files changed, 408 insertions, 264 deletions
diff --git a/CHANGES b/CHANGES
index 8a7fb3198..7cfdedeac 100644
--- a/CHANGES
+++ b/CHANGES
@@ -21,6 +21,11 @@ Core
Asterisk is compiled with the LOW_MEMORY compile time option enabled because
the cache code does not exist.
+chan_sip
+------------------
+ * Calls to invalid extensions are now reported as an ACL failure security event
+ "no_extension_match".
+
res_rtp_asterisk
------------------
* The X.509 certificate used for DTLS negotation can now be automatically
diff --git a/apps/app_queue.c b/apps/app_queue.c
index e3a4e22a9..6aea58ccb 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -1572,6 +1572,7 @@ struct member {
char state_exten[AST_MAX_EXTENSION]; /*!< Extension to get state from (if using hint) */
char state_context[AST_MAX_CONTEXT]; /*!< Context to use when getting state (if using hint) */
char state_interface[AST_CHANNEL_NAME]; /*!< Technology/Location from which to read devicestate changes */
+ int state_id; /*!< Extension state callback id (if using hint) */
char membername[80]; /*!< Member name to use in queue logs */
int penalty; /*!< Are we a last resort? */
int calls; /*!< Number of calls serviced by this member */
@@ -2629,12 +2630,21 @@ static int get_queue_member_status(struct member *cur)
return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten));
}
+static void destroy_queue_member_cb(void *obj)
+{
+ struct member *mem = obj;
+
+ if (mem->state_id != -1) {
+ ast_extension_state_del(mem->state_id, extension_state_cb);
+ }
+}
+
/*! \brief allocate space for new queue member and set fields based on parameters passed */
static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse)
{
struct member *cur;
- if ((cur = ao2_alloc(sizeof(*cur), NULL))) {
+ if ((cur = ao2_alloc(sizeof(*cur), destroy_queue_member_cb))) {
cur->ringinuse = ringinuse;
cur->penalty = penalty;
cur->paused = paused;
@@ -2661,6 +2671,10 @@ static struct member *create_queue_member(const char *interface, const char *mem
ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten));
ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context));
+
+ cur->state_id = ast_extension_state_add(cur->state_context, cur->state_exten, extension_state_cb, NULL);
+ } else {
+ cur->state_id = -1;
}
cur->status = get_queue_member_status(cur);
}
@@ -11081,8 +11095,6 @@ static int unload_module(void)
device_state_sub = stasis_unsubscribe_and_join(device_state_sub);
- ast_extension_state_del(0, extension_state_cb);
-
ast_unload_realtime("queue_members");
ao2_cleanup(queues);
ao2_cleanup(pending_members);
@@ -11240,8 +11252,6 @@ static int load_module(void)
err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_dump_type);
err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_ringnoanswer_type);
- ast_extension_state_add(NULL, NULL, extension_state_cb, NULL);
-
if (err) {
unload_module();
return AST_MODULE_LOAD_DECLINE;
diff --git a/apps/app_transfer.c b/apps/app_transfer.c
index 7bc67e154..1d7c87920 100644
--- a/apps/app_transfer.c
+++ b/apps/app_transfer.c
@@ -51,7 +51,7 @@
</syntax>
<description>
<para>Requests the remote caller be transferred
- to a given destination. If TECH (SIP, IAX2, LOCAL etc) is used, only
+ to a given destination. If TECH (SIP, IAX2, etc) is used, only
an incoming call with the same channel technology will be transferred.
Note that for SIP, if you transfer before call is setup, a 302 redirect
SIP message will be returned to the caller.</para>
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 69bcc187f..10f45a4cc 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -2381,7 +2381,7 @@ static int request(void *obj)
struct request_data *req_data = obj;
struct ast_sip_session *session = NULL;
char *tmp = ast_strdupa(req_data->dest), *endpoint_name = NULL, *request_user = NULL;
- RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
+ struct ast_sip_endpoint *endpoint;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(endpoint);
@@ -2406,10 +2406,18 @@ static int request(void *obj)
}
if (ast_strlen_zero(endpoint_name)) {
- ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name\n");
+ if (request_user) {
+ ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name: %s@<endpoint-name>\n",
+ request_user);
+ } else {
+ ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name\n");
+ }
req_data->cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
return -1;
- } else if (!(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name))) {
+ }
+ endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
+ endpoint_name);
+ if (!endpoint) {
ast_log(LOG_ERROR, "Unable to create PJSIP channel - endpoint '%s' was not found\n", endpoint_name);
req_data->cause = AST_CAUSE_NO_ROUTE_DESTINATION;
return -1;
@@ -2421,23 +2429,38 @@ static int request(void *obj)
ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name\n");
req_data->cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
return -1;
- } else if (!(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name))) {
+ }
+ endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
+ endpoint_name);
+ if (!endpoint) {
/* It seems it's not a multi-domain endpoint or single endpoint exact match,
* it's possible that it's a SIP trunk with a specified user (user@trunkname),
* so extract the user before @ sign.
*/
- if ((endpoint_name = strchr(args.endpoint, '@'))) {
- request_user = args.endpoint;
- *endpoint_name++ = '\0';
+ endpoint_name = strchr(args.endpoint, '@');
+ if (!endpoint_name) {
+ /*
+ * Couldn't find an '@' so it had to be an endpoint
+ * name that doesn't exist.
+ */
+ ast_log(LOG_ERROR, "Unable to create PJSIP channel - endpoint '%s' was not found\n",
+ args.endpoint);
+ req_data->cause = AST_CAUSE_NO_ROUTE_DESTINATION;
+ return -1;
}
+ request_user = args.endpoint;
+ *endpoint_name++ = '\0';
if (ast_strlen_zero(endpoint_name)) {
- ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name\n");
+ ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name: %s@<endpoint-name>\n",
+ request_user);
req_data->cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
return -1;
}
- if (!(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name))) {
+ endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
+ endpoint_name);
+ if (!endpoint) {
ast_log(LOG_ERROR, "Unable to create PJSIP channel - endpoint '%s' was not found\n", endpoint_name);
req_data->cause = AST_CAUSE_NO_ROUTE_DESTINATION;
return -1;
@@ -2445,7 +2468,10 @@ static int request(void *obj)
}
}
- if (!(session = ast_sip_session_create_outgoing(endpoint, NULL, args.aor, request_user, req_data->topology))) {
+ session = ast_sip_session_create_outgoing(endpoint, NULL, args.aor, request_user,
+ req_data->topology);
+ ao2_ref(endpoint, -1);
+ if (!session) {
ast_log(LOG_ERROR, "Failed to create outgoing session to endpoint '%s'\n", endpoint_name);
req_data->cause = AST_CAUSE_NO_ROUTE_DESTINATION;
return -1;
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 4bae39da0..b0573002b 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -26460,6 +26460,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str
ast_log(LOG_NOTICE, "Call from '%s' (%s) to extension"
" '%s' rejected because extension not found in context '%s'.\n",
S_OR(p->username, p->peername), ast_sockaddr_stringify(&p->recv), decoded_exten, p->context);
+ sip_report_failed_acl(p, "no_extension_match");
}
break;
case SIP_GET_DEST_REFUSED:
diff --git a/configs/samples/confbridge.conf.sample b/configs/samples/confbridge.conf.sample
index 9cf86aa0b..c8f30bcc3 100644
--- a/configs/samples/confbridge.conf.sample
+++ b/configs/samples/confbridge.conf.sample
@@ -243,8 +243,8 @@ type=bridge
; left the conference. This is used for user intros.
; Example "_____ has left the conference"
;sound_kicked ; The sound played to a user who has been kicked from the conference.
-;sound_muted ; The sound played when the mute option it toggled on.
-;sound_unmuted ; The sound played when the mute option it toggled off.
+;sound_muted ; The sound played when the mute option is toggled on using DTMF menu.
+;sound_unmuted ; The sound played when the mute option is toggled off using DTMF menu.
;sound_only_person ; The sound played when the user is the only person in the conference.
;sound_only_one ; The sound played to a user when there is only one other
; person is in the conference.
diff --git a/configs/samples/rtp.conf.sample b/configs/samples/rtp.conf.sample
index 9bc3de3cf..de9d59007 100644
--- a/configs/samples/rtp.conf.sample
+++ b/configs/samples/rtp.conf.sample
@@ -21,9 +21,17 @@ rtpend=20000
; rtcpinterval = 5000 ; Milliseconds between rtcp reports
;(min 500, max 60000, default 5000)
;
-; Enable strict RTP protection. This will drop RTP packets that
-; do not come from the source of the RTP stream. This option is
-; enabled by default.
+; Enable strict RTP protection. This will drop RTP packets that do not come
+; from the recoginized source of the RTP stream. Strict RTP qualifies RTP
+; packet stream sources before accepting them upon initial connection and
+; when the connection is renegotiated (e.g., transfers and direct media).
+; Initial connection and renegotiation starts a learning mode to qualify
+; stream source addresses. Once Asterisk has recognized a stream it will
+; allow other streams to qualify and replace the current stream for 5
+; seconds after starting learning mode. Once learning mode completes the
+; current stream is locked in and cannot change until the next
+; renegotiation.
+; This option is enabled by default.
; strictrtp=yes
;
; Number of packets containing consecutive sequence values needed
diff --git a/include/asterisk/module.h b/include/asterisk/module.h
index 6c60429c9..3df924c59 100644
--- a/include/asterisk/module.h
+++ b/include/asterisk/module.h
@@ -69,7 +69,7 @@ enum ast_module_load_result {
AST_MODULE_LOAD_SUCCESS = 0, /*!< Module loaded and configured */
AST_MODULE_LOAD_DECLINE = 1, /*!< Module is not configured */
AST_MODULE_LOAD_SKIP = 2, /*!< Module was skipped for some reason (For loader.c use only. Should never be returned by modules)*/
- AST_MODULE_LOAD_PRIORITY = 3, /*!< Module is not loaded yet, but is added to prioity heap */
+ AST_MODULE_LOAD_PRIORITY = 3, /*!< Module is not loaded yet, but is added to priority list */
AST_MODULE_LOAD_FAILURE = -1, /*!< Module could not be loaded properly */
};
diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h
index f9d686aca..c77be4584 100644
--- a/include/asterisk/rtp_engine.h
+++ b/include/asterisk/rtp_engine.h
@@ -1383,6 +1383,16 @@ int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs,
void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload);
/*!
+ * \brief Determine the type of RTP stream media from the codecs mapped.
+ * \since 13.19.0
+ *
+ * \param codecs Codecs structure to look in
+ *
+ * \return Media type or AST_MEDIA_TYPE_UNKNOWN if no codecs mapped.
+ */
+enum ast_media_type ast_rtp_codecs_get_stream_type(struct ast_rtp_codecs *codecs);
+
+/*!
* \brief Retrieve rx payload mapped information by payload type
*
* \param codecs Codecs structure to look in
diff --git a/main/asterisk.c b/main/asterisk.c
index 006a1b03a..cb0ea61df 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -2399,52 +2399,6 @@ static int remoteconsolehandler(const char *s)
(s[4] == '\0' || isspace(s[4]))) {
quit_handler(0, SHUTDOWN_FAST, 0);
ret = 1;
- } else if (s[0]) {
- char *shrunk = ast_strdupa(s);
- char *cur;
- char *prev;
-
- /*
- * Remove duplicate spaces from shrunk for matching purposes.
- *
- * shrunk has at least one character in it to start with or we
- * couldn't get here.
- */
- for (prev = shrunk, cur = shrunk + 1; *cur; ++cur) {
- if (*prev == ' ' && *cur == ' ') {
- /* Skip repeated space delimiter. */
- continue;
- }
- *++prev = *cur;
- }
- *++prev = '\0';
-
- if (strncasecmp(shrunk, "core set verbose ", 17) == 0) {
- /*
- * We need to still set the rasterisk option_verbose in case we are
- * talking to an earlier version which doesn't prefilter verbose
- * levels. This is really a compromise as we should always take
- * whatever the server sends.
- */
-
- if (!strncasecmp(shrunk + 17, "off", 3)) {
- ast_verb_console_set(0);
- } else {
- int verbose_new;
- int atleast;
-
- atleast = 8;
- if (strncasecmp(shrunk + 17, "atleast ", atleast)) {
- atleast = 0;
- }
-
- if (sscanf(shrunk + 17 + atleast, "%30d", &verbose_new) == 1) {
- if (!atleast || ast_verb_console_get() < verbose_new) {
- ast_verb_console_set(verbose_new);
- }
- }
- }
- }
}
return ret;
@@ -2768,6 +2722,9 @@ static void send_rasterisk_connect_commands(void)
fdsend(ast_consock, buf);
}
+ /* Leave verbose filtering to the server. */
+ option_verbose = INT_MAX;
+
if (!ast_opt_mute) {
fdsend(ast_consock, "logger mute silent");
} else {
diff --git a/main/cdr.c b/main/cdr.c
index d7384f259..0f6a66517 100644
--- a/main/cdr.c
+++ b/main/cdr.c
@@ -2477,12 +2477,12 @@ static void bridge_candidate_add_to_cdr(struct cdr_object *cdr,
* \param cand_cdr The \ref cdr_object that is a candidate
*
*/
-static int bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *base_cand_cdr)
+static void bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *base_cand_cdr)
{
struct cdr_object_snapshot *party_a;
struct cdr_object *cand_cdr;
- SCOPED_AO2LOCK(lock, base_cand_cdr);
+ ao2_lock(base_cand_cdr);
for (cand_cdr = base_cand_cdr; cand_cdr; cand_cdr = cand_cdr->next) {
/* Skip any records that are not in this bridge */
@@ -2494,7 +2494,7 @@ static int bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *b
if (!strcasecmp(cdr->party_a.snapshot->name, cand_cdr->party_a.snapshot->name)
|| (cdr->party_b.snapshot
&& !strcasecmp(cdr->party_b.snapshot->name, cand_cdr->party_a.snapshot->name))) {
- return 0;
+ break;
}
party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
@@ -2502,7 +2502,7 @@ static int bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *b
* Party B */
if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
bridge_candidate_add_to_cdr(cdr, &cand_cdr->party_a);
- return 0;
+ break;
}
/* We're Party B. Check if we can add ourselves immediately or if we need
@@ -2522,9 +2522,11 @@ static int bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *b
*/
memset(&cand_cdr->end, 0, sizeof(cand_cdr->end));
}
- return 0;
+
+ break;
}
- return 0;
+
+ ao2_unlock(base_cand_cdr);
}
/*!
@@ -2607,6 +2609,7 @@ static void handle_standard_bridge_enter_message(struct cdr_object *cdr,
ao2_lock(cdr);
+try_again:
for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
if (it_cdr->fn_table->process_party_a) {
CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,
@@ -2659,7 +2662,7 @@ static void handle_standard_bridge_enter_message(struct cdr_object *cdr,
/* This is guaranteed to succeed: the new CDR is created in the single state
* and will be able to handle the bridge enter message
*/
- handle_standard_bridge_enter_message(cdr, bridge, channel);
+ goto try_again;
}
}
ao2_unlock(cdr);
diff --git a/main/loader.c b/main/loader.c
index 23a29d994..2a203c6a7 100644
--- a/main/loader.c
+++ b/main/loader.c
@@ -52,7 +52,7 @@
#include "asterisk/features_config.h"
#include "asterisk/dsp.h"
#include "asterisk/udptl.h"
-#include "asterisk/heap.h"
+#include "asterisk/vector.h"
#include "asterisk/app.h"
#include "asterisk/test.h"
#include "asterisk/sounds_index.h"
@@ -110,6 +110,8 @@ static const unsigned char expected_key[] =
static char buildopt_sum[33] = AST_BUILDOPT_SUM;
+AST_VECTOR(module_vector, struct ast_module *);
+
/*!
* \brief Internal flag to indicate all modules have been initially loaded.
*/
@@ -133,13 +135,34 @@ struct ast_module {
/*! This module is being held open until it's time to shutdown. */
unsigned int keepuntilshutdown:1;
} flags;
- AST_LIST_ENTRY(ast_module) list_entry;
AST_DLLIST_ENTRY(ast_module) entry;
char resource[0];
};
static AST_DLLIST_HEAD_STATIC(module_list, ast_module);
+static int module_vector_strcasecmp(struct ast_module *a, struct ast_module *b)
+{
+ return strcasecmp(a->resource, b->resource);
+}
+
+static int module_vector_cmp(struct ast_module *a, struct ast_module *b)
+{
+ /* if load_pri is not set, default is 128. Lower is better */
+ int a_pri = ast_test_flag(a->info, AST_MODFLAG_LOAD_ORDER)
+ ? a->info->load_pri : AST_MODPRI_DEFAULT;
+ int b_pri = ast_test_flag(b->info, AST_MODFLAG_LOAD_ORDER)
+ ? b->info->load_pri : AST_MODPRI_DEFAULT;
+
+ /*
+ * Returns comparison values for a vector sorted by priority.
+ * <0 a_pri < b_pri
+ * =0 a_pri == b_pri
+ * >0 a_pri > b_pri
+ */
+ return a_pri - b_pri;
+}
+
const char *ast_module_name(const struct ast_module *mod)
{
if (!mod || !mod->info) {
@@ -167,38 +190,51 @@ static int do_full_reload = 0;
static AST_DLLIST_HEAD_STATIC(reload_queue, reload_queue_item);
-/* when dynamic modules are being loaded, ast_module_register() will
- need to know what filename the module was loaded from while it
- is being registered
-*/
+/*!
+ * \internal
+ *
+ * This variable is set by load_dynamic_module so ast_module_register
+ * can know what pointer is being registered.
+ *
+ * This is protected by the module_list lock.
+ */
static struct ast_module *resource_being_loaded;
-/* XXX: should we check for duplicate resource names here? */
-
+/*!
+ * \internal
+ * \brief Used by AST_MODULE_INFO to register with the module loader.
+ *
+ * This function is automatically called when each module is opened.
+ * It must never be used from outside AST_MODULE_INFO.
+ */
void ast_module_register(const struct ast_module_info *info)
{
- struct ast_module *mod = resource_being_loaded;
+ struct ast_module *mod;
+
+ /*
+ * This lock protects resource_being_loaded as well as the module
+ * list. Normally we already have a lock on module_list when we
+ * begin the load but locking again from here prevents corruption
+ * if an asterisk module is dlopen'ed from outside the module loader.
+ */
+ AST_DLLIST_LOCK(&module_list);
+ mod = resource_being_loaded;
+ if (!mod) {
+ AST_DLLIST_UNLOCK(&module_list);
+ return;
+ }
ast_debug(5, "Registering module %s\n", info->name);
+ /* This tells load_dynamic_module that we're registered. */
+ resource_being_loaded = NULL;
+
mod->info = info;
if (ast_opt_ref_debug) {
mod->ref_debug = ao2_t_alloc(0, NULL, info->name);
}
AST_LIST_HEAD_INIT(&mod->users);
- /* during startup, before the loader has been initialized,
- there are no threads, so there is no need to take the lock
- on this list to manipulate it. it is also possible that it
- might be unsafe to use the list lock at that point... so
- let's avoid it altogether
- */
- AST_DLLIST_LOCK(&module_list);
- /* it is paramount that the new entry be placed at the tail of
- the list, otherwise the code that uses dlopen() to load
- dynamic modules won't be able to find out if the module it
- just opened was registered or failed to load
- */
AST_DLLIST_INSERT_TAIL(&module_list, mod, entry);
AST_DLLIST_UNLOCK(&module_list);
@@ -206,6 +242,13 @@ void ast_module_register(const struct ast_module_info *info)
*((struct ast_module **) &(info->self)) = mod;
}
+static void module_destroy(struct ast_module *mod)
+{
+ AST_LIST_HEAD_DESTROY(&mod->users);
+ ao2_cleanup(mod->ref_debug);
+ ast_free(mod);
+}
+
void ast_module_unregister(const struct ast_module_info *info)
{
struct ast_module *mod = NULL;
@@ -226,9 +269,7 @@ void ast_module_unregister(const struct ast_module_info *info)
if (mod) {
ast_debug(5, "Unregistering module %s\n", info->name);
- AST_LIST_HEAD_DESTROY(&mod->users);
- ao2_cleanup(mod->ref_debug);
- ast_free(mod);
+ module_destroy(mod);
}
}
@@ -498,96 +539,93 @@ static void unload_dynamic_module(struct ast_module *mod)
#endif
}
-static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, unsigned int suppress_logging, struct ast_heap *resource_heap, int required);
-
#define MODULE_LOCAL_ONLY (void *)-1
-static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int global_symbols_only, unsigned int suppress_logging, struct ast_heap *resource_heap)
+/*!
+ * \internal
+ * \brief Attempt to dlopen a module.
+ *
+ * \param resource_in The module name to load.
+ * \param so_ext ".so" or blank if ".so" is already part of resource_in.
+ * \param filename Passed directly to dlopen.
+ * \param flags Passed directly to dlopen.
+ * \param suppress_logging Do not log any error from dlopen.
+ *
+ * \return Pointer to opened module, NULL on error.
+ *
+ * \warning module_list must be locked before calling this function.
+ */
+static struct ast_module *load_dlopen(const char *resource_in, const char *so_ext,
+ const char *filename, int flags, unsigned int suppress_logging)
{
- char fn[PATH_MAX] = "";
- void *lib = NULL;
struct ast_module *mod;
- unsigned int wants_global;
- int space; /* room needed for the descriptor */
- int missing_so = 0;
-
- space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1;
- if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) {
- missing_so = 1;
- space += 3; /* room for the extra ".so" */
- }
-
- snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : "");
- /* make a first load of the module in 'quiet' mode... don't try to resolve
- any symbols, and don't export any symbols. this will allow us to peek into
- the module's info block (if available) to see what flags it has set */
+ ast_assert(!resource_being_loaded);
- resource_being_loaded = ast_calloc(1, space);
- if (!resource_being_loaded)
+ mod = ast_calloc(1, sizeof(*mod) + strlen(resource_in) + strlen(so_ext) + 1);
+ if (!mod) {
return NULL;
- strcpy(resource_being_loaded->resource, resource_in);
- if (missing_so)
- strcat(resource_being_loaded->resource, ".so");
+ }
- if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_GLOBAL))) {
- if (!suppress_logging) {
+ sprintf(mod->resource, "%s%s", resource_in, so_ext); /* safe */
+
+ resource_being_loaded = mod;
+ mod->lib = dlopen(filename, flags);
+ if (resource_being_loaded) {
+ resource_being_loaded = NULL;
+ if (mod->lib) {
+ ast_log(LOG_ERROR, "Module '%s' did not register itself during load\n", resource_in);
+ logged_dlclose(resource_in, mod->lib);
+ } else if (!suppress_logging) {
ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
}
- ast_free(resource_being_loaded);
- return NULL;
- }
+ ast_free(mod);
- /* the dlopen() succeeded, let's find out if the module
- registered itself */
- /* note that this will only work properly as long as
- ast_module_register() (which is called by the module's
- constructor) places the new module at the tail of the
- module_list
- */
- if (resource_being_loaded != (mod = AST_DLLIST_LAST(&module_list))) {
- ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in);
- /* no, it did not, so close it and return */
- logged_dlclose(resource_in, lib);
- /* note that the module's destructor will call ast_module_unregister(),
- which will free the structure we allocated in resource_being_loaded */
return NULL;
}
- wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
+ return mod;
+}
- /* if we are being asked only to load modules that provide global symbols,
- and this one does not, then close it and return */
- if (global_symbols_only && !wants_global) {
- logged_dlclose(resource_in, lib);
- return MODULE_LOCAL_ONLY;
+static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int global_symbols_only, unsigned int suppress_logging)
+{
+ char fn[PATH_MAX];
+ struct ast_module *mod;
+ size_t resource_in_len = strlen(resource_in);
+ int exports_globals;
+ const char *so_ext = "";
+
+ if (resource_in_len < 4 || strcasecmp(resource_in + resource_in_len - 3, ".so")) {
+ so_ext = ".so";
}
- logged_dlclose(resource_in, lib);
- resource_being_loaded = NULL;
+ snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, so_ext);
- /* start the load process again */
- resource_being_loaded = ast_calloc(1, space);
- if (!resource_being_loaded)
- return NULL;
- strcpy(resource_being_loaded->resource, resource_in);
- if (missing_so)
- strcat(resource_being_loaded->resource, ".so");
+ /* Try loading in quiet mode first with flags to export global symbols.
+ * If the module does not want to export globals we will close and reopen. */
+ mod = load_dlopen(resource_in, so_ext, fn,
+ global_symbols_only ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL,
+ suppress_logging);
- if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
- ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
- ast_free(resource_being_loaded);
+ if (!mod) {
return NULL;
}
- /* since the module was successfully opened, and it registered itself
- the previous time we did that, we're going to assume it worked this
- time too :) */
+ exports_globals = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
+ if ((global_symbols_only && exports_globals) || (!global_symbols_only && !exports_globals)) {
+ /* The first dlopen had the correct flags. */
+ return mod;
+ }
- AST_DLLIST_LAST(&module_list)->lib = lib;
- resource_being_loaded = NULL;
+ /* Close the module so we can reopen with correct flags. */
+ logged_dlclose(resource_in, mod->lib);
+ if (global_symbols_only) {
+ return MODULE_LOCAL_ONLY;
+ }
- return AST_DLLIST_LAST(&module_list);
+ return load_dlopen(resource_in, so_ext, fn,
+ exports_globals ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL,
+ 0);
}
int modules_shutdown(void)
@@ -621,9 +659,7 @@ int modules_shutdown(void)
ast_verb(1, "Unloading %s\n", mod->resource);
mod->info->unload();
}
- AST_LIST_HEAD_DESTROY(&mod->users);
- ao2_cleanup(mod->ref_debug);
- ast_free(mod);
+ module_destroy(mod);
somethingchanged = 1;
}
AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_END;
@@ -1120,13 +1156,13 @@ static enum ast_module_load_result start_resource(struct ast_module *mod)
/*! loads a resource based upon resource_name. If global_symbols_only is set
* only modules with global symbols will be loaded.
*
- * If the ast_heap is provided (not NULL) the module is found and added to the
- * heap without running the module's load() function. By doing this, modules
- * added to the resource_heap can be initialized later in order by priority.
+ * If the module_vector is provided (not NULL) the module is found and added to the
+ * vector without running the module's load() function. By doing this, modules
+ * can be initialized later in order by priority and dependencies.
*
- * If the ast_heap is not provided, the module's load function will be executed
+ * If the module_vector is not provided, the module's load function will be executed
* immediately */
-static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, unsigned int suppress_logging, struct ast_heap *resource_heap, int required)
+static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, unsigned int suppress_logging, struct module_vector *resource_heap, int required)
{
struct ast_module *mod;
enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
@@ -1139,7 +1175,7 @@ static enum ast_module_load_result load_resource(const char *resource_name, unsi
if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
return AST_MODULE_LOAD_SKIP;
} else {
- mod = load_dynamic_module(resource_name, global_symbols_only, suppress_logging, resource_heap);
+ mod = load_dynamic_module(resource_name, global_symbols_only, suppress_logging);
if (mod == MODULE_LOCAL_ONLY) {
return AST_MODULE_LOAD_SKIP;
}
@@ -1152,21 +1188,26 @@ static enum ast_module_load_result load_resource(const char *resource_name, unsi
}
if (inspect_module(mod)) {
- ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
- unload_dynamic_module(mod);
- return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
+ goto prestart_error;
}
mod->flags.declined = 0;
if (resource_heap) {
- ast_heap_push(resource_heap, mod);
+ if (AST_VECTOR_ADD_SORTED(resource_heap, mod, module_vector_cmp)) {
+ goto prestart_error;
+ }
res = AST_MODULE_LOAD_PRIORITY;
} else {
res = start_resource(mod);
}
return res;
+
+prestart_error:
+ ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
+ unload_dynamic_module(mod);
+ return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
}
int ast_load_resource(const char *resource_name)
@@ -1214,23 +1255,6 @@ static struct load_order_entry *add_to_load_order(const char *resource, struct l
return order;
}
-static int mod_load_cmp(void *a, void *b)
-{
- struct ast_module *a_mod = (struct ast_module *) a;
- struct ast_module *b_mod = (struct ast_module *) b;
- /* if load_pri is not set, default is 128. Lower is better */
- int a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 128;
- int b_pri = ast_test_flag(b_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 128;
-
- /*
- * Returns comparison values for a min-heap
- * <0 a_pri > b_pri
- * =0 a_pri == b_pri
- * >0 a_pri < b_pri
- */
- return b_pri - a_pri;
-}
-
AST_LIST_HEAD_NOLOCK(load_retries, load_order_entry);
/*! loads modules in order by load_pri, updates mod_count
@@ -1238,9 +1262,8 @@ AST_LIST_HEAD_NOLOCK(load_retries, load_order_entry);
*/
static int load_resource_list(struct load_order *load_order, unsigned int global_symbols, int *mod_count)
{
- struct ast_heap *resource_heap;
+ struct module_vector resource_heap;
struct load_order_entry *order;
- struct ast_module *mod;
struct load_retries load_retries;
int count = 0;
int res = 0;
@@ -1249,7 +1272,9 @@ static int load_resource_list(struct load_order *load_order, unsigned int global
AST_LIST_HEAD_INIT_NOLOCK(&load_retries);
- if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) {
+ if (AST_VECTOR_INIT(&resource_heap, 500)) {
+ ast_log(LOG_ERROR, "Failed to initialize module loader.\n");
+
return -1;
}
@@ -1258,7 +1283,7 @@ static int load_resource_list(struct load_order *load_order, unsigned int global
enum ast_module_load_result lres;
/* Suppress log messages unless this is the last pass */
- lres = load_resource(order->resource, global_symbols, 1, resource_heap, order->required);
+ lres = load_resource(order->resource, global_symbols, 1, &resource_heap, order->required);
ast_debug(3, "PASS 0: %-46s %d %d\n", order->resource, lres, global_symbols);
switch (lres) {
case AST_MODULE_LOAD_SUCCESS:
@@ -1282,7 +1307,7 @@ static int load_resource_list(struct load_order *load_order, unsigned int global
*/
break;
case AST_MODULE_LOAD_PRIORITY:
- /* load_resource worked and the module was added to the priority heap */
+ /* load_resource worked and the module was added to the priority vector */
AST_LIST_REMOVE_CURRENT(entry);
ast_free(order->resource);
ast_free(order);
@@ -1297,7 +1322,7 @@ static int load_resource_list(struct load_order *load_order, unsigned int global
enum ast_module_load_result lres;
/* Suppress log messages unless this is the last pass */
- lres = load_resource(order->resource, global_symbols, (i < LOAD_RETRIES - 1), resource_heap, order->required);
+ lres = load_resource(order->resource, global_symbols, (i < LOAD_RETRIES - 1), &resource_heap, order->required);
ast_debug(3, "PASS %d %-46s %d %d\n", i + 1, order->resource, lres, global_symbols);
switch (lres) {
/* These are all retryable. */
@@ -1335,7 +1360,8 @@ static int load_resource_list(struct load_order *load_order, unsigned int global
}
/* second remove modules from heap sorted by priority */
- while ((mod = ast_heap_pop(resource_heap))) {
+ for (i = 0; i < AST_VECTOR_SIZE(&resource_heap); i++) {
+ struct ast_module *mod = AST_VECTOR_GET(&resource_heap, i);
enum ast_module_load_result lres;
lres = start_resource(mod);
@@ -1365,7 +1391,7 @@ done:
if (mod_count) {
*mod_count += count;
}
- ast_heap_destroy(resource_heap);
+ AST_VECTOR_FREE(&resource_heap);
return res;
}
@@ -1503,33 +1529,57 @@ void ast_update_use_count(void)
AST_LIST_UNLOCK(&updaters);
}
+/*!
+ * \internal
+ * \brief Build an alpha sorted list of modules.
+ *
+ * \param alpha_module_list Pointer to uninitialized module_vector.
+ *
+ * This function always initializes alpha_module_list.
+ *
+ * \pre module_list must be locked.
+ */
+static int alpha_module_list_create(struct module_vector *alpha_module_list)
+{
+ struct ast_module *cur;
+
+ if (AST_VECTOR_INIT(alpha_module_list, 32)) {
+ return -1;
+ }
+
+ AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
+ if (AST_VECTOR_ADD_SORTED(alpha_module_list, cur, module_vector_strcasecmp)) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
int ast_update_module_list(int (*modentry)(const char *module, const char *description,
int usecnt, const char *status, const char *like,
enum ast_module_support_level support_level),
const char *like)
{
- struct ast_module *cur;
- int unlock = -1;
int total_mod_loaded = 0;
- AST_LIST_HEAD_NOLOCK(, ast_module) alpha_module_list = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
+ struct module_vector alpha_module_list;
- if (AST_DLLIST_TRYLOCK(&module_list)) {
- unlock = 0;
- }
+ AST_DLLIST_LOCK(&module_list);
- AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
- AST_LIST_INSERT_SORTALPHA(&alpha_module_list, cur, list_entry, resource);
- }
+ if (!alpha_module_list_create(&alpha_module_list)) {
+ int idx;
- while ((cur = AST_LIST_REMOVE_HEAD(&alpha_module_list, list_entry))) {
- total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
- cur->flags.running ? "Running" : "Not Running", like, cur->info->support_level);
- }
+ for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
+ struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
- if (unlock) {
- AST_DLLIST_UNLOCK(&module_list);
+ total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
+ cur->flags.running ? "Running" : "Not Running", like, cur->info->support_level);
+ }
}
+ AST_DLLIST_UNLOCK(&module_list);
+ AST_VECTOR_FREE(&alpha_module_list);
+
return total_mod_loaded;
}
@@ -1539,22 +1589,24 @@ int ast_update_module_list_data(int (*modentry)(const char *module, const char *
void *data),
const char *like, void *data)
{
- struct ast_module *cur;
int total_mod_loaded = 0;
- AST_LIST_HEAD_NOLOCK(, ast_module) alpha_module_list = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
+ struct module_vector alpha_module_list;
AST_DLLIST_LOCK(&module_list);
- AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
- AST_LIST_INSERT_SORTALPHA(&alpha_module_list, cur, list_entry, resource);
- }
+ if (!alpha_module_list_create(&alpha_module_list)) {
+ int idx;
+
+ for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
+ struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
- while ((cur = AST_LIST_REMOVE_HEAD(&alpha_module_list, list_entry))) {
- total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
- cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data);
+ total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
+ cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data);
+ }
}
AST_DLLIST_UNLOCK(&module_list);
+ AST_VECTOR_FREE(&alpha_module_list);
return total_mod_loaded;
}
@@ -1566,23 +1618,25 @@ int ast_update_module_list_condition(int (*modentry)(const char *module, const c
void *data, const char *condition),
const char *like, void *data, const char *condition)
{
- struct ast_module *cur;
int conditions_met = 0;
- AST_LIST_HEAD_NOLOCK(, ast_module) alpha_module_list = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
+ struct module_vector alpha_module_list;
AST_DLLIST_LOCK(&module_list);
- AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
- AST_LIST_INSERT_SORTALPHA(&alpha_module_list, cur, list_entry, resource);
- }
+ if (!alpha_module_list_create(&alpha_module_list)) {
+ int idx;
+
+ for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
+ struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
- while ((cur = AST_LIST_REMOVE_HEAD(&alpha_module_list, list_entry))) {
- conditions_met += modentry(cur->resource, cur->info->description, cur->usecount,
- cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data,
- condition);
+ conditions_met += modentry(cur->resource, cur->info->description, cur->usecount,
+ cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data,
+ condition);
+ }
}
AST_DLLIST_UNLOCK(&module_list);
+ AST_VECTOR_FREE(&alpha_module_list);
return conditions_met;
}
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index 2431ffc0c..68c53e7ff 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -1176,6 +1176,25 @@ void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp
ast_rwlock_unlock(&codecs->codecs_lock);
}
+enum ast_media_type ast_rtp_codecs_get_stream_type(struct ast_rtp_codecs *codecs)
+{
+ enum ast_media_type stream_type = AST_MEDIA_TYPE_UNKNOWN;
+ int payload;
+ struct ast_rtp_payload_type *type;
+
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ for (payload = 0; payload < AST_VECTOR_SIZE(&codecs->payload_mapping_rx); ++payload) {
+ type = AST_VECTOR_GET(&codecs->payload_mapping_rx, payload);
+ if (type && type->asterisk_format) {
+ stream_type = ast_format_get_type(type->format);
+ break;
+ }
+ }
+ ast_rwlock_unlock(&codecs->codecs_lock);
+
+ return stream_type;
+}
+
struct ast_rtp_payload_type *ast_rtp_codecs_get_payload(struct ast_rtp_codecs *codecs, int payload)
{
struct ast_rtp_payload_type *type = NULL;
diff --git a/res/res_clialiases.c b/res/res_clialiases.c
index 1a2fc6939..337c31c97 100644
--- a/res/res_clialiases.c
+++ b/res/res_clialiases.c
@@ -103,7 +103,7 @@ static char *cli_alias_passthrough(struct ast_cli_entry *e, int cmd, struct ast_
struct cli_alias tmp = {
.cli_entry.command = e->command,
};
- char *generator;
+ char *generator = NULL;
const char *line;
/* Try to find the alias based on the CLI entry */
@@ -118,14 +118,10 @@ static char *cli_alias_passthrough(struct ast_cli_entry *e, int cmd, struct ast_
case CLI_GENERATE:
line = a->line;
line += (strlen(alias->alias));
- if (!strncasecmp(alias->alias, alias->real_cmd, strlen(alias->alias))) {
- generator = NULL;
- } else if (!ast_strlen_zero(a->word)) {
+ if (strncasecmp(alias->alias, alias->real_cmd, strlen(alias->alias))) {
struct ast_str *real_cmd = ast_str_alloca(strlen(alias->real_cmd) + strlen(line) + 1);
ast_str_append(&real_cmd, 0, "%s%s", alias->real_cmd, line);
generator = ast_cli_generator(ast_str_buffer(real_cmd), a->word, a->n);
- } else {
- generator = ast_cli_generator(alias->real_cmd, a->word, a->n);
}
ao2_ref(alias, -1);
return generator;
diff --git a/res/res_hep.c b/res/res_hep.c
index 48e7bbcbe..4e548e274 100644
--- a/res/res_hep.c
+++ b/res/res_hep.c
@@ -421,7 +421,7 @@ int hepv3_is_loaded(void)
{
RAII_VAR(struct module_config *, config, ao2_global_obj_ref(global_config), ao2_cleanup);
- return (config != NULL) ? 1 : 0;
+ return config && config->general->enabled;
}
struct hepv3_capture_info *hepv3_create_capture_info(const void *payload, size_t len)
diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c
index ef1b81c2a..17e91b70c 100644
--- a/res/res_musiconhold.c
+++ b/res/res_musiconhold.c
@@ -333,6 +333,7 @@ static int ast_moh_files_next(struct ast_channel *chan)
}
} else {
state->announcement = 0;
+ state->samples = 0;
}
if (!state->class->total_files) {
@@ -1934,6 +1935,9 @@ static char *handle_cli_moh_show_classes(struct ast_cli_entry *e, int cmd, struc
ast_cli(a->fd, "Class: %s\n", class->name);
ast_cli(a->fd, "\tMode: %s\n", S_OR(class->mode, "<none>"));
ast_cli(a->fd, "\tDirectory: %s\n", S_OR(class->dir, "<none>"));
+ if (ast_test_flag(class, MOH_ANNOUNCEMENT)) {
+ ast_cli(a->fd, "\tAnnouncement: %s\n", S_OR(class->announcement, "<none>"));
+ }
if (ast_test_flag(class, MOH_CUSTOM)) {
ast_cli(a->fd, "\tApplication: %s\n", S_OR(class->args, "<none>"));
ast_cli(a->fd, "\tKill Escalation Delay: %zu ms\n", class->kill_delay / 1000);
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index bdc83301e..51e509c77 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -256,6 +256,8 @@ struct rtp_learning_info {
struct timeval received; /*!< The time of the first received packet */
int max_seq; /*!< The highest sequence number received */
int packets; /*!< The number of remaining packets before the source is accepted */
+ /*! Type of media stream carried by the RTP instance */
+ enum ast_media_type stream_type;
};
#ifdef HAVE_OPENSSL_SRTP
@@ -3095,18 +3097,30 @@ static int rtp_learning_rtp_seq_update(struct rtp_learning_info *info, uint16_t
info->received = ast_tvnow();
}
- /*
- * Protect against packet floods by checking that we
- * received the packet sequence in at least the minimum
- * allowed time.
- */
- if (ast_tvzero(info->received)) {
- info->received = ast_tvnow();
- } else if (!info->packets && (ast_tvdiff_ms(ast_tvnow(), info->received) < learning_min_duration )) {
- /* Packet flood; reset */
- info->packets = learning_min_sequential - 1;
- info->received = ast_tvnow();
+ switch (info->stream_type) {
+ case AST_MEDIA_TYPE_UNKNOWN:
+ case AST_MEDIA_TYPE_AUDIO:
+ /*
+ * Protect against packet floods by checking that we
+ * received the packet sequence in at least the minimum
+ * allowed time.
+ */
+ if (ast_tvzero(info->received)) {
+ info->received = ast_tvnow();
+ } else if (!info->packets
+ && ast_tvdiff_ms(ast_tvnow(), info->received) < learning_min_duration) {
+ /* Packet flood; reset */
+ info->packets = learning_min_sequential - 1;
+ info->received = ast_tvnow();
+ }
+ break;
+ case AST_MEDIA_TYPE_VIDEO:
+ case AST_MEDIA_TYPE_IMAGE:
+ case AST_MEDIA_TYPE_TEXT:
+ case AST_MEDIA_TYPE_END:
+ break;
}
+
info->max_seq = seq;
return info->packets;
@@ -5951,6 +5965,15 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
* source and we should switch to it.
*/
if (!ast_sockaddr_cmp(&rtp->rtp_source_learn.proposed_address, &addr)) {
+ if (rtp->rtp_source_learn.stream_type == AST_MEDIA_TYPE_UNKNOWN) {
+ struct ast_rtp_codecs *codecs;
+
+ codecs = ast_rtp_instance_get_codecs(instance);
+ rtp->rtp_source_learn.stream_type =
+ ast_rtp_codecs_get_stream_type(codecs);
+ ast_verb(4, "%p -- Strict RTP qualifying stream type: %s\n",
+ rtp, ast_codec_media_type2str(rtp->rtp_source_learn.stream_type));
+ }
if (!rtp_learning_rtp_seq_update(&rtp->rtp_source_learn, seqno)) {
/* Accept the new RTP stream */
ast_verb(4, "%p -- Strict RTP switching source address to %s\n",
diff --git a/res/res_smdi.c b/res/res_smdi.c
index 0edabb83c..612a4b87b 100644
--- a/res/res_smdi.c
+++ b/res/res_smdi.c
@@ -586,9 +586,8 @@ static void *smdi_read(void *iface_p)
struct ast_smdi_interface *iface = iface_p;
struct ast_smdi_md_message *md_msg;
struct ast_smdi_mwi_message *mwi_msg;
- char c = '\0';
char *cp = NULL;
- int i;
+ int i, c;
int start = 0;
/* read an smdi message */
@@ -616,7 +615,14 @@ static void *smdi_read(void *iface_p)
/* read the message desk number */
for (i = 0; i < sizeof(md_msg->mesg_desk_num) - 1; i++) {
- md_msg->mesg_desk_num[i] = fgetc(iface->file);
+ c = fgetc(iface->file);
+ if (c == EOF) {
+ ast_log(LOG_ERROR, "Unexpected EOF while reading MD message\n");
+ ao2_ref(md_msg, -1);
+ ao2_ref(iface, -1);
+ return NULL;
+ }
+ md_msg->mesg_desk_num[i] = (char) c;
ast_debug(1, "Read a '%c'\n", md_msg->mesg_desk_num[i]);
}
@@ -626,7 +632,14 @@ static void *smdi_read(void *iface_p)
/* read the message desk terminal number */
for (i = 0; i < sizeof(md_msg->mesg_desk_term) - 1; i++) {
- md_msg->mesg_desk_term[i] = fgetc(iface->file);
+ c = fgetc(iface->file);
+ if (c == EOF) {
+ ast_log(LOG_ERROR, "Unexpected EOF while reading SMDI message\n");
+ ao2_ref(md_msg, -1);
+ ao2_ref(iface, -1);
+ return NULL;
+ }
+ md_msg->mesg_desk_term[i] = (char) c;
ast_debug(1, "Read a '%c'\n", md_msg->mesg_desk_term[i]);
}
@@ -635,7 +648,14 @@ static void *smdi_read(void *iface_p)
ast_debug(1, "The message desk terminal is '%s'\n", md_msg->mesg_desk_term);
/* read the message type */
- md_msg->type = fgetc(iface->file);
+ c = fgetc(iface->file);
+ if (c == EOF) {
+ ast_log(LOG_ERROR, "Unexpected EOF while reading SMDI message\n");
+ ao2_ref(md_msg, -1);
+ ao2_ref(iface, -1);
+ return NULL;
+ }
+ md_msg->type = (char) c;
ast_debug(1, "Message type is '%c'\n", md_msg->type);
@@ -717,7 +737,7 @@ static void *smdi_read(void *iface_p)
/* discard the 'I' (from 'MWI') */
fgetc(iface->file);
-
+
/* read the forwarding station number (may be blank) */
cp = &mwi_msg->fwd_st[0];
for (i = 0; i < sizeof(mwi_msg->fwd_st) - 1; i++) {
@@ -740,8 +760,16 @@ static void *smdi_read(void *iface_p)
ast_copy_string(mwi_msg->name, mwi_msg->fwd_st, sizeof(mwi_msg->name));
/* read the mwi failure cause */
- for (i = 0; i < sizeof(mwi_msg->cause) - 1; i++)
- mwi_msg->cause[i] = fgetc(iface->file);
+ for (i = 0; i < sizeof(mwi_msg->cause) - 1; i++) {
+ c = fgetc(iface->file);
+ if (c == EOF) {
+ ast_log(LOG_ERROR, "Unexpected EOF while reading MWI message\n");
+ ao2_ref(mwi_msg, -1);
+ ao2_ref(iface, -1);
+ return NULL;
+ }
+ mwi_msg->cause[i] = (char) c;
+ }
mwi_msg->cause[sizeof(mwi_msg->cause) - 1] = '\0';
@@ -1377,6 +1405,9 @@ static int load_module(void)
ast_custom_function_register(&smdi_msg_retrieve_function);
ast_custom_function_register(&smdi_msg_function);
+ /* For Optional API. */
+ ast_module_shutdown_ref(AST_MODULE_SELF);
+
return AST_MODULE_LOAD_SUCCESS;
}
@@ -1406,9 +1437,6 @@ static int _unload_module(int fromload)
smdi_loaded = 0;
- /* For Optional API. */
- ast_module_shutdown_ref(AST_MODULE_SELF);
-
return 0;
}