diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/channel.c | 21 | ||||
-rw-r--r-- | main/format_cap.c | 1 | ||||
-rw-r--r-- | main/iostream.c | 6 | ||||
-rw-r--r-- | main/libasteriskssl.c | 11 | ||||
-rw-r--r-- | main/manager.c | 15 | ||||
-rw-r--r-- | main/pbx.c | 2 | ||||
-rw-r--r-- | main/rtp_engine.c | 14 | ||||
-rw-r--r-- | main/stream.c | 339 | ||||
-rw-r--r-- | main/tcptls.c | 4 |
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()); |