diff options
-rw-r--r-- | testing/asterisk/100-uclibc-daemon.patch | 44 | ||||
-rw-r--r-- | testing/asterisk/101-caps-uclibc.patch | 17 | ||||
-rw-r--r-- | testing/asterisk/102-gsm-pic.patch | 54 | ||||
-rw-r--r-- | testing/asterisk/APKBUILD | 191 | ||||
-rw-r--r-- | testing/asterisk/ASTERISK-18995.patch | 358 | ||||
-rw-r--r-- | testing/asterisk/ASTERISK-19109.patch | 724 | ||||
-rw-r--r-- | testing/asterisk/ASTERISK-20362.patch | 30 | ||||
-rw-r--r-- | testing/asterisk/asterisk.confd | 91 | ||||
-rw-r--r-- | testing/asterisk/asterisk.initd | 251 | ||||
-rw-r--r-- | testing/asterisk/asterisk.logrotate | 17 | ||||
-rw-r--r-- | testing/asterisk/asterisk.pre-install | 6 | ||||
-rw-r--r-- | testing/asterisk/asterisk.pre-upgrade | 6 |
12 files changed, 1789 insertions, 0 deletions
diff --git a/testing/asterisk/100-uclibc-daemon.patch b/testing/asterisk/100-uclibc-daemon.patch new file mode 100644 index 000000000..4956791d4 --- /dev/null +++ b/testing/asterisk/100-uclibc-daemon.patch @@ -0,0 +1,44 @@ +diff -Nru asterisk-1.6.1-beta4.org/main/asterisk.c asterisk-1.6.1-beta4/main/asterisk.c +--- asterisk-1.6.1-beta4.org/main/asterisk.c 2008-12-12 23:05:58.000000000 +0100 ++++ asterisk-1.6.1-beta4/main/asterisk.c 2008-12-23 15:28:21.000000000 +0100 +@@ -3295,9 +3295,40 @@ + #if HAVE_WORKING_FORK + if (ast_opt_always_fork || !ast_opt_no_fork) { + #ifndef HAVE_SBIN_LAUNCHD ++#ifndef __UCLIBC__ + if (daemon(1, 0) < 0) { + ast_log(LOG_ERROR, "daemon() failed: %s\n", strerror(errno)); + } ++#else ++ /* ++ * workaround for uClibc-0.9.29 mipsel bug: ++ * recursive mutexes do not work if uClibc daemon() function has been called, ++ * if parent thread locks a mutex ++ * the child thread cannot acquire a lock with the same name ++ * (same code works if daemon() is not called) ++ * but duplication of uClibc daemon.c code in here does work. ++ */ ++ int fd; ++ switch (fork()) { ++ case -1: ++ exit(1); ++ case 0: ++ break; ++ default: ++ _exit(0); ++ } ++ if (setsid() == -1) ++ exit(1); ++ if (fork()) ++ _exit(0); ++ if ((fd = open("/dev/null", O_RDWR, 0)) != -1) { ++ dup2(fd, STDIN_FILENO); ++ dup2(fd, STDOUT_FILENO); ++ dup2(fd, STDERR_FILENO); ++ if (fd > 2) ++ close(fd); ++ } ++#endif + ast_mainpid = getpid(); + /* Blindly re-write pid file since we are forking */ + unlink(ast_config_AST_PID); diff --git a/testing/asterisk/101-caps-uclibc.patch b/testing/asterisk/101-caps-uclibc.patch new file mode 100644 index 000000000..bb32d1ece --- /dev/null +++ b/testing/asterisk/101-caps-uclibc.patch @@ -0,0 +1,17 @@ +--- asterisk-1.6.0.18/configure.ac.orig Mon Oct 26 23:13:28 2009 ++++ asterisk-1.6.0.18/configure.ac Fri Nov 27 21:42:36 2009 +@@ -627,9 +627,11 @@ + + AST_EXT_LIB_CHECK([CURSES], [curses], [initscr], [curses.h]) + +-if test "x${OSARCH}" = "xlinux-gnu" ; then +- AST_EXT_LIB_CHECK([CAP], [cap], [cap_from_text], [sys/capability.h]) +-fi ++case "${OSARCH}" in ++ linux*) ++ AST_EXT_LIB_CHECK([CAP], [cap], [cap_from_text], [sys/capability.h]) ++ ;; ++esac + + AST_C_DEFINE_CHECK([DAHDI], [DAHDI_CODE], [dahdi/user.h]) + diff --git a/testing/asterisk/102-gsm-pic.patch b/testing/asterisk/102-gsm-pic.patch new file mode 100644 index 000000000..71370ec0b --- /dev/null +++ b/testing/asterisk/102-gsm-pic.patch @@ -0,0 +1,54 @@ +--- a/codecs/gsm/Makefile.org 2008-03-29 11:33:09.000000000 +0100 ++++ b/codecs/gsm/Makefile 2008-03-29 11:44:40.000000000 +0100 +@@ -37,23 +37,6 @@ + ######### ppro's, etc, as well as the AMD K6 and K7. The compile will + ######### probably require gcc. + +-ifeq (, $(findstring $(OSARCH) , Darwin SunOS )) +-ifeq (, $(findstring $(PROC) , x86_64 amd64 ultrasparc sparc64 arm armv5b armeb ppc powerpc ppc64 ia64 s390 bfin mipsel mips)) +-ifeq (, $(findstring $(shell uname -m) , ppc ppc64 alpha armv4l s390 )) +-OPTIMIZE+=-march=$(PROC) +-endif +-endif +-endif +- +-#The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only. +-#This works for even old (2.96) versions of gcc and provides a small boost either way. +-#A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesn't support it. +-#So we go lowest common available by gcc and go a step down, still a step up from +-#the default as we now have a better instruction set to work with. - Belgarath +-ifeq ($(PROC),ultrasparc) +-OPTIMIZE+=-mcpu=v8 -mtune=$(PROC) -O3 +-endif +- + PG = + #PG = -g -pg + ######### Profiling flags. If you don't know what that means, leave it blank. +@@ -208,12 +191,10 @@ + # XXX Keep a space after each findstring argument + # XXX should merge with GSM_OBJECTS + ifeq ($(OSARCH),linux-gnu) +-ifeq (,$(findstring $(shell uname -m) , x86_64 amd64 ppc ppc64 alpha armv4l sparc64 parisc s390 )) +-ifeq (,$(findstring $(PROC) , arm armv5b armeb powerpc ia64 s390 bfin mipsel mips )) ++ifneq ($(K6OPT),) + GSM_SOURCES+= $(SRC)/k6opt.s + endif + endif +-endif + + TOAST_SOURCES = $(SRC)/toast.c \ + $(SRC)/toast_lin.c \ +@@ -260,12 +241,10 @@ + $(SRC)/table.o + + ifeq ($(OSARCH),linux-gnu) +-ifeq (,$(findstring $(shell uname -m) , x86_64 amd64 ppc ppc64 alpha armv4l sparc64 parisc )) +-ifeq (,$(findstring $(PROC) , arm armv5b armeb powerpc ia64 bfin mipsel mips )) ++ifneq ($(K6OPT),) + GSM_OBJECTS+= $(SRC)/k6opt.o + endif + endif +-endif + + TOAST_OBJECTS = $(SRC)/toast.o \ + $(SRC)/toast_lin.o \ diff --git a/testing/asterisk/APKBUILD b/testing/asterisk/APKBUILD new file mode 100644 index 000000000..82768e994 --- /dev/null +++ b/testing/asterisk/APKBUILD @@ -0,0 +1,191 @@ +# Contributor: Timo Teras <timo.teras@iki.fi> +# Maintainer: Timo Teras <timo.teras@iki.fi> +pkgname=asterisk +pkgver=11.0.0_beta1 +pkgrel=0 +pkgdesc="Asterisk: A Module Open Source PBX System" +pkgusers="asterisk" +pkggroups="asterisk" +url="http://www.asterisk.org/" +arch="all" +license="GPL" +depends= +makedepends="autoconf automake libtool ncurses-dev popt-dev newt-dev zlib-dev + postgresql-dev unixodbc-dev dahdi-tools-dev libpri-dev tar + freetds-dev openssl-dev lua-dev alsa-lib-dev spandsp-dev tiff-dev + libresample sqlite-dev wget speex-dev libogg-dev bluez-dev" +install="$pkgname.pre-install $pkgname.pre-upgrade" +subpackages="$pkgname-dev $pkgname-doc $pkgname-pgsql $pkgname-odbc + $pkgname-tds $pkgname-fax $pkgname-sample-config:sample + $pkgname-sounds-moh:sound_moh $pkgname-sounds-en:sound_en + $pkgname-mobile" +source="http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-${pkgver/_/-}.tar.gz + 100-uclibc-daemon.patch + 101-caps-uclibc.patch + ASTERISK-18995.patch + ASTERISK-19109.patch + ASTERISK-20362.patch + asterisk.initd + asterisk.confd + asterisk.logrotate" + +_builddir="$srcdir/$pkgname-${pkgver/_/-}" + +prepare() { + cd "$_builddir" + for i in ../[1-9A]*.patch; do + msg "Apply $i" + patch -p1 < $i || return 1 + done + + sed -i -e 's:lua5.1/::' pbx/pbx_lua.c + sed -i -e 's/PBX_ICONV=1/PBX_ICONV=0/g' configure.ac + sed -i -e 's/int foo = res_ninit(NULL);/res_ninit_is_not_really_here();/g' configure.ac + + ./bootstrap.sh +} + +build() { + cd "$_builddir" + SHA1SUM="$PWD"/build_tools/sha1sum-sh ./configure --prefix=/usr \ + --sysconfdir=/etc \ + --mandir=/usr/share/man \ + --infodir=/usr/share/info \ + --libdir=/usr/lib \ + --localstatedir=/var \ + --disable-xmldoc --with-gsm=internal \ + --without-iconv --with-popt --with-z --with-newt \ + --with-unixodbc --with-postgres --with-tds \ + --with-dahdi --with-pri --with-tonezone \ + --with-resample \ + --with-sqlite3 \ + --with-speex \ + --with-asound \ + --without-x11 \ + --with-spandsp \ + --with-bluetooth \ + || return 1 + + # and figure out which modules to build + rm menuselect.makeopts + make menuselect.makeopts + # enable chan_mobile + sed -i -e '/^MENUSELECT_ADDONS=/s/chan_mobile//' menuselect.makeopts + make ASTCFLAGS="$CFLAGS" ASTLDFLAGS="$LDFLAGS" || return 1 +} + +package() { + cd "$_builddir" + make -j1 DESTDIR="$pkgdir" install + + install -d "$pkgdir"/var/run/asterisk + install -d "$pkgdir"/var/lib/asterisk + + install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname + install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname + install -m644 -D "$srcdir"/$pkgname.logrotate \ + "$pkgdir"/etc/logrotate.d/$pkgname + + chown -R asterisk:asterisk "$pkgdir"/var/*/asterisk + chown -R asterisk:asterisk "$pkgdir"/etc/asterisk + chmod -R u=rwX,g=rX,o= "$pkgdir"/etc/asterisk +} + +_move_dir() { + for DIR in "$@"; do + local dest=`dirname "$subpkgdir/$DIR"` + echo mkdir -p $dest + mkdir -p "$dest" + echo mv "$pkgdir"/$DIR $dest + mv "$pkgdir"/"$DIR" "$dest" + done +} + +_find_and_move() { + local pattern="$1" + cd "$pkgdir" || return 1 + find -name "$pattern" -type f | while read f; do + local dest="$subpkgdir/${f%/*}" + mkdir -p "$dest" + mv "$f" "$dest" + done +} + +doc() { + default_doc +} + +dev() { + default_dev + depends="asterisk" +} + +pgsql() { + depends= + install= + _find_and_move '*_pgsql*' +} + +odbc() { + depends= + install= + _find_and_move '*odbc*' +} + +tds() { + depends= + install= + _find_and_move '*_tds*' +} + +fax() { + depends= + install= + _find_and_move '*_fax*' +} + +mobile() { + depends= + install= + _find_and_move '*_mobile*' +} + +sample() { + arch="noarch" + pkgdesc="Sample configuration files for asterisk" + cd "$_builddir" + mkdir -p "$subpkgdir"/var/lib/asterisk/phoneprov + make -j1 samples DESTDIR="$subpkgdir" + + chown -R asterisk:asterisk "$subpkgdir"/var/*/asterisk + chown -R asterisk:asterisk "$subpkgdir"/etc/asterisk + chmod -R u=rwX,g=rX,o= "$subpkgdir"/etc/asterisk +} + +sound_moh() { + arch="noarch" + pkgdesc="Default on-hold music files for asterisk" + depends= + install= + _move_dir var/lib/asterisk/moh + chown -R asterisk:asterisk "$subpkgdir"/var/*/asterisk +} + +sound_en() { + arch="noarch" + pkgdesc="English sound files for asterisk" + depends= + install= + _move_dir var/lib/asterisk/sounds/en + chown -R asterisk:asterisk "$subpkgdir"/var/*/asterisk +} + +md5sums="a99bdeae82f80b25b093eba957581dd9 asterisk-11.0.0-beta1.tar.gz +b00c9d98ce2ad445501248a197c6e436 100-uclibc-daemon.patch +6e1129e30c4fd2c25c86c81685a485a9 101-caps-uclibc.patch +bc6713f5434e07b79d3afdd155461d72 ASTERISK-18995.patch +146befabe95798a67c58d8ac00d397a6 ASTERISK-19109.patch +491aa86a1b3b6d1b9c8dd72314e9859f ASTERISK-20362.patch +74cd25a5638a94ef51e9f4ede2fd28f2 asterisk.initd +ed31d7ba37bcf8b0346dcf8593c395f0 asterisk.confd +3e65172275684373e1a25c8a11224411 asterisk.logrotate" diff --git a/testing/asterisk/ASTERISK-18995.patch b/testing/asterisk/ASTERISK-18995.patch new file mode 100644 index 000000000..cd144847b --- /dev/null +++ b/testing/asterisk/ASTERISK-18995.patch @@ -0,0 +1,358 @@ +--- /dev/null 2011-11-29 09:02:40.279581283 +0200 ++++ b/formats/format_ogg_speex.c 2011-12-08 15:57:12.000000000 +0200 +@@ -0,0 +1,355 @@ ++/* ++ * Asterisk -- An open source telephony toolkit. ++ * ++ * Copyright (C) 2011, Timo Teräs ++ * ++ * See http://www.asterisk.org for more information about ++ * the Asterisk project. Please do not directly contact ++ * any of the maintainers of this project for assistance; ++ * the project provides a web site, mailing lists and IRC ++ * channels for your use. ++ * ++ * This program is free software, distributed under the terms of ++ * the GNU General Public License Version 2. See the LICENSE file ++ * at the top of the source tree. ++ */ ++ ++/*! \file ++ * ++ * \brief OGG/Speex streams. ++ * \arg File name extension: spx ++ * \ingroup formats ++ */ ++ ++/*** MODULEINFO ++ <depend>speex</depend> ++ <depend>ogg</depend> ++ <support_level>extended</support_level> ++ ***/ ++ ++#include "asterisk.h" ++ ++ASTERISK_FILE_VERSION(__FILE__, "$Revision$") ++ ++#include "asterisk/mod_format.h" ++#include "asterisk/module.h" ++ ++#include <speex/speex_header.h> ++#include <ogg/ogg.h> ++ ++#define BLOCK_SIZE 4096 /* buffer size for feeding OGG routines */ ++#define BUF_SIZE 200 ++ ++struct speex_desc { /* format specific parameters */ ++ /* structures for handling the Ogg container */ ++ ogg_sync_state oy; ++ ogg_stream_state os; ++ ogg_page og; ++ ogg_packet op; ++ ++ int format_id; ++ int serialno; ++ ++ /*! \brief Indicates whether an End of Stream condition has been detected. */ ++ int eos; ++}; ++ ++static int read_packet(struct ast_filestream *fs) ++{ ++ struct speex_desc *s = (struct speex_desc *)fs->_private; ++ char *buffer; ++ int result; ++ size_t bytes; ++ ++ while (1) { ++ /* Get one packet */ ++ result = ogg_stream_packetout(&s->os, &s->op); ++ if (result > 0) { ++ if (s->op.bytes>=5 && !memcmp(s->op.packet, "Speex", 5)) ++ s->serialno = s->os.serialno; ++ if (s->serialno == -1 || s->os.serialno != s->serialno) ++ continue; ++ return 0; ++ } ++ ++ if (result < 0) ++ ast_log(LOG_WARNING, ++ "Corrupt or missing data at this page position; continuing...\n"); ++ ++ /* No more packets left in the current page... */ ++ if (s->eos) { ++ /* No more pages left in the stream */ ++ return -1; ++ } ++ ++ while (!s->eos) { ++ /* See if OGG has any pages in it's internal buffers */ ++ result = ogg_sync_pageout(&s->oy, &s->og); ++ if (result > 0) { ++ /* Read all streams. */ ++ if (ogg_page_serialno(&s->og) != s->os.serialno) ++ ogg_stream_reset_serialno(&s->os, ogg_page_serialno(&s->og)); ++ /* Yes, OGG has more pages in it's internal buffers, ++ add the page to the stream state */ ++ result = ogg_stream_pagein(&s->os, &s->og); ++ if (result == 0) { ++ /* Yes, got a new,valid page */ ++ if (ogg_page_eos(&s->og) && ++ ogg_page_serialno(&s->og) == s->serialno) ++ s->eos = 1; ++ break; ++ } ++ ast_log(LOG_WARNING, ++ "Invalid page in the bitstream; continuing...\n"); ++ } ++ ++ if (result < 0) ++ ast_log(LOG_WARNING, ++ "Corrupt or missing data in bitstream; continuing...\n"); ++ ++ /* No, we need to read more data from the file descrptor */ ++ /* get a buffer from OGG to read the data into */ ++ buffer = ogg_sync_buffer(&s->oy, BLOCK_SIZE); ++ bytes = fread(buffer, 1, BLOCK_SIZE, fs->f); ++ ogg_sync_wrote(&s->oy, bytes); ++ if (bytes == 0) ++ s->eos = 1; ++ } ++ } ++} ++ ++/*! ++ * \brief Create a new OGG/Speex filestream and set it up for reading. ++ * \param fs File that points to on disk storage of the OGG/Speex data. ++ * \param expected_rate The expected Speex format (sampling rate). ++ * \return The new filestream. ++ */ ++static int ogg_speex_open(struct ast_filestream *fs, int format_id, int expected_rate) ++{ ++ char *buffer; ++ size_t bytes; ++ struct speex_desc *s = (struct speex_desc *)fs->_private; ++ SpeexHeader *hdr = NULL; ++ int i, result; ++ ++ s->format_id = format_id; ++ s->serialno = -1; ++ ogg_sync_init(&s->oy); ++ ++ buffer = ogg_sync_buffer(&s->oy, BLOCK_SIZE); ++ bytes = fread(buffer, 1, BLOCK_SIZE, fs->f); ++ ogg_sync_wrote(&s->oy, bytes); ++ ++ result = ogg_sync_pageout(&s->oy, &s->og); ++ if (result != 1) { ++ if(bytes < BLOCK_SIZE) { ++ ast_log(LOG_ERROR, "Run out of data...\n"); ++ } else { ++ ast_log(LOG_ERROR, "Input does not appear to be an Ogg bitstream.\n"); ++ } ++ ogg_sync_clear(&s->oy); ++ return -1; ++ } ++ ++ ogg_stream_init(&s->os, ogg_page_serialno(&s->og)); ++ if (ogg_stream_pagein(&s->os, &s->og) < 0) { ++ ast_log(LOG_ERROR, "Error reading first page of Ogg bitstream data.\n"); ++ goto error; ++ } ++ ++ if (read_packet(fs) < 0) { ++ ast_log(LOG_ERROR, "Error reading initial header packet.\n"); ++ goto error; ++ } ++ ++ hdr = speex_packet_to_header((char*)s->op.packet, s->op.bytes); ++ if (memcmp(hdr->speex_string, "Speex ", 8)) { ++ ast_log(LOG_ERROR, "OGG container does not contain Speex audio!\n"); ++ goto error; ++ } ++ if (hdr->frames_per_packet != 1) { ++ ast_log(LOG_ERROR, "Only one frame-per-packet OGG/Speex files are currently supported!\n"); ++ goto error; ++ } ++ if (hdr->nb_channels != 1) { ++ ast_log(LOG_ERROR, "Only monophonic OGG/Speex files are currently supported!\n"); ++ goto error; ++ } ++ if (hdr->rate != expected_rate) { ++ ast_log(LOG_ERROR, "Unexpected sampling rate (%d != %d)!\n", ++ hdr->rate, expected_rate); ++ goto error; ++ } ++ ++ /* this packet is the comment */ ++ if (read_packet(fs) < 0) { ++ ast_log(LOG_ERROR, "Error reading comment packet.\n"); ++ goto error; ++ } ++ for (i = 0; i < hdr->extra_headers; i++) { ++ if (read_packet(fs) < 0) { ++ ast_log(LOG_ERROR, "Error reading extra header packet %d.\n", i+1); ++ goto error; ++ } ++ } ++ free(hdr); ++ ++ return 0; ++error: ++ if (hdr) ++ free(hdr); ++ ogg_stream_clear(&s->os); ++ ogg_sync_clear(&s->oy); ++ return -1; ++} ++ ++/*! ++ * \brief Close a OGG/Speex filestream. ++ * \param fs A OGG/Speex filestream. ++ */ ++static void ogg_speex_close(struct ast_filestream *fs) ++{ ++ struct speex_desc *s = (struct speex_desc *)fs->_private; ++ ++ ogg_stream_clear(&s->os); ++ ogg_sync_clear(&s->oy); ++} ++ ++/*! ++ * \brief Read a frame full of audio data from the filestream. ++ * \param fs The filestream. ++ * \param whennext Number of sample times to schedule the next call. ++ * \return A pointer to a frame containing audio data or NULL ifthere is no more audio data. ++ */ ++static struct ast_frame *ogg_speex_read(struct ast_filestream *fs, ++ int *whennext) ++{ ++ struct speex_desc *s = (struct speex_desc *)fs->_private; ++ ++ if (read_packet(fs) < 0) ++ return NULL; ++ ++ fs->fr.frametype = AST_FRAME_VOICE; ++ ast_format_set(&fs->fr.subclass.format, s->format_id, 0); ++ fs->fr.mallocd = 0; ++ AST_FRAME_SET_BUFFER(&fs->fr, fs->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); ++ memcpy(fs->fr.data.ptr, s->op.packet, s->op.bytes); ++ fs->fr.datalen = s->op.bytes; ++ fs->fr.samples = *whennext = ast_codec_get_samples(&fs->fr); ++ ++ return &fs->fr; ++} ++ ++/*! ++ * \brief Trucate an OGG/Speex filestream. ++ * \param s The filestream to truncate. ++ * \return 0 on success, -1 on failure. ++ */ ++ ++static int ogg_speex_trunc(struct ast_filestream *s) ++{ ++ ast_log(LOG_WARNING, "Truncation is not supported on OGG/Speex streams!\n"); ++ return -1; ++} ++ ++/*! ++ * \brief Seek to a specific position in an OGG/Speex filestream. ++ * \param s The filestream to truncate. ++ * \param sample_offset New position for the filestream, measured in 8KHz samples. ++ * \param whence Location to measure ++ * \return 0 on success, -1 on failure. ++ */ ++static int ogg_speex_seek(struct ast_filestream *s, off_t sample_offset, int whence) ++{ ++ ast_log(LOG_WARNING, "Seeking is not supported on OGG/Speex streams!\n"); ++ return -1; ++} ++ ++static off_t ogg_speex_tell(struct ast_filestream *s) ++{ ++ ast_log(LOG_WARNING, "Telling is not supported on OGG/Speex streams!\n"); ++ return -1; ++} ++ ++static int ogg_speex_open_nb(struct ast_filestream *fs) ++{ ++ return ogg_speex_open(fs, AST_FORMAT_SPEEX, 8000); ++} ++ ++static struct ast_format_def speex_f = { ++ .name = "ogg_speex", ++ .exts = "spx", ++ .open = ogg_speex_open_nb, ++ .seek = ogg_speex_seek, ++ .trunc = ogg_speex_trunc, ++ .tell = ogg_speex_tell, ++ .read = ogg_speex_read, ++ .close = ogg_speex_close, ++ .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET, ++ .desc_size = sizeof(struct speex_desc), ++}; ++ ++static int ogg_speex_open_wb(struct ast_filestream *fs) ++{ ++ return ogg_speex_open(fs, AST_FORMAT_SPEEX16, 16000); ++} ++ ++static struct ast_format_def speex16_f = { ++ .name = "ogg_speex16", ++ .exts = "spx16", ++ .open = ogg_speex_open_wb, ++ .seek = ogg_speex_seek, ++ .trunc = ogg_speex_trunc, ++ .tell = ogg_speex_tell, ++ .read = ogg_speex_read, ++ .close = ogg_speex_close, ++ .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET, ++ .desc_size = sizeof(struct speex_desc), ++}; ++ ++static int ogg_speex_open_uwb(struct ast_filestream *fs) ++{ ++ return ogg_speex_open(fs, AST_FORMAT_SPEEX32, 32000); ++} ++ ++static struct ast_format_def speex32_f = { ++ .name = "ogg_speex32", ++ .exts = "spx32", ++ .open = ogg_speex_open_uwb, ++ .seek = ogg_speex_seek, ++ .trunc = ogg_speex_trunc, ++ .tell = ogg_speex_tell, ++ .read = ogg_speex_read, ++ .close = ogg_speex_close, ++ .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET, ++ .desc_size = sizeof(struct speex_desc), ++}; ++ ++static int load_module(void) ++{ ++ ast_format_set(&speex_f.format, AST_FORMAT_SPEEX, 0); ++ ast_format_set(&speex16_f.format, AST_FORMAT_SPEEX16, 0); ++ ast_format_set(&speex32_f.format, AST_FORMAT_SPEEX32, 0); ++ ++ if (ast_format_def_register(&speex_f) || ++ ast_format_def_register(&speex16_f) || ++ ast_format_def_register(&speex32_f)) ++ return AST_MODULE_LOAD_FAILURE; ++ ++ return AST_MODULE_LOAD_SUCCESS; ++} ++ ++static int unload_module(void) ++{ ++ int res = 0; ++ res |= ast_format_def_unregister(speex_f.name); ++ res |= ast_format_def_unregister(speex16_f.name); ++ res |= ast_format_def_unregister(speex32_f.name); ++ return res; ++} ++ ++AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "OGG/Speex audio", ++ .load = load_module, ++ .unload = unload_module, ++ .load_pri = AST_MODPRI_APP_DEPEND ++); diff --git a/testing/asterisk/ASTERISK-19109.patch b/testing/asterisk/ASTERISK-19109.patch new file mode 100644 index 000000000..cd45b4273 --- /dev/null +++ b/testing/asterisk/ASTERISK-19109.patch @@ -0,0 +1,724 @@ +From 806946c35cf0560248e63fea53c4d82426a2034a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> +Date: Wed, 5 Sep 2012 10:07:05 +0300 +Subject: [PATCH] ASTERISK-19109: Implement deaf participant support for + ConfBridge + +--- + CHANGES | 3 + + apps/app_confbridge.c | 218 ++++++++++++++++++++++++++++++--- + apps/confbridge/conf_config_parser.c | 14 +++ + apps/confbridge/include/confbridge.h | 6 + + bridges/bridge_multiplexed.c | 2 +- + bridges/bridge_simple.c | 2 +- + bridges/bridge_softmix.c | 38 +++--- + configs/confbridge.conf.sample | 5 + + include/asterisk/bridging_features.h | 2 + + include/asterisk/bridging_technology.h | 15 +++ + main/bridging.c | 22 ++++ + 11 files changed, 294 insertions(+), 33 deletions(-) + +diff --git a/CHANGES b/CHANGES +index c3c9891..2efa17b 100644 +--- a/CHANGES ++++ b/CHANGES +@@ -66,6 +66,9 @@ ConfBridge + file will be played to the user, and only the user, upon joining the + conference bridge. + ++ * Added support for deaf participants with CLI commands, manager actions ++ and ConfBridge DTMF actions to toggle the deaf state. ++ + + Dial + ------------------- +diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c +index 90954b8..0455be4 100644 +--- a/apps/app_confbridge.c ++++ b/apps/app_confbridge.c +@@ -185,6 +185,30 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + <description> + </description> + </manager> ++ <manager name="ConfbridgeDeafen" language="en_US"> ++ <synopsis> ++ Deafen a Confbridge user. ++ </synopsis> ++ <syntax> ++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" /> ++ <parameter name="Conference" required="true" /> ++ <parameter name="Channel" required="true" /> ++ </syntax> ++ <description> ++ </description> ++ </manager> ++ <manager name="ConfbridgeUndeafen" language="en_US"> ++ <synopsis> ++ Undeafen a Confbridge user. ++ </synopsis> ++ <syntax> ++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" /> ++ <parameter name="Conference" required="true" /> ++ <parameter name="Channel" required="true" /> ++ </syntax> ++ <description> ++ </description> ++ </manager> + <manager name="ConfbridgeKick" language="en_US"> + <synopsis> + Kick a Confbridge user. +@@ -273,6 +297,13 @@ static const char app[] = "ConfBridge"; + /* Number of buckets our conference bridges container can have */ + #define CONFERENCE_BRIDGE_BUCKETS 53 + ++enum confbridge_feature_action { ++ CONFBRIDGE_FEATURE_MUTE, ++ CONFBRIDGE_FEATURE_UNMUTE, ++ CONFBRIDGE_FEATURE_DEAFEN, ++ CONFBRIDGE_FEATURE_UNDEAFEN ++}; ++ + /*! \brief Container to hold all conference bridges in progress */ + static struct ao2_container *conference_bridges; + +@@ -311,6 +342,10 @@ const char *conf_get_sound(enum conf_sounds sound, struct bridge_profile_sounds + return S_OR(custom_sounds->muted, "conf-muted"); + case CONF_SOUND_UNMUTED: + return S_OR(custom_sounds->unmuted, "conf-unmuted"); ++ case CONF_SOUND_DEAFENED: ++ return S_OR(custom_sounds->deafened, "conf-deafened"); ++ case CONF_SOUND_UNDEAFENED: ++ return S_OR(custom_sounds->undeafened, "conf-undeafened"); + case CONF_SOUND_ONLY_ONE: + return S_OR(custom_sounds->onlyone, "conf-onlyone"); + case CONF_SOUND_THERE_ARE: +@@ -1504,10 +1539,13 @@ static int confbridge_exec(struct ast_channel *chan, const char *data) + volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ); + volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE); + +- /* If the caller should be joined already muted, make it so */ ++ /* If the caller should be joined already muted or deaf, make it so */ + if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_STARTMUTED)) { + conference_bridge_user.features.mute = 1; + } ++ if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_STARTDEAF)) { ++ conference_bridge_user.features.deaf = 1; ++ } + + if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_DROP_SILENCE)) { + conference_bridge_user.tech_args.drop_silence = 1; +@@ -1668,6 +1706,20 @@ static int action_toggle_mute_participants(struct conference_bridge *conference_ + return 0; + } + ++static int action_toggle_deaf(struct conference_bridge *conference_bridge, ++ struct conference_bridge_user *conference_bridge_user, ++ struct ast_channel *chan) ++{ ++ /* Deafen or undeafen yourself */ ++ conference_bridge_user->features.deaf = (!conference_bridge_user->features.deaf ? 1 : 0); ++ ast_test_suite_event_notify("CONF_DEAF", "Message: participant %s %s\r\nConference: %s\r\nChannel: %s", chan->name, conference_bridge_user->features.deaf ? "deafened" : "undeafened", conference_bridge_user->b_profile.name, chan->name); ++ ++ return ast_stream_and_wait(chan, (conference_bridge_user->features.deaf ? ++ conf_get_sound(CONF_SOUND_DEAFENED, conference_bridge_user->b_profile.sounds) : ++ conf_get_sound(CONF_SOUND_UNDEAFENED, conference_bridge_user->b_profile.sounds)), ++ ""); ++} ++ + static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file) + { + char *file_copy = ast_strdupa(playback_file); +@@ -1856,6 +1908,11 @@ static int execute_menu_entry(struct conference_bridge *conference_bridge, + case MENU_ACTION_PARTICIPANT_COUNT: + announce_user_count(conference_bridge, conference_bridge_user); + break; ++ case MENU_ACTION_TOGGLE_DEAF: ++ res |= action_toggle_deaf(conference_bridge, ++ conference_bridge_user, ++ bridge_channel->chan); ++ break; + case MENU_ACTION_PLAYBACK: + if (!stop_prompts) { + res |= action_playback(bridge_channel, menu_action->data.playback_file); +@@ -2119,13 +2176,13 @@ static int generic_lock_unlock_helper(int lock, const char *conference) + } + + /* \internal +- * \brief finds a conference user by channel name and mutes/unmutes them. ++ * \brief finds a conference user by channel name and changes feature bits on it. + * + * \retval 0 success + * \retval -1 conference not found + * \retval -2 user not found + */ +-static int generic_mute_unmute_helper(int mute, const char *conference, const char *user) ++static int generic_feature_action_helper(enum confbridge_feature_action action, const char *conference, const char *user) + { + struct conference_bridge *bridge = NULL; + struct conference_bridge tmp; +@@ -2143,10 +2200,44 @@ static int generic_mute_unmute_helper(int mute, const char *conference, const ch + } + } + if (participant) { +- participant->features.mute = mute; +- ast_test_suite_event_notify("CONF_MUTE", "Message: participant %s %s\r\nConference: %s\r\nChannel: %s", ast_channel_name(participant->chan), participant->features.mute ? "muted" : "unmuted", bridge->b_profile.name, ast_channel_name(participant->chan)); ++ const char *state, *verb; ++ ++ switch (action) { ++ case CONFBRIDGE_FEATURE_DEAFEN: ++ participant->features.deaf = 1; ++ state = "CONF_DEAF"; ++ verb = "deafened"; ++ break; ++ case CONFBRIDGE_FEATURE_UNDEAFEN: ++ participant->features.deaf = 0; ++ state = "CONF_DEAF"; ++ verb = "undeafened"; ++ break; ++ case CONFBRIDGE_FEATURE_MUTE: ++ participant->features.mute = 1; ++ state = "CONF_MUTE"; ++ verb = "muted"; ++ break; ++ case CONFBRIDGE_FEATURE_UNMUTE: ++ default: ++ participant->features.mute = 0; ++ state = "CONF_MUTE"; ++ verb = "unmuted"; ++ break; ++ } ++ ++ if (state != NULL && verb != NULL) { ++ ast_test_suite_event_notify(state, ++ "Message: participant %s %s\r\n" ++ "Conference: %s\r\n" ++ "Channel: %s", ++ ast_channel_name(participant->chan), ++ verb, ++ bridge->b_profile.name, ++ ast_channel_name(participant->chan)); ++ } + } else { +- res = -2;; ++ res = -2; + } + ao2_unlock(bridge); + ao2_ref(bridge, -1); +@@ -2154,9 +2245,10 @@ static int generic_mute_unmute_helper(int mute, const char *conference, const ch + return res; + } + +-static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a) ++static int cli_feature_action_helper(enum confbridge_feature_action action, struct ast_cli_args *a) + { +- int res = generic_mute_unmute_helper(mute, a->argv[2], a->argv[3]); ++ const char *verb; ++ int res = generic_feature_action_helper(action, a->argv[2], a->argv[3]); + + if (res == -1) { + ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]); +@@ -2165,7 +2257,24 @@ static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a) + ast_cli(a->fd, "No channel named '%s' found in conference %s\n", a->argv[3], a->argv[2]); + return -1; + } +- ast_cli(a->fd, "%s %s from confbridge %s\n", mute ? "Muting" : "Unmuting", a->argv[3], a->argv[2]); ++ ++ switch (action) { ++ case CONFBRIDGE_FEATURE_DEAFEN: ++ verb = "Deafening"; ++ break; ++ case CONFBRIDGE_FEATURE_UNDEAFEN: ++ verb = "Undeafening"; ++ break; ++ case CONFBRIDGE_FEATURE_MUTE: ++ verb = "Muting"; ++ break; ++ case CONFBRIDGE_FEATURE_UNMUTE: ++ default: ++ verb = "Unmuting"; ++ break; ++ } ++ ++ ast_cli(a->fd, "%s %s from confbridge %s\n", verb, a->argv[3], a->argv[2]); + return 0; + } + +@@ -2187,7 +2296,7 @@ static char *handle_cli_confbridge_mute(struct ast_cli_entry *e, int cmd, struct + return CLI_SHOWUSAGE; + } + +- cli_mute_unmute_helper(1, a); ++ cli_feature_action_helper(CONFBRIDGE_FEATURE_MUTE, a); + + return CLI_SUCCESS; + } +@@ -2210,7 +2319,53 @@ static char *handle_cli_confbridge_unmute(struct ast_cli_entry *e, int cmd, stru + return CLI_SHOWUSAGE; + } + +- cli_mute_unmute_helper(0, a); ++ cli_feature_action_helper(CONFBRIDGE_FEATURE_UNMUTE, a); ++ ++ return CLI_SUCCESS; ++} ++ ++static char *handle_cli_confbridge_deafen(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) ++{ ++ switch (cmd) { ++ case CLI_INIT: ++ e->command = "confbridge deafen"; ++ e->usage = ++ "Usage: confbridge deafen <conference> <channel>\n"; ++ return NULL; ++ case CLI_GENERATE: ++ if (a->pos == 2) { ++ return complete_confbridge_name(a->line, a->word, a->pos, a->n); ++ } ++ return NULL; ++ } ++ if (a->argc != 4) { ++ return CLI_SHOWUSAGE; ++ } ++ ++ cli_feature_action_helper(CONFBRIDGE_FEATURE_DEAFEN, a); ++ ++ return CLI_SUCCESS; ++} ++ ++static char *handle_cli_confbridge_undeafen(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) ++{ ++ switch (cmd) { ++ case CLI_INIT: ++ e->command = "confbridge undeafen"; ++ e->usage = ++ "Usage: confbridge undeafen <conference> <channel>\n"; ++ return NULL; ++ case CLI_GENERATE: ++ if (a->pos == 2) { ++ return complete_confbridge_name(a->line, a->word, a->pos, a->n); ++ } ++ return NULL; ++ } ++ if (a->argc != 4) { ++ return CLI_SHOWUSAGE; ++ } ++ ++ cli_feature_action_helper(CONFBRIDGE_FEATURE_UNDEAFEN, a); + + return CLI_SUCCESS; + } +@@ -2358,6 +2513,8 @@ static struct ast_cli_entry cli_confbridge[] = { + AST_CLI_DEFINE(handle_cli_confbridge_kick, "Kick participants out of conference bridges."), + AST_CLI_DEFINE(handle_cli_confbridge_mute, "Mute a participant."), + AST_CLI_DEFINE(handle_cli_confbridge_unmute, "Unmute a participant."), ++ AST_CLI_DEFINE(handle_cli_confbridge_deafen, "Deafen a participant."), ++ AST_CLI_DEFINE(handle_cli_confbridge_undeafen, "Undeafen a participant."), + AST_CLI_DEFINE(handle_cli_confbridge_lock, "Lock a conference."), + AST_CLI_DEFINE(handle_cli_confbridge_unlock, "Unlock a conference."), + AST_CLI_DEFINE(handle_cli_confbridge_start_record, "Start recording a conference"), +@@ -2492,10 +2649,11 @@ static int action_confbridgelistrooms(struct mansession *s, const struct message + return 0; + } + +-static int action_mute_unmute_helper(struct mansession *s, const struct message *m, int mute) ++static int action_feature_action_helper(struct mansession *s, const struct message *m, enum confbridge_feature_action action) + { + const char *conference = astman_get_header(m, "Conference"); + const char *channel = astman_get_header(m, "Channel"); ++ char *verb; + int res = 0; + + if (ast_strlen_zero(conference)) { +@@ -2511,7 +2669,7 @@ static int action_mute_unmute_helper(struct mansession *s, const struct message + return 0; + } + +- res = generic_mute_unmute_helper(mute, conference, channel); ++ res = generic_feature_action_helper(action, conference, channel); + + if (res == -1) { + astman_send_error(s, m, "No Conference by that name found."); +@@ -2521,17 +2679,41 @@ static int action_mute_unmute_helper(struct mansession *s, const struct message + return 0; + } + +- astman_send_ack(s, m, mute ? "User muted" : "User unmuted"); ++ switch (action) { ++ case CONFBRIDGE_FEATURE_DEAFEN: ++ verb = "User deafened"; ++ break; ++ case CONFBRIDGE_FEATURE_UNDEAFEN: ++ verb = "User undeafened"; ++ break; ++ case CONFBRIDGE_FEATURE_MUTE: ++ verb = "User muted"; ++ break; ++ case CONFBRIDGE_FEATURE_UNMUTE: ++ default: ++ verb = "User unmuted"; ++ break; ++ } ++ ++ astman_send_ack(s, m, verb); + return 0; + } + + static int action_confbridgeunmute(struct mansession *s, const struct message *m) + { +- return action_mute_unmute_helper(s, m, 0); ++ return action_feature_action_helper(s, m, CONFBRIDGE_FEATURE_UNMUTE); + } + static int action_confbridgemute(struct mansession *s, const struct message *m) + { +- return action_mute_unmute_helper(s, m, 1); ++ return action_feature_action_helper(s, m, CONFBRIDGE_FEATURE_MUTE); ++} ++static int action_confbridgeundeafen(struct mansession *s, const struct message *m) ++{ ++ return action_feature_action_helper(s, m, CONFBRIDGE_FEATURE_UNDEAFEN); ++} ++static int action_confbridgedeafen(struct mansession *s, const struct message *m) ++{ ++ return action_feature_action_helper(s, m, CONFBRIDGE_FEATURE_DEAFEN); + } + + static int action_lock_unlock_helper(struct mansession *s, const struct message *m, int lock) +@@ -2818,6 +3000,8 @@ static int unload_module(void) + res |= ast_manager_unregister("ConfbridgeListRooms"); + res |= ast_manager_unregister("ConfbridgeMute"); + res |= ast_manager_unregister("ConfbridgeUnmute"); ++ res |= ast_manager_unregister("ConfbridgeDeafen"); ++ res |= ast_manager_unregister("ConfbridgeUndeafen"); + res |= ast_manager_unregister("ConfbridgeKick"); + res |= ast_manager_unregister("ConfbridgeUnlock"); + res |= ast_manager_unregister("ConfbridgeLock"); +@@ -2860,6 +3044,8 @@ static int load_module(void) + res |= ast_manager_register_xml("ConfbridgeListRooms", EVENT_FLAG_REPORTING, action_confbridgelistrooms); + res |= ast_manager_register_xml("ConfbridgeMute", EVENT_FLAG_CALL, action_confbridgemute); + res |= ast_manager_register_xml("ConfbridgeUnmute", EVENT_FLAG_CALL, action_confbridgeunmute); ++ res |= ast_manager_register_xml("ConfbridgeDeafen", EVENT_FLAG_CALL, action_confbridgedeafen); ++ res |= ast_manager_register_xml("ConfbridgeUndeafen", EVENT_FLAG_CALL, action_confbridgeundeafen); + res |= ast_manager_register_xml("ConfbridgeKick", EVENT_FLAG_CALL, action_confbridgekick); + res |= ast_manager_register_xml("ConfbridgeUnlock", EVENT_FLAG_CALL, action_confbridgeunlock); + res |= ast_manager_register_xml("ConfbridgeLock", EVENT_FLAG_CALL, action_confbridgelock); +diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c +index f4a9604..8a02de7 100644 +--- a/apps/confbridge/conf_config_parser.c ++++ b/apps/confbridge/conf_config_parser.c +@@ -279,6 +279,10 @@ static int set_sound(const char *sound_name, const char *sound_file, struct brid + ast_string_field_set(sounds, muted, sound_file); + } else if (!strcasecmp(sound_name, "sound_unmuted")) { + ast_string_field_set(sounds, unmuted, sound_file); ++ } else if (!strcasecmp(sound_name, "sound_deafened")) { ++ ast_string_field_set(sounds, deafened, sound_file); ++ } else if (!strcasecmp(sound_name, "sound_undeafened")) { ++ ast_string_field_set(sounds, undeafened, sound_file); + } else if (!strcasecmp(sound_name, "sound_there_are")) { + ast_string_field_set(sounds, thereare, sound_file); + } else if (!strcasecmp(sound_name, "sound_other_in_party")) { +@@ -418,6 +422,7 @@ static int add_action_to_menu_entry(struct conf_menu_entry *menu_entry, enum con + switch (id) { + case MENU_ACTION_NOOP: + case MENU_ACTION_TOGGLE_MUTE: ++ case MENU_ACTION_TOGGLE_DEAF: + case MENU_ACTION_INCREASE_LISTENING: + case MENU_ACTION_DECREASE_LISTENING: + case MENU_ACTION_INCREASE_TALKING: +@@ -708,6 +713,9 @@ static char *handle_cli_confbridge_show_user_profile(struct ast_cli_entry *e, in + ast_cli(a->fd,"Start Muted: %s\n", + u_profile.flags & USER_OPT_STARTMUTED? + "true" : "false"); ++ ast_cli(a->fd,"Start Deaf: %s\n", ++ u_profile.flags & USER_OPT_STARTDEAF? ++ "true" : "false"); + ast_cli(a->fd,"MOH When Empty: %s\n", + u_profile.flags & USER_OPT_MUSICONHOLD ? + "enabled" : "disabled"); +@@ -896,6 +904,8 @@ static char *handle_cli_confbridge_show_bridge_profile(struct ast_cli_entry *e, + ast_cli(a->fd,"sound_kicked: %s\n", conf_get_sound(CONF_SOUND_KICKED, b_profile.sounds)); + ast_cli(a->fd,"sound_muted: %s\n", conf_get_sound(CONF_SOUND_MUTED, b_profile.sounds)); + ast_cli(a->fd,"sound_unmuted: %s\n", conf_get_sound(CONF_SOUND_UNMUTED, b_profile.sounds)); ++ ast_cli(a->fd,"sound_deafened: %s\n", conf_get_sound(CONF_SOUND_DEAFENED, b_profile.sounds)); ++ ast_cli(a->fd,"sound_undeafened: %s\n", conf_get_sound(CONF_SOUND_UNDEAFENED, b_profile.sounds)); + ast_cli(a->fd,"sound_there_are: %s\n", conf_get_sound(CONF_SOUND_THERE_ARE, b_profile.sounds)); + ast_cli(a->fd,"sound_other_in_party: %s\n", conf_get_sound(CONF_SOUND_OTHER_IN_PARTY, b_profile.sounds)); + ast_cli(a->fd,"sound_place_into_conference: %s\n", conf_get_sound(CONF_SOUND_PLACE_IN_CONF, b_profile.sounds)); +@@ -1021,6 +1031,9 @@ static char *handle_cli_confbridge_show_menu(struct ast_cli_entry *e, int cmd, s + case MENU_ACTION_TOGGLE_MUTE: + ast_cli(a->fd, "toggle_mute"); + break; ++ case MENU_ACTION_TOGGLE_DEAF: ++ ast_cli(a->fd, "toggle_deaf"); ++ break; + case MENU_ACTION_NOOP: + ast_cli(a->fd, "no_op"); + break; +@@ -1268,6 +1281,7 @@ int conf_load_config(int reload) + aco_option_register(&cfg_info, "admin", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_ADMIN); + aco_option_register(&cfg_info, "marked", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_MARKEDUSER); + aco_option_register(&cfg_info, "startmuted", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_STARTMUTED); ++ aco_option_register(&cfg_info, "startdeaf", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_STARTDEAF); + aco_option_register(&cfg_info, "music_on_hold_when_empty", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_MUSICONHOLD); + aco_option_register(&cfg_info, "quiet", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_QUIET); + aco_option_register_custom(&cfg_info, "announce_user_count_all", ACO_EXACT, user_types, "no", announce_user_count_all_handler, 0); +diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h +index d3ead35..3d773c5 100644 +--- a/apps/confbridge/include/confbridge.h ++++ b/apps/confbridge/include/confbridge.h +@@ -57,6 +57,7 @@ enum user_profile_flags { + USER_OPT_DTMF_PASS = (1 << 13), /*!< Sets if dtmf should be passed into the conference or not */ + USER_OPT_ANNOUNCEUSERCOUNTALL = (1 << 14), /*!< Sets if the number of users should be announced to everyone. */ + USER_OPT_JITTERBUFFER = (1 << 15), /*!< Places a jitterbuffer on the user. */ ++ USER_OPT_STARTDEAF = (1 << 16), /*!< Set if the caller should be initially set deaf */ + }; + + enum bridge_profile_flags { +@@ -68,6 +69,7 @@ enum bridge_profile_flags { + + enum conf_menu_action_id { + MENU_ACTION_TOGGLE_MUTE = 1, ++ MENU_ACTION_TOGGLE_DEAF, + MENU_ACTION_PLAYBACK, + MENU_ACTION_PLAYBACK_AND_CONTINUE, + MENU_ACTION_INCREASE_LISTENING, +@@ -142,6 +144,8 @@ enum conf_sounds { + CONF_SOUND_KICKED, + CONF_SOUND_MUTED, + CONF_SOUND_UNMUTED, ++ CONF_SOUND_DEAFENED, ++ CONF_SOUND_UNDEAFENED, + CONF_SOUND_ONLY_ONE, + CONF_SOUND_THERE_ARE, + CONF_SOUND_OTHER_IN_PARTY, +@@ -168,6 +172,8 @@ struct bridge_profile_sounds { + AST_STRING_FIELD(kicked); + AST_STRING_FIELD(muted); + AST_STRING_FIELD(unmuted); ++ AST_STRING_FIELD(deafened); ++ AST_STRING_FIELD(undeafened); + AST_STRING_FIELD(onlyone); + AST_STRING_FIELD(thereare); + AST_STRING_FIELD(otherinparty); +diff --git a/bridges/bridge_multiplexed.c b/bridges/bridge_multiplexed.c +index cd30266..190f790 100644 +--- a/bridges/bridge_multiplexed.c ++++ b/bridges/bridge_multiplexed.c +@@ -386,7 +386,7 @@ static enum ast_bridge_write_result multiplexed_bridge_write(struct ast_bridge * + } + + if (other->state == AST_BRIDGE_CHANNEL_STATE_WAIT) { +- ast_write(other->chan, frame); ++ ast_bridge_handle_channel_write(bridge, other, frame); + } + + return AST_BRIDGE_WRITE_SUCCESS; +diff --git a/bridges/bridge_simple.c b/bridges/bridge_simple.c +index 69e4114..1623ce0 100644 +--- a/bridges/bridge_simple.c ++++ b/bridges/bridge_simple.c +@@ -81,7 +81,7 @@ static enum ast_bridge_write_result simple_bridge_write(struct ast_bridge *bridg + + /* Write the frame out if they are in the waiting state... don't worry about freeing it, the bridging core will take care of it */ + if (other->state == AST_BRIDGE_CHANNEL_STATE_WAIT) { +- ast_write(other->chan, frame); ++ ast_bridge_handle_channel_write(bridge, other, frame); + } + + return AST_BRIDGE_WRITE_SUCCESS; +diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c +index 52e5551..5754e41 100644 +--- a/bridges/bridge_softmix.c ++++ b/bridges/bridge_softmix.c +@@ -435,7 +435,7 @@ static void softmix_pass_dtmf(struct ast_bridge *bridge, struct ast_bridge_chann + if (tmp == bridge_channel) { + continue; + } +- ast_write(tmp->chan, frame); ++ ast_bridge_handle_channel_write(bridge, tmp, frame); + } + } + +@@ -447,7 +447,7 @@ static void softmix_pass_video_top_priority(struct ast_bridge *bridge, struct as + continue; + } + if (ast_bridge_is_video_src(bridge, tmp->chan) == 1) { +- ast_write(tmp->chan, frame); ++ ast_bridge_handle_channel_write(bridge, tmp, frame); + break; + } + } +@@ -463,7 +463,7 @@ static void softmix_pass_video_all(struct ast_bridge *bridge, struct ast_bridge_ + if ((tmp->chan == bridge_channel->chan) && !echo) { + continue; + } +- ast_write(tmp->chan, frame); ++ ast_bridge_handle_channel_write(bridge, tmp, frame); + } + } + +@@ -563,7 +563,7 @@ static enum ast_bridge_write_result softmix_bridge_write(struct ast_bridge *brid + + /* If a frame is ready to be written out, do so */ + if (sc->have_frame) { +- ast_write(bridge_channel->chan, &sc->write_frame); ++ ast_bridge_handle_channel_write(bridge, bridge_channel, &sc->write_frame); + sc->have_frame = 0; + } + +@@ -582,7 +582,7 @@ bridge_write_cleanup: + * the conference to the channel. */ + ast_mutex_lock(&sc->lock); + if (sc->have_frame) { +- ast_write(bridge_channel->chan, &sc->write_frame); ++ ast_bridge_handle_channel_write(bridge, bridge_channel, &sc->write_frame); + sc->have_frame = 0; + } + ast_mutex_unlock(&sc->lock); +@@ -598,7 +598,7 @@ static int softmix_bridge_poke(struct ast_bridge *bridge, struct ast_bridge_chan + ast_mutex_lock(&sc->lock); + + if (sc->have_frame) { +- ast_write(bridge_channel->chan, &sc->write_frame); ++ ast_bridge_handle_channel_write(bridge, bridge_channel, &sc->write_frame); + sc->have_frame = 0; + } + +@@ -850,16 +850,24 @@ static int softmix_bridge_thread(struct ast_bridge *bridge) + + ast_mutex_lock(&sc->lock); + +- /* Make SLINEAR write frame from local buffer */ +- if (sc->write_frame.subclass.format.id != cur_slin_id) { +- ast_format_set(&sc->write_frame.subclass.format, cur_slin_id, 0); ++ if (bridge->features.deaf || ++ (bridge_channel->features && bridge_channel->features->deaf)) { ++ /* For deaf channels post a null frame */ ++ sc->write_frame.frametype = AST_FRAME_NULL; ++ } else { ++ /* Make SLINEAR write frame from local buffer */ ++ sc->write_frame.frametype = AST_FRAME_VOICE; ++ if (sc->write_frame.subclass.format.id != cur_slin_id) { ++ ast_format_set(&sc->write_frame.subclass.format, cur_slin_id, 0); ++ } ++ sc->write_frame.datalen = softmix_datalen; ++ sc->write_frame.samples = softmix_samples; ++ memcpy(sc->final_buf, buf, softmix_datalen); ++ ++ /* process the softmix channel's new write audio */ ++ softmix_process_write_audio(&trans_helper, ++ ast_channel_rawwriteformat(bridge_channel->chan), sc); + } +- sc->write_frame.datalen = softmix_datalen; +- sc->write_frame.samples = softmix_samples; +- memcpy(sc->final_buf, buf, softmix_datalen); +- +- /* process the softmix channel's new write audio */ +- softmix_process_write_audio(&trans_helper, ast_channel_rawwriteformat(bridge_channel->chan), sc); + + /* The frame is now ready for use... */ + sc->have_frame = 1; +diff --git a/configs/confbridge.conf.sample b/configs/confbridge.conf.sample +index 7484b28..3b0ce85 100644 +--- a/configs/confbridge.conf.sample ++++ b/configs/confbridge.conf.sample +@@ -16,6 +16,7 @@ type=user + ;admin=yes ; Sets if the user is an admin or not. Off by default. + ;marked=yes ; Sets if this is a marked user or not. Off by default. + ;startmuted=yes; Sets if all users should start out muted. Off by default ++;startdeaf=yes ; Sets if all users should start out deaf. Off by default. + ;music_on_hold_when_empty=yes ; Sets whether MOH should be played when only + ; one person is in the conference or when the + ; the user is waiting on a marked user to enter +@@ -210,6 +211,8 @@ type=bridge + ;sound_kicked ; The sound played to a user who has been kicked from the conference. + ;sound_muted ; The sound played when the mute option it toggled on. + ;sound_unmuted ; The sound played when the mute option it toggled off. ++;sound_deafened ; The sound played when the deaf option is toggled on. ++;sound_undeafened ; The sound played when the deaf option is toggled off. + ;sound_only_person ; The sound played when the user is the only person in the conference. + ;sound_only_one ; The sound played to a user when there is only one other + ; person is in the conference. +@@ -264,6 +267,8 @@ type=bridge + ; toggle_mute ; Toggle turning on and off mute. Mute will make the user silent + ; to everyone else, but the user will still be able to listen in. + ; continue to collect the dtmf sequence. ++; toggle_deaf ; Toggle turning on and off deaf. Deaf will make the user to hear ++ ; only silence, but the user will still be able to talk. + ; no_op ; This action does nothing (No Operation). Its only real purpose exists for + ; being able to reserve a sequence in the config as a menu exit sequence. + ; decrease_listening_volume ; Decreases the channel's listening volume. +diff --git a/include/asterisk/bridging_features.h b/include/asterisk/bridging_features.h +index e377ca6..5ce3d56 100644 +--- a/include/asterisk/bridging_features.h ++++ b/include/asterisk/bridging_features.h +@@ -127,6 +127,8 @@ struct ast_bridge_features { + unsigned int usable:1; + /*! Bit to indicate whether the channel/bridge is muted or not */ + unsigned int mute:1; ++ /*! Bit to indicate whether the channel/bridge is deaf or not */ ++ unsigned int deaf:1; + /*! Bit to indicate whether DTMF should be passed into the bridge tech or not. */ + unsigned int dtmf_passthrough:1; + +diff --git a/include/asterisk/bridging_technology.h b/include/asterisk/bridging_technology.h +index 3d2e870..1ecb4c1 100644 +--- a/include/asterisk/bridging_technology.h ++++ b/include/asterisk/bridging_technology.h +@@ -143,6 +143,21 @@ int ast_bridge_technology_unregister(struct ast_bridge_technology *technology); + */ + void ast_bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_channel *chan, int outfd); + ++/*! \brief Used by bridging technologies to hand off a frame to be written to a bridge_channel. ++ * ++ * \param bridge The bridge that the channel is part of. ++ * \param bridge_channel The bridge channel to which the frame is written to. ++ * \param frame The frame to write. ++ * ++ * \retval 0 on success ++ * \retval -1 on failure ++ * ++ * \note This function is essentially a wrapper for ast_write(). The bridging core has some features associated with it ++ * that requires it to have control over how frames are written into a channel. For these features to be available, the bridging ++ * technology must use this wrapper function over ast_write when pushing a frame out a channel. ++ */ ++int ast_bridge_handle_channel_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame); ++ + /*! \brief Lets the bridging indicate when a bridge channel has stopped or started talking. + * + * \note All DSP functionality on the bridge has been pushed down to the lowest possible +diff --git a/main/bridging.c b/main/bridging.c +index 465d033..4f67e90 100644 +--- a/main/bridging.c ++++ b/main/bridging.c +@@ -337,6 +337,28 @@ void ast_bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel + return; + } + ++int ast_bridge_handle_channel_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) ++{ ++ if (frame->frametype == AST_FRAME_VOICE && ++ (bridge->features.deaf || ++ (bridge_channel->features && bridge_channel->features->deaf))) { ++ short buf[frame->samples]; ++ struct ast_frame sframe = { ++ .frametype = AST_FRAME_VOICE, ++ .data.ptr = buf, ++ .samples = frame->samples, ++ .datalen = sizeof(buf), ++ }; ++ ast_format_set(&sframe.subclass.format, AST_FORMAT_SLINEAR, 0); ++ memset(buf, 0, sizeof(buf)); ++ ++ return ast_write(bridge_channel->chan, &sframe); ++ } ++ ++ return ast_write(bridge_channel->chan, frame); ++} ++ ++ + /*! \brief Generic thread loop, TODO: Rethink this/improve it */ + static int generic_thread_loop(struct ast_bridge *bridge) + { +-- +1.7.12 + diff --git a/testing/asterisk/ASTERISK-20362.patch b/testing/asterisk/ASTERISK-20362.patch new file mode 100644 index 000000000..a64489784 --- /dev/null +++ b/testing/asterisk/ASTERISK-20362.patch @@ -0,0 +1,30 @@ +diff --git a/res/Makefile b/res/Makefile +index bfbca76..c2ad23b 100644 +--- a/res/Makefile ++++ b/res/Makefile +@@ -67,17 +67,20 @@ endif + ael/pval.o: ael/pval.c + + clean:: ++ ${MAKE} -C pjproject clean + rm -f snmp/*.o snmp/*.i ael/*.o ael/*.i ais/*.o ais/*.i + + pjproject/build.mak: + cd pjproject && ./configure AR="" CFLAGS=-fPIC --disable-floating-point --disable-sound --disable-oss --disable-speex-aec --disable-l16-codec --disable-gsm-codec --disable-g722-codec --disable-g7221-codec --disable-speex-codec --disable-ilbc-codec --disable-g711-codec + +-include pjproject/build.mak ++pjproject.stamp: pjproject/build.mak ++ ${MAKE} -j1 -C pjproject dep ++ ${MAKE} -j1 -C pjproject ++ touch pjproject.stamp + +-res_rtp_asterisk.o: pjproject/build.mak $(PJ_LIB_FILES) ++-include pjproject/build.mak ++ ++res_rtp_asterisk.o: pjproject.stamp + res_rtp_asterisk.o: _ASTCFLAGS+=$(PJ_CFLAGS) + res_rtp_asterisk.so: _ASTLDFLAGS+=$(PJ_LDFLAGS) + res_rtp_asterisk.so: LIBS+=$(PJ_LDLIBS) +- +-$(PJ_LIB_FILES): +- cd pjproject && make dep && make diff --git a/testing/asterisk/asterisk.confd b/testing/asterisk/asterisk.confd new file mode 100644 index 000000000..fe9f138ab --- /dev/null +++ b/testing/asterisk/asterisk.confd @@ -0,0 +1,91 @@ +# +# Additional options for asterisk +# +# see "asterisk -h" for a list of options +# +ASTERISK_OPTS="" + +# +# User and group to run asterisk as +# +# Value: double-colon separated list of user and group, or empty to run as root: +# +# +# "asterisk:asterisk" to run as user "asterisk" and group "asterisk" +# "asterisk" to run as user "asterisk" and all groups that user "asterisk" is a member of +# ":asterisk" to run as user "root" and group "asterisk" +# "" to run as user "root" and group "root" +# +ASTERISK_USER="asterisk" + +# +# Nicelevel +# +# Set the priority of the asterisk process +# +# Value: (highest) -20..19 (lowest) +# +#ASTERISK_NICE="19" + +# +# Wrapper script +# +# Value: yes or no/empty +# +ASTERISK_WRAPPER="no" + +############# Wrapper script settings ############# + +# +# Send crash notifications emails to this address +# (needs a working mail service and /usr/sbin/sendmail to do so (e.g. ssmtp)) +# +# Value: Email address or empty to disable +# +#ASTERISK_NOTIFY_EMAIL="root" + +# +# Send asterisk's output to this terminal +# +# Value: Full path to device node or a number +# +#ASTERISK_TTY="/dev/tty9" + +# +# Start an asterisk console on the terminal specified by ASTERISK_TTY +# +# Warning! Use only for debugging, this is a potential security issue! +# +# Value: yes or no/empty +# +ASTERISK_CONSOLE="no" + +# +# Maximum size of core files. +# +# Value: Size in bytes, unlimited for no limit or empty to disable. +# +#ASTERISK_CORE_SIZE="unlimited" + +# +# ASTERISK_CORE_DIR +# +# Value: Directory (will be created if non-existant), default is /tmp +# +ASTERISK_CORE_DIR="/var/lib/asterisk/coredump" + +# +# Max number of filedescriptors +# +# Value: Number of descriptors +# +#ASTERISK_MAX_FD="1024" + +# +# Kill these tasks after asterisk crashed (ASTERISK_WRAPPER=yes only!) +# +# Warning! This will kill _ALL_ tasks with the specified names! +# +# Value: Space separated list of names in double quotes (e.g. "mpg123 mad") +# +#ASTERISK_CLEANUP_ON_CRASH="mpg123 asterisk-mpg123 mad" diff --git a/testing/asterisk/asterisk.initd b/testing/asterisk/asterisk.initd new file mode 100644 index 000000000..9b6c93ecc --- /dev/null +++ b/testing/asterisk/asterisk.initd @@ -0,0 +1,251 @@ +#!/sbin/runscript + +extra_started_commands="forcestop reload" + +depend() { + need net + after firewall + use nscd dns zaptel mysql postgresql slapd capi +} + +is_running() { + if [ -z "$(pidof asterisk)" ]; then + return 1 + else + PID="$(cat /var/run/asterisk/asterisk.pid 2>/dev/null)" + for x in $(pidof asterisk); do + if [ "${x}" = "${PID}" ]; then + return 0 + fi + done + fi + + return 1 +} + +asterisk_run_loop() { + local OPTS ARGS MSG NICE="" + local result=0 signal=0 + + # default options + OPTS="-f" # don't fork / detach breaks wrapper script... + + # filter (redundant) arguments + ARGS="$(echo "${@}" | sed -e "s:-c\|-f::g")" + + # mangle yes/no options + ASTERISK_CONSOLE="$(echo ${ASTERISK_CONSOLE} | tr '[:lower:]' '[:upper:]')" + + if [ -n "${ASTERISK_CORE_SIZE}" ] && + [ "${ASTERISK_CORE_SIZE}" != "0" ]; then + ulimit -c ${ASTERISK_CORE_SIZE} + + if [ -n "${ASTERISK_CORE_DIR}" ] && \ + [ ! -d "${ASTERISK_CORE_DIR}" ] + then + mkdir -m750 -p "${ASTERISK_CORE_DIR}" + + if [ -n "${ASTERISK_USER}" ]; then + chown -R "${ASTERISK_USER}" "${ASTERISK_CORE_DIR}" + fi + fi + ASTERISK_CORE_DIR="${ASTERISK_CORE_DIR:-/tmp}" + + cd "${ASTERISK_CORE_DIR}" + echo " Core dump size : ${ASTERISK_CORE_SIZE}" + echo " Core dump location : ${ASTERISK_CORE_DIR}" + fi + + if [ -n "${ASTERISK_MAX_FD}" ]; then + ulimit -n ${ASTERISK_MAX_FD} + echo " Max open filedescriptors : ${ASTERISK_MAX_FD}" + fi + + if [ -n "${ASTERISK_NICE}" ]; then + echo " Nice level : ${ASTERISK_NICE}" + NICE="nice -n ${ASTERISK_NICE} --" + fi + + if [ -n "${ASTERISK_NOTIFY_EMAIL}" ]; then + if [ -x /usr/sbin/sendmail ]; then + echo " Email notifications go to : ${ASTERISK_NOTIFY_EMAIL}" + else + echo " Notifications disabled, /usr/sbin/sendmail doesn't exist or is not executable!" + unset ASTERISK_NOTIFY_EMAIL + fi + fi + + if [ -n "${ASTERISK_TTY}" ]; then + for x in ${ASTERISK_TTY} \ + /dev/tty${ASTERISK_TTY} \ + /dev/vc/${ASTERISK_TTY} + do + if [ -c "${x}" ]; then + TTY="${x}" + fi + done + [ -n "${TTY}" ] && \ + echo " Messages are sent to : ${TTY}" + fi + + if [ "${ASTERISK_CONSOLE}" = "YES" ] && [ -n "${TTY}" ]; then + echo " Starting Asterisk console : ${ASTERISK_CONSOLE}" + OPTS="${OPTS} -c" + fi + + OPTS="${OPTS} ${ARGS}" + + while :; do + + if [ -n "${TTY}" ]; then + /usr/bin/stty -F ${TTY} sane + ${NICE} /usr/sbin/asterisk ${OPTS} >${TTY} 2>&1 <${TTY} + result=$? + else + ${NICE} /usr/sbin/asterisk ${OPTS} &>/dev/null + result=$? + fi + + if [ $result -eq 0 ]; then + echo "Asterisk terminated normally" + break + else + if [ $result -gt 128 ]; then + signal=$((result - 128)) + MSG="Asterisk terminated with Signal: $signal" + + CORE_TARGET="core-$(date "+%Y%m%d-%h%M%s")" + + local CORE_DUMPED=0 + if [ -f "${ASTERISK_CORE_DIR}/core" ]; then + mv "${ASTERISK_CORE_DIR}/core" \ + "${ASTERISK_CORE_DIR}/${CORE_TARGET}" + CORE_DUMPED=1 + + elif [ -f "${ASTERISK_CORE_DIR}/core.${PID}" ]; then + mv "${ASTERISK_CORE_DIR}/core.${PID}" \ + "${ASTERISK_CORE_DIR}/${CORE_TARGET}" + CORE_DUMPED=1 + + fi + + [ $CORE_DUMPED -eq 1 ] && \ + MSG="${MSG}\n\rCore dumped: ${ASTERISK_CORE_DIR}/${CORE_TARGET}" + else + MSG="Asterisk terminated with return code: $result" + fi + + # kill left-over tasks + for X in ${ASTERISK_CLEANUP_ON_CRASH}; do + kill -9 $(pidof ${X}); + done + fi + + [ -n "${TTY}" ] \ + && echo "${MSG}" >${TTY} \ + || echo "${MSG}" + + + if [ -n "${ASTERISK_NOTIFY_EMAIL}" ] && \ + [ -x /usr/sbin/sendmail ]; then + echo -e -n "Subject: Asterisk crashed\n\r${MSG}\n\r" |\ + /usr/sbin/sendmail "${ASTERISK_NOTIFY_EMAIL}" + fi + sleep 5 + echo "Restarting Asterisk..." + done + return 0 +} + +start() { + local OPTS USER GROUP PID + local tmp x + + if [ -n "${ASTERISK_NICE}" ]; then + if [ ${ASTERISK_NICE} -ge -20 ] && \ + [ ${ASTERISK_NICE} -le 19 ]; then + OPTS="--nicelevel ${ASTERISK_NICE}" + else + eerror "Nice value must be between -20 and 19" + return 1 + fi + fi + + if [ -n "${ASTERISK_USER}" ]; then + USER=$(echo $ASTERISK_USER | sed 's/:.*//') + GROUP=$(echo $ASTERISK_USER | awk -F: '/.*:.*/ { print $2 }') + if [ -n "${USER}" ]; then + ASTERISK_OPTS="${ASTERISK_OPTS} -U ${USER}" + fi + if [ -n "${GROUP}" ]; then + ASTERISK_OPTS="${ASTERISK_OPTS} -G ${GROUP}" + GROUP=":${GROUP}" # make it look nice... + fi + ebegin "Starting asterisk PBX (as ${USER}${GROUP})" + else + ebegin "Starting asterisk PBX (as root)" + fi + + if [ "$(echo ${ASTERISK_WRAPPER} | tr '[:upper:]' '[:lower:]')" != "yes" ]; then + start-stop-daemon --start --exec /usr/sbin/asterisk \ + ${OPTS} -- ${ASTERISK_OPTS} + result=$? + else + asterisk_run_loop ${ASTERISK_OPTS} 2>/dev/null & + result=$? + fi + + if [ $result -eq 0 ]; then + # 2 seconds should be enough for asterisk to start + sleep 2 + is_running + result=$? + fi + + eend $result +} + +forcestop() { + ebegin "Stopping asterisk PBX" + start-stop-daemon --stop --pidfile /var/run/asterisk/asterisk.pid + eend $? +} + +stop() { + if ! is_running; then + eerror "Asterisk is not running!" + return 0 + fi + + ebegin "Stopping asterisk PBX now" + /usr/sbin/asterisk -r -x "core stop now" &>/dev/null + # Now we have to wait until asterisk has _really_ stopped. + sleep 1 + if is_running; then + einfon "Waiting for asterisk to shutdown ." + local cnt=0 + while is_running; do + cnt=`expr $cnt + 1` + if [ $cnt -gt 60 ] ; then + # Waited 120 seconds now. Fail. + echo + eend 1 "Failed." + return + fi + sleep 2 + echo -n "." + done + echo + fi + eend 0 +} + +reload() { + if is_running; then + ebegin "Reloading asterisk configuration" + /usr/sbin/asterisk -r -x "core reload" &>/dev/null + eend $? + else + eerror "Asterisk is not running!" + fi +} diff --git a/testing/asterisk/asterisk.logrotate b/testing/asterisk/asterisk.logrotate new file mode 100644 index 000000000..30836c5c1 --- /dev/null +++ b/testing/asterisk/asterisk.logrotate @@ -0,0 +1,17 @@ +/var/log/asterisk/messages /var/log/asterisk/*log { + missingok + rotate 5 + weekly + create 0640 asterisk asterisk + postrotate + /usr/sbin/asterisk -rx 'logger reload' > /dev/null 2> /dev/null + endscript +} + +/var/log/asterisk/cdr-csv/*csv { + missingok + rotate 5 + monthly + create 0640 asterisk asterisk +} + diff --git a/testing/asterisk/asterisk.pre-install b/testing/asterisk/asterisk.pre-install new file mode 100644 index 000000000..6c2984ae4 --- /dev/null +++ b/testing/asterisk/asterisk.pre-install @@ -0,0 +1,6 @@ +#!/bin/sh + +adduser -S -h /var/lib/asterisk -s /bin/false -D asterisk 2>/dev/null +addgroup -S dialout 2>/dev/null +addgroup asterisk dialout 2>/dev/null +exit 0 diff --git a/testing/asterisk/asterisk.pre-upgrade b/testing/asterisk/asterisk.pre-upgrade new file mode 100644 index 000000000..6c2984ae4 --- /dev/null +++ b/testing/asterisk/asterisk.pre-upgrade @@ -0,0 +1,6 @@ +#!/bin/sh + +adduser -S -h /var/lib/asterisk -s /bin/false -D asterisk 2>/dev/null +addgroup -S dialout 2>/dev/null +addgroup asterisk dialout 2>/dev/null +exit 0 |