2001-08-05 21:56:28 +00:00
|
|
|
/*
|
2005-09-14 20:46:50 +00:00
|
|
|
* Asterisk -- An open source telephony toolkit.
|
2001-08-05 21:56:28 +00:00
|
|
|
*
|
2005-01-21 07:06:25 +00:00
|
|
|
* Copyright (C) 1999 - 2005, Digium, Inc.
|
2001-08-05 21:56:28 +00:00
|
|
|
*
|
2004-09-17 15:05:29 +00:00
|
|
|
* Mark Spencer <markster@digium.com>
|
2001-08-05 21:56:28 +00:00
|
|
|
*
|
2005-09-14 20:46:50 +00:00
|
|
|
* 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.
|
|
|
|
*
|
2001-08-05 21:56:28 +00:00
|
|
|
* This program is free software, distributed under the terms of
|
2005-09-14 20:46:50 +00:00
|
|
|
* the GNU General Public License Version 2. See the LICENSE file
|
|
|
|
* at the top of the source tree.
|
|
|
|
*/
|
|
|
|
|
2005-10-24 20:12:06 +00:00
|
|
|
/*! \file
|
2005-09-14 20:46:50 +00:00
|
|
|
*
|
2005-10-24 20:12:06 +00:00
|
|
|
* \brief Convenient Application Routines
|
2005-12-30 21:18:06 +00:00
|
|
|
*
|
2009-03-04 20:48:42 +00:00
|
|
|
* \author Mark Spencer <markster@digium.com>
|
2001-08-05 21:56:28 +00:00
|
|
|
*/
|
|
|
|
|
2012-10-18 14:17:40 +00:00
|
|
|
/** \example
|
|
|
|
* \par This is an example of how to develop an app.
|
|
|
|
* Application Skeleton is an example of creating an application for Asterisk.
|
|
|
|
* \verbinclude app_skel.c
|
2012-10-13 16:38:48 +00:00
|
|
|
*/
|
|
|
|
|
2012-06-15 16:20:16 +00:00
|
|
|
/*** MODULEINFO
|
|
|
|
<support_level>core</support_level>
|
|
|
|
***/
|
|
|
|
|
2006-06-07 18:54:56 +00:00
|
|
|
#include "asterisk.h"
|
|
|
|
|
2007-11-24 13:48:48 +00:00
|
|
|
#ifdef HAVE_SYS_STAT_H
|
2005-02-28 23:18:03 +00:00
|
|
|
#include <sys/stat.h>
|
2007-11-24 13:48:48 +00:00
|
|
|
#endif
|
2011-01-19 20:33:30 +00:00
|
|
|
#include <regex.h> /* for regcomp(3) */
|
|
|
|
#include <sys/file.h> /* for flock(2) */
|
|
|
|
#include <signal.h> /* for pthread_sigmask(3) */
|
2009-01-12 23:06:12 +00:00
|
|
|
#include <stdlib.h> /* for closefrom(3) */
|
2011-01-19 20:33:30 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/wait.h> /* for waitpid(2) */
|
|
|
|
#ifndef HAVE_CLOSEFROM
|
|
|
|
#include <dirent.h> /* for opendir(3) */
|
|
|
|
#endif
|
2009-01-29 23:15:40 +00:00
|
|
|
#ifdef HAVE_CAP
|
|
|
|
#include <sys/capability.h>
|
|
|
|
#endif /* HAVE_CAP */
|
2005-04-22 13:11:34 +00:00
|
|
|
|
2007-11-20 23:16:15 +00:00
|
|
|
#include "asterisk/paths.h" /* use ast_config_AST_DATA_DIR */
|
2005-04-21 06:02:45 +00:00
|
|
|
#include "asterisk/channel.h"
|
|
|
|
#include "asterisk/pbx.h"
|
|
|
|
#include "asterisk/file.h"
|
|
|
|
#include "asterisk/app.h"
|
|
|
|
#include "asterisk/dsp.h"
|
|
|
|
#include "asterisk/utils.h"
|
|
|
|
#include "asterisk/lock.h"
|
|
|
|
#include "asterisk/indications.h"
|
2007-04-25 19:27:42 +00:00
|
|
|
#include "asterisk/linkedlists.h"
|
2008-12-13 08:36:35 +00:00
|
|
|
#include "asterisk/threadstorage.h"
|
2011-08-22 19:19:44 +00:00
|
|
|
#include "asterisk/test.h"
|
2012-06-14 23:22:53 +00:00
|
|
|
#include "asterisk/module.h"
|
2013-03-16 15:45:58 +00:00
|
|
|
#include "asterisk/astobj2.h"
|
|
|
|
#include "asterisk/stasis.h"
|
2013-05-24 20:44:07 +00:00
|
|
|
#include "asterisk/stasis_channels.h"
|
|
|
|
#include "asterisk/json.h"
|
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
|
|
|
#include "asterisk/format_cache.h"
|
2013-03-16 15:45:58 +00:00
|
|
|
|
|
|
|
#define MWI_TOPIC_BUCKETS 57
|
2008-12-13 08:36:35 +00:00
|
|
|
|
2009-03-27 16:21:10 +00:00
|
|
|
AST_THREADSTORAGE_PUBLIC(ast_str_thread_global_buf);
|
2008-12-13 08:36:35 +00:00
|
|
|
|
2011-01-19 20:33:30 +00:00
|
|
|
static pthread_t shaun_of_the_dead_thread = AST_PTHREADT_NULL;
|
|
|
|
|
|
|
|
struct zombie {
|
|
|
|
pid_t pid;
|
|
|
|
AST_LIST_ENTRY(zombie) list;
|
|
|
|
};
|
|
|
|
|
|
|
|
static AST_LIST_HEAD_STATIC(zombies, zombie);
|
|
|
|
|
2013-05-24 20:44:07 +00:00
|
|
|
/*
|
2013-08-22 18:52:41 +00:00
|
|
|
* @{ \brief Define \ref stasis topic objects
|
2013-05-24 20:44:07 +00:00
|
|
|
*/
|
2013-03-16 15:45:58 +00:00
|
|
|
static struct stasis_topic *mwi_topic_all;
|
2013-08-01 13:49:34 +00:00
|
|
|
static struct stasis_cache *mwi_state_cache;
|
2013-03-16 15:45:58 +00:00
|
|
|
static struct stasis_caching_topic *mwi_topic_cached;
|
|
|
|
static struct stasis_topic_pool *mwi_topic_pool;
|
2013-08-22 18:52:41 +00:00
|
|
|
|
|
|
|
static struct stasis_topic *queue_topic_all;
|
|
|
|
static struct stasis_topic_pool *queue_topic_pool;
|
2013-05-24 20:44:07 +00:00
|
|
|
/* @} */
|
|
|
|
|
2014-05-22 12:01:37 +00:00
|
|
|
/*! \brief Convert a MWI \ref stasis_message to a \ref ast_event */
|
|
|
|
static struct ast_event *mwi_to_event(struct stasis_message *message)
|
|
|
|
{
|
|
|
|
struct ast_event *event;
|
|
|
|
struct ast_mwi_state *mwi_state;
|
|
|
|
char *mailbox;
|
|
|
|
char *context;
|
|
|
|
|
|
|
|
if (!message) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
mwi_state = stasis_message_data(message);
|
|
|
|
|
|
|
|
/* Strip off @context */
|
|
|
|
context = mailbox = ast_strdupa(mwi_state->uniqueid);
|
|
|
|
strsep(&context, "@");
|
|
|
|
if (ast_strlen_zero(context)) {
|
|
|
|
context = "default";
|
|
|
|
}
|
|
|
|
|
|
|
|
event = ast_event_new(AST_EVENT_MWI,
|
|
|
|
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
|
|
|
|
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
|
|
|
|
AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, mwi_state->new_msgs,
|
|
|
|
AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, mwi_state->old_msgs,
|
|
|
|
AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, &mwi_state->eid, sizeof(mwi_state->eid),
|
|
|
|
AST_EVENT_IE_END);
|
|
|
|
|
|
|
|
return event;
|
|
|
|
}
|
|
|
|
|
2013-05-24 20:44:07 +00:00
|
|
|
/*
|
|
|
|
* @{ \brief Define \ref stasis message types for MWI
|
|
|
|
*/
|
2014-05-22 12:01:37 +00:00
|
|
|
STASIS_MESSAGE_TYPE_DEFN(ast_mwi_state_type,
|
|
|
|
.to_event = mwi_to_event, );
|
2013-05-24 20:44:07 +00:00
|
|
|
STASIS_MESSAGE_TYPE_DEFN(ast_mwi_vm_app_type);
|
|
|
|
/* @} */
|
|
|
|
|
2013-03-16 15:45:58 +00:00
|
|
|
|
2013-05-15 02:37:22 +00:00
|
|
|
|
2011-01-19 20:33:30 +00:00
|
|
|
static void *shaun_of_the_dead(void *data)
|
|
|
|
{
|
|
|
|
struct zombie *cur;
|
|
|
|
int status;
|
|
|
|
for (;;) {
|
|
|
|
if (!AST_LIST_EMPTY(&zombies)) {
|
|
|
|
/* Don't allow cancellation while we have a lock. */
|
|
|
|
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
|
|
|
AST_LIST_LOCK(&zombies);
|
|
|
|
AST_LIST_TRAVERSE_SAFE_BEGIN(&zombies, cur, list) {
|
|
|
|
if (waitpid(cur->pid, &status, WNOHANG) != 0) {
|
|
|
|
AST_LIST_REMOVE_CURRENT(list);
|
|
|
|
ast_free(cur);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
AST_LIST_TRAVERSE_SAFE_END
|
|
|
|
AST_LIST_UNLOCK(&zombies);
|
|
|
|
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
|
|
|
}
|
|
|
|
pthread_testcancel();
|
|
|
|
/* Wait for 60 seconds, without engaging in a busy loop. */
|
|
|
|
ast_poll(NULL, 0, AST_LIST_FIRST(&zombies) ? 5000 : 60000);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2001-08-05 21:56:28 +00:00
|
|
|
|
2009-11-30 21:31:55 +00:00
|
|
|
#define AST_MAX_FORMATS 10
|
2004-09-17 15:05:29 +00:00
|
|
|
|
2007-06-13 18:23:12 +00:00
|
|
|
static AST_RWLIST_HEAD_STATIC(groups, ast_group_info);
|
2005-01-05 19:56:47 +00:00
|
|
|
|
2007-06-04 15:56:13 +00:00
|
|
|
/*!
|
2009-03-04 20:48:42 +00:00
|
|
|
* \brief This function presents a dialtone and reads an extension into 'collect'
|
|
|
|
* which must be a pointer to a **pre-initialized** array of char having a
|
|
|
|
* size of 'size' suitable for writing to. It will collect no more than the smaller
|
2007-06-04 15:56:13 +00:00
|
|
|
* of 'maxlen' or 'size' minus the original strlen() of collect digits.
|
|
|
|
* \param chan struct.
|
2009-03-04 20:48:42 +00:00
|
|
|
* \param context
|
|
|
|
* \param collect
|
|
|
|
* \param size
|
2007-06-04 15:56:13 +00:00
|
|
|
* \param maxlen
|
2012-01-21 00:23:13 +00:00
|
|
|
* \param timeout timeout in milliseconds
|
2007-06-04 15:56:13 +00:00
|
|
|
*
|
|
|
|
* \return 0 if extension does not exist, 1 if extension exists
|
2005-02-17 20:04:10 +00:00
|
|
|
*/
|
2009-03-04 20:48:42 +00:00
|
|
|
int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout)
|
2005-01-05 19:56:47 +00:00
|
|
|
{
|
2009-02-17 20:41:24 +00:00
|
|
|
struct ast_tone_zone_sound *ts;
|
2007-06-06 18:51:42 +00:00
|
|
|
int res = 0, x = 0;
|
2005-01-05 19:56:47 +00:00
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (maxlen > size) {
|
2005-02-17 20:04:10 +00:00
|
|
|
maxlen = size;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
|
2012-01-21 00:23:13 +00:00
|
|
|
if (!timeout) {
|
2012-02-20 23:43:27 +00:00
|
|
|
if (ast_channel_pbx(chan) && ast_channel_pbx(chan)->dtimeoutms) {
|
|
|
|
timeout = ast_channel_pbx(chan)->dtimeoutms;
|
2012-01-21 00:23:13 +00:00
|
|
|
} else {
|
|
|
|
timeout = 5000;
|
|
|
|
}
|
2009-02-17 20:41:24 +00:00
|
|
|
}
|
2007-06-12 14:16:37 +00:00
|
|
|
|
2012-02-20 23:43:27 +00:00
|
|
|
if ((ts = ast_get_indication_tone(ast_channel_zone(chan), "dial"))) {
|
2005-03-23 05:56:32 +00:00
|
|
|
res = ast_playtones_start(chan, 0, ts->data, 0);
|
2009-02-17 20:41:24 +00:00
|
|
|
ts = ast_tone_zone_sound_unref(ts);
|
|
|
|
} else {
|
2008-03-04 23:04:29 +00:00
|
|
|
ast_log(LOG_NOTICE, "Huh....? no dial for indications?\n");
|
2009-02-17 20:41:24 +00:00
|
|
|
}
|
2009-03-04 20:48:42 +00:00
|
|
|
|
2006-03-28 14:30:31 +00:00
|
|
|
for (x = strlen(collect); x < maxlen; ) {
|
2005-01-05 19:56:47 +00:00
|
|
|
res = ast_waitfordigit(chan, timeout);
|
2009-03-04 20:48:42 +00:00
|
|
|
if (!ast_ignore_pattern(context, collect)) {
|
2005-01-05 19:56:47 +00:00
|
|
|
ast_playtones_stop(chan);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
if (res < 1) {
|
2005-01-05 19:56:47 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
if (res == '#') {
|
2007-04-03 18:02:47 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-01-05 19:56:47 +00:00
|
|
|
collect[x++] = res;
|
2010-07-14 15:48:36 +00:00
|
|
|
if (!ast_matchmore_extension(chan, context, collect, 1,
|
2012-02-29 16:52:47 +00:00
|
|
|
S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
|
2005-01-05 19:56:47 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-01-05 19:56:47 +00:00
|
|
|
}
|
2007-06-06 17:08:00 +00:00
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (res >= 0) {
|
2010-07-14 15:48:36 +00:00
|
|
|
res = ast_exists_extension(chan, context, collect, 1,
|
2012-02-29 16:52:47 +00:00
|
|
|
S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)) ? 1 : 0;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2007-06-06 17:08:00 +00:00
|
|
|
|
2005-01-05 19:56:47 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2007-06-04 15:56:13 +00:00
|
|
|
/*!
|
|
|
|
* \brief ast_app_getdata
|
|
|
|
* \param c The channel to read from
|
|
|
|
* \param prompt The file to stream to the channel
|
|
|
|
* \param s The string to read in to. Must be at least the size of your length
|
|
|
|
* \param maxlen How many digits to read (maximum)
|
2012-03-22 19:51:16 +00:00
|
|
|
* \param timeout set timeout to 0 for "standard" timeouts. Set timeout to -1 for
|
2006-10-30 16:33:02 +00:00
|
|
|
* "ludicrous time" (essentially never times out) */
|
2009-03-03 23:21:18 +00:00
|
|
|
enum ast_getdata_result ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout)
|
2001-08-05 21:56:28 +00:00
|
|
|
{
|
2006-11-10 03:59:48 +00:00
|
|
|
int res = 0, to, fto;
|
|
|
|
char *front, *filename;
|
|
|
|
|
2003-02-23 06:00:11 +00:00
|
|
|
/* XXX Merge with full version? XXX */
|
2009-03-04 20:48:42 +00:00
|
|
|
|
2004-09-02 13:52:58 +00:00
|
|
|
if (maxlen)
|
|
|
|
s[0] = '\0';
|
2006-11-10 03:59:48 +00:00
|
|
|
|
2006-12-11 17:00:36 +00:00
|
|
|
if (!prompt)
|
2008-03-04 23:04:29 +00:00
|
|
|
prompt = "";
|
2006-11-10 03:59:48 +00:00
|
|
|
|
|
|
|
filename = ast_strdupa(prompt);
|
|
|
|
while ((front = strsep(&filename, "&"))) {
|
2006-12-11 17:00:36 +00:00
|
|
|
if (!ast_strlen_zero(front)) {
|
2012-01-24 20:12:09 +00:00
|
|
|
res = ast_streamfile(c, front, ast_channel_language(c));
|
2006-12-11 17:00:36 +00:00
|
|
|
if (res)
|
|
|
|
continue;
|
|
|
|
}
|
2006-11-10 03:59:48 +00:00
|
|
|
if (ast_strlen_zero(filename)) {
|
|
|
|
/* set timeouts for the last prompt */
|
2012-02-20 23:43:27 +00:00
|
|
|
fto = ast_channel_pbx(c) ? ast_channel_pbx(c)->rtimeoutms : 6000;
|
|
|
|
to = ast_channel_pbx(c) ? ast_channel_pbx(c)->dtimeoutms : 2000;
|
2006-11-10 03:59:48 +00:00
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (timeout > 0) {
|
2006-11-10 03:59:48 +00:00
|
|
|
fto = to = timeout;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
if (timeout < 0) {
|
2006-11-10 03:59:48 +00:00
|
|
|
fto = to = 1000000000;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2006-11-10 03:59:48 +00:00
|
|
|
} else {
|
|
|
|
/* there is more than one prompt, so
|
2009-03-04 20:48:42 +00:00
|
|
|
* get rid of the long timeout between
|
|
|
|
* prompts, and make it 50ms */
|
2006-11-10 03:59:48 +00:00
|
|
|
fto = 50;
|
2012-02-20 23:43:27 +00:00
|
|
|
to = ast_channel_pbx(c) ? ast_channel_pbx(c)->dtimeoutms : 2000;
|
2006-11-10 03:59:48 +00:00
|
|
|
}
|
|
|
|
res = ast_readstring(c, s, maxlen, to, fto, "#");
|
2009-03-03 23:21:18 +00:00
|
|
|
if (res == AST_GETDATA_EMPTY_END_TERMINATED) {
|
2001-08-05 21:56:28 +00:00
|
|
|
return res;
|
2009-03-03 23:21:18 +00:00
|
|
|
}
|
|
|
|
if (!ast_strlen_zero(s)) {
|
|
|
|
return res;
|
|
|
|
}
|
2001-08-05 21:56:28 +00:00
|
|
|
}
|
2009-03-03 23:21:18 +00:00
|
|
|
|
2001-08-05 21:56:28 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2007-08-28 16:28:26 +00:00
|
|
|
/* The lock type used by ast_lock_path() / ast_unlock_path() */
|
|
|
|
static enum AST_LOCK_TYPE ast_lock_type = AST_LOCK_TYPE_LOCKFILE;
|
2003-02-23 06:00:11 +00:00
|
|
|
|
2009-05-21 21:13:09 +00:00
|
|
|
int ast_app_getdata_full(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
|
2003-02-23 06:00:11 +00:00
|
|
|
{
|
2007-06-12 14:16:37 +00:00
|
|
|
int res, to = 2000, fto = 6000;
|
|
|
|
|
|
|
|
if (!ast_strlen_zero(prompt)) {
|
2012-01-24 20:12:09 +00:00
|
|
|
res = ast_streamfile(c, prompt, ast_channel_language(c));
|
2009-03-04 20:48:42 +00:00
|
|
|
if (res < 0) {
|
2003-02-23 06:00:11 +00:00
|
|
|
return res;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2003-02-23 06:00:11 +00:00
|
|
|
}
|
2009-03-04 20:48:42 +00:00
|
|
|
|
|
|
|
if (timeout > 0) {
|
2005-03-23 05:56:32 +00:00
|
|
|
fto = to = timeout;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
if (timeout < 0) {
|
2005-03-23 05:56:32 +00:00
|
|
|
fto = to = 1000000000;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2007-06-12 14:16:37 +00:00
|
|
|
|
2003-02-23 06:00:11 +00:00
|
|
|
res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
|
2007-06-12 14:16:37 +00:00
|
|
|
|
2003-02-23 06:00:11 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2012-04-20 23:29:56 +00:00
|
|
|
int ast_app_exec_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const char *macro_args)
|
2009-06-01 20:57:31 +00:00
|
|
|
{
|
2012-04-20 23:29:56 +00:00
|
|
|
struct ast_app *macro_app;
|
|
|
|
int res;
|
|
|
|
|
|
|
|
macro_app = pbx_findapp("Macro");
|
|
|
|
if (!macro_app) {
|
|
|
|
ast_log(LOG_WARNING,
|
|
|
|
"Cannot run 'Macro(%s)'. The application is not available.\n", macro_args);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (autoservice_chan) {
|
|
|
|
ast_autoservice_start(autoservice_chan);
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_debug(4, "%s Original location: %s,%s,%d\n", ast_channel_name(macro_chan),
|
|
|
|
ast_channel_context(macro_chan), ast_channel_exten(macro_chan),
|
|
|
|
ast_channel_priority(macro_chan));
|
|
|
|
|
|
|
|
res = pbx_exec(macro_chan, macro_app, macro_args);
|
|
|
|
ast_debug(4, "Macro exited with status %d\n", res);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Assume anything negative from Macro is an error.
|
|
|
|
* Anything else is success.
|
|
|
|
*/
|
|
|
|
if (res < 0) {
|
|
|
|
res = -1;
|
|
|
|
} else {
|
|
|
|
res = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_debug(4, "%s Ending location: %s,%s,%d\n", ast_channel_name(macro_chan),
|
|
|
|
ast_channel_context(macro_chan), ast_channel_exten(macro_chan),
|
|
|
|
ast_channel_priority(macro_chan));
|
|
|
|
|
|
|
|
if (autoservice_chan) {
|
|
|
|
ast_autoservice_stop(autoservice_chan);
|
|
|
|
}
|
2016-01-12 17:14:29 +00:00
|
|
|
|
|
|
|
if (ast_check_hangup_locked(macro_chan)) {
|
|
|
|
ast_queue_hangup(macro_chan);
|
|
|
|
}
|
|
|
|
|
2012-04-20 23:29:56 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ast_app_run_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const char *macro_name, const char *macro_args)
|
|
|
|
{
|
|
|
|
int res;
|
|
|
|
char *args_str;
|
|
|
|
size_t args_len;
|
|
|
|
|
|
|
|
if (ast_strlen_zero(macro_args)) {
|
|
|
|
return ast_app_exec_macro(autoservice_chan, macro_chan, macro_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create the Macro application argument string. */
|
|
|
|
args_len = strlen(macro_name) + strlen(macro_args) + 2;
|
|
|
|
args_str = ast_malloc(args_len);
|
|
|
|
if (!args_str) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
snprintf(args_str, args_len, "%s,%s", macro_name, macro_args);
|
|
|
|
|
|
|
|
res = ast_app_exec_macro(autoservice_chan, macro_chan, args_str);
|
|
|
|
ast_free(args_str);
|
|
|
|
return res;
|
|
|
|
}
|
2012-02-27 16:50:19 +00:00
|
|
|
|
2017-12-30 00:24:02 +00:00
|
|
|
/* BUGBUG this is not thread safe. */
|
2012-06-14 23:22:53 +00:00
|
|
|
static const struct ast_app_stack_funcs *app_stack_callbacks;
|
|
|
|
|
|
|
|
void ast_install_stack_functions(const struct ast_app_stack_funcs *funcs)
|
2012-04-20 23:29:56 +00:00
|
|
|
{
|
2012-06-14 23:22:53 +00:00
|
|
|
app_stack_callbacks = funcs;
|
|
|
|
}
|
2009-06-01 20:57:31 +00:00
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
const char *ast_app_expand_sub_args(struct ast_channel *chan, const char *args)
|
|
|
|
{
|
|
|
|
const struct ast_app_stack_funcs *funcs;
|
|
|
|
const char *new_args;
|
|
|
|
|
|
|
|
funcs = app_stack_callbacks;
|
2017-12-30 00:24:02 +00:00
|
|
|
if (!funcs || !funcs->expand_sub_args || !ast_module_running_ref(funcs->module)) {
|
2012-04-20 23:29:56 +00:00
|
|
|
ast_log(LOG_WARNING,
|
2012-06-14 23:22:53 +00:00
|
|
|
"Cannot expand 'Gosub(%s)' arguments. The app_stack module is not available.\n",
|
|
|
|
args);
|
|
|
|
return NULL;
|
2009-06-01 20:57:31 +00:00
|
|
|
}
|
2012-04-20 23:29:56 +00:00
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
new_args = funcs->expand_sub_args(chan, args);
|
|
|
|
ast_module_unref(funcs->module);
|
2017-12-30 00:24:02 +00:00
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
return new_args;
|
|
|
|
}
|
2012-04-20 23:29:56 +00:00
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_args, int ignore_hangup)
|
|
|
|
{
|
|
|
|
const struct ast_app_stack_funcs *funcs;
|
|
|
|
int res;
|
2012-04-20 23:29:56 +00:00
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
funcs = app_stack_callbacks;
|
2017-12-30 00:24:02 +00:00
|
|
|
if (!funcs || !funcs->run_sub || !ast_module_running_ref(funcs->module)) {
|
2012-06-14 23:22:53 +00:00
|
|
|
ast_log(LOG_WARNING,
|
|
|
|
"Cannot run 'Gosub(%s)'. The app_stack module is not available.\n",
|
|
|
|
sub_args);
|
|
|
|
return -1;
|
2012-02-27 16:50:19 +00:00
|
|
|
}
|
2012-04-20 23:29:56 +00:00
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
if (autoservice_chan) {
|
|
|
|
ast_autoservice_start(autoservice_chan);
|
|
|
|
}
|
2012-04-20 23:29:56 +00:00
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
res = funcs->run_sub(sub_chan, sub_args, ignore_hangup);
|
|
|
|
ast_module_unref(funcs->module);
|
2012-04-20 23:29:56 +00:00
|
|
|
|
2009-06-01 20:57:31 +00:00
|
|
|
if (autoservice_chan) {
|
|
|
|
ast_autoservice_stop(autoservice_chan);
|
|
|
|
}
|
2016-01-12 17:14:29 +00:00
|
|
|
|
|
|
|
if (!ignore_hangup && ast_check_hangup_locked(sub_chan)) {
|
|
|
|
ast_queue_hangup(sub_chan);
|
|
|
|
}
|
|
|
|
|
2009-06-01 20:57:31 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
int ast_app_run_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_location, const char *sub_args, int ignore_hangup)
|
2012-02-27 16:50:19 +00:00
|
|
|
{
|
2012-04-20 23:29:56 +00:00
|
|
|
int res;
|
|
|
|
char *args_str;
|
|
|
|
size_t args_len;
|
2012-02-27 16:50:19 +00:00
|
|
|
|
2012-04-20 23:29:56 +00:00
|
|
|
if (ast_strlen_zero(sub_args)) {
|
2012-06-14 23:22:53 +00:00
|
|
|
return ast_app_exec_sub(autoservice_chan, sub_chan, sub_location, ignore_hangup);
|
2012-02-27 16:50:19 +00:00
|
|
|
}
|
2012-04-20 23:29:56 +00:00
|
|
|
|
|
|
|
/* Create the Gosub application argument string. */
|
|
|
|
args_len = strlen(sub_location) + strlen(sub_args) + 3;
|
|
|
|
args_str = ast_malloc(args_len);
|
|
|
|
if (!args_str) {
|
|
|
|
return -1;
|
2012-02-27 16:50:19 +00:00
|
|
|
}
|
2012-04-20 23:29:56 +00:00
|
|
|
snprintf(args_str, args_len, "%s(%s)", sub_location, sub_args);
|
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
res = ast_app_exec_sub(autoservice_chan, sub_chan, args_str, ignore_hangup);
|
2012-04-20 23:29:56 +00:00
|
|
|
ast_free(args_str);
|
|
|
|
return res;
|
2012-02-27 16:50:19 +00:00
|
|
|
}
|
|
|
|
|
2013-12-11 19:19:24 +00:00
|
|
|
/*! \brief The container for the voicemail provider */
|
|
|
|
static AO2_GLOBAL_OBJ_STATIC(vm_provider);
|
|
|
|
|
|
|
|
/*! Voicemail not registered warning */
|
|
|
|
static int vm_warnings;
|
|
|
|
|
2013-12-13 00:40:49 +00:00
|
|
|
int ast_vm_is_registered(void)
|
|
|
|
{
|
|
|
|
struct ast_vm_functions *table;
|
|
|
|
int is_registered;
|
|
|
|
|
|
|
|
table = ao2_global_obj_ref(vm_provider);
|
|
|
|
is_registered = table ? 1 : 0;
|
|
|
|
ao2_cleanup(table);
|
|
|
|
return is_registered;
|
|
|
|
}
|
|
|
|
|
2013-12-11 19:19:24 +00:00
|
|
|
int __ast_vm_register(const struct ast_vm_functions *vm_table, struct ast_module *module)
|
2004-12-31 01:11:33 +00:00
|
|
|
{
|
2013-12-11 19:19:24 +00:00
|
|
|
RAII_VAR(struct ast_vm_functions *, table, NULL, ao2_cleanup);
|
|
|
|
|
|
|
|
if (!vm_table->module_name) {
|
|
|
|
ast_log(LOG_ERROR, "Voicemail provider missing required information.\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (vm_table->module_version != VM_MODULE_VERSION) {
|
|
|
|
ast_log(LOG_ERROR, "Voicemail provider '%s' has incorrect version\n",
|
|
|
|
vm_table->module_name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
table = ao2_global_obj_ref(vm_provider);
|
|
|
|
if (table) {
|
|
|
|
ast_log(LOG_WARNING, "Voicemail provider already registered by %s.\n",
|
|
|
|
table->module_name);
|
2015-12-30 16:49:03 +00:00
|
|
|
return AST_MODULE_LOAD_DECLINE;
|
2013-12-11 19:19:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
table = ao2_alloc_options(sizeof(*table), NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
|
|
|
|
if (!table) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
*table = *vm_table;
|
|
|
|
table->module = module;
|
|
|
|
|
|
|
|
ao2_global_obj_replace_unref(vm_provider, table);
|
|
|
|
return 0;
|
2004-12-31 01:11:33 +00:00
|
|
|
}
|
|
|
|
|
2013-12-11 19:19:24 +00:00
|
|
|
void ast_vm_unregister(const char *module_name)
|
2004-12-31 01:11:33 +00:00
|
|
|
{
|
2013-12-11 19:19:24 +00:00
|
|
|
struct ast_vm_functions *table;
|
|
|
|
|
|
|
|
table = ao2_global_obj_ref(vm_provider);
|
|
|
|
if (table && !strcmp(table->module_name, module_name)) {
|
|
|
|
ao2_global_obj_release(vm_provider);
|
|
|
|
}
|
|
|
|
ao2_cleanup(table);
|
2004-12-31 01:11:33 +00:00
|
|
|
}
|
|
|
|
|
2015-03-06 21:38:36 +00:00
|
|
|
#ifdef TEST_FRAMEWORK
|
|
|
|
/*! \brief Holding container for the voicemail provider used while testing */
|
|
|
|
static AO2_GLOBAL_OBJ_STATIC(vm_provider_holder);
|
|
|
|
static int provider_is_swapped = 0;
|
|
|
|
|
|
|
|
void ast_vm_test_swap_table_in(const struct ast_vm_functions *vm_table)
|
|
|
|
{
|
|
|
|
RAII_VAR(struct ast_vm_functions *, holding_table, NULL, ao2_cleanup);
|
|
|
|
RAII_VAR(struct ast_vm_functions *, new_table, NULL, ao2_cleanup);
|
|
|
|
|
|
|
|
if (provider_is_swapped) {
|
|
|
|
ast_log(LOG_ERROR, "Attempted to swap in test function table without swapping out old test table.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
holding_table = ao2_global_obj_ref(vm_provider);
|
|
|
|
|
|
|
|
if (holding_table) {
|
|
|
|
ao2_global_obj_replace_unref(vm_provider_holder, holding_table);
|
|
|
|
}
|
|
|
|
|
|
|
|
new_table = ao2_alloc_options(sizeof(*new_table), NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
|
|
|
|
if (!new_table) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
*new_table = *vm_table;
|
|
|
|
|
|
|
|
ao2_global_obj_replace_unref(vm_provider, new_table);
|
|
|
|
provider_is_swapped = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ast_vm_test_swap_table_out(void)
|
|
|
|
{
|
|
|
|
RAII_VAR(struct ast_vm_functions *, held_table, NULL, ao2_cleanup);
|
|
|
|
|
|
|
|
if (!provider_is_swapped) {
|
|
|
|
ast_log(LOG_ERROR, "Attempted to swap out test function table, but none is currently installed.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
held_table = ao2_global_obj_ref(vm_provider_holder);
|
|
|
|
if (!held_table) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ao2_global_obj_replace_unref(vm_provider, held_table);
|
|
|
|
ao2_global_obj_release(vm_provider_holder);
|
|
|
|
provider_is_swapped = 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-06-20 17:06:42 +00:00
|
|
|
/*! \brief The container for the voicemail greeter provider */
|
|
|
|
static AO2_GLOBAL_OBJ_STATIC(vm_greeter_provider);
|
|
|
|
|
|
|
|
/*! Voicemail greeter not registered warning */
|
|
|
|
static int vm_greeter_warnings;
|
|
|
|
|
|
|
|
int ast_vm_greeter_is_registered(void)
|
|
|
|
{
|
|
|
|
struct ast_vm_greeter_functions *table;
|
|
|
|
int is_registered;
|
|
|
|
|
|
|
|
table = ao2_global_obj_ref(vm_greeter_provider);
|
|
|
|
is_registered = table ? 1 : 0;
|
|
|
|
ao2_cleanup(table);
|
|
|
|
return is_registered;
|
|
|
|
}
|
|
|
|
|
|
|
|
int __ast_vm_greeter_register(const struct ast_vm_greeter_functions *vm_table, struct ast_module *module)
|
|
|
|
{
|
|
|
|
RAII_VAR(struct ast_vm_greeter_functions *, table, NULL, ao2_cleanup);
|
|
|
|
|
|
|
|
if (!vm_table->module_name) {
|
|
|
|
ast_log(LOG_ERROR, "Voicemail greeter provider missing required information.\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (vm_table->module_version != VM_GREETER_MODULE_VERSION) {
|
|
|
|
ast_log(LOG_ERROR, "Voicemail greeter provider '%s' has incorrect version\n",
|
|
|
|
vm_table->module_name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
table = ao2_global_obj_ref(vm_greeter_provider);
|
|
|
|
if (table) {
|
|
|
|
ast_log(LOG_WARNING, "Voicemail greeter provider already registered by %s.\n",
|
|
|
|
table->module_name);
|
2015-12-30 16:49:03 +00:00
|
|
|
return AST_MODULE_LOAD_DECLINE;
|
2014-06-20 17:06:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
table = ao2_alloc_options(sizeof(*table), NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
|
|
|
|
if (!table) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
*table = *vm_table;
|
|
|
|
table->module = module;
|
|
|
|
|
|
|
|
ao2_global_obj_replace_unref(vm_greeter_provider, table);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ast_vm_greeter_unregister(const char *module_name)
|
|
|
|
{
|
|
|
|
struct ast_vm_greeter_functions *table;
|
|
|
|
|
|
|
|
table = ao2_global_obj_ref(vm_greeter_provider);
|
|
|
|
if (table && !strcmp(table->module_name, module_name)) {
|
|
|
|
ao2_global_obj_release(vm_greeter_provider);
|
|
|
|
}
|
|
|
|
ao2_cleanup(table);
|
|
|
|
}
|
|
|
|
|
2012-06-14 19:40:11 +00:00
|
|
|
#ifdef TEST_FRAMEWORK
|
2013-11-01 23:20:54 +00:00
|
|
|
static ast_vm_test_create_user_fn *ast_vm_test_create_user_func = NULL;
|
|
|
|
static ast_vm_test_destroy_user_fn *ast_vm_test_destroy_user_func = NULL;
|
2012-06-14 19:40:11 +00:00
|
|
|
|
2013-11-01 23:20:54 +00:00
|
|
|
void ast_install_vm_test_functions(ast_vm_test_create_user_fn *vm_test_create_user_func,
|
|
|
|
ast_vm_test_destroy_user_fn *vm_test_destroy_user_func)
|
2012-06-14 19:40:11 +00:00
|
|
|
{
|
|
|
|
ast_vm_test_create_user_func = vm_test_create_user_func;
|
|
|
|
ast_vm_test_destroy_user_func = vm_test_destroy_user_func;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ast_uninstall_vm_test_functions(void)
|
|
|
|
{
|
|
|
|
ast_vm_test_create_user_func = NULL;
|
|
|
|
ast_vm_test_destroy_user_func = NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-12-11 19:19:24 +00:00
|
|
|
static void vm_warn_no_provider(void)
|
2003-01-30 15:03:20 +00:00
|
|
|
{
|
2013-12-11 19:19:24 +00:00
|
|
|
if (vm_warnings++ % 10 == 0) {
|
|
|
|
ast_verb(3, "No voicemail provider registered.\n");
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2013-12-11 19:19:24 +00:00
|
|
|
}
|
2004-12-31 01:11:33 +00:00
|
|
|
|
2013-12-11 19:19:24 +00:00
|
|
|
#define VM_API_CALL(res, api_call, api_parms) \
|
|
|
|
do { \
|
2014-06-20 17:06:42 +00:00
|
|
|
struct ast_vm_functions *table; \
|
|
|
|
table = ao2_global_obj_ref(vm_provider); \
|
2013-12-11 19:19:24 +00:00
|
|
|
if (!table) { \
|
|
|
|
vm_warn_no_provider(); \
|
|
|
|
} else if (table->api_call) { \
|
|
|
|
ast_module_ref(table->module); \
|
|
|
|
(res) = table->api_call api_parms; \
|
|
|
|
ast_module_unref(table->module); \
|
|
|
|
} \
|
|
|
|
ao2_cleanup(table); \
|
|
|
|
} while (0)
|
|
|
|
|
2014-06-20 17:06:42 +00:00
|
|
|
static void vm_greeter_warn_no_provider(void)
|
|
|
|
{
|
|
|
|
if (vm_greeter_warnings++ % 10 == 0) {
|
|
|
|
ast_verb(3, "No voicemail greeter provider registered.\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define VM_GREETER_API_CALL(res, api_call, api_parms) \
|
|
|
|
do { \
|
|
|
|
struct ast_vm_greeter_functions *table; \
|
|
|
|
table = ao2_global_obj_ref(vm_greeter_provider); \
|
|
|
|
if (!table) { \
|
|
|
|
vm_greeter_warn_no_provider(); \
|
|
|
|
} else if (table->api_call) { \
|
|
|
|
ast_module_ref(table->module); \
|
|
|
|
(res) = table->api_call api_parms; \
|
|
|
|
ast_module_unref(table->module); \
|
|
|
|
} \
|
|
|
|
ao2_cleanup(table); \
|
|
|
|
} while (0)
|
|
|
|
|
2013-12-11 19:19:24 +00:00
|
|
|
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
|
|
|
|
{
|
|
|
|
int res = 0;
|
|
|
|
|
|
|
|
VM_API_CALL(res, has_voicemail, (mailboxes, folder));
|
|
|
|
return res;
|
2003-01-30 15:03:20 +00:00
|
|
|
}
|
2003-03-26 00:15:11 +00:00
|
|
|
|
2012-06-04 20:26:12 +00:00
|
|
|
/*!
|
|
|
|
* \internal
|
|
|
|
* \brief Function used as a callback for ast_copy_recording_to_vm when a real one isn't installed.
|
|
|
|
* \param vm_rec_data Stores crucial information about the voicemail that will basically just be used
|
|
|
|
* to figure out what the name of the recipient was supposed to be
|
|
|
|
*/
|
|
|
|
int ast_app_copy_recording_to_vm(struct ast_vm_recording_data *vm_rec_data)
|
|
|
|
{
|
2013-12-11 19:19:24 +00:00
|
|
|
int res = -1;
|
2012-06-04 20:26:12 +00:00
|
|
|
|
2013-12-11 19:19:24 +00:00
|
|
|
VM_API_CALL(res, copy_recording_to_vm, (vm_rec_data));
|
|
|
|
return res;
|
2012-06-04 20:26:12 +00:00
|
|
|
}
|
2004-12-31 01:11:33 +00:00
|
|
|
|
2013-12-11 19:19:24 +00:00
|
|
|
int ast_app_inboxcount(const char *mailboxes, int *newmsgs, int *oldmsgs)
|
2003-03-26 00:15:11 +00:00
|
|
|
{
|
2013-12-11 19:19:24 +00:00
|
|
|
int res = 0;
|
|
|
|
|
2008-07-02 21:27:53 +00:00
|
|
|
if (newmsgs) {
|
2003-03-26 00:15:11 +00:00
|
|
|
*newmsgs = 0;
|
2008-07-02 21:27:53 +00:00
|
|
|
}
|
|
|
|
if (oldmsgs) {
|
|
|
|
*oldmsgs = 0;
|
|
|
|
}
|
|
|
|
|
2013-12-11 19:19:24 +00:00
|
|
|
VM_API_CALL(res, inboxcount, (mailboxes, newmsgs, oldmsgs));
|
|
|
|
return res;
|
2008-07-02 21:27:53 +00:00
|
|
|
}
|
|
|
|
|
2013-12-11 19:19:24 +00:00
|
|
|
int ast_app_inboxcount2(const char *mailboxes, int *urgentmsgs, int *newmsgs, int *oldmsgs)
|
2008-07-02 21:27:53 +00:00
|
|
|
{
|
2013-12-11 19:19:24 +00:00
|
|
|
int res = 0;
|
|
|
|
|
2008-07-02 21:27:53 +00:00
|
|
|
if (newmsgs) {
|
|
|
|
*newmsgs = 0;
|
|
|
|
}
|
|
|
|
if (oldmsgs) {
|
2003-03-26 00:15:11 +00:00
|
|
|
*oldmsgs = 0;
|
2008-07-02 21:27:53 +00:00
|
|
|
}
|
|
|
|
if (urgentmsgs) {
|
2008-05-09 21:22:42 +00:00
|
|
|
*urgentmsgs = 0;
|
2008-07-02 21:27:53 +00:00
|
|
|
}
|
2004-12-31 01:11:33 +00:00
|
|
|
|
2013-12-11 19:19:24 +00:00
|
|
|
VM_API_CALL(res, inboxcount2, (mailboxes, urgentmsgs, newmsgs, oldmsgs));
|
|
|
|
return res;
|
2003-03-26 00:15:11 +00:00
|
|
|
}
|
2004-05-07 20:39:14 +00:00
|
|
|
|
2014-06-20 17:06:42 +00:00
|
|
|
int ast_app_sayname(struct ast_channel *chan, const char *mailbox_id)
|
2008-04-28 22:38:07 +00:00
|
|
|
{
|
2013-12-11 19:19:24 +00:00
|
|
|
int res = -1;
|
|
|
|
|
2014-06-20 17:06:42 +00:00
|
|
|
VM_GREETER_API_CALL(res, sayname, (chan, mailbox_id));
|
2013-12-11 19:19:24 +00:00
|
|
|
return res;
|
2008-04-28 22:38:07 +00:00
|
|
|
}
|
|
|
|
|
2013-12-19 16:52:43 +00:00
|
|
|
int ast_app_messagecount(const char *mailbox_id, const char *folder)
|
2006-05-19 15:44:33 +00:00
|
|
|
{
|
2013-12-11 19:19:24 +00:00
|
|
|
int res = 0;
|
2006-05-19 15:44:33 +00:00
|
|
|
|
2013-12-19 16:52:43 +00:00
|
|
|
VM_API_CALL(res, messagecount, (mailbox_id, folder));
|
2013-12-11 19:19:24 +00:00
|
|
|
return res;
|
2006-05-19 15:44:33 +00:00
|
|
|
}
|
|
|
|
|
2012-06-14 19:40:11 +00:00
|
|
|
const char *ast_vm_index_to_foldername(int id)
|
|
|
|
{
|
2013-12-11 19:19:24 +00:00
|
|
|
const char *res = NULL;
|
|
|
|
|
|
|
|
VM_API_CALL(res, index_to_foldername, (id));
|
|
|
|
return res;
|
2012-06-14 19:40:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct ast_vm_mailbox_snapshot *ast_vm_mailbox_snapshot_create(const char *mailbox,
|
|
|
|
const char *context,
|
|
|
|
const char *folder,
|
|
|
|
int descending,
|
|
|
|
enum ast_vm_snapshot_sort_val sort_val,
|
|
|
|
int combine_INBOX_and_OLD)
|
|
|
|
{
|
2013-12-11 19:19:24 +00:00
|
|
|
struct ast_vm_mailbox_snapshot *res = NULL;
|
|
|
|
|
|
|
|
VM_API_CALL(res, mailbox_snapshot_create, (mailbox, context, folder, descending,
|
|
|
|
sort_val, combine_INBOX_and_OLD));
|
|
|
|
return res;
|
2012-06-14 19:40:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct ast_vm_mailbox_snapshot *ast_vm_mailbox_snapshot_destroy(struct ast_vm_mailbox_snapshot *mailbox_snapshot)
|
|
|
|
{
|
2013-12-11 19:19:24 +00:00
|
|
|
struct ast_vm_mailbox_snapshot *res = NULL;
|
|
|
|
|
|
|
|
VM_API_CALL(res, mailbox_snapshot_destroy, (mailbox_snapshot));
|
|
|
|
return res;
|
2012-06-14 19:40:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int ast_vm_msg_move(const char *mailbox,
|
|
|
|
const char *context,
|
|
|
|
size_t num_msgs,
|
|
|
|
const char *oldfolder,
|
|
|
|
const char *old_msg_ids[],
|
|
|
|
const char *newfolder)
|
|
|
|
{
|
2013-12-11 19:19:24 +00:00
|
|
|
int res = 0;
|
|
|
|
|
|
|
|
VM_API_CALL(res, msg_move, (mailbox, context, num_msgs, oldfolder, old_msg_ids,
|
|
|
|
newfolder));
|
|
|
|
return res;
|
2012-06-14 19:40:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int ast_vm_msg_remove(const char *mailbox,
|
|
|
|
const char *context,
|
|
|
|
size_t num_msgs,
|
|
|
|
const char *folder,
|
|
|
|
const char *msgs[])
|
|
|
|
{
|
2013-12-11 19:19:24 +00:00
|
|
|
int res = 0;
|
|
|
|
|
|
|
|
VM_API_CALL(res, msg_remove, (mailbox, context, num_msgs, folder, msgs));
|
|
|
|
return res;
|
2012-06-14 19:40:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int ast_vm_msg_forward(const char *from_mailbox,
|
|
|
|
const char *from_context,
|
|
|
|
const char *from_folder,
|
|
|
|
const char *to_mailbox,
|
|
|
|
const char *to_context,
|
|
|
|
const char *to_folder,
|
|
|
|
size_t num_msgs,
|
|
|
|
const char *msg_ids[],
|
|
|
|
int delete_old)
|
|
|
|
{
|
2013-12-11 19:19:24 +00:00
|
|
|
int res = 0;
|
|
|
|
|
|
|
|
VM_API_CALL(res, msg_forward, (from_mailbox, from_context, from_folder, to_mailbox,
|
|
|
|
to_context, to_folder, num_msgs, msg_ids, delete_old));
|
|
|
|
return res;
|
2012-06-14 19:40:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int ast_vm_msg_play(struct ast_channel *chan,
|
|
|
|
const char *mailbox,
|
|
|
|
const char *context,
|
|
|
|
const char *folder,
|
|
|
|
const char *msg_num,
|
2013-11-01 23:20:54 +00:00
|
|
|
ast_vm_msg_play_cb *cb)
|
2012-06-14 19:40:11 +00:00
|
|
|
{
|
2013-12-11 19:19:24 +00:00
|
|
|
int res = 0;
|
|
|
|
|
|
|
|
VM_API_CALL(res, msg_play, (chan, mailbox, context, folder, msg_num, cb));
|
|
|
|
return res;
|
2012-06-14 19:40:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef TEST_FRAMEWORK
|
|
|
|
int ast_vm_test_create_user(const char *context, const char *mailbox)
|
|
|
|
{
|
|
|
|
if (ast_vm_test_create_user_func) {
|
|
|
|
return ast_vm_test_create_user_func(context, mailbox);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ast_vm_test_destroy_user(const char *context, const char *mailbox)
|
|
|
|
{
|
|
|
|
if (ast_vm_test_destroy_user_func) {
|
|
|
|
return ast_vm_test_destroy_user_func(context, mailbox);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-06-13 21:41:43 +00:00
|
|
|
static int external_sleep(struct ast_channel *chan, int ms)
|
|
|
|
{
|
|
|
|
usleep(ms * 1000);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dtmf_stream(struct ast_channel *chan, const char *digits, int between, unsigned int duration, int is_external)
|
2004-05-07 21:14:55 +00:00
|
|
|
{
|
2006-01-11 05:23:19 +00:00
|
|
|
const char *ptr;
|
2012-09-27 22:33:15 +00:00
|
|
|
int res;
|
2008-03-25 14:39:45 +00:00
|
|
|
struct ast_silence_generator *silgen = NULL;
|
2018-06-13 21:41:43 +00:00
|
|
|
int (*my_sleep)(struct ast_channel *chan, int ms);
|
|
|
|
int (*my_senddigit)(struct ast_channel *chan, char digit, unsigned int duration);
|
2006-01-11 05:23:19 +00:00
|
|
|
|
2018-06-13 21:41:43 +00:00
|
|
|
if (is_external) {
|
|
|
|
my_sleep = external_sleep;
|
|
|
|
my_senddigit = ast_senddigit_external;
|
|
|
|
} else {
|
|
|
|
my_sleep = ast_safe_sleep;
|
|
|
|
my_senddigit = ast_senddigit;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-05-07 20:39:14 +00:00
|
|
|
|
2018-06-13 21:41:43 +00:00
|
|
|
if (!between) {
|
|
|
|
between = 100;
|
2008-07-30 18:33:12 +00:00
|
|
|
}
|
2006-01-11 05:23:19 +00:00
|
|
|
|
2012-09-27 22:33:15 +00:00
|
|
|
/* Need a quiet time before sending digits. */
|
2008-03-25 14:39:45 +00:00
|
|
|
if (ast_opt_transmit_silence) {
|
|
|
|
silgen = ast_channel_start_silence_generator(chan);
|
|
|
|
}
|
2018-06-13 21:41:43 +00:00
|
|
|
res = my_sleep(chan, 100);
|
2012-09-27 22:33:15 +00:00
|
|
|
if (res) {
|
|
|
|
goto dtmf_stream_cleanup;
|
|
|
|
}
|
2008-03-25 14:39:45 +00:00
|
|
|
|
2006-01-11 05:23:19 +00:00
|
|
|
for (ptr = digits; *ptr; ptr++) {
|
|
|
|
if (*ptr == 'w') {
|
|
|
|
/* 'w' -- wait half a second */
|
2018-06-13 21:41:43 +00:00
|
|
|
res = my_sleep(chan, 500);
|
|
|
|
if (res) {
|
2006-01-11 05:23:19 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2012-09-28 18:27:02 +00:00
|
|
|
} else if (*ptr == 'W') {
|
|
|
|
/* 'W' -- wait a second */
|
2018-06-13 21:41:43 +00:00
|
|
|
res = my_sleep(chan, 1000);
|
|
|
|
if (res) {
|
2012-09-28 18:27:02 +00:00
|
|
|
break;
|
|
|
|
}
|
2006-01-11 05:23:19 +00:00
|
|
|
} else if (strchr("0123456789*#abcdfABCDF", *ptr)) {
|
|
|
|
if (*ptr == 'f' || *ptr == 'F') {
|
|
|
|
/* ignore return values if not supported by channel */
|
|
|
|
ast_indicate(chan, AST_CONTROL_FLASH);
|
2009-03-04 20:48:42 +00:00
|
|
|
} else {
|
2012-09-27 22:33:15 +00:00
|
|
|
/* Character represents valid DTMF */
|
2018-06-13 21:41:43 +00:00
|
|
|
my_senddigit(chan, *ptr, duration);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2006-01-11 05:23:19 +00:00
|
|
|
/* pause between digits */
|
2018-06-13 21:41:43 +00:00
|
|
|
res = my_sleep(chan, between);
|
|
|
|
if (res) {
|
2006-01-11 05:23:19 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
} else {
|
2008-03-04 23:04:29 +00:00
|
|
|
ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n", *ptr);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-05-07 21:14:55 +00:00
|
|
|
}
|
2006-01-11 05:23:19 +00:00
|
|
|
|
2012-09-27 22:33:15 +00:00
|
|
|
dtmf_stream_cleanup:
|
2008-03-25 14:39:45 +00:00
|
|
|
if (silgen) {
|
|
|
|
ast_channel_stop_silence_generator(chan, silgen);
|
|
|
|
}
|
2018-06-13 21:41:43 +00:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration)
|
|
|
|
{
|
|
|
|
int res;
|
|
|
|
|
|
|
|
if (peer && ast_autoservice_start(peer)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
res = dtmf_stream(chan, digits, between, duration, 0);
|
2012-09-27 22:33:15 +00:00
|
|
|
if (peer && ast_autoservice_stop(peer)) {
|
|
|
|
res = -1;
|
|
|
|
}
|
2008-03-25 14:39:45 +00:00
|
|
|
|
2004-05-07 21:14:55 +00:00
|
|
|
return res;
|
2004-05-07 20:39:14 +00:00
|
|
|
}
|
2004-05-13 19:01:10 +00:00
|
|
|
|
2018-06-13 21:41:43 +00:00
|
|
|
void ast_dtmf_stream_external(struct ast_channel *chan, const char *digits, int between, unsigned int duration)
|
|
|
|
{
|
|
|
|
dtmf_stream(chan, digits, between, duration, 1);
|
|
|
|
}
|
|
|
|
|
2004-05-13 19:01:10 +00:00
|
|
|
struct linear_state {
|
|
|
|
int fd;
|
|
|
|
int autoclose;
|
|
|
|
int allowoverride;
|
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
|
|
|
struct ast_format *origwfmt;
|
2004-05-13 19:01:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static void linear_release(struct ast_channel *chan, void *params)
|
|
|
|
{
|
|
|
|
struct linear_state *ls = params;
|
2009-03-04 20:48:42 +00:00
|
|
|
|
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
|
|
|
if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) {
|
|
|
|
ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%s'\n",
|
|
|
|
ast_channel_name(chan), ast_format_get_name(ls->origwfmt));
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
|
|
|
ao2_cleanup(ls->origwfmt);
|
2007-06-12 14:16:37 +00:00
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (ls->autoclose) {
|
2004-05-13 19:01:10 +00:00
|
|
|
close(ls->fd);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2007-06-12 14:16:37 +00:00
|
|
|
|
2007-06-06 21:20:11 +00:00
|
|
|
ast_free(params);
|
2004-05-13 19:01:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int linear_generator(struct ast_channel *chan, void *data, int len, int samples)
|
|
|
|
{
|
|
|
|
short buf[2048 + AST_FRIENDLY_OFFSET / 2];
|
|
|
|
struct linear_state *ls = data;
|
2007-06-12 14:16:37 +00:00
|
|
|
struct ast_frame f = {
|
2008-03-04 23:04:29 +00:00
|
|
|
.frametype = AST_FRAME_VOICE,
|
2008-05-22 16:29:54 +00:00
|
|
|
.data.ptr = buf + AST_FRIENDLY_OFFSET / 2,
|
2007-06-12 14:16:37 +00:00
|
|
|
.offset = AST_FRIENDLY_OFFSET,
|
2008-03-04 23:04:29 +00:00
|
|
|
};
|
2004-05-13 19:01:10 +00:00
|
|
|
int res;
|
2007-06-12 14:16:37 +00:00
|
|
|
|
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
|
|
|
f.subclass.format = ast_format_slin;
|
2011-02-03 16:22:10 +00:00
|
|
|
|
2004-05-13 19:01:10 +00:00
|
|
|
len = samples * 2;
|
|
|
|
if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
|
2008-03-04 23:04:29 +00:00
|
|
|
ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" , len);
|
2004-05-13 19:01:10 +00:00
|
|
|
len = sizeof(buf) - AST_FRIENDLY_OFFSET;
|
|
|
|
}
|
|
|
|
res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len);
|
|
|
|
if (res > 0) {
|
|
|
|
f.datalen = res;
|
|
|
|
f.samples = res / 2;
|
|
|
|
ast_write(chan, &f);
|
2009-03-04 20:48:42 +00:00
|
|
|
if (res == len) {
|
2004-05-13 19:01:10 +00:00
|
|
|
return 0;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-05-13 19:01:10 +00:00
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *linear_alloc(struct ast_channel *chan, void *params)
|
|
|
|
{
|
2007-06-12 14:16:37 +00:00
|
|
|
struct linear_state *ls = params;
|
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (!params) {
|
2007-06-12 14:16:37 +00:00
|
|
|
return NULL;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2007-06-12 14:16:37 +00:00
|
|
|
|
2004-05-13 19:01:10 +00:00
|
|
|
/* In this case, params is already malloc'd */
|
2009-03-04 20:48:42 +00:00
|
|
|
if (ls->allowoverride) {
|
2012-03-13 18:20:34 +00:00
|
|
|
ast_set_flag(ast_channel_flags(chan), AST_FLAG_WRITE_INT);
|
2009-03-04 20:48:42 +00:00
|
|
|
} else {
|
2012-03-13 18:20:34 +00:00
|
|
|
ast_clear_flag(ast_channel_flags(chan), AST_FLAG_WRITE_INT);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2007-06-12 14:16:37 +00:00
|
|
|
|
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
|
|
|
ls->origwfmt = ao2_bump(ast_channel_writeformat(chan));
|
2007-06-12 14:16:37 +00:00
|
|
|
|
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
|
|
|
if (ast_set_write_format(chan, ast_format_slin)) {
|
2012-01-09 22:15:50 +00:00
|
|
|
ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", ast_channel_name(chan));
|
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
|
|
|
ao2_cleanup(ls->origwfmt);
|
2007-06-12 14:16:37 +00:00
|
|
|
ast_free(ls);
|
|
|
|
ls = params = NULL;
|
2004-05-13 19:01:10 +00:00
|
|
|
}
|
2007-06-12 14:16:37 +00:00
|
|
|
|
2004-05-13 19:01:10 +00:00
|
|
|
return params;
|
|
|
|
}
|
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
static struct ast_generator linearstream =
|
2004-05-13 19:01:10 +00:00
|
|
|
{
|
2012-04-04 18:08:28 +00:00
|
|
|
.alloc = linear_alloc,
|
|
|
|
.release = linear_release,
|
|
|
|
.generate = linear_generator,
|
2004-05-13 19:01:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
int ast_linear_stream(struct ast_channel *chan, const char *filename, int fd, int allowoverride)
|
|
|
|
{
|
|
|
|
struct linear_state *lin;
|
2005-09-07 21:01:31 +00:00
|
|
|
char tmpf[256];
|
2004-05-13 19:01:10 +00:00
|
|
|
int autoclose = 0;
|
2017-12-19 01:47:54 +00:00
|
|
|
|
2004-05-13 19:01:10 +00:00
|
|
|
if (fd < 0) {
|
2009-03-04 20:48:42 +00:00
|
|
|
if (ast_strlen_zero(filename)) {
|
2004-05-13 19:01:10 +00:00
|
|
|
return -1;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2017-12-19 01:47:54 +00:00
|
|
|
|
2004-05-13 19:01:10 +00:00
|
|
|
autoclose = 1;
|
2017-12-19 01:47:54 +00:00
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (filename[0] == '/') {
|
2005-06-05 16:32:16 +00:00
|
|
|
ast_copy_string(tmpf, filename, sizeof(tmpf));
|
2009-03-04 20:48:42 +00:00
|
|
|
} else {
|
2006-11-04 01:32:31 +00:00
|
|
|
snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", ast_config_AST_DATA_DIR, "sounds", filename);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2017-12-19 01:47:54 +00:00
|
|
|
|
|
|
|
fd = open(tmpf, O_RDONLY);
|
|
|
|
if (fd < 0) {
|
2004-05-13 19:01:10 +00:00
|
|
|
ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2017-12-19 01:47:54 +00:00
|
|
|
|
|
|
|
lin = ast_calloc(1, sizeof(*lin));
|
|
|
|
if (!lin) {
|
|
|
|
if (autoclose) {
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
2004-05-13 19:01:10 +00:00
|
|
|
}
|
2017-12-19 01:47:54 +00:00
|
|
|
|
|
|
|
lin->fd = fd;
|
|
|
|
lin->allowoverride = allowoverride;
|
|
|
|
lin->autoclose = autoclose;
|
|
|
|
|
|
|
|
return ast_activate_generator(chan, &linearstream, lin);
|
2004-05-13 19:01:10 +00:00
|
|
|
}
|
2004-05-26 15:22:54 +00:00
|
|
|
|
2012-06-04 20:26:12 +00:00
|
|
|
static int control_streamfile(struct ast_channel *chan,
|
|
|
|
const char *file,
|
|
|
|
const char *fwd,
|
|
|
|
const char *rev,
|
|
|
|
const char *stop,
|
|
|
|
const char *suspend,
|
|
|
|
const char *restart,
|
|
|
|
int skipms,
|
|
|
|
long *offsetms,
|
2013-05-23 20:21:16 +00:00
|
|
|
const char *lang,
|
2012-06-04 20:26:12 +00:00
|
|
|
ast_waitstream_fr_cb cb)
|
2004-05-26 16:51:25 +00:00
|
|
|
{
|
2005-09-07 21:01:31 +00:00
|
|
|
char *breaks = NULL;
|
|
|
|
char *end = NULL;
|
|
|
|
int blen = 2;
|
|
|
|
int res;
|
2005-12-13 06:00:17 +00:00
|
|
|
long pause_restart_point = 0;
|
2007-06-08 21:02:46 +00:00
|
|
|
long offset = 0;
|
2016-11-11 13:13:30 +00:00
|
|
|
struct ast_silence_generator *silgen = NULL;
|
2007-06-08 21:02:46 +00:00
|
|
|
|
Resolve FORWARD_NULL static analysis warnings
This resolves core findings from ASTERISK-19650 numbers 0-2, 6, 7, 9-11, 14-20,
22-24, 28, 30-32, 34-36, 42-56, 82-84, 87, 89-90, 93-102, 104, 105, 109-111,
and 115. Finding numbers 26, 33, and 29 were already resolved. Those skipped
were either extended/deprecated or in areas of code that shouldn't be
disturbed.
(Closes issue ASTERISK-19650)
........
Merged revisions 366167 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 366168 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@366169 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-05-10 20:56:09 +00:00
|
|
|
if (!file) {
|
|
|
|
return -1;
|
|
|
|
}
|
2009-03-04 20:48:42 +00:00
|
|
|
if (offsetms) {
|
2007-06-08 21:02:46 +00:00
|
|
|
offset = *offsetms * 8; /* XXX Assumes 8kHz */
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2013-05-23 20:21:16 +00:00
|
|
|
if (lang == NULL) {
|
|
|
|
lang = ast_channel_language(chan);
|
|
|
|
}
|
2004-06-01 18:50:18 +00:00
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (stop) {
|
2004-06-01 18:50:18 +00:00
|
|
|
blen += strlen(stop);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
if (suspend) {
|
2008-08-10 19:35:50 +00:00
|
|
|
blen += strlen(suspend);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
if (restart) {
|
2005-08-22 19:06:42 +00:00
|
|
|
blen += strlen(restart);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-06-01 18:50:18 +00:00
|
|
|
|
2004-09-23 16:02:10 +00:00
|
|
|
if (blen > 2) {
|
2012-07-31 20:21:43 +00:00
|
|
|
breaks = ast_alloca(blen + 1);
|
2004-09-23 14:46:09 +00:00
|
|
|
breaks[0] = '\0';
|
2009-03-04 20:48:42 +00:00
|
|
|
if (stop) {
|
2005-08-22 19:06:42 +00:00
|
|
|
strcat(breaks, stop);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
if (suspend) {
|
2008-08-10 19:35:50 +00:00
|
|
|
strcat(breaks, suspend);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
if (restart) {
|
2005-08-22 19:06:42 +00:00
|
|
|
strcat(breaks, restart);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-09-23 14:46:09 +00:00
|
|
|
}
|
2004-05-26 23:56:41 +00:00
|
|
|
|
Resolve FORWARD_NULL static analysis warnings
This resolves core findings from ASTERISK-19650 numbers 0-2, 6, 7, 9-11, 14-20,
22-24, 28, 30-32, 34-36, 42-56, 82-84, 87, 89-90, 93-102, 104, 105, 109-111,
and 115. Finding numbers 26, 33, and 29 were already resolved. Those skipped
were either extended/deprecated or in areas of code that shouldn't be
disturbed.
(Closes issue ASTERISK-19650)
........
Merged revisions 366167 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 366168 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@366169 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-05-10 20:56:09 +00:00
|
|
|
if ((end = strchr(file, ':'))) {
|
|
|
|
if (!strcasecmp(end, ":end")) {
|
|
|
|
*end = '\0';
|
|
|
|
end++;
|
2016-02-29 01:05:16 +00:00
|
|
|
} else {
|
|
|
|
end = NULL;
|
2004-09-23 16:02:10 +00:00
|
|
|
}
|
2004-09-23 16:58:09 +00:00
|
|
|
}
|
2004-09-23 16:39:33 +00:00
|
|
|
|
2004-05-27 00:07:18 +00:00
|
|
|
for (;;) {
|
2005-12-13 06:00:17 +00:00
|
|
|
ast_stopstream(chan);
|
2013-05-23 20:21:16 +00:00
|
|
|
res = ast_streamfile(chan, file, lang);
|
2004-05-27 00:07:18 +00:00
|
|
|
if (!res) {
|
2005-12-13 06:00:17 +00:00
|
|
|
if (pause_restart_point) {
|
2012-02-20 23:43:27 +00:00
|
|
|
ast_seekstream(ast_channel_stream(chan), pause_restart_point, SEEK_SET);
|
2005-12-13 06:00:17 +00:00
|
|
|
pause_restart_point = 0;
|
2004-05-26 23:56:41 +00:00
|
|
|
}
|
2007-06-08 21:02:46 +00:00
|
|
|
else if (end || offset < 0) {
|
2009-03-04 20:48:42 +00:00
|
|
|
if (offset == -8) {
|
2007-06-08 21:02:46 +00:00
|
|
|
offset = 0;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2007-07-26 15:49:18 +00:00
|
|
|
ast_verb(3, "ControlPlayback seek to offset %ld from end\n", offset);
|
2007-06-08 21:02:46 +00:00
|
|
|
|
2012-02-20 23:43:27 +00:00
|
|
|
ast_seekstream(ast_channel_stream(chan), offset, SEEK_END);
|
2005-12-13 06:00:17 +00:00
|
|
|
end = NULL;
|
2007-06-08 21:02:46 +00:00
|
|
|
offset = 0;
|
|
|
|
} else if (offset) {
|
2007-07-26 15:49:18 +00:00
|
|
|
ast_verb(3, "ControlPlayback seek to offset %ld\n", offset);
|
2012-02-20 23:43:27 +00:00
|
|
|
ast_seekstream(ast_channel_stream(chan), offset, SEEK_SET);
|
2007-06-08 21:02:46 +00:00
|
|
|
offset = 0;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2012-06-04 20:26:12 +00:00
|
|
|
if (cb) {
|
|
|
|
res = ast_waitstream_fr_w_cb(chan, breaks, fwd, rev, skipms, cb);
|
|
|
|
} else {
|
|
|
|
res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
|
|
|
|
}
|
2004-05-26 23:56:41 +00:00
|
|
|
}
|
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (res < 1) {
|
2004-05-26 23:56:41 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-05-26 23:56:41 +00:00
|
|
|
|
2005-08-22 19:06:42 +00:00
|
|
|
/* We go at next loop if we got the restart char */
|
2013-01-22 15:16:20 +00:00
|
|
|
if ((restart && strchr(restart, res)) || res == AST_CONTROL_STREAM_RESTART) {
|
2007-06-14 19:39:12 +00:00
|
|
|
ast_debug(1, "we'll restart the stream here at next loop\n");
|
2005-12-13 06:00:17 +00:00
|
|
|
pause_restart_point = 0;
|
2013-01-22 15:16:20 +00:00
|
|
|
ast_test_suite_event_notify("PLAYBACK","Channel: %s\r\n"
|
|
|
|
"Control: %s\r\n",
|
|
|
|
ast_channel_name(chan),
|
|
|
|
"Restart");
|
2005-08-22 19:06:42 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-01-22 15:16:20 +00:00
|
|
|
if ((suspend && strchr(suspend, res)) || res == AST_CONTROL_STREAM_SUSPEND) {
|
2012-02-20 23:43:27 +00:00
|
|
|
pause_restart_point = ast_tellstream(ast_channel_stream(chan));
|
2016-11-11 13:13:30 +00:00
|
|
|
|
|
|
|
if (ast_opt_transmit_silence) {
|
|
|
|
silgen = ast_channel_start_silence_generator(chan);
|
|
|
|
}
|
2013-01-22 15:16:20 +00:00
|
|
|
ast_test_suite_event_notify("PLAYBACK","Channel: %s\r\n"
|
|
|
|
"Control: %s\r\n",
|
|
|
|
ast_channel_name(chan),
|
|
|
|
"Pause");
|
2005-12-13 06:00:17 +00:00
|
|
|
for (;;) {
|
|
|
|
ast_stopstream(chan);
|
2009-03-04 20:48:42 +00:00
|
|
|
if (!(res = ast_waitfordigit(chan, 1000))) {
|
2004-06-01 19:38:06 +00:00
|
|
|
continue;
|
2013-01-22 15:16:20 +00:00
|
|
|
} else if (res == -1 || (suspend && strchr(suspend, res)) || (stop && strchr(stop, res))
|
|
|
|
|| res == AST_CONTROL_STREAM_SUSPEND || res == AST_CONTROL_STREAM_STOP) {
|
2004-05-26 23:56:41 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-05-26 23:56:41 +00:00
|
|
|
}
|
2016-11-11 13:13:30 +00:00
|
|
|
if (silgen) {
|
|
|
|
ast_channel_stop_silence_generator(chan, silgen);
|
|
|
|
silgen = NULL;
|
|
|
|
}
|
|
|
|
|
2013-01-22 15:16:20 +00:00
|
|
|
if ((suspend && (res == *suspend)) || res == AST_CONTROL_STREAM_SUSPEND) {
|
2004-05-26 23:56:41 +00:00
|
|
|
res = 0;
|
2013-01-22 15:16:20 +00:00
|
|
|
ast_test_suite_event_notify("PLAYBACK","Channel: %s\r\n"
|
|
|
|
"Control: %s\r\n",
|
|
|
|
ast_channel_name(chan),
|
|
|
|
"Unpause");
|
2004-05-26 23:56:41 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2005-12-13 06:00:17 +00:00
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (res == -1) {
|
2004-05-26 23:56:41 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-05-26 23:56:41 +00:00
|
|
|
|
2004-06-15 20:33:26 +00:00
|
|
|
/* if we get one of our stop chars, return it to the calling function */
|
2013-01-22 15:16:20 +00:00
|
|
|
if ((stop && strchr(stop, res)) || res == AST_CONTROL_STREAM_STOP) {
|
|
|
|
ast_test_suite_event_notify("PLAYBACK","Channel: %s\r\n"
|
|
|
|
"Control: %s\r\n",
|
|
|
|
ast_channel_name(chan),
|
|
|
|
"Stop");
|
2004-05-26 23:56:41 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-05-26 23:56:41 +00:00
|
|
|
}
|
2005-12-13 06:00:17 +00:00
|
|
|
|
2007-06-08 21:02:46 +00:00
|
|
|
if (pause_restart_point) {
|
|
|
|
offset = pause_restart_point;
|
|
|
|
} else {
|
2012-02-20 23:43:27 +00:00
|
|
|
if (ast_channel_stream(chan)) {
|
|
|
|
offset = ast_tellstream(ast_channel_stream(chan));
|
2007-06-08 21:02:46 +00:00
|
|
|
} else {
|
|
|
|
offset = -8; /* indicate end of file */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (offsetms) {
|
2007-06-08 21:02:46 +00:00
|
|
|
*offsetms = offset / 8; /* samples --> ms ... XXX Assumes 8 kHz */
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2007-06-08 21:02:46 +00:00
|
|
|
|
2005-12-13 06:00:17 +00:00
|
|
|
ast_stopstream(chan);
|
2004-05-26 23:56:41 +00:00
|
|
|
|
2004-05-26 16:51:25 +00:00
|
|
|
return res;
|
2004-05-26 15:22:54 +00:00
|
|
|
}
|
2004-09-17 15:05:29 +00:00
|
|
|
|
2012-06-04 20:26:12 +00:00
|
|
|
int ast_control_streamfile_w_cb(struct ast_channel *chan,
|
|
|
|
const char *file,
|
|
|
|
const char *fwd,
|
|
|
|
const char *rev,
|
|
|
|
const char *stop,
|
|
|
|
const char *suspend,
|
|
|
|
const char *restart,
|
|
|
|
int skipms,
|
|
|
|
long *offsetms,
|
|
|
|
ast_waitstream_fr_cb cb)
|
|
|
|
{
|
2013-05-23 20:21:16 +00:00
|
|
|
return control_streamfile(chan, file, fwd, rev, stop, suspend, restart, skipms, offsetms, NULL, cb);
|
2012-06-04 20:26:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int ast_control_streamfile(struct ast_channel *chan, const char *file,
|
|
|
|
const char *fwd, const char *rev,
|
|
|
|
const char *stop, const char *suspend,
|
|
|
|
const char *restart, int skipms, long *offsetms)
|
|
|
|
{
|
2013-05-23 20:21:16 +00:00
|
|
|
return control_streamfile(chan, file, fwd, rev, stop, suspend, restart, skipms, offsetms, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int ast_control_streamfile_lang(struct ast_channel *chan, const char *file,
|
|
|
|
const char *fwd, const char *rev, const char *stop, const char *suspend,
|
|
|
|
const char *restart, int skipms, const char *lang, long *offsetms)
|
|
|
|
{
|
|
|
|
return control_streamfile(chan, file, fwd, rev, stop, suspend, restart, skipms, offsetms, lang, NULL);
|
2012-06-04 20:26:12 +00:00
|
|
|
}
|
|
|
|
|
2014-04-17 21:57:36 +00:00
|
|
|
enum control_tone_frame_response_result {
|
|
|
|
CONTROL_TONE_RESPONSE_FAILED = -1,
|
|
|
|
CONTROL_TONE_RESPONSE_NORMAL = 0,
|
|
|
|
CONTROL_TONE_RESPONSE_FINISHED = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
static enum control_tone_frame_response_result control_tone_frame_response(struct ast_channel *chan, struct ast_frame *fr, struct ast_tone_zone_sound *ts, const char *tone, int *paused)
|
|
|
|
{
|
|
|
|
switch (fr->subclass.integer) {
|
|
|
|
case AST_CONTROL_STREAM_STOP:
|
|
|
|
ast_playtones_stop(chan);
|
|
|
|
return CONTROL_TONE_RESPONSE_FINISHED;
|
|
|
|
case AST_CONTROL_STREAM_SUSPEND:
|
|
|
|
if (*paused) {
|
|
|
|
*paused = 0;
|
|
|
|
if (ast_playtones_start(chan, 0, ts ? ts->data : tone, 0)) {
|
|
|
|
return CONTROL_TONE_RESPONSE_FAILED;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*paused = 1;
|
|
|
|
ast_playtones_stop(chan);
|
|
|
|
}
|
|
|
|
return CONTROL_TONE_RESPONSE_NORMAL;
|
|
|
|
case AST_CONTROL_STREAM_RESTART:
|
|
|
|
ast_playtones_stop(chan);
|
|
|
|
if (ast_playtones_start(chan, 0, ts ? ts->data : tone, 0)) {
|
|
|
|
return CONTROL_TONE_RESPONSE_FAILED;
|
|
|
|
}
|
|
|
|
return CONTROL_TONE_RESPONSE_NORMAL;
|
|
|
|
case AST_CONTROL_STREAM_REVERSE:
|
|
|
|
ast_log(LOG_NOTICE, "Media control operation 'reverse' not supported for media type 'tone'\n");
|
|
|
|
return CONTROL_TONE_RESPONSE_NORMAL;
|
|
|
|
case AST_CONTROL_STREAM_FORWARD:
|
|
|
|
ast_log(LOG_NOTICE, "Media control operation 'forward' not supported for media type 'tone'\n");
|
|
|
|
return CONTROL_TONE_RESPONSE_NORMAL;
|
|
|
|
case AST_CONTROL_HANGUP:
|
|
|
|
case AST_CONTROL_BUSY:
|
|
|
|
case AST_CONTROL_CONGESTION:
|
|
|
|
return CONTROL_TONE_RESPONSE_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CONTROL_TONE_RESPONSE_NORMAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int parse_tone_uri(char *tone_parser,
|
|
|
|
const char **tone_indication,
|
|
|
|
const char **tone_zone)
|
|
|
|
{
|
|
|
|
*tone_indication = strsep(&tone_parser, ";");
|
|
|
|
|
|
|
|
if (ast_strlen_zero(tone_parser)) {
|
|
|
|
/* Only the indication is included */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(strncmp(tone_parser, "tonezone=", 9))) {
|
|
|
|
*tone_zone = tone_parser + 9;
|
|
|
|
} else {
|
|
|
|
ast_log(LOG_ERROR, "Unexpected Tone URI component: %s\n", tone_parser);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ast_control_tone(struct ast_channel *chan, const char *tone)
|
|
|
|
{
|
|
|
|
struct ast_tone_zone *zone = NULL;
|
|
|
|
struct ast_tone_zone_sound *ts;
|
|
|
|
int paused = 0;
|
2014-04-17 22:42:57 +00:00
|
|
|
int res = 0;
|
2014-04-17 21:57:36 +00:00
|
|
|
|
|
|
|
const char *tone_indication = NULL;
|
|
|
|
const char *tone_zone = NULL;
|
|
|
|
char *tone_uri_parser;
|
|
|
|
|
|
|
|
if (ast_strlen_zero(tone)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
tone_uri_parser = ast_strdupa(tone);
|
|
|
|
|
|
|
|
if (parse_tone_uri(tone_uri_parser, &tone_indication, &tone_zone)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tone_zone) {
|
|
|
|
zone = ast_get_indication_zone(tone_zone);
|
|
|
|
}
|
|
|
|
|
|
|
|
ts = ast_get_indication_tone(zone ? zone : ast_channel_zone(chan), tone_indication);
|
|
|
|
|
|
|
|
if (ast_playtones_start(chan, 0, ts ? ts->data : tone_indication, 0)) {
|
2017-12-19 01:47:54 +00:00
|
|
|
res = -1;
|
2014-04-17 21:57:36 +00:00
|
|
|
}
|
|
|
|
|
2017-12-19 01:47:54 +00:00
|
|
|
while (!res) {
|
2014-04-17 21:57:36 +00:00
|
|
|
struct ast_frame *fr;
|
|
|
|
|
|
|
|
if (ast_waitfor(chan, -1) < 0) {
|
|
|
|
res = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
fr = ast_read_noaudio(chan);
|
|
|
|
|
|
|
|
if (!fr) {
|
|
|
|
res = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fr->frametype != AST_FRAME_CONTROL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
res = control_tone_frame_response(chan, fr, ts, tone_indication, &paused);
|
|
|
|
if (res == CONTROL_TONE_RESPONSE_FINISHED) {
|
|
|
|
res = 0;
|
|
|
|
break;
|
|
|
|
} else if (res == CONTROL_TONE_RESPONSE_FAILED) {
|
|
|
|
res = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ts) {
|
|
|
|
ast_tone_zone_sound_unref(ts);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (zone) {
|
|
|
|
ast_tone_zone_unref(zone);
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2005-01-10 14:46:59 +00:00
|
|
|
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
|
2004-09-17 15:05:29 +00:00
|
|
|
{
|
2007-06-12 14:16:37 +00:00
|
|
|
int d = 0;
|
|
|
|
|
2012-01-24 20:12:09 +00:00
|
|
|
if ((d = ast_streamfile(chan, fn, ast_channel_language(chan)))) {
|
2004-09-17 15:05:29 +00:00
|
|
|
return d;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2007-06-12 14:16:37 +00:00
|
|
|
|
2004-09-17 15:05:29 +00:00
|
|
|
d = ast_waitstream(chan, AST_DIGIT_ANY);
|
2007-06-12 14:16:37 +00:00
|
|
|
|
2004-09-17 15:05:29 +00:00
|
|
|
ast_stopstream(chan);
|
2007-06-12 14:16:37 +00:00
|
|
|
|
2004-09-17 15:05:29 +00:00
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
2013-08-06 14:44:45 +00:00
|
|
|
/*!
|
|
|
|
* \brief Construct a silence frame of the same duration as \a orig.
|
|
|
|
*
|
|
|
|
* The \a orig frame must be \ref AST_FORMAT_SLINEAR.
|
|
|
|
*
|
|
|
|
* \param orig Frame as basis for silence to generate.
|
|
|
|
* \return New frame of silence; free with ast_frfree().
|
|
|
|
* \return \c NULL on error.
|
|
|
|
*/
|
|
|
|
static struct ast_frame *make_silence(const struct ast_frame *orig)
|
|
|
|
{
|
|
|
|
struct ast_frame *silence;
|
|
|
|
size_t size;
|
|
|
|
size_t datalen;
|
|
|
|
size_t samples = 0;
|
|
|
|
|
|
|
|
if (!orig) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-01-10 19:11:20 +00:00
|
|
|
do {
|
|
|
|
if (ast_format_cmp(orig->subclass.format, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
|
|
|
|
ast_log(LOG_WARNING, "Attempting to silence non-slin frame\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-08-06 14:44:45 +00:00
|
|
|
|
|
|
|
samples += orig->samples;
|
2017-01-10 19:11:20 +00:00
|
|
|
|
|
|
|
orig = AST_LIST_NEXT(orig, frame_list);
|
|
|
|
} while (orig);
|
2013-08-06 14:44:45 +00:00
|
|
|
|
2014-05-09 22:49:26 +00:00
|
|
|
ast_verb(4, "Silencing %zu samples\n", samples);
|
2013-08-06 14:44:45 +00:00
|
|
|
|
|
|
|
|
|
|
|
datalen = sizeof(short) * samples;
|
|
|
|
size = sizeof(*silence) + datalen;
|
|
|
|
silence = ast_calloc(1, size);
|
|
|
|
if (!silence) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
silence->mallocd = AST_MALLOCD_HDR;
|
|
|
|
silence->frametype = AST_FRAME_VOICE;
|
|
|
|
silence->data.ptr = (void *)(silence + 1);
|
|
|
|
silence->samples = samples;
|
|
|
|
silence->datalen = datalen;
|
|
|
|
|
2017-01-10 19:11:20 +00:00
|
|
|
silence->subclass.format = ao2_bump(ast_format_slin);
|
2013-08-06 14:44:45 +00:00
|
|
|
|
|
|
|
return silence;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Sets a channel's read format to \ref AST_FORMAT_SLINEAR, recording
|
|
|
|
* its original format.
|
|
|
|
*
|
|
|
|
* \param chan Channel to modify.
|
|
|
|
* \param[out] orig_format Output variable to store channel's original read
|
|
|
|
* format.
|
|
|
|
* \return 0 on success.
|
|
|
|
* \return -1 on error.
|
|
|
|
*/
|
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
|
|
|
static int set_read_to_slin(struct ast_channel *chan, struct ast_format **orig_format)
|
2013-08-06 14:44:45 +00:00
|
|
|
{
|
|
|
|
if (!chan || !orig_format) {
|
|
|
|
return -1;
|
|
|
|
}
|
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
|
|
|
*orig_format = ao2_bump(ast_channel_readformat(chan));
|
|
|
|
return ast_set_read_format(chan, ast_format_slin);
|
2013-08-06 14:44:45 +00:00
|
|
|
}
|
|
|
|
|
2004-09-17 15:05:29 +00:00
|
|
|
static int global_silence_threshold = 128;
|
|
|
|
static int global_maxsilence = 0;
|
|
|
|
|
2006-05-05 19:10:11 +00:00
|
|
|
/*! Optionally play a sound file or a beep, then record audio and video from the channel.
|
2007-06-04 15:56:13 +00:00
|
|
|
* \param chan Channel to playback to/record from.
|
|
|
|
* \param playfile Filename of sound to play before recording begins.
|
|
|
|
* \param recordfile Filename to record to.
|
2011-07-26 14:17:13 +00:00
|
|
|
* \param maxtime Maximum length of recording (in seconds).
|
2007-06-04 15:56:13 +00:00
|
|
|
* \param fmt Format(s) to record message in. Multiple formats may be specified by separating them with a '|'.
|
|
|
|
* \param duration Where to store actual length of the recorded message (in milliseconds).
|
Merged revisions 337120 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/10
................
r337120 | mjordan | 2011-09-20 17:49:36 -0500 (Tue, 20 Sep 2011) | 28 lines
Merged revisions 337118 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8
........
r337118 | mjordan | 2011-09-20 17:38:54 -0500 (Tue, 20 Sep 2011) | 21 lines
Fix for incorrect voicemail duration in external notifications
This patch fixes an issue where the voicemail duration was being reported
with a duration significantly less than the actual sound file duration.
Voicemails that contained mostly silence were reporting the duration of
only the sound in the file, as opposed to the duration of the file with
the silence. This patch fixes this by having two durations reported in
the __ast_play_and_record family of functions - the sound_duration and the
actual duration of the file. The sound_duration, which is optional, now
reports the duration of the sound in the file, while the actual full duration
of the file is reported in the duration parameter. This allows the voicemail
applications to use the sound_duration for minimum duration checking, while
reporting the full duration to external parties if the voicemail is kept.
(issue ASTERISK-2234)
(closes issue ASTERISK-16981)
Reported by: Mary Ciuciu, Byron Clark, Brad House, Karsten Wemheuer, KevinH
Tested by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/1443
........
................
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@337124 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2011-09-20 23:02:25 +00:00
|
|
|
* \param sound_duration Where to store the length of the recorded message (in milliseconds), minus any silence
|
2007-06-04 15:56:13 +00:00
|
|
|
* \param beep Whether to play a beep before starting to record.
|
2009-03-04 20:48:42 +00:00
|
|
|
* \param silencethreshold
|
2007-06-04 15:56:13 +00:00
|
|
|
* \param maxsilence Length of silence that will end a recording (in milliseconds).
|
|
|
|
* \param path Optional filesystem path to unlock.
|
2011-07-26 14:17:13 +00:00
|
|
|
* \param prepend If true, prepend the recorded audio to an existing file and follow prepend mode recording rules
|
2007-06-04 15:56:13 +00:00
|
|
|
* \param acceptdtmf DTMF digits that will end the recording.
|
|
|
|
* \param canceldtmf DTMF digits that will cancel the recording.
|
2011-07-26 14:17:13 +00:00
|
|
|
* \param skip_confirmation_sound If true, don't play auth-thankyou at end. Nice for custom recording prompts in apps.
|
|
|
|
*
|
|
|
|
* \retval -1 failure or hangup
|
|
|
|
* \retval 'S' Recording ended from silence timeout
|
|
|
|
* \retval 't' Recording ended from the message exceeding the maximum duration, or via DTMF in prepend mode
|
|
|
|
* \retval dtmfchar Recording ended via the return value's DTMF character for either cancel or accept.
|
2006-05-05 19:10:11 +00:00
|
|
|
*/
|
2013-07-03 17:58:45 +00:00
|
|
|
static int __ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence, const char *path, int prepend, const char *acceptdtmf, const char *canceldtmf, int skip_confirmation_sound, enum ast_record_if_exists if_exists)
|
2004-09-17 15:05:29 +00:00
|
|
|
{
|
2006-05-04 20:29:13 +00:00
|
|
|
int d = 0;
|
2005-06-05 15:04:43 +00:00
|
|
|
char *fmts;
|
2004-09-17 15:05:29 +00:00
|
|
|
char comment[256];
|
2006-05-04 21:26:04 +00:00
|
|
|
int x, fmtcnt = 1, res = -1, outmsg = 0;
|
2009-11-30 21:31:55 +00:00
|
|
|
struct ast_filestream *others[AST_MAX_FORMATS];
|
|
|
|
char *sfmt[AST_MAX_FORMATS];
|
2006-05-04 21:26:04 +00:00
|
|
|
char *stringp = NULL;
|
2004-09-17 15:05:29 +00:00
|
|
|
time_t start, end;
|
2006-05-04 21:26:04 +00:00
|
|
|
struct ast_dsp *sildet = NULL; /* silence detector dsp */
|
2004-09-17 15:05:29 +00:00
|
|
|
int totalsilence = 0;
|
2009-06-23 14:54:21 +00:00
|
|
|
int dspsilence = 0;
|
2009-06-27 10:04:51 +00:00
|
|
|
int olddspsilence = 0;
|
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
|
|
|
struct ast_format *rfmt = NULL;
|
2005-11-01 17:22:25 +00:00
|
|
|
struct ast_silence_generator *silgen = NULL;
|
2011-05-09 14:41:33 +00:00
|
|
|
char prependfile[PATH_MAX];
|
2013-07-03 17:58:45 +00:00
|
|
|
int ioflags; /* IO flags for writing output file */
|
|
|
|
|
|
|
|
ioflags = O_CREAT|O_WRONLY;
|
|
|
|
|
|
|
|
switch (if_exists) {
|
|
|
|
case AST_RECORD_IF_EXISTS_FAIL:
|
|
|
|
ioflags |= O_EXCL;
|
|
|
|
break;
|
|
|
|
case AST_RECORD_IF_EXISTS_OVERWRITE:
|
|
|
|
ioflags |= O_TRUNC;
|
|
|
|
break;
|
|
|
|
case AST_RECORD_IF_EXISTS_APPEND:
|
|
|
|
ioflags |= O_APPEND;
|
|
|
|
break;
|
2015-04-09 12:57:21 +00:00
|
|
|
case AST_RECORD_IF_EXISTS_ERROR:
|
|
|
|
ast_assert(0);
|
|
|
|
break;
|
2013-07-03 17:58:45 +00:00
|
|
|
}
|
2004-09-17 15:05:29 +00:00
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (silencethreshold < 0) {
|
2004-09-17 15:05:29 +00:00
|
|
|
silencethreshold = global_silence_threshold;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-09-17 15:05:29 +00:00
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (maxsilence < 0) {
|
2004-09-17 15:05:29 +00:00
|
|
|
maxsilence = global_maxsilence;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-09-17 15:05:29 +00:00
|
|
|
|
|
|
|
/* barf if no pointer passed to store duration in */
|
2007-06-06 19:00:40 +00:00
|
|
|
if (!duration) {
|
2004-09-17 15:05:29 +00:00
|
|
|
ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-06-14 19:39:12 +00:00
|
|
|
ast_debug(1, "play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
|
2012-01-09 22:15:50 +00:00
|
|
|
snprintf(comment, sizeof(comment), "Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, ast_channel_name(chan));
|
2004-09-17 15:05:29 +00:00
|
|
|
|
2006-05-04 20:29:13 +00:00
|
|
|
if (playfile || beep) {
|
2009-03-04 20:48:42 +00:00
|
|
|
if (!beep) {
|
2006-05-04 20:29:13 +00:00
|
|
|
d = ast_play_and_wait(chan, playfile);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
if (d > -1) {
|
2006-11-17 23:18:51 +00:00
|
|
|
d = ast_stream_and_wait(chan, "beep", "");
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
if (d < 0) {
|
2004-09-17 15:05:29 +00:00
|
|
|
return -1;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-09-17 15:05:29 +00:00
|
|
|
}
|
|
|
|
|
2006-05-04 20:29:13 +00:00
|
|
|
if (prepend) {
|
2009-03-04 20:48:42 +00:00
|
|
|
ast_copy_string(prependfile, recordfile, sizeof(prependfile));
|
2006-05-04 20:29:13 +00:00
|
|
|
strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
|
|
|
|
}
|
|
|
|
|
2004-09-17 15:05:29 +00:00
|
|
|
fmts = ast_strdupa(fmt);
|
|
|
|
|
2006-05-04 21:26:04 +00:00
|
|
|
stringp = fmts;
|
2004-09-17 15:05:29 +00:00
|
|
|
strsep(&stringp, "|");
|
2007-06-14 19:39:12 +00:00
|
|
|
ast_debug(1, "Recording Formats: sfmts=%s\n", fmts);
|
2004-09-17 15:05:29 +00:00
|
|
|
sfmt[0] = ast_strdupa(fmts);
|
|
|
|
|
2006-05-10 13:22:15 +00:00
|
|
|
while ((fmt = strsep(&stringp, "|"))) {
|
2009-11-30 21:31:55 +00:00
|
|
|
if (fmtcnt > AST_MAX_FORMATS - 1) {
|
|
|
|
ast_log(LOG_WARNING, "Please increase AST_MAX_FORMATS in file.h\n");
|
2004-09-17 15:05:29 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
sfmt[fmtcnt++] = ast_strdupa(fmt);
|
|
|
|
}
|
|
|
|
|
2006-05-22 02:51:04 +00:00
|
|
|
end = start = time(NULL); /* pre-initialize end to be same as start in case we never get into loop */
|
2006-05-04 21:26:04 +00:00
|
|
|
for (x = 0; x < fmtcnt; x++) {
|
2013-07-03 17:58:45 +00:00
|
|
|
others[x] = ast_writefile(prepend ? prependfile : recordfile, sfmt[x], comment, ioflags, 0, AST_FILE_MODE);
|
2007-07-26 15:49:18 +00:00
|
|
|
ast_verb(3, "x=%d, open writing: %s format: %s, %p\n", x, prepend ? prependfile : recordfile, sfmt[x], others[x]);
|
2004-09-17 15:05:29 +00:00
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (!others[x]) {
|
2004-09-17 15:05:29 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-09-17 15:05:29 +00:00
|
|
|
}
|
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (path) {
|
2005-01-23 09:05:01 +00:00
|
|
|
ast_unlock_path(path);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-01-23 09:05:01 +00:00
|
|
|
|
2004-09-17 15:05:29 +00:00
|
|
|
if (maxsilence > 0) {
|
2005-01-23 09:05:01 +00:00
|
|
|
sildet = ast_dsp_new(); /* Create the silence detector */
|
|
|
|
if (!sildet) {
|
|
|
|
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
ast_dsp_set_threshold(sildet, silencethreshold);
|
2013-08-06 14:44:45 +00:00
|
|
|
res = set_read_to_slin(chan, &rfmt);
|
2004-09-17 15:05:29 +00:00
|
|
|
if (res < 0) {
|
|
|
|
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
|
2005-01-23 09:05:01 +00:00
|
|
|
ast_dsp_free(sildet);
|
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
|
|
|
ao2_cleanup(rfmt);
|
2004-09-17 15:05:29 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2005-11-01 17:22:25 +00:00
|
|
|
|
2006-05-04 20:29:13 +00:00
|
|
|
if (!prepend) {
|
|
|
|
/* Request a video update */
|
|
|
|
ast_indicate(chan, AST_CONTROL_VIDUPDATE);
|
2004-09-17 15:05:29 +00:00
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (ast_opt_transmit_silence) {
|
2006-05-04 20:29:13 +00:00
|
|
|
silgen = ast_channel_start_silence_generator(chan);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2006-05-04 20:29:13 +00:00
|
|
|
}
|
2005-11-01 17:22:25 +00:00
|
|
|
|
2004-09-17 15:05:29 +00:00
|
|
|
if (x == fmtcnt) {
|
2013-08-06 14:44:45 +00:00
|
|
|
/* Loop, writing the packets we read to the writer(s), until
|
|
|
|
* we have reason to stop. */
|
2006-05-04 20:29:13 +00:00
|
|
|
struct ast_frame *f;
|
2013-08-06 14:44:45 +00:00
|
|
|
int paused = 0;
|
|
|
|
int muted = 0;
|
|
|
|
time_t pause_start = 0;
|
|
|
|
int paused_secs = 0;
|
|
|
|
int pausedsilence = 0;
|
|
|
|
|
2006-05-04 21:26:04 +00:00
|
|
|
for (;;) {
|
2009-03-04 20:48:42 +00:00
|
|
|
if (!(res = ast_waitfor(chan, 2000))) {
|
2007-06-14 19:39:12 +00:00
|
|
|
ast_debug(1, "One waitfor failed, trying another\n");
|
2004-09-17 15:05:29 +00:00
|
|
|
/* Try one more time in case of masq */
|
2009-03-04 20:48:42 +00:00
|
|
|
if (!(res = ast_waitfor(chan, 2000))) {
|
2012-01-09 22:15:50 +00:00
|
|
|
ast_log(LOG_WARNING, "No audio available on %s??\n", ast_channel_name(chan));
|
2004-09-17 15:05:29 +00:00
|
|
|
res = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res < 0) {
|
|
|
|
f = NULL;
|
|
|
|
break;
|
|
|
|
}
|
2009-03-04 20:48:42 +00:00
|
|
|
if (!(f = ast_read(chan))) {
|
2004-09-17 15:05:29 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-09-17 15:05:29 +00:00
|
|
|
if (f->frametype == AST_FRAME_VOICE) {
|
|
|
|
/* write each format */
|
2013-08-06 14:44:45 +00:00
|
|
|
if (paused) {
|
|
|
|
/* It's all good */
|
|
|
|
res = 0;
|
|
|
|
} else {
|
2017-01-10 19:11:20 +00:00
|
|
|
struct ast_frame *silence = NULL;
|
2013-08-06 14:44:45 +00:00
|
|
|
struct ast_frame *orig = f;
|
|
|
|
|
|
|
|
if (muted) {
|
|
|
|
silence = make_silence(orig);
|
|
|
|
if (!silence) {
|
2017-01-10 19:11:20 +00:00
|
|
|
ast_log(LOG_WARNING, "Error creating silence\n");
|
2013-08-06 14:44:45 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
f = silence;
|
|
|
|
}
|
|
|
|
for (x = 0; x < fmtcnt; x++) {
|
|
|
|
if (prepend && !others[x]) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
res = ast_writestream(others[x], f);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2017-01-10 19:11:20 +00:00
|
|
|
ast_frame_dtor(silence);
|
2013-08-06 14:44:45 +00:00
|
|
|
f = orig;
|
2004-09-17 15:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Silence Detection */
|
|
|
|
if (maxsilence > 0) {
|
2009-06-23 14:54:21 +00:00
|
|
|
dspsilence = 0;
|
2004-09-17 15:05:29 +00:00
|
|
|
ast_dsp_silence(sildet, f, &dspsilence);
|
2009-06-27 10:04:51 +00:00
|
|
|
if (olddspsilence > dspsilence) {
|
|
|
|
totalsilence += olddspsilence;
|
|
|
|
}
|
|
|
|
olddspsilence = dspsilence;
|
2004-09-17 15:05:29 +00:00
|
|
|
|
2013-08-06 14:44:45 +00:00
|
|
|
if (paused) {
|
|
|
|
/* record how much silence there was while we are paused */
|
|
|
|
pausedsilence = dspsilence;
|
|
|
|
} else if (dspsilence > pausedsilence) {
|
|
|
|
/* ignore the paused silence */
|
|
|
|
dspsilence -= pausedsilence;
|
|
|
|
} else {
|
|
|
|
/* dspsilence has reset, reset pausedsilence */
|
|
|
|
pausedsilence = 0;
|
|
|
|
}
|
|
|
|
|
2009-06-23 14:54:21 +00:00
|
|
|
if (dspsilence > maxsilence) {
|
2005-01-23 09:05:01 +00:00
|
|
|
/* Ended happily with silence */
|
2009-06-23 14:54:21 +00:00
|
|
|
ast_verb(3, "Recording automatically stopped after a silence of %d seconds\n", dspsilence/1000);
|
2006-04-11 01:12:13 +00:00
|
|
|
res = 'S';
|
2006-05-04 21:26:04 +00:00
|
|
|
outmsg = 2;
|
2005-01-23 09:05:01 +00:00
|
|
|
break;
|
2004-09-17 15:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Exit on any error */
|
|
|
|
if (res) {
|
|
|
|
ast_log(LOG_WARNING, "Error writing frame\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (f->frametype == AST_FRAME_VIDEO) {
|
|
|
|
/* Write only once */
|
|
|
|
ast_writestream(others[0], f);
|
|
|
|
} else if (f->frametype == AST_FRAME_DTMF) {
|
2006-05-04 20:29:13 +00:00
|
|
|
if (prepend) {
|
|
|
|
/* stop recording with any digit */
|
2009-11-04 14:05:12 +00:00
|
|
|
ast_verb(3, "User ended message by pressing %c\n", f->subclass.integer);
|
2006-05-04 20:29:13 +00:00
|
|
|
res = 't';
|
|
|
|
outmsg = 2;
|
|
|
|
break;
|
|
|
|
}
|
2009-11-04 14:05:12 +00:00
|
|
|
if (strchr(acceptdtmf, f->subclass.integer)) {
|
|
|
|
ast_verb(3, "User ended message by pressing %c\n", f->subclass.integer);
|
|
|
|
res = f->subclass.integer;
|
2004-09-17 15:05:29 +00:00
|
|
|
outmsg = 2;
|
|
|
|
break;
|
|
|
|
}
|
2009-11-04 14:05:12 +00:00
|
|
|
if (strchr(canceldtmf, f->subclass.integer)) {
|
2013-08-06 14:44:45 +00:00
|
|
|
ast_verb(3, "User canceled message by pressing %c\n", f->subclass.integer);
|
2009-11-04 14:05:12 +00:00
|
|
|
res = f->subclass.integer;
|
2004-09-17 15:05:29 +00:00
|
|
|
outmsg = 0;
|
|
|
|
break;
|
|
|
|
}
|
2013-08-06 14:44:45 +00:00
|
|
|
} else if (f->frametype == AST_FRAME_CONTROL) {
|
|
|
|
if (f->subclass.integer == AST_CONTROL_RECORD_CANCEL) {
|
|
|
|
ast_verb(3, "Message canceled by control\n");
|
|
|
|
outmsg = 0; /* cancels the recording */
|
|
|
|
res = 0;
|
|
|
|
break;
|
|
|
|
} else if (f->subclass.integer == AST_CONTROL_RECORD_STOP) {
|
|
|
|
ast_verb(3, "Message ended by control\n");
|
|
|
|
res = 0;
|
|
|
|
break;
|
|
|
|
} else if (f->subclass.integer == AST_CONTROL_RECORD_SUSPEND) {
|
|
|
|
paused = !paused;
|
|
|
|
ast_verb(3, "Message %spaused by control\n",
|
|
|
|
paused ? "" : "un");
|
|
|
|
if (paused) {
|
|
|
|
pause_start = time(NULL);
|
|
|
|
} else {
|
|
|
|
paused_secs += time(NULL) - pause_start;
|
|
|
|
}
|
|
|
|
} else if (f->subclass.integer == AST_CONTROL_RECORD_MUTE) {
|
|
|
|
muted = !muted;
|
|
|
|
ast_verb(3, "Message %smuted by control\n",
|
|
|
|
muted ? "" : "un");
|
|
|
|
/* We can only silence slin frames, so
|
|
|
|
* set the mode, if we haven't already
|
|
|
|
* for sildet
|
|
|
|
*/
|
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
|
|
|
if (muted && !rfmt) {
|
2013-08-06 14:44:45 +00:00
|
|
|
ast_verb(3, "Setting read format to linear mode\n");
|
|
|
|
res = set_read_to_slin(chan, &rfmt);
|
|
|
|
if (res < 0) {
|
|
|
|
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-10-26 15:02:23 +00:00
|
|
|
}
|
2013-08-06 14:44:45 +00:00
|
|
|
if (maxtime && !paused) {
|
2006-05-22 02:51:04 +00:00
|
|
|
end = time(NULL);
|
2013-08-06 14:44:45 +00:00
|
|
|
if (maxtime < (end - start - paused_secs)) {
|
2007-07-26 15:49:18 +00:00
|
|
|
ast_verb(3, "Took too long, cutting it short...\n");
|
2004-09-17 15:05:29 +00:00
|
|
|
res = 't';
|
2006-05-04 20:29:13 +00:00
|
|
|
outmsg = 2;
|
2004-09-17 15:05:29 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ast_frfree(f);
|
|
|
|
}
|
|
|
|
if (!f) {
|
2007-07-26 15:49:18 +00:00
|
|
|
ast_verb(3, "User hung up\n");
|
2004-09-17 15:05:29 +00:00
|
|
|
res = -1;
|
2006-05-04 21:26:04 +00:00
|
|
|
outmsg = 1;
|
2006-05-04 20:29:13 +00:00
|
|
|
} else {
|
|
|
|
ast_frfree(f);
|
2004-09-17 15:05:29 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]);
|
|
|
|
}
|
2006-05-04 21:26:04 +00:00
|
|
|
|
2006-05-04 20:29:13 +00:00
|
|
|
if (!prepend) {
|
2009-03-04 20:48:42 +00:00
|
|
|
if (silgen) {
|
2006-05-04 20:29:13 +00:00
|
|
|
ast_channel_stop_silence_generator(chan, silgen);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-09-17 15:05:29 +00:00
|
|
|
}
|
2007-11-24 06:24:46 +00:00
|
|
|
|
|
|
|
/*!\note
|
|
|
|
* Instead of asking how much time passed (end - start), calculate the number
|
|
|
|
* of seconds of audio which actually went into the file. This fixes a
|
|
|
|
* problem where audio is stopped up on the network and never gets to us.
|
|
|
|
*
|
|
|
|
* Note that we still want to use the number of seconds passed for the max
|
|
|
|
* message, otherwise we could get a situation where this stream is never
|
|
|
|
* closed (which would create a resource leak).
|
|
|
|
*/
|
2008-02-18 20:53:25 +00:00
|
|
|
*duration = others[0] ? ast_tellstream(others[0]) / 8000 : 0;
|
Merged revisions 337120 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/10
................
r337120 | mjordan | 2011-09-20 17:49:36 -0500 (Tue, 20 Sep 2011) | 28 lines
Merged revisions 337118 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8
........
r337118 | mjordan | 2011-09-20 17:38:54 -0500 (Tue, 20 Sep 2011) | 21 lines
Fix for incorrect voicemail duration in external notifications
This patch fixes an issue where the voicemail duration was being reported
with a duration significantly less than the actual sound file duration.
Voicemails that contained mostly silence were reporting the duration of
only the sound in the file, as opposed to the duration of the file with
the silence. This patch fixes this by having two durations reported in
the __ast_play_and_record family of functions - the sound_duration and the
actual duration of the file. The sound_duration, which is optional, now
reports the duration of the sound in the file, while the actual full duration
of the file is reported in the duration parameter. This allows the voicemail
applications to use the sound_duration for minimum duration checking, while
reporting the full duration to external parties if the voicemail is kept.
(issue ASTERISK-2234)
(closes issue ASTERISK-16981)
Reported by: Mary Ciuciu, Byron Clark, Brad House, Karsten Wemheuer, KevinH
Tested by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/1443
........
................
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@337124 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2011-09-20 23:02:25 +00:00
|
|
|
if (sound_duration) {
|
|
|
|
*sound_duration = *duration;
|
|
|
|
}
|
2006-05-04 21:26:04 +00:00
|
|
|
|
2006-05-04 20:29:13 +00:00
|
|
|
if (!prepend) {
|
2009-06-23 14:54:21 +00:00
|
|
|
/* Reduce duration by a total silence amount */
|
2009-06-27 10:04:51 +00:00
|
|
|
if (olddspsilence <= dspsilence) {
|
|
|
|
totalsilence += dspsilence;
|
|
|
|
}
|
|
|
|
|
Merged revisions 337120 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/10
................
r337120 | mjordan | 2011-09-20 17:49:36 -0500 (Tue, 20 Sep 2011) | 28 lines
Merged revisions 337118 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8
........
r337118 | mjordan | 2011-09-20 17:38:54 -0500 (Tue, 20 Sep 2011) | 21 lines
Fix for incorrect voicemail duration in external notifications
This patch fixes an issue where the voicemail duration was being reported
with a duration significantly less than the actual sound file duration.
Voicemails that contained mostly silence were reporting the duration of
only the sound in the file, as opposed to the duration of the file with
the silence. This patch fixes this by having two durations reported in
the __ast_play_and_record family of functions - the sound_duration and the
actual duration of the file. The sound_duration, which is optional, now
reports the duration of the sound in the file, while the actual full duration
of the file is reported in the duration parameter. This allows the voicemail
applications to use the sound_duration for minimum duration checking, while
reporting the full duration to external parties if the voicemail is kept.
(issue ASTERISK-2234)
(closes issue ASTERISK-16981)
Reported by: Mary Ciuciu, Byron Clark, Brad House, Karsten Wemheuer, KevinH
Tested by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/1443
........
................
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@337124 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2011-09-20 23:02:25 +00:00
|
|
|
if (sound_duration) {
|
|
|
|
if (totalsilence > 0) {
|
|
|
|
*sound_duration -= (totalsilence - 200) / 1000;
|
|
|
|
}
|
|
|
|
if (*sound_duration < 0) {
|
|
|
|
*sound_duration = 0;
|
|
|
|
}
|
2010-09-11 17:35:15 +00:00
|
|
|
}
|
Merged revisions 337120 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/10
................
r337120 | mjordan | 2011-09-20 17:49:36 -0500 (Tue, 20 Sep 2011) | 28 lines
Merged revisions 337118 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8
........
r337118 | mjordan | 2011-09-20 17:38:54 -0500 (Tue, 20 Sep 2011) | 21 lines
Fix for incorrect voicemail duration in external notifications
This patch fixes an issue where the voicemail duration was being reported
with a duration significantly less than the actual sound file duration.
Voicemails that contained mostly silence were reporting the duration of
only the sound in the file, as opposed to the duration of the file with
the silence. This patch fixes this by having two durations reported in
the __ast_play_and_record family of functions - the sound_duration and the
actual duration of the file. The sound_duration, which is optional, now
reports the duration of the sound in the file, while the actual full duration
of the file is reported in the duration parameter. This allows the voicemail
applications to use the sound_duration for minimum duration checking, while
reporting the full duration to external parties if the voicemail is kept.
(issue ASTERISK-2234)
(closes issue ASTERISK-16981)
Reported by: Mary Ciuciu, Byron Clark, Brad House, Karsten Wemheuer, KevinH
Tested by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/1443
........
................
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@337124 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2011-09-20 23:02:25 +00:00
|
|
|
|
|
|
|
if (dspsilence > 0) {
|
|
|
|
*duration -= (dspsilence - 200) / 1000;
|
|
|
|
}
|
|
|
|
|
2009-06-23 14:54:21 +00:00
|
|
|
if (*duration < 0) {
|
|
|
|
*duration = 0;
|
|
|
|
}
|
Merged revisions 337120 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/10
................
r337120 | mjordan | 2011-09-20 17:49:36 -0500 (Tue, 20 Sep 2011) | 28 lines
Merged revisions 337118 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8
........
r337118 | mjordan | 2011-09-20 17:38:54 -0500 (Tue, 20 Sep 2011) | 21 lines
Fix for incorrect voicemail duration in external notifications
This patch fixes an issue where the voicemail duration was being reported
with a duration significantly less than the actual sound file duration.
Voicemails that contained mostly silence were reporting the duration of
only the sound in the file, as opposed to the duration of the file with
the silence. This patch fixes this by having two durations reported in
the __ast_play_and_record family of functions - the sound_duration and the
actual duration of the file. The sound_duration, which is optional, now
reports the duration of the sound in the file, while the actual full duration
of the file is reported in the duration parameter. This allows the voicemail
applications to use the sound_duration for minimum duration checking, while
reporting the full duration to external parties if the voicemail is kept.
(issue ASTERISK-2234)
(closes issue ASTERISK-16981)
Reported by: Mary Ciuciu, Byron Clark, Brad House, Karsten Wemheuer, KevinH
Tested by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/1443
........
................
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@337124 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2011-09-20 23:02:25 +00:00
|
|
|
|
2006-05-04 21:26:04 +00:00
|
|
|
for (x = 0; x < fmtcnt; x++) {
|
2009-03-04 20:48:42 +00:00
|
|
|
if (!others[x]) {
|
2004-09-17 15:05:29 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2007-11-15 00:01:22 +00:00
|
|
|
/*!\note
|
|
|
|
* If we ended with silence, trim all but the first 200ms of silence
|
|
|
|
* off the recording. However, if we ended with '#', we don't want
|
|
|
|
* to trim ANY part of the recording.
|
|
|
|
*/
|
2009-06-23 14:54:21 +00:00
|
|
|
if (res > 0 && dspsilence) {
|
2010-09-11 17:35:15 +00:00
|
|
|
/* rewind only the trailing silence */
|
2009-06-23 14:54:21 +00:00
|
|
|
ast_stream_rewind(others[x], dspsilence - 200);
|
2009-03-02 23:10:18 +00:00
|
|
|
}
|
2006-05-04 20:29:13 +00:00
|
|
|
ast_truncstream(others[x]);
|
|
|
|
ast_closestream(others[x]);
|
2004-09-17 15:05:29 +00:00
|
|
|
}
|
2014-11-02 08:13:52 +00:00
|
|
|
} else if (prepend && outmsg) {
|
2009-11-30 21:31:55 +00:00
|
|
|
struct ast_filestream *realfiles[AST_MAX_FORMATS];
|
2004-09-17 15:05:29 +00:00
|
|
|
struct ast_frame *fr;
|
2006-05-04 21:26:04 +00:00
|
|
|
|
|
|
|
for (x = 0; x < fmtcnt; x++) {
|
2004-09-17 15:05:29 +00:00
|
|
|
snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]);
|
|
|
|
realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0);
|
2014-11-02 08:13:52 +00:00
|
|
|
if (!others[x]) {
|
2004-09-17 15:05:29 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2014-11-02 08:13:52 +00:00
|
|
|
if (!realfiles[x]) {
|
2014-11-04 14:11:54 +00:00
|
|
|
ast_closestream(others[x]);
|
2014-11-02 08:13:52 +00:00
|
|
|
continue;
|
|
|
|
}
|
2007-11-15 00:01:22 +00:00
|
|
|
/*!\note Same logic as above. */
|
2009-06-23 14:54:21 +00:00
|
|
|
if (dspsilence) {
|
|
|
|
ast_stream_rewind(others[x], dspsilence - 200);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-09-17 15:05:29 +00:00
|
|
|
ast_truncstream(others[x]);
|
|
|
|
/* add the original file too */
|
|
|
|
while ((fr = ast_readframe(realfiles[x]))) {
|
2006-05-04 21:26:04 +00:00
|
|
|
ast_writestream(others[x], fr);
|
2006-05-04 20:29:13 +00:00
|
|
|
ast_frfree(fr);
|
2004-09-17 15:05:29 +00:00
|
|
|
}
|
|
|
|
ast_closestream(others[x]);
|
|
|
|
ast_closestream(realfiles[x]);
|
|
|
|
ast_filerename(prependfile, recordfile, sfmt[x]);
|
2007-07-26 15:49:18 +00:00
|
|
|
ast_verb(4, "Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x], prependfile, recordfile);
|
2004-09-17 15:05:29 +00:00
|
|
|
ast_filedelete(prependfile, sfmt[x]);
|
|
|
|
}
|
2014-11-02 08:13:52 +00:00
|
|
|
} else {
|
|
|
|
for (x = 0; x < fmtcnt; x++) {
|
|
|
|
if (!others[x]) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ast_closestream(others[x]);
|
|
|
|
}
|
2004-09-17 15:05:29 +00:00
|
|
|
}
|
2014-11-02 08:13:52 +00:00
|
|
|
|
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
|
|
|
if (rfmt && ast_set_read_format(chan, rfmt)) {
|
|
|
|
ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_format_get_name(rfmt), ast_channel_name(chan));
|
2004-09-17 15:05:29 +00:00
|
|
|
}
|
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
|
|
|
ao2_cleanup(rfmt);
|
2011-07-26 14:17:13 +00:00
|
|
|
if ((outmsg == 2) && (!skip_confirmation_sound)) {
|
2006-11-17 23:18:51 +00:00
|
|
|
ast_stream_and_wait(chan, "auth-thankyou", "");
|
2006-05-04 21:26:04 +00:00
|
|
|
}
|
2009-03-04 20:48:42 +00:00
|
|
|
if (sildet) {
|
2006-05-04 20:29:13 +00:00
|
|
|
ast_dsp_free(sildet);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-09-17 15:05:29 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2009-05-21 21:13:09 +00:00
|
|
|
static const char default_acceptdtmf[] = "#";
|
|
|
|
static const char default_canceldtmf[] = "";
|
2006-05-05 19:10:11 +00:00
|
|
|
|
2013-08-06 14:44:45 +00:00
|
|
|
int ast_play_and_record_full(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence, const char *path, const char *acceptdtmf, const char *canceldtmf, int skip_confirmation_sound, enum ast_record_if_exists if_exists)
|
2006-05-05 19:10:11 +00:00
|
|
|
{
|
2014-09-11 22:17:39 +00:00
|
|
|
return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, beep, silencethreshold, maxsilence, path, 0, S_OR(acceptdtmf, ""), S_OR(canceldtmf, default_canceldtmf), skip_confirmation_sound, if_exists);
|
2006-05-05 19:10:11 +00:00
|
|
|
}
|
|
|
|
|
Merged revisions 337120 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/10
................
r337120 | mjordan | 2011-09-20 17:49:36 -0500 (Tue, 20 Sep 2011) | 28 lines
Merged revisions 337118 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8
........
r337118 | mjordan | 2011-09-20 17:38:54 -0500 (Tue, 20 Sep 2011) | 21 lines
Fix for incorrect voicemail duration in external notifications
This patch fixes an issue where the voicemail duration was being reported
with a duration significantly less than the actual sound file duration.
Voicemails that contained mostly silence were reporting the duration of
only the sound in the file, as opposed to the duration of the file with
the silence. This patch fixes this by having two durations reported in
the __ast_play_and_record family of functions - the sound_duration and the
actual duration of the file. The sound_duration, which is optional, now
reports the duration of the sound in the file, while the actual full duration
of the file is reported in the duration parameter. This allows the voicemail
applications to use the sound_duration for minimum duration checking, while
reporting the full duration to external parties if the voicemail is kept.
(issue ASTERISK-2234)
(closes issue ASTERISK-16981)
Reported by: Mary Ciuciu, Byron Clark, Brad House, Karsten Wemheuer, KevinH
Tested by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/1443
........
................
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@337124 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2011-09-20 23:02:25 +00:00
|
|
|
int ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int *sound_duration, int silencethreshold, int maxsilence, const char *path)
|
2006-05-04 20:29:13 +00:00
|
|
|
{
|
2013-07-03 17:58:45 +00:00
|
|
|
return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, 0, silencethreshold, maxsilence, path, 0, default_acceptdtmf, default_canceldtmf, 0, AST_RECORD_IF_EXISTS_OVERWRITE);
|
2006-05-04 20:29:13 +00:00
|
|
|
}
|
|
|
|
|
Merged revisions 337120 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/10
................
r337120 | mjordan | 2011-09-20 17:49:36 -0500 (Tue, 20 Sep 2011) | 28 lines
Merged revisions 337118 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8
........
r337118 | mjordan | 2011-09-20 17:38:54 -0500 (Tue, 20 Sep 2011) | 21 lines
Fix for incorrect voicemail duration in external notifications
This patch fixes an issue where the voicemail duration was being reported
with a duration significantly less than the actual sound file duration.
Voicemails that contained mostly silence were reporting the duration of
only the sound in the file, as opposed to the duration of the file with
the silence. This patch fixes this by having two durations reported in
the __ast_play_and_record family of functions - the sound_duration and the
actual duration of the file. The sound_duration, which is optional, now
reports the duration of the sound in the file, while the actual full duration
of the file is reported in the duration parameter. This allows the voicemail
applications to use the sound_duration for minimum duration checking, while
reporting the full duration to external parties if the voicemail is kept.
(issue ASTERISK-2234)
(closes issue ASTERISK-16981)
Reported by: Mary Ciuciu, Byron Clark, Brad House, Karsten Wemheuer, KevinH
Tested by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/1443
........
................
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@337124 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2011-09-20 23:02:25 +00:00
|
|
|
int ast_play_and_prepend(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence)
|
2006-05-04 20:29:13 +00:00
|
|
|
{
|
2013-07-03 17:58:45 +00:00
|
|
|
return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, beep, silencethreshold, maxsilence, NULL, 1, default_acceptdtmf, default_canceldtmf, 1, AST_RECORD_IF_EXISTS_OVERWRITE);
|
2006-05-04 20:29:13 +00:00
|
|
|
}
|
|
|
|
|
2004-10-03 16:34:52 +00:00
|
|
|
/* Channel group core functions */
|
|
|
|
|
2005-12-03 19:25:33 +00:00
|
|
|
int ast_app_group_split_group(const char *data, char *group, int group_max, char *category, int category_max)
|
2004-10-03 16:34:52 +00:00
|
|
|
{
|
2007-06-06 17:10:52 +00:00
|
|
|
int res = 0;
|
2005-09-07 21:01:31 +00:00
|
|
|
char tmp[256];
|
2007-06-06 17:10:52 +00:00
|
|
|
char *grp = NULL, *cat = NULL;
|
2004-10-03 16:34:52 +00:00
|
|
|
|
2005-10-26 18:54:24 +00:00
|
|
|
if (!ast_strlen_zero(data)) {
|
2005-06-05 16:32:16 +00:00
|
|
|
ast_copy_string(tmp, data, sizeof(tmp));
|
2004-10-03 16:34:52 +00:00
|
|
|
grp = tmp;
|
2009-03-04 20:48:42 +00:00
|
|
|
if ((cat = strchr(tmp, '@'))) {
|
|
|
|
*cat++ = '\0';
|
2004-10-03 16:34:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (!ast_strlen_zero(grp)) {
|
2005-06-05 16:32:16 +00:00
|
|
|
ast_copy_string(group, grp, group_max);
|
2009-03-04 20:48:42 +00:00
|
|
|
} else {
|
2007-09-24 16:40:12 +00:00
|
|
|
*group = '\0';
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-10-03 16:34:52 +00:00
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (!ast_strlen_zero(cat)) {
|
2007-04-25 19:27:42 +00:00
|
|
|
ast_copy_string(category, cat, category_max);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-10-03 16:34:52 +00:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2005-12-03 19:25:33 +00:00
|
|
|
int ast_app_group_set_channel(struct ast_channel *chan, const char *data)
|
2004-10-03 16:34:52 +00:00
|
|
|
{
|
2007-04-25 19:27:42 +00:00
|
|
|
int res = 0;
|
|
|
|
char group[80] = "", category[80] = "";
|
|
|
|
struct ast_group_info *gi = NULL;
|
|
|
|
size_t len = 0;
|
2009-03-04 20:48:42 +00:00
|
|
|
|
|
|
|
if (ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category))) {
|
2007-04-25 19:27:42 +00:00
|
|
|
return -1;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
|
2007-04-25 19:27:42 +00:00
|
|
|
/* Calculate memory we will need if this is new */
|
|
|
|
len = sizeof(*gi) + strlen(group) + 1;
|
2009-03-04 20:48:42 +00:00
|
|
|
if (!ast_strlen_zero(category)) {
|
2007-04-25 19:27:42 +00:00
|
|
|
len += strlen(category) + 1;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
|
2007-06-13 18:23:12 +00:00
|
|
|
AST_RWLIST_WRLOCK(&groups);
|
2009-04-22 21:15:55 +00:00
|
|
|
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) {
|
2007-06-13 18:18:51 +00:00
|
|
|
if ((gi->chan == chan) && ((ast_strlen_zero(category) && ast_strlen_zero(gi->category)) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) {
|
2009-04-22 21:15:55 +00:00
|
|
|
AST_RWLIST_REMOVE_CURRENT(group_list);
|
2014-09-26 14:41:38 +00:00
|
|
|
ast_free(gi);
|
2007-04-25 19:27:42 +00:00
|
|
|
break;
|
2007-06-13 18:18:51 +00:00
|
|
|
}
|
2007-04-25 19:27:42 +00:00
|
|
|
}
|
2007-11-08 05:28:47 +00:00
|
|
|
AST_RWLIST_TRAVERSE_SAFE_END;
|
2007-06-13 18:18:51 +00:00
|
|
|
|
2007-09-25 14:18:09 +00:00
|
|
|
if (ast_strlen_zero(group)) {
|
|
|
|
/* Enable unsetting the group */
|
2014-09-26 14:41:38 +00:00
|
|
|
} else if ((gi = ast_calloc(1, len))) {
|
2007-04-25 19:27:42 +00:00
|
|
|
gi->chan = chan;
|
|
|
|
gi->group = (char *) gi + sizeof(*gi);
|
|
|
|
strcpy(gi->group, group);
|
|
|
|
if (!ast_strlen_zero(category)) {
|
|
|
|
gi->category = (char *) gi + sizeof(*gi) + strlen(group) + 1;
|
|
|
|
strcpy(gi->category, category);
|
|
|
|
}
|
2009-04-22 21:15:55 +00:00
|
|
|
AST_RWLIST_INSERT_TAIL(&groups, gi, group_list);
|
2007-04-25 19:27:42 +00:00
|
|
|
} else {
|
2004-10-03 16:34:52 +00:00
|
|
|
res = -1;
|
2007-04-25 19:27:42 +00:00
|
|
|
}
|
2009-03-04 20:48:42 +00:00
|
|
|
|
2007-06-13 18:23:12 +00:00
|
|
|
AST_RWLIST_UNLOCK(&groups);
|
2009-03-04 20:48:42 +00:00
|
|
|
|
2004-10-03 16:34:52 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2005-12-03 19:25:33 +00:00
|
|
|
int ast_app_group_get_count(const char *group, const char *category)
|
2004-10-03 16:34:52 +00:00
|
|
|
{
|
2007-04-25 19:27:42 +00:00
|
|
|
struct ast_group_info *gi = NULL;
|
2004-10-03 16:34:52 +00:00
|
|
|
int count = 0;
|
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (ast_strlen_zero(group)) {
|
2005-06-06 02:29:18 +00:00
|
|
|
return 0;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
|
2007-06-13 18:23:12 +00:00
|
|
|
AST_RWLIST_RDLOCK(&groups);
|
2009-04-22 21:15:55 +00:00
|
|
|
AST_RWLIST_TRAVERSE(&groups, gi, group_list) {
|
2009-03-04 20:48:42 +00:00
|
|
|
if (!strcasecmp(gi->group, group) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) {
|
2007-04-25 19:27:42 +00:00
|
|
|
count++;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-10-03 16:34:52 +00:00
|
|
|
}
|
2007-06-13 18:23:12 +00:00
|
|
|
AST_RWLIST_UNLOCK(&groups);
|
2004-10-03 16:34:52 +00:00
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2005-12-03 19:25:33 +00:00
|
|
|
int ast_app_group_match_get_count(const char *groupmatch, const char *category)
|
2004-10-03 16:34:52 +00:00
|
|
|
{
|
2007-04-25 19:27:42 +00:00
|
|
|
struct ast_group_info *gi = NULL;
|
2010-02-17 19:51:53 +00:00
|
|
|
regex_t regexbuf_group;
|
|
|
|
regex_t regexbuf_category;
|
2004-10-03 16:34:52 +00:00
|
|
|
int count = 0;
|
|
|
|
|
2010-03-13 22:21:18 +00:00
|
|
|
if (ast_strlen_zero(groupmatch)) {
|
|
|
|
ast_log(LOG_NOTICE, "groupmatch empty\n");
|
2004-10-03 16:34:52 +00:00
|
|
|
return 0;
|
2010-03-13 22:21:18 +00:00
|
|
|
}
|
2004-10-03 16:34:52 +00:00
|
|
|
|
|
|
|
/* if regex compilation fails, return zero matches */
|
2010-02-17 19:51:53 +00:00
|
|
|
if (regcomp(®exbuf_group, groupmatch, REG_EXTENDED | REG_NOSUB)) {
|
|
|
|
ast_log(LOG_ERROR, "Regex compile failed on: %s\n", groupmatch);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-03-13 22:21:18 +00:00
|
|
|
if (!ast_strlen_zero(category) && regcomp(®exbuf_category, category, REG_EXTENDED | REG_NOSUB)) {
|
2010-02-17 19:51:53 +00:00
|
|
|
ast_log(LOG_ERROR, "Regex compile failed on: %s\n", category);
|
2012-10-22 20:19:51 +00:00
|
|
|
regfree(®exbuf_group);
|
2004-10-03 16:34:52 +00:00
|
|
|
return 0;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-10-03 16:34:52 +00:00
|
|
|
|
2007-06-13 18:23:12 +00:00
|
|
|
AST_RWLIST_RDLOCK(&groups);
|
2009-04-22 21:15:55 +00:00
|
|
|
AST_RWLIST_TRAVERSE(&groups, gi, group_list) {
|
2010-02-17 19:51:53 +00:00
|
|
|
if (!regexec(®exbuf_group, gi->group, 0, NULL, 0) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !regexec(®exbuf_category, gi->category, 0, NULL, 0)))) {
|
2004-10-03 16:34:52 +00:00
|
|
|
count++;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2004-10-03 16:34:52 +00:00
|
|
|
}
|
2007-06-13 18:23:12 +00:00
|
|
|
AST_RWLIST_UNLOCK(&groups);
|
2004-10-03 16:34:52 +00:00
|
|
|
|
2010-02-17 19:51:53 +00:00
|
|
|
regfree(®exbuf_group);
|
2010-03-13 22:21:18 +00:00
|
|
|
if (!ast_strlen_zero(category)) {
|
|
|
|
regfree(®exbuf_category);
|
|
|
|
}
|
2004-10-03 16:34:52 +00:00
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
2004-12-29 13:06:53 +00:00
|
|
|
|
2007-05-07 21:47:08 +00:00
|
|
|
int ast_app_group_update(struct ast_channel *old, struct ast_channel *new)
|
|
|
|
{
|
|
|
|
struct ast_group_info *gi = NULL;
|
|
|
|
|
2007-06-13 18:23:12 +00:00
|
|
|
AST_RWLIST_WRLOCK(&groups);
|
2009-04-22 21:15:55 +00:00
|
|
|
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) {
|
2008-12-09 14:57:39 +00:00
|
|
|
if (gi->chan == old) {
|
2007-05-07 21:47:08 +00:00
|
|
|
gi->chan = new;
|
2008-12-09 14:57:39 +00:00
|
|
|
} else if (gi->chan == new) {
|
2009-04-22 21:15:55 +00:00
|
|
|
AST_RWLIST_REMOVE_CURRENT(group_list);
|
2008-12-09 14:57:39 +00:00
|
|
|
ast_free(gi);
|
|
|
|
}
|
2007-05-07 21:47:08 +00:00
|
|
|
}
|
2009-04-10 03:55:27 +00:00
|
|
|
AST_RWLIST_TRAVERSE_SAFE_END;
|
2007-06-13 18:23:12 +00:00
|
|
|
AST_RWLIST_UNLOCK(&groups);
|
2007-05-07 21:47:08 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-04-25 19:27:42 +00:00
|
|
|
int ast_app_group_discard(struct ast_channel *chan)
|
|
|
|
{
|
|
|
|
struct ast_group_info *gi = NULL;
|
2009-03-04 20:48:42 +00:00
|
|
|
|
2007-06-13 18:23:12 +00:00
|
|
|
AST_RWLIST_WRLOCK(&groups);
|
2009-04-22 21:15:55 +00:00
|
|
|
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) {
|
2007-04-25 19:27:42 +00:00
|
|
|
if (gi->chan == chan) {
|
2009-04-22 21:15:55 +00:00
|
|
|
AST_RWLIST_REMOVE_CURRENT(group_list);
|
2007-06-06 21:20:11 +00:00
|
|
|
ast_free(gi);
|
2007-04-25 19:27:42 +00:00
|
|
|
}
|
|
|
|
}
|
2008-03-04 23:04:29 +00:00
|
|
|
AST_RWLIST_TRAVERSE_SAFE_END;
|
2007-06-13 18:23:12 +00:00
|
|
|
AST_RWLIST_UNLOCK(&groups);
|
2009-03-04 20:48:42 +00:00
|
|
|
|
2007-04-25 19:27:42 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-06-13 18:23:12 +00:00
|
|
|
int ast_app_group_list_wrlock(void)
|
2007-04-25 19:27:42 +00:00
|
|
|
{
|
2007-06-13 18:23:12 +00:00
|
|
|
return AST_RWLIST_WRLOCK(&groups);
|
|
|
|
}
|
|
|
|
|
|
|
|
int ast_app_group_list_rdlock(void)
|
|
|
|
{
|
|
|
|
return AST_RWLIST_RDLOCK(&groups);
|
2007-04-25 19:27:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct ast_group_info *ast_app_group_list_head(void)
|
|
|
|
{
|
2007-06-13 18:23:12 +00:00
|
|
|
return AST_RWLIST_FIRST(&groups);
|
2007-04-25 19:27:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int ast_app_group_list_unlock(void)
|
|
|
|
{
|
2007-06-13 18:23:12 +00:00
|
|
|
return AST_RWLIST_UNLOCK(&groups);
|
2007-04-25 19:27:42 +00:00
|
|
|
}
|
|
|
|
|
2009-08-06 21:29:26 +00:00
|
|
|
unsigned int __ast_app_separate_args(char *buf, char delim, int remove_chars, char **array, int arraylen)
|
2004-12-29 13:06:53 +00:00
|
|
|
{
|
2005-08-06 16:52:56 +00:00
|
|
|
int argc;
|
2008-06-20 22:04:37 +00:00
|
|
|
char *scan, *wasdelim = NULL;
|
2010-07-08 22:08:07 +00:00
|
|
|
int paren = 0, quote = 0, bracket = 0;
|
2005-05-04 03:43:10 +00:00
|
|
|
|
2010-05-26 19:46:49 +00:00
|
|
|
if (!array || !arraylen) {
|
2004-12-29 13:06:53 +00:00
|
|
|
return 0;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-05-04 03:43:10 +00:00
|
|
|
|
|
|
|
memset(array, 0, arraylen * sizeof(*array));
|
|
|
|
|
2010-05-26 19:46:49 +00:00
|
|
|
if (!buf) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-05-04 03:43:10 +00:00
|
|
|
scan = buf;
|
2005-08-06 16:52:56 +00:00
|
|
|
|
|
|
|
for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
|
|
|
|
array[argc] = scan;
|
|
|
|
for (; *scan; scan++) {
|
2009-03-04 20:48:42 +00:00
|
|
|
if (*scan == '(') {
|
2005-08-06 16:52:56 +00:00
|
|
|
paren++;
|
2009-03-04 20:48:42 +00:00
|
|
|
} else if (*scan == ')') {
|
|
|
|
if (paren) {
|
2005-08-06 16:52:56 +00:00
|
|
|
paren--;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2010-07-08 22:08:07 +00:00
|
|
|
} else if (*scan == '[') {
|
|
|
|
bracket++;
|
|
|
|
} else if (*scan == ']') {
|
|
|
|
if (bracket) {
|
|
|
|
bracket--;
|
|
|
|
}
|
2006-08-14 04:25:13 +00:00
|
|
|
} else if (*scan == '"' && delim != '"') {
|
2006-01-15 18:02:46 +00:00
|
|
|
quote = quote ? 0 : 1;
|
2009-08-06 21:29:26 +00:00
|
|
|
if (remove_chars) {
|
|
|
|
/* Remove quote character from argument */
|
|
|
|
memmove(scan, scan + 1, strlen(scan));
|
|
|
|
scan--;
|
|
|
|
}
|
2006-01-15 18:02:46 +00:00
|
|
|
} else if (*scan == '\\') {
|
2009-08-06 21:29:26 +00:00
|
|
|
if (remove_chars) {
|
|
|
|
/* Literal character, don't parse */
|
|
|
|
memmove(scan, scan + 1, strlen(scan));
|
|
|
|
} else {
|
|
|
|
scan++;
|
|
|
|
}
|
2010-07-08 22:08:07 +00:00
|
|
|
} else if ((*scan == delim) && !paren && !quote && !bracket) {
|
2008-06-20 22:04:37 +00:00
|
|
|
wasdelim = scan;
|
2005-08-06 16:52:56 +00:00
|
|
|
*scan++ = '\0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-12-29 13:24:10 +00:00
|
|
|
}
|
2005-05-04 03:43:10 +00:00
|
|
|
|
2008-06-20 22:04:37 +00:00
|
|
|
/* If the last character in the original string was the delimiter, then
|
|
|
|
* there is one additional argument. */
|
|
|
|
if (*scan || (scan > buf && (scan - 1) == wasdelim)) {
|
2005-08-06 16:52:56 +00:00
|
|
|
array[argc++] = scan;
|
2008-06-20 22:04:37 +00:00
|
|
|
}
|
2005-05-04 03:43:10 +00:00
|
|
|
|
2005-08-06 16:52:56 +00:00
|
|
|
return argc;
|
2004-12-29 13:06:53 +00:00
|
|
|
}
|
2005-01-07 07:23:31 +00:00
|
|
|
|
2007-08-28 16:28:26 +00:00
|
|
|
static enum AST_LOCK_RESULT ast_lock_path_lockfile(const char *path)
|
2005-01-23 09:05:01 +00:00
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
char *fs;
|
|
|
|
int res;
|
|
|
|
int fd;
|
2006-03-28 14:30:31 +00:00
|
|
|
int lp = strlen(path);
|
2005-01-23 09:05:01 +00:00
|
|
|
time_t start;
|
2005-07-13 19:27:09 +00:00
|
|
|
|
2012-07-31 20:21:43 +00:00
|
|
|
s = ast_alloca(lp + 10);
|
|
|
|
fs = ast_alloca(lp + 20);
|
2005-07-13 19:27:09 +00:00
|
|
|
|
2014-05-09 22:49:26 +00:00
|
|
|
snprintf(fs, strlen(path) + 19, "%s/.lock-%08lx", path, (unsigned long)ast_random());
|
2006-12-21 19:44:20 +00:00
|
|
|
fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, AST_FILE_MODE);
|
2005-01-23 09:05:01 +00:00
|
|
|
if (fd < 0) {
|
2006-07-10 17:42:12 +00:00
|
|
|
ast_log(LOG_ERROR, "Unable to create lock file '%s': %s\n", path, strerror(errno));
|
2005-07-13 19:27:09 +00:00
|
|
|
return AST_LOCK_PATH_NOT_FOUND;
|
2005-01-23 09:05:01 +00:00
|
|
|
}
|
|
|
|
close(fd);
|
2005-07-13 19:27:09 +00:00
|
|
|
|
|
|
|
snprintf(s, strlen(path) + 9, "%s/.lock", path);
|
2006-05-22 02:51:04 +00:00
|
|
|
start = time(NULL);
|
2009-03-04 20:48:42 +00:00
|
|
|
while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5)) {
|
|
|
|
sched_yield();
|
|
|
|
}
|
2006-07-13 15:20:02 +00:00
|
|
|
|
|
|
|
unlink(fs);
|
|
|
|
|
2005-07-13 19:27:09 +00:00
|
|
|
if (res) {
|
2005-01-23 09:05:01 +00:00
|
|
|
ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
|
2005-07-13 19:27:09 +00:00
|
|
|
return AST_LOCK_TIMEOUT;
|
|
|
|
} else {
|
2007-06-14 19:39:12 +00:00
|
|
|
ast_debug(1, "Locked path '%s'\n", path);
|
2005-07-13 19:27:09 +00:00
|
|
|
return AST_LOCK_SUCCESS;
|
2005-01-23 09:05:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-28 16:28:26 +00:00
|
|
|
static int ast_unlock_path_lockfile(const char *path)
|
2005-01-23 09:05:01 +00:00
|
|
|
{
|
|
|
|
char *s;
|
2006-07-13 15:20:02 +00:00
|
|
|
int res;
|
|
|
|
|
2012-07-31 20:21:43 +00:00
|
|
|
s = ast_alloca(strlen(path) + 10);
|
2006-07-13 15:20:02 +00:00
|
|
|
|
2005-01-23 09:05:01 +00:00
|
|
|
snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
|
2006-07-13 15:20:02 +00:00
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if ((res = unlink(s))) {
|
2006-07-13 15:20:02 +00:00
|
|
|
ast_log(LOG_ERROR, "Could not unlock path '%s': %s\n", path, strerror(errno));
|
2009-03-04 20:48:42 +00:00
|
|
|
} else {
|
2007-06-14 19:39:12 +00:00
|
|
|
ast_debug(1, "Unlocked path '%s'\n", path);
|
2006-10-03 15:53:07 +00:00
|
|
|
}
|
2006-07-13 15:20:02 +00:00
|
|
|
|
|
|
|
return res;
|
2005-01-23 09:05:01 +00:00
|
|
|
}
|
|
|
|
|
2007-08-28 16:28:26 +00:00
|
|
|
struct path_lock {
|
|
|
|
AST_LIST_ENTRY(path_lock) le;
|
|
|
|
int fd;
|
|
|
|
char *path;
|
|
|
|
};
|
|
|
|
|
|
|
|
static AST_LIST_HEAD_STATIC(path_lock_list, path_lock);
|
|
|
|
|
|
|
|
static void path_lock_destroy(struct path_lock *obj)
|
|
|
|
{
|
2009-03-04 20:48:42 +00:00
|
|
|
if (obj->fd >= 0) {
|
2007-08-28 16:28:26 +00:00
|
|
|
close(obj->fd);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
if (obj->path) {
|
2014-09-26 14:41:38 +00:00
|
|
|
ast_free(obj->path);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2014-09-26 14:41:38 +00:00
|
|
|
ast_free(obj);
|
2007-08-28 16:28:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static enum AST_LOCK_RESULT ast_lock_path_flock(const char *path)
|
|
|
|
{
|
|
|
|
char *fs;
|
|
|
|
int res;
|
|
|
|
int fd;
|
|
|
|
time_t start;
|
|
|
|
struct path_lock *pl;
|
|
|
|
struct stat st, ost;
|
|
|
|
|
2012-07-31 20:21:43 +00:00
|
|
|
fs = ast_alloca(strlen(path) + 20);
|
2007-08-28 16:28:26 +00:00
|
|
|
|
|
|
|
snprintf(fs, strlen(path) + 19, "%s/lock", path);
|
|
|
|
if (lstat(fs, &st) == 0) {
|
|
|
|
if ((st.st_mode & S_IFMT) == S_IFLNK) {
|
|
|
|
ast_log(LOG_WARNING, "Unable to create lock file "
|
|
|
|
"'%s': it's already a symbolic link\n",
|
|
|
|
fs);
|
|
|
|
return AST_LOCK_FAILURE;
|
|
|
|
}
|
|
|
|
if (st.st_nlink > 1) {
|
|
|
|
ast_log(LOG_WARNING, "Unable to create lock file "
|
|
|
|
"'%s': %u hard links exist\n",
|
|
|
|
fs, (unsigned int) st.st_nlink);
|
|
|
|
return AST_LOCK_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
2009-03-04 20:48:42 +00:00
|
|
|
if ((fd = open(fs, O_WRONLY | O_CREAT, 0600)) < 0) {
|
2007-08-28 16:28:26 +00:00
|
|
|
ast_log(LOG_WARNING, "Unable to create lock file '%s': %s\n",
|
|
|
|
fs, strerror(errno));
|
|
|
|
return AST_LOCK_PATH_NOT_FOUND;
|
|
|
|
}
|
2009-03-04 20:48:42 +00:00
|
|
|
if (!(pl = ast_calloc(1, sizeof(*pl)))) {
|
2007-08-28 16:28:26 +00:00
|
|
|
/* We don't unlink the lock file here, on the possibility that
|
|
|
|
* someone else created it - better to leave a little mess
|
2007-09-20 19:22:10 +00:00
|
|
|
* than create a big one by destroying someone else's lock
|
2007-08-28 16:28:26 +00:00
|
|
|
* and causing something to be corrupted.
|
|
|
|
*/
|
|
|
|
close(fd);
|
|
|
|
return AST_LOCK_FAILURE;
|
|
|
|
}
|
|
|
|
pl->fd = fd;
|
2014-09-26 14:41:38 +00:00
|
|
|
pl->path = ast_strdup(path);
|
2007-08-28 16:28:26 +00:00
|
|
|
|
|
|
|
time(&start);
|
2009-03-04 20:48:42 +00:00
|
|
|
while (
|
2007-09-12 16:24:45 +00:00
|
|
|
#ifdef SOLARIS
|
2009-03-04 20:48:42 +00:00
|
|
|
((res = fcntl(pl->fd, F_SETLK, fcntl(pl->fd, F_GETFL) | O_NONBLOCK)) < 0) &&
|
2007-09-12 16:24:45 +00:00
|
|
|
#else
|
2009-03-04 20:48:42 +00:00
|
|
|
((res = flock(pl->fd, LOCK_EX | LOCK_NB)) < 0) &&
|
2007-09-12 16:24:45 +00:00
|
|
|
#endif
|
2009-03-04 20:48:42 +00:00
|
|
|
(errno == EWOULDBLOCK) &&
|
2007-09-12 16:24:45 +00:00
|
|
|
(time(NULL) - start < 5))
|
2007-08-28 16:28:26 +00:00
|
|
|
usleep(1000);
|
|
|
|
if (res) {
|
|
|
|
ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n",
|
|
|
|
path, strerror(errno));
|
|
|
|
/* No unlinking of lock done, since we tried and failed to
|
|
|
|
* flock() it.
|
|
|
|
*/
|
|
|
|
path_lock_destroy(pl);
|
|
|
|
return AST_LOCK_TIMEOUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for the race where the file is recreated or deleted out from
|
|
|
|
* underneath us.
|
|
|
|
*/
|
|
|
|
if (lstat(fs, &st) != 0 && fstat(pl->fd, &ost) != 0 &&
|
|
|
|
st.st_dev != ost.st_dev &&
|
|
|
|
st.st_ino != ost.st_ino) {
|
|
|
|
ast_log(LOG_WARNING, "Unable to create lock file '%s': "
|
|
|
|
"file changed underneath us\n", fs);
|
|
|
|
path_lock_destroy(pl);
|
|
|
|
return AST_LOCK_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Success: file created, flocked, and is the one we started with */
|
|
|
|
AST_LIST_LOCK(&path_lock_list);
|
|
|
|
AST_LIST_INSERT_TAIL(&path_lock_list, pl, le);
|
|
|
|
AST_LIST_UNLOCK(&path_lock_list);
|
|
|
|
|
|
|
|
ast_debug(1, "Locked path '%s'\n", path);
|
|
|
|
|
|
|
|
return AST_LOCK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ast_unlock_path_flock(const char *path)
|
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
struct path_lock *p;
|
|
|
|
|
2012-07-31 20:21:43 +00:00
|
|
|
s = ast_alloca(strlen(path) + 20);
|
2007-08-28 16:28:26 +00:00
|
|
|
|
|
|
|
AST_LIST_LOCK(&path_lock_list);
|
|
|
|
AST_LIST_TRAVERSE_SAFE_BEGIN(&path_lock_list, p, le) {
|
|
|
|
if (!strcmp(p->path, path)) {
|
2007-11-08 05:28:47 +00:00
|
|
|
AST_LIST_REMOVE_CURRENT(le);
|
2007-08-28 16:28:26 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
AST_LIST_TRAVERSE_SAFE_END;
|
|
|
|
AST_LIST_UNLOCK(&path_lock_list);
|
|
|
|
|
|
|
|
if (p) {
|
|
|
|
snprintf(s, strlen(path) + 19, "%s/lock", path);
|
|
|
|
unlink(s);
|
|
|
|
path_lock_destroy(p);
|
2011-02-04 16:55:39 +00:00
|
|
|
ast_debug(1, "Unlocked path '%s'\n", path);
|
2009-03-04 20:48:42 +00:00
|
|
|
} else {
|
2011-02-04 16:55:39 +00:00
|
|
|
ast_debug(1, "Failed to unlock path '%s': "
|
2007-08-28 16:28:26 +00:00
|
|
|
"lock not found\n", path);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2007-08-28 16:28:26 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ast_set_lock_type(enum AST_LOCK_TYPE type)
|
|
|
|
{
|
|
|
|
ast_lock_type = type;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum AST_LOCK_RESULT ast_lock_path(const char *path)
|
|
|
|
{
|
|
|
|
enum AST_LOCK_RESULT r = AST_LOCK_FAILURE;
|
|
|
|
|
|
|
|
switch (ast_lock_type) {
|
|
|
|
case AST_LOCK_TYPE_LOCKFILE:
|
|
|
|
r = ast_lock_path_lockfile(path);
|
|
|
|
break;
|
|
|
|
case AST_LOCK_TYPE_FLOCK:
|
|
|
|
r = ast_lock_path_flock(path);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ast_unlock_path(const char *path)
|
|
|
|
{
|
|
|
|
int r = 0;
|
|
|
|
|
|
|
|
switch (ast_lock_type) {
|
|
|
|
case AST_LOCK_TYPE_LOCKFILE:
|
|
|
|
r = ast_unlock_path_lockfile(path);
|
|
|
|
break;
|
|
|
|
case AST_LOCK_TYPE_FLOCK:
|
|
|
|
r = ast_unlock_path_flock(path);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2012-03-22 19:51:16 +00:00
|
|
|
int ast_record_review(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, const char *path)
|
2005-01-07 07:23:31 +00:00
|
|
|
{
|
2009-03-04 20:48:42 +00:00
|
|
|
int silencethreshold;
|
2007-06-06 18:55:45 +00:00
|
|
|
int maxsilence = 0;
|
2005-01-07 07:23:31 +00:00
|
|
|
int res = 0;
|
|
|
|
int cmd = 0;
|
|
|
|
int max_attempts = 3;
|
|
|
|
int attempts = 0;
|
|
|
|
int recorded = 0;
|
|
|
|
int message_exists = 0;
|
|
|
|
/* Note that urgent and private are for flagging messages as such in the future */
|
|
|
|
|
|
|
|
/* barf if no pointer passed to store duration in */
|
2007-06-06 19:03:14 +00:00
|
|
|
if (!duration) {
|
2005-01-07 07:23:31 +00:00
|
|
|
ast_log(LOG_WARNING, "Error ast_record_review called without duration pointer\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd = '3'; /* Want to start by recording */
|
|
|
|
|
2008-03-05 16:23:44 +00:00
|
|
|
silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
|
|
|
|
|
2005-01-07 07:23:31 +00:00
|
|
|
while ((cmd >= 0) && (cmd != 't')) {
|
|
|
|
switch (cmd) {
|
|
|
|
case '1':
|
|
|
|
if (!message_exists) {
|
|
|
|
/* In this case, 1 is to record a message */
|
|
|
|
cmd = '3';
|
|
|
|
break;
|
|
|
|
} else {
|
2006-11-17 23:18:51 +00:00
|
|
|
ast_stream_and_wait(chan, "vm-msgsaved", "");
|
2005-01-07 07:23:31 +00:00
|
|
|
cmd = 't';
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
case '2':
|
|
|
|
/* Review */
|
2007-07-26 15:49:18 +00:00
|
|
|
ast_verb(3, "Reviewing the recording\n");
|
2006-11-17 23:18:51 +00:00
|
|
|
cmd = ast_stream_and_wait(chan, recordfile, AST_DIGIT_ANY);
|
2005-01-07 07:23:31 +00:00
|
|
|
break;
|
|
|
|
case '3':
|
|
|
|
message_exists = 0;
|
|
|
|
/* Record */
|
2009-03-04 20:48:42 +00:00
|
|
|
ast_verb(3, "R%secording\n", recorded == 1 ? "e-r" : "");
|
2005-01-07 07:23:31 +00:00
|
|
|
recorded = 1;
|
Merged revisions 337120 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/10
................
r337120 | mjordan | 2011-09-20 17:49:36 -0500 (Tue, 20 Sep 2011) | 28 lines
Merged revisions 337118 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8
........
r337118 | mjordan | 2011-09-20 17:38:54 -0500 (Tue, 20 Sep 2011) | 21 lines
Fix for incorrect voicemail duration in external notifications
This patch fixes an issue where the voicemail duration was being reported
with a duration significantly less than the actual sound file duration.
Voicemails that contained mostly silence were reporting the duration of
only the sound in the file, as opposed to the duration of the file with
the silence. This patch fixes this by having two durations reported in
the __ast_play_and_record family of functions - the sound_duration and the
actual duration of the file. The sound_duration, which is optional, now
reports the duration of the sound in the file, while the actual full duration
of the file is reported in the duration parameter. This allows the voicemail
applications to use the sound_duration for minimum duration checking, while
reporting the full duration to external parties if the voicemail is kept.
(issue ASTERISK-2234)
(closes issue ASTERISK-16981)
Reported by: Mary Ciuciu, Byron Clark, Brad House, Karsten Wemheuer, KevinH
Tested by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/1443
........
................
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@337124 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2011-09-20 23:02:25 +00:00
|
|
|
if ((cmd = ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, NULL, silencethreshold, maxsilence, path)) == -1) {
|
2009-03-04 20:48:42 +00:00
|
|
|
/* User has hung up, no options to give */
|
2005-01-07 07:23:31 +00:00
|
|
|
return cmd;
|
|
|
|
}
|
|
|
|
if (cmd == '0') {
|
|
|
|
break;
|
|
|
|
} else if (cmd == '*') {
|
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
} else {
|
2005-01-07 07:23:31 +00:00
|
|
|
/* If all is well, a message exists */
|
|
|
|
message_exists = 1;
|
|
|
|
cmd = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '4':
|
|
|
|
case '5':
|
|
|
|
case '6':
|
|
|
|
case '7':
|
|
|
|
case '8':
|
|
|
|
case '9':
|
|
|
|
case '*':
|
|
|
|
case '#':
|
|
|
|
cmd = ast_play_and_wait(chan, "vm-sorry");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (message_exists) {
|
|
|
|
cmd = ast_play_and_wait(chan, "vm-review");
|
2009-03-04 20:48:42 +00:00
|
|
|
} else {
|
|
|
|
if (!(cmd = ast_play_and_wait(chan, "vm-torerecord"))) {
|
2005-01-07 07:23:31 +00:00
|
|
|
cmd = ast_waitfordigit(chan, 600);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-01-07 07:23:31 +00:00
|
|
|
}
|
2009-03-04 20:48:42 +00:00
|
|
|
|
|
|
|
if (!cmd) {
|
2005-01-07 07:23:31 +00:00
|
|
|
cmd = ast_waitfordigit(chan, 6000);
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-01-07 07:23:31 +00:00
|
|
|
if (!cmd) {
|
|
|
|
attempts++;
|
|
|
|
}
|
|
|
|
if (attempts > max_attempts) {
|
|
|
|
cmd = 't';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-03-04 20:48:42 +00:00
|
|
|
if (cmd == 't') {
|
2005-01-07 07:23:31 +00:00
|
|
|
cmd = 0;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-01-07 07:23:31 +00:00
|
|
|
return cmd;
|
|
|
|
}
|
2005-02-17 14:57:36 +00:00
|
|
|
|
|
|
|
#define RES_UPONE (1 << 16)
|
|
|
|
#define RES_EXIT (1 << 17)
|
|
|
|
#define RES_REPEAT (1 << 18)
|
|
|
|
#define RES_RESTART ((1 << 19) | RES_REPEAT)
|
|
|
|
|
|
|
|
static int ast_ivr_menu_run_internal(struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata);
|
2006-07-10 17:42:12 +00:00
|
|
|
|
2005-02-17 14:57:36 +00:00
|
|
|
static int ivr_dispatch(struct ast_channel *chan, struct ast_ivr_option *option, char *exten, void *cbdata)
|
|
|
|
{
|
|
|
|
int res;
|
2005-03-05 21:06:26 +00:00
|
|
|
int (*ivr_func)(struct ast_channel *, void *);
|
|
|
|
char *c;
|
|
|
|
char *n;
|
2009-03-04 20:48:42 +00:00
|
|
|
|
2007-01-23 00:11:32 +00:00
|
|
|
switch (option->action) {
|
2005-02-17 14:57:36 +00:00
|
|
|
case AST_ACTION_UPONE:
|
|
|
|
return RES_UPONE;
|
|
|
|
case AST_ACTION_EXIT:
|
|
|
|
return RES_EXIT | (((unsigned long)(option->adata)) & 0xffff);
|
|
|
|
case AST_ACTION_REPEAT:
|
|
|
|
return RES_REPEAT | (((unsigned long)(option->adata)) & 0xffff);
|
|
|
|
case AST_ACTION_RESTART:
|
|
|
|
return RES_RESTART ;
|
|
|
|
case AST_ACTION_NOOP:
|
|
|
|
return 0;
|
|
|
|
case AST_ACTION_BACKGROUND:
|
2006-11-17 23:18:51 +00:00
|
|
|
res = ast_stream_and_wait(chan, (char *)option->adata, AST_DIGIT_ANY);
|
2006-04-21 20:39:50 +00:00
|
|
|
if (res < 0) {
|
2005-02-17 14:57:36 +00:00
|
|
|
ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
|
|
|
|
res = 0;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
case AST_ACTION_PLAYBACK:
|
2006-11-17 23:18:51 +00:00
|
|
|
res = ast_stream_and_wait(chan, (char *)option->adata, "");
|
2006-04-21 20:39:50 +00:00
|
|
|
if (res < 0) {
|
2005-02-17 14:57:36 +00:00
|
|
|
ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
|
|
|
|
res = 0;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
case AST_ACTION_MENU:
|
2009-03-04 20:48:42 +00:00
|
|
|
if ((res = ast_ivr_menu_run_internal(chan, (struct ast_ivr_menu *)option->adata, cbdata)) == -2) {
|
|
|
|
/* Do not pass entry errors back up, treat as though it was an "UPONE" */
|
2005-03-05 21:06:26 +00:00
|
|
|
res = 0;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-03-05 21:06:26 +00:00
|
|
|
return res;
|
|
|
|
case AST_ACTION_WAITOPTION:
|
2012-02-20 23:43:27 +00:00
|
|
|
if (!(res = ast_waitfordigit(chan, ast_channel_pbx(chan) ? ast_channel_pbx(chan)->rtimeoutms : 10000))) {
|
2005-03-05 21:06:26 +00:00
|
|
|
return 't';
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-02-17 14:57:36 +00:00
|
|
|
return res;
|
|
|
|
case AST_ACTION_CALLBACK:
|
2005-03-05 21:06:26 +00:00
|
|
|
ivr_func = option->adata;
|
|
|
|
res = ivr_func(chan, cbdata);
|
|
|
|
return res;
|
2005-02-17 14:57:36 +00:00
|
|
|
case AST_ACTION_TRANSFER:
|
2005-03-05 21:06:26 +00:00
|
|
|
res = ast_parseable_goto(chan, option->adata);
|
2005-02-17 14:57:36 +00:00
|
|
|
return 0;
|
2005-03-05 21:06:26 +00:00
|
|
|
case AST_ACTION_PLAYLIST:
|
|
|
|
case AST_ACTION_BACKLIST:
|
|
|
|
res = 0;
|
|
|
|
c = ast_strdupa(option->adata);
|
2006-05-10 13:22:15 +00:00
|
|
|
while ((n = strsep(&c, ";"))) {
|
2006-11-17 23:18:51 +00:00
|
|
|
if ((res = ast_stream_and_wait(chan, n,
|
2009-03-04 20:48:42 +00:00
|
|
|
(option->action == AST_ACTION_BACKLIST) ? AST_DIGIT_ANY : ""))) {
|
2006-05-10 13:22:15 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-03-05 21:06:26 +00:00
|
|
|
}
|
2006-05-10 13:22:15 +00:00
|
|
|
ast_stopstream(chan);
|
2005-03-05 21:06:26 +00:00
|
|
|
return res;
|
2005-02-17 14:57:36 +00:00
|
|
|
default:
|
2014-05-09 22:49:26 +00:00
|
|
|
ast_log(LOG_NOTICE, "Unknown dispatch function %u, ignoring!\n", option->action);
|
2005-02-17 14:57:36 +00:00
|
|
|
return 0;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-02-17 14:57:36 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int option_exists(struct ast_ivr_menu *menu, char *option)
|
|
|
|
{
|
|
|
|
int x;
|
2009-03-04 20:48:42 +00:00
|
|
|
for (x = 0; menu->options[x].option; x++) {
|
|
|
|
if (!strcasecmp(menu->options[x].option, option)) {
|
2005-02-17 14:57:36 +00:00
|
|
|
return x;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
}
|
2005-02-17 14:57:36 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int option_matchmore(struct ast_ivr_menu *menu, char *option)
|
|
|
|
{
|
|
|
|
int x;
|
2009-03-04 20:48:42 +00:00
|
|
|
for (x = 0; menu->options[x].option; x++) {
|
|
|
|
if ((!strncasecmp(menu->options[x].option, option, strlen(option))) &&
|
|
|
|
(menu->options[x].option[strlen(option)])) {
|
2005-02-17 14:57:36 +00:00
|
|
|
return x;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
}
|
2005-02-17 14:57:36 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int read_newoption(struct ast_channel *chan, struct ast_ivr_menu *menu, char *exten, int maxexten)
|
|
|
|
{
|
2008-02-11 18:27:47 +00:00
|
|
|
int res = 0;
|
2005-02-17 14:57:36 +00:00
|
|
|
int ms;
|
2006-07-10 17:42:12 +00:00
|
|
|
while (option_matchmore(menu, exten)) {
|
2012-02-20 23:43:27 +00:00
|
|
|
ms = ast_channel_pbx(chan) ? ast_channel_pbx(chan)->dtimeoutms : 5000;
|
2009-03-04 20:48:42 +00:00
|
|
|
if (strlen(exten) >= maxexten - 1) {
|
2005-02-17 14:57:36 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
if ((res = ast_waitfordigit(chan, ms)) < 1) {
|
2005-02-17 14:57:36 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-02-17 14:57:36 +00:00
|
|
|
exten[strlen(exten) + 1] = '\0';
|
|
|
|
exten[strlen(exten)] = res;
|
|
|
|
}
|
|
|
|
return res > 0 ? 0 : res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ast_ivr_menu_run_internal(struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata)
|
|
|
|
{
|
|
|
|
/* Execute an IVR menu structure */
|
2008-02-11 18:27:47 +00:00
|
|
|
int res = 0;
|
2005-02-17 14:57:36 +00:00
|
|
|
int pos = 0;
|
|
|
|
int retries = 0;
|
|
|
|
char exten[AST_MAX_EXTENSION] = "s";
|
|
|
|
if (option_exists(menu, "s") < 0) {
|
|
|
|
strcpy(exten, "g");
|
|
|
|
if (option_exists(menu, "g") < 0) {
|
|
|
|
ast_log(LOG_WARNING, "No 's' nor 'g' extension in menu '%s'!\n", menu->title);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2007-01-23 00:11:32 +00:00
|
|
|
while (!res) {
|
|
|
|
while (menu->options[pos].option) {
|
2005-02-17 14:57:36 +00:00
|
|
|
if (!strcasecmp(menu->options[pos].option, exten)) {
|
|
|
|
res = ivr_dispatch(chan, menu->options + pos, exten, cbdata);
|
2007-06-14 19:39:12 +00:00
|
|
|
ast_debug(1, "IVR Dispatch of '%s' (pos %d) yields %d\n", exten, pos, res);
|
2009-03-04 20:48:42 +00:00
|
|
|
if (res < 0) {
|
2005-02-17 14:57:36 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
} else if (res & RES_UPONE) {
|
2005-02-17 14:57:36 +00:00
|
|
|
return 0;
|
2009-03-04 20:48:42 +00:00
|
|
|
} else if (res & RES_EXIT) {
|
2005-02-17 14:57:36 +00:00
|
|
|
return res;
|
2009-03-04 20:48:42 +00:00
|
|
|
} else if (res & RES_REPEAT) {
|
2005-02-17 14:57:36 +00:00
|
|
|
int maxretries = res & 0xffff;
|
2005-03-05 21:06:26 +00:00
|
|
|
if ((res & RES_RESTART) == RES_RESTART) {
|
2005-02-17 14:57:36 +00:00
|
|
|
retries = 0;
|
2009-03-04 20:48:42 +00:00
|
|
|
} else {
|
2005-02-17 14:57:36 +00:00
|
|
|
retries++;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
|
|
|
if (!maxretries) {
|
2005-02-17 14:57:36 +00:00
|
|
|
maxretries = 3;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-03-05 21:06:26 +00:00
|
|
|
if ((maxretries > 0) && (retries >= maxretries)) {
|
2007-06-14 19:39:12 +00:00
|
|
|
ast_debug(1, "Max retries %d exceeded\n", maxretries);
|
2005-02-17 14:57:36 +00:00
|
|
|
return -2;
|
2005-03-05 21:06:26 +00:00
|
|
|
} else {
|
2009-03-04 20:48:42 +00:00
|
|
|
if (option_exists(menu, "g") > -1) {
|
2005-02-17 14:57:36 +00:00
|
|
|
strcpy(exten, "g");
|
2009-03-04 20:48:42 +00:00
|
|
|
} else if (option_exists(menu, "s") > -1) {
|
2005-02-17 14:57:36 +00:00
|
|
|
strcpy(exten, "s");
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-02-17 14:57:36 +00:00
|
|
|
}
|
2006-07-10 17:42:12 +00:00
|
|
|
pos = 0;
|
2005-03-05 21:06:26 +00:00
|
|
|
continue;
|
2005-02-17 14:57:36 +00:00
|
|
|
} else if (res && strchr(AST_DIGIT_ANY, res)) {
|
2007-06-14 19:39:12 +00:00
|
|
|
ast_debug(1, "Got start of extension, %c\n", res);
|
2005-02-17 14:57:36 +00:00
|
|
|
exten[1] = '\0';
|
|
|
|
exten[0] = res;
|
2009-03-04 20:48:42 +00:00
|
|
|
if ((res = read_newoption(chan, menu, exten, sizeof(exten)))) {
|
2005-02-17 14:57:36 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-03-05 21:06:26 +00:00
|
|
|
if (option_exists(menu, exten) < 0) {
|
2005-02-17 14:57:36 +00:00
|
|
|
if (option_exists(menu, "i")) {
|
2007-06-14 19:39:12 +00:00
|
|
|
ast_debug(1, "Invalid extension entered, going to 'i'!\n");
|
2005-02-17 14:57:36 +00:00
|
|
|
strcpy(exten, "i");
|
|
|
|
pos = 0;
|
|
|
|
continue;
|
|
|
|
} else {
|
2007-06-14 19:39:12 +00:00
|
|
|
ast_debug(1, "Aborting on invalid entry, with no 'i' option!\n");
|
2005-02-17 14:57:36 +00:00
|
|
|
res = -2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
2007-06-14 19:39:12 +00:00
|
|
|
ast_debug(1, "New existing extension: %s\n", exten);
|
2005-02-17 14:57:36 +00:00
|
|
|
pos = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pos++;
|
|
|
|
}
|
2007-06-14 19:39:12 +00:00
|
|
|
ast_debug(1, "Stopping option '%s', res is %d\n", exten, res);
|
2005-02-17 14:57:36 +00:00
|
|
|
pos = 0;
|
2009-03-04 20:48:42 +00:00
|
|
|
if (!strcasecmp(exten, "s")) {
|
2005-02-17 14:57:36 +00:00
|
|
|
strcpy(exten, "g");
|
2009-03-04 20:48:42 +00:00
|
|
|
} else {
|
2005-02-17 14:57:36 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-02-17 14:57:36 +00:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ast_ivr_menu_run(struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata)
|
|
|
|
{
|
2006-07-10 17:42:12 +00:00
|
|
|
int res = ast_ivr_menu_run_internal(chan, menu, cbdata);
|
2005-02-17 14:57:36 +00:00
|
|
|
/* Hide internal coding */
|
2006-07-10 17:42:12 +00:00
|
|
|
return res > 0 ? 0 : res;
|
2005-02-17 14:57:36 +00:00
|
|
|
}
|
2009-03-04 20:48:42 +00:00
|
|
|
|
2005-02-27 19:07:46 +00:00
|
|
|
char *ast_read_textfile(const char *filename)
|
|
|
|
{
|
2007-06-12 14:16:37 +00:00
|
|
|
int fd, count = 0, res;
|
2006-07-10 17:42:12 +00:00
|
|
|
char *output = NULL;
|
2005-02-27 19:07:46 +00:00
|
|
|
struct stat filesize;
|
2007-06-12 14:16:37 +00:00
|
|
|
|
2006-07-10 17:42:12 +00:00
|
|
|
if (stat(filename, &filesize) == -1) {
|
|
|
|
ast_log(LOG_WARNING, "Error can't stat %s\n", filename);
|
2005-02-27 19:07:46 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2007-06-12 14:16:37 +00:00
|
|
|
|
2006-07-10 17:42:12 +00:00
|
|
|
count = filesize.st_size + 1;
|
2007-06-12 14:16:37 +00:00
|
|
|
|
|
|
|
if ((fd = open(filename, O_RDONLY)) < 0) {
|
2005-02-27 19:07:46 +00:00
|
|
|
ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno));
|
|
|
|
return NULL;
|
2006-03-28 14:30:31 +00:00
|
|
|
}
|
2007-06-12 14:16:37 +00:00
|
|
|
|
2006-02-14 22:28:01 +00:00
|
|
|
if ((output = ast_malloc(count))) {
|
2005-02-27 19:07:46 +00:00
|
|
|
res = read(fd, output, count - 1);
|
|
|
|
if (res == count - 1) {
|
|
|
|
output[res] = '\0';
|
|
|
|
} else {
|
2006-07-10 17:42:12 +00:00
|
|
|
ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count - 1, strerror(errno));
|
2007-06-06 21:20:11 +00:00
|
|
|
ast_free(output);
|
2005-02-27 19:07:46 +00:00
|
|
|
output = NULL;
|
|
|
|
}
|
2006-02-14 22:28:01 +00:00
|
|
|
}
|
2007-06-12 14:16:37 +00:00
|
|
|
|
2005-02-27 19:07:46 +00:00
|
|
|
close(fd);
|
2007-06-12 14:16:37 +00:00
|
|
|
|
2005-02-27 19:07:46 +00:00
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2010-04-15 21:26:19 +00:00
|
|
|
static int parse_options(const struct ast_app_option *options, void *_flags, char **args, char *optstr, int flaglen)
|
2005-03-12 05:37:32 +00:00
|
|
|
{
|
2007-06-12 14:16:37 +00:00
|
|
|
char *s, *arg;
|
|
|
|
int curarg, res = 0;
|
2005-11-03 21:19:11 +00:00
|
|
|
unsigned int argloc;
|
2010-04-15 21:26:19 +00:00
|
|
|
struct ast_flags *flags = _flags;
|
|
|
|
struct ast_flags64 *flags64 = _flags;
|
2005-09-14 17:20:24 +00:00
|
|
|
|
2010-04-15 21:26:19 +00:00
|
|
|
if (flaglen == 32) {
|
|
|
|
ast_clear_flag(flags, AST_FLAGS_ALL);
|
|
|
|
} else {
|
|
|
|
flags64->flags = 0;
|
|
|
|
}
|
2005-09-14 17:20:24 +00:00
|
|
|
|
2009-03-04 20:48:42 +00:00
|
|
|
if (!optstr) {
|
2005-03-12 05:37:32 +00:00
|
|
|
return 0;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-09-14 17:20:24 +00:00
|
|
|
|
2005-03-12 05:37:32 +00:00
|
|
|
s = optstr;
|
2005-09-14 17:20:24 +00:00
|
|
|
while (*s) {
|
2006-03-28 14:30:31 +00:00
|
|
|
curarg = *s++ & 0x7f; /* the array (in app.h) has 128 entries */
|
2005-09-14 17:20:24 +00:00
|
|
|
argloc = options[curarg].arg_index;
|
2005-03-12 05:37:32 +00:00
|
|
|
if (*s == '(') {
|
2010-04-15 21:26:19 +00:00
|
|
|
int paren = 1, quote = 0;
|
|
|
|
int parsequotes = (s[1] == '"') ? 1 : 0;
|
|
|
|
|
2005-03-12 05:37:32 +00:00
|
|
|
/* Has argument */
|
2005-11-10 23:12:09 +00:00
|
|
|
arg = ++s;
|
2010-04-15 21:26:19 +00:00
|
|
|
for (; *s; s++) {
|
|
|
|
if (*s == '(' && !quote) {
|
|
|
|
paren++;
|
|
|
|
} else if (*s == ')' && !quote) {
|
|
|
|
/* Count parentheses, unless they're within quotes (or backslashed, below) */
|
|
|
|
paren--;
|
|
|
|
} else if (*s == '"' && parsequotes) {
|
|
|
|
/* Leave embedded quotes alone, unless they are the first character */
|
|
|
|
quote = quote ? 0 : 1;
|
|
|
|
ast_copy_string(s, s + 1, INT_MAX);
|
|
|
|
s--;
|
|
|
|
} else if (*s == '\\') {
|
|
|
|
if (!quote) {
|
|
|
|
/* If a backslash is found outside of quotes, remove it */
|
|
|
|
ast_copy_string(s, s + 1, INT_MAX);
|
|
|
|
} else if (quote && s[1] == '"') {
|
|
|
|
/* Backslash for a quote character within quotes, remove the backslash */
|
|
|
|
ast_copy_string(s, s + 1, INT_MAX);
|
|
|
|
} else {
|
|
|
|
/* Backslash within quotes, keep both characters */
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (paren == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* This will find the closing paren we found above, or none, if the string ended before we found one. */
|
2006-10-05 16:11:09 +00:00
|
|
|
if ((s = strchr(s, ')'))) {
|
2009-03-04 20:48:42 +00:00
|
|
|
if (argloc) {
|
2005-03-12 05:37:32 +00:00
|
|
|
args[argloc - 1] = arg;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2005-11-03 21:19:11 +00:00
|
|
|
*s++ = '\0';
|
2005-03-12 05:37:32 +00:00
|
|
|
} else {
|
2005-09-14 17:20:24 +00:00
|
|
|
ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg);
|
2005-03-12 05:37:32 +00:00
|
|
|
res = -1;
|
2006-10-05 16:11:09 +00:00
|
|
|
break;
|
2005-03-12 05:37:32 +00:00
|
|
|
}
|
2005-11-03 21:19:11 +00:00
|
|
|
} else if (argloc) {
|
2007-11-27 20:21:57 +00:00
|
|
|
args[argloc - 1] = "";
|
2007-11-27 19:47:19 +00:00
|
|
|
}
|
2010-04-15 21:26:19 +00:00
|
|
|
if (flaglen == 32) {
|
|
|
|
ast_set_flag(flags, options[curarg].flag);
|
|
|
|
} else {
|
|
|
|
ast_set_flag64(flags64, options[curarg].flag);
|
|
|
|
}
|
2005-03-12 05:37:32 +00:00
|
|
|
}
|
2005-11-03 21:19:11 +00:00
|
|
|
|
2005-03-12 05:37:32 +00:00
|
|
|
return res;
|
|
|
|
}
|
2006-07-10 17:42:12 +00:00
|
|
|
|
2010-04-15 21:26:19 +00:00
|
|
|
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
|
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@75983 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-19 23:24:27 +00:00
|
|
|
{
|
2010-04-15 21:26:19 +00:00
|
|
|
return parse_options(options, flags, args, optstr, 32);
|
|
|
|
}
|
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@75983 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-19 23:24:27 +00:00
|
|
|
|
2010-04-15 21:26:19 +00:00
|
|
|
int ast_app_parse_options64(const struct ast_app_option *options, struct ast_flags64 *flags, char **args, char *optstr)
|
|
|
|
{
|
|
|
|
return parse_options(options, flags, args, optstr, 64);
|
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@75983 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-19 23:24:27 +00:00
|
|
|
}
|
|
|
|
|
2008-03-01 01:30:37 +00:00
|
|
|
void ast_app_options2str64(const struct ast_app_option *options, struct ast_flags64 *flags, char *buf, size_t len)
|
|
|
|
{
|
|
|
|
unsigned int i, found = 0;
|
|
|
|
for (i = 32; i < 128 && found < len; i++) {
|
|
|
|
if (ast_test_flag64(flags, options[i].flag)) {
|
|
|
|
buf[found++] = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
buf[found] = '\0';
|
|
|
|
}
|
|
|
|
|
2007-10-26 00:11:31 +00:00
|
|
|
int ast_get_encoded_char(const char *stream, char *result, size_t *consumed)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
*consumed = 1;
|
|
|
|
*result = 0;
|
2008-09-12 16:54:44 +00:00
|
|
|
if (ast_strlen_zero(stream)) {
|
|
|
|
*consumed = 0;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-10-26 00:11:31 +00:00
|
|
|
if (*stream == '\\') {
|
|
|
|
*consumed = 2;
|
|
|
|
switch (*(stream + 1)) {
|
|
|
|
case 'n':
|
|
|
|
*result = '\n';
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
*result = '\r';
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
*result = '\t';
|
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
/* Hexadecimal */
|
|
|
|
if (strchr("0123456789ABCDEFabcdef", *(stream + 2)) && *(stream + 2) != '\0') {
|
|
|
|
*consumed = 3;
|
2009-03-04 20:48:42 +00:00
|
|
|
if (*(stream + 2) <= '9') {
|
2007-10-26 00:11:31 +00:00
|
|
|
*result = *(stream + 2) - '0';
|
2009-03-04 20:48:42 +00:00
|
|
|
} else if (*(stream + 2) <= 'F') {
|
2007-10-26 00:11:31 +00:00
|
|
|
*result = *(stream + 2) - 'A' + 10;
|
2009-03-04 20:48:42 +00:00
|
|
|
} else {
|
2007-10-26 00:11:31 +00:00
|
|
|
*result = *(stream + 2) - 'a' + 10;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2007-10-26 00:11:31 +00:00
|
|
|
} else {
|
|
|
|
ast_log(LOG_ERROR, "Illegal character '%c' in hexadecimal string\n", *(stream + 2));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strchr("0123456789ABCDEFabcdef", *(stream + 3)) && *(stream + 3) != '\0') {
|
|
|
|
*consumed = 4;
|
|
|
|
*result <<= 4;
|
2009-03-04 20:48:42 +00:00
|
|
|
if (*(stream + 3) <= '9') {
|
2007-10-26 00:11:31 +00:00
|
|
|
*result += *(stream + 3) - '0';
|
2009-03-04 20:48:42 +00:00
|
|
|
} else if (*(stream + 3) <= 'F') {
|
2007-10-26 00:11:31 +00:00
|
|
|
*result += *(stream + 3) - 'A' + 10;
|
2009-03-04 20:48:42 +00:00
|
|
|
} else {
|
2007-10-26 00:11:31 +00:00
|
|
|
*result += *(stream + 3) - 'a' + 10;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2007-10-26 00:11:31 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '0':
|
|
|
|
/* Octal */
|
|
|
|
*consumed = 2;
|
|
|
|
for (i = 2; ; i++) {
|
|
|
|
if (strchr("01234567", *(stream + i)) && *(stream + i) != '\0') {
|
|
|
|
(*consumed)++;
|
|
|
|
ast_debug(5, "result was %d, ", *result);
|
|
|
|
*result <<= 3;
|
|
|
|
*result += *(stream + i) - '0';
|
|
|
|
ast_debug(5, "is now %d\n", *result);
|
2009-03-04 20:48:42 +00:00
|
|
|
} else {
|
2007-10-26 00:11:31 +00:00
|
|
|
break;
|
2009-03-04 20:48:42 +00:00
|
|
|
}
|
2007-10-26 00:11:31 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
*result = *(stream + 1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*result = *stream;
|
|
|
|
*consumed = 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-01-29 13:21:31 +00:00
|
|
|
char *ast_get_encoded_str(const char *stream, char *result, size_t result_size)
|
2008-11-05 21:58:48 +00:00
|
|
|
{
|
|
|
|
char *cur = result;
|
|
|
|
size_t consumed;
|
|
|
|
|
|
|
|
while (cur < result + result_size - 1 && !ast_get_encoded_char(stream, cur, &consumed)) {
|
|
|
|
cur++;
|
|
|
|
stream += consumed;
|
|
|
|
}
|
|
|
|
*cur = '\0';
|
2009-01-29 13:21:31 +00:00
|
|
|
return result;
|
2008-11-05 21:58:48 +00:00
|
|
|
}
|
|
|
|
|
2009-02-20 17:29:51 +00:00
|
|
|
int ast_str_get_encoded_str(struct ast_str **str, int maxlen, const char *stream)
|
|
|
|
{
|
|
|
|
char next, *buf;
|
|
|
|
size_t offset = 0;
|
|
|
|
size_t consumed;
|
|
|
|
|
|
|
|
if (strchr(stream, '\\')) {
|
|
|
|
while (!ast_get_encoded_char(stream, &next, &consumed)) {
|
|
|
|
if (offset + 2 > ast_str_size(*str) && maxlen > -1) {
|
|
|
|
ast_str_make_space(str, maxlen > 0 ? maxlen : (ast_str_size(*str) + 48) * 2 - 48);
|
|
|
|
}
|
|
|
|
if (offset + 2 > ast_str_size(*str)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
buf = ast_str_buffer(*str);
|
|
|
|
buf[offset++] = next;
|
|
|
|
stream += consumed;
|
|
|
|
}
|
|
|
|
buf = ast_str_buffer(*str);
|
|
|
|
buf[offset++] = '\0';
|
|
|
|
ast_str_update(*str);
|
|
|
|
} else {
|
|
|
|
ast_str_set(str, maxlen, "%s", stream);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-04-16 22:57:54 +00:00
|
|
|
void ast_close_fds_above_n(int n)
|
|
|
|
{
|
2009-01-12 23:06:12 +00:00
|
|
|
closefrom(n + 1);
|
2008-04-16 22:57:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int ast_safe_fork(int stop_reaper)
|
|
|
|
{
|
|
|
|
sigset_t signal_set, old_set;
|
|
|
|
int pid;
|
|
|
|
|
|
|
|
/* Don't let the default signal handler for children reap our status */
|
|
|
|
if (stop_reaper) {
|
|
|
|
ast_replace_sigchld();
|
|
|
|
}
|
|
|
|
|
2015-01-26 14:50:40 +00:00
|
|
|
/* GCC 4.9 gives a bogus "right-hand operand of comma expression has
|
|
|
|
* no effect" warning */
|
|
|
|
(void) sigfillset(&signal_set);
|
2008-04-16 22:57:54 +00:00
|
|
|
pthread_sigmask(SIG_BLOCK, &signal_set, &old_set);
|
|
|
|
|
|
|
|
pid = fork();
|
|
|
|
|
|
|
|
if (pid != 0) {
|
|
|
|
/* Fork failed or parent */
|
|
|
|
pthread_sigmask(SIG_SETMASK, &old_set, NULL);
|
2011-01-19 20:33:30 +00:00
|
|
|
if (!stop_reaper && pid > 0) {
|
|
|
|
struct zombie *cur = ast_calloc(1, sizeof(*cur));
|
|
|
|
if (cur) {
|
|
|
|
cur->pid = pid;
|
|
|
|
AST_LIST_LOCK(&zombies);
|
|
|
|
AST_LIST_INSERT_TAIL(&zombies, cur, list);
|
|
|
|
AST_LIST_UNLOCK(&zombies);
|
|
|
|
if (shaun_of_the_dead_thread == AST_PTHREADT_NULL) {
|
|
|
|
if (ast_pthread_create_background(&shaun_of_the_dead_thread, NULL, shaun_of_the_dead, NULL)) {
|
|
|
|
ast_log(LOG_ERROR, "Shaun of the Dead wants to kill zombies, but can't?!!\n");
|
|
|
|
shaun_of_the_dead_thread = AST_PTHREADT_NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-04-16 22:57:54 +00:00
|
|
|
return pid;
|
|
|
|
} else {
|
|
|
|
/* Child */
|
2009-01-29 23:15:40 +00:00
|
|
|
#ifdef HAVE_CAP
|
|
|
|
cap_t cap = cap_from_text("cap_net_admin-eip");
|
|
|
|
|
|
|
|
if (cap_set_proc(cap)) {
|
|
|
|
ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
|
|
|
|
}
|
|
|
|
cap_free(cap);
|
|
|
|
#endif
|
2008-04-16 22:57:54 +00:00
|
|
|
|
|
|
|
/* Before we unblock our signals, return our trapped signals back to the defaults */
|
|
|
|
signal(SIGHUP, SIG_DFL);
|
|
|
|
signal(SIGCHLD, SIG_DFL);
|
|
|
|
signal(SIGINT, SIG_DFL);
|
|
|
|
signal(SIGURG, SIG_DFL);
|
|
|
|
signal(SIGTERM, SIG_DFL);
|
|
|
|
signal(SIGPIPE, SIG_DFL);
|
|
|
|
signal(SIGXFSZ, SIG_DFL);
|
|
|
|
|
|
|
|
/* unblock important signal handlers */
|
|
|
|
if (pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
|
2008-04-25 19:39:26 +00:00
|
|
|
ast_log(LOG_WARNING, "unable to unblock signals: %s\n", strerror(errno));
|
2008-04-16 22:57:54 +00:00
|
|
|
_exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return pid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ast_safe_fork_cleanup(void)
|
|
|
|
{
|
|
|
|
ast_unreplace_sigchld();
|
|
|
|
}
|
|
|
|
|
2009-10-17 16:39:37 +00:00
|
|
|
int ast_app_parse_timelen(const char *timestr, int *result, enum ast_timelen unit)
|
2009-10-15 22:33:30 +00:00
|
|
|
{
|
|
|
|
int res;
|
|
|
|
char u[10];
|
|
|
|
#ifdef HAVE_LONG_DOUBLE_WIDER
|
|
|
|
long double amount;
|
|
|
|
#define FMT "%30Lf%9s"
|
|
|
|
#else
|
|
|
|
double amount;
|
|
|
|
#define FMT "%30lf%9s"
|
|
|
|
#endif
|
|
|
|
if (!timestr) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-10-24 17:00:27 +00:00
|
|
|
res = sscanf(timestr, FMT, &amount, u);
|
|
|
|
|
|
|
|
if (res == 0 || res == EOF) {
|
2009-10-15 22:33:30 +00:00
|
|
|
#undef FMT
|
|
|
|
return -1;
|
|
|
|
} else if (res == 2) {
|
|
|
|
switch (u[0]) {
|
|
|
|
case 'h':
|
|
|
|
case 'H':
|
|
|
|
unit = TIMELEN_HOURS;
|
2017-07-10 19:04:58 +00:00
|
|
|
if (u[1] != '\0') {
|
|
|
|
return -1;
|
|
|
|
}
|
2009-10-15 22:33:30 +00:00
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
case 'S':
|
|
|
|
unit = TIMELEN_SECONDS;
|
2017-07-10 19:04:58 +00:00
|
|
|
if (u[1] != '\0') {
|
|
|
|
return -1;
|
|
|
|
}
|
2009-10-15 22:33:30 +00:00
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
case 'M':
|
|
|
|
if (toupper(u[1]) == 'S') {
|
|
|
|
unit = TIMELEN_MILLISECONDS;
|
2017-07-10 19:04:58 +00:00
|
|
|
if (u[2] != '\0') {
|
|
|
|
return -1;
|
|
|
|
}
|
2009-10-15 22:33:30 +00:00
|
|
|
} else if (u[1] == '\0') {
|
|
|
|
unit = TIMELEN_MINUTES;
|
2017-07-10 19:04:58 +00:00
|
|
|
} else {
|
|
|
|
return -1;
|
2009-10-15 22:33:30 +00:00
|
|
|
}
|
|
|
|
break;
|
2017-07-10 19:04:58 +00:00
|
|
|
default:
|
|
|
|
return -1;
|
2009-10-15 22:33:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (unit) {
|
|
|
|
case TIMELEN_HOURS:
|
|
|
|
amount *= 60;
|
|
|
|
/* fall-through */
|
|
|
|
case TIMELEN_MINUTES:
|
|
|
|
amount *= 60;
|
|
|
|
/* fall-through */
|
|
|
|
case TIMELEN_SECONDS:
|
|
|
|
amount *= 1000;
|
|
|
|
/* fall-through */
|
|
|
|
case TIMELEN_MILLISECONDS:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
*result = amount > INT_MAX ? INT_MAX : (int) amount;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-03-16 15:45:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
static void mwi_state_dtor(void *obj)
|
|
|
|
{
|
2013-05-24 20:44:07 +00:00
|
|
|
struct ast_mwi_state *mwi_state = obj;
|
2013-03-16 15:45:58 +00:00
|
|
|
ast_string_field_free_memory(mwi_state);
|
2013-05-24 20:44:07 +00:00
|
|
|
ao2_cleanup(mwi_state->snapshot);
|
|
|
|
mwi_state->snapshot = NULL;
|
2013-03-16 15:45:58 +00:00
|
|
|
}
|
|
|
|
|
2013-05-24 20:44:07 +00:00
|
|
|
struct stasis_topic *ast_mwi_topic_all(void)
|
2013-03-16 15:45:58 +00:00
|
|
|
{
|
|
|
|
return mwi_topic_all;
|
|
|
|
}
|
|
|
|
|
2013-08-01 13:49:34 +00:00
|
|
|
struct stasis_cache *ast_mwi_state_cache(void)
|
2013-03-16 15:45:58 +00:00
|
|
|
{
|
2013-08-01 13:49:34 +00:00
|
|
|
return mwi_state_cache;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct stasis_topic *ast_mwi_topic_cached(void)
|
|
|
|
{
|
|
|
|
return stasis_caching_get_topic(mwi_topic_cached);
|
2013-03-16 15:45:58 +00:00
|
|
|
}
|
|
|
|
|
2013-05-24 20:44:07 +00:00
|
|
|
struct stasis_topic *ast_mwi_topic(const char *uniqueid)
|
2013-03-16 15:45:58 +00:00
|
|
|
{
|
|
|
|
return stasis_topic_pool_get_topic(mwi_topic_pool, uniqueid);
|
|
|
|
}
|
|
|
|
|
2013-05-24 20:44:07 +00:00
|
|
|
struct ast_mwi_state *ast_mwi_create(const char *mailbox, const char *context)
|
|
|
|
{
|
2017-11-16 18:51:37 +00:00
|
|
|
struct ast_mwi_state *mwi_state;
|
2013-05-24 20:44:07 +00:00
|
|
|
|
|
|
|
ast_assert(!ast_strlen_zero(mailbox));
|
|
|
|
|
|
|
|
mwi_state = ao2_alloc(sizeof(*mwi_state), mwi_state_dtor);
|
|
|
|
if (!mwi_state) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ast_string_field_init(mwi_state, 256)) {
|
2017-11-16 18:51:37 +00:00
|
|
|
ao2_ref(mwi_state, -1);
|
2013-05-24 20:44:07 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2013-12-19 16:52:43 +00:00
|
|
|
if (!ast_strlen_zero(context)) {
|
|
|
|
ast_string_field_build(mwi_state, uniqueid, "%s@%s", mailbox, context);
|
|
|
|
} else {
|
|
|
|
ast_string_field_set(mwi_state, uniqueid, mailbox);
|
|
|
|
}
|
2013-05-24 20:44:07 +00:00
|
|
|
|
|
|
|
return mwi_state;
|
|
|
|
}
|
|
|
|
|
2014-03-14 16:01:13 +00:00
|
|
|
/*!
|
|
|
|
* \internal
|
|
|
|
* \brief Create a MWI state snapshot message.
|
|
|
|
* \since 12.2.0
|
|
|
|
*
|
|
|
|
* \param[in] mailbox The mailbox identifier string.
|
|
|
|
* \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)
|
|
|
|
* \param[in] new_msgs The number of new messages in this mailbox
|
|
|
|
* \param[in] old_msgs The number of old messages in this mailbox
|
|
|
|
* \param[in] channel_id A unique identifier for a channel associated with this
|
|
|
|
* change in mailbox state
|
|
|
|
* \param[in] eid The EID of the server that originally published the message
|
|
|
|
*
|
|
|
|
* \retval message on success. Use ao2_cleanup() when done with it.
|
|
|
|
* \retval NULL on error.
|
|
|
|
*/
|
|
|
|
static struct stasis_message *mwi_state_create_message(
|
|
|
|
const char *mailbox,
|
|
|
|
const char *context,
|
|
|
|
int new_msgs,
|
|
|
|
int old_msgs,
|
|
|
|
const char *channel_id,
|
|
|
|
struct ast_eid *eid)
|
2013-03-16 15:45:58 +00:00
|
|
|
{
|
2014-03-14 16:01:13 +00:00
|
|
|
struct ast_mwi_state *mwi_state;
|
|
|
|
struct stasis_message *message;
|
2013-03-16 15:45:58 +00:00
|
|
|
|
2014-08-06 12:55:28 +00:00
|
|
|
if (!ast_mwi_state_type()) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-05-24 20:44:07 +00:00
|
|
|
mwi_state = ast_mwi_create(mailbox, context);
|
|
|
|
if (!mwi_state) {
|
2014-03-14 16:01:13 +00:00
|
|
|
return NULL;
|
2013-03-16 15:45:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
mwi_state->new_msgs = new_msgs;
|
|
|
|
mwi_state->old_msgs = old_msgs;
|
2013-05-24 20:44:07 +00:00
|
|
|
|
|
|
|
if (!ast_strlen_zero(channel_id)) {
|
2018-10-10 14:28:18 +00:00
|
|
|
mwi_state->snapshot = ast_channel_snapshot_get_latest(channel_id);
|
2013-05-24 20:44:07 +00:00
|
|
|
}
|
|
|
|
|
2013-03-16 15:45:58 +00:00
|
|
|
if (eid) {
|
|
|
|
mwi_state->eid = *eid;
|
|
|
|
} else {
|
2014-03-07 20:41:13 +00:00
|
|
|
mwi_state->eid = ast_eid_default;
|
2013-03-16 15:45:58 +00:00
|
|
|
}
|
|
|
|
|
2014-03-07 20:41:13 +00:00
|
|
|
/*
|
2014-03-14 16:01:13 +00:00
|
|
|
* XXX As far as stasis is concerned, all MWI events are local.
|
2014-03-07 20:41:13 +00:00
|
|
|
*
|
2014-03-14 16:01:13 +00:00
|
|
|
* We may in the future want to make MWI aggregate local/remote
|
2014-03-07 20:41:13 +00:00
|
|
|
* message counts similar to how device state aggregates state.
|
|
|
|
*/
|
|
|
|
message = stasis_message_create_full(ast_mwi_state_type(), mwi_state, &ast_eid_default);
|
2014-03-14 16:01:13 +00:00
|
|
|
ao2_cleanup(mwi_state);
|
|
|
|
return message;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ast_publish_mwi_state_full(
|
|
|
|
const char *mailbox,
|
|
|
|
const char *context,
|
|
|
|
int new_msgs,
|
|
|
|
int old_msgs,
|
|
|
|
const char *channel_id,
|
|
|
|
struct ast_eid *eid)
|
|
|
|
{
|
|
|
|
struct ast_mwi_state *mwi_state;
|
|
|
|
RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
|
|
|
|
struct stasis_topic *mailbox_specific_topic;
|
|
|
|
|
|
|
|
message = mwi_state_create_message(mailbox, context, new_msgs, old_msgs, channel_id, eid);
|
2014-03-07 20:41:13 +00:00
|
|
|
if (!message) {
|
|
|
|
return -1;
|
|
|
|
}
|
2013-03-16 15:45:58 +00:00
|
|
|
|
2014-03-14 16:01:13 +00:00
|
|
|
mwi_state = stasis_message_data(message);
|
2013-06-14 23:26:50 +00:00
|
|
|
mailbox_specific_topic = ast_mwi_topic(mwi_state->uniqueid);
|
2013-03-16 15:45:58 +00:00
|
|
|
if (!mailbox_specific_topic) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
stasis_publish(mailbox_specific_topic, message);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-03-14 16:01:13 +00:00
|
|
|
int ast_delete_mwi_state_full(const char *mailbox, const char *context, struct ast_eid *eid)
|
|
|
|
{
|
|
|
|
RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
|
|
|
|
struct stasis_message *cached_msg;
|
|
|
|
struct stasis_message *clear_msg;
|
|
|
|
struct ast_mwi_state *mwi_state;
|
|
|
|
struct stasis_topic *mailbox_specific_topic;
|
|
|
|
|
|
|
|
msg = mwi_state_create_message(mailbox, context, 0, 0, NULL, eid);
|
|
|
|
if (!msg) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
mwi_state = stasis_message_data(msg);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX As far as stasis is concerned, all MWI events are local.
|
|
|
|
*
|
|
|
|
* For now, it is assumed that there is only one entity
|
|
|
|
* maintaining the state of a particular mailbox.
|
|
|
|
*
|
|
|
|
* If we ever have multiple MWI event entities maintaining
|
|
|
|
* the same mailbox that wish to delete their cached entry
|
|
|
|
* we will need to do something about the race condition
|
|
|
|
* potential between checking the cache and removing the
|
|
|
|
* cache entry.
|
|
|
|
*/
|
|
|
|
cached_msg = stasis_cache_get_by_eid(ast_mwi_state_cache(),
|
|
|
|
ast_mwi_state_type(), mwi_state->uniqueid, &ast_eid_default);
|
|
|
|
if (!cached_msg) {
|
|
|
|
/* Nothing to clear */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
ao2_cleanup(cached_msg);
|
|
|
|
|
|
|
|
mailbox_specific_topic = ast_mwi_topic(mwi_state->uniqueid);
|
|
|
|
if (!mailbox_specific_topic) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
clear_msg = stasis_cache_clear_create(msg);
|
|
|
|
if (clear_msg) {
|
|
|
|
stasis_publish(mailbox_specific_topic, clear_msg);
|
|
|
|
}
|
2018-09-20 15:15:48 +00:00
|
|
|
|
|
|
|
stasis_topic_pool_delete_topic(mwi_topic_pool, stasis_topic_name(mailbox_specific_topic));
|
|
|
|
|
2014-03-14 16:01:13 +00:00
|
|
|
ao2_cleanup(clear_msg);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-03-16 15:45:58 +00:00
|
|
|
static const char *mwi_state_get_id(struct stasis_message *message)
|
|
|
|
{
|
2013-05-24 20:44:07 +00:00
|
|
|
if (ast_mwi_state_type() == stasis_message_type(message)) {
|
|
|
|
struct ast_mwi_state *mwi_state = stasis_message_data(message);
|
2013-03-16 15:45:58 +00:00
|
|
|
return mwi_state->uniqueid;
|
2013-03-28 15:45:18 +00:00
|
|
|
} else if (stasis_subscription_change_type() == stasis_message_type(message)) {
|
2013-03-16 15:45:58 +00:00
|
|
|
struct stasis_subscription_change *change = stasis_message_data(message);
|
|
|
|
return change->uniqueid;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-05-24 20:44:07 +00:00
|
|
|
static void mwi_blob_dtor(void *obj)
|
|
|
|
{
|
|
|
|
struct ast_mwi_blob *mwi_blob = obj;
|
|
|
|
|
|
|
|
ao2_cleanup(mwi_blob->mwi_state);
|
|
|
|
ast_json_unref(mwi_blob->blob);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct stasis_message *ast_mwi_blob_create(struct ast_mwi_state *mwi_state,
|
|
|
|
struct stasis_message_type *message_type,
|
|
|
|
struct ast_json *blob)
|
|
|
|
{
|
2017-11-16 18:51:37 +00:00
|
|
|
struct ast_mwi_blob *obj;
|
|
|
|
struct stasis_message *msg;
|
2013-05-24 20:44:07 +00:00
|
|
|
|
|
|
|
ast_assert(blob != NULL);
|
|
|
|
|
2014-08-06 12:55:28 +00:00
|
|
|
if (!message_type) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-05-24 20:44:07 +00:00
|
|
|
obj = ao2_alloc(sizeof(*obj), mwi_blob_dtor);
|
|
|
|
if (!obj) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
obj->mwi_state = mwi_state;
|
|
|
|
ao2_ref(obj->mwi_state, +1);
|
|
|
|
obj->blob = ast_json_ref(blob);
|
|
|
|
|
2014-03-07 20:41:13 +00:00
|
|
|
/* This is not a normal MWI event. Only used by the MinivmNotify app. */
|
2013-05-24 20:44:07 +00:00
|
|
|
msg = stasis_message_create(message_type, obj);
|
2017-11-16 18:51:37 +00:00
|
|
|
ao2_ref(obj, -1);
|
2013-05-24 20:44:07 +00:00
|
|
|
|
|
|
|
return msg;
|
|
|
|
}
|
|
|
|
|
2013-08-22 18:52:41 +00:00
|
|
|
struct stasis_topic *ast_queue_topic_all(void)
|
|
|
|
{
|
|
|
|
return queue_topic_all;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct stasis_topic *ast_queue_topic(const char *queuename)
|
|
|
|
{
|
|
|
|
return stasis_topic_pool_get_topic(queue_topic_pool, queuename);
|
|
|
|
}
|
|
|
|
|
Avoid unnecessary cleanups during immediate shutdown
This patch addresses issues during immediate shutdowns, where modules
are not unloaded, but Asterisk atexit handlers are run.
In the typical case, this usually isn't a big deal. But the
introduction of the Stasis message bus makes it much more likely for
asynchronous activity to be happening off in some thread during
shutdown.
During an immediate shutdown, Asterisk skips unloading modules. But
while it is processing the atexit handlers, there is a window of time
where some of the core message types have been cleaned up, but the
message bus is still running. Specifically, it's still running
module subscriptions that might be using the core message types. If a
message is received by that subscription in that window, it will
attempt to use a message type that has been cleaned up.
To solve this problem, this patch introduces ast_register_cleanup().
This function operates identically to ast_register_atexit(), except
that cleanup calls are not invoked on an immediate shutdown. All of
the core message type and topic cleanup was moved from atexit handlers
to cleanup handlers.
This ensures that core type and topic cleanup only happens if the
modules that used them are first unloaded.
This patch also changes the ast_assert() when accessing a cleaned up
or uninitialized message type to an error log message. Message type
functions are actually NULL safe across the board, so the assert was a
bit heavy handed. Especially for anyone with DO_CRASH enabled.
Review: https://reviewboard.asterisk.org/r/2562/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@390122 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2013-05-30 17:05:53 +00:00
|
|
|
static void app_cleanup(void)
|
2013-03-16 15:45:58 +00:00
|
|
|
{
|
2013-08-22 18:52:41 +00:00
|
|
|
ao2_cleanup(queue_topic_pool);
|
|
|
|
queue_topic_pool = NULL;
|
|
|
|
ao2_cleanup(queue_topic_all);
|
|
|
|
queue_topic_all = NULL;
|
2013-06-09 21:11:25 +00:00
|
|
|
ao2_cleanup(mwi_topic_pool);
|
|
|
|
mwi_topic_pool = NULL;
|
2013-03-16 15:45:58 +00:00
|
|
|
ao2_cleanup(mwi_topic_all);
|
|
|
|
mwi_topic_all = NULL;
|
2013-08-29 21:37:29 +00:00
|
|
|
ao2_cleanup(mwi_state_cache);
|
|
|
|
mwi_state_cache = NULL;
|
2013-05-17 21:10:32 +00:00
|
|
|
mwi_topic_cached = stasis_caching_unsubscribe_and_join(mwi_topic_cached);
|
2013-05-24 20:44:07 +00:00
|
|
|
STASIS_MESSAGE_TYPE_CLEANUP(ast_mwi_state_type);
|
|
|
|
STASIS_MESSAGE_TYPE_CLEANUP(ast_mwi_vm_app_type);
|
2013-03-16 15:45:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int app_init(void)
|
|
|
|
{
|
2013-05-30 19:23:53 +00:00
|
|
|
ast_register_cleanup(app_cleanup);
|
Avoid unnecessary cleanups during immediate shutdown
This patch addresses issues during immediate shutdowns, where modules
are not unloaded, but Asterisk atexit handlers are run.
In the typical case, this usually isn't a big deal. But the
introduction of the Stasis message bus makes it much more likely for
asynchronous activity to be happening off in some thread during
shutdown.
During an immediate shutdown, Asterisk skips unloading modules. But
while it is processing the atexit handlers, there is a window of time
where some of the core message types have been cleaned up, but the
message bus is still running. Specifically, it's still running
module subscriptions that might be using the core message types. If a
message is received by that subscription in that window, it will
attempt to use a message type that has been cleaned up.
To solve this problem, this patch introduces ast_register_cleanup().
This function operates identically to ast_register_atexit(), except
that cleanup calls are not invoked on an immediate shutdown. All of
the core message type and topic cleanup was moved from atexit handlers
to cleanup handlers.
This ensures that core type and topic cleanup only happens if the
modules that used them are first unloaded.
This patch also changes the ast_assert() when accessing a cleaned up
or uninitialized message type to an error log message. Message type
functions are actually NULL safe across the board, so the assert was a
bit heavy handed. Especially for anyone with DO_CRASH enabled.
Review: https://reviewboard.asterisk.org/r/2562/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@390122 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2013-05-30 17:05:53 +00:00
|
|
|
|
2013-05-24 20:44:07 +00:00
|
|
|
if (STASIS_MESSAGE_TYPE_INIT(ast_mwi_state_type) != 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (STASIS_MESSAGE_TYPE_INIT(ast_mwi_vm_app_type) != 0) {
|
2013-05-22 19:15:16 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2013-03-16 15:45:58 +00:00
|
|
|
mwi_topic_all = stasis_topic_create("stasis_mwi_topic");
|
|
|
|
if (!mwi_topic_all) {
|
|
|
|
return -1;
|
|
|
|
}
|
2013-08-01 13:49:34 +00:00
|
|
|
mwi_state_cache = stasis_cache_create(mwi_state_get_id);
|
|
|
|
if (!mwi_state_cache) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
mwi_topic_cached = stasis_caching_topic_create(mwi_topic_all, mwi_state_cache);
|
2013-03-16 15:45:58 +00:00
|
|
|
if (!mwi_topic_cached) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
mwi_topic_pool = stasis_topic_pool_create(mwi_topic_all);
|
|
|
|
if (!mwi_topic_pool) {
|
|
|
|
return -1;
|
|
|
|
}
|
2013-08-22 18:52:41 +00:00
|
|
|
queue_topic_all = stasis_topic_create("stasis_queue_topic");
|
|
|
|
if (!queue_topic_all) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
queue_topic_pool = stasis_topic_pool_create(queue_topic_all);
|
|
|
|
if (!queue_topic_pool) {
|
|
|
|
return -1;
|
|
|
|
}
|
2013-03-16 15:45:58 +00:00
|
|
|
return 0;
|
|
|
|
}
|