summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/channel.c21
-rw-r--r--main/format_cap.c1
-rw-r--r--main/iostream.c6
-rw-r--r--main/libasteriskssl.c11
-rw-r--r--main/manager.c15
-rw-r--r--main/pbx.c2
-rw-r--r--main/rtp_engine.c14
-rw-r--r--main/stream.c339
-rw-r--r--main/tcptls.c4
9 files changed, 384 insertions, 29 deletions
diff --git a/main/channel.c b/main/channel.c
index 2890cf000..54db47351 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -823,7 +823,12 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
ast_channel_stage_snapshot(tmp);
if (!(nativeformats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
- /* format capabilities structure allocation failure */
+ /*
+ * Aborting the channel creation. We do not need to complete staging
+ * the channel snapshot because the channel has not been finalized or
+ * linked into the channels container yet. Nobody else knows about
+ * this channel nor will anybody ever know about it.
+ */
return ast_channel_unref(tmp);
}
ast_format_cap_append(nativeformats, ast_format_none, 0);
@@ -849,6 +854,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
if (!(schedctx = ast_sched_context_create())) {
ast_log(LOG_WARNING, "Channel allocation failed: Unable to create schedule context\n");
+ /* See earlier channel creation abort comment above. */
return ast_channel_unref(tmp);
}
ast_channel_sched_set(tmp, schedctx);
@@ -863,6 +869,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
ast_channel_caller(tmp)->id.name.valid = 1;
ast_channel_caller(tmp)->id.name.str = ast_strdup(cid_name);
if (!ast_channel_caller(tmp)->id.name.str) {
+ /* See earlier channel creation abort comment above. */
return ast_channel_unref(tmp);
}
}
@@ -870,6 +877,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
ast_channel_caller(tmp)->id.number.valid = 1;
ast_channel_caller(tmp)->id.number.str = ast_strdup(cid_num);
if (!ast_channel_caller(tmp)->id.number.str) {
+ /* See earlier channel creation abort comment above. */
return ast_channel_unref(tmp);
}
}
@@ -883,6 +891,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
}
if (needqueue && ast_channel_internal_alertpipe_init(tmp)) {
+ /* See earlier channel creation abort comment above. */
return ast_channel_unref(tmp);
}
@@ -974,20 +983,14 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
if (assignedids && (does_id_conflict(assignedids->uniqueid) || does_id_conflict(assignedids->uniqueid2))) {
ast_channel_internal_errno_set(AST_CHANNEL_ERROR_ID_EXISTS);
ao2_unlock(channels);
- /* This is a bit unorthodox, but we can't just call ast_channel_stage_snapshot_done()
- * because that will result in attempting to publish the channel snapshot. That causes
- * badness in some places, such as CDRs. So we need to manually clear the flag on the
- * channel that says that a snapshot is being cleared.
- */
- ast_clear_flag(ast_channel_flags(tmp), AST_FLAG_SNAPSHOT_STAGE);
ast_channel_unlock(tmp);
+ /* See earlier channel creation abort comment above. */
return ast_channel_unref(tmp);
}
+ /* Finalize and link into the channels container. */
ast_channel_internal_finalize(tmp);
-
ast_atomic_fetchadd_int(&chancount, +1);
-
ao2_link_flags(channels, tmp, OBJ_NOLOCK);
ao2_unlock(channels);
diff --git a/main/format_cap.c b/main/format_cap.c
index 1fe342b31..b0897c001 100644
--- a/main/format_cap.c
+++ b/main/format_cap.c
@@ -268,6 +268,7 @@ int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_
{
int idx, res = 0;
+ /* NOTE: The streams API is dependent on the formats being in "preference" order */
for (idx = 0; (idx < AST_VECTOR_SIZE(&src->preference_order)) && !res; ++idx) {
struct format_cap_framed *framed = AST_VECTOR_GET(&src->preference_order, idx);
diff --git a/main/iostream.c b/main/iostream.c
index 22cd5985c..6187bc2fb 100644
--- a/main/iostream.c
+++ b/main/iostream.c
@@ -465,19 +465,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 defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 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 !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 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 */
+#endif /* !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L */
}
SSL_free(stream->ssl);
diff --git a/main/libasteriskssl.c b/main/libasteriskssl.c
index 9905b150c..0ed05e3dc 100644
--- a/main/libasteriskssl.c
+++ b/main/libasteriskssl.c
@@ -72,7 +72,7 @@ static void ssl_lock(int mode, int n, const char *file, int line)
}
}
-#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L
+#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L
int SSL_library_init(void)
{
#if defined(AST_DEVMODE)
@@ -114,17 +114,20 @@ void ERR_free_strings(void)
{
/* we can't allow this to be called, ever */
}
-#endif /* !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L */
+#endif /* !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L */
#endif /* HAVE_OPENSSL */
/*!
* \internal
* \brief Common OpenSSL initialization for all of Asterisk.
+ *
+ * Not needed for OpenSSL versions >= 1.1.0
*/
int ast_ssl_init(void)
{
-#ifdef HAVE_OPENSSL
+#if defined(HAVE_OPENSSL) && defined(OPENSSL_VERSION_NUMBER) && \
+ OPENSSL_VERSION_NUMBER < 0x10100000L
unsigned int i;
int (*real_SSL_library_init)(void);
void (*real_CRYPTO_set_id_callback)(unsigned long (*)(void));
@@ -189,7 +192,7 @@ int ast_ssl_init(void)
startup_complete = 1;
-#endif /* HAVE_OPENSSL */
+#endif /* HAVE_OPENSSL and its version < 1.1 */
return 0;
}
diff --git a/main/manager.c b/main/manager.c
index dfe056438..a25497fd3 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -5130,13 +5130,15 @@ static void *fast_originate(void *data)
if (!ast_strlen_zero(in->app)) {
res = ast_pbx_outgoing_app(in->tech, in->cap, in->data,
- in->timeout, in->app, in->appdata, &reason, 1,
+ in->timeout, in->app, in->appdata, &reason,
+ AST_OUTGOING_WAIT,
S_OR(in->cid_num, NULL),
S_OR(in->cid_name, NULL),
in->vars, in->account, &chan, &assignedids);
} else {
res = ast_pbx_outgoing_exten(in->tech, in->cap, in->data,
- in->timeout, in->context, in->exten, in->priority, &reason, 1,
+ in->timeout, in->context, in->exten, in->priority, &reason,
+ AST_OUTGOING_WAIT,
S_OR(in->cid_num, NULL),
S_OR(in->cid_name, NULL),
in->vars, in->account, &chan, in->early_media, &assignedids);
@@ -5607,11 +5609,16 @@ static int action_originate(struct mansession *s, const struct message *m)
}
}
} else if (!ast_strlen_zero(app)) {
- res = ast_pbx_outgoing_app(tech, cap, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL, assignedids.uniqueid ? &assignedids : NULL);
+ res = ast_pbx_outgoing_app(tech, cap, data, to, app, appdata, &reason,
+ AST_OUTGOING_WAIT, l, n, vars, account, NULL,
+ assignedids.uniqueid ? &assignedids : NULL);
ast_variables_destroy(vars);
} else {
if (exten && context && pi) {
- res = ast_pbx_outgoing_exten(tech, cap, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL, bridge_early, assignedids.uniqueid ? &assignedids : NULL);
+ res = ast_pbx_outgoing_exten(tech, cap, data, to,
+ context, exten, pi, &reason, AST_OUTGOING_WAIT,
+ l, n, vars, account, NULL, bridge_early,
+ assignedids.uniqueid ? &assignedids : NULL);
ast_variables_destroy(vars);
} else {
astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
diff --git a/main/pbx.c b/main/pbx.c
index 3e35a3a14..47e0b0eda 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -7876,7 +7876,7 @@ int ast_pbx_outgoing_exten_predial(const char *type, struct ast_format_cap *cap,
early_media, assignedids, predial_callee);
if (res < 0 /* Call failed to get connected for some reason. */
- && 1 < synchronous
+ && 0 < synchronous
&& ast_exists_extension(NULL, context, "failed", 1, NULL)) {
struct ast_channel *failed;
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index 3ef2d876b..a46546318 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -1899,16 +1899,16 @@ void ast_rtp_instance_set_stats_vars(struct ast_channel *chan, struct ast_rtp_in
{
char quality_buf[AST_MAX_USER_FIELD];
char *quality;
- struct ast_channel *bridge = ast_channel_bridge_peer(chan);
+ struct ast_channel *bridge;
- ast_channel_lock(chan);
- ast_channel_stage_snapshot(chan);
- ast_channel_unlock(chan);
+ bridge = ast_channel_bridge_peer(chan);
if (bridge) {
- ast_channel_lock(bridge);
+ ast_channel_lock_both(chan, bridge);
ast_channel_stage_snapshot(bridge);
- ast_channel_unlock(bridge);
+ } else {
+ ast_channel_lock(chan);
}
+ ast_channel_stage_snapshot(chan);
quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY,
quality_buf, sizeof(quality_buf));
@@ -1946,11 +1946,9 @@ void ast_rtp_instance_set_stats_vars(struct ast_channel *chan, struct ast_rtp_in
}
}
- ast_channel_lock(chan);
ast_channel_stage_snapshot_done(chan);
ast_channel_unlock(chan);
if (bridge) {
- ast_channel_lock(bridge);
ast_channel_stage_snapshot_done(bridge);
ast_channel_unlock(bridge);
ast_channel_unref(bridge);
diff --git a/main/stream.c b/main/stream.c
new file mode 100644
index 000000000..24844c4ab
--- /dev/null
+++ b/main/stream.c
@@ -0,0 +1,339 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2017, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Media Stream API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+#include "asterisk/logger.h"
+#include "asterisk/stream.h"
+#include "asterisk/strings.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cap.h"
+
+struct ast_stream {
+ /*!
+ * \brief The type of media the stream is handling
+ */
+ enum ast_media_type type;
+
+ /*!
+ * \brief The position of the stream in the topology
+ */
+ unsigned int position;
+
+ /*!
+ * \brief Current formats negotiated on the stream
+ */
+ struct ast_format_cap *formats;
+
+ /*!
+ * \brief The current state of the stream
+ */
+ enum ast_stream_state state;
+
+ /*!
+ * \brief Name for the stream within the context of the channel it is on
+ */
+ char name[0];
+};
+
+struct ast_stream_topology {
+ /*!
+ * \brief A vector of all the streams in this topology
+ */
+ AST_VECTOR(, struct ast_stream *) streams;
+};
+
+struct ast_stream *ast_stream_create(const char *name, enum ast_media_type type)
+{
+ struct ast_stream *stream;
+
+ stream = ast_calloc(1, sizeof(*stream) + strlen(S_OR(name, "")) + 1);
+ if (!stream) {
+ return NULL;
+ }
+
+ stream->type = type;
+ stream->state = AST_STREAM_STATE_INACTIVE;
+ strcpy(stream->name, S_OR(name, "")); /* Safe */
+
+ return stream;
+}
+
+struct ast_stream *ast_stream_clone(const struct ast_stream *stream)
+{
+ struct ast_stream *new_stream;
+ size_t stream_size;
+
+ if (!stream) {
+ return NULL;
+ }
+
+ stream_size = sizeof(*stream) + strlen(stream->name) + 1;
+ new_stream = ast_calloc(1, stream_size);
+ if (!new_stream) {
+ return NULL;
+ }
+
+ memcpy(new_stream, stream, stream_size);
+ if (new_stream->formats) {
+ ao2_ref(new_stream->formats, +1);
+ }
+
+ return new_stream;
+}
+
+void ast_stream_destroy(struct ast_stream *stream)
+{
+ if (!stream) {
+ return;
+ }
+
+ ao2_cleanup(stream->formats);
+ ast_free(stream);
+}
+
+const char *ast_stream_get_name(const struct ast_stream *stream)
+{
+ ast_assert(stream != NULL);
+
+ return stream->name;
+}
+
+enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
+{
+ ast_assert(stream != NULL);
+
+ return stream->type;
+}
+
+void ast_stream_set_type(struct ast_stream *stream, enum ast_media_type type)
+{
+ ast_assert(stream != NULL);
+
+ stream->type = type;
+}
+
+struct ast_format_cap *ast_stream_get_formats(const struct ast_stream *stream)
+{
+ ast_assert(stream != NULL);
+
+ return stream->formats;
+}
+
+void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
+{
+ ast_assert(stream != NULL);
+
+ ao2_cleanup(stream->formats);
+ stream->formats = ao2_bump(caps);
+}
+
+enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
+{
+ ast_assert(stream != NULL);
+
+ return stream->state;
+}
+
+void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
+{
+ ast_assert(stream != NULL);
+
+ stream->state = state;
+}
+
+int ast_stream_get_position(const struct ast_stream *stream)
+{
+ ast_assert(stream != NULL);
+
+ return stream->position;
+}
+
+#define TOPOLOGY_INITIAL_STREAM_COUNT 2
+struct ast_stream_topology *ast_stream_topology_create(void)
+{
+ struct ast_stream_topology *topology;
+
+ topology = ast_calloc(1, sizeof(*topology));
+ if (!topology) {
+ return NULL;
+ }
+
+ if (AST_VECTOR_INIT(&topology->streams, TOPOLOGY_INITIAL_STREAM_COUNT)) {
+ ast_free(topology);
+ topology = NULL;
+ }
+
+ return topology;
+}
+
+struct ast_stream_topology *ast_stream_topology_clone(
+ const struct ast_stream_topology *topology)
+{
+ struct ast_stream_topology *new_topology;
+ int i;
+
+ ast_assert(topology != NULL);
+
+ new_topology = ast_stream_topology_create();
+ if (!new_topology) {
+ return NULL;
+ }
+
+ for (i = 0; i < AST_VECTOR_SIZE(&topology->streams); i++) {
+ struct ast_stream *stream =
+ ast_stream_clone(AST_VECTOR_GET(&topology->streams, i));
+
+ if (!stream || AST_VECTOR_APPEND(&new_topology->streams, stream)) {
+ ast_stream_destroy(stream);
+ ast_stream_topology_destroy(new_topology);
+ return NULL;
+ }
+ }
+
+ return new_topology;
+}
+
+void ast_stream_topology_destroy(struct ast_stream_topology *topology)
+{
+ if (!topology) {
+ return;
+ }
+
+ AST_VECTOR_CALLBACK_VOID(&topology->streams, ast_stream_destroy);
+ AST_VECTOR_FREE(&topology->streams);
+ ast_free(topology);
+}
+
+int ast_stream_topology_append_stream(struct ast_stream_topology *topology, struct ast_stream *stream)
+{
+ ast_assert(topology && stream);
+
+ if (AST_VECTOR_APPEND(&topology->streams, stream)) {
+ return -1;
+ }
+
+ stream->position = AST_VECTOR_SIZE(&topology->streams) - 1;
+
+ return AST_VECTOR_SIZE(&topology->streams) - 1;
+}
+
+int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
+{
+ ast_assert(topology != NULL);
+
+ return AST_VECTOR_SIZE(&topology->streams);
+}
+
+struct ast_stream *ast_stream_topology_get_stream(
+ const struct ast_stream_topology *topology, unsigned int stream_num)
+{
+ ast_assert(topology != NULL);
+
+ return AST_VECTOR_GET(&topology->streams, stream_num);
+}
+
+int ast_stream_topology_set_stream(struct ast_stream_topology *topology,
+ unsigned int position, struct ast_stream *stream)
+{
+ struct ast_stream *existing_stream;
+
+ ast_assert(topology && stream);
+
+ if (position > AST_VECTOR_SIZE(&topology->streams)) {
+ return -1;
+ }
+
+ if (position < AST_VECTOR_SIZE(&topology->streams)) {
+ existing_stream = AST_VECTOR_GET(&topology->streams, position);
+ ast_stream_destroy(existing_stream);
+ }
+
+ stream->position = position;
+
+ if (position == AST_VECTOR_SIZE(&topology->streams)) {
+ AST_VECTOR_APPEND(&topology->streams, stream);
+ return 0;
+ }
+
+ return AST_VECTOR_REPLACE(&topology->streams, position, stream);
+}
+
+struct ast_stream_topology *ast_stream_topology_create_from_format_cap(
+ struct ast_format_cap *cap)
+{
+ struct ast_stream_topology *topology;
+ enum ast_media_type type;
+
+ ast_assert(cap != NULL);
+
+ topology = ast_stream_topology_create();
+ if (!topology) {
+ return NULL;
+ }
+
+ for (type = AST_MEDIA_TYPE_UNKNOWN + 1; type < AST_MEDIA_TYPE_END; type++) {
+ struct ast_format_cap *new_cap;
+ struct ast_stream *stream;
+
+ if (!ast_format_cap_has_type(cap, type)) {
+ continue;
+ }
+
+ new_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!new_cap) {
+ ast_stream_topology_destroy(topology);
+ return NULL;
+ }
+
+ ast_format_cap_set_framing(new_cap, ast_format_cap_get_framing(cap));
+ if (ast_format_cap_append_from_cap(new_cap, cap, type)) {
+ ao2_cleanup(new_cap);
+ ast_stream_topology_destroy(topology);
+ return NULL;
+ }
+
+ stream = ast_stream_create(ast_codec_media_type2str(type), type);
+ if (!stream) {
+ ao2_cleanup(new_cap);
+ ast_stream_topology_destroy(topology);
+ return NULL;
+ }
+ /* We're transferring the initial ref so no bump needed */
+ stream->formats = new_cap;
+ stream->state = AST_STREAM_STATE_SENDRECV;
+ if (ast_stream_topology_append_stream(topology, stream) == -1) {
+ ast_stream_destroy(stream);
+ ast_stream_topology_destroy(topology);
+ return NULL;
+ }
+ }
+
+ return topology;
+}
diff --git a/main/tcptls.c b/main/tcptls.c
index b20e04ef8..7f1421db8 100644
--- a/main/tcptls.c
+++ b/main/tcptls.c
@@ -324,12 +324,16 @@ static int __ssl_setup(struct ast_tls_config *cfg, int client)
cfg->ssl_ctx = SSL_CTX_new(SSLv3_client_method());
} else
#endif
+#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+ cfg->ssl_ctx = SSL_CTX_new(TLS_client_method());
+#else
if (ast_test_flag(&cfg->flags, AST_SSL_TLSV1_CLIENT)) {
cfg->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
} else {
disable_ssl = 1;
cfg->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
}
+#endif
} else {
disable_ssl = 1;
cfg->ssl_ctx = SSL_CTX_new(SSLv23_server_method());