mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 04:11:08 +00:00
Improve the build system to *properly* remove unnecessary symbols from the runtime global namespace. Along the way, change the prefixes on some internal-only API calls to use a common prefix.
With these changes, for a module to export symbols into the global namespace, it must have *both* the AST_MODFLAG_GLOBAL_SYMBOLS flag and a linker script that allows the linker to leave the symbols exposed in the module's .so file (see res_odbc.exports for an example). git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@182802 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -51,8 +51,13 @@ endif
|
||||
# per-target settings will be applied
|
||||
CC_CFLAGS=$(PTHREAD_CFLAGS) $(ASTCFLAGS)
|
||||
CXX_CFLAGS=$(PTHREAD_CFLAGS) $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(AST_DECLARATION_AFTER_STATEMENT),$(ASTCFLAGS))
|
||||
CC_LDFLAGS_SO=$(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK)
|
||||
CXX_LDFLAGS_SO=$(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK)
|
||||
|
||||
ifeq ($(GNU_LD),1)
|
||||
SO_SUPPRESS_SYMBOLS=-Wl,--version-script,$(if $(wildcard $(subst .so,.exports,$@)),$(subst .so,.exports,$@),$(ASTTOPDIR)/default.exports)
|
||||
endif
|
||||
|
||||
CC_LDFLAGS_SO=$(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK) $(SO_SUPPRESS_SYMBOLS)
|
||||
CXX_LDFLAGS_SO=$(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK) $(SO_SUPPRESS_SYMBOLS)
|
||||
CC_LIBS=$(PTHREAD_LIBS) $(LIBS)
|
||||
CXX_LIBS=$(PTHREAD_LIBS) $(LIBS)
|
||||
|
||||
|
@@ -171,7 +171,7 @@ static void spy_release(struct ast_channel *chan, void *data)
|
||||
static int spy_generate(struct ast_channel *chan, void *data, int len, int samples)
|
||||
{
|
||||
struct chanspy_translation_helper *csth = data;
|
||||
struct ast_frame *f;
|
||||
struct ast_frame *f, *cur;
|
||||
|
||||
ast_audiohook_lock(&csth->spy_audiohook);
|
||||
if (csth->spy_audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) {
|
||||
@@ -186,14 +186,16 @@ static int spy_generate(struct ast_channel *chan, void *data, int len, int sampl
|
||||
if (!f)
|
||||
return 0;
|
||||
|
||||
if (ast_write(chan, f)) {
|
||||
ast_frfree(f);
|
||||
return -1;
|
||||
}
|
||||
for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
|
||||
if (ast_write(chan, cur)) {
|
||||
ast_frfree(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (csth->fd) {
|
||||
if (write(csth->fd, f->data, f->datalen) < 0) {
|
||||
ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
|
||||
if (csth->fd) {
|
||||
if (write(csth->fd, cur->data, cur->datalen) < 0) {
|
||||
ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -2338,9 +2338,19 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
|
||||
}
|
||||
}
|
||||
if (conf->transframe[index]) {
|
||||
if (conf->transframe[index]->frametype != AST_FRAME_NULL) {
|
||||
if (can_write(chan, confflags) && ast_write(chan, conf->transframe[index]))
|
||||
ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name);
|
||||
if ((conf->transframe[index]->frametype != AST_FRAME_NULL) &&
|
||||
can_write(chan, confflags)) {
|
||||
struct ast_frame *cur;
|
||||
|
||||
/* the translator may have returned a list of frames, so
|
||||
write each one onto the channel
|
||||
*/
|
||||
for (cur = conf->transframe[index]; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
|
||||
if (ast_write(chan, cur)) {
|
||||
ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ast_mutex_unlock(&conf->listenlock);
|
||||
|
@@ -229,9 +229,14 @@ static void *mixmonitor_thread(void *obj)
|
||||
}
|
||||
}
|
||||
|
||||
/* Write out the frame */
|
||||
if (fs)
|
||||
ast_writestream(fs, fr);
|
||||
/* Write out the frame(s) */
|
||||
if (fs) {
|
||||
struct ast_frame *cur;
|
||||
|
||||
for (cur = fr; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
|
||||
ast_writestream(fs, cur);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
|
||||
}
|
||||
|
@@ -12,6 +12,4 @@
|
||||
</member>
|
||||
<member name="MTX_PROFILE" displayname="Enable Code Profiling Using TSC Counters">
|
||||
</member>
|
||||
<member name="TRACE_FRAMES" displayname="Trace Frame Allocations">
|
||||
</member>
|
||||
</category>
|
||||
|
@@ -1,37 +0,0 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# This script is designed to remove all non-API global symbols from an object
|
||||
# file. The only global symbols that should be retained are those that belong
|
||||
# to the official namespace. Unfortunately doing this is platform-specific, as
|
||||
# the object file manipulation tools are not consistent across platforms.
|
||||
#
|
||||
# On platforms where this script does not know what to do, the object file
|
||||
# will retain non-API global symbols, and this may have unpleasant side effects.
|
||||
#
|
||||
# Prefixes that belong to the official namespace are:
|
||||
# ast_
|
||||
# _ast_
|
||||
# __ast_
|
||||
# astman_
|
||||
# pbx_
|
||||
|
||||
case "${PROC}" in
|
||||
powerpc64)
|
||||
TEXTSYM=" D "
|
||||
;;
|
||||
*)
|
||||
TEXTSYM=" T "
|
||||
;;
|
||||
esac
|
||||
|
||||
FILTER="${GREP} -v -e ^ast_ -e ^_ast_ -e ^__ast_ -e ^astman_ -e ^pbx_"
|
||||
|
||||
case "${OSARCH}" in
|
||||
linux-gnu)
|
||||
nm ${1} | ${GREP} -e "$TEXTSYM" | cut -d" " -f3 | ${FILTER} > striplist
|
||||
sed -e "s/^/-N /" striplist | xargs -n 40 ${STRIP} ${1}
|
||||
rm -f striplist
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
4
default.exports
Normal file
4
default.exports
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
local:
|
||||
*;
|
||||
};
|
@@ -188,15 +188,15 @@ int ao2_ref(void *o, int delta);
|
||||
#ifndef DEBUG_THREADS
|
||||
int ao2_lock(void *a);
|
||||
#else
|
||||
#define ao2_lock(a) _ao2_lock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
|
||||
int _ao2_lock(void *a, const char *file, const char *func, int line, const char *var);
|
||||
#define ao2_lock(a) __ao2_lock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
|
||||
int __ao2_lock(void *a, const char *file, const char *func, int line, const char *var);
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_THREADS
|
||||
int ao2_trylock(void *a);
|
||||
#else
|
||||
#define ao2_trylock(a) _ao2_trylock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
|
||||
int _ao2_trylock(void *a, const char *file, const char *func, int line, const char *var);
|
||||
#define ao2_trylock(a) __ao2_trylock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
|
||||
int __ao2_trylock(void *a, const char *file, const char *func, int line, const char *var);
|
||||
#endif
|
||||
|
||||
/*!
|
||||
@@ -208,8 +208,8 @@ int _ao2_trylock(void *a, const char *file, const char *func, int line, const ch
|
||||
#ifndef DEBUG_THREADS
|
||||
int ao2_unlock(void *a);
|
||||
#else
|
||||
#define ao2_unlock(a) _ao2_unlock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
|
||||
int _ao2_unlock(void *a, const char *file, const char *func, int line, const char *var);
|
||||
#define ao2_unlock(a) __ao2_unlock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
|
||||
int __ao2_unlock(void *a, const char *file, const char *func, int line, const char *var);
|
||||
#endif
|
||||
|
||||
/*!
|
||||
|
@@ -399,9 +399,9 @@ struct ast_frame *ast_fralloc(char *source, int len);
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief Frees a frame
|
||||
* \brief Frees a frame or list of frames
|
||||
*
|
||||
* \param fr Frame to free
|
||||
* \param fr Frame to free, or head of list to free
|
||||
* \param cache Whether to consider this frame for frame caching
|
||||
*/
|
||||
void ast_frame_free(struct ast_frame *fr, int cache);
|
||||
@@ -415,6 +415,11 @@ void ast_frame_free(struct ast_frame *fr, int cache);
|
||||
* data malloc'd. If you need to store frames, say for queueing, then
|
||||
* you should call this function.
|
||||
* \return Returns a frame on success, NULL on error
|
||||
* \note This function may modify the frame passed to it, so you must
|
||||
* not assume the frame will be intact after the isolated frame has
|
||||
* been produced. In other words, calling this function on a frame
|
||||
* should be the last operation you do with that frame before freeing
|
||||
* it (or exiting the block, if the frame is on the stack.)
|
||||
*/
|
||||
struct ast_frame *ast_frisolate(struct ast_frame *fr);
|
||||
|
||||
|
@@ -685,7 +685,7 @@ struct { \
|
||||
\param head This is a pointer to the list head structure
|
||||
\param list This is a pointer to the list to be appended.
|
||||
\param field This is the name of the field (declared using AST_LIST_ENTRY())
|
||||
used to link entries of this list together.
|
||||
used to link entries of the lists together.
|
||||
|
||||
Note: The source list (the \a list parameter) will be empty after
|
||||
calling this macro (the list entries are \b moved to the target list).
|
||||
@@ -704,6 +704,30 @@ struct { \
|
||||
|
||||
#define AST_RWLIST_APPEND_LIST AST_LIST_APPEND_LIST
|
||||
|
||||
/*!
|
||||
\brief Inserts a whole list after a specific entry in a list
|
||||
\param head This is a pointer to the list head structure
|
||||
\param list This is a pointer to the list to be inserted.
|
||||
\param elm This is a pointer to the entry after which the new list should
|
||||
be inserted.
|
||||
\param field This is the name of the field (declared using AST_LIST_ENTRY())
|
||||
used to link entries of the lists together.
|
||||
|
||||
Note: The source list (the \a list parameter) will be empty after
|
||||
calling this macro (the list entries are \b moved to the target list).
|
||||
*/
|
||||
#define AST_LIST_INSERT_LIST_AFTER(head, list, elm, field) do { \
|
||||
(list)->last->field.next = (elm)->field.next; \
|
||||
(elm)->field.next = (list)->first; \
|
||||
if ((head)->last == elm) { \
|
||||
(head)->last = (list)->last; \
|
||||
} \
|
||||
(list)->first = NULL; \
|
||||
(list)->last = NULL; \
|
||||
} while(0)
|
||||
|
||||
#define AST_RWLIST_INSERT_LIST_AFTER AST_LIST_INSERT_LIST_AFTER
|
||||
|
||||
/*!
|
||||
\brief Removes and returns the head entry from a list.
|
||||
\param head This is a pointer to the list head structure
|
||||
|
@@ -94,6 +94,10 @@ ifeq ($(OSARCH),SunOS)
|
||||
ASTLINK=
|
||||
endif
|
||||
|
||||
ifeq ($(GNU_LD),1)
|
||||
ASTLINK+=-Wl,--version-script,asterisk.exports
|
||||
endif
|
||||
|
||||
editline/libedit.a:
|
||||
cd editline && test -f config.h || CFLAGS="$(PTHREAD_CFLAGS) $(subst $(ASTTOPDIR),../../,$(ASTCFLAGS:-Werror=))" LDFLAGS="$(ASTLDFLAGS)" ./configure --build=$(BUILD_PLATFORM) --host=$(HOST_PLATFORM) --with-ncurses=$(NCURSES_DIR) --with-curses=$(CURSES_DIR) --with-termcap=$(TERMCAP_DIR) --with-tinfo=$(TINFO_DIR)
|
||||
$(MAKE) -C editline libedit.a
|
||||
@@ -133,20 +137,19 @@ else
|
||||
H323LDLIBS=
|
||||
endif
|
||||
|
||||
asterisk: $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS)
|
||||
asterisk: $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS) asterisk.exports
|
||||
@$(ASTTOPDIR)/build_tools/make_build_h > $(ASTTOPDIR)/include/asterisk/build.h.tmp
|
||||
@if cmp -s $(ASTTOPDIR)/include/asterisk/build.h.tmp $(ASTTOPDIR)/include/asterisk/build.h ; then echo ; else \
|
||||
mv $(ASTTOPDIR)/include/asterisk/build.h.tmp $(ASTTOPDIR)/include/asterisk/build.h ; \
|
||||
fi
|
||||
@rm -f $(ASTTOPDIR)/include/asterisk/build.h.tmp
|
||||
@$(CC) -c -o buildinfo.o $(ASTCFLAGS) buildinfo.c
|
||||
$(ECHO_PREFIX) echo " [LD] $^ -> $@"
|
||||
$(ECHO_PREFIX) echo " [LD] $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS) -> $@"
|
||||
ifneq ($(findstring chan_h323,$(MENUSELECT_CHANNELS)),)
|
||||
$(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $^ buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS)
|
||||
$(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS) buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS)
|
||||
else
|
||||
$(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $(H323LDFLAGS) $^ buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(H323LDLIBS)
|
||||
$(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $(H323LDFLAGS) $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS) buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(H323LDLIBS)
|
||||
endif
|
||||
$(CMD_PREFIX) $(ASTTOPDIR)/build_tools/strip_nonapi $@ || rm $@
|
||||
|
||||
clean::
|
||||
rm -f asterisk
|
||||
|
28
main/asterisk.exports
Normal file
28
main/asterisk.exports
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
global:
|
||||
ast_*;
|
||||
_ast_*;
|
||||
__ast_*;
|
||||
pbx_*;
|
||||
astman_*;
|
||||
ao2_*;
|
||||
__ao2_*;
|
||||
option_debug;
|
||||
option_verbose;
|
||||
dahdi_chan_name;
|
||||
dahdi_chan_name_len;
|
||||
dahdi_chan_mode;
|
||||
cid_di;
|
||||
cid_dr;
|
||||
clidsb;
|
||||
MD5*;
|
||||
sched_*;
|
||||
io_*;
|
||||
jb_*;
|
||||
channelreloadreason2txt;
|
||||
devstate2str;
|
||||
manager_event;
|
||||
dialed_interface_info;
|
||||
local:
|
||||
*;
|
||||
};
|
@@ -128,7 +128,7 @@ static inline struct astobj2 *INTERNAL_OBJ(void *user_data)
|
||||
#ifndef DEBUG_THREADS
|
||||
int ao2_lock(void *user_data)
|
||||
#else
|
||||
int _ao2_lock(void *user_data, const char *file, const char *func, int line, const char *var)
|
||||
int __ao2_lock(void *user_data, const char *file, const char *func, int line, const char *var)
|
||||
#endif
|
||||
{
|
||||
struct astobj2 *p = INTERNAL_OBJ(user_data);
|
||||
@@ -150,7 +150,7 @@ int _ao2_lock(void *user_data, const char *file, const char *func, int line, con
|
||||
#ifndef DEBUG_THREADS
|
||||
int ao2_trylock(void *user_data)
|
||||
#else
|
||||
int _ao2_trylock(void *user_data, const char *file, const char *func, int line, const char *var)
|
||||
int __ao2_trylock(void *user_data, const char *file, const char *func, int line, const char *var)
|
||||
#endif
|
||||
{
|
||||
struct astobj2 *p = INTERNAL_OBJ(user_data);
|
||||
@@ -177,7 +177,7 @@ int _ao2_trylock(void *user_data, const char *file, const char *func, int line,
|
||||
#ifndef DEBUG_THREADS
|
||||
int ao2_unlock(void *user_data)
|
||||
#else
|
||||
int _ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
|
||||
int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
|
||||
#endif
|
||||
{
|
||||
struct astobj2 *p = INTERNAL_OBJ(user_data);
|
||||
|
@@ -168,15 +168,22 @@ static void *autoservice_run(void *ign)
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((dup_f = ast_frdup(defer_frame))) {
|
||||
AST_LIST_INSERT_HEAD(&ents[i]->deferred_frames, dup_f, frame_list);
|
||||
if (defer_frame != f) {
|
||||
if ((dup_f = ast_frdup(defer_frame))) {
|
||||
AST_LIST_INSERT_HEAD(&ents[i]->deferred_frames, dup_f, frame_list);
|
||||
}
|
||||
} else {
|
||||
if ((dup_f = ast_frisolate(defer_frame))) {
|
||||
if (dup_f != defer_frame) {
|
||||
ast_frfree(defer_frame);
|
||||
}
|
||||
AST_LIST_INSERT_HEAD(&ents[i]->deferred_frames, dup_f, frame_list);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (f) {
|
||||
} else if (f) {
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
|
234
main/channel.c
234
main/channel.c
@@ -895,60 +895,90 @@ alertpipe_failed:
|
||||
}
|
||||
|
||||
/*! \brief Queue an outgoing media frame */
|
||||
static int __ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int head)
|
||||
static int __ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int head, struct ast_frame *after)
|
||||
{
|
||||
struct ast_frame *f;
|
||||
struct ast_frame *cur;
|
||||
int blah = 1;
|
||||
int qlen = 0;
|
||||
unsigned int new_frames = 0;
|
||||
unsigned int new_voice_frames = 0;
|
||||
unsigned int queued_frames = 0;
|
||||
unsigned int queued_voice_frames = 0;
|
||||
|
||||
/* Build us a copy and free the original one */
|
||||
if (!(f = ast_frdup(fin))) {
|
||||
return -1;
|
||||
AST_LIST_HEAD_NOLOCK(, ast_frame) frames;
|
||||
|
||||
/* Build copies of all the frames and count them */
|
||||
AST_LIST_HEAD_INIT_NOLOCK(&frames);
|
||||
for (cur = fin; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
|
||||
if (!(f = ast_frdup(cur))) {
|
||||
ast_frfree(AST_LIST_FIRST(&frames));
|
||||
return -1;
|
||||
}
|
||||
|
||||
AST_LIST_INSERT_TAIL(&frames, f, frame_list);
|
||||
new_frames++;
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
new_voice_frames++;
|
||||
}
|
||||
}
|
||||
|
||||
ast_channel_lock(chan);
|
||||
|
||||
/* See if the last frame on the queue is a hangup, if so don't queue anything */
|
||||
if ((cur = AST_LIST_LAST(&chan->readq)) && (cur->frametype == AST_FRAME_CONTROL) && (cur->subclass == AST_CONTROL_HANGUP)) {
|
||||
ast_frfree(f);
|
||||
while ((f = AST_LIST_REMOVE_HEAD(&frames, frame_list))) {
|
||||
ast_frfree(f);
|
||||
}
|
||||
ast_channel_unlock(chan);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Count how many frames exist on the queue */
|
||||
AST_LIST_TRAVERSE(&chan->readq, cur, frame_list) {
|
||||
qlen++;
|
||||
}
|
||||
|
||||
/* Allow up to 96 voice frames outstanding, and up to 128 total frames */
|
||||
if (((fin->frametype == AST_FRAME_VOICE) && (qlen > 96)) || (qlen > 128)) {
|
||||
if (fin->frametype != AST_FRAME_VOICE) {
|
||||
ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name);
|
||||
ast_assert(fin->frametype == AST_FRAME_VOICE);
|
||||
} else {
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Dropping voice to exceptionally long queue on %s\n", chan->name);
|
||||
ast_frfree(f);
|
||||
ast_channel_unlock(chan);
|
||||
return 0;
|
||||
queued_frames++;
|
||||
if (cur->frametype == AST_FRAME_VOICE) {
|
||||
queued_voice_frames++;
|
||||
}
|
||||
}
|
||||
|
||||
if (head) {
|
||||
AST_LIST_INSERT_HEAD(&chan->readq, f, frame_list);
|
||||
if ((queued_frames + new_frames) > 128) {
|
||||
ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name);
|
||||
while ((f = AST_LIST_REMOVE_HEAD(&frames, frame_list))) {
|
||||
ast_frfree(f);
|
||||
}
|
||||
ast_channel_unlock(chan);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((queued_voice_frames + new_voice_frames) > 96) {
|
||||
ast_log(LOG_WARNING, "Exceptionally long voice queue length queuing to %s\n", chan->name);
|
||||
while ((f = AST_LIST_REMOVE_HEAD(&frames, frame_list))) {
|
||||
ast_frfree(f);
|
||||
}
|
||||
ast_channel_unlock(chan);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (after) {
|
||||
AST_LIST_INSERT_LIST_AFTER(&chan->readq, &frames, after, frame_list);
|
||||
} else {
|
||||
AST_LIST_INSERT_TAIL(&chan->readq, f, frame_list);
|
||||
if (head) {
|
||||
AST_LIST_APPEND_LIST(&frames, &chan->readq, frame_list);
|
||||
AST_LIST_HEAD_INIT_NOLOCK(&chan->readq);
|
||||
}
|
||||
AST_LIST_APPEND_LIST(&chan->readq, &frames, frame_list);
|
||||
}
|
||||
|
||||
if (chan->alertpipe[1] > -1) {
|
||||
if (write(chan->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah)) {
|
||||
ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d (qlen = %d): %s!\n",
|
||||
chan->name, f->frametype, f->subclass, qlen, strerror(errno));
|
||||
if (write(chan->alertpipe[1], &blah, new_frames * sizeof(blah)) != (new_frames * sizeof(blah))) {
|
||||
ast_log(LOG_WARNING, "Unable to write to alert pipe on %s (qlen = %d): %s!\n",
|
||||
chan->name, queued_frames, strerror(errno));
|
||||
}
|
||||
#ifdef HAVE_DAHDI
|
||||
} else if (chan->timingfd > -1) {
|
||||
ioctl(chan->timingfd, DAHDI_TIMERPING, &blah);
|
||||
while (new_frames--) {
|
||||
ioctl(chan->timingfd, DAHDI_TIMERPING, &blah);
|
||||
}
|
||||
#endif
|
||||
} else if (ast_test_flag(chan, AST_FLAG_BLOCKING)) {
|
||||
pthread_kill(chan->blocker, SIGURG);
|
||||
@@ -961,12 +991,12 @@ static int __ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, in
|
||||
|
||||
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin)
|
||||
{
|
||||
return __ast_queue_frame(chan, fin, 0);
|
||||
return __ast_queue_frame(chan, fin, 0, NULL);
|
||||
}
|
||||
|
||||
int ast_queue_frame_head(struct ast_channel *chan, struct ast_frame *fin)
|
||||
{
|
||||
return __ast_queue_frame(chan, fin, 1);
|
||||
return __ast_queue_frame(chan, fin, 1, NULL);
|
||||
}
|
||||
|
||||
/*! \brief Queue a hangup frame for channel */
|
||||
@@ -2150,7 +2180,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
|
||||
AST_LIST_REMOVE_CURRENT(&chan->readq, frame_list);
|
||||
break;
|
||||
}
|
||||
AST_LIST_TRAVERSE_SAFE_END
|
||||
AST_LIST_TRAVERSE_SAFE_END;
|
||||
|
||||
if (!f) {
|
||||
/* There were no acceptable frames on the readq. */
|
||||
@@ -2195,13 +2225,14 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
|
||||
chan->fdno = -1;
|
||||
|
||||
if (f) {
|
||||
struct ast_frame *readq_tail = AST_LIST_LAST(&chan->readq);
|
||||
|
||||
/* if the channel driver returned more than one frame, stuff the excess
|
||||
into the readq for the next ast_read call (note that we can safely assume
|
||||
that the readq is empty, because otherwise we would not have called into
|
||||
the channel driver and f would be only a single frame)
|
||||
into the readq for the next ast_read call
|
||||
*/
|
||||
if (AST_LIST_NEXT(f, frame_list)) {
|
||||
AST_LIST_HEAD_SET_NOLOCK(&chan->readq, AST_LIST_NEXT(f, frame_list));
|
||||
ast_queue_frame(chan, AST_LIST_NEXT(f, frame_list));
|
||||
ast_frfree(AST_LIST_NEXT(f, frame_list));
|
||||
AST_LIST_NEXT(f, frame_list) = NULL;
|
||||
}
|
||||
|
||||
@@ -2410,8 +2441,26 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
|
||||
}
|
||||
}
|
||||
|
||||
if (chan->readtrans && (f = ast_translate(chan->readtrans, f, 1)) == NULL)
|
||||
if (chan->readtrans && (f = ast_translate(chan->readtrans, f, 1)) == NULL) {
|
||||
f = &ast_null_frame;
|
||||
}
|
||||
|
||||
/* it is possible for the translation process on chan->readtrans to have
|
||||
produced multiple frames from the single input frame we passed it; if
|
||||
this happens, queue the additional frames *before* the frames we may
|
||||
have queued earlier. if the readq was empty, put them at the head of
|
||||
the queue, and if it was not, put them just after the frame that was
|
||||
at the end of the queue.
|
||||
*/
|
||||
if (AST_LIST_NEXT(f, frame_list)) {
|
||||
if (!readq_tail) {
|
||||
ast_queue_frame_head(chan, AST_LIST_NEXT(f, frame_list));
|
||||
} else {
|
||||
__ast_queue_frame(chan, AST_LIST_NEXT(f, frame_list), 0, readq_tail);
|
||||
}
|
||||
ast_frfree(AST_LIST_NEXT(f, frame_list));
|
||||
AST_LIST_NEXT(f, frame_list) = NULL;
|
||||
}
|
||||
|
||||
/* Run generator sitting on the line if timing device not available
|
||||
* and synchronous generation of outgoing frames is necessary */
|
||||
@@ -2742,7 +2791,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
|
||||
{
|
||||
int res = -1;
|
||||
int count = 0;
|
||||
struct ast_frame *f = NULL, *f2 = NULL;
|
||||
struct ast_frame *f = NULL;
|
||||
|
||||
/*Deadlock avoidance*/
|
||||
while(ast_channel_trylock(chan)) {
|
||||
@@ -2813,10 +2862,12 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
|
||||
break;
|
||||
case AST_FRAME_DTMF_END:
|
||||
if (chan->audiohooks) {
|
||||
struct ast_frame *old_frame = fr;
|
||||
fr = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, fr);
|
||||
if (old_frame != fr)
|
||||
f = fr;
|
||||
struct ast_frame *new_frame = fr;
|
||||
|
||||
new_frame = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, fr);
|
||||
if (new_frame != fr) {
|
||||
ast_frfree(new_frame);
|
||||
}
|
||||
}
|
||||
ast_clear_flag(chan, AST_FLAG_BLOCKING);
|
||||
ast_channel_unlock(chan);
|
||||
@@ -2845,13 +2896,6 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
|
||||
if (chan->tech->write == NULL)
|
||||
break; /*! \todo XXX should return 0 maybe ? */
|
||||
|
||||
if (chan->audiohooks) {
|
||||
struct ast_frame *old_frame = fr;
|
||||
fr = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, fr);
|
||||
if (old_frame != fr)
|
||||
f2 = fr;
|
||||
}
|
||||
|
||||
/* If the frame is in the raw write format, then it's easy... just use the frame - otherwise we will have to translate */
|
||||
if (fr->subclass == chan->rawwriteformat)
|
||||
f = fr;
|
||||
@@ -2864,37 +2908,82 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
|
||||
break;
|
||||
}
|
||||
|
||||
if (chan->audiohooks) {
|
||||
struct ast_frame *new_frame, *cur;
|
||||
|
||||
for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
|
||||
new_frame = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, cur);
|
||||
if (new_frame != cur) {
|
||||
ast_frfree(new_frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If Monitor is running on this channel, then we have to write frames out there too */
|
||||
/* the translator on chan->writetrans may have returned multiple frames
|
||||
from the single frame we passed in; if so, feed each one of them to the
|
||||
monitor */
|
||||
if (chan->monitor && chan->monitor->write_stream) {
|
||||
struct ast_frame *cur;
|
||||
|
||||
for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
|
||||
/* XXX must explain this code */
|
||||
#ifndef MONITOR_CONSTANT_DELAY
|
||||
int jump = chan->insmpl - chan->outsmpl - 4 * f->samples;
|
||||
if (jump >= 0) {
|
||||
jump = chan->insmpl - chan->outsmpl;
|
||||
if (ast_seekstream(chan->monitor->write_stream, jump, SEEK_FORCECUR) == -1)
|
||||
ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
|
||||
chan->outsmpl += jump + f->samples;
|
||||
} else
|
||||
chan->outsmpl += f->samples;
|
||||
int jump = chan->insmpl - chan->outsmpl - 4 * cur->samples;
|
||||
if (jump >= 0) {
|
||||
jump = chan->insmpl - chan->outsmpl;
|
||||
if (ast_seekstream(chan->monitor->write_stream, jump, SEEK_FORCECUR) == -1)
|
||||
ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
|
||||
chan->outsmpl += jump + cur->samples;
|
||||
} else {
|
||||
chan->outsmpl += cur->samples;
|
||||
}
|
||||
#else
|
||||
int jump = chan->insmpl - chan->outsmpl;
|
||||
if (jump - MONITOR_DELAY >= 0) {
|
||||
if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1)
|
||||
ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
|
||||
chan->outsmpl += jump;
|
||||
} else
|
||||
chan->outsmpl += f->samples;
|
||||
int jump = chan->insmpl - chan->outsmpl;
|
||||
if (jump - MONITOR_DELAY >= 0) {
|
||||
if (ast_seekstream(chan->monitor->write_stream, jump - cur->samples, SEEK_FORCECUR) == -1)
|
||||
ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
|
||||
chan->outsmpl += jump;
|
||||
} else {
|
||||
chan->outsmpl += cur->samples;
|
||||
}
|
||||
#endif
|
||||
if (chan->monitor->state == AST_MONITOR_RUNNING) {
|
||||
if (ast_writestream(chan->monitor->write_stream, f) < 0)
|
||||
ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
|
||||
if (chan->monitor->state == AST_MONITOR_RUNNING) {
|
||||
if (ast_writestream(chan->monitor->write_stream, cur) < 0)
|
||||
ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (f)
|
||||
res = chan->tech->write(chan,f);
|
||||
else
|
||||
res = 0;
|
||||
/* the translator on chan->writetrans may have returned multiple frames
|
||||
from the single frame we passed in; if so, feed each one of them to the
|
||||
channel, freeing each one after it has been written */
|
||||
if ((f != fr) && AST_LIST_NEXT(f, frame_list)) {
|
||||
struct ast_frame *cur, *next;
|
||||
unsigned int skip = 0;
|
||||
|
||||
for (cur = f, next = AST_LIST_NEXT(cur, frame_list);
|
||||
cur;
|
||||
cur = next, next = cur ? AST_LIST_NEXT(cur, frame_list) : NULL) {
|
||||
if (!skip) {
|
||||
if ((res = chan->tech->write(chan, cur)) < 0) {
|
||||
chan->_softhangup |= AST_SOFTHANGUP_DEV;
|
||||
skip = 1;
|
||||
} else if (next) {
|
||||
/* don't do this for the last frame in the list,
|
||||
as the code outside the loop will do it once
|
||||
*/
|
||||
chan->fout = FRAMECOUNT_INC(chan->fout);
|
||||
}
|
||||
}
|
||||
ast_frfree(cur);
|
||||
}
|
||||
|
||||
/* reset f so the code below doesn't attempt to free it */
|
||||
f = NULL;
|
||||
} else {
|
||||
res = chan->tech->write(chan, f);
|
||||
}
|
||||
break;
|
||||
case AST_FRAME_NULL:
|
||||
case AST_FRAME_IAX:
|
||||
@@ -2911,13 +3000,12 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
|
||||
|
||||
if (f && f != fr)
|
||||
ast_frfree(f);
|
||||
if (f2)
|
||||
ast_frfree(f2);
|
||||
ast_clear_flag(chan, AST_FLAG_BLOCKING);
|
||||
|
||||
/* Consider a write failure to force a soft hangup */
|
||||
if (res < 0)
|
||||
if (res < 0) {
|
||||
chan->_softhangup |= AST_SOFTHANGUP_DEV;
|
||||
else {
|
||||
} else {
|
||||
chan->fout = FRAMECOUNT_INC(chan->fout);
|
||||
}
|
||||
done:
|
||||
|
18
main/file.c
18
main/file.c
@@ -203,14 +203,20 @@ int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
|
||||
struct ast_frame *trf;
|
||||
fs->lastwriteformat = f->subclass;
|
||||
/* Get the translated frame but don't consume the original in case they're using it on another stream */
|
||||
trf = ast_translate(fs->trans, f, 0);
|
||||
if (trf) {
|
||||
res = fs->fmt->write(fs, trf);
|
||||
if ((trf = ast_translate(fs->trans, f, 0))) {
|
||||
struct ast_frame *cur;
|
||||
|
||||
/* the translator may have returned multiple frames, so process them */
|
||||
for (cur = trf; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
|
||||
if ((res = fs->fmt->write(fs, trf))) {
|
||||
ast_log(LOG_WARNING, "Translated frame write failed\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
ast_frfree(trf);
|
||||
if (res)
|
||||
ast_log(LOG_WARNING, "Translated frame write failed\n");
|
||||
} else
|
||||
} else {
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
127
main/frame.c
127
main/frame.c
@@ -47,11 +47,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/dsp.h"
|
||||
#include "asterisk/file.h"
|
||||
|
||||
#ifdef TRACE_FRAMES
|
||||
static int headers;
|
||||
static AST_LIST_HEAD_STATIC(headerlist, ast_frame);
|
||||
#endif
|
||||
|
||||
#if !defined(LOW_MEMORY)
|
||||
static void frame_cache_cleanup(void *data);
|
||||
|
||||
@@ -291,7 +286,7 @@ struct ast_frame *ast_smoother_read(struct ast_smoother *s)
|
||||
memmove(s->data, s->data + len, s->len);
|
||||
if (!ast_tvzero(s->delivery)) {
|
||||
/* If we have delivery time, increment it, otherwise, leave it at 0 */
|
||||
s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, 8000));
|
||||
s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, ast_format_rate(s->format)));
|
||||
}
|
||||
}
|
||||
/* Return frame */
|
||||
@@ -328,12 +323,6 @@ static struct ast_frame *ast_frame_header_new(void)
|
||||
#endif
|
||||
|
||||
f->mallocd_hdr_len = sizeof(*f);
|
||||
#ifdef TRACE_FRAMES
|
||||
AST_LIST_LOCK(&headerlist);
|
||||
headers++;
|
||||
AST_LIST_INSERT_HEAD(&headerlist, f, frame_list);
|
||||
AST_LIST_UNLOCK(&headerlist);
|
||||
#endif
|
||||
|
||||
return f;
|
||||
}
|
||||
@@ -351,7 +340,7 @@ static void frame_cache_cleanup(void *data)
|
||||
}
|
||||
#endif
|
||||
|
||||
void ast_frame_free(struct ast_frame *fr, int cache)
|
||||
static void __frame_free(struct ast_frame *fr, int cache)
|
||||
{
|
||||
if (ast_test_flag(fr, AST_FRFLAG_FROM_TRANSLATOR)) {
|
||||
ast_translate_frame_freed(fr);
|
||||
@@ -370,8 +359,8 @@ void ast_frame_free(struct ast_frame *fr, int cache)
|
||||
* to keep things simple... */
|
||||
struct ast_frame_cache *frames;
|
||||
|
||||
if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))
|
||||
&& frames->size < FRAME_CACHE_MAX_SIZE) {
|
||||
if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames))) &&
|
||||
(frames->size < FRAME_CACHE_MAX_SIZE)) {
|
||||
AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
|
||||
frames->size++;
|
||||
return;
|
||||
@@ -385,19 +374,25 @@ void ast_frame_free(struct ast_frame *fr, int cache)
|
||||
}
|
||||
if (fr->mallocd & AST_MALLOCD_SRC) {
|
||||
if (fr->src)
|
||||
free((char *)fr->src);
|
||||
free((void *)fr->src);
|
||||
}
|
||||
if (fr->mallocd & AST_MALLOCD_HDR) {
|
||||
#ifdef TRACE_FRAMES
|
||||
AST_LIST_LOCK(&headerlist);
|
||||
headers--;
|
||||
AST_LIST_REMOVE(&headerlist, fr, frame_list);
|
||||
AST_LIST_UNLOCK(&headerlist);
|
||||
#endif
|
||||
free(fr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ast_frame_free(struct ast_frame *frame, int cache)
|
||||
{
|
||||
struct ast_frame *next;
|
||||
|
||||
for (next = AST_LIST_NEXT(frame, frame_list);
|
||||
frame;
|
||||
frame = next, next = frame ? AST_LIST_NEXT(frame, frame_list) : NULL) {
|
||||
__frame_free(frame, cache);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief 'isolates' a frame by duplicating non-malloc'ed components
|
||||
* (header, src, data).
|
||||
@@ -408,19 +403,29 @@ struct ast_frame *ast_frisolate(struct ast_frame *fr)
|
||||
struct ast_frame *out;
|
||||
void *newdata;
|
||||
|
||||
ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR);
|
||||
ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
|
||||
/* if none of the existing frame is malloc'd, let ast_frdup() do it
|
||||
since it is more efficient
|
||||
*/
|
||||
if (fr->mallocd == 0) {
|
||||
return ast_frdup(fr);
|
||||
}
|
||||
|
||||
/* if everything is already malloc'd, we are done */
|
||||
if ((fr->mallocd & (AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA)) ==
|
||||
(AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA)) {
|
||||
return fr;
|
||||
}
|
||||
|
||||
if (!(fr->mallocd & AST_MALLOCD_HDR)) {
|
||||
/* Allocate a new header if needed */
|
||||
if (!(out = ast_frame_header_new()))
|
||||
if (!(out = ast_frame_header_new())) {
|
||||
return NULL;
|
||||
}
|
||||
out->frametype = fr->frametype;
|
||||
out->subclass = fr->subclass;
|
||||
out->datalen = fr->datalen;
|
||||
out->samples = fr->samples;
|
||||
out->offset = fr->offset;
|
||||
out->data = fr->data;
|
||||
/* Copy the timing data */
|
||||
ast_copy_flags(out, fr, AST_FRFLAG_HAS_TIMING_INFO);
|
||||
if (ast_test_flag(fr, AST_FRFLAG_HAS_TIMING_INFO)) {
|
||||
@@ -428,26 +433,34 @@ struct ast_frame *ast_frisolate(struct ast_frame *fr)
|
||||
out->len = fr->len;
|
||||
out->seqno = fr->seqno;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR);
|
||||
ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
|
||||
ast_clear_flag(fr, AST_FRFLAG_FROM_FILESTREAM);
|
||||
out = fr;
|
||||
}
|
||||
|
||||
if (!(fr->mallocd & AST_MALLOCD_SRC)) {
|
||||
if (fr->src) {
|
||||
if (!(out->src = ast_strdup(fr->src))) {
|
||||
if (out != fr)
|
||||
free(out);
|
||||
return NULL;
|
||||
if (!(fr->mallocd & AST_MALLOCD_SRC) && fr->src) {
|
||||
if (!(out->src = ast_strdup(fr->src))) {
|
||||
if (out != fr) {
|
||||
free(out);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
out->src = fr->src;
|
||||
fr->src = NULL;
|
||||
fr->mallocd &= ~AST_MALLOCD_SRC;
|
||||
}
|
||||
|
||||
if (!(fr->mallocd & AST_MALLOCD_DATA)) {
|
||||
if (!(newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET))) {
|
||||
if (out->src != fr->src)
|
||||
if (out->src != fr->src) {
|
||||
free((void *) out->src);
|
||||
if (out != fr)
|
||||
}
|
||||
if (out != fr) {
|
||||
free(out);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
newdata += AST_FRIENDLY_OFFSET;
|
||||
@@ -455,6 +468,10 @@ struct ast_frame *ast_frisolate(struct ast_frame *fr)
|
||||
out->datalen = fr->datalen;
|
||||
memcpy(newdata, fr->data, fr->datalen);
|
||||
out->data = newdata;
|
||||
} else {
|
||||
out->data = fr->data;
|
||||
fr->data = NULL;
|
||||
fr->mallocd &= ~AST_MALLOCD_DATA;
|
||||
}
|
||||
|
||||
out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
|
||||
@@ -497,7 +514,7 @@ struct ast_frame *ast_frdup(const struct ast_frame *f)
|
||||
break;
|
||||
}
|
||||
}
|
||||
AST_LIST_TRAVERSE_SAFE_END
|
||||
AST_LIST_TRAVERSE_SAFE_END;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -970,29 +987,6 @@ void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
|
||||
}
|
||||
|
||||
|
||||
#ifdef TRACE_FRAMES
|
||||
static int show_frame_stats(int fd, int argc, char *argv[])
|
||||
{
|
||||
struct ast_frame *f;
|
||||
int x=1;
|
||||
if (argc != 4)
|
||||
return RESULT_SHOWUSAGE;
|
||||
AST_LIST_LOCK(&headerlist);
|
||||
ast_cli(fd, " Framer Statistics \n");
|
||||
ast_cli(fd, "---------------------------\n");
|
||||
ast_cli(fd, "Total allocated headers: %d\n", headers);
|
||||
ast_cli(fd, "Queue Dump:\n");
|
||||
AST_LIST_TRAVERSE(&headerlist, f, frame_list)
|
||||
ast_cli(fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
|
||||
AST_LIST_UNLOCK(&headerlist);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static char frame_stats_usage[] =
|
||||
"Usage: core show frame stats\n"
|
||||
" Displays debugging statistics from framer\n";
|
||||
#endif
|
||||
|
||||
/* Builtin Asterisk CLI-commands for debugging */
|
||||
static struct ast_cli_entry cli_show_codecs = {
|
||||
{ "show", "codecs", NULL },
|
||||
@@ -1019,13 +1013,6 @@ static struct ast_cli_entry cli_show_codec = {
|
||||
show_codec_n_deprecated, NULL,
|
||||
NULL };
|
||||
|
||||
#ifdef TRACE_FRAMES
|
||||
static struct ast_cli_entry cli_show_frame_stats = {
|
||||
{ "show", "frame", "stats", NULL },
|
||||
show_frame_stats, NULL,
|
||||
NULL };
|
||||
#endif
|
||||
|
||||
static struct ast_cli_entry my_clis[] = {
|
||||
{ { "core", "show", "codecs", NULL },
|
||||
show_codecs, "Displays a list of codecs",
|
||||
@@ -1046,12 +1033,6 @@ static struct ast_cli_entry my_clis[] = {
|
||||
{ { "core", "show", "codec", NULL },
|
||||
show_codec_n, "Shows a specific codec",
|
||||
frame_show_codec_n_usage, NULL, &cli_show_codec },
|
||||
|
||||
#ifdef TRACE_FRAMES
|
||||
{ { "core", "show", "frame", "stats", NULL },
|
||||
show_frame_stats, "Shows frame statistics",
|
||||
frame_stats_usage, NULL, &cli_show_frame_stats },
|
||||
#endif
|
||||
};
|
||||
|
||||
int init_framer(void)
|
||||
|
@@ -57,7 +57,7 @@ void ast_slinfactory_destroy(struct ast_slinfactory *sf)
|
||||
int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
|
||||
{
|
||||
struct ast_frame *begin_frame = f, *duped_frame = NULL, *frame_ptr;
|
||||
unsigned int x;
|
||||
unsigned int x = 0;
|
||||
|
||||
/* In some cases, we can be passed a frame which has no data in it, but
|
||||
* which has a positive number of samples defined. Once such situation is
|
||||
@@ -84,27 +84,33 @@ int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
|
||||
}
|
||||
}
|
||||
|
||||
if (!(begin_frame = ast_translate(sf->trans, f, 0)))
|
||||
if (!(begin_frame = ast_translate(sf->trans, f, 0))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
duped_frame = ast_frdup(begin_frame);
|
||||
|
||||
ast_frfree(begin_frame);
|
||||
|
||||
if (!duped_frame)
|
||||
if (!(duped_frame = ast_frisolate(begin_frame))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (duped_frame != begin_frame) {
|
||||
ast_frfree(begin_frame);
|
||||
}
|
||||
} else {
|
||||
if (!(duped_frame = ast_frdup(f)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
x = 0;
|
||||
AST_LIST_TRAVERSE(&sf->queue, frame_ptr, frame_list)
|
||||
AST_LIST_TRAVERSE(&sf->queue, frame_ptr, frame_list) {
|
||||
x++;
|
||||
}
|
||||
|
||||
AST_LIST_INSERT_TAIL(&sf->queue, duped_frame, frame_list);
|
||||
|
||||
sf->size += duped_frame->samples;
|
||||
/* if the frame was translated, the translator may have returned multiple
|
||||
frames, so process each of them
|
||||
*/
|
||||
for (begin_frame = duped_frame; begin_frame; begin_frame = AST_LIST_NEXT(begin_frame, frame_list)) {
|
||||
AST_LIST_INSERT_TAIL(&sf->queue, begin_frame, frame_list);
|
||||
sf->size += begin_frame->samples;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
@@ -43,6 +43,8 @@ GC_LDFLAGS=@GC_LDFLAGS@
|
||||
PTHREAD_CFLAGS=@PTHREAD_CFLAGS@
|
||||
PTHREAD_LIBS=@PTHREAD_LIBS@
|
||||
|
||||
GNU_LD=@GNU_LD@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
|
33
res/res_adsi.exports
Normal file
33
res/res_adsi.exports
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
global:
|
||||
ast_adsi_available;
|
||||
ast_adsi_begin_download;
|
||||
ast_adsi_channel_restore;
|
||||
ast_adsi_clear_screen;
|
||||
ast_adsi_clear_soft_keys;
|
||||
ast_adsi_connect_session;
|
||||
ast_adsi_data_mode;
|
||||
ast_adsi_disconnect_session;
|
||||
ast_adsi_display;
|
||||
ast_adsi_download_connect;
|
||||
ast_adsi_download_disconnect;
|
||||
ast_adsi_end_download;
|
||||
ast_adsi_get_cpeid;
|
||||
ast_adsi_get_cpeinfo;
|
||||
ast_adsi_input_control;
|
||||
ast_adsi_input_format;
|
||||
ast_adsi_load_session;
|
||||
ast_adsi_load_soft_key;
|
||||
ast_adsi_print;
|
||||
ast_adsi_query_cpeid;
|
||||
ast_adsi_query_cpeinfo;
|
||||
ast_adsi_read_encoded_dtmf;
|
||||
ast_adsi_set_keys;
|
||||
ast_adsi_set_line;
|
||||
ast_adsi_transmit_message;
|
||||
ast_adsi_transmit_message_full;
|
||||
ast_adsi_unload_session;
|
||||
ast_adsi_voice_mode;
|
||||
local:
|
||||
*;
|
||||
};
|
7
res/res_agi.exports
Normal file
7
res/res_agi.exports
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
global:
|
||||
ast_agi_register;
|
||||
ast_agi_unregister;
|
||||
local:
|
||||
*;
|
||||
};
|
@@ -558,7 +558,7 @@ static int load_module (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "ODBC Configuration",
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ODBC Configuration",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
);
|
||||
|
@@ -835,7 +835,7 @@ static int realtime_pgsql_status(int fd, int argc, char **argv)
|
||||
}
|
||||
|
||||
/* needs usecount semantics defined */
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "PostgreSQL RealTime Configuration Driver",
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "PostgreSQL RealTime Configuration Driver",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.reload = reload
|
||||
|
@@ -624,7 +624,7 @@ static int unload_module(void)
|
||||
}
|
||||
|
||||
/* needs usecount semantics defined */
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Cryptographic Digital Signatures",
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Cryptographic Digital Signatures",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.reload = reload
|
||||
|
13
res/res_features.exports
Normal file
13
res/res_features.exports
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
global:
|
||||
ast_bridge_call;
|
||||
ast_masq_park_call;
|
||||
ast_park_call;
|
||||
ast_parking_ext;
|
||||
ast_pickup_call;
|
||||
ast_pickup_ext;
|
||||
ast_register_feature;
|
||||
ast_unregister_feature;
|
||||
local:
|
||||
*;
|
||||
};
|
@@ -399,7 +399,7 @@ static int reload(void)
|
||||
return ind_load_module();
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Indications Resource",
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Indications Resource",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.reload = reload,
|
||||
|
13
res/res_jabber.exports
Normal file
13
res/res_jabber.exports
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
global:
|
||||
ast_aji_create_chat;
|
||||
ast_aji_disconnect;
|
||||
ast_aji_get_client;
|
||||
ast_aji_get_clients;
|
||||
ast_aji_increment_mid;
|
||||
ast_aji_invite_chat;
|
||||
ast_aji_join_chat;
|
||||
ast_aji_send;
|
||||
local:
|
||||
*;
|
||||
};
|
11
res/res_monitor.exports
Normal file
11
res/res_monitor.exports
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
global:
|
||||
ast_monitor_change_fname;
|
||||
ast_monitor_pause;
|
||||
ast_monitor_setjoinfiles;
|
||||
ast_monitor_start;
|
||||
ast_monitor_stop;
|
||||
ast_monitor_unpause;
|
||||
local:
|
||||
*;
|
||||
};
|
@@ -1486,7 +1486,7 @@ static int unload_module(void)
|
||||
return res;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Music On Hold Resource",
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Music On Hold Resource",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.reload = reload,
|
||||
|
11
res/res_odbc.exports
Normal file
11
res/res_odbc.exports
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
global:
|
||||
ast_odbc_backslash_is_escape;
|
||||
ast_odbc_prepare_and_execute;
|
||||
ast_odbc_release_obj;
|
||||
ast_odbc_request_obj;
|
||||
ast_odbc_sanity_check;
|
||||
ast_odbc_smart_execute;
|
||||
local:
|
||||
*;
|
||||
};
|
18
res/res_smdi.exports
Normal file
18
res/res_smdi.exports
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
global:
|
||||
ast_smdi_interface_find;
|
||||
ast_smdi_interface_unref;
|
||||
ast_smdi_md_message_destroy;
|
||||
ast_smdi_md_message_pop;
|
||||
ast_smdi_md_message_putback;
|
||||
ast_smdi_md_message_wait;
|
||||
ast_smdi_mwi_message_destroy;
|
||||
ast_smdi_mwi_message_pop;
|
||||
ast_smdi_mwi_message_putback;
|
||||
ast_smdi_mwi_message_wait;
|
||||
ast_smdi_mwi_message_wait_station;
|
||||
ast_smdi_mwi_set;
|
||||
ast_smdi_mwi_unset;
|
||||
local:
|
||||
*;
|
||||
};
|
@@ -109,7 +109,7 @@ static int unload_module(void)
|
||||
return ((thread != AST_PTHREADT_NULL) ? pthread_join(thread, NULL) : 0);
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "SNMP [Sub]Agent for Asterisk",
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "SNMP [Sub]Agent for Asterisk",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
);
|
||||
|
21
res/res_speech.exports
Normal file
21
res/res_speech.exports
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
global:
|
||||
ast_speech_change;
|
||||
ast_speech_change_results_type;
|
||||
ast_speech_change_state;
|
||||
ast_speech_destroy;
|
||||
ast_speech_dtmf;
|
||||
ast_speech_grammar_activate;
|
||||
ast_speech_grammar_deactivate;
|
||||
ast_speech_grammar_load;
|
||||
ast_speech_grammar_unload;
|
||||
ast_speech_new;
|
||||
ast_speech_register;
|
||||
ast_speech_results_free;
|
||||
ast_speech_results_get;
|
||||
ast_speech_start;
|
||||
ast_speech_unregister;
|
||||
ast_speech_write;
|
||||
local:
|
||||
*;
|
||||
};
|
Reference in New Issue
Block a user