aboutsummaryrefslogtreecommitdiffstats
path: root/1.2-netsec/res
diff options
context:
space:
mode:
Diffstat (limited to '1.2-netsec/res')
-rw-r--r--1.2-netsec/res/Makefile122
-rw-r--r--1.2-netsec/res/res_adsi.c1141
-rw-r--r--1.2-netsec/res/res_agi.c2142
-rw-r--r--1.2-netsec/res/res_config_odbc.c540
-rw-r--r--1.2-netsec/res/res_crypto.c622
-rw-r--r--1.2-netsec/res/res_features.c2187
-rw-r--r--1.2-netsec/res/res_indications.c435
-rw-r--r--1.2-netsec/res/res_monitor.c592
-rw-r--r--1.2-netsec/res/res_musiconhold.c1237
-rw-r--r--1.2-netsec/res/res_odbc.c618
-rw-r--r--1.2-netsec/res/res_osp.c886
11 files changed, 0 insertions, 10522 deletions
diff --git a/1.2-netsec/res/Makefile b/1.2-netsec/res/Makefile
deleted file mode 100644
index a32465282..000000000
--- a/1.2-netsec/res/Makefile
+++ /dev/null
@@ -1,122 +0,0 @@
-#
-# Asterisk -- A telephony toolkit for Linux.
-#
-# Makefile for resource modules
-#
-# Copyright (C) 1999-2005, Digium
-#
-# Mark Spencer <markster@digium.com>
-#
-# This program is free software, distributed under the terms of
-# the GNU General Public License
-#
-
-MODS=res_indications.so res_monitor.so res_adsi.so res_agi.so res_features.so
-
-ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/odbcinst.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/odbcinst.h),)
- ifneq (${OSARCH},FreeBSD)
- MODS+=res_config_odbc.so
- else
- MODS+=$(shell if test ${BSDVERSION} -ge 500000 ; then echo "res_config_odbc.so"; fi)
- endif
- MODS+=res_odbc.so
-endif
-
-ifneq ($(NOCRYPTO),yes)
- MODS+=res_crypto.so
-endif
-
-ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/lib/libosptk.a),)
- MODS+=res_osp.so
- OSPLIB=$(CROSS_COMPILE_TARGET)/usr/lib/libosptk.a
-else
- ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/local/lib/libosptk.a),)
- MODS+=res_osp.so
- OSPLIB=$(CROSS_COMPILE_TARGET)/usr/local/lib/libosptk.a
- endif
-endif
-
-ifeq ($(findstring BSD,${OSARCH}),BSD)
- CFLAGS+=-I$(CROSS_COMPILE_TARGET)/usr/local/include
- SOLINK+=-L$(CROSS_COMPILE_TARGET)/usr/local/lib
-endif
-
-ifeq (${OSARCH},CYGWIN)
-CYGSOLINK=-Wl,--out-implib=lib$@.a -Wl,--export-all-symbols
-CYGSOLIB=-L.. -L. -lasterisk.dll
-CYG_RES_CONFIG_ODBC_LIB=-lres_odbc.so
-CYG_RES_FEATURES_LIB=-lres_adsi.so -lres_monitor.so
-else
-MODS+=res_musiconhold.so
-endif
-
-CRYPTO_LIBS=-lssl -lcrypto
-
-CFLAGS+=
-
-ifndef WITHOUT_ZAPTEL
-ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/linux/zaptel.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/zaptel.h),)
- CFLAGS+=-DZAPATA_MOH
-endif
-endif # WITHOUT_ZAPTEL
-
-#
-# Work around buggy RedHat 9.0
-#
-ifeq (${OSARCH},CYGWIN)
-CFLAGS+=-DOPENSSL_NO_KRB5
-else
-CFLAGS+=-DOPENSSL_NO_KRB5 -fPIC
-endif
-
-all: depend $(MODS)
-
-install: all
- rm -f $(DESTDIR)$(ASTHEADERDIR)/parking.h
- rm -f $(DESTDIR)$(MODULES_DIR)/app_agi.so
- rm -f $(DESTDIR)$(MODULES_DIR)/res_parking.so
- for x in $(MODS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
- @if [ x`which mpg123 2>/dev/null | grep -v '^no'` != x ] ; then \
- if mpg123 --longhelp 2>&1 | grep -q .59r 2>&1 >/dev/null ; then echo ; else \
- echo "*************************************************************";\
- echo "*** You have the WRONG version of mpg123... you need .59r ***";\
- echo "*** Use 'make mpg123' to get the right verison ***";\
- echo "*************************************************************";\
- fi ;\
- else \
- echo "*** You don't have mpg123 installed. You may need ***";\
- echo "*** it if you want to use MusicOnHold ***";\
- fi
-
-res_crypto.so: res_crypto.o
- $(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} $(CRYPTO_LIBS)
-
-clean:
- rm -f *.so *.o .depend
-
-res_odbc.so: res_odbc.o
- $(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} -lodbc
-
-res_osp.so: res_osp.o $(OSPLIB)
- $(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} $(OSPLIB)
-
-%.so : %.o
- $(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB}
-
-res_features.so: res_features.o
- $(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} ${CYG_RES_FEATURES_LIB}
-
-res_config_odbc.so: res_config_odbc.o
- $(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} ${CYG_RES_CONFIG_ODBC_LIB}
-
-ifneq ($(wildcard .depend),)
- include .depend
-endif
-
-depend: .depend
-
-.depend:
- ../build_tools/mkdep $(CFLAGS) `ls *.c`
-
-env:
- env
diff --git a/1.2-netsec/res/res_adsi.c b/1.2-netsec/res/res_adsi.c
deleted file mode 100644
index 18e7849f3..000000000
--- a/1.2-netsec/res/res_adsi.c
+++ /dev/null
@@ -1,1141 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * Includes code and algorithms from the Zapata library.
- *
- * 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 ADSI support
- *
- */
-
-#include <time.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <math.h>
-#include <errno.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/ulaw.h"
-#include "asterisk/alaw.h"
-#include "asterisk/callerid.h"
-#include "asterisk/logger.h"
-#include "asterisk/fskmodem.h"
-#include "asterisk/channel.h"
-#include "asterisk/adsi.h"
-#include "asterisk/module.h"
-#include "asterisk/config.h"
-#include "asterisk/file.h"
-
-#define DEFAULT_ADSI_MAX_RETRIES 3
-
-#define ADSI_MAX_INTRO 20
-#define ADSI_MAX_SPEED_DIAL 6
-
-#define ADSI_FLAG_DATAMODE (1 << 8)
-
-static int maxretries = DEFAULT_ADSI_MAX_RETRIES;
-
-/* Asterisk ADSI button definitions */
-#define ADSI_SPEED_DIAL 10 /* 10-15 are reserved for speed dial */
-
-static char intro[ADSI_MAX_INTRO][20];
-static int aligns[ADSI_MAX_INTRO];
-
-static char speeddial[ADSI_MAX_SPEED_DIAL][3][20];
-
-static int alignment = 0;
-
-static int adsi_generate(unsigned char *buf, int msgtype, unsigned char *msg, int msglen, int msgnum, int last, int codec)
-{
- int sum;
- int x;
- int bytes=0;
- /* Initial carrier (imaginary) */
- float cr = 1.0;
- float ci = 0.0;
- float scont = 0.0;
-
- if (msglen > 255)
- msglen = 255;
-
- /* If first message, Send 150ms of MARK's */
- if (msgnum == 1) {
- for (x=0;x<150;x++) /* was 150 */
- PUT_CLID_MARKMS;
- }
- /* Put message type */
- PUT_CLID(msgtype);
- sum = msgtype;
-
- /* Put message length (plus one for the message number) */
- PUT_CLID(msglen + 1);
- sum += msglen + 1;
-
- /* Put message number */
- PUT_CLID(msgnum);
- sum += msgnum;
-
- /* Put actual message */
- for (x=0;x<msglen;x++) {
- PUT_CLID(msg[x]);
- sum += msg[x];
- }
-
- /* Put 2's compliment of sum */
- PUT_CLID(256-(sum & 0xff));
-
-#if 0
- if (last) {
- /* Put trailing marks */
- for (x=0;x<50;x++)
- PUT_CLID_MARKMS;
- }
-#endif
- return bytes;
-
-}
-
-static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int len, int *remainder)
-{
- /* Sends carefully on a full duplex channel by using reading for
- timing */
- struct ast_frame *inf, outf;
- int amt;
-
- /* Zero out our outgoing frame */
- memset(&outf, 0, sizeof(outf));
-
- if (remainder && *remainder) {
- amt = len;
-
- /* Send remainder if provided */
- if (amt > *remainder)
- amt = *remainder;
- else
- *remainder = *remainder - amt;
- outf.frametype = AST_FRAME_VOICE;
- outf.subclass = AST_FORMAT_ULAW;
- outf.data = buf;
- outf.datalen = amt;
- outf.samples = amt;
- if (ast_write(chan, &outf)) {
- ast_log(LOG_WARNING, "Failed to carefully write frame\n");
- return -1;
- }
- /* Update pointers and lengths */
- buf += amt;
- len -= amt;
- }
-
- while(len) {
- amt = len;
- /* If we don't get anything at all back in a second, forget
- about it */
- if (ast_waitfor(chan, 1000) < 1)
- return -1;
- inf = ast_read(chan);
- /* Detect hangup */
- if (!inf)
- return -1;
- if (inf->frametype == AST_FRAME_VOICE) {
- /* Read a voice frame */
- if (inf->subclass != AST_FORMAT_ULAW) {
- ast_log(LOG_WARNING, "Channel not in ulaw?\n");
- return -1;
- }
- /* Send no more than they sent us */
- if (amt > inf->datalen)
- amt = inf->datalen;
- else if (remainder)
- *remainder = inf->datalen - amt;
- outf.frametype = AST_FRAME_VOICE;
- outf.subclass = AST_FORMAT_ULAW;
- outf.data = buf;
- outf.datalen = amt;
- outf.samples = amt;
- if (ast_write(chan, &outf)) {
- ast_log(LOG_WARNING, "Failed to carefully write frame\n");
- return -1;
- }
- /* Update pointers and lengths */
- buf += amt;
- len -= amt;
- }
- ast_frfree(inf);
- }
- return 0;
-}
-
-static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **msg, int *msglen, int *msgtype)
-{
- /* msglen must be no more than 256 bits, each */
- unsigned char buf[24000 * 5];
- int pos = 0, res;
- int x;
- int start=0;
- int retries = 0;
-
- char ack[3];
-
- /* Wait up to 500 ms for initial ACK */
- int waittime;
- struct ast_frame *f;
- int rem = 0;
- int def;
-
- if (chan->adsicpe == AST_ADSI_UNAVAILABLE) {
- /* Don't bother if we know they don't support ADSI */
- errno = ENOSYS;
- return -1;
- }
-
- while(retries < maxretries) {
- if (!(chan->adsicpe & ADSI_FLAG_DATAMODE)) {
- /* Generate CAS (no SAS) */
- ast_gen_cas(buf, 0, 680, AST_FORMAT_ULAW);
-
- /* Send CAS */
- if (adsi_careful_send(chan, buf, 680, NULL)) {
- ast_log(LOG_WARNING, "Unable to send CAS\n");
- }
- /* Wait For DTMF result */
- waittime = 500;
- for(;;) {
- if (((res = ast_waitfor(chan, waittime)) < 1)) {
- /* Didn't get back DTMF A in time */
- ast_log(LOG_DEBUG, "No ADSI CPE detected (%d)\n", res);
- if (!chan->adsicpe)
- chan->adsicpe = AST_ADSI_UNAVAILABLE;
- errno = ENOSYS;
- return -1;
- }
- waittime = res;
- f = ast_read(chan);
- if (!f) {
- ast_log(LOG_DEBUG, "Hangup in ADSI\n");
- return -1;
- }
- if (f->frametype == AST_FRAME_DTMF) {
- if (f->subclass == 'A') {
- /* Okay, this is an ADSI CPE. Note this for future reference, too */
- if (!chan->adsicpe)
- chan->adsicpe = AST_ADSI_AVAILABLE;
- break;
- } else {
- if (f->subclass == 'D') {
- ast_log(LOG_DEBUG, "Off-hook capable CPE only, not ADSI\n");
- } else
- ast_log(LOG_WARNING, "Unknown ADSI response '%c'\n", f->subclass);
- if (!chan->adsicpe)
- chan->adsicpe = AST_ADSI_UNAVAILABLE;
- errno = ENOSYS;
- return -1;
- }
- }
- ast_frfree(f);
- }
-
- ast_log(LOG_DEBUG, "ADSI Compatible CPE Detected\n");
- } else
- ast_log(LOG_DEBUG, "Already in data mode\n");
-
- x = 0;
- pos = 0;
-#if 1
- def= ast_channel_defer_dtmf(chan);
-#endif
- while((x < 6) && msg[x]) {
- res = adsi_generate(buf + pos, msgtype[x], msg[x], msglen[x], x+1 - start, (x == 5) || !msg[x+1], AST_FORMAT_ULAW);
- if (res < 0) {
- ast_log(LOG_WARNING, "Failed to generate ADSI message %d on channel %s\n", x + 1, chan->name);
- return -1;
- }
- ast_log(LOG_DEBUG, "Message %d, of %d input bytes, %d output bytes\n",
- x + 1, msglen[x], res);
- pos += res;
- x++;
- }
-
-
- rem = 0;
- res = adsi_careful_send(chan, buf, pos, &rem);
- if (!def)
- ast_channel_undefer_dtmf(chan);
- if (res)
- return -1;
-
- ast_log(LOG_DEBUG, "Sent total spill of %d bytes\n", pos);
-
- memset(ack, 0, sizeof(ack));
- /* Get real result */
- res = ast_readstring(chan, ack, 2, 1000, 1000, "");
- /* Check for hangup */
- if (res < 0)
- return -1;
- if (ack[0] == 'D') {
- ast_log(LOG_DEBUG, "Acked up to message %d\n", atoi(ack + 1));
- start += atoi(ack + 1);
- if (start >= x)
- break;
- else {
- retries++;
- ast_log(LOG_DEBUG, "Retransmitting (%d), from %d\n", retries, start + 1);
- }
- } else {
- retries++;
- ast_log(LOG_WARNING, "Unexpected response to ack: %s (retry %d)\n", ack, retries);
- }
- }
- if (retries >= maxretries) {
- ast_log(LOG_WARNING, "Maximum ADSI Retries (%d) exceeded\n", maxretries);
- errno = ETIMEDOUT;
- return -1;
- }
- return 0;
-
-}
-
-int adsi_begin_download(struct ast_channel *chan, char *service, unsigned char *fdn, unsigned char *sec, int version)
-{
- int bytes;
- unsigned char buf[256];
- char ack[2];
- bytes = 0;
- /* Setup the resident soft key stuff, a piece at a time */
- /* Upload what scripts we can for voicemail ahead of time */
- bytes += adsi_download_connect(buf + bytes, service, fdn, sec, version);
- if (adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DOWNLOAD, 0))
- return -1;
- if (ast_readstring(chan, ack, 1, 10000, 10000, ""))
- return -1;
- if (ack[0] == 'B')
- return 0;
- ast_log(LOG_DEBUG, "Download was denied by CPE\n");
- return -1;
-}
-
-int adsi_end_download(struct ast_channel *chan)
-{
- int bytes;
- unsigned char buf[256];
- bytes = 0;
- /* Setup the resident soft key stuff, a piece at a time */
- /* Upload what scripts we can for voicemail ahead of time */
- bytes += adsi_download_disconnect(buf + bytes);
- if (adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DOWNLOAD, 0))
- return -1;
- return 0;
-}
-
-int adsi_transmit_message_full(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype, int dowait)
-{
- unsigned char *msgs[5] = { NULL, NULL, NULL, NULL, NULL };
- int msglens[5];
- int msgtypes[5];
- int newdatamode;
- int res;
- int x;
- int writeformat, readformat;
- int waitforswitch = 0;
-
- writeformat = chan->writeformat;
- readformat = chan->readformat;
-
- newdatamode = chan->adsicpe & ADSI_FLAG_DATAMODE;
-
- for (x=0;x<msglen;x+=(msg[x+1]+2)) {
- if (msg[x] == ADSI_SWITCH_TO_DATA) {
- ast_log(LOG_DEBUG, "Switch to data is sent!\n");
- waitforswitch++;
- newdatamode = ADSI_FLAG_DATAMODE;
- }
-
- if (msg[x] == ADSI_SWITCH_TO_VOICE) {
- ast_log(LOG_DEBUG, "Switch to voice is sent!\n");
- waitforswitch++;
- newdatamode = 0;
- }
- }
- msgs[0] = msg;
-
- msglens[0] = msglen;
- msgtypes[0] = msgtype;
-
- if (msglen > 253) {
- ast_log(LOG_WARNING, "Can't send ADSI message of %d bytes, too large\n", msglen);
- return -1;
- }
-
- ast_stopstream(chan);
-
- if (ast_set_write_format(chan, AST_FORMAT_ULAW)) {
- ast_log(LOG_WARNING, "Unable to set write format to ULAW\n");
- return -1;
- }
-
- if (ast_set_read_format(chan, AST_FORMAT_ULAW)) {
- ast_log(LOG_WARNING, "Unable to set read format to ULAW\n");
- if (writeformat) {
- if (ast_set_write_format(chan, writeformat))
- ast_log(LOG_WARNING, "Unable to restore write format to %d\n", writeformat);
- }
- return -1;
- }
- res = __adsi_transmit_messages(chan, msgs, msglens, msgtypes);
-
- if (dowait) {
- ast_log(LOG_DEBUG, "Wait for switch is '%d'\n", waitforswitch);
- while(waitforswitch-- && ((res = ast_waitfordigit(chan, 1000)) > 0)) { res = 0; ast_log(LOG_DEBUG, "Waiting for 'B'...\n"); }
- }
-
- if (!res)
- chan->adsicpe = (chan->adsicpe & ~ADSI_FLAG_DATAMODE) | newdatamode;
-
- if (writeformat)
- ast_set_write_format(chan, writeformat);
- if (readformat)
- ast_set_read_format(chan, readformat);
-
- if (!res)
- res = ast_safe_sleep(chan, 100 );
- return res;
-}
-
-int adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
-{
- return adsi_transmit_message_full(chan, msg, msglen, msgtype, 1);
-}
-
-static inline int ccopy(unsigned char *dst, unsigned char *src, int max)
-{
- int x=0;
- /* Carefully copy the requested data */
- while ((x < max) && src[x] && (src[x] != 0xff)) {
- dst[x] = src[x];
- x++;
- }
- return x;
-}
-
-int adsi_load_soft_key(unsigned char *buf, int key, char *llabel, char *slabel, char *ret, int data)
-{
- int bytes=0;
-
- /* Abort if invalid key specified */
- if ((key < 2) || (key > 33))
- return -1;
- buf[bytes++] = ADSI_LOAD_SOFTKEY;
- /* Reserve for length */
- bytes++;
- /* Which key */
- buf[bytes++] = key;
-
- /* Carefully copy long label */
- bytes += ccopy(buf + bytes, (unsigned char *)llabel, 18);
-
- /* Place delimiter */
- buf[bytes++] = 0xff;
-
- /* Short label */
- bytes += ccopy(buf + bytes, (unsigned char *)slabel, 7);
-
-
- /* If specified, copy return string */
- if (ret) {
- /* Place delimiter */
- buf[bytes++] = 0xff;
- if (data)
- buf[bytes++] = ADSI_SWITCH_TO_DATA2;
- /* Carefully copy return string */
- bytes += ccopy(buf + bytes, (unsigned char *)ret, 20);
-
- }
- /* Replace parameter length */
- buf[1] = bytes - 2;
- return bytes;
-
-}
-
-int adsi_connect_session(unsigned char *buf, unsigned char *fdn, int ver)
-{
- int bytes=0;
- int x;
-
- /* Message type */
- buf[bytes++] = ADSI_CONNECT_SESSION;
-
- /* Reserve space for length */
- bytes++;
-
- if (fdn) {
- for (x=0;x<4;x++)
- buf[bytes++] = fdn[x];
- if (ver > -1)
- buf[bytes++] = ver & 0xff;
- }
-
- buf[1] = bytes - 2;
- return bytes;
-
-}
-
-int adsi_download_connect(unsigned char *buf, char *service, unsigned char *fdn, unsigned char *sec, int ver)
-{
- int bytes=0;
- int x;
-
- /* Message type */
- buf[bytes++] = ADSI_DOWNLOAD_CONNECT;
-
- /* Reserve space for length */
- bytes++;
-
- /* Primary column */
- bytes+= ccopy(buf + bytes, (unsigned char *)service, 18);
-
- /* Delimiter */
- buf[bytes++] = 0xff;
-
- for (x=0;x<4;x++) {
- buf[bytes++] = fdn[x];
- }
- for (x=0;x<4;x++)
- buf[bytes++] = sec[x];
- buf[bytes++] = ver & 0xff;
-
- buf[1] = bytes - 2;
-
- return bytes;
-
-}
-
-int adsi_disconnect_session(unsigned char *buf)
-{
- int bytes=0;
-
- /* Message type */
- buf[bytes++] = ADSI_DISC_SESSION;
-
- /* Reserve space for length */
- bytes++;
-
- buf[1] = bytes - 2;
- return bytes;
-
-}
-
-int adsi_query_cpeid(unsigned char *buf)
-{
- int bytes = 0;
- buf[bytes++] = ADSI_QUERY_CPEID;
- /* Reserve space for length */
- bytes++;
- buf[1] = bytes - 2;
- return bytes;
-}
-
-int adsi_query_cpeinfo(unsigned char *buf)
-{
- int bytes = 0;
- buf[bytes++] = ADSI_QUERY_CONFIG;
- /* Reserve space for length */
- bytes++;
- buf[1] = bytes - 2;
- return bytes;
-}
-
-int adsi_read_encoded_dtmf(struct ast_channel *chan, unsigned char *buf, int maxlen)
-{
- int bytes = 0;
- int res;
- unsigned char current = 0;
- int gotstar = 0;
- int pos = 0;
- memset(buf, 0, sizeof(buf));
- while(bytes <= maxlen) {
- /* Wait up to a second for a digit */
- res = ast_waitfordigit(chan, 1000);
- if (!res)
- break;
- if (res == '*') {
- gotstar = 1;
- continue;
- }
- /* Ignore anything other than a digit */
- if ((res < '0') || (res > '9'))
- continue;
- res -= '0';
- if (gotstar)
- res += 9;
- if (pos) {
- pos = 0;
- buf[bytes++] = (res << 4) | current;
- } else {
- pos = 1;
- current = res;
- }
- gotstar = 0;
- }
- return bytes;
-}
-
-int adsi_get_cpeid(struct ast_channel *chan, unsigned char *cpeid, int voice)
-{
- unsigned char buf[256];
- int bytes = 0;
- int res;
- bytes += adsi_data_mode(buf);
- adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
-
- bytes = 0;
- bytes += adsi_query_cpeid(buf);
- adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
-
- /* Get response */
- memset(buf, 0, sizeof(buf));
- res = adsi_read_encoded_dtmf(chan, cpeid, 4);
- if (res != 4) {
- ast_log(LOG_WARNING, "Got %d bytes back of encoded DTMF, expecting 4\n", res);
- res = 0;
- } else {
- res = 1;
- }
-
- if (voice) {
- bytes = 0;
- bytes += adsi_voice_mode(buf, 0);
- adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
- /* Ignore the resulting DTMF B announcing it's in voice mode */
- ast_waitfordigit(chan, 1000);
- }
- return res;
-}
-
-int adsi_get_cpeinfo(struct ast_channel *chan, int *width, int *height, int *buttons, int voice)
-{
- unsigned char buf[256];
- int bytes = 0;
- int res;
- bytes += adsi_data_mode(buf);
- adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
-
- bytes = 0;
- bytes += adsi_query_cpeinfo(buf);
- adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
-
- /* Get width */
- memset(buf, 0, sizeof(buf));
- res = ast_readstring(chan, (char *)buf, 2, 1000, 500, "");
- if (res < 0)
- return res;
- if (strlen((char *)buf) != 2) {
- ast_log(LOG_WARNING, "Got %d bytes of width, expecting 2\n", res);
- res = 0;
- } else {
- res = 1;
- }
- if (width)
- *width = atoi((char *)buf);
- /* Get height */
- memset(buf, 0, sizeof(buf));
- if (res) {
- res = ast_readstring(chan, (char *)buf, 2, 1000, 500, "");
- if (res < 0)
- return res;
- if (strlen((char *)buf) != 2) {
- ast_log(LOG_WARNING, "Got %d bytes of height, expecting 2\n", res);
- res = 0;
- } else {
- res = 1;
- }
- if (height)
- *height= atoi((char *)buf);
- }
- /* Get buttons */
- memset(buf, 0, sizeof(buf));
- if (res) {
- res = ast_readstring(chan, (char *)buf, 1, 1000, 500, "");
- if (res < 0)
- return res;
- if (strlen((char *)buf) != 1) {
- ast_log(LOG_WARNING, "Got %d bytes of buttons, expecting 1\n", res);
- res = 0;
- } else {
- res = 1;
- }
- if (buttons)
- *buttons = atoi((char *)buf);
- }
- if (voice) {
- bytes = 0;
- bytes += adsi_voice_mode(buf, 0);
- adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
- /* Ignore the resulting DTMF B announcing it's in voice mode */
- ast_waitfordigit(chan, 1000);
- }
- return res;
-}
-
-int adsi_data_mode(unsigned char *buf)
-{
- int bytes=0;
-
- /* Message type */
- buf[bytes++] = ADSI_SWITCH_TO_DATA;
-
- /* Reserve space for length */
- bytes++;
-
- buf[1] = bytes - 2;
- return bytes;
-
-}
-
-int adsi_clear_soft_keys(unsigned char *buf)
-{
- int bytes=0;
-
- /* Message type */
- buf[bytes++] = ADSI_CLEAR_SOFTKEY;
-
- /* Reserve space for length */
- bytes++;
-
- buf[1] = bytes - 2;
- return bytes;
-
-}
-
-int adsi_clear_screen(unsigned char *buf)
-{
- int bytes=0;
-
- /* Message type */
- buf[bytes++] = ADSI_CLEAR_SCREEN;
-
- /* Reserve space for length */
- bytes++;
-
- buf[1] = bytes - 2;
- return bytes;
-
-}
-
-int adsi_voice_mode(unsigned char *buf, int when)
-{
- int bytes=0;
-
- /* Message type */
- buf[bytes++] = ADSI_SWITCH_TO_VOICE;
-
- /* Reserve space for length */
- bytes++;
-
- buf[bytes++] = when & 0x7f;
-
- buf[1] = bytes - 2;
- return bytes;
-
-}
-
-int adsi_available(struct ast_channel *chan)
-{
- int cpe = chan->adsicpe & 0xff;
- if ((cpe == AST_ADSI_AVAILABLE) ||
- (cpe == AST_ADSI_UNKNOWN))
- return 1;
- return 0;
-}
-
-int adsi_download_disconnect(unsigned char *buf)
-{
- int bytes=0;
-
- /* Message type */
- buf[bytes++] = ADSI_DOWNLOAD_DISC;
-
- /* Reserve space for length */
- bytes++;
-
- buf[1] = bytes - 2;
- return bytes;
-
-}
-
-int adsi_display(unsigned char *buf, int page, int line, int just, int wrap,
- char *col1, char *col2)
-{
- int bytes=0;
-
- /* Sanity check line number */
-
- if (page) {
- if (line > 4) return -1;
- } else {
- if (line > 33) return -1;
- }
-
- if (line < 1)
- return -1;
- /* Parameter type */
- buf[bytes++] = ADSI_LOAD_VIRTUAL_DISP;
-
- /* Reserve space for size */
- bytes++;
-
- /* Page and wrap indicator */
- buf[bytes++] = ((page & 0x1) << 7) | ((wrap & 0x1) << 6) | (line & 0x3f);
-
- /* Justification */
- buf[bytes++] = (just & 0x3) << 5;
-
- /* Omit highlight mode definition */
- buf[bytes++] = 0xff;
-
- /* Primary column */
- bytes+= ccopy(buf + bytes, (unsigned char *)col1, 20);
-
- /* Delimiter */
- buf[bytes++] = 0xff;
-
- /* Secondary column */
- bytes += ccopy(buf + bytes, (unsigned char *)col2, 20);
-
- /* Update length */
- buf[1] = bytes - 2;
-
- return bytes;
-
-}
-
-int adsi_input_control(unsigned char *buf, int page, int line, int display, int format, int just)
-{
- int bytes=0;
-
- if (page) {
- if (line > 4) return -1;
- } else {
- if (line > 33) return -1;
- }
-
- if (line < 1)
- return -1;
-
- buf[bytes++] = ADSI_INPUT_CONTROL;
- bytes++;
- buf[bytes++] = ((page & 1) << 7) | (line & 0x3f);
- buf[bytes++] = ((display & 1) << 7) | ((just & 0x3) << 4) | (format & 0x7);
-
- buf[1] = bytes - 2;
- return bytes;
-
-}
-
-int adsi_input_format(unsigned char *buf, int num, int dir, int wrap, char *format1, char *format2)
-{
- int bytes = 0;
-
- if (!strlen((char *)format1))
- return -1;
-
- buf[bytes++] = ADSI_INPUT_FORMAT;
- bytes++;
- buf[bytes++] = ((dir & 1) << 7) | ((wrap & 1) << 6) | (num & 0x7);
- bytes += ccopy(buf + bytes, (unsigned char *)format1, 20);
- buf[bytes++] = 0xff;
- if (format2 && strlen((char *)format2)) {
- bytes += ccopy(buf + bytes, (unsigned char *)format2, 20);
- }
- buf[1] = bytes - 2;
- return bytes;
-}
-
-int adsi_set_keys(unsigned char *buf, unsigned char *keys)
-{
- int bytes=0;
- int x;
- /* Message type */
- buf[bytes++] = ADSI_INIT_SOFTKEY_LINE;
- /* Space for size */
- bytes++;
- /* Key definitions */
- for (x=0;x<6;x++)
- buf[bytes++] = (keys[x] & 0x3f) ? keys[x] : (keys[x] | 0x1);
- buf[1] = bytes - 2;
- return bytes;
-}
-
-int adsi_set_line(unsigned char *buf, int page, int line)
-{
- int bytes=0;
-
- /* Sanity check line number */
-
- if (page) {
- if (line > 4) return -1;
- } else {
- if (line > 33) return -1;
- }
-
- if (line < 1)
- return -1;
- /* Parameter type */
- buf[bytes++] = ADSI_LINE_CONTROL;
-
- /* Reserve space for size */
- bytes++;
-
- /* Page and line */
- buf[bytes++] = ((page & 0x1) << 7) | (line & 0x3f);
-
- buf[1] = bytes - 2;
- return bytes;
-
-};
-
-static int total = 0;
-static int speeds = 0;
-
-int adsi_channel_restore(struct ast_channel *chan)
-{
- unsigned char dsp[256];
- int bytes;
- int x;
- unsigned char keyd[6];
-
- memset(dsp, 0, sizeof(dsp));
-
- /* Start with initial display setup */
- bytes = 0;
- bytes += adsi_set_line(dsp + bytes, ADSI_INFO_PAGE, 1);
-
- /* Prepare key setup messages */
-
- if (speeds) {
- memset(keyd, 0, sizeof(keyd));
- for (x=0;x<speeds;x++) {
- keyd[x] = ADSI_SPEED_DIAL + x;
- }
- bytes += adsi_set_keys(dsp + bytes, keyd);
- }
- adsi_transmit_message_full(chan, dsp, bytes, ADSI_MSG_DISPLAY, 0);
- return 0;
-
-}
-
-int adsi_print(struct ast_channel *chan, char **lines, int *aligns, int voice)
-{
- unsigned char buf[4096];
- int bytes=0;
- int res;
- int x;
- for(x=0;lines[x];x++)
- bytes += adsi_display(buf + bytes, ADSI_INFO_PAGE, x+1, aligns[x], 0, lines[x], "");
- bytes += adsi_set_line(buf + bytes, ADSI_INFO_PAGE, 1);
- if (voice) {
- bytes += adsi_voice_mode(buf + bytes, 0);
- }
- res = adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
- if (voice) {
- /* Ignore the resulting DTMF B announcing it's in voice mode */
- ast_waitfordigit(chan, 1000);
- }
- return res;
-}
-
-int adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data)
-{
- unsigned char dsp[256];
- int bytes;
- int res;
- char resp[2];
-
- memset(dsp, 0, sizeof(dsp));
-
- /* Connect to session */
- bytes = 0;
- bytes += adsi_connect_session(dsp + bytes, app, ver);
-
- if (data)
- bytes += adsi_data_mode(dsp + bytes);
-
- /* Prepare key setup messages */
- if (adsi_transmit_message_full(chan, dsp, bytes, ADSI_MSG_DISPLAY, 0))
- return -1;
- if (app) {
- res = ast_readstring(chan, resp, 1, 1200, 1200, "");
- if (res < 0)
- return -1;
- if (res) {
- ast_log(LOG_DEBUG, "No response from CPE about version. Assuming not there.\n");
- return 0;
- }
- if (!strcmp(resp, "B")) {
- ast_log(LOG_DEBUG, "CPE has script '%s' version %d already loaded\n", app, ver);
- return 1;
- } else if (!strcmp(resp, "A")) {
- ast_log(LOG_DEBUG, "CPE hasn't script '%s' version %d already loaded\n", app, ver);
- } else {
- ast_log(LOG_WARNING, "Unexpected CPE response to script query: %s\n", resp);
- }
- } else
- return 1;
- return 0;
-
-}
-
-int adsi_unload_session(struct ast_channel *chan)
-{
- unsigned char dsp[256];
- int bytes;
-
- memset(dsp, 0, sizeof(dsp));
-
- /* Connect to session */
- bytes = 0;
- bytes += adsi_disconnect_session(dsp + bytes);
- bytes += adsi_voice_mode(dsp + bytes, 0);
-
- /* Prepare key setup messages */
- if (adsi_transmit_message_full(chan, dsp, bytes, ADSI_MSG_DISPLAY, 0))
- return -1;
- return 0;
-}
-
-static int str2align(char *s)
-{
- if (!strncasecmp(s, "l", 1))
- return ADSI_JUST_LEFT;
- else if (!strncasecmp(s, "r", 1))
- return ADSI_JUST_RIGHT;
- else if (!strncasecmp(s, "i", 1))
- return ADSI_JUST_IND;
- else
- return ADSI_JUST_CENT;
-}
-
-static void init_state(void)
-{
- int x;
-
- for (x=0;x<ADSI_MAX_INTRO;x++)
- aligns[x] = ADSI_JUST_CENT;
- strncpy(intro[0], "Welcome to the", sizeof(intro[0]) - 1);
- strncpy(intro[1], "Asterisk", sizeof(intro[1]) - 1);
- strncpy(intro[2], "Open Source PBX", sizeof(intro[2]) - 1);
- total = 3;
- speeds = 0;
- for (x=3;x<ADSI_MAX_INTRO;x++)
- intro[x][0] = '\0';
- memset(speeddial, 0, sizeof(speeddial));
- alignment = ADSI_JUST_CENT;
-}
-
-static void adsi_load(void)
-{
- int x;
- struct ast_config *conf;
- struct ast_variable *v;
- char *name, *sname;
- init_state();
- conf = ast_config_load("adsi.conf");
- if (conf) {
- x=0;
- v = ast_variable_browse(conf, "intro");
- while(v) {
- if (!strcasecmp(v->name, "alignment"))
- alignment = str2align(v->value);
- else if (!strcasecmp(v->name, "greeting")) {
- if (x < ADSI_MAX_INTRO) {
- aligns[x] = alignment;
- strncpy(intro[x], v->value, sizeof(intro[x]) - 1);
- intro[x][sizeof(intro[x]) - 1] = '\0';
- x++;
- }
- } else if (!strcasecmp(v->name, "maxretries")) {
- if (atoi(v->value) > 0)
- maxretries = atoi(v->value);
- }
- v = v->next;
- }
- v = ast_variable_browse(conf, "speeddial");
- if (x)
- total = x;
- x = 0;
- while(v) {
- char *stringp=NULL;
- stringp=v->value;
- name = strsep(&stringp, ",");
- sname = strsep(&stringp, ",");
- if (!sname)
- sname = name;
- if (x < ADSI_MAX_SPEED_DIAL) {
- /* Up to 20 digits */
- strncpy(speeddial[x][0], v->name, sizeof(speeddial[x][0]) - 1);
- strncpy(speeddial[x][1], name, 18);
- strncpy(speeddial[x][2], sname, 7);
- x++;
- }
- v = v->next;
-
- }
- if (x)
- speeds = x;
- ast_config_destroy(conf);
- }
-}
-
-int reload(void)
-{
- adsi_load();
- return 0;
-}
-
-int load_module(void)
-{
- adsi_load();
- return 0;
-}
-
-int unload_module(void)
-{
- /* Can't unload this once we're loaded */
- return -1;
-}
-
-char *description(void)
-{
- return "ADSI Resource";
-}
-
-int usecount(void)
-{
- /* We should never be unloaded */
- return 1;
-}
-
-char *key()
-{
- return ASTERISK_GPL_KEY;
-}
diff --git a/1.2-netsec/res/res_agi.c b/1.2-netsec/res/res_agi.c
deleted file mode 100644
index 8f9654443..000000000
--- a/1.2-netsec/res/res_agi.c
+++ /dev/null
@@ -1,2142 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief AGI - the Asterisk Gateway Interface
- *
- */
-
-#include <sys/types.h>
-#include <netdb.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <math.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/file.h"
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/pbx.h"
-#include "asterisk/module.h"
-#include "asterisk/astdb.h"
-#include "asterisk/callerid.h"
-#include "asterisk/cli.h"
-#include "asterisk/logger.h"
-#include "asterisk/options.h"
-#include "asterisk/image.h"
-#include "asterisk/say.h"
-#include "asterisk/app.h"
-#include "asterisk/dsp.h"
-#include "asterisk/musiconhold.h"
-#include "asterisk/manager.h"
-#include "asterisk/utils.h"
-#include "asterisk/lock.h"
-#include "asterisk/strings.h"
-#include "asterisk/agi.h"
-
-#define MAX_ARGS 128
-#define MAX_COMMANDS 128
-
-/* Recycle some stuff from the CLI interface */
-#define fdprintf agi_debug_cli
-
-static char *tdesc = "Asterisk Gateway Interface (AGI)";
-
-static char *app = "AGI";
-
-static char *eapp = "EAGI";
-
-static char *deadapp = "DeadAGI";
-
-static char *synopsis = "Executes an AGI compliant application";
-static char *esynopsis = "Executes an EAGI compliant application";
-static char *deadsynopsis = "Executes AGI on a hungup channel";
-
-static char *descrip =
-" [E|Dead]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
-"program on a channel. AGI allows Asterisk to launch external programs\n"
-"written in any language to control a telephony channel, play audio,\n"
-"read DTMF digits, etc. by communicating with the AGI protocol on stdin\n"
-"and stdout.\n"
-"Returns -1 on hangup (except for DeadAGI) or if application requested\n"
-" hangup, or 0 on non-hangup exit. \n"
-"Using 'EAGI' provides enhanced AGI, with incoming audio available out of band\n"
-"on file descriptor 3\n\n"
-"Use the CLI command 'show agi' to list available agi commands\n";
-
-static int agidebug = 0;
-
-STANDARD_LOCAL_USER;
-
-LOCAL_USER_DECL;
-
-
-#define TONE_BLOCK_SIZE 200
-
-/* Max time to connect to an AGI remote host */
-#define MAX_AGI_CONNECT 2000
-
-#define AGI_PORT 4573
-
-static void agi_debug_cli(int fd, char *fmt, ...)
-{
- char *stuff;
- int res = 0;
-
- va_list ap;
- va_start(ap, fmt);
- res = vasprintf(&stuff, fmt, ap);
- va_end(ap);
- if (res == -1) {
- ast_log(LOG_ERROR, "Out of memory\n");
- } else {
- if (agidebug)
- ast_verbose("AGI Tx >> %s", stuff);
- ast_carefulwrite(fd, stuff, strlen(stuff), 100);
- free(stuff);
- }
-}
-
-/* launch_netscript: The fastagi handler.
- FastAGI defaults to port 4573 */
-static int launch_netscript(char *agiurl, char *argv[], int *fds, int *efd, int *opid)
-{
- int s;
- int flags;
- struct pollfd pfds[1];
- char *host;
- char *c; int port = AGI_PORT;
- char *script="";
- struct sockaddr_in sin;
- struct hostent *hp;
- struct ast_hostent ahp;
-
- host = ast_strdupa(agiurl + 6); /* Remove agi:// */
- if (!host)
- return -1;
- /* Strip off any script name */
- if ((c = strchr(host, '/'))) {
- *c = '\0';
- c++;
- script = c;
- }
- if ((c = strchr(host, ':'))) {
- *c = '\0';
- c++;
- port = atoi(c);
- }
- if (efd) {
- ast_log(LOG_WARNING, "AGI URI's don't support Enhanced AGI yet\n");
- return -1;
- }
- hp = ast_gethostbyname(host, &ahp);
- if (!hp) {
- ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host);
- return -1;
- }
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s < 0) {
- ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
- return -1;
- }
- flags = fcntl(s, F_GETFL);
- if (flags < 0) {
- ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno));
- close(s);
- return -1;
- }
- if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
- ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno));
- close(s);
- return -1;
- }
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
- if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) && (errno != EINPROGRESS)) {
- ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno));
- close(s);
- return -1;
- }
-
- pfds[0].fd = s;
- pfds[0].events = POLLOUT;
- while (poll(pfds, 1, MAX_AGI_CONNECT) != 1) {
- if (errno != EINTR) {
- ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
- close(s);
- return -1;
- }
- }
-
- while (write(s, "agi_network: yes\n", strlen("agi_network: yes\n")) < 0) {
- if (errno != EINTR) {
- ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
- close(s);
- return -1;
- }
- }
-
- /* If we have a script parameter, relay it to the fastagi server */
- if (!ast_strlen_zero(script))
- fdprintf(s, "agi_network_script: %s\n", script);
-
- if (option_debug > 3)
- ast_log(LOG_DEBUG, "Wow, connected!\n");
- fds[0] = s;
- fds[1] = s;
- *opid = -1;
- return 0;
-}
-
-static int launch_script(char *script, char *argv[], int *fds, int *efd, int *opid)
-{
- char tmp[256];
- int pid;
- int toast[2];
- int fromast[2];
- int audio[2];
- int x;
- int res;
- sigset_t signal_set;
-
- if (!strncasecmp(script, "agi://", 6))
- return launch_netscript(script, argv, fds, efd, opid);
-
- if (script[0] != '/') {
- snprintf(tmp, sizeof(tmp), "%s/%s", (char *)ast_config_AST_AGI_DIR, script);
- script = tmp;
- }
- if (pipe(toast)) {
- ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno));
- return -1;
- }
- if (pipe(fromast)) {
- ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno));
- close(toast[0]);
- close(toast[1]);
- return -1;
- }
- if (efd) {
- if (pipe(audio)) {
- ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
- close(fromast[0]);
- close(fromast[1]);
- close(toast[0]);
- close(toast[1]);
- return -1;
- }
- res = fcntl(audio[1], F_GETFL);
- if (res > -1)
- res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK);
- if (res < 0) {
- ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
- close(fromast[0]);
- close(fromast[1]);
- close(toast[0]);
- close(toast[1]);
- close(audio[0]);
- close(audio[1]);
- return -1;
- }
- }
- pid = fork();
- if (pid < 0) {
- ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
- return -1;
- }
- if (!pid) {
- /* Redirect stdin and out, provide enhanced audio channel if desired */
- dup2(fromast[0], STDIN_FILENO);
- dup2(toast[1], STDOUT_FILENO);
- if (efd) {
- dup2(audio[0], STDERR_FILENO + 1);
- } else {
- close(STDERR_FILENO + 1);
- }
-
- /* unblock important signal handlers */
- if (sigfillset(&signal_set) || pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
- ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno));
- exit(1);
- }
-
- /* Close everything but stdin/out/error */
- for (x=STDERR_FILENO + 2;x<1024;x++)
- close(x);
-
- /* Don't run AGI scripts with realtime priority -- it causes audio stutter */
- ast_set_priority(0);
-
- /* Execute script */
- execv(script, argv);
- /* Can't use ast_log since FD's are closed */
- fprintf(stderr, "Failed to execute '%s': %s\n", script, strerror(errno));
- exit(1);
- }
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Launched AGI Script %s\n", script);
- fds[0] = toast[0];
- fds[1] = fromast[1];
- if (efd) {
- *efd = audio[1];
- }
- /* close what we're not using in the parent */
- close(toast[1]);
- close(fromast[0]);
-
- if (efd) {
- /* [PHM 12/18/03] */
- close(audio[0]);
- }
-
- *opid = pid;
- return 0;
-
-}
-
-static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced)
-{
- /* Print initial environment, with agi_request always being the first
- thing */
- fdprintf(fd, "agi_request: %s\n", request);
- fdprintf(fd, "agi_channel: %s\n", chan->name);
- fdprintf(fd, "agi_language: %s\n", chan->language);
- fdprintf(fd, "agi_type: %s\n", chan->type);
- fdprintf(fd, "agi_uniqueid: %s\n", chan->uniqueid);
-
- /* ANI/DNIS */
- fdprintf(fd, "agi_callerid: %s\n", chan->cid.cid_num ? chan->cid.cid_num : "unknown");
- fdprintf(fd, "agi_calleridname: %s\n", chan->cid.cid_name ? chan->cid.cid_name : "unknown");
- fdprintf(fd, "agi_callingpres: %d\n", chan->cid.cid_pres);
- fdprintf(fd, "agi_callingani2: %d\n", chan->cid.cid_ani2);
- fdprintf(fd, "agi_callington: %d\n", chan->cid.cid_ton);
- fdprintf(fd, "agi_callingtns: %d\n", chan->cid.cid_tns);
- fdprintf(fd, "agi_dnid: %s\n", chan->cid.cid_dnid ? chan->cid.cid_dnid : "unknown");
- fdprintf(fd, "agi_rdnis: %s\n", chan->cid.cid_rdnis ? chan->cid.cid_rdnis : "unknown");
-
- /* Context information */
- fdprintf(fd, "agi_context: %s\n", chan->context);
- fdprintf(fd, "agi_extension: %s\n", chan->exten);
- fdprintf(fd, "agi_priority: %d\n", chan->priority);
- fdprintf(fd, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
-
- /* User information */
- fdprintf(fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
-
- /* End with empty return */
- fdprintf(fd, "\n");
-}
-
-static int handle_answer(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res;
- res = 0;
- if (chan->_state != AST_STATE_UP) {
- /* Answer the chan */
- res = ast_answer(chan);
- }
- fdprintf(agi->fd, "200 result=%d\n", res);
- if (res >= 0)
- return RESULT_SUCCESS;
- else
- return RESULT_FAILURE;
-}
-
-static int handle_waitfordigit(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res;
- int to;
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- if (sscanf(argv[3], "%d", &to) != 1)
- return RESULT_SHOWUSAGE;
- res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
- fdprintf(agi->fd, "200 result=%d\n", res);
- if (res >= 0)
- return RESULT_SUCCESS;
- else
- return RESULT_FAILURE;
-}
-
-static int handle_sendtext(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res;
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- /* At the moment, the parser (perhaps broken) returns with
- the last argument PLUS the newline at the end of the input
- buffer. This probably needs to be fixed, but I wont do that
- because other stuff may break as a result. The right way
- would probably be to strip off the trailing newline before
- parsing, then here, add a newline at the end of the string
- before sending it to ast_sendtext --DUDE */
- res = ast_sendtext(chan, argv[2]);
- fdprintf(agi->fd, "200 result=%d\n", res);
- if (res >= 0)
- return RESULT_SUCCESS;
- else
- return RESULT_FAILURE;
-}
-
-static int handle_recvchar(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res;
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- res = ast_recvchar(chan,atoi(argv[2]));
- if (res == 0) {
- fdprintf(agi->fd, "200 result=%d (timeout)\n", res);
- return RESULT_SUCCESS;
- }
- if (res > 0) {
- fdprintf(agi->fd, "200 result=%d\n", res);
- return RESULT_SUCCESS;
- }
- else {
- fdprintf(agi->fd, "200 result=%d (hangup)\n", res);
- return RESULT_FAILURE;
- }
-}
-
-static int handle_recvtext(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- char *buf;
-
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- buf = ast_recvtext(chan,atoi(argv[2]));
- if (buf) {
- fdprintf(agi->fd, "200 result=1 (%s)\n", buf);
- free(buf);
- } else {
- fdprintf(agi->fd, "200 result=-1\n");
- }
- return RESULT_SUCCESS;
-}
-
-static int handle_tddmode(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res,x;
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- if (!strncasecmp(argv[2],"on",2))
- x = 1;
- else
- x = 0;
- if (!strncasecmp(argv[2],"mate",4))
- x = 2;
- if (!strncasecmp(argv[2],"tdd",3))
- x = 1;
- res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0);
- if (res != RESULT_SUCCESS)
- fdprintf(agi->fd, "200 result=0\n");
- else
- fdprintf(agi->fd, "200 result=1\n");
- return RESULT_SUCCESS;
-}
-
-static int handle_sendimage(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res;
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- res = ast_send_image(chan, argv[2]);
- if (!ast_check_hangup(chan))
- res = 0;
- fdprintf(agi->fd, "200 result=%d\n", res);
- if (res >= 0)
- return RESULT_SUCCESS;
- else
- return RESULT_FAILURE;
-}
-
-static int handle_controlstreamfile(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res = 0;
- int skipms = 3000;
- char *fwd = NULL;
- char *rev = NULL;
- char *pause = NULL;
- char *stop = NULL;
-
- if (argc < 5 || argc > 9)
- return RESULT_SHOWUSAGE;
-
- if (!ast_strlen_zero(argv[4]))
- stop = argv[4];
- else
- stop = NULL;
-
- if ((argc > 5) && (sscanf(argv[5], "%d", &skipms) != 1))
- return RESULT_SHOWUSAGE;
-
- if (argc > 6 && !ast_strlen_zero(argv[8]))
- fwd = argv[6];
- else
- fwd = "#";
-
- if (argc > 7 && !ast_strlen_zero(argv[8]))
- rev = argv[7];
- else
- rev = "*";
-
- if (argc > 8 && !ast_strlen_zero(argv[8]))
- pause = argv[8];
- else
- pause = NULL;
-
- res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, pause, NULL, skipms);
-
- fdprintf(agi->fd, "200 result=%d\n", res);
-
- if (res >= 0)
- return RESULT_SUCCESS;
- else
- return RESULT_FAILURE;
-}
-
-static int handle_streamfile(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res;
- struct ast_filestream *fs;
- long sample_offset = 0;
- long max_length;
-
- if (argc < 4)
- return RESULT_SHOWUSAGE;
- if (argc > 5)
- return RESULT_SHOWUSAGE;
- if ((argc > 4) && (sscanf(argv[4], "%ld", &sample_offset) != 1))
- return RESULT_SHOWUSAGE;
-
- fs = ast_openstream(chan, argv[2], chan->language);
- if (!fs){
- fdprintf(agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset);
- return RESULT_SUCCESS;
- }
- ast_seekstream(fs, 0, SEEK_END);
- max_length = ast_tellstream(fs);
- ast_seekstream(fs, sample_offset, SEEK_SET);
- res = ast_applystream(chan, fs);
- res = ast_playstream(fs);
- if (res) {
- fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset);
- if (res >= 0)
- return RESULT_SHOWUSAGE;
- else
- return RESULT_FAILURE;
- }
- res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
- /* this is to check for if ast_waitstream closed the stream, we probably are at
- * the end of the stream, return that amount, else check for the amount */
- sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length;
- ast_stopstream(chan);
- if (res == 1) {
- /* Stop this command, don't print a result line, as there is a new command */
- return RESULT_SUCCESS;
- }
- fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset);
- if (res >= 0)
- return RESULT_SUCCESS;
- else
- return RESULT_FAILURE;
-}
-
-/* get option - really similar to the handle_streamfile, but with a timeout */
-static int handle_getoption(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res;
- struct ast_filestream *fs;
- long sample_offset = 0;
- long max_length;
- int timeout = 0;
- char *edigits = NULL;
-
- if ( argc < 4 || argc > 5 )
- return RESULT_SHOWUSAGE;
-
- if ( argv[3] )
- edigits = argv[3];
-
- if ( argc == 5 )
- timeout = atoi(argv[4]);
- else if (chan->pbx->dtimeout) {
- /* by default dtimeout is set to 5sec */
- timeout = chan->pbx->dtimeout * 1000; /* in msec */
- }
-
- fs = ast_openstream(chan, argv[2], chan->language);
- if (!fs){
- fdprintf(agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset);
- ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]);
- return RESULT_SUCCESS;
- }
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout);
-
- ast_seekstream(fs, 0, SEEK_END);
- max_length = ast_tellstream(fs);
- ast_seekstream(fs, sample_offset, SEEK_SET);
- res = ast_applystream(chan, fs);
- res = ast_playstream(fs);
- if (res) {
- fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset);
- if (res >= 0)
- return RESULT_SHOWUSAGE;
- else
- return RESULT_FAILURE;
- }
- res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
- /* this is to check for if ast_waitstream closed the stream, we probably are at
- * the end of the stream, return that amount, else check for the amount */
- sample_offset = (chan->stream)?ast_tellstream(fs):max_length;
- ast_stopstream(chan);
- if (res == 1) {
- /* Stop this command, don't print a result line, as there is a new command */
- return RESULT_SUCCESS;
- }
-
- /* If the user didnt press a key, wait for digitTimeout*/
- if (res == 0 ) {
- res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);
- /* Make sure the new result is in the escape digits of the GET OPTION */
- if ( !strchr(edigits,res) )
- res=0;
- }
-
- fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset);
- if (res >= 0)
- return RESULT_SUCCESS;
- else
- return RESULT_FAILURE;
-}
-
-
-
-
-/*--- handle_saynumber: Say number in various language syntaxes ---*/
-/* Need to add option for gender here as well. Coders wanted */
-/* While waiting, we're sending a (char *) NULL. */
-static int handle_saynumber(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res;
- int num;
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- if (sscanf(argv[2], "%d", &num) != 1)
- return RESULT_SHOWUSAGE;
- res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio, agi->ctrl);
- if (res == 1)
- return RESULT_SUCCESS;
- fdprintf(agi->fd, "200 result=%d\n", res);
- if (res >= 0)
- return RESULT_SUCCESS;
- else
- return RESULT_FAILURE;
-}
-
-static int handle_saydigits(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res;
- int num;
-
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- if (sscanf(argv[2], "%d", &num) != 1)
- return RESULT_SHOWUSAGE;
-
- res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
- if (res == 1) /* New command */
- return RESULT_SUCCESS;
- fdprintf(agi->fd, "200 result=%d\n", res);
- if (res >= 0)
- return RESULT_SUCCESS;
- else
- return RESULT_FAILURE;
-}
-
-static int handle_sayalpha(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res;
-
- if (argc != 4)
- return RESULT_SHOWUSAGE;
-
- res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
- if (res == 1) /* New command */
- return RESULT_SUCCESS;
- fdprintf(agi->fd, "200 result=%d\n", res);
- if (res >= 0)
- return RESULT_SUCCESS;
- else
- return RESULT_FAILURE;
-}
-
-static int handle_saydate(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res;
- int num;
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- if (sscanf(argv[2], "%d", &num) != 1)
- return RESULT_SHOWUSAGE;
- res = ast_say_date(chan, num, argv[3], chan->language);
- if (res == 1)
- return RESULT_SUCCESS;
- fdprintf(agi->fd, "200 result=%d\n", res);
- if (res >= 0)
- return RESULT_SUCCESS;
- else
- return RESULT_FAILURE;
-}
-
-static int handle_saytime(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res;
- int num;
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- if (sscanf(argv[2], "%d", &num) != 1)
- return RESULT_SHOWUSAGE;
- res = ast_say_time(chan, num, argv[3], chan->language);
- if (res == 1)
- return RESULT_SUCCESS;
- fdprintf(agi->fd, "200 result=%d\n", res);
- if (res >= 0)
- return RESULT_SUCCESS;
- else
- return RESULT_FAILURE;
-}
-
-static int handle_saydatetime(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res=0;
- long unixtime;
- char *format, *zone=NULL;
-
- if (argc < 4)
- return RESULT_SHOWUSAGE;
-
- if (argc > 4) {
- format = argv[4];
- } else {
- if (!strcasecmp(chan->language, "de")) {
- format = "A dBY HMS";
- } else {
- format = "ABdY 'digits/at' IMp";
- }
- }
-
- if (argc > 5 && !ast_strlen_zero(argv[5]))
- zone = argv[5];
-
- if (sscanf(argv[2], "%ld", &unixtime) != 1)
- return RESULT_SHOWUSAGE;
-
- res = ast_say_date_with_format(chan, (time_t) unixtime, argv[3], chan->language, format, zone);
- if (res == 1)
- return RESULT_SUCCESS;
-
- fdprintf(agi->fd, "200 result=%d\n", res);
-
- if (res >= 0)
- return RESULT_SUCCESS;
- else
- return RESULT_FAILURE;
-}
-
-static int handle_sayphonetic(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res;
-
- if (argc != 4)
- return RESULT_SHOWUSAGE;
-
- res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
- if (res == 1) /* New command */
- return RESULT_SUCCESS;
- fdprintf(agi->fd, "200 result=%d\n", res);
- if (res >= 0)
- return RESULT_SUCCESS;
- else
- return RESULT_FAILURE;
-}
-
-static int handle_getdata(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int res;
- char data[1024];
- int max;
- int timeout;
-
- if (argc < 3)
- return RESULT_SHOWUSAGE;
- if (argc >= 4)
- timeout = atoi(argv[3]);
- else
- timeout = 0;
- if (argc >= 5)
- max = atoi(argv[4]);
- else
- max = 1024;
- res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
- if (res == 2) /* New command */
- return RESULT_SUCCESS;
- else if (res == 1)
- fdprintf(agi->fd, "200 result=%s (timeout)\n", data);
- else if (res < 0 )
- fdprintf(agi->fd, "200 result=-1\n");
- else
- fdprintf(agi->fd, "200 result=%s\n", data);
- return RESULT_SUCCESS;
-}
-
-static int handle_setcontext(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
-
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- ast_copy_string(chan->context, argv[2], sizeof(chan->context));
- fdprintf(agi->fd, "200 result=0\n");
- return RESULT_SUCCESS;
-}
-
-static int handle_setextension(struct ast_channel *chan, AGI *agi, int argc, char **argv)
-{
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- ast_copy_string(chan->exten, argv[2], sizeof(chan->exten));
- fdprintf(agi->fd, "200 result=0\n");
- return RESULT_SUCCESS;
-}
-
-static int handle_setpriority(struct ast_channel *chan, AGI *agi, int argc, char **argv)
-{
- int pri;
- if (argc != 3)
- return RESULT_SHOWUSAGE;
-
- if (sscanf(argv[2], "%d", &pri) != 1) {
- if ((pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2], chan->cid.cid_num)) < 1)
- return RESULT_SHOWUSAGE;
- }
-
- ast_explicit_goto(chan, NULL, NULL, pri);
- fdprintf(agi->fd, "200 result=0\n");
- return RESULT_SUCCESS;
-}
-
-static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- struct ast_filestream *fs;
- struct ast_frame *f;
- struct timeval start;
- long sample_offset = 0;
- int res = 0;
- int ms;
-
- struct ast_dsp *sildet=NULL; /* silence detector dsp */
- int totalsilence = 0;
- int dspsilence = 0;
- int silence = 0; /* amount of silence to allow */
- int gotsilence = 0; /* did we timeout for silence? */
- char *silencestr=NULL;
- int rfmt=0;
-
-
- /* XXX EAGI FIXME XXX */
-
- if (argc < 6)
- return RESULT_SHOWUSAGE;
- if (sscanf(argv[5], "%d", &ms) != 1)
- return RESULT_SHOWUSAGE;
-
- if (argc > 6)
- silencestr = strchr(argv[6],'s');
- if ((argc > 7) && (!silencestr))
- silencestr = strchr(argv[7],'s');
- if ((argc > 8) && (!silencestr))
- silencestr = strchr(argv[8],'s');
-
- if (silencestr) {
- if (strlen(silencestr) > 2) {
- if ((silencestr[0] == 's') && (silencestr[1] == '=')) {
- silencestr++;
- silencestr++;
- if (silencestr)
- silence = atoi(silencestr);
- if (silence > 0)
- silence *= 1000;
- }
- }
- }
-
- if (silence > 0) {
- rfmt = chan->readformat;
- res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
- if (res < 0) {
- ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
- return -1;
- }
- sildet = ast_dsp_new();
- if (!sildet) {
- ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
- return -1;
- }
- ast_dsp_set_threshold(sildet, 256);
- }
-
- /* backward compatibility, if no offset given, arg[6] would have been
- * caught below and taken to be a beep, else if it is a digit then it is a
- * offset */
- if ((argc >6) && (sscanf(argv[6], "%ld", &sample_offset) != 1) && (!strchr(argv[6], '=')))
- res = ast_streamfile(chan, "beep", chan->language);
-
- if ((argc > 7) && (!strchr(argv[7], '=')))
- res = ast_streamfile(chan, "beep", chan->language);
-
- if (!res)
- res = ast_waitstream(chan, argv[4]);
- if (res) {
- fdprintf(agi->fd, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset);
- } else {
- fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, 0644);
- if (!fs) {
- res = -1;
- fdprintf(agi->fd, "200 result=%d (writefile)\n", res);
- if (sildet)
- ast_dsp_free(sildet);
- return RESULT_FAILURE;
- }
-
- chan->stream = fs;
- ast_applystream(chan,fs);
- /* really should have checks */
- ast_seekstream(fs, sample_offset, SEEK_SET);
- ast_truncstream(fs);
-
- start = ast_tvnow();
- while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) {
- res = ast_waitfor(chan, -1);
- if (res < 0) {
- ast_closestream(fs);
- fdprintf(agi->fd, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset);
- if (sildet)
- ast_dsp_free(sildet);
- return RESULT_FAILURE;
- }
- f = ast_read(chan);
- if (!f) {
- fdprintf(agi->fd, "200 result=%d (hangup) endpos=%ld\n", 0, sample_offset);
- ast_closestream(fs);
- if (sildet)
- ast_dsp_free(sildet);
- return RESULT_FAILURE;
- }
- switch(f->frametype) {
- case AST_FRAME_DTMF:
- if (strchr(argv[4], f->subclass)) {
- /* This is an interrupting chracter, so rewind to chop off any small
- amount of DTMF that may have been recorded
- */
- ast_stream_rewind(fs, 200);
- ast_truncstream(fs);
- sample_offset = ast_tellstream(fs);
- fdprintf(agi->fd, "200 result=%d (dtmf) endpos=%ld\n", f->subclass, sample_offset);
- ast_closestream(fs);
- ast_frfree(f);
- if (sildet)
- ast_dsp_free(sildet);
- return RESULT_SUCCESS;
- }
- break;
- case AST_FRAME_VOICE:
- ast_writestream(fs, f);
- /* this is a safe place to check progress since we know that fs
- * is valid after a write, and it will then have our current
- * location */
- sample_offset = ast_tellstream(fs);
- if (silence > 0) {
- dspsilence = 0;
- ast_dsp_silence(sildet, f, &dspsilence);
- if (dspsilence) {
- totalsilence = dspsilence;
- } else {
- totalsilence = 0;
- }
- if (totalsilence > silence) {
- /* Ended happily with silence */
- ast_frfree(f);
- gotsilence = 1;
- break;
- }
- }
- break;
- }
- ast_frfree(f);
- if (gotsilence)
- break;
- }
-
- if (gotsilence) {
- ast_stream_rewind(fs, silence-1000);
- ast_truncstream(fs);
- sample_offset = ast_tellstream(fs);
- }
- fdprintf(agi->fd, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
- ast_closestream(fs);
- }
-
- if (silence > 0) {
- res = ast_set_read_format(chan, rfmt);
- if (res)
- ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
- ast_dsp_free(sildet);
- }
- return RESULT_SUCCESS;
-}
-
-static int handle_autohangup(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- int timeout;
-
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- if (sscanf(argv[2], "%d", &timeout) != 1)
- return RESULT_SHOWUSAGE;
- if (timeout < 0)
- timeout = 0;
- if (timeout)
- chan->whentohangup = time(NULL) + timeout;
- else
- chan->whentohangup = 0;
- fdprintf(agi->fd, "200 result=0\n");
- return RESULT_SUCCESS;
-}
-
-static int handle_hangup(struct ast_channel *chan, AGI *agi, int argc, char **argv)
-{
- struct ast_channel *c;
- if (argc == 1) {
- /* no argument: hangup the current channel */
- ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT);
- fdprintf(agi->fd, "200 result=1\n");
- return RESULT_SUCCESS;
- } else if (argc == 2) {
- /* one argument: look for info on the specified channel */
- c = ast_get_channel_by_name_locked(argv[1]);
- if (c) {
- /* we have a matching channel */
- ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT);
- fdprintf(agi->fd, "200 result=1\n");
- ast_mutex_unlock(&c->lock);
- return RESULT_SUCCESS;
- }
- /* if we get this far no channel name matched the argument given */
- fdprintf(agi->fd, "200 result=-1\n");
- return RESULT_SUCCESS;
- } else {
- return RESULT_SHOWUSAGE;
- }
-}
-
-static int handle_exec(struct ast_channel *chan, AGI *agi, int argc, char **argv)
-{
- int res;
- struct ast_app *app;
-
- if (argc < 2)
- return RESULT_SHOWUSAGE;
-
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argv[2]);
-
- app = pbx_findapp(argv[1]);
-
- if (app) {
- res = pbx_exec(chan, app, argv[2], 1);
- } else {
- ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]);
- res = -2;
- }
- fdprintf(agi->fd, "200 result=%d\n", res);
-
- return res;
-}
-
-static int handle_setcallerid(struct ast_channel *chan, AGI *agi, int argc, char **argv)
-{
- char tmp[256]="";
- char *l = NULL, *n = NULL;
-
- if (argv[2]) {
- ast_copy_string(tmp, argv[2], sizeof(tmp));
- ast_callerid_parse(tmp, &n, &l);
- if (l)
- ast_shrink_phone_number(l);
- else
- l = "";
- if (!n)
- n = "";
- ast_set_callerid(chan, l, n, NULL);
- }
-
- fdprintf(agi->fd, "200 result=1\n");
- return RESULT_SUCCESS;
-}
-
-static int handle_channelstatus(struct ast_channel *chan, AGI *agi, int argc, char **argv)
-{
- struct ast_channel *c;
- if (argc == 2) {
- /* no argument: supply info on the current channel */
- fdprintf(agi->fd, "200 result=%d\n", chan->_state);
- return RESULT_SUCCESS;
- } else if (argc == 3) {
- /* one argument: look for info on the specified channel */
- c = ast_get_channel_by_name_locked(argv[2]);
- if (c) {
- fdprintf(agi->fd, "200 result=%d\n", c->_state);
- ast_mutex_unlock(&c->lock);
- return RESULT_SUCCESS;
- }
- /* if we get this far no channel name matched the argument given */
- fdprintf(agi->fd, "200 result=-1\n");
- return RESULT_SUCCESS;
- } else {
- return RESULT_SHOWUSAGE;
- }
-}
-
-static int handle_setvariable(struct ast_channel *chan, AGI *agi, int argc, char **argv)
-{
- if (argv[3])
- pbx_builtin_setvar_helper(chan, argv[2], argv[3]);
-
- fdprintf(agi->fd, "200 result=1\n");
- return RESULT_SUCCESS;
-}
-
-static int handle_getvariable(struct ast_channel *chan, AGI *agi, int argc, char **argv)
-{
- char *ret;
- char tempstr[1024];
-
- if (argc != 3)
- return RESULT_SHOWUSAGE;
-
- /* check if we want to execute an ast_custom_function */
- if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) {
- ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr));
- } else {
- pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL);
- }
-
- if (ret)
- fdprintf(agi->fd, "200 result=1 (%s)\n", ret);
- else
- fdprintf(agi->fd, "200 result=0\n");
-
- return RESULT_SUCCESS;
-}
-
-static int handle_getvariablefull(struct ast_channel *chan, AGI *agi, int argc, char **argv)
-{
- char tmp[4096] = "";
- struct ast_channel *chan2=NULL;
-
- if ((argc != 4) && (argc != 5))
- return RESULT_SHOWUSAGE;
- if (argc == 5) {
- chan2 = ast_get_channel_by_name_locked(argv[4]);
- } else {
- chan2 = chan;
- }
- if (chan) { /* XXX isn't this chan2 ? */
- pbx_substitute_variables_helper(chan2, argv[3], tmp, sizeof(tmp) - 1);
- fdprintf(agi->fd, "200 result=1 (%s)\n", tmp);
- } else {
- fdprintf(agi->fd, "200 result=0\n");
- }
- if (chan2 && (chan2 != chan))
- ast_mutex_unlock(&chan2->lock);
- return RESULT_SUCCESS;
-}
-
-static int handle_verbose(struct ast_channel *chan, AGI *agi, int argc, char **argv)
-{
- int level = 0;
- char *prefix;
-
- if (argc < 2)
- return RESULT_SHOWUSAGE;
-
- if (argv[2])
- sscanf(argv[2], "%d", &level);
-
- switch (level) {
- case 4:
- prefix = VERBOSE_PREFIX_4;
- break;
- case 3:
- prefix = VERBOSE_PREFIX_3;
- break;
- case 2:
- prefix = VERBOSE_PREFIX_2;
- break;
- case 1:
- default:
- prefix = VERBOSE_PREFIX_1;
- break;
- }
-
- if (level <= option_verbose)
- ast_verbose("%s %s: %s\n", prefix, chan->data, argv[1]);
-
- fdprintf(agi->fd, "200 result=1\n");
-
- return RESULT_SUCCESS;
-}
-
-static int handle_dbget(struct ast_channel *chan, AGI *agi, int argc, char **argv)
-{
- int res;
- char tmp[256];
-
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp));
- if (res)
- fdprintf(agi->fd, "200 result=0\n");
- else
- fdprintf(agi->fd, "200 result=1 (%s)\n", tmp);
-
- return RESULT_SUCCESS;
-}
-
-static int handle_dbput(struct ast_channel *chan, AGI *agi, int argc, char **argv)
-{
- int res;
-
- if (argc != 5)
- return RESULT_SHOWUSAGE;
- res = ast_db_put(argv[2], argv[3], argv[4]);
- if (res)
- fdprintf(agi->fd, "200 result=0\n");
- else
- fdprintf(agi->fd, "200 result=1\n");
-
- return RESULT_SUCCESS;
-}
-
-static int handle_dbdel(struct ast_channel *chan, AGI *agi, int argc, char **argv)
-{
- int res;
-
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- res = ast_db_del(argv[2], argv[3]);
- if (res)
- fdprintf(agi->fd, "200 result=0\n");
- else
- fdprintf(agi->fd, "200 result=1\n");
-
- return RESULT_SUCCESS;
-}
-
-static int handle_dbdeltree(struct ast_channel *chan, AGI *agi, int argc, char **argv)
-{
- int res;
- if ((argc < 3) || (argc > 4))
- return RESULT_SHOWUSAGE;
- if (argc == 4)
- res = ast_db_deltree(argv[2], argv[3]);
- else
- res = ast_db_deltree(argv[2], NULL);
-
- if (res)
- fdprintf(agi->fd, "200 result=0\n");
- else
- fdprintf(agi->fd, "200 result=1\n");
- return RESULT_SUCCESS;
-}
-
-static char debug_usage[] =
-"Usage: agi debug\n"
-" Enables dumping of AGI transactions for debugging purposes\n";
-
-static char no_debug_usage[] =
-"Usage: agi no debug\n"
-" Disables dumping of AGI transactions for debugging purposes\n";
-
-static int agi_do_debug(int fd, int argc, char *argv[])
-{
- if (argc != 2)
- return RESULT_SHOWUSAGE;
- agidebug = 1;
- ast_cli(fd, "AGI Debugging Enabled\n");
- return RESULT_SUCCESS;
-}
-
-static int agi_no_debug(int fd, int argc, char *argv[])
-{
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- agidebug = 0;
- ast_cli(fd, "AGI Debugging Disabled\n");
- return RESULT_SUCCESS;
-}
-
-static struct ast_cli_entry cli_debug =
- { { "agi", "debug", NULL }, agi_do_debug, "Enable AGI debugging", debug_usage };
-
-static struct ast_cli_entry cli_no_debug =
- { { "agi", "no", "debug", NULL }, agi_no_debug, "Disable AGI debugging", no_debug_usage };
-
-static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, char *argv[])
-{
- fdprintf(agi->fd, "200 result=0\n");
- return RESULT_SUCCESS;
-}
-
-static int handle_setmusic(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
-{
- if (!strncasecmp(argv[2],"on",2)) {
- if (argc > 3)
- ast_moh_start(chan, argv[3]);
- else
- ast_moh_start(chan, NULL);
- }
- if (!strncasecmp(argv[2],"off",3)) {
- ast_moh_stop(chan);
- }
- fdprintf(agi->fd, "200 result=0\n");
- return RESULT_SUCCESS;
-}
-
-static char usage_setmusic[] =
-" Usage: SET MUSIC ON <on|off> <class>\n"
-" Enables/Disables the music on hold generator. If <class> is\n"
-" not specified, then the default music on hold class will be used.\n"
-" Always returns 0.\n";
-
-static char usage_dbput[] =
-" Usage: DATABASE PUT <family> <key> <value>\n"
-" Adds or updates an entry in the Asterisk database for a\n"
-" given family, key, and value.\n"
-" Returns 1 if successful, 0 otherwise.\n";
-
-static char usage_dbget[] =
-" Usage: DATABASE GET <family> <key>\n"
-" Retrieves an entry in the Asterisk database for a\n"
-" given family and key.\n"
-" Returns 0 if <key> is not set. Returns 1 if <key>\n"
-" is set and returns the variable in parentheses.\n"
-" Example return code: 200 result=1 (testvariable)\n";
-
-static char usage_dbdel[] =
-" Usage: DATABASE DEL <family> <key>\n"
-" Deletes an entry in the Asterisk database for a\n"
-" given family and key.\n"
-" Returns 1 if successful, 0 otherwise.\n";
-
-static char usage_dbdeltree[] =
-" Usage: DATABASE DELTREE <family> [keytree]\n"
-" Deletes a family or specific keytree within a family\n"
-" in the Asterisk database.\n"
-" Returns 1 if successful, 0 otherwise.\n";
-
-static char usage_verbose[] =
-" Usage: VERBOSE <message> <level>\n"
-" Sends <message> to the console via verbose message system.\n"
-" <level> is the the verbose level (1-4)\n"
-" Always returns 1.\n";
-
-static char usage_getvariable[] =
-" Usage: GET VARIABLE <variablename>\n"
-" Returns 0 if <variablename> is not set. Returns 1 if <variablename>\n"
-" is set and returns the variable in parentheses.\n"
-" example return code: 200 result=1 (testvariable)\n";
-
-static char usage_getvariablefull[] =
-" Usage: GET FULL VARIABLE <variablename> [<channel name>]\n"
-" Returns 0 if <variablename> is not set or channel does not exist. Returns 1\n"
-"if <variablename> is set and returns the variable in parenthesis. Understands\n"
-"complex variable names and builtin variables, unlike GET VARIABLE.\n"
-" example return code: 200 result=1 (testvariable)\n";
-
-static char usage_setvariable[] =
-" Usage: SET VARIABLE <variablename> <value>\n";
-
-static char usage_channelstatus[] =
-" Usage: CHANNEL STATUS [<channelname>]\n"
-" Returns the status of the specified channel.\n"
-" If no channel name is given the returns the status of the\n"
-" current channel. Return values:\n"
-" 0 Channel is down and available\n"
-" 1 Channel is down, but reserved\n"
-" 2 Channel is off hook\n"
-" 3 Digits (or equivalent) have been dialed\n"
-" 4 Line is ringing\n"
-" 5 Remote end is ringing\n"
-" 6 Line is up\n"
-" 7 Line is busy\n";
-
-static char usage_setcallerid[] =
-" Usage: SET CALLERID <number>\n"
-" Changes the callerid of the current channel.\n";
-
-static char usage_exec[] =
-" Usage: EXEC <application> <options>\n"
-" Executes <application> with given <options>.\n"
-" Returns whatever the application returns, or -2 on failure to find application\n";
-
-static char usage_hangup[] =
-" Usage: HANGUP [<channelname>]\n"
-" Hangs up the specified channel.\n"
-" If no channel name is given, hangs up the current channel\n";
-
-static char usage_answer[] =
-" Usage: ANSWER\n"
-" Answers channel if not already in answer state. Returns -1 on\n"
-" channel failure, or 0 if successful.\n";
-
-static char usage_waitfordigit[] =
-" Usage: WAIT FOR DIGIT <timeout>\n"
-" Waits up to 'timeout' milliseconds for channel to receive a DTMF digit.\n"
-" Returns -1 on channel failure, 0 if no digit is received in the timeout, or\n"
-" the numerical value of the ascii of the digit if one is received. Use -1\n"
-" for the timeout value if you desire the call to block indefinitely.\n";
-
-static char usage_sendtext[] =
-" Usage: SEND TEXT \"<text to send>\"\n"
-" Sends the given text on a channel. Most channels do not support the\n"
-" transmission of text. Returns 0 if text is sent, or if the channel does not\n"
-" support text transmission. Returns -1 only on error/hangup. Text\n"
-" consisting of greater than one word should be placed in quotes since the\n"
-" command only accepts a single argument.\n";
-
-static char usage_recvchar[] =
-" Usage: RECEIVE CHAR <timeout>\n"
-" Receives a character of text on a channel. Specify timeout to be the\n"
-" maximum time to wait for input in milliseconds, or 0 for infinite. Most channels\n"
-" do not support the reception of text. Returns the decimal value of the character\n"
-" if one is received, or 0 if the channel does not support text reception. Returns\n"
-" -1 only on error/hangup.\n";
-
-static char usage_recvtext[] =
-" Usage: RECEIVE TEXT <timeout>\n"
-" Receives a string of text on a channel. Specify timeout to be the\n"
-" maximum time to wait for input in milliseconds, or 0 for infinite. Most channels\n"
-" do not support the reception of text. Returns -1 for failure or 1 for success, and the string in parentheses.\n";
-
-static char usage_tddmode[] =
-" Usage: TDD MODE <on|off>\n"
-" Enable/Disable TDD transmission/reception on a channel. Returns 1 if\n"
-" successful, or 0 if channel is not TDD-capable.\n";
-
-static char usage_sendimage[] =
-" Usage: SEND IMAGE <image>\n"
-" Sends the given image on a channel. Most channels do not support the\n"
-" transmission of images. Returns 0 if image is sent, or if the channel does not\n"
-" support image transmission. Returns -1 only on error/hangup. Image names\n"
-" should not include extensions.\n";
-
-static char usage_streamfile[] =
-" Usage: STREAM FILE <filename> <escape digits> [sample offset]\n"
-" Send the given file, allowing playback to be interrupted by the given\n"
-" digits, if any. Use double quotes for the digits if you wish none to be\n"
-" permitted. If sample offset is provided then the audio will seek to sample\n"
-" offset before play starts. Returns 0 if playback completes without a digit\n"
-" being pressed, or the ASCII numerical value of the digit if one was pressed,\n"
-" or -1 on error or if the channel was disconnected. Remember, the file\n"
-" extension must not be included in the filename.\n";
-
-static char usage_controlstreamfile[] =
-" Usage: CONTROL STREAM FILE <filename> <escape digits> [skipms] [ffchar] [rewchr] [pausechr]\n"
-" Send the given file, allowing playback to be controled by the given\n"
-" digits, if any. Use double quotes for the digits if you wish none to be\n"
-" permitted. Returns 0 if playback completes without a digit\n"
-" being pressed, or the ASCII numerical value of the digit if one was pressed,\n"
-" or -1 on error or if the channel was disconnected. Remember, the file\n"
-" extension must not be included in the filename.\n\n"
-" Note: ffchar and rewchar default to * and # respectively.\n";
-
-static char usage_getoption[] =
-" Usage: GET OPTION <filename> <escape_digits> [timeout]\n"
-" Behaves similar to STREAM FILE but used with a timeout option.\n";
-
-static char usage_saynumber[] =
-" Usage: SAY NUMBER <number> <escape digits>\n"
-" Say a given number, returning early if any of the given DTMF digits\n"
-" are received on the channel. Returns 0 if playback completes without a digit\n"
-" being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
-" -1 on error/hangup.\n";
-
-static char usage_saydigits[] =
-" Usage: SAY DIGITS <number> <escape digits>\n"
-" Say a given digit string, returning early if any of the given DTMF digits\n"
-" are received on the channel. Returns 0 if playback completes without a digit\n"
-" being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
-" -1 on error/hangup.\n";
-
-static char usage_sayalpha[] =
-" Usage: SAY ALPHA <number> <escape digits>\n"
-" Say a given character string, returning early if any of the given DTMF digits\n"
-" are received on the channel. Returns 0 if playback completes without a digit\n"
-" being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
-" -1 on error/hangup.\n";
-
-static char usage_saydate[] =
-" Usage: SAY DATE <date> <escape digits>\n"
-" Say a given date, returning early if any of the given DTMF digits are\n"
-" received on the channel. <date> is number of seconds elapsed since 00:00:00\n"
-" on January 1, 1970, Coordinated Universal Time (UTC). Returns 0 if playback\n"
-" completes without a digit being pressed, or the ASCII numerical value of the\n"
-" digit if one was pressed or -1 on error/hangup.\n";
-
-static char usage_saytime[] =
-" Usage: SAY TIME <time> <escape digits>\n"
-" Say a given time, returning early if any of the given DTMF digits are\n"
-" received on the channel. <time> is number of seconds elapsed since 00:00:00\n"
-" on January 1, 1970, Coordinated Universal Time (UTC). Returns 0 if playback\n"
-" completes without a digit being pressed, or the ASCII numerical value of the\n"
-" digit if one was pressed or -1 on error/hangup.\n";
-
-static char usage_saydatetime[] =
-" Usage: SAY DATETIME <time> <escape digits> [format] [timezone]\n"
-" Say a given time, returning early if any of the given DTMF digits are\n"
-" received on the channel. <time> is number of seconds elapsed since 00:00:00\n"
-" on January 1, 1970, Coordinated Universal Time (UTC). [format] is the format\n"
-" the time should be said in. See voicemail.conf (defaults to \"ABdY\n"
-" 'digits/at' IMp\"). Acceptable values for [timezone] can be found in\n"
-" /usr/share/zoneinfo. Defaults to machine default. Returns 0 if playback\n"
-" completes without a digit being pressed, or the ASCII numerical value of the\n"
-" digit if one was pressed or -1 on error/hangup.\n";
-
-static char usage_sayphonetic[] =
-" Usage: SAY PHONETIC <string> <escape digits>\n"
-" Say a given character string with phonetics, returning early if any of the\n"
-" given DTMF digits are received on the channel. Returns 0 if playback\n"
-" completes without a digit pressed, the ASCII numerical value of the digit\n"
-" if one was pressed, or -1 on error/hangup.\n";
-
-static char usage_getdata[] =
-" Usage: GET DATA <file to be streamed> [timeout] [max digits]\n"
-" Stream the given file, and recieve DTMF data. Returns the digits received\n"
-"from the channel at the other end.\n";
-
-static char usage_setcontext[] =
-" Usage: SET CONTEXT <desired context>\n"
-" Sets the context for continuation upon exiting the application.\n";
-
-static char usage_setextension[] =
-" Usage: SET EXTENSION <new extension>\n"
-" Changes the extension for continuation upon exiting the application.\n";
-
-static char usage_setpriority[] =
-" Usage: SET PRIORITY <priority>\n"
-" Changes the priority for continuation upon exiting the application.\n"
-" The priority must be a valid priority or label.\n";
-
-static char usage_recordfile[] =
-" Usage: RECORD FILE <filename> <format> <escape digits> <timeout> \\\n"
-" [offset samples] [BEEP] [s=silence]\n"
-" Record to a file until a given dtmf digit in the sequence is received\n"
-" Returns -1 on hangup or error. The format will specify what kind of file\n"
-" will be recorded. The timeout is the maximum record time in milliseconds, or\n"
-" -1 for no timeout. \"Offset samples\" is optional, and, if provided, will seek\n"
-" to the offset without exceeding the end of the file. \"silence\" is the number\n"
-" of seconds of silence allowed before the function returns despite the\n"
-" lack of dtmf digits or reaching timeout. Silence value must be\n"
-" preceeded by \"s=\" and is also optional.\n";
-
-static char usage_autohangup[] =
-" Usage: SET AUTOHANGUP <time>\n"
-" Cause the channel to automatically hangup at <time> seconds in the\n"
-" future. Of course it can be hungup before then as well. Setting to 0 will\n"
-" cause the autohangup feature to be disabled on this channel.\n";
-
-static char usage_noop[] =
-" Usage: NoOp\n"
-" Does nothing.\n";
-
-static agi_command commands[MAX_COMMANDS] = {
- { { "answer", NULL }, handle_answer, "Answer channel", usage_answer },
- { { "channel", "status", NULL }, handle_channelstatus, "Returns status of the connected channel", usage_channelstatus },
- { { "database", "del", NULL }, handle_dbdel, "Removes database key/value", usage_dbdel },
- { { "database", "deltree", NULL }, handle_dbdeltree, "Removes database keytree/value", usage_dbdeltree },
- { { "database", "get", NULL }, handle_dbget, "Gets database value", usage_dbget },
- { { "database", "put", NULL }, handle_dbput, "Adds/updates database value", usage_dbput },
- { { "exec", NULL }, handle_exec, "Executes a given Application", usage_exec },
- { { "get", "data", NULL }, handle_getdata, "Prompts for DTMF on a channel", usage_getdata },
- { { "get", "full", "variable", NULL }, handle_getvariablefull, "Evaluates a channel expression", usage_getvariablefull },
- { { "get", "option", NULL }, handle_getoption, "Stream file, prompt for DTMF, with timeout", usage_getoption },
- { { "get", "variable", NULL }, handle_getvariable, "Gets a channel variable", usage_getvariable },
- { { "hangup", NULL }, handle_hangup, "Hangup the current channel", usage_hangup },
- { { "noop", NULL }, handle_noop, "Does nothing", usage_noop },
- { { "receive", "char", NULL }, handle_recvchar, "Receives one character from channels supporting it", usage_recvchar },
- { { "receive", "text", NULL }, handle_recvtext, "Receives text from channels supporting it", usage_recvtext },
- { { "record", "file", NULL }, handle_recordfile, "Records to a given file", usage_recordfile },
- { { "say", "alpha", NULL }, handle_sayalpha, "Says a given character string", usage_sayalpha },
- { { "say", "digits", NULL }, handle_saydigits, "Says a given digit string", usage_saydigits },
- { { "say", "number", NULL }, handle_saynumber, "Says a given number", usage_saynumber },
- { { "say", "phonetic", NULL }, handle_sayphonetic, "Says a given character string with phonetics", usage_sayphonetic },
- { { "say", "date", NULL }, handle_saydate, "Says a given date", usage_saydate },
- { { "say", "time", NULL }, handle_saytime, "Says a given time", usage_saytime },
- { { "say", "datetime", NULL }, handle_saydatetime, "Says a given time as specfied by the format given", usage_saydatetime },
- { { "send", "image", NULL }, handle_sendimage, "Sends images to channels supporting it", usage_sendimage },
- { { "send", "text", NULL }, handle_sendtext, "Sends text to channels supporting it", usage_sendtext },
- { { "set", "autohangup", NULL }, handle_autohangup, "Autohangup channel in some time", usage_autohangup },
- { { "set", "callerid", NULL }, handle_setcallerid, "Sets callerid for the current channel", usage_setcallerid },
- { { "set", "context", NULL }, handle_setcontext, "Sets channel context", usage_setcontext },
- { { "set", "extension", NULL }, handle_setextension, "Changes channel extension", usage_setextension },
- { { "set", "music", NULL }, handle_setmusic, "Enable/Disable Music on hold generator", usage_setmusic },
- { { "set", "priority", NULL }, handle_setpriority, "Set channel dialplan priority", usage_setpriority },
- { { "set", "variable", NULL }, handle_setvariable, "Sets a channel variable", usage_setvariable },
- { { "stream", "file", NULL }, handle_streamfile, "Sends audio file on channel", usage_streamfile },
- { { "control", "stream", "file", NULL }, handle_controlstreamfile, "Sends audio file on channel and allows the listner to control the stream", usage_controlstreamfile },
- { { "tdd", "mode", NULL }, handle_tddmode, "Toggles TDD mode (for the deaf)", usage_tddmode },
- { { "verbose", NULL }, handle_verbose, "Logs a message to the asterisk verbose log", usage_verbose },
- { { "wait", "for", "digit", NULL }, handle_waitfordigit, "Waits for a digit to be pressed", usage_waitfordigit },
-};
-
-static void join(char *s, size_t len, char *w[])
-{
- int x;
-
- /* Join words into a string */
- if (!s) {
- return;
- }
- s[0] = '\0';
- for (x=0; w[x]; x++) {
- if (x)
- strncat(s, " ", len - strlen(s) - 1);
- strncat(s, w[x], len - strlen(s) - 1);
- }
-}
-
-static int help_workhorse(int fd, char *match[])
-{
- char fullcmd[80];
- char matchstr[80];
- int x;
- struct agi_command *e;
- if (match)
- join(matchstr, sizeof(matchstr), match);
- for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) {
- if (!commands[x].cmda[0]) break;
- e = &commands[x];
- if (e)
- join(fullcmd, sizeof(fullcmd), e->cmda);
- /* Hide commands that start with '_' */
- if (fullcmd[0] == '_')
- continue;
- if (match) {
- if (strncasecmp(matchstr, fullcmd, strlen(matchstr))) {
- continue;
- }
- }
- ast_cli(fd, "%20.20s %s\n", fullcmd, e->summary);
- }
- return 0;
-}
-
-int agi_register(agi_command *agi)
-{
- int x;
- for (x=0; x<MAX_COMMANDS - 1; x++) {
- if (commands[x].cmda[0] == agi->cmda[0]) {
- ast_log(LOG_WARNING, "Command already registered!\n");
- return -1;
- }
- }
- for (x=0; x<MAX_COMMANDS - 1; x++) {
- if (!commands[x].cmda[0]) {
- commands[x] = *agi;
- return 0;
- }
- }
- ast_log(LOG_WARNING, "No more room for new commands!\n");
- return -1;
-}
-
-void agi_unregister(agi_command *agi)
-{
- int x;
- for (x=0; x<MAX_COMMANDS - 1; x++) {
- if (commands[x].cmda[0] == agi->cmda[0]) {
- memset(&commands[x], 0, sizeof(agi_command));
- }
- }
-}
-
-static agi_command *find_command(char *cmds[], int exact)
-{
- int x;
- int y;
- int match;
-
- for (x=0; x < sizeof(commands) / sizeof(commands[0]); x++) {
- if (!commands[x].cmda[0])
- break;
- /* start optimistic */
- match = 1;
- for (y=0; match && cmds[y]; y++) {
- /* If there are no more words in the command (and we're looking for
- an exact match) or there is a difference between the two words,
- then this is not a match */
- if (!commands[x].cmda[y] && !exact)
- break;
- /* don't segfault if the next part of a command doesn't exist */
- if (!commands[x].cmda[y])
- return NULL;
- if (strcasecmp(commands[x].cmda[y], cmds[y]))
- match = 0;
- }
- /* If more words are needed to complete the command then this is not
- a candidate (unless we're looking for a really inexact answer */
- if ((exact > -1) && commands[x].cmda[y])
- match = 0;
- if (match)
- return &commands[x];
- }
- return NULL;
-}
-
-
-static int parse_args(char *s, int *max, char *argv[])
-{
- int x=0;
- int quoted=0;
- int escaped=0;
- int whitespace=1;
- char *cur;
-
- cur = s;
- while(*s) {
- switch(*s) {
- case '"':
- /* If it's escaped, put a literal quote */
- if (escaped)
- goto normal;
- else
- quoted = !quoted;
- if (quoted && whitespace) {
- /* If we're starting a quote, coming off white space start a new word, too */
- argv[x++] = cur;
- whitespace=0;
- }
- escaped = 0;
- break;
- case ' ':
- case '\t':
- if (!quoted && !escaped) {
- /* If we're not quoted, mark this as whitespace, and
- end the previous argument */
- whitespace = 1;
- *(cur++) = '\0';
- } else
- /* Otherwise, just treat it as anything else */
- goto normal;
- break;
- case '\\':
- /* If we're escaped, print a literal, otherwise enable escaping */
- if (escaped) {
- goto normal;
- } else {
- escaped=1;
- }
- break;
- default:
-normal:
- if (whitespace) {
- if (x >= MAX_ARGS -1) {
- ast_log(LOG_WARNING, "Too many arguments, truncating\n");
- break;
- }
- /* Coming off of whitespace, start the next argument */
- argv[x++] = cur;
- whitespace=0;
- }
- *(cur++) = *s;
- escaped=0;
- }
- s++;
- }
- /* Null terminate */
- *(cur++) = '\0';
- argv[x] = NULL;
- *max = x;
- return 0;
-}
-
-static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf)
-{
- char *argv[MAX_ARGS];
- int argc = 0;
- int res;
- agi_command *c;
- argc = MAX_ARGS;
-
- parse_args(buf, &argc, argv);
-#if 0
- { int x;
- for (x=0; x<argc; x++)
- fprintf(stderr, "Got Arg%d: %s\n", x, argv[x]); }
-#endif
- c = find_command(argv, 0);
- if (c) {
- res = c->handler(chan, agi, argc, argv);
- switch(res) {
- case RESULT_SHOWUSAGE:
- fdprintf(agi->fd, "520-Invalid command syntax. Proper usage follows:\n");
- fdprintf(agi->fd, c->usage);
- fdprintf(agi->fd, "520 End of proper usage.\n");
- break;
- case AST_PBX_KEEPALIVE:
- /* We've been asked to keep alive, so do so */
- return AST_PBX_KEEPALIVE;
- break;
- case RESULT_FAILURE:
- /* They've already given the failure. We've been hung up on so handle this
- appropriately */
- return -1;
- }
- } else {
- fdprintf(agi->fd, "510 Invalid or unknown command\n");
- }
- return 0;
-}
-#define RETRY 3
-static int run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int dead)
-{
- struct ast_channel *c;
- int outfd;
- int ms;
- int returnstatus = 0;
- struct ast_frame *f;
- char buf[2048];
- FILE *readf;
- /* how many times we'll retry if ast_waitfor_nandfs will return without either
- channel or file descriptor in case select is interrupted by a system call (EINTR) */
- int retry = RETRY;
-
- if (!(readf = fdopen(agi->ctrl, "r"))) {
- ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
- if (pid > -1)
- kill(pid, SIGHUP);
- close(agi->ctrl);
- return -1;
- }
- setlinebuf(readf);
- setup_env(chan, request, agi->fd, (agi->audio > -1));
- for (;;) {
- ms = -1;
- c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
- if (c) {
- retry = RETRY;
- /* Idle the channel until we get a command */
- f = ast_read(c);
- if (!f) {
- ast_log(LOG_DEBUG, "%s hungup\n", chan->name);
- returnstatus = -1;
- break;
- } else {
- /* If it's voice, write it to the audio pipe */
- if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
- /* Write, ignoring errors */
- write(agi->audio, f->data, f->datalen);
- }
- ast_frfree(f);
- }
- } else if (outfd > -1) {
- retry = RETRY;
- if (!fgets(buf, sizeof(buf), readf)) {
- /* Program terminated */
- if (returnstatus)
- returnstatus = -1;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "AGI Script %s completed, returning %d\n", request, returnstatus);
- /* No need to kill the pid anymore, since they closed us */
- pid = -1;
- break;
- }
- /* get rid of trailing newline, if any */
- if (*buf && buf[strlen(buf) - 1] == '\n')
- buf[strlen(buf) - 1] = 0;
- if (agidebug)
- ast_verbose("AGI Rx << %s\n", buf);
- returnstatus |= agi_handle_command(chan, agi, buf);
- /* If the handle_command returns -1, we need to stop */
- if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) {
- break;
- }
- } else {
- if (--retry <= 0) {
- ast_log(LOG_WARNING, "No channel, no fd?\n");
- returnstatus = -1;
- break;
- }
- }
- }
- /* Notify process */
- if (pid > -1) {
- if (kill(pid, SIGHUP))
- ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno));
- }
- fclose(readf);
- return returnstatus;
-}
-
-static int handle_showagi(int fd, int argc, char *argv[]) {
- struct agi_command *e;
- char fullcmd[80];
- if ((argc < 2))
- return RESULT_SHOWUSAGE;
- if (argc > 2) {
- e = find_command(argv + 2, 1);
- if (e)
- ast_cli(fd, e->usage);
- else {
- if (find_command(argv + 2, -1)) {
- return help_workhorse(fd, argv + 1);
- } else {
- join(fullcmd, sizeof(fullcmd), argv+1);
- ast_cli(fd, "No such command '%s'.\n", fullcmd);
- }
- }
- } else {
- return help_workhorse(fd, NULL);
- }
- return RESULT_SUCCESS;
-}
-
-static int handle_dumpagihtml(int fd, int argc, char *argv[]) {
- struct agi_command *e;
- char fullcmd[80];
- char *tempstr;
- int x;
- FILE *htmlfile;
-
- if ((argc < 3))
- return RESULT_SHOWUSAGE;
-
- if (!(htmlfile = fopen(argv[2], "wt"))) {
- ast_cli(fd, "Could not create file '%s'\n", argv[2]);
- return RESULT_SHOWUSAGE;
- }
-
- fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n");
- fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n");
-
-
- fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n");
-
- for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) {
- char *stringp=NULL;
- if (!commands[x].cmda[0]) break;
- e = &commands[x];
- if (e)
- join(fullcmd, sizeof(fullcmd), e->cmda);
- /* Hide commands that start with '_' */
- if (fullcmd[0] == '_')
- continue;
-
- fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n");
- fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TD></TR>\n", fullcmd,e->summary);
-
-
- stringp=e->usage;
- tempstr = strsep(&stringp, "\n");
-
- fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">%s</TD></TR>\n", tempstr);
-
- fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n");
- while ((tempstr = strsep(&stringp, "\n")) != NULL) {
- fprintf(htmlfile, "%s<BR>\n",tempstr);
-
- }
- fprintf(htmlfile, "</TD></TR>\n");
- fprintf(htmlfile, "</TABLE></TD></TR>\n\n");
-
- }
-
- fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n");
- fclose(htmlfile);
- ast_cli(fd, "AGI HTML Commands Dumped to: %s\n", argv[2]);
- return RESULT_SUCCESS;
-}
-
-static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int dead)
-{
- int res=0;
- struct localuser *u;
- char *argv[MAX_ARGS];
- char buf[2048]="";
- char *tmp = (char *)buf;
- int argc = 0;
- int fds[2];
- int efd = -1;
- int pid;
- char *stringp;
- AGI agi;
-
- if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "AGI requires an argument (script)\n");
- return -1;
- }
- ast_copy_string(buf, data, sizeof(buf));
-
- memset(&agi, 0, sizeof(agi));
- while ((stringp = strsep(&tmp, "|")) && argc < MAX_ARGS - 1)
- argv[argc++] = stringp;
- argv[argc] = NULL;
-
- LOCAL_USER_ADD(u);
-#if 0
- /* Answer if need be */
- if (chan->_state != AST_STATE_UP) {
- if (ast_answer(chan)) {
- LOCAL_USER_REMOVE(u);
- return -1;
- }
- }
-#endif
- res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
- if (!res) {
- agi.fd = fds[1];
- agi.ctrl = fds[0];
- agi.audio = efd;
- res = run_agi(chan, argv[0], &agi, pid, dead);
- close(fds[1]);
- if (efd > -1)
- close(efd);
- }
- LOCAL_USER_REMOVE(u);
- return res;
-}
-
-static int agi_exec(struct ast_channel *chan, void *data)
-{
- if (chan->_softhangup)
- ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
- return agi_exec_full(chan, data, 0, 0);
-}
-
-static int eagi_exec(struct ast_channel *chan, void *data)
-{
- int readformat;
- int res;
-
- if (chan->_softhangup)
- ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
- readformat = chan->readformat;
- if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
- ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
- return -1;
- }
- res = agi_exec_full(chan, data, 1, 0);
- if (!res) {
- if (ast_set_read_format(chan, readformat)) {
- ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
- }
- }
- return res;
-}
-
-static int deadagi_exec(struct ast_channel *chan, void *data)
-{
- return agi_exec_full(chan, data, 0, 1);
-}
-
-static char showagi_help[] =
-"Usage: show agi [topic]\n"
-" When called with a topic as an argument, displays usage\n"
-" information on the given command. If called without a\n"
-" topic, it provides a list of AGI commands.\n";
-
-
-static char dumpagihtml_help[] =
-"Usage: dump agihtml <filename>\n"
-" Dumps the agi command list in html format to given filename\n";
-
-static struct ast_cli_entry showagi =
-{ { "show", "agi", NULL }, handle_showagi, "Show AGI commands or specific help", showagi_help };
-
-static struct ast_cli_entry dumpagihtml =
-{ { "dump", "agihtml", NULL }, handle_dumpagihtml, "Dumps a list of agi command in html format", dumpagihtml_help };
-
-int unload_module(void)
-{
- STANDARD_HANGUP_LOCALUSERS;
- ast_cli_unregister(&showagi);
- ast_cli_unregister(&dumpagihtml);
- ast_cli_unregister(&cli_debug);
- ast_cli_unregister(&cli_no_debug);
- ast_unregister_application(eapp);
- ast_unregister_application(deadapp);
- return ast_unregister_application(app);
-}
-
-int load_module(void)
-{
- ast_cli_register(&showagi);
- ast_cli_register(&dumpagihtml);
- ast_cli_register(&cli_debug);
- ast_cli_register(&cli_no_debug);
- ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
- ast_register_application(eapp, eagi_exec, esynopsis, descrip);
- return ast_register_application(app, agi_exec, synopsis, descrip);
-}
-
-char *description(void)
-{
- return tdesc;
-}
-
-int usecount(void)
-{
- int res;
- STANDARD_USECOUNT(res);
- return res;
-}
-
-char *key()
-{
- return ASTERISK_GPL_KEY;
-}
-
diff --git a/1.2-netsec/res/res_config_odbc.c b/1.2-netsec/res/res_config_odbc.c
deleted file mode 100644
index e10f4ff7f..000000000
--- a/1.2-netsec/res/res_config_odbc.c
+++ /dev/null
@@ -1,540 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * Copyright (C) 2004 - 2005 Anthony Minessale II <anthmct@yahoo.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief odbc+odbc plugin for portable configuration engine
- *
- * http://www.unixodbc.org
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/file.h"
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/pbx.h"
-#include "asterisk/config.h"
-#include "asterisk/module.h"
-#include "asterisk/lock.h"
-#include "asterisk/options.h"
-#include "asterisk/res_odbc.h"
-#include "asterisk/utils.h"
-
-static char *tdesc = "ODBC Configuration";
-STANDARD_LOCAL_USER;
-
-LOCAL_USER_DECL;
-
-static struct ast_variable *realtime_odbc(const char *database, const char *table, va_list ap)
-{
- odbc_obj *obj;
- SQLHSTMT stmt;
- char sql[1024];
- char coltitle[256];
- char rowdata[2048];
- char *op;
- const char *newparam, *newval;
- char *stringp;
- char *chunk;
- SQLSMALLINT collen;
- int res;
- int x;
- struct ast_variable *var=NULL, *prev=NULL;
- SQLULEN colsize;
- SQLSMALLINT colcount=0;
- SQLSMALLINT datatype;
- SQLSMALLINT decimaldigits;
- SQLSMALLINT nullable;
- SQLINTEGER indicator;
- va_list aq;
-
- va_copy(aq, ap);
-
-
- if (!table)
- return NULL;
-
- obj = fetch_odbc_obj(database, 0);
- if (!obj)
- return NULL;
-
- res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
- return NULL;
- }
-
- newparam = va_arg(aq, const char *);
- if (!newparam) {
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return NULL;
- }
- newval = va_arg(aq, const char *);
- if (!strchr(newparam, ' ')) op = " ="; else op = "";
- snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?", table, newparam, op);
- while((newparam = va_arg(aq, const char *))) {
- if (!strchr(newparam, ' ')) op = " ="; else op = "";
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?", newparam, op);
- newval = va_arg(aq, const char *);
- }
- va_end(aq);
- res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return NULL;
- }
-
- /* Now bind the parameters */
- x = 1;
-
- while((newparam = va_arg(ap, const char *))) {
- newval = va_arg(ap, const char *);
- SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
- }
-
- res = odbc_smart_execute(obj, stmt);
-
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return NULL;
- }
-
- res = SQLNumResultCols(stmt, &colcount);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return NULL;
- }
-
- res = SQLFetch(stmt);
- if (res == SQL_NO_DATA) {
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return NULL;
- }
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return NULL;
- }
- for (x=0;x<colcount;x++) {
- rowdata[0] = '\0';
- collen = sizeof(coltitle);
- res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
- &datatype, &colsize, &decimaldigits, &nullable);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
- if (var)
- ast_variables_destroy(var);
- return NULL;
- }
-
- indicator = 0;
- res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator);
- if (indicator == SQL_NULL_DATA)
- continue;
-
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
- if (var)
- ast_variables_destroy(var);
- return NULL;
- }
- stringp = rowdata;
- while(stringp) {
- chunk = strsep(&stringp, ";");
- if (!ast_strlen_zero(ast_strip(chunk))) {
- if (prev) {
- prev->next = ast_variable_new(coltitle, chunk);
- if (prev->next)
- prev = prev->next;
- } else
- prev = var = ast_variable_new(coltitle, chunk);
-
- }
- }
- }
-
-
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return var;
-}
-
-static struct ast_config *realtime_multi_odbc(const char *database, const char *table, va_list ap)
-{
- odbc_obj *obj;
- SQLHSTMT stmt;
- char sql[1024];
- char coltitle[256];
- char rowdata[2048];
- const char *initfield=NULL;
- char *op;
- const char *newparam, *newval;
- char *stringp;
- char *chunk;
- SQLSMALLINT collen;
- int res;
- int x;
- struct ast_variable *var=NULL;
- struct ast_config *cfg=NULL;
- struct ast_category *cat=NULL;
- struct ast_realloca ra;
- SQLULEN colsize;
- SQLSMALLINT colcount=0;
- SQLSMALLINT datatype;
- SQLSMALLINT decimaldigits;
- SQLSMALLINT nullable;
- SQLINTEGER indicator;
-
- va_list aq;
- va_copy(aq, ap);
-
-
- if (!table)
- return NULL;
- memset(&ra, 0, sizeof(ra));
-
- obj = fetch_odbc_obj(database, 0);
- if (!obj)
- return NULL;
-
- res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
- return NULL;
- }
-
- newparam = va_arg(aq, const char *);
- if (!newparam) {
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return NULL;
- }
- initfield = ast_strdupa(newparam);
- if (initfield && (op = strchr(initfield, ' ')))
- *op = '\0';
- newval = va_arg(aq, const char *);
- if (!strchr(newparam, ' ')) op = " ="; else op = "";
- snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?", table, newparam, op);
- while((newparam = va_arg(aq, const char *))) {
- if (!strchr(newparam, ' ')) op = " ="; else op = "";
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?", newparam, op);
- newval = va_arg(aq, const char *);
- }
- if (initfield)
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
- va_end(aq);
- res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return NULL;
- }
-
- /* Now bind the parameters */
- x = 1;
-
- while((newparam = va_arg(ap, const char *))) {
- newval = va_arg(ap, const char *);
- SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
- }
-
- res = odbc_smart_execute(obj, stmt);
-
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return NULL;
- }
-
- res = SQLNumResultCols(stmt, &colcount);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return NULL;
- }
-
- cfg = ast_config_new();
- if (!cfg) {
- ast_log(LOG_WARNING, "Out of memory!\n");
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return NULL;
- }
-
- while ((res=SQLFetch(stmt)) != SQL_NO_DATA) {
- var = NULL;
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
- continue;
- }
- cat = ast_category_new("");
- if (!cat) {
- ast_log(LOG_WARNING, "Out of memory!\n");
- continue;
- }
- for (x=0;x<colcount;x++) {
- rowdata[0] = '\0';
- collen = sizeof(coltitle);
- res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
- &datatype, &colsize, &decimaldigits, &nullable);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
- ast_category_destroy(cat);
- continue;
- }
-
- indicator = 0;
- res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator);
- if (indicator == SQL_NULL_DATA)
- continue;
-
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
- ast_category_destroy(cat);
- continue;
- }
- stringp = rowdata;
- while(stringp) {
- chunk = strsep(&stringp, ";");
- if (!ast_strlen_zero(ast_strip(chunk))) {
- if (initfield && !strcmp(initfield, coltitle))
- ast_category_rename(cat, chunk);
- var = ast_variable_new(coltitle, chunk);
- ast_variable_append(cat, var);
- }
- }
- }
- ast_category_append(cfg, cat);
- }
-
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return cfg;
-}
-
-static int update_odbc(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
-{
- odbc_obj *obj;
- SQLHSTMT stmt;
- char sql[256];
- SQLLEN rowcount=0;
- const char *newparam, *newval;
- int res;
- int x;
- va_list aq;
-
- va_copy(aq, ap);
-
- if (!table)
- return -1;
-
- obj = fetch_odbc_obj (database, 0);
- if (!obj)
- return -1;
-
- res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
- return -1;
- }
-
- newparam = va_arg(aq, const char *);
- if (!newparam) {
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return -1;
- }
- newval = va_arg(aq, const char *);
- snprintf(sql, sizeof(sql), "UPDATE %s SET %s=?", table, newparam);
- while((newparam = va_arg(aq, const char *))) {
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s=?", newparam);
- newval = va_arg(aq, const char *);
- }
- va_end(aq);
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s=?", keyfield);
-
- res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return -1;
- }
-
- /* Now bind the parameters */
- x = 1;
-
- while((newparam = va_arg(ap, const char *))) {
- newval = va_arg(ap, const char *);
- SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
- }
-
- SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(lookup), 0, (void *)lookup, 0, NULL);
-
- res = odbc_smart_execute(obj, stmt);
-
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return -1;
- }
-
- res = SQLRowCount(stmt, &rowcount);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
-
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql);
- return -1;
- }
-
- if (rowcount >= 0)
- return (int)rowcount;
-
- return -1;
-}
-
-static struct ast_config *config_odbc(const char *database, const char *table, const char *file, struct ast_config *cfg)
-{
- struct ast_variable *new_v;
- struct ast_category *cur_cat;
- int res = 0;
- odbc_obj *obj;
- SQLINTEGER err=0, commented=0, cat_metric=0, var_metric=0, last_cat_metric=0;
- SQLBIGINT id;
- char sql[255] = "", filename[128], category[128], var_name[128], var_val[512];
- SQLSMALLINT rowcount=0;
- SQLHSTMT stmt;
- char last[128] = "";
-
- if (!file || !strcmp (file, "res_config_odbc.conf"))
- return NULL; /* cant configure myself with myself ! */
-
- obj = fetch_odbc_obj(database, 0);
- if (!obj)
- return NULL;
-
- res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt);
-
- SQLBindCol (stmt, 1, SQL_C_ULONG, &id, sizeof (id), &err);
- SQLBindCol (stmt, 2, SQL_C_ULONG, &cat_metric, sizeof (cat_metric), &err);
- SQLBindCol (stmt, 3, SQL_C_ULONG, &var_metric, sizeof (var_metric), &err);
- SQLBindCol (stmt, 4, SQL_C_ULONG, &commented, sizeof (commented), &err);
- SQLBindCol (stmt, 5, SQL_C_CHAR, &filename, sizeof (filename), &err);
- SQLBindCol (stmt, 6, SQL_C_CHAR, &category, sizeof (category), &err);
- SQLBindCol (stmt, 7, SQL_C_CHAR, &var_name, sizeof (var_name), &err);
- SQLBindCol (stmt, 8, SQL_C_CHAR, &var_val, sizeof (var_val), &err);
-
- snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE filename='%s' and commented=0 ORDER BY filename,cat_metric desc,var_metric asc,category,var_name,var_val,id", table, file);
-
- res = odbc_smart_direct_execute(obj, stmt, sql);
-
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log (LOG_WARNING, "SQL select error!\n[%s]\n\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return NULL;
- }
-
- res = SQLNumResultCols (stmt, &rowcount);
-
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log (LOG_WARNING, "SQL NumResultCols error!\n[%s]\n\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return NULL;
- }
-
- if (!rowcount) {
- ast_log (LOG_NOTICE, "found nothing\n");
- return cfg;
- }
-
- cur_cat = ast_config_get_current_category(cfg);
-
- while ((res = SQLFetch(stmt)) != SQL_NO_DATA) {
- if (!strcmp (var_name, "#include")) {
- if (!ast_config_internal_load(var_val, cfg)) {
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return NULL;
- }
- continue;
- }
- if (strcmp(last, category) || last_cat_metric != cat_metric) {
- cur_cat = ast_category_new(category);
- if (!cur_cat) {
- ast_log(LOG_WARNING, "Out of memory!\n");
- break;
- }
- strcpy(last, category);
- last_cat_metric = cat_metric;
- ast_category_append(cfg, cur_cat);
- }
-
- new_v = ast_variable_new(var_name, var_val);
- ast_variable_append(cur_cat, new_v);
- }
-
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- return cfg;
-}
-
-static struct ast_config_engine odbc_engine = {
- .name = "odbc",
- .load_func = config_odbc,
- .realtime_func = realtime_odbc,
- .realtime_multi_func = realtime_multi_odbc,
- .update_func = update_odbc
-};
-
-int unload_module (void)
-{
- ast_config_engine_deregister(&odbc_engine);
- if (option_verbose)
- ast_verbose("res_config_odbc unloaded.\n");
- STANDARD_HANGUP_LOCALUSERS;
- return 0;
-}
-
-int load_module (void)
-{
- ast_config_engine_register(&odbc_engine);
- if (option_verbose)
- ast_verbose("res_config_odbc loaded.\n");
- return 0;
-}
-
-char *description (void)
-{
- return tdesc;
-}
-
-int usecount (void)
-{
- /* never unload a config module */
- return 1;
-}
-
-char *key ()
-{
- return ASTERISK_GPL_KEY;
-}
diff --git a/1.2-netsec/res/res_crypto.c b/1.2-netsec/res/res_crypto.c
deleted file mode 100644
index 037ff8e79..000000000
--- a/1.2-netsec/res/res_crypto.c
+++ /dev/null
@@ -1,622 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Provide Cryptographic Signature capability
- *
- */
-
-#include <sys/types.h>
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#include <stdio.h>
-#include <dirent.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/file.h"
-#include "asterisk/channel.h"
-#include "asterisk/logger.h"
-#include "asterisk/say.h"
-#include "asterisk/module.h"
-#include "asterisk/options.h"
-#include "asterisk/crypto.h"
-#include "asterisk/md5.h"
-#include "asterisk/cli.h"
-#include "asterisk/io.h"
-#include "asterisk/lock.h"
-#include "asterisk/utils.h"
-
-/*
- * Asterisk uses RSA keys with SHA-1 message digests for its
- * digital signatures. The choice of RSA is due to its higher
- * throughput on verification, and the choice of SHA-1 based
- * on the recently discovered collisions in MD5's compression
- * algorithm and recommendations of avoiding MD5 in new schemes
- * from various industry experts.
- *
- * We use OpenSSL to provide our crypto routines, although we never
- * actually use full-up SSL
- *
- */
-
-/*
- * XXX This module is not very thread-safe. It is for everyday stuff
- * like reading keys and stuff, but there are all kinds of weird
- * races with people running reload and key init at the same time
- * for example
- *
- * XXXX
- */
-
-AST_MUTEX_DEFINE_STATIC(keylock);
-
-#define KEY_NEEDS_PASSCODE (1 << 16)
-
-struct ast_key {
- /* Name of entity */
- char name[80];
- /* File name */
- char fn[256];
- /* Key type (AST_KEY_PUB or AST_KEY_PRIV, along with flags from above) */
- int ktype;
- /* RSA structure (if successfully loaded) */
- RSA *rsa;
- /* Whether we should be deleted */
- int delme;
- /* FD for input (or -1 if no input allowed, or -2 if we needed input) */
- int infd;
- /* FD for output */
- int outfd;
- /* Last MD5 Digest */
- unsigned char digest[16];
- struct ast_key *next;
-};
-
-static struct ast_key *keys = NULL;
-
-
-#if 0
-static int fdprint(int fd, char *s)
-{
- return write(fd, s, strlen(s) + 1);
-}
-#endif
-static int pw_cb(char *buf, int size, int rwflag, void *userdata)
-{
- struct ast_key *key = (struct ast_key *)userdata;
- char prompt[256];
- int res;
- int tmp;
- if (key->infd > -1) {
- snprintf(prompt, sizeof(prompt), ">>>> passcode for %s key '%s': ",
- key->ktype == AST_KEY_PRIVATE ? "PRIVATE" : "PUBLIC", key->name);
- write(key->outfd, prompt, strlen(prompt));
- memset(buf, 0, sizeof(buf));
- tmp = ast_hide_password(key->infd);
- memset(buf, 0, size);
- res = read(key->infd, buf, size);
- ast_restore_tty(key->infd, tmp);
- if (buf[strlen(buf) -1] == '\n')
- buf[strlen(buf) - 1] = '\0';
- return strlen(buf);
- } else {
- /* Note that we were at least called */
- key->infd = -2;
- }
- return -1;
-}
-
-static struct ast_key *__ast_key_get(const char *kname, int ktype)
-{
- struct ast_key *key;
- ast_mutex_lock(&keylock);
- key = keys;
- while(key) {
- if (!strcmp(kname, key->name) &&
- (ktype == key->ktype))
- break;
- key = key->next;
- }
- ast_mutex_unlock(&keylock);
- return key;
-}
-
-static struct ast_key *try_load_key (char *dir, char *fname, int ifd, int ofd, int *not2)
-{
- int ktype = 0;
- char *c = NULL;
- char ffname[256];
- unsigned char digest[16];
- FILE *f;
- struct MD5Context md5;
- struct ast_key *key;
- static int notice = 0;
- int found = 0;
-
- /* Make sure its name is a public or private key */
-
- if ((c = strstr(fname, ".pub")) && !strcmp(c, ".pub")) {
- ktype = AST_KEY_PUBLIC;
- } else if ((c = strstr(fname, ".key")) && !strcmp(c, ".key")) {
- ktype = AST_KEY_PRIVATE;
- } else
- return NULL;
-
- /* Get actual filename */
- snprintf(ffname, sizeof(ffname), "%s/%s", dir, fname);
-
- ast_mutex_lock(&keylock);
- key = keys;
- while(key) {
- /* Look for an existing version already */
- if (!strcasecmp(key->fn, ffname))
- break;
- key = key->next;
- }
- ast_mutex_unlock(&keylock);
-
- /* Open file */
- f = fopen(ffname, "r");
- if (!f) {
- ast_log(LOG_WARNING, "Unable to open key file %s: %s\n", ffname, strerror(errno));
- return NULL;
- }
- MD5Init(&md5);
- while(!feof(f)) {
- /* Calculate a "whatever" quality md5sum of the key */
- char buf[256];
- memset(buf, 0, 256);
- fgets(buf, sizeof(buf), f);
- if (!feof(f)) {
- MD5Update(&md5, (unsigned char *) buf, strlen(buf));
- }
- }
- MD5Final(digest, &md5);
- if (key) {
- /* If the MD5 sum is the same, and it isn't awaiting a passcode
- then this is far enough */
- if (!memcmp(digest, key->digest, 16) &&
- !(key->ktype & KEY_NEEDS_PASSCODE)) {
- fclose(f);
- key->delme = 0;
- return NULL;
- } else {
- /* Preserve keytype */
- ktype = key->ktype;
- /* Recycle the same structure */
- found++;
- }
- }
-
- /* Make fname just be the normal name now */
- *c = '\0';
- if (!key) {
- key = (struct ast_key *)malloc(sizeof(struct ast_key));
- if (!key) {
- ast_log(LOG_WARNING, "Out of memory\n");
- fclose(f);
- return NULL;
- }
- memset(key, 0, sizeof(struct ast_key));
- }
- /* At this point we have a key structure (old or new). Time to
- fill it with what we know */
- /* Gotta lock if this one already exists */
- if (found)
- ast_mutex_lock(&keylock);
- /* First the filename */
- ast_copy_string(key->fn, ffname, sizeof(key->fn));
- /* Then the name */
- ast_copy_string(key->name, fname, sizeof(key->name));
- key->ktype = ktype;
- /* Yes, assume we're going to be deleted */
- key->delme = 1;
- /* Keep the key type */
- memcpy(key->digest, digest, 16);
- /* Can I/O takes the FD we're given */
- key->infd = ifd;
- key->outfd = ofd;
- /* Reset the file back to the beginning */
- rewind(f);
- /* Now load the key with the right method */
- if (ktype == AST_KEY_PUBLIC)
- key->rsa = PEM_read_RSA_PUBKEY(f, NULL, pw_cb, key);
- else
- key->rsa = PEM_read_RSAPrivateKey(f, NULL, pw_cb, key);
- fclose(f);
- if (key->rsa) {
- if (RSA_size(key->rsa) == 128) {
- /* Key loaded okay */
- key->ktype &= ~KEY_NEEDS_PASSCODE;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Loaded %s key '%s'\n", key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name);
- if (option_debug)
- ast_log(LOG_DEBUG, "Key '%s' loaded OK\n", key->name);
- key->delme = 0;
- } else
- ast_log(LOG_NOTICE, "Key '%s' is not expected size.\n", key->name);
- } else if (key->infd != -2) {
- ast_log(LOG_WARNING, "Key load %s '%s' failed\n",key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name);
- if (ofd > -1) {
- ERR_print_errors_fp(stderr);
- } else
- ERR_print_errors_fp(stderr);
- } else {
- ast_log(LOG_NOTICE, "Key '%s' needs passcode.\n", key->name);
- key->ktype |= KEY_NEEDS_PASSCODE;
- if (!notice) {
- if (!option_initcrypto)
- ast_log(LOG_NOTICE, "Add the '-i' flag to the asterisk command line if you want to automatically initialize passcodes at launch.\n");
- notice++;
- }
- /* Keep it anyway */
- key->delme = 0;
- /* Print final notice about "init keys" when done */
- *not2 = 1;
- }
- if (found)
- ast_mutex_unlock(&keylock);
- if (!found) {
- ast_mutex_lock(&keylock);
- key->next = keys;
- keys = key;
- ast_mutex_unlock(&keylock);
- }
- return key;
-}
-
-#if 0
-
-static void dump(unsigned char *src, int len)
-{
- int x;
- for (x=0;x<len;x++)
- printf("%02x", *(src++));
- printf("\n");
-}
-
-static char *binary(int y, int len)
-{
- static char res[80];
- int x;
- memset(res, 0, sizeof(res));
- for (x=0;x<len;x++) {
- if (y & (1 << x))
- res[(len - x - 1)] = '1';
- else
- res[(len - x - 1)] = '0';
- }
- return res;
-}
-
-#endif
-
-static int __ast_sign_bin(struct ast_key *key, const char *msg, int msglen, unsigned char *dsig)
-{
- unsigned char digest[20];
- unsigned int siglen = 128;
- int res;
-
- if (key->ktype != AST_KEY_PRIVATE) {
- ast_log(LOG_WARNING, "Cannot sign with a public key\n");
- return -1;
- }
-
- /* Calculate digest of message */
- SHA1((unsigned char *)msg, msglen, digest);
-
- /* Verify signature */
- res = RSA_sign(NID_sha1, digest, sizeof(digest), dsig, &siglen, key->rsa);
-
- if (!res) {
- ast_log(LOG_WARNING, "RSA Signature (key %s) failed\n", key->name);
- return -1;
- }
-
- if (siglen != 128) {
- ast_log(LOG_WARNING, "Unexpected signature length %d, expecting %d\n", (int)siglen, (int)128);
- return -1;
- }
-
- return 0;
-
-}
-
-static int __ast_decrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
-{
- int res;
- int pos = 0;
- if (key->ktype != AST_KEY_PRIVATE) {
- ast_log(LOG_WARNING, "Cannot decrypt with a public key\n");
- return -1;
- }
-
- if (srclen % 128) {
- ast_log(LOG_NOTICE, "Tried to decrypt something not a multiple of 128 bytes\n");
- return -1;
- }
- while(srclen) {
- /* Process chunks 128 bytes at a time */
- res = RSA_private_decrypt(128, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING);
- if (res < 0)
- return -1;
- pos += res;
- src += 128;
- srclen -= 128;
- dst += res;
- }
- return pos;
-}
-
-static int __ast_encrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
-{
- int res;
- int bytes;
- int pos = 0;
- if (key->ktype != AST_KEY_PUBLIC) {
- ast_log(LOG_WARNING, "Cannot encrypt with a private key\n");
- return -1;
- }
-
- while(srclen) {
- bytes = srclen;
- if (bytes > 128 - 41)
- bytes = 128 - 41;
- /* Process chunks 128-41 bytes at a time */
- res = RSA_public_encrypt(bytes, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING);
- if (res != 128) {
- ast_log(LOG_NOTICE, "How odd, encrypted size is %d\n", res);
- return -1;
- }
- src += bytes;
- srclen -= bytes;
- pos += res;
- dst += res;
- }
- return pos;
-}
-
-static int __ast_sign(struct ast_key *key, char *msg, char *sig)
-{
- unsigned char dsig[128];
- int siglen = sizeof(dsig);
- int res;
- res = ast_sign_bin(key, msg, strlen(msg), dsig);
- if (!res)
- /* Success -- encode (256 bytes max as documented) */
- ast_base64encode(sig, dsig, siglen, 256);
- return res;
-
-}
-
-static int __ast_check_signature_bin(struct ast_key *key, const char *msg, int msglen, const unsigned char *dsig)
-{
- unsigned char digest[20];
- int res;
-
- if (key->ktype != AST_KEY_PUBLIC) {
- /* Okay, so of course you really *can* but for our purposes
- we're going to say you can't */
- ast_log(LOG_WARNING, "Cannot check message signature with a private key\n");
- return -1;
- }
-
- /* Calculate digest of message */
- SHA1((unsigned char *)msg, msglen, digest);
-
- /* Verify signature */
- res = RSA_verify(NID_sha1, digest, sizeof(digest), (unsigned char *)dsig, 128, key->rsa);
-
- if (!res) {
- ast_log(LOG_DEBUG, "Key failed verification: %s\n", key->name);
- return -1;
- }
- /* Pass */
- return 0;
-}
-
-static int __ast_check_signature(struct ast_key *key, const char *msg, const char *sig)
-{
- unsigned char dsig[128];
- int res;
-
- /* Decode signature */
- res = ast_base64decode(dsig, sig, sizeof(dsig));
- if (res != sizeof(dsig)) {
- ast_log(LOG_WARNING, "Signature improper length (expect %d, got %d)\n", (int)sizeof(dsig), (int)res);
- return -1;
- }
- res = ast_check_signature_bin(key, msg, strlen(msg), dsig);
- return res;
-}
-
-static void crypto_load(int ifd, int ofd)
-{
- struct ast_key *key, *nkey, *last;
- DIR *dir = NULL;
- struct dirent *ent;
- int note = 0;
- /* Mark all keys for deletion */
- ast_mutex_lock(&keylock);
- key = keys;
- while(key) {
- key->delme = 1;
- key = key->next;
- }
- ast_mutex_unlock(&keylock);
- /* Load new keys */
- dir = opendir((char *)ast_config_AST_KEY_DIR);
- if (dir) {
- while((ent = readdir(dir))) {
- try_load_key((char *)ast_config_AST_KEY_DIR, ent->d_name, ifd, ofd, &note);
- }
- closedir(dir);
- } else
- ast_log(LOG_WARNING, "Unable to open key directory '%s'\n", (char *)ast_config_AST_KEY_DIR);
- if (note) {
- ast_log(LOG_NOTICE, "Please run the command 'init keys' to enter the passcodes for the keys\n");
- }
- ast_mutex_lock(&keylock);
- key = keys;
- last = NULL;
- while(key) {
- nkey = key->next;
- if (key->delme) {
- ast_log(LOG_DEBUG, "Deleting key %s type %d\n", key->name, key->ktype);
- /* Do the delete */
- if (last)
- last->next = nkey;
- else
- keys = nkey;
- if (key->rsa)
- RSA_free(key->rsa);
- free(key);
- } else
- last = key;
- key = nkey;
- }
- ast_mutex_unlock(&keylock);
-}
-
-static void md52sum(char *sum, unsigned char *md5)
-{
- int x;
- for (x=0;x<16;x++)
- sum += sprintf(sum, "%02x", *(md5++));
-}
-
-static int show_keys(int fd, int argc, char *argv[])
-{
- struct ast_key *key;
- char sum[16 * 2 + 1];
- int count_keys = 0;
-
- ast_mutex_lock(&keylock);
- key = keys;
- ast_cli(fd, "%-18s %-8s %-16s %-33s\n", "Key Name", "Type", "Status", "Sum");
- while(key) {
- md52sum(sum, key->digest);
- ast_cli(fd, "%-18s %-8s %-16s %-33s\n", key->name,
- (key->ktype & 0xf) == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE",
- key->ktype & KEY_NEEDS_PASSCODE ? "[Needs Passcode]" : "[Loaded]", sum);
-
- key = key->next;
- count_keys++;
- }
- ast_mutex_unlock(&keylock);
- ast_cli(fd, "%d known RSA keys.\n", count_keys);
- return RESULT_SUCCESS;
-}
-
-static int init_keys(int fd, int argc, char *argv[])
-{
- struct ast_key *key;
- int ign;
- char *kn;
- char tmp[256] = "";
-
- key = keys;
- while(key) {
- /* Reload keys that need pass codes now */
- if (key->ktype & KEY_NEEDS_PASSCODE) {
- kn = key->fn + strlen(ast_config_AST_KEY_DIR) + 1;
- ast_copy_string(tmp, kn, sizeof(tmp));
- try_load_key((char *)ast_config_AST_KEY_DIR, tmp, fd, fd, &ign);
- }
- key = key->next;
- }
- return RESULT_SUCCESS;
-}
-
-static char show_key_usage[] =
-"Usage: show keys\n"
-" Displays information about RSA keys known by Asterisk\n";
-
-static char init_keys_usage[] =
-"Usage: init keys\n"
-" Initializes private keys (by reading in pass code from the user)\n";
-
-static struct ast_cli_entry cli_show_keys =
-{ { "show", "keys", NULL }, show_keys, "Displays RSA key information", show_key_usage };
-
-static struct ast_cli_entry cli_init_keys =
-{ { "init", "keys", NULL }, init_keys, "Initialize RSA key passcodes", init_keys_usage };
-
-static int crypto_init(void)
-{
- SSL_library_init();
- ERR_load_crypto_strings();
- ast_cli_register(&cli_show_keys);
- ast_cli_register(&cli_init_keys);
-
- /* Install ourselves into stubs */
- ast_key_get = __ast_key_get;
- ast_check_signature = __ast_check_signature;
- ast_check_signature_bin = __ast_check_signature_bin;
- ast_sign = __ast_sign;
- ast_sign_bin = __ast_sign_bin;
- ast_encrypt_bin = __ast_encrypt_bin;
- ast_decrypt_bin = __ast_decrypt_bin;
- return 0;
-}
-
-int reload(void)
-{
- crypto_load(-1, -1);
- return 0;
-}
-
-int load_module(void)
-{
- crypto_init();
- if (option_initcrypto)
- crypto_load(STDIN_FILENO, STDOUT_FILENO);
- else
- crypto_load(-1, -1);
- return 0;
-}
-
-int unload_module(void)
-{
- /* Can't unload this once we're loaded */
- return -1;
-}
-
-char *description(void)
-{
- return "Cryptographic Digital Signatures";
-}
-
-int usecount(void)
-{
- /* We should never be unloaded */
- return 1;
-}
-
-char *key()
-{
- return ASTERISK_GPL_KEY;
-}
diff --git a/1.2-netsec/res/res_features.c b/1.2-netsec/res/res_features.c
deleted file mode 100644
index bf23129ae..000000000
--- a/1.2-netsec/res/res_features.c
+++ /dev/null
@@ -1,2187 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Routines implementing call parking
- *
- */
-
-#include <pthread.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/time.h>
-#include <sys/signal.h>
-#include <netinet/in.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/lock.h"
-#include "asterisk/file.h"
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/pbx.h"
-#include "asterisk/options.h"
-#include "asterisk/causes.h"
-#include "asterisk/module.h"
-#include "asterisk/translate.h"
-#include "asterisk/app.h"
-#include "asterisk/say.h"
-#include "asterisk/features.h"
-#include "asterisk/musiconhold.h"
-#include "asterisk/config.h"
-#include "asterisk/cli.h"
-#include "asterisk/manager.h"
-#include "asterisk/utils.h"
-#include "asterisk/adsi.h"
-#include "asterisk/monitor.h"
-
-#ifdef __AST_DEBUG_MALLOC
-static void FREE(void *ptr)
-{
- free(ptr);
-}
-#else
-#define FREE free
-#endif
-
-#define DEFAULT_PARK_TIME 45000
-#define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
-#define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
-
-#define AST_MAX_WATCHERS 256
-
-static char *parkedcall = "ParkedCall";
-
-/* No more than 45 seconds parked before you do something with them */
-static int parkingtime = DEFAULT_PARK_TIME;
-
-/* Context for which parking is made accessible */
-static char parking_con[AST_MAX_EXTENSION];
-
-/* Context for dialback for parking (KLUDGE) */
-static char parking_con_dial[AST_MAX_EXTENSION];
-
-/* Extension you type to park the call */
-static char parking_ext[AST_MAX_EXTENSION];
-
-static char pickup_ext[AST_MAX_EXTENSION];
-
-/* Default sounds */
-static char courtesytone[256];
-static char xfersound[256];
-static char xferfailsound[256];
-
-/* First available extension for parking */
-static int parking_start;
-
-/* Last available extension for parking */
-static int parking_stop;
-
-static int parking_offset;
-
-static int parkfindnext;
-
-static int adsipark;
-
-static int transferdigittimeout;
-static int featuredigittimeout;
-
-/* Default courtesy tone played when party joins conference */
-
-/* Registrar for operations */
-static char *registrar = "res_features";
-
-static char *synopsis = "Answer a parked call";
-
-static char *descrip = "ParkedCall(exten):"
-"Used to connect to a parked call. This application is always\n"
-"registered internally and does not need to be explicitly added\n"
-"into the dialplan, although you should include the 'parkedcalls'\n"
-"context.\n";
-
-static char *parkcall = "Park";
-
-static char *synopsis2 = "Park yourself";
-
-static char *descrip2 = "Park(exten):"
-"Used to park yourself (typically in combination with a supervised\n"
-"transfer to know the parking space). This application is always\n"
-"registered internally and does not need to be explicitly added\n"
-"into the dialplan, although you should include the 'parkedcalls'\n"
-"context.\n";
-
-static struct ast_app *monitor_app=NULL;
-static int monitor_ok=1;
-
-struct parkeduser {
- struct ast_channel *chan;
- struct timeval start;
- int parkingnum;
- /* Where to go if our parking time expires */
- char context[AST_MAX_CONTEXT];
- char exten[AST_MAX_EXTENSION];
- int priority;
- int parkingtime;
- int notquiteyet;
- char peername[1024];
- unsigned char moh_trys;
- struct parkeduser *next;
-};
-
-static struct parkeduser *parkinglot;
-
-AST_MUTEX_DEFINE_STATIC(parking_lock);
-
-static pthread_t parking_thread;
-
-STANDARD_LOCAL_USER;
-
-LOCAL_USER_DECL;
-
-char *ast_parking_ext(void)
-{
- return parking_ext;
-}
-
-char *ast_pickup_ext(void)
-{
- return pickup_ext;
-}
-
-struct ast_bridge_thread_obj
-{
- struct ast_bridge_config bconfig;
- struct ast_channel *chan;
- struct ast_channel *peer;
-};
-
-static void check_goto_on_transfer(struct ast_channel *chan)
-{
- struct ast_channel *xferchan;
- char *goto_on_transfer;
-
- goto_on_transfer = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
-
- if (!ast_strlen_zero(goto_on_transfer) && (xferchan = ast_channel_alloc(0))) {
- char *x;
- struct ast_frame *f;
-
- for (x = goto_on_transfer; x && *x; x++)
- if (*x == '^')
- *x = '|';
-
- strcpy(xferchan->name, chan->name);
- /* Make formats okay */
- xferchan->readformat = chan->readformat;
- xferchan->writeformat = chan->writeformat;
- ast_channel_masquerade(xferchan, chan);
- ast_parseable_goto(xferchan, goto_on_transfer);
- xferchan->_state = AST_STATE_UP;
- ast_clear_flag(xferchan, AST_FLAGS_ALL);
- xferchan->_softhangup = 0;
- if ((f = ast_read(xferchan))) {
- ast_frfree(f);
- f = NULL;
- ast_pbx_start(xferchan);
- } else {
- ast_hangup(xferchan);
- }
- }
-}
-
-static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name);
-
-
-static void *ast_bridge_call_thread(void *data)
-{
- struct ast_bridge_thread_obj *tobj = data;
-
- tobj->chan->appl = "Transferred Call";
- tobj->chan->data = tobj->peer->name;
- tobj->peer->appl = "Transferred Call";
- tobj->peer->data = tobj->chan->name;
- if (tobj->chan->cdr) {
- ast_cdr_reset(tobj->chan->cdr, NULL);
- ast_cdr_setdestchan(tobj->chan->cdr, tobj->peer->name);
- }
- if (tobj->peer->cdr) {
- ast_cdr_reset(tobj->peer->cdr, NULL);
- ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
- }
-
- ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
- ast_hangup(tobj->chan);
- ast_hangup(tobj->peer);
- tobj->chan = tobj->peer = NULL;
- free(tobj);
- tobj=NULL;
- return NULL;
-}
-
-static void ast_bridge_call_thread_launch(void *data)
-{
- pthread_t thread;
- pthread_attr_t attr;
- struct sched_param sched;
-
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
- pthread_attr_destroy(&attr);
- memset(&sched, 0, sizeof(sched));
- pthread_setschedparam(thread, SCHED_RR, &sched);
-}
-
-
-
-static int adsi_announce_park(struct ast_channel *chan, int parkingnum)
-{
- int res;
- int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
- char tmp[256];
- char *message[5] = {NULL, NULL, NULL, NULL, NULL};
-
- snprintf(tmp, sizeof(tmp), "Parked on %d", parkingnum);
- message[0] = tmp;
- res = adsi_load_session(chan, NULL, 0, 1);
- if (res == -1) {
- return res;
- }
- return adsi_print(chan, message, justify, 1);
-}
-
-/*--- ast_park_call: Park a call */
-/* We put the user in the parking list, then wake up the parking thread to be sure it looks
- after these channels too */
-int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
-{
- struct parkeduser *pu, *cur;
- int i,x,parking_range;
- char exten[AST_MAX_EXTENSION];
- struct ast_context *con;
-
- pu = malloc(sizeof(struct parkeduser));
- if (!pu) {
- ast_log(LOG_WARNING, "Out of memory\n");
- return -1;
- }
- memset(pu, 0, sizeof(struct parkeduser));
- ast_mutex_lock(&parking_lock);
- parking_range = parking_stop - parking_start+1;
- for (i = 0; i < parking_range; i++) {
- x = (i + parking_offset) % parking_range + parking_start;
- cur = parkinglot;
- while(cur) {
- if (cur->parkingnum == x)
- break;
- cur = cur->next;
- }
- if (!cur)
- break;
- }
-
- if (!(i < parking_range)) {
- ast_log(LOG_WARNING, "No more parking spaces\n");
- free(pu);
- ast_mutex_unlock(&parking_lock);
- return -1;
- }
- if (parkfindnext)
- parking_offset = x - parking_start + 1;
- chan->appl = "Parked Call";
- chan->data = NULL;
-
- pu->chan = chan;
- /* Start music on hold */
- if (chan != peer) {
- ast_indicate(pu->chan, AST_CONTROL_HOLD);
- ast_moh_start(pu->chan, NULL);
- }
- pu->start = ast_tvnow();
- pu->parkingnum = x;
- if (timeout > 0)
- pu->parkingtime = timeout;
- else
- pu->parkingtime = parkingtime;
- if (extout)
- *extout = x;
- if (peer)
- ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
-
- /* Remember what had been dialed, so that if the parking
- expires, we try to come back to the same place */
- if (!ast_strlen_zero(chan->macrocontext))
- ast_copy_string(pu->context, chan->macrocontext, sizeof(pu->context));
- else
- ast_copy_string(pu->context, chan->context, sizeof(pu->context));
- if (!ast_strlen_zero(chan->macroexten))
- ast_copy_string(pu->exten, chan->macroexten, sizeof(pu->exten));
- else
- ast_copy_string(pu->exten, chan->exten, sizeof(pu->exten));
- if (chan->macropriority)
- pu->priority = chan->macropriority;
- else
- pu->priority = chan->priority;
- pu->next = parkinglot;
- parkinglot = pu;
- /* If parking a channel directly, don't quiet yet get parking running on it */
- if (peer == chan)
- pu->notquiteyet = 1;
- ast_mutex_unlock(&parking_lock);
- /* Wake up the (presumably select()ing) thread */
- pthread_kill(parking_thread, SIGURG);
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d. Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
-
- manager_event(EVENT_FLAG_CALL, "ParkedCall",
- "Exten: %d\r\n"
- "Channel: %s\r\n"
- "From: %s\r\n"
- "Timeout: %ld\r\n"
- "CallerID: %s\r\n"
- "CallerIDName: %s\r\n"
- ,pu->parkingnum, pu->chan->name, peer->name
- ,(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL)
- ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
- ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
- );
-
- if (peer) {
- if (adsipark && adsi_available(peer)) {
- adsi_announce_park(peer, pu->parkingnum);
- }
- if (adsipark && adsi_available(peer)) {
- adsi_unload_session(peer);
- }
- }
- con = ast_context_find(parking_con);
- if (!con) {
- con = ast_context_create(NULL, parking_con, registrar);
- if (!con) {
- ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
- }
- }
- if (con) {
- snprintf(exten, sizeof(exten), "%d", x);
- ast_add_extension2(con, 1, exten, 1, NULL, NULL, parkedcall, strdup(exten), FREE, registrar);
- }
- if (peer)
- ast_say_digits(peer, pu->parkingnum, "", peer->language);
- if (pu->notquiteyet) {
- /* Wake up parking thread if we're really done */
- ast_moh_start(pu->chan, NULL);
- pu->notquiteyet = 0;
- pthread_kill(parking_thread, SIGURG);
- }
- return 0;
-}
-
-int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
-{
- struct ast_channel *chan;
- struct ast_frame *f;
-
- /* Make a new, fake channel that we'll use to masquerade in the real one */
- chan = ast_channel_alloc(0);
- if (chan) {
- /* Let us keep track of the channel name */
- snprintf(chan->name, sizeof (chan->name), "Parked/%s",rchan->name);
-
- /* Make formats okay */
- chan->readformat = rchan->readformat;
- chan->writeformat = rchan->writeformat;
- ast_channel_masquerade(chan, rchan);
-
- /* Setup the extensions and such */
- ast_copy_string(chan->context, rchan->context, sizeof(chan->context));
- ast_copy_string(chan->exten, rchan->exten, sizeof(chan->exten));
- chan->priority = rchan->priority;
-
- /* Make the masq execute */
- f = ast_read(chan);
- if (f)
- ast_frfree(f);
- ast_park_call(chan, peer, timeout, extout);
- } else {
- ast_log(LOG_WARNING, "Unable to create parked channel\n");
- return -1;
- }
- return 0;
-}
-
-
-#define FEATURE_RETURN_HANGUP -1
-#define FEATURE_RETURN_SUCCESSBREAK 0
-#define FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE
-#define FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER
-#define FEATURE_RETURN_PASSDIGITS 21
-#define FEATURE_RETURN_STOREDIGITS 22
-#define FEATURE_RETURN_SUCCESS 23
-
-#define FEATURE_SENSE_CHAN (1 << 0)
-#define FEATURE_SENSE_PEER (1 << 1)
-
-
-static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
-{
- char *touch_monitor = NULL, *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_format = NULL;
- int x = 0;
- size_t len;
- struct ast_channel *caller_chan = NULL, *callee_chan = NULL;
-
-
- if(sense == 2) {
- caller_chan = peer;
- callee_chan = chan;
- } else {
- callee_chan = peer;
- caller_chan = chan;
- }
-
- if (!monitor_ok) {
- ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
- return -1;
- }
-
- if (!monitor_app) {
- if (!(monitor_app = pbx_findapp("Monitor"))) {
- monitor_ok=0;
- ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
- return -1;
- }
- }
- if (!ast_strlen_zero(courtesytone)) {
- if (ast_autoservice_start(callee_chan))
- return -1;
- if (!ast_streamfile(caller_chan, courtesytone, caller_chan->language)) {
- if (ast_waitstream(caller_chan, "") < 0) {
- ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
- ast_autoservice_stop(callee_chan);
- return -1;
- }
- }
- if (ast_autoservice_stop(callee_chan))
- return -1;
- }
-
- if (callee_chan->monitor) {
- if (option_verbose > 3)
- ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to stop recording call.\n", code);
- ast_monitor_stop(callee_chan, 1);
- return FEATURE_RETURN_SUCCESS;
- }
-
- if (caller_chan && callee_chan) {
- touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
- if (!touch_format)
- touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
-
- touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
- if (!touch_monitor)
- touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
-
- if (touch_monitor) {
- len = strlen(touch_monitor) + 50;
- args = alloca(len);
- snprintf(args, len, "%s|auto-%ld-%s|m", (touch_format) ? touch_format : "wav", time(NULL), touch_monitor);
- } else {
- caller_chan_id = ast_strdupa(caller_chan->cid.cid_num ? caller_chan->cid.cid_num : caller_chan->name);
- callee_chan_id = ast_strdupa(callee_chan->cid.cid_num ? callee_chan->cid.cid_num : callee_chan->name);
- len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
- args = alloca(len);
- snprintf(args, len, "%s|auto-%ld-%s-%s|m", (touch_format) ? touch_format : "wav", time(NULL), caller_chan_id, callee_chan_id);
- }
-
- for( x = 0; x < strlen(args); x++)
- if (args[x] == '/')
- args[x] = '-';
-
- if (option_verbose > 3)
- ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to record call. filename: %s\n", code, args);
-
- pbx_exec(callee_chan, monitor_app, args, 1);
-
- return FEATURE_RETURN_SUCCESS;
- }
-
- ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
- return -1;
-}
-
-static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
-{
- if (option_verbose > 3)
- ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to disconnect call.\n", code);
- return FEATURE_RETURN_HANGUP;
-}
-
-static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
-{
- struct ast_channel *transferer;
- struct ast_channel *transferee;
- char *transferer_real_context;
- char newext[256];
- int res;
-
- if (sense == FEATURE_SENSE_PEER) {
- transferer = peer;
- transferee = chan;
- } else {
- transferer = chan;
- transferee = peer;
- }
- if (!(transferer_real_context = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT")) &&
- !(transferer_real_context = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT"))) {
- /* Use the non-macro context to transfer the call */
- if (!ast_strlen_zero(transferer->macrocontext))
- transferer_real_context = transferer->macrocontext;
- else
- transferer_real_context = transferer->context;
- }
- /* Start autoservice on chan while we talk
- to the originator */
- ast_indicate(transferee, AST_CONTROL_HOLD);
- ast_autoservice_start(transferee);
- ast_moh_start(transferee, NULL);
-
- memset(newext, 0, sizeof(newext));
-
- /* Transfer */
- if ((res=ast_streamfile(transferer, "pbx-transfer", transferer->language))) {
- ast_moh_stop(transferee);
- ast_autoservice_stop(transferee);
- ast_indicate(transferee, AST_CONTROL_UNHOLD);
- return res;
- }
- if ((res=ast_waitstream(transferer, AST_DIGIT_ANY)) < 0) {
- ast_moh_stop(transferee);
- ast_autoservice_stop(transferee);
- ast_indicate(transferee, AST_CONTROL_UNHOLD);
- return res;
- } else if (res > 0) {
- /* If they've typed a digit already, handle it */
- newext[0] = (char) res;
- }
-
- ast_stopstream(transferer);
- res = ast_app_dtget(transferer, transferer_real_context, newext, sizeof(newext), 100, transferdigittimeout);
- if (res < 0) {
- ast_moh_stop(transferee);
- ast_autoservice_stop(transferee);
- ast_indicate(transferee, AST_CONTROL_UNHOLD);
- return res;
- }
- if (!strcmp(newext, ast_parking_ext())) {
- ast_moh_stop(transferee);
-
- res = ast_autoservice_stop(transferee);
- ast_indicate(transferee, AST_CONTROL_UNHOLD);
- if (res)
- res = -1;
- else if (!ast_park_call(transferee, transferer, 0, NULL)) {
- /* We return non-zero, but tell the PBX not to hang the channel when
- the thread dies -- We have to be careful now though. We are responsible for
- hanging up the channel, else it will never be hung up! */
-
- if (transferer == peer)
- res = AST_PBX_KEEPALIVE;
- else
- res = AST_PBX_NO_HANGUP_PEER;
- return res;
- } else {
- ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
- }
- /* XXX Maybe we should have another message here instead of invalid extension XXX */
- } else if (ast_exists_extension(transferee, transferer_real_context, newext, 1, transferer->cid.cid_num)) {
- pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", chan->name);
- pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
- ast_moh_stop(transferee);
- res=ast_autoservice_stop(transferee);
- ast_indicate(transferee, AST_CONTROL_UNHOLD);
- if (!transferee->pbx) {
- /* Doh! Use our handy async_goto functions */
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
- ,transferee->name, newext, transferer_real_context);
- if (ast_async_goto(transferee, transferer_real_context, newext, 1))
- ast_log(LOG_WARNING, "Async goto failed :-(\n");
- res = -1;
- } else {
- /* Set the channel's new extension, since it exists, using transferer context */
- ast_copy_string(transferee->exten, newext, sizeof(transferee->exten));
- ast_copy_string(transferee->context, transferer_real_context, sizeof(transferee->context));
- transferee->priority = 0;
- }
- check_goto_on_transfer(transferer);
- return res;
- } else {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Unable to find extension '%s' in context '%s'\n", newext, transferer_real_context);
- }
- if (!ast_strlen_zero(xferfailsound))
- res = ast_streamfile(transferer, xferfailsound, transferee->language);
- else
- res = 0;
- if (res) {
- ast_moh_stop(transferee);
- ast_autoservice_stop(transferee);
- ast_indicate(transferee, AST_CONTROL_UNHOLD);
- return res;
- }
- res = ast_waitstream(transferer, AST_DIGIT_ANY);
- ast_stopstream(transferer);
- ast_moh_stop(transferee);
- res = ast_autoservice_stop(transferee);
- ast_indicate(transferee, AST_CONTROL_UNHOLD);
- if (res) {
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Hungup during autoservice stop on '%s'\n", transferee->name);
- return res;
- }
- return FEATURE_RETURN_SUCCESS;
-}
-
-static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
-{
- struct ast_channel *transferer;
- struct ast_channel *transferee;
- struct ast_channel *newchan, *xferchan=NULL;
- int outstate=0;
- struct ast_bridge_config bconfig;
- char *transferer_real_context;
- char xferto[256],dialstr[265];
- char *cid_num;
- char *cid_name;
- int res;
- struct ast_frame *f = NULL;
- struct ast_bridge_thread_obj *tobj;
-
- ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) XXX\n", chan->name, peer->name, sense);
- if (sense == FEATURE_SENSE_PEER) {
- transferer = peer;
- transferee = chan;
- } else {
- transferer = chan;
- transferee = peer;
- }
- if (!(transferer_real_context=pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT")) &&
- !(transferer_real_context=pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT"))) {
- /* Use the non-macro context to transfer the call */
- if (!ast_strlen_zero(transferer->macrocontext))
- transferer_real_context = transferer->macrocontext;
- else
- transferer_real_context = transferer->context;
- }
- /* Start autoservice on chan while we talk
- to the originator */
- ast_indicate(transferee, AST_CONTROL_HOLD);
- ast_autoservice_start(transferee);
- ast_moh_start(transferee, NULL);
- memset(xferto, 0, sizeof(xferto));
- /* Transfer */
- if ((res = ast_streamfile(transferer, "pbx-transfer", transferer->language))) {
- ast_moh_stop(transferee);
- ast_autoservice_stop(transferee);
- ast_indicate(transferee, AST_CONTROL_UNHOLD);
- return res;
- }
- if ((res=ast_waitstream(transferer, AST_DIGIT_ANY)) < 0) {
- ast_moh_stop(transferee);
- ast_autoservice_stop(transferee);
- ast_indicate(transferee, AST_CONTROL_UNHOLD);
- return res;
- } else if(res > 0) {
- /* If they've typed a digit already, handle it */
- xferto[0] = (char) res;
- }
- if ((ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout))) {
- cid_num = transferer->cid.cid_num;
- cid_name = transferer->cid.cid_name;
- if (ast_exists_extension(transferer, transferer_real_context,xferto, 1, cid_num)) {
- snprintf(dialstr, sizeof(dialstr), "%s@%s/n", xferto, transferer_real_context);
- newchan = ast_feature_request_and_dial(transferer, "Local", ast_best_codec(transferer->nativeformats), dialstr, 15000, &outstate, cid_num, cid_name);
- ast_indicate(transferer, -1);
- if (newchan) {
- res = ast_channel_make_compatible(transferer, newchan);
- if (res < 0) {
- ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", transferer->name, newchan->name);
- ast_hangup(newchan);
- return -1;
- }
- memset(&bconfig,0,sizeof(struct ast_bridge_config));
- ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
- ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
- res = ast_bridge_call(transferer,newchan,&bconfig);
- if (newchan->_softhangup || newchan->_state != AST_STATE_UP || !transferer->_softhangup) {
- ast_hangup(newchan);
- if (f) {
- ast_frfree(f);
- f = NULL;
- }
- if (!ast_strlen_zero(xfersound) && !ast_streamfile(transferer, xfersound, transferer->language)) {
- if (ast_waitstream(transferer, "") < 0) {
- ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
- }
- }
- ast_moh_stop(transferee);
- ast_autoservice_stop(transferee);
- ast_indicate(transferee, AST_CONTROL_UNHOLD);
- transferer->_softhangup = 0;
- return FEATURE_RETURN_SUCCESS;
- }
-
- res = ast_channel_make_compatible(transferee, newchan);
- if (res < 0) {
- ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", transferee->name, newchan->name);
- ast_hangup(newchan);
- return -1;
- }
-
-
- ast_moh_stop(transferee);
-
- if ((ast_autoservice_stop(transferee) < 0)
- || (ast_waitfordigit(transferee, 100) < 0)
- || (ast_waitfordigit(newchan, 100) < 0)
- || ast_check_hangup(transferee)
- || ast_check_hangup(newchan)) {
- ast_hangup(newchan);
- res = -1;
- return -1;
- }
-
- if ((xferchan = ast_channel_alloc(0))) {
- snprintf(xferchan->name, sizeof (xferchan->name), "Transfered/%s",transferee->name);
- /* Make formats okay */
- xferchan->readformat = transferee->readformat;
- xferchan->writeformat = transferee->writeformat;
- ast_channel_masquerade(xferchan, transferee);
- ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
- xferchan->_state = AST_STATE_UP;
- ast_clear_flag(xferchan, AST_FLAGS_ALL);
- xferchan->_softhangup = 0;
-
- if ((f = ast_read(xferchan))) {
- ast_frfree(f);
- f = NULL;
- }
-
- } else {
- ast_hangup(newchan);
- return -1;
- }
-
- newchan->_state = AST_STATE_UP;
- ast_clear_flag(newchan, AST_FLAGS_ALL);
- newchan->_softhangup = 0;
-
- tobj = malloc(sizeof(struct ast_bridge_thread_obj));
- if (tobj) {
- memset(tobj,0,sizeof(struct ast_bridge_thread_obj));
- tobj->chan = xferchan;
- tobj->peer = newchan;
- tobj->bconfig = *config;
-
- if (!ast_strlen_zero(xfersound) && !ast_streamfile(newchan, xfersound, newchan->language)) {
- if (ast_waitstream(newchan, "") < 0) {
- ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
- }
- }
- ast_bridge_call_thread_launch(tobj);
- } else {
- ast_log(LOG_WARNING, "Out of memory!\n");
- ast_hangup(xferchan);
- ast_hangup(newchan);
- }
- return -1;
-
- } else {
- ast_moh_stop(transferee);
- ast_autoservice_stop(transferee);
- ast_indicate(transferee, AST_CONTROL_UNHOLD);
- /* any reason besides user requested cancel and busy triggers the failed sound */
- if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY && !ast_strlen_zero(xferfailsound)) {
- res = ast_streamfile(transferer, xferfailsound, transferer->language);
- if (!res && (ast_waitstream(transferer, "") < 0)) {
- return -1;
- }
- }
- return FEATURE_RETURN_SUCCESS;
- }
- } else {
- ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
- ast_moh_stop(transferee);
- ast_autoservice_stop(transferee);
- ast_indicate(transferee, AST_CONTROL_UNHOLD);
- res = ast_streamfile(transferer, "beeperr", transferer->language);
- if (!res && (ast_waitstream(transferer, "") < 0)) {
- return -1;
- }
- }
- } else {
- ast_log(LOG_WARNING, "Did not read data.\n");
- res = ast_streamfile(transferer, "beeperr", transferer->language);
- if (ast_waitstream(transferer, "") < 0) {
- return -1;
- }
- }
- ast_moh_stop(transferee);
- ast_autoservice_stop(transferee);
- ast_indicate(transferee, AST_CONTROL_UNHOLD);
-
- return FEATURE_RETURN_SUCCESS;
-}
-
-
-/* add atxfer and automon as undefined so you can only use em if you configure them */
-#define FEATURES_COUNT (sizeof(builtin_features) / sizeof(builtin_features[0]))
-struct ast_call_feature builtin_features[] =
- {
- { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF },
- { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF },
- { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF },
- { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF },
-};
-
-
-static AST_LIST_HEAD(feature_list,ast_call_feature) feature_list;
-
-/* register new feature into feature_list*/
-void ast_register_feature(struct ast_call_feature *feature)
-{
- if (!feature) {
- ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
- return;
- }
-
- AST_LIST_LOCK(&feature_list);
- AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
- AST_LIST_UNLOCK(&feature_list);
-
- if (option_verbose >= 2)
- ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
-}
-
-/* unregister feature from feature_list */
-void ast_unregister_feature(struct ast_call_feature *feature)
-{
- if (!feature) return;
-
- AST_LIST_LOCK(&feature_list);
- AST_LIST_REMOVE(&feature_list,feature,feature_entry);
- AST_LIST_UNLOCK(&feature_list);
- free(feature);
-}
-
-static void ast_unregister_features(void)
-{
- struct ast_call_feature *feature;
-
- AST_LIST_LOCK(&feature_list);
- while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
- free(feature);
- AST_LIST_UNLOCK(&feature_list);
-}
-
-/* find a feature by name */
-static struct ast_call_feature *find_feature(char *name)
-{
- struct ast_call_feature *tmp;
-
- AST_LIST_LOCK(&feature_list);
- AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
- if (!strcasecmp(tmp->sname, name))
- break;
- }
- AST_LIST_UNLOCK(&feature_list);
-
- return tmp;
-}
-
-/* exec an app by feature */
-static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
-{
- struct ast_app *app;
- struct ast_call_feature *feature;
- int res;
-
- AST_LIST_LOCK(&feature_list);
- AST_LIST_TRAVERSE(&feature_list,feature,feature_entry) {
- if (!strcasecmp(feature->exten,code)) break;
- }
- AST_LIST_UNLOCK(&feature_list);
-
- if (!feature) { /* shouldn't ever happen! */
- ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
- return -1;
- }
-
- app = pbx_findapp(feature->app);
- if (app) {
- struct ast_channel *work = chan;
- if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLEE))
- work = peer;
- res = pbx_exec(work, app, feature->app_args, 1);
- if (res < 0)
- return res;
- } else {
- ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
- return -2;
- }
-
- return FEATURE_RETURN_SUCCESS;
-}
-
-static void unmap_features(void)
-{
- int x;
- for (x = 0; x < FEATURES_COUNT; x++)
- strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
-}
-
-static int remap_feature(const char *name, const char *value)
-{
- int x;
- int res = -1;
- for (x = 0; x < FEATURES_COUNT; x++) {
- if (!strcasecmp(name, builtin_features[x].sname)) {
- ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Remapping feature %s (%s) to sequence '%s'\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
- res = 0;
- } else if (!strcmp(value, builtin_features[x].exten))
- ast_log(LOG_WARNING, "Sequence '%s' already mapped to function %s (%s) while assigning to %s\n", value, builtin_features[x].fname, builtin_features[x].sname, name);
- }
- return res;
-}
-
-static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
-{
- int x;
- struct ast_flags features;
- int res = FEATURE_RETURN_PASSDIGITS;
- struct ast_call_feature *feature;
- char *dynamic_features=pbx_builtin_getvar_helper(chan,"DYNAMIC_FEATURES");
-
- if (sense == FEATURE_SENSE_CHAN)
- ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
- else
- ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
- ast_log(LOG_DEBUG, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features.flags);
-
- for (x=0; x < FEATURES_COUNT; x++) {
- if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
- !ast_strlen_zero(builtin_features[x].exten)) {
- /* Feature is up for consideration */
- if (!strcmp(builtin_features[x].exten, code)) {
- res = builtin_features[x].operation(chan, peer, config, code, sense);
- break;
- } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
- if (res == FEATURE_RETURN_PASSDIGITS)
- res = FEATURE_RETURN_STOREDIGITS;
- }
- }
- }
-
-
- if (!ast_strlen_zero(dynamic_features)) {
- char *tmp = ast_strdupa(dynamic_features);
- char *tok;
-
- if (!tmp)
- return res;
-
- while ((tok = strsep(&tmp, "#")) != NULL) {
- feature = find_feature(tok);
-
- if (feature) {
- /* Feature is up for consideration */
- if (!strcmp(feature->exten, code)) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 " Feature Found: %s exten: %s\n",feature->sname, tok);
- res = feature->operation(chan, peer, config, code, sense);
- break;
- } else if (!strncmp(feature->exten, code, strlen(code))) {
- res = FEATURE_RETURN_STOREDIGITS;
- }
- }
- }
- }
-
- return res;
-}
-
-static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
-{
- int x;
-
- ast_clear_flag(config, AST_FLAGS_ALL);
- for (x = 0; x < FEATURES_COUNT; x++) {
- if (ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF)) {
- if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
- ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
-
- if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
- ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
- }
- }
-
- if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
- char *dynamic_features;
-
- dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
-
- if (dynamic_features) {
- char *tmp = ast_strdupa(dynamic_features);
- char *tok;
- struct ast_call_feature *feature;
-
- if (!tmp) {
- return;
- }
-
- /* while we have a feature */
- while (NULL != (tok = strsep(&tmp, "#"))) {
- if ((feature = find_feature(tok))) {
- if (ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
- if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLER))
- ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
- if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLEE))
- ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
- }
- }
- }
- }
- }
-}
-
-
-static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name)
-{
- int state = 0;
- int cause = 0;
- int to;
- struct ast_channel *chan;
- struct ast_channel *monitor_chans[2];
- struct ast_channel *active_channel;
- struct ast_frame *f = NULL;
- int res = 0, ready = 0;
-
- if ((chan = ast_request(type, format, data, &cause))) {
- ast_set_callerid(chan, cid_num, cid_name, cid_num);
- ast_channel_inherit_variables(caller, chan);
- if (!ast_call(chan, data, timeout)) {
- struct timeval started;
- int x, len = 0;
- char *disconnect_code = NULL, *dialed_code = NULL;
-
- ast_indicate(caller, AST_CONTROL_RINGING);
- /* support dialing of the featuremap disconnect code while performing an attended tranfer */
- for (x=0; x < FEATURES_COUNT; x++) {
- if (strcasecmp(builtin_features[x].sname, "disconnect"))
- continue;
-
- disconnect_code = builtin_features[x].exten;
- len = strlen(disconnect_code) + 1;
- dialed_code = alloca(len);
- memset(dialed_code, 0, len);
- break;
- }
- x = 0;
- started = ast_tvnow();
- to = timeout;
- while (!ast_check_hangup(caller) && timeout && (chan->_state != AST_STATE_UP)) {
- monitor_chans[0] = caller;
- monitor_chans[1] = chan;
- active_channel = ast_waitfor_n(monitor_chans, 2, &to);
-
- /* see if the timeout has been violated */
- if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
- state = AST_CONTROL_UNHOLD;
- ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
- break; /*doh! timeout*/
- }
-
- if (!active_channel) {
- continue;
- }
-
- if (chan && (chan == active_channel)){
- f = ast_read(chan);
- if (f == NULL) { /*doh! where'd he go?*/
- state = AST_CONTROL_HANGUP;
- res = 0;
- break;
- }
-
- if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
- if (f->subclass == AST_CONTROL_RINGING) {
- state = f->subclass;
- if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", chan->name);
- ast_indicate(caller, AST_CONTROL_RINGING);
- } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
- state = f->subclass;
- ast_frfree(f);
- f = NULL;
- break;
- } else if (f->subclass == AST_CONTROL_ANSWER) {
- /* This is what we are hoping for */
- state = f->subclass;
- ast_frfree(f);
- f = NULL;
- ready=1;
- break;
- } else {
- ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
- }
- /* else who cares */
- }
-
- } else if (caller && (active_channel == caller)) {
- f = ast_read(caller);
- if (f == NULL) { /*doh! where'd he go?*/
- if (caller->_softhangup && !chan->_softhangup) {
- /* make this a blind transfer */
- ready = 1;
- break;
- }
- state = AST_CONTROL_HANGUP;
- res = 0;
- break;
- }
-
- if (f->frametype == AST_FRAME_DTMF) {
- dialed_code[x++] = f->subclass;
- dialed_code[x] = '\0';
- if (strlen(dialed_code) == len) {
- x = 0;
- } else if (x && strncmp(dialed_code, disconnect_code, x)) {
- x = 0;
- dialed_code[x] = '\0';
- }
- if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
- /* Caller Canceled the call */
- state = AST_CONTROL_UNHOLD;
- ast_frfree(f);
- f = NULL;
- break;
- }
- }
- }
- if (f) {
- ast_frfree(f);
- }
- }
- } else
- ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
- } else {
- ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
- switch(cause) {
- case AST_CAUSE_BUSY:
- state = AST_CONTROL_BUSY;
- break;
- case AST_CAUSE_CONGESTION:
- state = AST_CONTROL_CONGESTION;
- break;
- }
- }
-
- ast_indicate(caller, -1);
- if (chan && ready) {
- if (chan->_state == AST_STATE_UP)
- state = AST_CONTROL_ANSWER;
- res = 0;
- } else if(chan) {
- res = -1;
- ast_hangup(chan);
- chan = NULL;
- } else {
- res = -1;
- }
-
- if (outstate)
- *outstate = state;
-
- if (chan && res <= 0) {
- if (!chan->cdr) {
- chan->cdr = ast_cdr_alloc();
- }
- if (chan->cdr) {
- char tmp[256];
- ast_cdr_init(chan->cdr, chan);
- snprintf(tmp, 256, "%s/%s", type, (char *)data);
- ast_cdr_setapp(chan->cdr,"Dial",tmp);
- ast_cdr_update(chan);
- ast_cdr_start(chan->cdr);
- ast_cdr_end(chan->cdr);
- /* If the cause wasn't handled properly */
- if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
- ast_cdr_failed(chan->cdr);
- } else {
- ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
- }
- }
-
- return chan;
-}
-
-int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
-{
- /* Copy voice back and forth between the two channels. Give the peer
- the ability to transfer calls with '#<extension' syntax. */
- struct ast_frame *f;
- struct ast_channel *who;
- char chan_featurecode[FEATURE_MAX_LEN + 1]="";
- char peer_featurecode[FEATURE_MAX_LEN + 1]="";
- int res;
- int diff;
- int hasfeatures=0;
- int hadfeatures=0;
- struct ast_option_header *aoh;
- struct timeval start = { 0 , 0 };
- struct ast_bridge_config backup_config;
- char *monitor_exec;
-
- memset(&backup_config, 0, sizeof(backup_config));
-
- config->start_time = ast_tvnow();
-
- if (chan && peer) {
- pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
- pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
- } else if (chan)
- pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
-
- if (monitor_ok) {
- if (!monitor_app) {
- if (!(monitor_app = pbx_findapp("Monitor")))
- monitor_ok=0;
- }
- if (monitor_app) {
- if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
- pbx_exec(chan, monitor_app, monitor_exec, 1);
- else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
- pbx_exec(peer, monitor_app, monitor_exec, 1);
- }
- }
-
- set_config_flags(chan, peer, config);
- config->firstpass = 1;
-
- /* Answer if need be */
- if (ast_answer(chan))
- return -1;
- peer->appl = "Bridged Call";
- peer->data = chan->name;
-
- /* copy the userfield from the B-leg to A-leg if applicable */
- if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
- char tmp[256];
- if (!ast_strlen_zero(chan->cdr->userfield)) {
- snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
- ast_cdr_appenduserfield(chan, tmp);
- } else
- ast_cdr_setuserfield(chan, peer->cdr->userfield);
- /* free the peer's cdr without ast_cdr_free complaining */
- free(peer->cdr);
- peer->cdr = NULL;
- }
- for (;;) {
- if (config->feature_timer)
- start = ast_tvnow();
-
- res = ast_channel_bridge(chan, peer, config, &f, &who);
-
- if (config->feature_timer) {
- /* Update time limit for next pass */
- diff = ast_tvdiff_ms(ast_tvnow(), start);
- config->feature_timer -= diff;
- if (hasfeatures) {
- /* Running on backup config, meaning a feature might be being
- activated, but that's no excuse to keep things going
- indefinitely! */
- if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
- ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
- config->feature_timer = 0;
- who = chan;
- if (f)
- ast_frfree(f);
- f = NULL;
- res = 0;
- } else if (config->feature_timer <= 0) {
- /* Not *really* out of time, just out of time for
- digits to come in for features. */
- ast_log(LOG_DEBUG, "Timed out for feature!\n");
- if (!ast_strlen_zero(peer_featurecode)) {
- ast_dtmf_stream(chan, peer, peer_featurecode, 0);
- memset(peer_featurecode, 0, sizeof(peer_featurecode));
- }
- if (!ast_strlen_zero(chan_featurecode)) {
- ast_dtmf_stream(peer, chan, chan_featurecode, 0);
- memset(chan_featurecode, 0, sizeof(chan_featurecode));
- }
- if (f)
- ast_frfree(f);
- hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
- if (!hasfeatures) {
- /* Restore original (possibly time modified) bridge config */
- memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
- memset(&backup_config, 0, sizeof(backup_config));
- }
- hadfeatures = hasfeatures;
- /* Continue as we were */
- continue;
- }
- } else {
- if (config->feature_timer <=0) {
- /* We ran out of time */
- config->feature_timer = 0;
- who = chan;
- if (f)
- ast_frfree(f);
- f = NULL;
- res = 0;
- }
- }
- }
- if (res < 0) {
- ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
- return -1;
- }
-
- if (!f || ((f->frametype == AST_FRAME_CONTROL) && ((f->subclass == AST_CONTROL_HANGUP) || (f->subclass == AST_CONTROL_BUSY) ||
- (f->subclass == AST_CONTROL_CONGESTION)))) {
- res = -1;
- break;
- }
- if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RINGING)) {
- if (who == chan)
- ast_indicate(peer, AST_CONTROL_RINGING);
- else
- ast_indicate(chan, AST_CONTROL_RINGING);
- }
- if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == -1)) {
- if (who == chan)
- ast_indicate(peer, -1);
- else
- ast_indicate(chan, -1);
- }
- if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_FLASH)) {
- if (who == chan)
- ast_indicate(peer, AST_CONTROL_FLASH);
- else
- ast_indicate(chan, AST_CONTROL_FLASH);
- }
- if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_OPTION)) {
- aoh = f->data;
- /* Forward option Requests */
- if (aoh && (aoh->flag == AST_OPTION_FLAG_REQUEST)) {
- if (who == chan)
- ast_channel_setoption(peer, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
- else
- ast_channel_setoption(chan, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
- }
- }
- /* check for '*', if we find it it's time to disconnect */
- if (f && (f->frametype == AST_FRAME_DTMF)) {
- char *featurecode;
- int sense;
- struct ast_channel *other;
-
- hadfeatures = hasfeatures;
- /* This cannot overrun because the longest feature is one shorter than our buffer */
- if (who == chan) {
- other = peer;
- sense = FEATURE_SENSE_CHAN;
- featurecode = chan_featurecode;
- } else {
- other = chan;
- sense = FEATURE_SENSE_PEER;
- featurecode = peer_featurecode;
- }
- featurecode[strlen(featurecode)] = f->subclass;
- config->feature_timer = backup_config.feature_timer;
- res = ast_feature_interpret(chan, peer, config, featurecode, sense);
- switch(res) {
- case FEATURE_RETURN_PASSDIGITS:
- ast_dtmf_stream(other, who, featurecode, 0);
- /* Fall through */
- case FEATURE_RETURN_SUCCESS:
- memset(featurecode, 0, sizeof(chan_featurecode));
- break;
- }
- if (res >= FEATURE_RETURN_PASSDIGITS) {
- res = 0;
- } else {
- ast_frfree(f);
- break;
- }
- hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
- if (hadfeatures && !hasfeatures) {
- /* Restore backup */
- memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
- memset(&backup_config, 0, sizeof(struct ast_bridge_config));
- } else if (hasfeatures) {
- if (!hadfeatures) {
- /* Backup configuration */
- memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
- /* Setup temporary config options */
- config->play_warning = 0;
- ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
- ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
- config->warning_freq = 0;
- config->warning_sound = NULL;
- config->end_sound = NULL;
- config->start_sound = NULL;
- config->firstpass = 0;
- }
- config->feature_timer = featuredigittimeout;
- ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer);
- }
- }
- if (f)
- ast_frfree(f);
- }
- return res;
-}
-
-static void *do_parking_thread(void *ignore)
-{
- int ms, tms, max;
- struct parkeduser *pu, *pl, *pt = NULL;
- struct timeval tv;
- struct ast_frame *f;
- char exten[AST_MAX_EXTENSION];
- char *peername,*cp;
- char returnexten[AST_MAX_EXTENSION];
- struct ast_context *con;
- int x;
- fd_set rfds, efds;
- fd_set nrfds, nefds;
- FD_ZERO(&rfds);
- FD_ZERO(&efds);
-
- for (;;) {
- ms = -1;
- max = -1;
- ast_mutex_lock(&parking_lock);
- pl = NULL;
- pu = parkinglot;
- FD_ZERO(&nrfds);
- FD_ZERO(&nefds);
- while(pu) {
- if (pu->notquiteyet) {
- /* Pretend this one isn't here yet */
- pl = pu;
- pu = pu->next;
- continue;
- }
- tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
- if (tms > pu->parkingtime) {
- /* Stop music on hold */
- ast_moh_stop(pu->chan);
- ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
- /* Get chan, exten from derived kludge */
- if (pu->peername[0]) {
- peername = ast_strdupa(pu->peername);
- cp = strrchr(peername, '-');
- if (cp)
- *cp = 0;
- con = ast_context_find(parking_con_dial);
- if (!con) {
- con = ast_context_create(NULL, parking_con_dial, registrar);
- if (!con) {
- ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
- }
- }
- if (con) {
- snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
- ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), FREE, registrar);
- }
- ast_copy_string(pu->chan->exten, peername, sizeof(pu->chan->exten));
- ast_copy_string(pu->chan->context, parking_con_dial, sizeof(pu->chan->context));
- pu->chan->priority = 1;
-
- } else {
- /* They've been waiting too long, send them back to where they came. Theoretically they
- should have their original extensions and such, but we copy to be on the safe side */
- ast_copy_string(pu->chan->exten, pu->exten, sizeof(pu->chan->exten));
- ast_copy_string(pu->chan->context, pu->context, sizeof(pu->chan->context));
- pu->chan->priority = pu->priority;
- }
-
- manager_event(EVENT_FLAG_CALL, "ParkedCallTimeOut",
- "Exten: %d\r\n"
- "Channel: %s\r\n"
- "CallerID: %s\r\n"
- "CallerIDName: %s\r\n"
- ,pu->parkingnum, pu->chan->name
- ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
- ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
- );
-
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Timeout for %s parked on %d. Returning to %s,%s,%d\n", pu->chan->name, pu->parkingnum, pu->chan->context, pu->chan->exten, pu->chan->priority);
- /* Start up the PBX, or hang them up */
- if (ast_pbx_start(pu->chan)) {
- ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
- ast_hangup(pu->chan);
- }
- /* And take them out of the parking lot */
- if (pl)
- pl->next = pu->next;
- else
- parkinglot = pu->next;
- pt = pu;
- pu = pu->next;
- con = ast_context_find(parking_con);
- if (con) {
- snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
- if (ast_context_remove_extension2(con, exten, 1, NULL))
- ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
- } else
- ast_log(LOG_WARNING, "Whoa, no parking context?\n");
- free(pt);
- } else {
- for (x = 0; x < AST_MAX_FDS; x++) {
- if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
- if (FD_ISSET(pu->chan->fds[x], &efds))
- ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
- else
- ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
- pu->chan->fdno = x;
- /* See if they need servicing */
- f = ast_read(pu->chan);
- if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
- if (f)
- ast_frfree(f);
- manager_event(EVENT_FLAG_CALL, "ParkedCallGiveUp",
- "Exten: %d\r\n"
- "Channel: %s\r\n"
- "CallerID: %s\r\n"
- "CallerIDName: %s\r\n"
- ,pu->parkingnum, pu->chan->name
- ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
- ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
- );
-
- /* There's a problem, hang them up*/
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", pu->chan->name);
- ast_hangup(pu->chan);
- /* And take them out of the parking lot */
- if (pl)
- pl->next = pu->next;
- else
- parkinglot = pu->next;
- pt = pu;
- pu = pu->next;
- con = ast_context_find(parking_con);
- if (con) {
- snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
- if (ast_context_remove_extension2(con, exten, 1, NULL))
- ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
- } else
- ast_log(LOG_WARNING, "Whoa, no parking context?\n");
- free(pt);
- break;
- } else {
- /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
- ast_frfree(f);
- if (pu->moh_trys < 3 && !pu->chan->generatordata) {
- ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source. Restarting.\n");
- ast_moh_start(pu->chan, NULL);
- pu->moh_trys++;
- }
- goto std; /* XXX Ick: jumping into an else statement??? XXX */
- }
- }
- }
- if (x >= AST_MAX_FDS) {
-std: for (x=0; x<AST_MAX_FDS; x++) {
- /* Keep this one for next one */
- if (pu->chan->fds[x] > -1) {
- FD_SET(pu->chan->fds[x], &nrfds);
- FD_SET(pu->chan->fds[x], &nefds);
- if (pu->chan->fds[x] > max)
- max = pu->chan->fds[x];
- }
- }
- /* Keep track of our longest wait */
- if ((tms < ms) || (ms < 0))
- ms = tms;
- pl = pu;
- pu = pu->next;
- }
- }
- }
- ast_mutex_unlock(&parking_lock);
- rfds = nrfds;
- efds = nefds;
- tv = ast_samp2tv(ms, 1000);
- /* Wait for something to happen */
- ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
- pthread_testcancel();
- }
- return NULL; /* Never reached */
-}
-
-static int park_call_exec(struct ast_channel *chan, void *data)
-{
- /* Data is unused at the moment but could contain a parking
- lot context eventually */
- int res=0;
- struct localuser *u;
- LOCAL_USER_ADD(u);
- /* Setup the exten/priority to be s/1 since we don't know
- where this call should return */
- strcpy(chan->exten, "s");
- chan->priority = 1;
- if (chan->_state != AST_STATE_UP)
- res = ast_answer(chan);
- if (!res)
- res = ast_safe_sleep(chan, 1000);
- if (!res)
- res = ast_park_call(chan, chan, 0, NULL);
- LOCAL_USER_REMOVE(u);
- if (!res)
- res = AST_PBX_KEEPALIVE;
- return res;
-}
-
-static int park_exec(struct ast_channel *chan, void *data)
-{
- int res=0;
- struct localuser *u;
- struct ast_channel *peer=NULL;
- struct parkeduser *pu, *pl=NULL;
- char exten[AST_MAX_EXTENSION];
- struct ast_context *con;
- int park;
- int dres;
- struct ast_bridge_config config;
-
- if (!data) {
- ast_log(LOG_WARNING, "Park requires an argument (extension number)\n");
- return -1;
- }
- LOCAL_USER_ADD(u);
- park = atoi((char *)data);
- ast_mutex_lock(&parking_lock);
- pu = parkinglot;
- while(pu) {
- if (pu->parkingnum == park) {
- if (pl)
- pl->next = pu->next;
- else
- parkinglot = pu->next;
- break;
- }
- pl = pu;
- pu = pu->next;
- }
- ast_mutex_unlock(&parking_lock);
- if (pu) {
- peer = pu->chan;
- con = ast_context_find(parking_con);
- if (con) {
- snprintf(exten, sizeof(exten), "%d", pu->parkingnum);
- if (ast_context_remove_extension2(con, exten, 1, NULL))
- ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
- } else
- ast_log(LOG_WARNING, "Whoa, no parking context?\n");
-
- manager_event(EVENT_FLAG_CALL, "UnParkedCall",
- "Exten: %d\r\n"
- "Channel: %s\r\n"
- "From: %s\r\n"
- "CallerID: %s\r\n"
- "CallerIDName: %s\r\n"
- ,pu->parkingnum, pu->chan->name, chan->name
- ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
- ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
- );
-
- free(pu);
- }
- /* JK02: it helps to answer the channel if not already up */
- if (chan->_state != AST_STATE_UP) {
- ast_answer(chan);
- }
-
- if (peer) {
- /* Play a courtesy beep in the calling channel to prefix the bridge connecting */
- if (!ast_strlen_zero(courtesytone)) {
- if (!ast_streamfile(chan, courtesytone, chan->language)) {
- if (ast_waitstream(chan, "") < 0) {
- ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
- ast_hangup(peer);
- return -1;
- }
- }
- }
-
- ast_moh_stop(peer);
- ast_indicate(peer, AST_CONTROL_UNHOLD);
- res = ast_channel_make_compatible(chan, peer);
- if (res < 0) {
- ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
- ast_hangup(peer);
- return -1;
- }
- /* This runs sorta backwards, since we give the incoming channel control, as if it
- were the person called. */
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
-
- memset(&config, 0, sizeof(struct ast_bridge_config));
- ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
- ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
- config.timelimit = 0;
- config.play_warning = 0;
- config.warning_freq = 0;
- config.warning_sound=NULL;
- res = ast_bridge_call(chan, peer, &config);
-
- /* Simulate the PBX hanging up */
- if (res != AST_PBX_NO_HANGUP_PEER)
- ast_hangup(peer);
- return res;
- } else {
- /* XXX Play a message XXX */
- dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
- if (!dres)
- dres = ast_waitstream(chan, "");
- else {
- ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
- dres = 0;
- }
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
- res = -1;
- }
- LOCAL_USER_REMOVE(u);
- return res;
-}
-
-static int handle_showfeatures(int fd, int argc, char *argv[])
-{
- int i;
- int fcount;
- struct ast_call_feature *feature;
- char format[] = "%-25s %-7s %-7s\n";
-
- ast_cli(fd, format, "Builtin Feature", "Default", "Current");
- ast_cli(fd, format, "---------------", "-------", "-------");
-
- ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext()); /* default hardcoded above, so we'll hardcode it here */
-
- fcount = sizeof(builtin_features) / sizeof(builtin_features[0]);
-
- for (i = 0; i < fcount; i++)
- {
- ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
- }
- ast_cli(fd, "\n");
- ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
- ast_cli(fd, format, "---------------", "-------", "-------");
- if (AST_LIST_EMPTY(&feature_list)) {
- ast_cli(fd, "(none)\n");
- }
- else {
- AST_LIST_LOCK(&feature_list);
- AST_LIST_TRAVERSE(&feature_list, feature, feature_entry) {
- ast_cli(fd, format, feature->sname, "no def", feature->exten);
- }
- AST_LIST_UNLOCK(&feature_list);
- }
- ast_cli(fd, "\nCall parking\n");
- ast_cli(fd, "------------\n");
- ast_cli(fd,"%-20s: %s\n", "Parking extension", parking_ext);
- ast_cli(fd,"%-20s: %s\n", "Parking context", parking_con);
- ast_cli(fd,"%-20s: %d-%d\n", "Parked call extensions", parking_start, parking_stop);
- ast_cli(fd,"\n");
-
- return RESULT_SUCCESS;
-}
-
-static char showfeatures_help[] =
-"Usage: show features\n"
-" Lists currently configured features.\n";
-
-static struct ast_cli_entry showfeatures =
-{ { "show", "features", NULL }, handle_showfeatures, "Lists configured features", showfeatures_help };
-
-static int handle_parkedcalls(int fd, int argc, char *argv[])
-{
- struct parkeduser *cur;
- int numparked = 0;
-
- ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
- , "Context", "Extension", "Pri", "Timeout");
-
- ast_mutex_lock(&parking_lock);
-
- cur = parkinglot;
- while(cur) {
- ast_cli(fd, "%4d %25s (%-15s %-12s %-4d) %6lds\n"
- ,cur->parkingnum, cur->chan->name, cur->context, cur->exten
- ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
-
- cur = cur->next;
- numparked++;
- }
- ast_cli(fd, "%d parked call%s.\n", numparked, (numparked != 1) ? "s" : "");
-
- ast_mutex_unlock(&parking_lock);
-
- return RESULT_SUCCESS;
-}
-
-static char showparked_help[] =
-"Usage: show parkedcalls\n"
-" Lists currently parked calls.\n";
-
-static struct ast_cli_entry showparked =
-{ { "show", "parkedcalls", NULL }, handle_parkedcalls, "Lists parked calls", showparked_help };
-
-/* Dump lot status */
-static int manager_parking_status( struct mansession *s, struct message *m )
-{
- struct parkeduser *cur;
- char *id = astman_get_header(m,"ActionID");
- char idText[256] = "";
-
- if (!ast_strlen_zero(id))
- snprintf(idText,256,"ActionID: %s\r\n",id);
-
- astman_send_ack(s, m, "Parked calls will follow");
-
- ast_mutex_lock(&parking_lock);
-
- cur=parkinglot;
- while(cur) {
- ast_cli(s->fd, "Event: ParkedCall\r\n"
- "Exten: %d\r\n"
- "Channel: %s\r\n"
- "Timeout: %ld\r\n"
- "CallerID: %s\r\n"
- "CallerIDName: %s\r\n"
- "%s"
- "\r\n"
- ,cur->parkingnum, cur->chan->name
- ,(long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL)
- ,(cur->chan->cid.cid_num ? cur->chan->cid.cid_num : "")
- ,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : "")
- ,idText);
-
- cur = cur->next;
- }
-
- ast_cli(s->fd,
- "Event: ParkedCallsComplete\r\n"
- "%s"
- "\r\n",idText);
-
- ast_mutex_unlock(&parking_lock);
-
- return RESULT_SUCCESS;
-}
-
-
-int ast_pickup_call(struct ast_channel *chan)
-{
- struct ast_channel *cur = NULL;
- int res = -1;
-
- while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
- if (!cur->pbx &&
- (cur != chan) &&
- (chan->pickupgroup & cur->callgroup) &&
- ((cur->_state == AST_STATE_RINGING) ||
- (cur->_state == AST_STATE_RING))) {
- break;
- }
- ast_mutex_unlock(&cur->lock);
- }
- if (cur) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
- res = ast_answer(chan);
- if (res)
- ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
- res = ast_queue_control(chan, AST_CONTROL_ANSWER);
- if (res)
- ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
- res = ast_channel_masquerade(cur, chan);
- if (res)
- ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */
- ast_mutex_unlock(&cur->lock);
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "No call pickup possible...\n");
- }
- return res;
-}
-
-static int load_config(void)
-{
- int start = 0, end = 0;
- struct ast_context *con = NULL;
- struct ast_config *cfg = NULL;
- struct ast_variable *var = NULL;
- char old_parking_ext[AST_MAX_EXTENSION];
- char old_parking_con[AST_MAX_EXTENSION] = "";
-
- if (!ast_strlen_zero(parking_con)) {
- strcpy(old_parking_ext, parking_ext);
- strcpy(old_parking_con, parking_con);
- }
-
- /* Reset to defaults */
- strcpy(parking_con, "parkedcalls");
- strcpy(parking_con_dial, "park-dial");
- strcpy(parking_ext, "700");
- strcpy(pickup_ext, "*8");
- courtesytone[0] = '\0';
- strcpy(xfersound, "beep");
- strcpy(xferfailsound, "pbx-invalid");
- parking_start = 701;
- parking_stop = 750;
- parkfindnext = 0;
-
- transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
- featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
-
- cfg = ast_config_load("features.conf");
- if (!cfg) {
- cfg = ast_config_load("parking.conf");
- if (cfg)
- ast_log(LOG_NOTICE, "parking.conf is deprecated in favor of 'features.conf'. Please rename it.\n");
- }
- if (cfg) {
- var = ast_variable_browse(cfg, "general");
- while(var) {
- if (!strcasecmp(var->name, "parkext")) {
- ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
- } else if (!strcasecmp(var->name, "context")) {
- ast_copy_string(parking_con, var->value, sizeof(parking_con));
- } else if (!strcasecmp(var->name, "parkingtime")) {
- if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
- ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
- parkingtime = DEFAULT_PARK_TIME;
- } else
- parkingtime = parkingtime * 1000;
- } else if (!strcasecmp(var->name, "parkpos")) {
- if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
- ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers at line %d of parking.conf\n", var->lineno);
- } else {
- parking_start = start;
- parking_stop = end;
- }
- } else if (!strcasecmp(var->name, "findslot")) {
- parkfindnext = (!strcasecmp(var->value, "next"));
- } else if (!strcasecmp(var->name, "adsipark")) {
- adsipark = ast_true(var->value);
- } else if (!strcasecmp(var->name, "transferdigittimeout")) {
- if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
- ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
- transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
- } else
- transferdigittimeout = transferdigittimeout * 1000;
- } else if (!strcasecmp(var->name, "featuredigittimeout")) {
- if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
- ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
- featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
- }
- } else if (!strcasecmp(var->name, "courtesytone")) {
- ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
- } else if (!strcasecmp(var->name, "xfersound")) {
- ast_copy_string(xfersound, var->value, sizeof(xfersound));
- } else if (!strcasecmp(var->name, "xferfailsound")) {
- ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
- } else if (!strcasecmp(var->name, "pickupexten")) {
- ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
- }
- var = var->next;
- }
-
- unmap_features();
- var = ast_variable_browse(cfg, "featuremap");
- while(var) {
- if (remap_feature(var->name, var->value))
- ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
- var = var->next;
- }
-
- /* Map a key combination to an application*/
- ast_unregister_features();
- var = ast_variable_browse(cfg, "applicationmap");
- while(var) {
- char *tmp_val=strdup(var->value);
- char *exten, *party=NULL, *app=NULL, *app_args=NULL;
-
- if (!tmp_val) {
- ast_log(LOG_ERROR, "res_features: strdup failed");
- continue;
- }
-
-
- exten=strsep(&tmp_val,",");
- if (exten) party=strsep(&tmp_val,",");
- if (party) app=strsep(&tmp_val,",");
-
- if (app) app_args=strsep(&tmp_val,",");
-
- if (!(app && strlen(app)) || !(exten && strlen(exten)) || !(party && strlen(party)) || !(var->name && strlen(var->name))) {
- ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",app,exten,party,var->name);
- free(tmp_val);
- var = var->next;
- continue;
- }
-
- {
- struct ast_call_feature *feature=find_feature(var->name);
- int mallocd=0;
-
- if (!feature) {
- feature=malloc(sizeof(struct ast_call_feature));
- mallocd=1;
- }
- if (!feature) {
- ast_log(LOG_NOTICE, "Malloc failed at feature mapping\n");
- free(tmp_val);
- var = var->next;
- continue;
- }
-
- memset(feature,0,sizeof(struct ast_call_feature));
- ast_copy_string(feature->sname,var->name,FEATURE_SNAME_LEN);
- ast_copy_string(feature->app,app,FEATURE_APP_LEN);
- ast_copy_string(feature->exten, exten,FEATURE_EXTEN_LEN);
- free(tmp_val);
-
- if (app_args)
- ast_copy_string(feature->app_args,app_args,FEATURE_APP_ARGS_LEN);
-
- ast_copy_string(feature->exten, exten,sizeof(feature->exten));
- feature->operation=feature_exec_app;
- ast_set_flag(feature,AST_FEATURE_FLAG_NEEDSDTMF);
-
- if (!strcasecmp(party,"caller"))
- ast_set_flag(feature,AST_FEATURE_FLAG_CALLER);
- else if (!strcasecmp(party, "callee"))
- ast_set_flag(feature,AST_FEATURE_FLAG_CALLEE);
- else {
- ast_log(LOG_NOTICE, "Invalid party specification for feature '%s', must be caller, or callee\n", var->name);
- var = var->next;
- continue;
- }
-
- ast_register_feature(feature);
-
- if (option_verbose >=1) ast_verbose(VERBOSE_PREFIX_2 "Mapping Feature '%s' to app '%s' with code '%s'\n", var->name, app, exten);
- }
- var = var->next;
- }
- }
- ast_config_destroy(cfg);
-
- /* Remove the old parking extension */
- if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con))) {
- ast_context_remove_extension2(con, old_parking_ext, 1, registrar);
- ast_log(LOG_DEBUG, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
- }
-
- if (!(con = ast_context_find(parking_con))) {
- if (!(con = ast_context_create(NULL, parking_con, registrar))) {
- ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
- return -1;
- }
- }
- return ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, strdup(""), FREE, registrar);
-}
-
-int reload(void) {
- return load_config();
-}
-
-int load_module(void)
-{
- int res;
-
- AST_LIST_HEAD_INIT(&feature_list);
- memset(parking_ext, 0, sizeof(parking_ext));
- memset(parking_con, 0, sizeof(parking_con));
-
- if ((res = load_config()))
- return res;
- ast_cli_register(&showparked);
- ast_cli_register(&showfeatures);
- ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
- res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
- if (!res)
- res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
- if (!res) {
- ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
- }
- return res;
-}
-
-
-int unload_module(void)
-{
- STANDARD_HANGUP_LOCALUSERS;
-
- ast_manager_unregister("ParkedCalls");
- ast_cli_unregister(&showfeatures);
- ast_cli_unregister(&showparked);
- ast_unregister_application(parkcall);
- return ast_unregister_application(parkedcall);
-}
-
-char *description(void)
-{
- return "Call Features Resource";
-}
-
-int usecount(void)
-{
- /* Never allow parking to be unloaded because it will
- unresolve needed symbols in the dialer */
-#if 0
- int res;
- STANDARD_USECOUNT(res);
- return res;
-#else
- return 1;
-#endif
-}
-
-char *key()
-{
- return ASTERISK_GPL_KEY;
-}
diff --git a/1.2-netsec/res/res_indications.c b/1.2-netsec/res/res_indications.c
deleted file mode 100644
index 65ac3a9ba..000000000
--- a/1.2-netsec/res/res_indications.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2002, Pauline Middelink
- *
- *
- * 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 res_indications.c
- *
- * \brief Load the indications
- *
- * \author Pauline Middelink <middelink@polyware.nl>
- *
- * Load the country specific dialtones into the asterisk PBX.
- */
-
-#include <unistd.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/lock.h"
-#include "asterisk/file.h"
-#include "asterisk/cli.h"
-#include "asterisk/logger.h"
-#include "asterisk/config.h"
-#include "asterisk/channel.h"
-#include "asterisk/pbx.h"
-#include "asterisk/module.h"
-#include "asterisk/translate.h"
-#include "asterisk/indications.h"
-
-
-/* Globals */
-static const char dtext[] = "Indications Configuration";
-static const char config[] = "indications.conf";
-
-/*
- * Help for commands provided by this module ...
- */
-static char help_add_indication[] =
-"Usage: indication add <country> <indication> \"<tonelist>\"\n"
-" Add the given indication to the country.\n";
-
-static char help_remove_indication[] =
-"Usage: indication remove <country> <indication>\n"
-" Remove the given indication from the country.\n";
-
-static char help_show_indications[] =
-"Usage: show indications [<country> ...]\n"
-" Show either a condensed for of all country/indications, or the\n"
-" indications for the specified countries.\n";
-
-char *playtones_desc=
-"PlayTones(arg): Plays a tone list. Execution will continue with the next step immediately,\n"
-"while the tones continue to play.\n"
-"Arg is either the tone name defined in the indications.conf configuration file, or a directly\n"
-"specified list of frequencies and durations.\n"
-"See the sample indications.conf for a description of the specification of a tonelist.\n\n"
-"Use the StopPlayTones application to stop the tones playing. \n";
-
-/*
- * Implementation of functions provided by this module
- */
-
-/*
- * ADD INDICATION command stuff
- */
-static int handle_add_indication(int fd, int argc, char *argv[])
-{
- struct tone_zone *tz;
- int created_country = 0;
- if (argc != 5) return RESULT_SHOWUSAGE;
-
- tz = ast_get_indication_zone(argv[2]);
- if (!tz) {
- /* country does not exist, create it */
- ast_log(LOG_NOTICE, "Country '%s' does not exist, creating it.\n",argv[2]);
-
- tz = malloc(sizeof(struct tone_zone));
- if (!tz) {
- ast_log(LOG_WARNING, "Out of memory\n");
- return -1;
- }
- memset(tz,0,sizeof(struct tone_zone));
- ast_copy_string(tz->country,argv[2],sizeof(tz->country));
- if (ast_register_indication_country(tz)) {
- ast_log(LOG_WARNING, "Unable to register new country\n");
- free(tz);
- return -1;
- }
- created_country = 1;
- }
- if (ast_register_indication(tz,argv[3],argv[4])) {
- ast_log(LOG_WARNING, "Unable to register indication %s/%s\n",argv[2],argv[3]);
- if (created_country)
- ast_unregister_indication_country(argv[2]);
- return -1;
- }
- return 0;
-}
-
-/*
- * REMOVE INDICATION command stuff
- */
-static int handle_remove_indication(int fd, int argc, char *argv[])
-{
- struct tone_zone *tz;
- if (argc != 3 && argc != 4) return RESULT_SHOWUSAGE;
-
- if (argc == 3) {
- /* remove entiry country */
- if (ast_unregister_indication_country(argv[2])) {
- ast_log(LOG_WARNING, "Unable to unregister indication country %s\n",argv[2]);
- return -1;
- }
- return 0;
- }
-
- tz = ast_get_indication_zone(argv[2]);
- if (!tz) {
- ast_log(LOG_WARNING, "Unable to unregister indication %s/%s, country does not exists\n",argv[2],argv[3]);
- return -1;
- }
- if (ast_unregister_indication(tz,argv[3])) {
- ast_log(LOG_WARNING, "Unable to unregister indication %s/%s\n",argv[2],argv[3]);
- return -1;
- }
- return 0;
-}
-
-/*
- * SHOW INDICATIONS command stuff
- */
-static int handle_show_indications(int fd, int argc, char *argv[])
-{
- struct tone_zone *tz;
- char buf[256];
- int found_country = 0;
-
- if (ast_mutex_lock(&tzlock)) {
- ast_log(LOG_WARNING, "Unable to lock tone_zones list\n");
- return 0;
- }
- if (argc == 2) {
- /* no arguments, show a list of countries */
- ast_cli(fd,"Country Alias Description\n"
- "===========================\n");
- for (tz=tone_zones; tz; tz=tz->next) {
- ast_cli(fd,"%-7.7s %-7.7s %s\n", tz->country, tz->alias, tz->description);
- }
- ast_mutex_unlock(&tzlock);
- return 0;
- }
- /* there was a request for specific country(ies), lets humor them */
- for (tz=tone_zones; tz; tz=tz->next) {
- int i,j;
- for (i=2; i<argc; i++) {
- if (strcasecmp(tz->country,argv[i])==0 &&
- !tz->alias[0]) {
- struct tone_zone_sound* ts;
- if (!found_country) {
- found_country = 1;
- ast_cli(fd,"Country Indication PlayList\n"
- "=====================================\n");
- }
- j = snprintf(buf,sizeof(buf),"%-7.7s %-15.15s ",tz->country,"<ringcadence>");
- for (i=0; i<tz->nrringcadence; i++) {
- j += snprintf(buf+j,sizeof(buf)-j,"%d,",tz->ringcadence[i]);
- }
- if (tz->nrringcadence) j--;
- ast_copy_string(buf+j,"\n",sizeof(buf)-j);
- ast_cli(fd,buf);
- for (ts=tz->tones; ts; ts=ts->next)
- ast_cli(fd,"%-7.7s %-15.15s %s\n",tz->country,ts->name,ts->data);
- break;
- }
- }
- }
- if (!found_country)
- ast_cli(fd,"No countries matched your criteria.\n");
- ast_mutex_unlock(&tzlock);
- return -1;
-}
-
-/*
- * Playtones command stuff
- */
-static int handle_playtones(struct ast_channel *chan, void *data)
-{
- struct tone_zone_sound *ts;
- int res;
-
- if (!data || !((char*)data)[0]) {
- ast_log(LOG_NOTICE,"Nothing to play\n");
- return -1;
- }
- ts = ast_get_indication_tone(chan->zone, (const char*)data);
- if (ts && ts->data[0])
- res = ast_playtones_start(chan, 0, ts->data, 0);
- else
- res = ast_playtones_start(chan, 0, (const char*)data, 0);
- if (res)
- ast_log(LOG_NOTICE,"Unable to start playtones\n");
- return res;
-}
-
-/*
- * StopPlaylist command stuff
- */
-static int handle_stopplaytones(struct ast_channel *chan, void *data)
-{
- ast_playtones_stop(chan);
- return 0;
-}
-
-/*
- * Load module stuff
- */
-static int ind_load_module(void)
-{
- struct ast_config *cfg;
- struct ast_variable *v;
- char *cxt;
- char *c;
- struct tone_zone *tones;
- const char *country = NULL;
-
- /* that the following cast is needed, is yuk! */
- /* yup, checked it out. It is NOT written to. */
- cfg = ast_config_load((char *)config);
- if (!cfg)
- return 0;
-
- /* Use existing config to populate the Indication table */
- cxt = ast_category_browse(cfg, NULL);
- while(cxt) {
- /* All categories but "general" are considered countries */
- if (!strcasecmp(cxt, "general")) {
- cxt = ast_category_browse(cfg, cxt);
- continue;
- }
- tones = malloc(sizeof(struct tone_zone));
- if (!tones) {
- ast_log(LOG_WARNING,"Out of memory\n");
- ast_config_destroy(cfg);
- return -1;
- }
- memset(tones,0,sizeof(struct tone_zone));
- ast_copy_string(tones->country,cxt,sizeof(tones->country));
-
- v = ast_variable_browse(cfg, cxt);
- while(v) {
- if (!strcasecmp(v->name, "description")) {
- ast_copy_string(tones->description, v->value, sizeof(tones->description));
- } else if ((!strcasecmp(v->name,"ringcadence"))||(!strcasecmp(v->name,"ringcadance"))) {
- char *ring,*rings = ast_strdupa(v->value);
- c = rings;
- ring = strsep(&c,",");
- while (ring) {
- int *tmp, val;
- if (!isdigit(ring[0]) || (val=atoi(ring))==-1) {
- ast_log(LOG_WARNING,"Invalid ringcadence given '%s' at line %d.\n",ring,v->lineno);
- ring = strsep(&c,",");
- continue;
- }
- tmp = realloc(tones->ringcadence,(tones->nrringcadence+1)*sizeof(int));
- if (!tmp) {
- ast_log(LOG_WARNING, "Out of memory\n");
- ast_config_destroy(cfg);
- return -1;
- }
- tones->ringcadence = tmp;
- tmp[tones->nrringcadence] = val;
- tones->nrringcadence++;
- /* next item */
- ring = strsep(&c,",");
- }
- } else if (!strcasecmp(v->name,"alias")) {
- char *countries = ast_strdupa(v->value);
- c = countries;
- country = strsep(&c,",");
- while (country) {
- struct tone_zone* azone = malloc(sizeof(struct tone_zone));
- if (!azone) {
- ast_log(LOG_WARNING,"Out of memory\n");
- ast_config_destroy(cfg);
- return -1;
- }
- memset(azone,0,sizeof(struct tone_zone));
- ast_copy_string(azone->country, country, sizeof(azone->country));
- ast_copy_string(azone->alias, cxt, sizeof(azone->alias));
- if (ast_register_indication_country(azone)) {
- ast_log(LOG_WARNING, "Unable to register indication alias at line %d.\n",v->lineno);
- free(tones);
- }
- /* next item */
- country = strsep(&c,",");
- }
- } else {
- /* add tone to country */
- struct tone_zone_sound *ps,*ts;
- for (ps=NULL,ts=tones->tones; ts; ps=ts, ts=ts->next) {
- if (strcasecmp(v->name,ts->name)==0) {
- /* already there */
- ast_log(LOG_NOTICE,"Duplicate entry '%s', skipped.\n",v->name);
- goto out;
- }
- }
- /* not there, add it to the back */
- ts = malloc(sizeof(struct tone_zone_sound));
- if (!ts) {
- ast_log(LOG_WARNING, "Out of memory\n");
- ast_config_destroy(cfg);
- return -1;
- }
- ts->next = NULL;
- ts->name = strdup(v->name);
- ts->data = strdup(v->value);
- if (ps)
- ps->next = ts;
- else
- tones->tones = ts;
- }
-out: v = v->next;
- }
- if (tones->description[0] || tones->alias[0] || tones->tones) {
- if (ast_register_indication_country(tones)) {
- ast_log(LOG_WARNING, "Unable to register indication at line %d.\n",v->lineno);
- free(tones);
- }
- } else free(tones);
-
- cxt = ast_category_browse(cfg, cxt);
- }
-
- /* determine which country is the default */
- country = ast_variable_retrieve(cfg,"general","country");
- if (!country || !*country || ast_set_indication_country(country))
- ast_log(LOG_WARNING,"Unable to set the default country (for indication tones)\n");
-
- ast_config_destroy(cfg);
- return 0;
-}
-
-/*
- * CLI entries for commands provided by this module
- */
-static struct ast_cli_entry add_indication_cli =
- { { "indication", "add", NULL }, handle_add_indication,
- "Add the given indication to the country", help_add_indication,
- NULL };
-
-static struct ast_cli_entry remove_indication_cli =
- { { "indication", "remove", NULL }, handle_remove_indication,
- "Remove the given indication from the country", help_remove_indication,
- NULL };
-
-static struct ast_cli_entry show_indications_cli =
- { { "show", "indications", NULL }, handle_show_indications,
- "Show a list of all country/indications", help_show_indications,
- NULL };
-
-/*
- * Standard module functions ...
- */
-int unload_module(void)
-{
- /* remove the registed indications... */
- ast_unregister_indication_country(NULL);
-
- /* and the functions */
- ast_cli_unregister(&add_indication_cli);
- ast_cli_unregister(&remove_indication_cli);
- ast_cli_unregister(&show_indications_cli);
- ast_unregister_application("PlayTones");
- ast_unregister_application("StopPlayTones");
- return 0;
-}
-
-
-int load_module(void)
-{
- if (ind_load_module()) return -1;
-
- ast_cli_register(&add_indication_cli);
- ast_cli_register(&remove_indication_cli);
- ast_cli_register(&show_indications_cli);
- ast_register_application("PlayTones", handle_playtones, "Play a tone list", playtones_desc);
- ast_register_application("StopPlayTones", handle_stopplaytones, "Stop playing a tone list","Stop playing a tone list");
-
- return 0;
-}
-
-int reload(void)
-{
- /* remove the registed indications... */
- ast_unregister_indication_country(NULL);
-
- return ind_load_module();
-}
-
-char *description(void)
-{
- /* that the following cast is needed, is yuk! */
- return (char*)dtext;
-}
-
-int usecount(void)
-{
- return 0;
-}
-
-char *key()
-{
- return ASTERISK_GPL_KEY;
-}
diff --git a/1.2-netsec/res/res_monitor.c b/1.2-netsec/res/res_monitor.c
deleted file mode 100644
index adc6144b5..000000000
--- a/1.2-netsec/res/res_monitor.c
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief PBX channel monitoring
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <libgen.h> /* dirname() */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/lock.h"
-#include "asterisk/channel.h"
-#include "asterisk/logger.h"
-#include "asterisk/file.h"
-#include "asterisk/pbx.h"
-#include "asterisk/module.h"
-#include "asterisk/manager.h"
-#include "asterisk/cli.h"
-#include "asterisk/monitor.h"
-#include "asterisk/app.h"
-#include "asterisk/utils.h"
-#include "asterisk/config.h"
-
-AST_MUTEX_DEFINE_STATIC(monitorlock);
-
-static unsigned long seq = 0;
-
-static char *monitor_synopsis = "Monitor a channel";
-
-static char *monitor_descrip = "Monitor([file_format[:urlbase]|[fname_base]|[options]]):\n"
-"Used to start monitoring a channel. The channel's input and output\n"
-"voice packets are logged to files until the channel hangs up or\n"
-"monitoring is stopped by the StopMonitor application.\n"
-" file_format optional, if not set, defaults to \"wav\"\n"
-" fname_base if set, changes the filename used to the one specified.\n"
-" options:\n"
-" m - when the recording ends mix the two leg files into one and\n"
-" delete the two leg files. If the variable MONITOR_EXEC is set, the\n"
-" application referenced in it will be executed instead of\n"
-" soxmix and the raw leg files will NOT be deleted automatically.\n"
-" soxmix or MONITOR_EXEC is handed 3 arguments, the two leg files\n"
-" and a target mixed file name which is the same as the leg file names\n"
-" only without the in/out designator.\n"
-" If MONITOR_EXEC_ARGS is set, the contents will be passed on as\n"
-" additional arguements to MONITOR_EXEC\n"
-" Both MONITOR_EXEC and the Mix flag can be set from the\n"
-" administrator interface\n"
-"\n"
-" b - Don't begin recording unless a call is bridged to another channel\n"
-"\nReturns -1 if monitor files can't be opened or if the channel is already\n"
-"monitored, otherwise 0.\n"
-;
-
-static char *stopmonitor_synopsis = "Stop monitoring a channel";
-
-static char *stopmonitor_descrip = "StopMonitor\n"
- "Stops monitoring a channel. Has no effect if the channel is not monitored\n";
-
-static char *changemonitor_synopsis = "Change monitoring filename of a channel";
-
-static char *changemonitor_descrip = "ChangeMonitor(filename_base)\n"
- "Changes monitoring filename of a channel. Has no effect if the channel is not monitored\n"
- "The argument is the new filename base to use for monitoring this channel.\n";
-
-/* Start monitoring a channel */
-int ast_monitor_start( struct ast_channel *chan, const char *format_spec,
- const char *fname_base, int need_lock)
-{
- int res = 0;
- char tmp[256];
-
- if (need_lock) {
- if (ast_mutex_lock(&chan->lock)) {
- ast_log(LOG_WARNING, "Unable to lock channel\n");
- return -1;
- }
- }
-
- if (!(chan->monitor)) {
- struct ast_channel_monitor *monitor;
- char *channel_name, *p;
-
- /* Create monitoring directory if needed */
- if (mkdir(ast_config_AST_MONITOR_DIR, 0770) < 0) {
- if (errno != EEXIST) {
- ast_log(LOG_WARNING, "Unable to create audio monitor directory: %s\n",
- strerror(errno));
- }
- }
-
- monitor = malloc(sizeof(struct ast_channel_monitor));
- if (!monitor) {
- if (need_lock)
- ast_mutex_unlock(&chan->lock);
- return -1;
- }
- memset(monitor, 0, sizeof(struct ast_channel_monitor));
-
- /* Determine file names */
- if (!ast_strlen_zero(fname_base)) {
- int directory = strchr(fname_base, '/') ? 1 : 0;
- /* try creating the directory just in case it doesn't exist */
- if (directory) {
- char *name = strdup(fname_base);
- snprintf(tmp, sizeof(tmp), "mkdir -p \"%s\"",dirname(name));
- free(name);
- ast_safe_system(tmp);
- }
- snprintf(monitor->read_filename, FILENAME_MAX, "%s/%s-in",
- directory ? "" : ast_config_AST_MONITOR_DIR, fname_base);
- snprintf(monitor->write_filename, FILENAME_MAX, "%s/%s-out",
- directory ? "" : ast_config_AST_MONITOR_DIR, fname_base);
- ast_copy_string(monitor->filename_base, fname_base, sizeof(monitor->filename_base));
- } else {
- ast_mutex_lock(&monitorlock);
- snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld",
- ast_config_AST_MONITOR_DIR, seq);
- snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld",
- ast_config_AST_MONITOR_DIR, seq);
- seq++;
- ast_mutex_unlock(&monitorlock);
-
- if((channel_name = ast_strdupa(chan->name))) {
- while((p = strchr(channel_name, '/'))) {
- *p = '-';
- }
- snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s",
- ast_config_AST_MONITOR_DIR, (int)time(NULL),channel_name);
- monitor->filename_changed = 1;
- } else {
- ast_log(LOG_ERROR,"Failed to allocate Memory\n");
- return -1;
- }
- }
-
- monitor->stop = ast_monitor_stop;
-
- /* Determine file format */
- if (!ast_strlen_zero(format_spec)) {
- monitor->format = strdup(format_spec);
- } else {
- monitor->format = strdup("wav");
- }
-
- /* open files */
- if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0) {
- ast_filedelete(monitor->read_filename, NULL);
- }
- if (!(monitor->read_stream = ast_writefile(monitor->read_filename,
- monitor->format, NULL,
- O_CREAT|O_TRUNC|O_WRONLY, 0, 0644))) {
- ast_log(LOG_WARNING, "Could not create file %s\n",
- monitor->read_filename);
- free(monitor);
- ast_mutex_unlock(&chan->lock);
- return -1;
- }
- if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) {
- ast_filedelete(monitor->write_filename, NULL);
- }
- if (!(monitor->write_stream = ast_writefile(monitor->write_filename,
- monitor->format, NULL,
- O_CREAT|O_TRUNC|O_WRONLY, 0, 0644))) {
- ast_log(LOG_WARNING, "Could not create file %s\n",
- monitor->write_filename);
- ast_closestream(monitor->read_stream);
- free(monitor);
- ast_mutex_unlock(&chan->lock);
- return -1;
- }
- chan->monitor = monitor;
- /* so we know this call has been monitored in case we need to bill for it or something */
- pbx_builtin_setvar_helper(chan, "__MONITORED","true");
- } else {
- ast_log(LOG_DEBUG,"Cannot start monitoring %s, already monitored\n",
- chan->name);
- res = -1;
- }
-
- if (need_lock) {
- ast_mutex_unlock(&chan->lock);
- }
- return res;
-}
-
-/* Stop monitoring a channel */
-int ast_monitor_stop(struct ast_channel *chan, int need_lock)
-{
- char *execute, *execute_args;
- int delfiles = 0;
-
- if (need_lock) {
- if (ast_mutex_lock(&chan->lock)) {
- ast_log(LOG_WARNING, "Unable to lock channel\n");
- return -1;
- }
- }
-
- if (chan->monitor) {
- char filename[ FILENAME_MAX ];
-
- if (chan->monitor->read_stream) {
- ast_closestream(chan->monitor->read_stream);
- }
- if (chan->monitor->write_stream) {
- ast_closestream(chan->monitor->write_stream);
- }
-
- if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) {
- if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) {
- snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base);
- if (ast_fileexists(filename, NULL, NULL) > 0) {
- ast_filedelete(filename, NULL);
- }
- ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format);
- } else {
- ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename);
- }
-
- if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) {
- snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base);
- if (ast_fileexists(filename, NULL, NULL) > 0) {
- ast_filedelete(filename, NULL);
- }
- ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format);
- } else {
- ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename);
- }
- }
-
- if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
- char tmp[1024];
- char tmp2[1024];
- char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
- char *name = chan->monitor->filename_base;
- int directory = strchr(name, '/') ? 1 : 0;
- char *dir = directory ? "" : ast_config_AST_MONITOR_DIR;
-
- /* Set the execute application */
- execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC");
- if (ast_strlen_zero(execute)) {
- execute = "nice -n 19 soxmix";
- delfiles = 1;
- }
- execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS");
- if (ast_strlen_zero(execute_args)) {
- execute_args = "";
- }
-
- snprintf(tmp, sizeof(tmp), "%s \"%s/%s-in.%s\" \"%s/%s-out.%s\" \"%s/%s.%s\" %s &", execute, dir, name, format, dir, name, format, dir, name, format,execute_args);
- if (delfiles) {
- snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s/%s-\"* ) &",tmp, dir ,name); /* remove legs when done mixing */
- ast_copy_string(tmp, tmp2, sizeof(tmp));
- }
- ast_log(LOG_DEBUG,"monitor executing %s\n",tmp);
- if (ast_safe_system(tmp) == -1)
- ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
- }
-
- free(chan->monitor->format);
- free(chan->monitor);
- chan->monitor = NULL;
- }
-
- if (need_lock)
- ast_mutex_unlock(&chan->lock);
- return 0;
-}
-
-/* Change monitoring filename of a channel */
-int ast_monitor_change_fname(struct ast_channel *chan, const char *fname_base, int need_lock)
-{
- char tmp[256];
- if (ast_strlen_zero(fname_base)) {
- ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null", chan->name);
- return -1;
- }
-
- if (need_lock) {
- if (ast_mutex_lock(&chan->lock)) {
- ast_log(LOG_WARNING, "Unable to lock channel\n");
- return -1;
- }
- }
-
- if (chan->monitor) {
- int directory = strchr(fname_base, '/') ? 1 : 0;
- /* try creating the directory just in case it doesn't exist */
- if (directory) {
- char *name = strdup(fname_base);
- snprintf(tmp, sizeof(tmp), "mkdir -p %s",dirname(name));
- free(name);
- ast_safe_system(tmp);
- }
-
- snprintf(chan->monitor->filename_base, FILENAME_MAX, "%s/%s", directory ? "" : ast_config_AST_MONITOR_DIR, fname_base);
- } else {
- ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base);
- }
-
- if (need_lock)
- ast_mutex_unlock(&chan->lock);
-
- return 0;
-}
-
-static int start_monitor_exec(struct ast_channel *chan, void *data)
-{
- char *arg = NULL;
- char *format = NULL;
- char *fname_base = NULL;
- char *options = NULL;
- char *delay = NULL;
- char *urlprefix = NULL;
- char tmp[256];
- int joinfiles = 0;
- int waitforbridge = 0;
- int res = 0;
-
- /* Parse arguments. */
- if (!ast_strlen_zero((char*)data)) {
- arg = ast_strdupa((char*)data);
- format = arg;
- fname_base = strchr(arg, '|');
- if (fname_base) {
- *fname_base = 0;
- fname_base++;
- if ((options = strchr(fname_base, '|'))) {
- *options = 0;
- options++;
- if (strchr(options, 'm'))
- joinfiles = 1;
- if (strchr(options, 'b'))
- waitforbridge = 1;
- }
- }
- arg = strchr(format,':');
- if (arg) {
- *arg++ = 0;
- urlprefix = arg;
- }
- }
- if (urlprefix) {
- snprintf(tmp,sizeof(tmp) - 1,"%s/%s.%s",urlprefix,fname_base,
- ((strcmp(format,"gsm")) ? "wav" : "gsm"));
- if (!chan->cdr)
- chan->cdr = ast_cdr_alloc();
- ast_cdr_setuserfield(chan, tmp);
- }
- if (waitforbridge) {
- /* We must remove the "b" option if listed. In principle none of
- the following could give NULL results, but we check just to
- be pedantic. Reconstructing with checks for 'm' option does not
- work if we end up adding more options than 'm' in the future. */
- delay = ast_strdupa((char*)data);
- if (delay) {
- options = strrchr(delay, '|');
- if (options) {
- arg = strchr(options, 'b');
- if (arg) {
- *arg = 'X';
- pbx_builtin_setvar_helper(chan,"AUTO_MONITOR",delay);
- }
- }
- }
- return 0;
- }
-
- res = ast_monitor_start(chan, format, fname_base, 1);
- if (res < 0)
- res = ast_monitor_change_fname(chan, fname_base, 1);
- ast_monitor_setjoinfiles(chan, joinfiles);
-
- return res;
-}
-
-static int stop_monitor_exec(struct ast_channel *chan, void *data)
-{
- return ast_monitor_stop(chan, 1);
-}
-
-static int change_monitor_exec(struct ast_channel *chan, void *data)
-{
- return ast_monitor_change_fname(chan, (const char*)data, 1);
-}
-
-static char start_monitor_action_help[] =
-"Description: The 'Monitor' action may be used to record the audio on a\n"
-" specified channel. The following parameters may be used to control\n"
-" this:\n"
-" Channel - Required. Used to specify the channel to record.\n"
-" File - Optional. Is the name of the file created in the\n"
-" monitor spool directory. Defaults to the same name\n"
-" as the channel (with slashes replaced with dashes).\n"
-" Format - Optional. Is the audio recording format. Defaults\n"
-" to \"wav\".\n"
-" Mix - Optional. Boolean parameter as to whether to mix\n"
-" the input and output channels together after the\n"
-" recording is finished.\n";
-
-static int start_monitor_action(struct mansession *s, struct message *m)
-{
- struct ast_channel *c = NULL;
- char *name = astman_get_header(m, "Channel");
- char *fname = astman_get_header(m, "File");
- char *format = astman_get_header(m, "Format");
- char *mix = astman_get_header(m, "Mix");
- char *d;
-
- if (ast_strlen_zero(name)) {
- astman_send_error(s, m, "No channel specified");
- return 0;
- }
- c = ast_get_channel_by_name_locked(name);
- if (!c) {
- astman_send_error(s, m, "No such channel");
- return 0;
- }
-
- if (ast_strlen_zero(fname)) {
- /* No filename base specified, default to channel name as per CLI */
- fname = malloc (FILENAME_MAX);
- if (!fname) {
- astman_send_error(s, m, "Could not start monitoring channel");
- ast_mutex_unlock(&c->lock);
- return 0;
- }
- memset(fname, 0, FILENAME_MAX);
- ast_copy_string(fname, c->name, FILENAME_MAX);
- /* Channels have the format technology/channel_name - have to replace that / */
- if ((d=strchr(fname, '/'))) *d='-';
- }
-
- if (ast_monitor_start(c, format, fname, 1)) {
- if (ast_monitor_change_fname(c, fname, 1)) {
- astman_send_error(s, m, "Could not start monitoring channel");
- ast_mutex_unlock(&c->lock);
- return 0;
- }
- }
-
- if (ast_true(mix)) {
- ast_monitor_setjoinfiles(c, 1);
- }
-
- ast_mutex_unlock(&c->lock);
- astman_send_ack(s, m, "Started monitoring channel");
- return 0;
-}
-
-static char stop_monitor_action_help[] =
-"Description: The 'StopMonitor' action may be used to end a previously\n"
-" started 'Monitor' action. The only parameter is 'Channel', the name\n"
-" of the channel monitored.\n";
-
-static int stop_monitor_action(struct mansession *s, struct message *m)
-{
- struct ast_channel *c = NULL;
- char *name = astman_get_header(m, "Channel");
- int res;
- if (ast_strlen_zero(name)) {
- astman_send_error(s, m, "No channel specified");
- return 0;
- }
- c = ast_get_channel_by_name_locked(name);
- if (!c) {
- astman_send_error(s, m, "No such channel");
- return 0;
- }
- res = ast_monitor_stop(c, 1);
- ast_mutex_unlock(&c->lock);
- if (res) {
- astman_send_error(s, m, "Could not stop monitoring channel");
- return 0;
- }
- astman_send_ack(s, m, "Stopped monitoring channel");
- return 0;
-}
-
-static char change_monitor_action_help[] =
-"Description: The 'ChangeMonitor' action may be used to change the file\n"
-" started by a previous 'Monitor' action. The following parameters may\n"
-" be used to control this:\n"
-" Channel - Required. Used to specify the channel to record.\n"
-" File - Required. Is the new name of the file created in the\n"
-" monitor spool directory.\n";
-
-static int change_monitor_action(struct mansession *s, struct message *m)
-{
- struct ast_channel *c = NULL;
- char *name = astman_get_header(m, "Channel");
- char *fname = astman_get_header(m, "File");
- if (ast_strlen_zero(name)) {
- astman_send_error(s, m, "No channel specified");
- return 0;
- }
- if (ast_strlen_zero(fname)) {
- astman_send_error(s, m, "No filename specified");
- return 0;
- }
- c = ast_get_channel_by_name_locked(name);
- if (!c) {
- astman_send_error(s, m, "No such channel");
- return 0;
- }
- if (ast_monitor_change_fname(c, fname, 1)) {
- astman_send_error(s, m, "Could not change monitored filename of channel");
- ast_mutex_unlock(&c->lock);
- return 0;
- }
- ast_mutex_unlock(&c->lock);
- astman_send_ack(s, m, "Changed monitor filename");
- return 0;
-}
-
-void ast_monitor_setjoinfiles(struct ast_channel *chan, int turnon)
-{
- if (chan->monitor)
- chan->monitor->joinfiles = turnon;
-}
-
-int load_module(void)
-{
- ast_register_application("Monitor", start_monitor_exec, monitor_synopsis, monitor_descrip);
- ast_register_application("StopMonitor", stop_monitor_exec, stopmonitor_synopsis, stopmonitor_descrip);
- ast_register_application("ChangeMonitor", change_monitor_exec, changemonitor_synopsis, changemonitor_descrip);
- ast_manager_register2("Monitor", EVENT_FLAG_CALL, start_monitor_action, monitor_synopsis, start_monitor_action_help);
- ast_manager_register2("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action, stopmonitor_synopsis, stop_monitor_action_help);
- ast_manager_register2("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action, changemonitor_synopsis, change_monitor_action_help);
-
- return 0;
-}
-
-int unload_module(void)
-{
- ast_unregister_application("Monitor");
- ast_unregister_application("StopMonitor");
- ast_unregister_application("ChangeMonitor");
- ast_manager_unregister("Monitor");
- ast_manager_unregister("StopMonitor");
- ast_manager_unregister("ChangeMonitor");
- return 0;
-}
-
-char *description(void)
-{
- return "Call Monitoring Resource";
-}
-
-int usecount(void)
-{
- /* Never allow monitor to be unloaded because it will
- unresolve needed symbols in the channel */
-#if 0
- int res;
- STANDARD_USECOUNT(res);
- return res;
-#else
- return 1;
-#endif
-}
-
-char *key()
-{
- return ASTERISK_GPL_KEY;
-}
diff --git a/1.2-netsec/res/res_musiconhold.c b/1.2-netsec/res/res_musiconhold.c
deleted file mode 100644
index 2a27dcec8..000000000
--- a/1.2-netsec/res/res_musiconhold.c
+++ /dev/null
@@ -1,1237 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Routines implementing music on hold
- *
- * \arg See also \ref Config_moh
- *
- */
-
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/time.h>
-#include <sys/signal.h>
-#include <netinet/in.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#ifdef ZAPATA_MOH
-#ifdef __linux__
-#include <linux/zaptel.h>
-#else
-#include <zaptel.h>
-#endif /* __linux__ */
-#endif
-#include <unistd.h>
-#include <sys/ioctl.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/lock.h"
-#include "asterisk/file.h"
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/pbx.h"
-#include "asterisk/options.h"
-#include "asterisk/module.h"
-#include "asterisk/translate.h"
-#include "asterisk/say.h"
-#include "asterisk/musiconhold.h"
-#include "asterisk/config.h"
-#include "asterisk/utils.h"
-#include "asterisk/cli.h"
-
-#define MAX_MOHFILES 512
-#define MAX_MOHFILE_LEN 128
-
-static char *app0 = "MusicOnHold";
-static char *app1 = "WaitMusicOnHold";
-static char *app2 = "SetMusicOnHold";
-static char *app3 = "StartMusicOnHold";
-static char *app4 = "StopMusicOnHold";
-
-static char *synopsis0 = "Play Music On Hold indefinitely";
-static char *synopsis1 = "Wait, playing Music On Hold";
-static char *synopsis2 = "Set default Music On Hold class";
-static char *synopsis3 = "Play Music On Hold";
-static char *synopsis4 = "Stop Playing Music On Hold";
-
-static char *descrip0 = "MusicOnHold(class): "
-"Plays hold music specified by class. If omitted, the default\n"
-"music source for the channel will be used. Set the default \n"
-"class with the SetMusicOnHold() application.\n"
-"Returns -1 on hangup.\n"
-"Never returns otherwise.\n";
-
-static char *descrip1 = "WaitMusicOnHold(delay): "
-"Plays hold music specified number of seconds. Returns 0 when\n"
-"done, or -1 on hangup. If no hold music is available, the delay will\n"
-"still occur with no sound.\n";
-
-static char *descrip2 = "SetMusicOnHold(class): "
-"Sets the default class for music on hold for a given channel. When\n"
-"music on hold is activated, this class will be used to select which\n"
-"music is played.\n";
-
-static char *descrip3 = "StartMusicOnHold(class): "
-"Starts playing music on hold, uses default music class for channel.\n"
-"Starts playing music specified by class. If omitted, the default\n"
-"music source for the channel will be used. Always returns 0.\n";
-
-static char *descrip4 = "StopMusicOnHold: "
-"Stops playing music on hold.\n";
-
-static int respawn_time = 20;
-
-struct moh_files_state {
- struct mohclass *class;
- int origwfmt;
- int samples;
- int sample_queue;
- unsigned char pos;
- unsigned char save_pos;
-};
-
-#define MOH_QUIET (1 << 0)
-#define MOH_SINGLE (1 << 1)
-#define MOH_CUSTOM (1 << 2)
-#define MOH_RANDOMIZE (1 << 3)
-
-struct mohclass {
- char name[MAX_MUSICCLASS];
- char dir[256];
- char args[256];
- char mode[80];
- char filearray[MAX_MOHFILES][MAX_MOHFILE_LEN];
- unsigned int flags;
- int total_files;
- int format;
- int pid; /* PID of mpg123 */
- time_t start;
- pthread_t thread;
- struct mohdata *members;
- /* Source of audio */
- int srcfd;
- /* FD for timing source */
- int pseudofd;
- struct mohclass *next;
-};
-
-struct mohdata {
- int pipe[2];
- int origwfmt;
- struct mohclass *parent;
- struct mohdata *next;
-};
-
-static struct mohclass *mohclasses;
-
-AST_MUTEX_DEFINE_STATIC(moh_lock);
-
-#define LOCAL_MPG_123 "/usr/local/bin/mpg123"
-#define MPG_123 "/usr/bin/mpg123"
-#define MAX_MP3S 256
-
-
-static void ast_moh_free_class(struct mohclass **class)
-{
- struct mohdata *members, *mtmp;
-
- members = (*class)->members;
- while(members) {
- mtmp = members;
- members = members->next;
- free(mtmp);
- }
- free(*class);
- *class = NULL;
-}
-
-
-static void moh_files_release(struct ast_channel *chan, void *data)
-{
- struct moh_files_state *state = chan->music_state;
-
- if (chan && state) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Stopped music on hold on %s\n", chan->name);
-
- if (state->origwfmt && ast_set_write_format(chan, state->origwfmt)) {
- ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, state->origwfmt);
- }
- state->save_pos = state->pos + 1;
- }
-}
-
-
-static int ast_moh_files_next(struct ast_channel *chan)
-{
- struct moh_files_state *state = chan->music_state;
- int tries;
-
- if (state->save_pos) {
- state->pos = state->save_pos - 1;
- state->save_pos = 0;
- } else {
- /* Try 20 times to find something good */
- for (tries=0;tries < 20;tries++) {
- state->samples = 0;
- if (chan->stream) {
- ast_closestream(chan->stream);
- chan->stream = NULL;
- state->pos++;
- }
-
- if (ast_test_flag(state->class, MOH_RANDOMIZE))
- state->pos = rand();
-
- /* check to see if this file's format can be opened */
- if (ast_fileexists(state->class->filearray[state->pos], NULL, NULL) != -1)
- break;
-
- }
- }
-
- state->pos = state->pos % state->class->total_files;
-
- if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
- ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", chan->name);
- return -1;
- }
- if (!ast_openstream_full(chan, state->class->filearray[state->pos], chan->language, 1)) {
- ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", state->class->filearray[state->pos], strerror(errno));
- state->pos++;
- return -1;
- }
-
- if (option_debug)
- ast_log(LOG_DEBUG, "%s Opened file %d '%s'\n", chan->name, state->pos, state->class->filearray[state->pos]);
-
- if (state->samples)
- ast_seekstream(chan->stream, state->samples, SEEK_SET);
-
- return 0;
-}
-
-
-static struct ast_frame *moh_files_readframe(struct ast_channel *chan)
-{
- struct ast_frame *f = NULL;
-
- if (!(chan->stream && (f = ast_readframe(chan->stream)))) {
- if (!ast_moh_files_next(chan))
- f = ast_readframe(chan->stream);
- }
-
- return f;
-}
-
-static int moh_files_generator(struct ast_channel *chan, void *data, int len, int samples)
-{
- struct moh_files_state *state = chan->music_state;
- struct ast_frame *f = NULL;
- int res = 0;
-
- state->sample_queue += samples;
-
- while (state->sample_queue > 0) {
- if ((f = moh_files_readframe(chan))) {
- state->samples += f->samples;
- res = ast_write(chan, f);
- state->sample_queue -= f->samples;
- ast_frfree(f);
- if (res < 0) {
- ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
- return -1;
- }
- } else
- return -1;
- }
- return res;
-}
-
-
-static void *moh_files_alloc(struct ast_channel *chan, void *params)
-{
- struct moh_files_state *state;
- struct mohclass *class = params;
- int allocated = 0;
-
- if (!chan->music_state && (state = malloc(sizeof(struct moh_files_state)))) {
- chan->music_state = state;
- allocated = 1;
- } else
- state = chan->music_state;
-
- if (state) {
- if (allocated || state->class != class) {
- /* initialize */
- memset(state, 0, sizeof(struct moh_files_state));
- state->class = class;
- }
-
- state->origwfmt = chan->writeformat;
-
- if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
- ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", chan->name);
- free(chan->music_state);
- chan->music_state = NULL;
- } else {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Started music on hold, class '%s', on %s\n", class->name, chan->name);
- }
- }
-
- return chan->music_state;
-}
-
-static struct ast_generator moh_file_stream =
-{
- alloc: moh_files_alloc,
- release: moh_files_release,
- generate: moh_files_generator,
-};
-
-static int spawn_mp3(struct mohclass *class)
-{
- int fds[2];
- int files = 0;
- char fns[MAX_MP3S][80];
- char *argv[MAX_MP3S + 50];
- char xargs[256];
- char *argptr;
- int argc = 0;
- DIR *dir = NULL;
- struct dirent *de;
-
-
- if (!strcasecmp(class->dir, "nodir")) {
- files = 1;
- } else {
- dir = opendir(class->dir);
- if (!dir && !strstr(class->dir,"http://") && !strstr(class->dir,"HTTP://")) {
- ast_log(LOG_WARNING, "%s is not a valid directory\n", class->dir);
- return -1;
- }
- }
-
- if (!ast_test_flag(class, MOH_CUSTOM)) {
- argv[argc++] = "mpg123";
- argv[argc++] = "-q";
- argv[argc++] = "-s";
- argv[argc++] = "--mono";
- argv[argc++] = "-r";
- argv[argc++] = "8000";
-
- if (!ast_test_flag(class, MOH_SINGLE)) {
- argv[argc++] = "-b";
- argv[argc++] = "2048";
- }
-
- argv[argc++] = "-f";
-
- if (ast_test_flag(class, MOH_QUIET))
- argv[argc++] = "4096";
- else
- argv[argc++] = "8192";
-
- /* Look for extra arguments and add them to the list */
- strncpy(xargs, class->args, sizeof(xargs) - 1);
- argptr = xargs;
- while (!ast_strlen_zero(argptr)) {
- argv[argc++] = argptr;
- argptr = strchr(argptr, ',');
- if (argptr) {
- *argptr = '\0';
- argptr++;
- }
- }
- } else {
- /* Format arguments for argv vector */
- strncpy(xargs, class->args, sizeof(xargs) - 1);
- argptr = xargs;
- while (!ast_strlen_zero(argptr)) {
- argv[argc++] = argptr;
- argptr = strchr(argptr, ' ');
- if (argptr) {
- *argptr = '\0';
- argptr++;
- }
- }
- }
-
-
- if (strstr(class->dir,"http://") || strstr(class->dir,"HTTP://")) {
- strncpy(fns[files], class->dir, sizeof(fns[files]) - 1);
- argv[argc++] = fns[files];
- files++;
- } else if (dir) {
- while ((de = readdir(dir)) && (files < MAX_MP3S)) {
- if ((strlen(de->d_name) > 3) &&
- ((ast_test_flag(class, MOH_CUSTOM) &&
- (!strcasecmp(de->d_name + strlen(de->d_name) - 4, ".raw") ||
- !strcasecmp(de->d_name + strlen(de->d_name) - 4, ".sln"))) ||
- !strcasecmp(de->d_name + strlen(de->d_name) - 4, ".mp3"))) {
- strncpy(fns[files], de->d_name, sizeof(fns[files]) - 1);
- argv[argc++] = fns[files];
- files++;
- }
- }
- }
- argv[argc] = NULL;
- if (dir) {
- closedir(dir);
- }
- if (pipe(fds)) {
- ast_log(LOG_WARNING, "Pipe failed\n");
- return -1;
- }
-#if 0
- printf("%d files total, %d args total\n", files, argc);
- {
- int x;
- for (x=0;argv[x];x++)
- printf("arg%d: %s\n", x, argv[x]);
- }
-#endif
- if (!files) {
- ast_log(LOG_WARNING, "Found no files in '%s'\n", class->dir);
- close(fds[0]);
- close(fds[1]);
- return -1;
- }
- if (time(NULL) - class->start < respawn_time) {
- sleep(respawn_time - (time(NULL) - class->start));
- }
- time(&class->start);
- class->pid = fork();
- if (class->pid < 0) {
- close(fds[0]);
- close(fds[1]);
- ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
- return -1;
- }
- if (!class->pid) {
- int x;
- close(fds[0]);
- /* Stdout goes to pipe */
- dup2(fds[1], STDOUT_FILENO);
- /* Close unused file descriptors */
- for (x=3;x<8192;x++) {
- if (-1 != fcntl(x, F_GETFL)) {
- close(x);
- }
- }
- /* Child */
- chdir(class->dir);
- if (ast_test_flag(class, MOH_CUSTOM)) {
- execv(argv[0], argv);
- } else {
- /* Default install is /usr/local/bin */
- execv(LOCAL_MPG_123, argv);
- /* Many places have it in /usr/bin */
- execv(MPG_123, argv);
- /* Check PATH as a last-ditch effort */
- execvp("mpg123", argv);
- }
- ast_log(LOG_WARNING, "Exec failed: %s\n", strerror(errno));
- close(fds[1]);
- exit(1);
- } else {
- /* Parent */
- close(fds[1]);
- }
- return fds[0];
-}
-
-static void *monmp3thread(void *data)
-{
-#define MOH_MS_INTERVAL 100
-
- struct mohclass *class = data;
- struct mohdata *moh;
- char buf[8192];
- short sbuf[8192];
- int res, res2;
- int len;
- struct timeval tv, tv_tmp;
-
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- for(;/* ever */;) {
- /* Spawn mp3 player if it's not there */
- if (class->srcfd < 0) {
- if ((class->srcfd = spawn_mp3(class)) < 0) {
- ast_log(LOG_WARNING, "Unable to spawn mp3player\n");
- /* Try again later */
- sleep(500);
- }
- }
- if (class->pseudofd > -1) {
- /* Pause some amount of time */
- res = read(class->pseudofd, buf, sizeof(buf));
- } else {
- long delta;
- /* Reliable sleep */
- tv_tmp = ast_tvnow();
- if (ast_tvzero(tv))
- tv = tv_tmp;
- delta = ast_tvdiff_ms(tv_tmp, tv);
- if (delta < MOH_MS_INTERVAL) { /* too early */
- tv = ast_tvadd(tv, ast_samp2tv(MOH_MS_INTERVAL, 1000)); /* next deadline */
- usleep(1000 * (MOH_MS_INTERVAL - delta));
- } else {
- ast_log(LOG_NOTICE, "Request to schedule in the past?!?!\n");
- tv = tv_tmp;
- }
- res = 8 * MOH_MS_INTERVAL; /* 8 samples per millisecond */
- }
- if (!class->members)
- continue;
- /* Read mp3 audio */
- len = ast_codec_get_len(class->format, res);
-
- if ((res2 = read(class->srcfd, sbuf, len)) != len) {
- if (!res2) {
- close(class->srcfd);
- class->srcfd = -1;
- if (class->pid) {
- kill(class->pid, SIGKILL);
- class->pid = 0;
- }
- } else
- ast_log(LOG_DEBUG, "Read %d bytes of audio while expecting %d\n", res2, len);
- continue;
- }
- ast_mutex_lock(&moh_lock);
- moh = class->members;
- while (moh) {
- /* Write data */
- if ((res = write(moh->pipe[1], sbuf, res2)) != res2)
- if (option_debug)
- ast_log(LOG_DEBUG, "Only wrote %d of %d bytes to pipe\n", res, res2);
- moh = moh->next;
- }
- ast_mutex_unlock(&moh_lock);
- }
- return NULL;
-}
-
-static int moh0_exec(struct ast_channel *chan, void *data)
-{
- if (ast_moh_start(chan, data)) {
- ast_log(LOG_WARNING, "Unable to start music on hold (class '%s') on channel %s\n", (char *)data, chan->name);
- return -1;
- }
- while (!ast_safe_sleep(chan, 10000));
- ast_moh_stop(chan);
- return -1;
-}
-
-static int moh1_exec(struct ast_channel *chan, void *data)
-{
- int res;
- if (!data || !atoi(data)) {
- ast_log(LOG_WARNING, "WaitMusicOnHold requires an argument (number of seconds to wait)\n");
- return -1;
- }
- if (ast_moh_start(chan, NULL)) {
- ast_log(LOG_WARNING, "Unable to start music on hold for %d seconds on channel %s\n", atoi(data), chan->name);
- return -1;
- }
- res = ast_safe_sleep(chan, atoi(data) * 1000);
- ast_moh_stop(chan);
- return res;
-}
-
-static int moh2_exec(struct ast_channel *chan, void *data)
-{
- if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "SetMusicOnHold requires an argument (class)\n");
- return -1;
- }
- strncpy(chan->musicclass, data, sizeof(chan->musicclass) - 1);
- return 0;
-}
-
-static int moh3_exec(struct ast_channel *chan, void *data)
-{
- char *class = NULL;
- if (data && strlen(data))
- class = data;
- if (ast_moh_start(chan, class))
- ast_log(LOG_NOTICE, "Unable to start music on hold class '%s' on channel %s\n", class ? class : "default", chan->name);
-
- return 0;
-}
-
-static int moh4_exec(struct ast_channel *chan, void *data)
-{
- ast_moh_stop(chan);
-
- return 0;
-}
-
-static struct mohclass *get_mohbyname(char *name)
-{
- struct mohclass *moh;
- moh = mohclasses;
- while (moh) {
- if (!strcasecmp(name, moh->name))
- return moh;
- moh = moh->next;
- }
- return NULL;
-}
-
-static struct mohdata *mohalloc(struct mohclass *cl)
-{
- struct mohdata *moh;
- long flags;
- moh = malloc(sizeof(struct mohdata));
- if (!moh)
- return NULL;
- memset(moh, 0, sizeof(struct mohdata));
- if (pipe(moh->pipe)) {
- ast_log(LOG_WARNING, "Failed to create pipe: %s\n", strerror(errno));
- free(moh);
- return NULL;
- }
- /* Make entirely non-blocking */
- flags = fcntl(moh->pipe[0], F_GETFL);
- fcntl(moh->pipe[0], F_SETFL, flags | O_NONBLOCK);
- flags = fcntl(moh->pipe[1], F_GETFL);
- fcntl(moh->pipe[1], F_SETFL, flags | O_NONBLOCK);
- moh->parent = cl;
- moh->next = cl->members;
- cl->members = moh;
- return moh;
-}
-
-static void moh_release(struct ast_channel *chan, void *data)
-{
- struct mohdata *moh = data, *prev, *cur;
- int oldwfmt;
- ast_mutex_lock(&moh_lock);
- /* Unlink */
- prev = NULL;
- cur = moh->parent->members;
- while (cur) {
- if (cur == moh) {
- if (prev)
- prev->next = cur->next;
- else
- moh->parent->members = cur->next;
- break;
- }
- prev = cur;
- cur = cur->next;
- }
- ast_mutex_unlock(&moh_lock);
- close(moh->pipe[0]);
- close(moh->pipe[1]);
- oldwfmt = moh->origwfmt;
- free(moh);
- if (chan) {
- if (oldwfmt && ast_set_write_format(chan, oldwfmt))
- ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(oldwfmt));
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Stopped music on hold on %s\n", chan->name);
- }
-}
-
-static void *moh_alloc(struct ast_channel *chan, void *params)
-{
- struct mohdata *res;
- struct mohclass *class = params;
-
- res = mohalloc(class);
- if (res) {
- res->origwfmt = chan->writeformat;
- if (ast_set_write_format(chan, class->format)) {
- ast_log(LOG_WARNING, "Unable to set channel '%s' to format '%s'\n", chan->name, ast_codec2str(class->format));
- moh_release(NULL, res);
- res = NULL;
- }
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Started music on hold, class '%s', on channel '%s'\n", class->name, chan->name);
- }
- return res;
-}
-
-static int moh_generate(struct ast_channel *chan, void *data, int len, int samples)
-{
- struct ast_frame f;
- struct mohdata *moh = data;
- short buf[1280 + AST_FRIENDLY_OFFSET / 2];
- int res;
-
- if (!moh->parent->pid)
- return -1;
-
- len = ast_codec_get_len(moh->parent->format, samples);
-
- if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
- ast_log(LOG_WARNING, "Only doing %d of %d requested bytes on %s\n", (int)sizeof(buf), len, chan->name);
- len = sizeof(buf) - AST_FRIENDLY_OFFSET;
- }
- res = read(moh->pipe[0], buf + AST_FRIENDLY_OFFSET/2, len);
-#if 0
- if (res != len) {
- ast_log(LOG_WARNING, "Read only %d of %d bytes: %s\n", res, len, strerror(errno));
- }
-#endif
- if (res <= 0)
- return 0;
-
- memset(&f, 0, sizeof(f));
-
- f.frametype = AST_FRAME_VOICE;
- f.subclass = moh->parent->format;
- f.mallocd = 0;
- f.datalen = res;
- f.data = buf + AST_FRIENDLY_OFFSET / 2;
- f.offset = AST_FRIENDLY_OFFSET;
- f.samples = ast_codec_get_samples(&f);
-
- if (ast_write(chan, &f) < 0) {
- ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
- return -1;
- }
-
- return 0;
-}
-
-static struct ast_generator mohgen =
-{
- alloc: moh_alloc,
- release: moh_release,
- generate: moh_generate,
-};
-
-static int moh_scan_files(struct mohclass *class) {
-
- DIR *files_DIR;
- struct dirent *files_dirent;
- char path[512];
- char filepath[MAX_MOHFILE_LEN];
- char *ext;
- struct stat statbuf;
- int dirnamelen;
- int i;
-
- files_DIR = opendir(class->dir);
- if (!files_DIR) {
- ast_log(LOG_WARNING, "Cannot open dir %s or dir does not exist", class->dir);
- return -1;
- }
-
- class->total_files = 0;
- dirnamelen = strlen(class->dir) + 2;
- getcwd(path, 512);
- chdir(class->dir);
- memset(class->filearray, 0, MAX_MOHFILES*MAX_MOHFILE_LEN);
- while ((files_dirent = readdir(files_DIR))) {
- if ((strlen(files_dirent->d_name) < 4) || ((strlen(files_dirent->d_name) + dirnamelen) >= MAX_MOHFILE_LEN))
- continue;
-
- snprintf(filepath, MAX_MOHFILE_LEN, "%s/%s", class->dir, files_dirent->d_name);
-
- if (stat(filepath, &statbuf))
- continue;
-
- if (!S_ISREG(statbuf.st_mode))
- continue;
-
- if ((ext = strrchr(filepath, '.'))) {
- *ext = '\0';
- ext++;
- }
-
- /* if the file is present in multiple formats, ensure we only put it into the list once */
- for (i = 0; i < class->total_files; i++)
- if (!strcmp(filepath, class->filearray[i]))
- break;
-
- if (i == class->total_files)
- strcpy(class->filearray[class->total_files++], filepath);
- }
-
- closedir(files_DIR);
- chdir(path);
- return class->total_files;
-}
-
-static int moh_register(struct mohclass *moh, int reload)
-{
-#ifdef ZAPATA_MOH
- int x;
-#endif
- ast_mutex_lock(&moh_lock);
- if (get_mohbyname(moh->name)) {
- if (reload) {
- ast_log(LOG_DEBUG, "Music on Hold class '%s' left alone from initial load.\n", moh->name);
- } else {
- ast_log(LOG_WARNING, "Music on Hold class '%s' already exists\n", moh->name);
- }
- free(moh);
- ast_mutex_unlock(&moh_lock);
- return -1;
- }
- ast_mutex_unlock(&moh_lock);
-
- time(&moh->start);
- moh->start -= respawn_time;
-
- if (!strcasecmp(moh->mode, "files")) {
- if (!moh_scan_files(moh)) {
- ast_moh_free_class(&moh);
- return -1;
- }
- if (strchr(moh->args, 'r'))
- ast_set_flag(moh, MOH_RANDOMIZE);
- } else if (!strcasecmp(moh->mode, "mp3") || !strcasecmp(moh->mode, "mp3nb") || !strcasecmp(moh->mode, "quietmp3") || !strcasecmp(moh->mode, "quietmp3nb") || !strcasecmp(moh->mode, "httpmp3") || !strcasecmp(moh->mode, "custom")) {
-
- if (!strcasecmp(moh->mode, "custom"))
- ast_set_flag(moh, MOH_CUSTOM);
- else if (!strcasecmp(moh->mode, "mp3nb"))
- ast_set_flag(moh, MOH_SINGLE);
- else if (!strcasecmp(moh->mode, "quietmp3nb"))
- ast_set_flag(moh, MOH_SINGLE | MOH_QUIET);
- else if (!strcasecmp(moh->mode, "quietmp3"))
- ast_set_flag(moh, MOH_QUIET);
-
- moh->srcfd = -1;
-#ifdef ZAPATA_MOH
- /* Open /dev/zap/pseudo for timing... Is
- there a better, yet reliable way to do this? */
- moh->pseudofd = open("/dev/zap/pseudo", O_RDONLY);
- if (moh->pseudofd < 0) {
- ast_log(LOG_WARNING, "Unable to open pseudo channel for timing... Sound may be choppy.\n");
- } else {
- x = 320;
- ioctl(moh->pseudofd, ZT_SET_BLOCKSIZE, &x);
- }
-#else
- moh->pseudofd = -1;
-#endif
- if (ast_pthread_create(&moh->thread, NULL, monmp3thread, moh)) {
- ast_log(LOG_WARNING, "Unable to create moh...\n");
- if (moh->pseudofd > -1)
- close(moh->pseudofd);
- ast_moh_free_class(&moh);
- return -1;
- }
- } else {
- ast_log(LOG_WARNING, "Don't know how to do a mode '%s' music on hold\n", moh->mode);
- ast_moh_free_class(&moh);
- return -1;
- }
- ast_mutex_lock(&moh_lock);
- moh->next = mohclasses;
- mohclasses = moh;
- ast_mutex_unlock(&moh_lock);
- return 0;
-}
-
-static void local_ast_moh_cleanup(struct ast_channel *chan)
-{
- if (chan->music_state) {
- free(chan->music_state);
- chan->music_state = NULL;
- }
-}
-
-static int local_ast_moh_start(struct ast_channel *chan, char *class)
-{
- struct mohclass *mohclass;
-
- if (ast_strlen_zero(class))
- class = chan->musicclass;
- if (ast_strlen_zero(class))
- class = "default";
- ast_mutex_lock(&moh_lock);
- mohclass = get_mohbyname(class);
- ast_mutex_unlock(&moh_lock);
-
- if (!mohclass) {
- ast_log(LOG_WARNING, "No class: %s\n", (char *)class);
- return -1;
- }
-
- ast_set_flag(chan, AST_FLAG_MOH);
- if (mohclass->total_files) {
- return ast_activate_generator(chan, &moh_file_stream, mohclass);
- } else
- return ast_activate_generator(chan, &mohgen, mohclass);
-}
-
-static void local_ast_moh_stop(struct ast_channel *chan)
-{
- ast_clear_flag(chan, AST_FLAG_MOH);
- ast_deactivate_generator(chan);
-
- if (chan->music_state) {
- if (chan->stream) {
- ast_closestream(chan->stream);
- chan->stream = NULL;
- }
- }
-}
-
-static struct mohclass *moh_class_malloc(void)
-{
- struct mohclass *class;
-
- class = malloc(sizeof(struct mohclass));
-
- if (!class)
- return NULL;
-
- memset(class, 0, sizeof(struct mohclass));
-
- class->format = AST_FORMAT_SLINEAR;
-
- return class;
-}
-
-static int load_moh_classes(int reload)
-{
- struct ast_config *cfg;
- struct ast_variable *var;
- struct mohclass *class;
- char *data;
- char *args;
- char *cat;
- int numclasses = 0;
- static int dep_warning = 0;
-
- cfg = ast_config_load("musiconhold.conf");
-
- if (!cfg)
- return 0;
-
- cat = ast_category_browse(cfg, NULL);
- for (; cat; cat = ast_category_browse(cfg, cat)) {
- if (strcasecmp(cat, "classes") && strcasecmp(cat, "moh_files")) {
- class = moh_class_malloc();
- if (!class) {
- ast_log(LOG_WARNING, "Out of memory!\n");
- break;
- }
- ast_copy_string(class->name, cat, sizeof(class->name));
- var = ast_variable_browse(cfg, cat);
- while (var) {
- if (!strcasecmp(var->name, "mode"))
- ast_copy_string(class->mode, var->value, sizeof(class->mode));
- else if (!strcasecmp(var->name, "directory"))
- ast_copy_string(class->dir, var->value, sizeof(class->dir));
- else if (!strcasecmp(var->name, "application"))
- ast_copy_string(class->args, var->value, sizeof(class->args));
- else if (!strcasecmp(var->name, "random"))
- ast_set2_flag(class, ast_true(var->value), MOH_RANDOMIZE);
- else if (!strcasecmp(var->name, "format")) {
- class->format = ast_getformatbyname(var->value);
- if (!class->format) {
- ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", var->value);
- class->format = AST_FORMAT_SLINEAR;
- }
- }
- var = var->next;
- }
-
- if (ast_strlen_zero(class->dir)) {
- if (!strcasecmp(class->mode, "custom")) {
- strcpy(class->dir, "nodir");
- } else {
- ast_log(LOG_WARNING, "A directory must be specified for class '%s'!\n", class->name);
- free(class);
- continue;
- }
- }
- if (ast_strlen_zero(class->mode)) {
- ast_log(LOG_WARNING, "A mode must be specified for class '%s'!\n", class->name);
- free(class);
- continue;
- }
- if (ast_strlen_zero(class->args) && !strcasecmp(class->mode, "custom")) {
- ast_log(LOG_WARNING, "An application must be specified for class '%s'!\n", class->name);
- free(class);
- continue;
- }
-
- /* Don't leak a class when it's already registered */
- moh_register(class, reload);
-
- numclasses++;
- }
- }
-
-
- /* Deprecated Old-School Configuration */
- var = ast_variable_browse(cfg, "classes");
- while (var) {
- if (!dep_warning) {
- ast_log(LOG_WARNING, "The old musiconhold.conf syntax has been deprecated! Please refer to the sample configuration for information on the new syntax.\n");
- dep_warning = 1;
- }
- data = strchr(var->value, ':');
- if (data) {
- *data++ = '\0';
- args = strchr(data, ',');
- if (args)
- *args++ = '\0';
- if (!(get_mohbyname(var->name))) {
- class = moh_class_malloc();
- if (!class) {
- ast_log(LOG_WARNING, "Out of memory!\n");
- return numclasses;
- }
-
- ast_copy_string(class->name, var->name, sizeof(class->name));
- ast_copy_string(class->dir, data, sizeof(class->dir));
- ast_copy_string(class->mode, var->value, sizeof(class->mode));
- if (args)
- ast_copy_string(class->args, args, sizeof(class->args));
-
- moh_register(class, reload);
- numclasses++;
- }
- }
- var = var->next;
- }
- var = ast_variable_browse(cfg, "moh_files");
- while (var) {
- if (!dep_warning) {
- ast_log(LOG_WARNING, "The old musiconhold.conf syntax has been deprecated! Please refer to the sample configuration for information on the new syntax.\n");
- dep_warning = 1;
- }
- if (!(get_mohbyname(var->name))) {
- args = strchr(var->value, ',');
- if (args)
- *args++ = '\0';
- class = moh_class_malloc();
- if (!class) {
- ast_log(LOG_WARNING, "Out of memory!\n");
- return numclasses;
- }
-
- ast_copy_string(class->name, var->name, sizeof(class->name));
- ast_copy_string(class->dir, var->value, sizeof(class->dir));
- strcpy(class->mode, "files");
- if (args)
- ast_copy_string(class->args, args, sizeof(class->args));
-
- moh_register(class, reload);
- numclasses++;
- }
- var = var->next;
- }
-
- ast_config_destroy(cfg);
-
- return numclasses;
-}
-
-static void ast_moh_destroy(void)
-{
- struct mohclass *moh, *tmp;
- char buff[8192];
- int bytes, tbytes=0, stime = 0, pid = 0;
-
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Destroying musiconhold processes\n");
- ast_mutex_lock(&moh_lock);
- moh = mohclasses;
-
- while (moh) {
- if (moh->pid) {
- ast_log(LOG_DEBUG, "killing %d!\n", moh->pid);
- stime = time(NULL) + 2;
- pid = moh->pid;
- moh->pid = 0;
- kill(pid, SIGKILL);
- while ((ast_wait_for_input(moh->srcfd, 100) > 0) && (bytes = read(moh->srcfd, buff, 8192)) && time(NULL) < stime) {
- tbytes = tbytes + bytes;
- }
- ast_log(LOG_DEBUG, "mpg123 pid %d and child died after %d bytes read\n", pid, tbytes);
- close(moh->srcfd);
- }
- tmp = moh;
- moh = moh->next;
- ast_moh_free_class(&tmp);
- }
- mohclasses = NULL;
- ast_mutex_unlock(&moh_lock);
-}
-
-static void moh_on_off(int on)
-{
- struct ast_channel *chan = NULL;
-
- while ( (chan = ast_channel_walk_locked(chan)) != NULL) {
- if (ast_test_flag(chan, AST_FLAG_MOH)) {
- if (on)
- local_ast_moh_start(chan, NULL);
- else
- ast_deactivate_generator(chan);
- }
- ast_mutex_unlock(&chan->lock);
- }
-}
-
-static int moh_cli(int fd, int argc, char *argv[])
-{
- int x;
-
- moh_on_off(0);
- ast_moh_destroy();
- x = load_moh_classes(1);
- moh_on_off(1);
- ast_cli(fd, "\n%d class%s reloaded.\n", x, x == 1 ? "" : "es");
- return 0;
-}
-
-static int cli_files_show(int fd, int argc, char *argv[])
-{
- int i;
- struct mohclass *class;
-
- ast_mutex_lock(&moh_lock);
- for (class = mohclasses; class; class = class->next) {
- if (!class->total_files)
- continue;
-
- ast_cli(fd, "Class: %s\n", class->name);
- for (i = 0; i < class->total_files; i++)
- ast_cli(fd, "\tFile: %s\n", class->filearray[i]);
- }
- ast_mutex_unlock(&moh_lock);
-
- return 0;
-}
-
-static int moh_classes_show(int fd, int argc, char *argv[])
-{
- struct mohclass *class;
-
- ast_mutex_lock(&moh_lock);
- for (class = mohclasses; class; class = class->next) {
- ast_cli(fd, "Class: %s\n", class->name);
- ast_cli(fd, "\tMode: %s\n", ast_strlen_zero(class->mode) ? "<none>" : class->mode);
- ast_cli(fd, "\tDirectory: %s\n", ast_strlen_zero(class->dir) ? "<none>" : class->dir);
- if (ast_test_flag(class, MOH_CUSTOM))
- ast_cli(fd, "\tApplication: %s\n", ast_strlen_zero(class->args) ? "<none>" : class->args);
- ast_cli(fd, "\tFormat: %s\n", ast_getformatname(class->format));
- }
- ast_mutex_unlock(&moh_lock);
-
- return 0;
-}
-
-static struct ast_cli_entry cli_moh = { { "moh", "reload"}, moh_cli, "Music On Hold", "Music On Hold", NULL};
-
-static struct ast_cli_entry cli_moh_classes_show = { { "moh", "classes", "show"}, moh_classes_show, "List MOH classes", "Lists all MOH classes", NULL};
-
-static struct ast_cli_entry cli_moh_files_show = { { "moh", "files", "show"}, cli_files_show, "List MOH file-based classes", "Lists all loaded file-based MOH classes and their files", NULL};
-
-static int init_classes(int reload)
-{
- struct mohclass *moh;
-
- if (!load_moh_classes(reload)) /* Load classes from config */
- return 0; /* Return if nothing is found */
- moh = mohclasses;
- while (moh) {
- if (moh->total_files)
- moh_scan_files(moh);
- moh = moh->next;
- }
- return 1;
-}
-
-int load_module(void)
-{
- int res;
-
- res = ast_register_application(app0, moh0_exec, synopsis0, descrip0);
- ast_register_atexit(ast_moh_destroy);
- ast_cli_register(&cli_moh);
- ast_cli_register(&cli_moh_files_show);
- ast_cli_register(&cli_moh_classes_show);
- if (!res)
- res = ast_register_application(app1, moh1_exec, synopsis1, descrip1);
- if (!res)
- res = ast_register_application(app2, moh2_exec, synopsis2, descrip2);
- if (!res)
- res = ast_register_application(app3, moh3_exec, synopsis3, descrip3);
- if (!res)
- res = ast_register_application(app4, moh4_exec, synopsis4, descrip4);
-
- if (!init_classes(0)) { /* No music classes configured, so skip it */
- ast_log(LOG_WARNING, "No music on hold classes configured, disabling music on hold.");
- } else {
- ast_install_music_functions(local_ast_moh_start, local_ast_moh_stop, local_ast_moh_cleanup);
- }
-
- return 0;
-}
-
-int reload(void)
-{
- if (init_classes(1))
- ast_install_music_functions(local_ast_moh_start, local_ast_moh_stop, local_ast_moh_cleanup);
-
- return 0;
-}
-
-int unload_module(void)
-{
- return -1;
-}
-
-char *description(void)
-{
- return "Music On Hold Resource";
-}
-
-int usecount(void)
-{
- /* Never allow Music On Hold to be unloaded
- unresolve needed symbols in the dialer */
-#if 0
- int res;
- STANDARD_USECOUNT(res);
- return res;
-#else
- return 1;
-#endif
-}
-
-char *key()
-{
- return ASTERISK_GPL_KEY;
-}
diff --git a/1.2-netsec/res/res_odbc.c b/1.2-netsec/res/res_odbc.c
deleted file mode 100644
index cc4b61f2d..000000000
--- a/1.2-netsec/res/res_odbc.c
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * res_odbc.c <ODBC resource manager>
- * Copyright (C) 2004 - 2005 Anthony Minessale II <anthmct@yahoo.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-
-/*! \file
- *
- * \brief ODBC resource manager
- *
- * \arg See also: \ref cdr_odbc
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/file.h"
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/config.h"
-#include "asterisk/options.h"
-#include "asterisk/pbx.h"
-#include "asterisk/module.h"
-#include "asterisk/cli.h"
-#include "asterisk/lock.h"
-#include "asterisk/res_odbc.h"
-#define MAX_ODBC_HANDLES 25
-
-struct odbc_list
-{
- char name[80];
- odbc_obj *obj;
- int used;
-};
-
-static struct odbc_list ODBC_REGISTRY[MAX_ODBC_HANDLES];
-
-
-static void odbc_destroy(void)
-{
- int x = 0;
-
- for (x = 0; x < MAX_ODBC_HANDLES; x++) {
- if (ODBC_REGISTRY[x].obj) {
- destroy_odbc_obj(&ODBC_REGISTRY[x].obj);
- ODBC_REGISTRY[x].obj = NULL;
- }
- }
-}
-
-static odbc_obj *odbc_read(struct odbc_list *registry, const char *name)
-{
- int x = 0;
- for (x = 0; x < MAX_ODBC_HANDLES; x++) {
- if (registry[x].used && !strcmp(registry[x].name, name)) {
- return registry[x].obj;
- }
- }
- return NULL;
-}
-
-static int odbc_write(struct odbc_list *registry, char *name, odbc_obj *obj)
-{
- int x = 0;
- for (x = 0; x < MAX_ODBC_HANDLES; x++) {
- if (!registry[x].used) {
- ast_copy_string(registry[x].name, name, sizeof(registry[x].name));
- registry[x].obj = obj;
- registry[x].used = 1;
- return 1;
- }
- }
- return 0;
-}
-
-static void odbc_init(void)
-{
- int x = 0;
- for (x = 0; x < MAX_ODBC_HANDLES; x++) {
- memset(&ODBC_REGISTRY[x], 0, sizeof(struct odbc_list));
- }
-}
-
-static char *tdesc = "ODBC Resource";
-/* internal stuff */
-
-SQLHSTMT odbc_prepare_and_execute(odbc_obj *obj, SQLHSTMT (*prepare_cb)(odbc_obj *obj, void *data), void *data)
-{
- int res = 0, i, attempt;
- SQLINTEGER nativeerror=0, numfields=0;
- SQLSMALLINT diagbytes=0;
- unsigned char state[10], diagnostic[256];
- SQLHSTMT stmt;
-
- for (attempt = 0; attempt < 2; attempt++) {
- /* This prepare callback may do more than just prepare -- it may also
- * bind parameters, bind results, etc. The real key, here, is that
- * when we disconnect, all handles become invalid for most databases.
- * We must therefore redo everything when we establish a new
- * connection. */
- stmt = prepare_cb(obj, data);
-
- if (stmt) {
- res = SQLExecute(stmt);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
- if (res == SQL_ERROR) {
- SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes);
- for (i=0; i< numfields + 1; i++) {
- SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes);
- ast_log(LOG_WARNING, "SQL Execute returned an error %d: %s: %s (%d)\n", res, state, diagnostic, diagbytes);
- if (i > 10) {
- ast_log(LOG_WARNING, "Oh, that was good. There are really %d diagnostics?\n", (int)numfields);
- break;
- }
- }
- }
-
- ast_log(LOG_WARNING, "SQL Execute error %d! Attempting a reconnect...\n", res);
- SQLFreeHandle(SQL_HANDLE_STMT, stmt);
-
- ast_mutex_lock(&obj->lock);
- obj->up = 0;
- ast_mutex_unlock(&obj->lock);
- odbc_obj_disconnect(obj);
- odbc_obj_connect(obj);
- continue;
- }
- break;
- }
- }
-
- return stmt;
-}
-
-int odbc_smart_execute(odbc_obj *obj, SQLHSTMT stmt)
-{
- int res = 0, i;
- SQLINTEGER nativeerror=0, numfields=0;
- SQLSMALLINT diagbytes=0;
- unsigned char state[10], diagnostic[256];
-
- res = SQLExecute(stmt);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
- if (res == SQL_ERROR) {
- SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes);
- for (i=0; i< numfields + 1; i++) {
- SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes);
- ast_log(LOG_WARNING, "SQL Execute returned an error %d: %s: %s (%d)\n", res, state, diagnostic, diagbytes);
- if (i > 10) {
- ast_log(LOG_WARNING, "Oh, that was good. There are really %d diagnostics?\n", (int)numfields);
- break;
- }
- }
- }
-/*
- ast_log(LOG_WARNING, "SQL Execute error %d! Attempting a reconnect...\n", res);
- ast_mutex_lock(&obj->lock);
- obj->up = 0;
- ast_mutex_unlock(&obj->lock);
- odbc_obj_disconnect(obj);
- odbc_obj_connect(obj);
- res = SQLExecute(stmt);
-*/
- }
-
- return res;
-}
-
-
-int odbc_smart_direct_execute(odbc_obj *obj, SQLHSTMT stmt, char *sql)
-{
- int res = 0;
-
- res = SQLExecDirect (stmt, (unsigned char *)sql, SQL_NTS);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Execute error! Attempting a reconnect...\n");
- ast_mutex_lock(&obj->lock);
- obj->up = 0;
- ast_mutex_unlock(&obj->lock);
- odbc_obj_disconnect(obj);
- odbc_obj_connect(obj);
- res = SQLExecDirect (stmt, (unsigned char *)sql, SQL_NTS);
- }
-
- return res;
-}
-
-int odbc_sanity_check(odbc_obj *obj)
-{
- char *test_sql = "select 1";
- SQLHSTMT stmt;
- int res = 0;
-
- ast_mutex_lock(&obj->lock);
- if(obj->up) { /* so you say... let's make sure */
- res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- obj->up = 0; /* Liar!*/
- } else {
- res = SQLPrepare(stmt, (unsigned char *)test_sql, SQL_NTS);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- obj->up = 0; /* Liar!*/
- } else {
- res = SQLExecute(stmt);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- obj->up = 0; /* Liar!*/
- }
- }
- }
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- }
- ast_mutex_unlock(&obj->lock);
-
- if(!obj->up) { /* Try to reconnect! */
- ast_log(LOG_WARNING, "Connection is down attempting to reconnect...\n");
- odbc_obj_disconnect(obj);
- odbc_obj_connect(obj);
- }
- return obj->up;
-}
-
-static int load_odbc_config(void)
-{
- static char *cfg = "res_odbc.conf";
- struct ast_config *config;
- struct ast_variable *v;
- char *cat, *dsn, *username, *password;
- int enabled;
- int connect = 0;
- char *env_var;
-
- odbc_obj *obj;
-
- config = ast_config_load(cfg);
- if (config) {
- for (cat = ast_category_browse(config, NULL); cat; cat=ast_category_browse(config, cat)) {
- if (!strcmp(cat, "ENV")) {
- for (v = ast_variable_browse(config, cat); v; v = v->next) {
- env_var = malloc(strlen(v->name) + strlen(v->value) + 2);
- if (env_var) {
- sprintf(env_var, "%s=%s", v->name, v->value);
- ast_log(LOG_NOTICE, "Adding ENV var: %s=%s\n", v->name, v->value);
- putenv(env_var);
- free(env_var);
- }
- }
-
- cat = ast_category_browse(config, cat);
- }
-
- dsn = username = password = NULL;
- enabled = 1;
- connect = 0;
- for (v = ast_variable_browse(config, cat); v; v = v->next) {
- if (!strcmp(v->name, "enabled"))
- enabled = ast_true(v->value);
- if (!strcmp(v->name, "pre-connect"))
- connect = ast_true(v->value);
- if (!strcmp(v->name, "dsn"))
- dsn = v->value;
- if (!strcmp(v->name, "username"))
- username = v->value;
- if (!strcmp(v->name, "password"))
- password = v->value;
- }
-
- if (enabled && dsn) {
- obj = new_odbc_obj(cat, dsn, username, password);
- if (obj) {
- register_odbc_obj(cat, obj);
- ast_log(LOG_NOTICE, "registered database handle '%s' dsn->[%s]\n", cat, obj->dsn);
- if (connect) {
- odbc_obj_connect(obj);
- }
- } else {
- ast_log(LOG_WARNING, "Addition of obj %s failed.\n", cat);
- }
-
- }
- }
- ast_config_destroy(config);
- }
- return 0;
-}
-
-int odbc_dump_fd(int fd, odbc_obj *obj)
-{
- /* make sure the connection is up before we lie to our master.*/
- odbc_sanity_check(obj);
- ast_cli(fd, "Name: %s\nDSN: %s\nConnected: %s\n\n", obj->name, obj->dsn, obj->up ? "yes" : "no");
- return 0;
-}
-
-static int odbc_connect_usage(int fd)
-{
- ast_cli(fd, "usage odbc connect <DSN>\n");
- return 0;
-}
-
-static int odbc_disconnect_usage(int fd)
-{
- ast_cli(fd, "usage odbc disconnect <DSN>\n");
- return 0;
-}
-
-static int odbc_show_command(int fd, int argc, char **argv)
-{
- odbc_obj *obj;
- int x = 0;
-
- if (!strcmp(argv[1], "show")) {
- if (!argv[2] || (argv[2] && !strcmp(argv[2], "all"))) {
- for (x = 0; x < MAX_ODBC_HANDLES; x++) {
- if (!ODBC_REGISTRY[x].used)
- break;
- if (ODBC_REGISTRY[x].obj)
- odbc_dump_fd(fd, ODBC_REGISTRY[x].obj);
- }
- } else {
- obj = odbc_read(ODBC_REGISTRY, argv[2]);
- if (obj)
- odbc_dump_fd(fd, obj);
- }
- }
- return 0;
-}
-
-static int odbc_disconnect_command(int fd, int argc, char **argv)
-{
- odbc_obj *obj;
- if (!strcmp(argv[1], "disconnect")) {
- if (!argv[2])
- return odbc_disconnect_usage(fd);
-
- obj = odbc_read(ODBC_REGISTRY, argv[2]);
- if (obj) {
- odbc_obj_disconnect(obj);
- }
- }
- return 0;
-}
-
-static int odbc_connect_command(int fd, int argc, char **argv)
-{
- odbc_obj *obj;
- if (!argv[1])
- return odbc_connect_usage(fd);
-
- if (!strcmp(argv[1], "connect") || !strcmp(argv[1], "disconnect")) {
- if (!argv[2])
- return odbc_connect_usage(fd);
-
- obj = odbc_read(ODBC_REGISTRY, argv[2]);
- if (obj) {
- odbc_obj_connect(obj);
- }
- }
- return 0;
-}
-
-
-static char connect_usage[] =
-"Usage: odbc connect <DSN>\n"
-" Connect to ODBC DSN\n";
-
-static char disconnect_usage[] =
-"Usage: odbc connect <DSN>\n"
-" Disconnect from ODBC DSN\n";
-
-static char show_usage[] =
-"Usage: odbc show {DSN}\n"
-" Show ODBC {DSN}\n"
-" Specifying DSN will show that DSN else, all DSNs are shown\n";
-
-static struct ast_cli_entry odbc_connect_struct =
- { { "odbc", "connect", NULL }, odbc_connect_command, "Connect to ODBC DSN", connect_usage };
-
-
-static struct ast_cli_entry odbc_disconnect_struct =
- { { "odbc", "disconnect", NULL }, odbc_disconnect_command, "Disconnect from ODBC DSN", disconnect_usage };
-
-static struct ast_cli_entry odbc_show_struct =
- { { "odbc", "show", NULL }, odbc_show_command, "Show ODBC DSN(s)", show_usage };
-
-/* api calls */
-
-int register_odbc_obj(char *name, odbc_obj *obj)
-{
- if (obj != NULL)
- return odbc_write(ODBC_REGISTRY, name, obj);
- return 0;
-}
-
-odbc_obj *fetch_odbc_obj(const char *name, int check)
-{
- odbc_obj *obj = NULL;
- if((obj = (odbc_obj *) odbc_read(ODBC_REGISTRY, name))) {
- if(check)
- odbc_sanity_check(obj);
- }
- return obj;
-}
-
-odbc_obj *new_odbc_obj(char *name, char *dsn, char *username, char *password)
-{
- static odbc_obj *new;
-
- if (!(new = calloc(1, sizeof(*new))) ||
- !(new->name = malloc(strlen(name) + 1)) ||
- !(new->dsn = malloc(strlen(dsn) + 1)))
- goto cleanup;
-
- if (username) {
- if (!(new->username = malloc(strlen(username) + 1)))
- goto cleanup;
- strcpy(new->username, username);
- }
-
- if (password) {
- if (!(new->password = malloc(strlen(password) + 1)))
- goto cleanup;
- strcpy(new->password, password);
- }
-
- strcpy(new->name, name);
- strcpy(new->dsn, dsn);
- new->env = SQL_NULL_HANDLE;
- new->up = 0;
- ast_mutex_init(&new->lock);
- return new;
-
-cleanup:
- if (new) {
- free(new->name);
- free(new->dsn);
- free(new->username);
- free(new->password);
-
- free(new);
- }
-
- return NULL;
-}
-
-void destroy_odbc_obj(odbc_obj **obj)
-{
- odbc_obj_disconnect(*obj);
-
- ast_mutex_lock(&(*obj)->lock);
- SQLFreeHandle(SQL_HANDLE_STMT, (*obj)->stmt);
- SQLFreeHandle(SQL_HANDLE_DBC, (*obj)->con);
- SQLFreeHandle(SQL_HANDLE_ENV, (*obj)->env);
-
- free((*obj)->name);
- free((*obj)->dsn);
- if ((*obj)->username)
- free((*obj)->username);
- if ((*obj)->password)
- free((*obj)->password);
- ast_mutex_unlock(&(*obj)->lock);
- ast_mutex_destroy(&(*obj)->lock);
- free(*obj);
-}
-
-odbc_status odbc_obj_disconnect(odbc_obj *obj)
-{
- int res;
- ast_mutex_lock(&obj->lock);
-
- res = SQLDisconnect(obj->con);
-
-
- if (res == ODBC_SUCCESS) {
- ast_log(LOG_WARNING, "res_odbc: disconnected %d from %s [%s]\n", res, obj->name, obj->dsn);
- } else {
- ast_log(LOG_WARNING, "res_odbc: %s [%s] already disconnected\n",
- obj->name, obj->dsn);
- }
- obj->up = 0;
- ast_mutex_unlock(&obj->lock);
- return ODBC_SUCCESS;
-}
-
-odbc_status odbc_obj_connect(odbc_obj *obj)
-{
- int res;
- SQLINTEGER err;
- short int mlen;
- unsigned char msg[200], stat[10];
-
- ast_mutex_lock(&obj->lock);
-
- if (obj->env == SQL_NULL_HANDLE) {
- res = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &obj->env);
-
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- if (option_verbose > 3)
- ast_log(LOG_WARNING, "res_odbc: Error AllocHandle\n");
- ast_mutex_unlock(&obj->lock);
- return ODBC_FAIL;
- }
-
- res = SQLSetEnvAttr(obj->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
-
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- if (option_verbose > 3)
- ast_log(LOG_WARNING, "res_odbc: Error SetEnv\n");
- SQLFreeHandle(SQL_HANDLE_ENV, obj->env);
- ast_mutex_unlock(&obj->lock);
- return ODBC_FAIL;
- }
-
- res = SQLAllocHandle(SQL_HANDLE_DBC, obj->env, &obj->con);
-
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-
- if (option_verbose > 3)
- ast_log(LOG_WARNING, "res_odbc: Error AllocHDB %d\n", res);
- SQLFreeHandle(SQL_HANDLE_ENV, obj->env);
-
- ast_mutex_unlock(&obj->lock);
- return ODBC_FAIL;
- }
- SQLSetConnectAttr(obj->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0);
- }
- if(obj->up) {
- odbc_obj_disconnect(obj);
- ast_log(LOG_NOTICE,"Re-connecting %s\n", obj->name);
- }
-
- ast_log(LOG_NOTICE, "Connecting %s\n", obj->name);
-
- res = SQLConnect(obj->con,
- (SQLCHAR *) obj->dsn, SQL_NTS,
- (SQLCHAR *) obj->username, SQL_NTS,
- (SQLCHAR *) obj->password, SQL_NTS);
-
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- SQLGetDiagRec(SQL_HANDLE_DBC, obj->con, 1, stat, &err, msg, 100, &mlen);
- SQLFreeHandle(SQL_HANDLE_ENV, obj->env);
- ast_mutex_unlock(&obj->lock);
- ast_log(LOG_WARNING, "res_odbc: Error SQLConnect=%d errno=%d %s\n", res, (int)err, msg);
- return ODBC_FAIL;
- } else {
-
- ast_log(LOG_NOTICE, "res_odbc: Connected to %s [%s]\n", obj->name, obj->dsn);
- obj->up = 1;
- }
-
- ast_mutex_unlock(&obj->lock);
- return ODBC_SUCCESS;
-}
-
-STANDARD_LOCAL_USER;
-
-LOCAL_USER_DECL;
-
-int unload_module(void)
-{
- STANDARD_HANGUP_LOCALUSERS;
- odbc_destroy();
- ast_cli_unregister(&odbc_disconnect_struct);
- ast_cli_unregister(&odbc_connect_struct);
- ast_cli_unregister(&odbc_show_struct);
- ast_log(LOG_NOTICE, "res_odbc unloaded.\n");
- return 0;
-}
-
-int load_module(void)
-{
- odbc_init();
- load_odbc_config();
- ast_cli_register(&odbc_disconnect_struct);
- ast_cli_register(&odbc_connect_struct);
- ast_cli_register(&odbc_show_struct);
- ast_log(LOG_NOTICE, "res_odbc loaded.\n");
- return 0;
-}
-
-char *description(void)
-{
- return tdesc;
-}
-
-int usecount(void)
-{
- int res;
- STANDARD_USECOUNT(res);
- return res;
-}
-
-char *key()
-{
- return ASTERISK_GPL_KEY;
-}
diff --git a/1.2-netsec/res/res_osp.c b/1.2-netsec/res/res_osp.c
deleted file mode 100644
index 41ca8c0cf..000000000
--- a/1.2-netsec/res/res_osp.c
+++ /dev/null
@@ -1,886 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Provide Open Settlement Protocol capability
- *
- * \arg See also: \ref chan_sip.c
- */
-
-#include <sys/types.h>
-#include <osp.h>
-#include <openssl/err.h>
-#include <stdio.h>
-#include <dirent.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <openssl/bio.h>
-#include <openssl/pem.h>
-#include <openssl/evp.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/file.h"
-#include "asterisk/channel.h"
-#include "asterisk/logger.h"
-#include "asterisk/say.h"
-#include "asterisk/module.h"
-#include "asterisk/options.h"
-#include "asterisk/crypto.h"
-#include "asterisk/md5.h"
-#include "asterisk/cli.h"
-#include "asterisk/io.h"
-#include "asterisk/lock.h"
-#include "asterisk/astosp.h"
-#include "asterisk/config.h"
-#include "asterisk/utils.h"
-#include "asterisk/lock.h"
-#include "asterisk/causes.h"
-#include "asterisk/callerid.h"
-#include "asterisk/pbx.h"
-
-#define MAX_CERTS 10
-#define MAX_SERVICEPOINTS 10
-#define OSP_MAX 256
-
-#define OSP_DEFAULT_MAX_CONNECTIONS 20
-#define OSP_DEFAULT_RETRY_DELAY 0
-#define OSP_DEFAULT_RETRY_LIMIT 2
-#define OSP_DEFAULT_TIMEOUT 500
-
-static int loadPemCert(unsigned char *FileName, unsigned char *buffer, int *len);
-static int loadPemPrivateKey(unsigned char *FileName, unsigned char *buffer, int *len);
-
-AST_MUTEX_DEFINE_STATIC(osplock);
-
-static int initialized = 0;
-static int hardware = 0;
-static unsigned tokenformat = TOKEN_ALGO_SIGNED;
-
-struct osp_provider {
- char name[OSP_MAX];
- char localpvtkey[OSP_MAX];
- char localcert[OSP_MAX];
- char cacerts[MAX_CERTS][OSP_MAX];
- int cacount;
- char servicepoints[MAX_SERVICEPOINTS][OSP_MAX];
- char source[OSP_MAX];
- int spcount;
- int dead;
- int maxconnections;
- int retrydelay;
- int retrylimit;
- int timeout;
- OSPTPROVHANDLE handle;
- struct osp_provider *next;
-};
-static struct osp_provider *providers;
-
-static int osp_build(struct ast_config *cfg, char *cat)
-{
- OSPTCERT TheAuthCert[MAX_CERTS];
- unsigned char Reqbuf[4096],LocalBuf[4096],AuthBuf[MAX_CERTS][4096];
- struct ast_variable *v;
- struct osp_provider *osp;
- int x,length,errorcode=0;
- int mallocd=0,i;
- char *cacerts[MAX_CERTS];
- const char *servicepoints[MAX_SERVICEPOINTS];
- OSPTPRIVATEKEY privatekey;
- OSPTCERT localcert;
- OSPTCERT *authCerts[MAX_CERTS];
-
-
-
- ast_mutex_lock(&osplock);
- osp = providers;
- while(osp) {
- if (!strcasecmp(osp->name, cat))
- break;
- osp = osp->next;
- }
- ast_mutex_unlock(&osplock);
- if (!osp) {
- mallocd = 1;
- osp = malloc(sizeof(struct osp_provider));
- if (!osp) {
- ast_log(LOG_WARNING, "Out of memory!\n");
- return -1;
- }
- memset(osp, 0, sizeof(struct osp_provider));
- osp->handle = -1;
- }
- ast_copy_string(osp->name, cat, sizeof(osp->name));
- snprintf(osp->localpvtkey, sizeof(osp->localpvtkey) ,"%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, cat);
- snprintf(osp->localcert, sizeof(osp->localpvtkey), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, cat);
- osp->maxconnections=OSP_DEFAULT_MAX_CONNECTIONS;
- osp->retrydelay = OSP_DEFAULT_RETRY_DELAY;
- osp->retrylimit = OSP_DEFAULT_RETRY_LIMIT;
- osp->timeout = OSP_DEFAULT_TIMEOUT;
- osp->source[0] = '\0';
- ast_log(LOG_DEBUG, "Building OSP Provider '%s'\n", cat);
- v = ast_variable_browse(cfg, cat);
- while(v) {
- if (!strcasecmp(v->name, "privatekey")) {
- if (v->value[0] == '/')
- ast_copy_string(osp->localpvtkey, v->value, sizeof(osp->localpvtkey));
- else
- snprintf(osp->localpvtkey, sizeof(osp->localpvtkey), "%s/%s", ast_config_AST_KEY_DIR , v->value);
- } else if (!strcasecmp(v->name, "localcert")) {
- if (v->value[0] == '/')
- ast_copy_string(osp->localcert, v->value, sizeof(osp->localcert));
- else
- snprintf(osp->localcert, sizeof(osp->localcert), "%s/%s", ast_config_AST_KEY_DIR, v->value);
- } else if (!strcasecmp(v->name, "cacert")) {
- if (osp->cacount < MAX_CERTS) {
- if (v->value[0] == '/')
- ast_copy_string(osp->cacerts[osp->cacount], v->value, sizeof(osp->cacerts[0]));
- else
- snprintf(osp->cacerts[osp->cacount], sizeof(osp->cacerts[0]), "%s/%s", ast_config_AST_KEY_DIR, v->value);
- osp->cacount++;
- } else
- ast_log(LOG_WARNING, "Too many CA Certificates at line %d\n", v->lineno);
- } else if (!strcasecmp(v->name, "servicepoint")) {
- if (osp->spcount < MAX_SERVICEPOINTS) {
- ast_copy_string(osp->servicepoints[osp->spcount], v->value, sizeof(osp->servicepoints[0]));
- osp->spcount++;
- } else
- ast_log(LOG_WARNING, "Too many Service points at line %d\n", v->lineno);
- } else if (!strcasecmp(v->name, "maxconnections")) {
- if ((sscanf(v->value, "%d", &x) == 1) && (x > 0) && (x <= 1000)) {
- osp->maxconnections = x;
- } else
- ast_log(LOG_WARNING, "maxconnections should be an integer from 1 to 1000, not '%s' at line %d\n", v->value, v->lineno);
- } else if (!strcasecmp(v->name, "retrydelay")) {
- if ((sscanf(v->value, "%d", &x) == 1) && (x >= 0) && (x <= 10)) {
- osp->retrydelay = x;
- } else
- ast_log(LOG_WARNING, "retrydelay should be an integer from 0 to 10, not '%s' at line %d\n", v->value, v->lineno);
- } else if (!strcasecmp(v->name, "retrylimit")) {
- if ((sscanf(v->value, "%d", &x) == 1) && (x >= 0) && (x <= 100)) {
- osp->retrylimit = x;
- } else
- ast_log(LOG_WARNING, "retrylimit should be an integer from 0 to 100, not '%s' at line %d\n", v->value, v->lineno);
- } else if (!strcasecmp(v->name, "timeout")) {
- if ((sscanf(v->value, "%d", &x) == 1) && (x >= 200) && (x <= 10000)) {
- osp->timeout = x;
- } else
- ast_log(LOG_WARNING, "timeout should be an integer from 200 to 10000, not '%s' at line %d\n", v->value, v->lineno);
- } else if (!strcasecmp(v->name, "source")) {
- ast_copy_string(osp->source, v->value, sizeof(osp->source));
- }
- v = v->next;
- }
- if (osp->cacount < 1) {
- snprintf(osp->cacerts[osp->cacount], sizeof(osp->cacerts[0]), "%s/%s-cacert.pem", ast_config_AST_KEY_DIR, cat);
- osp->cacount++;
- }
- for (x=0;x<osp->cacount;x++)
- cacerts[x] = osp->cacerts[x];
- for (x=0;x<osp->spcount;x++)
- servicepoints[x] = osp->servicepoints[x];
-
- ast_mutex_lock(&osplock);
- osp->dead = 0;
- if (osp->handle > -1) {
- ast_log(LOG_DEBUG, "Deleting old handle for '%s'\n", osp->name);
- OSPPProviderDelete(osp->handle, 0);
- }
-
-
- length = 0;
- ast_log(LOG_DEBUG, "Loading private key for '%s' (%s)\n", osp->name, osp->localpvtkey);
- errorcode = loadPemPrivateKey(osp->localpvtkey,Reqbuf,&length);
- if (errorcode == 0)
- {
- privatekey.PrivateKeyData = Reqbuf;
- privatekey.PrivateKeyLength = length;
- }
- else
- {
- return -1;
- }
-
- length = 0;
- ast_log(LOG_DEBUG, "Loading local cert for '%s' (%s)\n", osp->name, osp->localcert);
- errorcode = loadPemCert(osp->localcert,LocalBuf,&length);
- if (errorcode == 0)
- {
- localcert.CertData = LocalBuf;
- localcert.CertDataLength = length;
- }
- else
- {
- return -1;
- }
-
- for (i=0;i<osp->cacount;i++)
- {
- length = 0;
- ast_log(LOG_DEBUG, "Loading CA cert %d for '%s' (%s)\n", i + 1, osp->name, osp->cacerts[i]);
- errorcode = loadPemCert(osp->cacerts[i],AuthBuf[i],&length);
- if (errorcode == 0)
- {
- TheAuthCert[i].CertData = AuthBuf[i];
- TheAuthCert[i].CertDataLength = length;
- authCerts[i] = &(TheAuthCert[i]);
- }
- else
- {
- return -1;
- }
- }
-
- ast_log(LOG_DEBUG, "Creating provider handle for '%s'\n", osp->name);
-
- ast_log(LOG_DEBUG, "Service point '%s %d'\n", servicepoints[0], osp->spcount);
-
- if (OSPPProviderNew(osp->spcount,
- servicepoints,
- NULL,
- "localhost",
- &privatekey,
- &localcert,
- osp->cacount,
- (const OSPTCERT **)authCerts,
- 1,
- 300,
- osp->maxconnections,
- 1,
- osp->retrydelay,
- osp->retrylimit,
- osp->timeout,
- "",
- "",
- &osp->handle)) {
- ast_log(LOG_WARNING, "Unable to initialize provider '%s'\n", cat);
- osp->dead = 1;
- }
-
- if (mallocd) {
- osp->next = providers;
- providers = osp;
- }
- ast_mutex_unlock(&osplock);
- return 0;
-}
-
-static int show_osp(int fd, int argc, char *argv[])
-{
- struct osp_provider *osp;
- char *search = NULL;
- int x;
- int found = 0;
- char *tokenalgo;
-
- if ((argc < 2) || (argc > 3))
- return RESULT_SHOWUSAGE;
- if (argc > 2)
- search = argv[2];
- if (!search) {
- switch (tokenformat) {
- case TOKEN_ALGO_BOTH:
- tokenalgo = "Both";
- break;
- case TOKEN_ALGO_UNSIGNED:
- tokenalgo = "Unsigned";
- break;
- case TOKEN_ALGO_SIGNED:
- default:
- tokenalgo = "Signed";
- break;
- }
- ast_cli(fd, "OSP: %s %s %s\n", initialized ? "Initialized" : "Uninitialized", hardware ? "Accelerated" : "Normal", tokenalgo);
- }
-
- ast_mutex_lock(&osplock);
- osp = providers;
- while(osp) {
- if (!search || !strcasecmp(osp->name, search)) {
- if (found)
- ast_cli(fd, "\n");
- ast_cli(fd, " == OSP Provider '%s' ==\n", osp->name);
- ast_cli(fd, "Local Private Key: %s\n", osp->localpvtkey);
- ast_cli(fd, "Local Certificate: %s\n", osp->localcert);
- for (x=0;x<osp->cacount;x++)
- ast_cli(fd, "CA Certificate %d: %s\n", x + 1, osp->cacerts[x]);
- for (x=0;x<osp->spcount;x++)
- ast_cli(fd, "Service Point %d: %s\n", x + 1, osp->servicepoints[x]);
- ast_cli(fd, "Max Connections: %d\n", osp->maxconnections);
- ast_cli(fd, "Retry Delay: %d seconds\n", osp->retrydelay);
- ast_cli(fd, "Retry Limit: %d\n", osp->retrylimit);
- ast_cli(fd, "Timeout: %d milliseconds\n", osp->timeout);
- ast_cli(fd, "Source: %s\n", strlen(osp->source) ? osp->source : "<unspecified>");
- ast_cli(fd, "OSP Handle: %d\n", osp->handle);
- found++;
- }
- osp = osp->next;
- }
- ast_mutex_unlock(&osplock);
- if (!found) {
- if (search)
- ast_cli(fd, "Unable to find OSP provider '%s'\n", search);
- else
- ast_cli(fd, "No OSP providers configured\n");
- }
- return RESULT_SUCCESS;
-}
-
-
-/*----------------------------------------------*
- * Loads the Certificate *
- *----------------------------------------------*/
-static int loadPemCert(unsigned char *FileName, unsigned char *buffer, int *len)
-{
- int length = 0;
- unsigned char *temp;
- BIO *bioIn = NULL;
- X509 *cert=NULL;
- int retVal = OSPC_ERR_NO_ERROR;
-
- temp = buffer;
- bioIn = BIO_new_file((const char*)FileName,"r");
- if (bioIn == NULL)
- {
- ast_log(LOG_WARNING,"Failed to find the File - %s \n",FileName);
- return -1;
- }
- else
- {
- cert = PEM_read_bio_X509(bioIn,NULL,NULL,NULL);
- if (cert == NULL)
- {
- ast_log(LOG_WARNING,"Failed to parse the Certificate from the File - %s \n",FileName);
- return -1;
- }
- else
- {
- length = i2d_X509(cert,&temp);
- if (cert == 0)
- {
- ast_log(LOG_WARNING,"Failed to parse the Certificate from the File - %s, Length=0 \n",FileName);
- return -1;
- }
- else
- {
- *len = length;
- }
- }
- }
-
- if (bioIn != NULL)
- {
- BIO_free(bioIn);
- }
-
- if (cert != NULL)
- {
- X509_free(cert);
- }
- return retVal;
-}
-
-/*----------------------------------------------*
- * Loads the Private Key *
- *----------------------------------------------*/
-static int loadPemPrivateKey(unsigned char *FileName, unsigned char *buffer, int *len)
-{
- int length = 0;
- unsigned char *temp;
- BIO *bioIn = NULL;
- RSA *pKey = NULL;
- int retVal = OSPC_ERR_NO_ERROR;
-
- temp = buffer;
-
- bioIn = BIO_new_file((const char*)FileName,"r");
- if (bioIn == NULL)
- {
- ast_log(LOG_WARNING,"Failed to find the File - %s \n",FileName);
- return -1;
- }
- else
- {
- pKey = PEM_read_bio_RSAPrivateKey(bioIn,NULL,NULL,NULL);
- if (pKey == NULL)
- {
- ast_log(LOG_WARNING,"Failed to parse the Private Key from the File - %s \n",FileName);
- return -1;
- }
- else
- {
- length = i2d_RSAPrivateKey(pKey,&temp);
- if (length == 0)
- {
- ast_log(LOG_WARNING,"Failed to parse the Private Key from the File - %s, Length=0 \n",FileName);
- return -1;
- }
- else
- {
- *len = length;
- }
- }
- }
- if (bioIn != NULL)
- {
- BIO_free(bioIn);
- }
-
- if (pKey != NULL)
- {
- RSA_free(pKey);
- }
- return retVal;
-}
-
-int ast_osp_validate(char *provider, char *token, int *handle, unsigned int *timelimit, char *callerid, struct in_addr addr, char *extension)
-{
- char tmp[256]="", *l, *n;
- char iabuf[INET_ADDRSTRLEN];
- char source[OSP_MAX] = ""; /* Same length as osp->source */
- char *token2;
- int tokenlen;
- struct osp_provider *osp;
- int res = 0;
- unsigned int authorised, dummy;
-
- if (!provider || !strlen(provider))
- provider = "default";
-
- token2 = ast_strdupa(token);
- if (!token2)
- return -1;
- tokenlen = ast_base64decode(token2, token, strlen(token));
- *handle = -1;
- if (!callerid)
- callerid = "";
- ast_copy_string(tmp, callerid, sizeof(tmp));
- ast_callerid_parse(tmp, &n, &l);
- if (!l)
- l = "";
- else {
- ast_shrink_phone_number(l);
- if (!ast_isphonenumber(l))
- l = "";
- }
- callerid = l;
- ast_mutex_lock(&osplock);
- ast_inet_ntoa(iabuf, sizeof(iabuf), addr);
- osp = providers;
- while(osp) {
- if (!strcasecmp(osp->name, provider)) {
- if (OSPPTransactionNew(osp->handle, handle)) {
- ast_log(LOG_WARNING, "Unable to create OSP Transaction handle!\n");
- } else {
- ast_copy_string(source, osp->source, sizeof(source));
- res = 1;
- }
- break;
- }
- osp = osp->next;
- }
- ast_mutex_unlock(&osplock);
- if (res) {
- res = 0;
- dummy = 0;
- if (!OSPPTransactionValidateAuthorisation(*handle, iabuf, source, NULL, NULL,
- callerid, OSPC_E164, extension, OSPC_E164, 0, "", tokenlen, token2, &authorised, timelimit, &dummy, NULL, tokenformat)) {
- if (authorised) {
- ast_log(LOG_DEBUG, "Validated token for '%s' from '%s@%s'\n", extension, callerid, iabuf);
- res = 1;
- }
- }
- }
- return res;
-}
-
-int ast_osp_lookup(struct ast_channel *chan, char *provider, char *extension, char *callerid, struct ast_osp_result *result)
-{
- int cres;
- int res = 0;
- int counts;
- int tokenlen;
- unsigned int dummy=0;
- unsigned int timelimit;
- unsigned int callidlen;
- char callidstr[OSPC_CALLID_MAXSIZE] = "";
- struct osp_provider *osp;
- char source[OSP_MAX] = ""; /* Same length as osp->source */
- char callednum[2048]="";
- char callingnum[2048]="";
- char destination[2048]="";
- char token[2000];
- char tmp[256]="", *l, *n;
- OSPE_DEST_PROT prot;
- OSPE_DEST_OSP_ENABLED ospenabled;
- char *devinfo = NULL;
-
- result->handle = -1;
- result->numresults = 0;
- result->tech[0] = '\0';
- result->dest[0] = '\0';
- result->token[0] = '\0';
-
- if (!provider || !strlen(provider))
- provider = "default";
-
- if (!callerid)
- callerid = "";
- ast_copy_string(tmp, callerid, sizeof(tmp));
- ast_callerid_parse(tmp, &n, &l);
- if (!l)
- l = "";
- else {
- ast_shrink_phone_number(l);
- if (!ast_isphonenumber(l))
- l = "";
- }
- callerid = l;
-
- if (chan) {
- cres = ast_autoservice_start(chan);
- if (cres < 0)
- return cres;
- }
- ast_mutex_lock(&osplock);
- osp = providers;
- while(osp) {
- if (!strcasecmp(osp->name, provider)) {
- if (OSPPTransactionNew(osp->handle, &result->handle)) {
- ast_log(LOG_WARNING, "Unable to create OSP Transaction handle!\n");
- } else {
- ast_copy_string(source, osp->source, sizeof(source));
- res = 1;
- }
- break;
- }
- osp = osp->next;
- }
- ast_mutex_unlock(&osplock);
- if (res) {
- res = 0;
- /* No more than 10 back */
- counts = 10;
- dummy = 0;
- devinfo = pbx_builtin_getvar_helper (chan, "OSPPEER");
- if (!devinfo) {
- devinfo = "";
- }
- if (!OSPPTransactionRequestAuthorisation(result->handle, source, devinfo,
- callerid,OSPC_E164, extension, OSPC_E164, NULL, 0, NULL, NULL, &counts, &dummy, NULL)) {
- if (counts) {
- tokenlen = sizeof(token);
- result->numresults = counts - 1;
- callidlen = sizeof(callidstr);
- if (!OSPPTransactionGetFirstDestination(result->handle, 0, NULL, NULL, &timelimit, &callidlen, callidstr,
- sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
- ast_log(LOG_DEBUG, "Got destination '%s' and called: '%s' calling: '%s' for '%s' (provider '%s')\n",
- destination, callednum, callingnum, extension, provider);
- /* Only support OSP server with only one duration limit */
- if (ast_channel_cmpwhentohangup (chan, timelimit) < 0) {
- ast_channel_setwhentohangup (chan, timelimit);
- }
- do {
- if (!OSPPTransactionIsDestOSPEnabled (result->handle, &ospenabled) && (ospenabled == OSPE_OSP_FALSE)) {
- result->token[0] = 0;
- }
- else {
- ast_base64encode(result->token, token, tokenlen, sizeof(result->token) - 1);
- }
- if ((strlen(destination) > 2) && !OSPPTransactionGetDestProtocol(result->handle, &prot)) {
- res = 1;
- /* Strip leading and trailing brackets */
- destination[strlen(destination) - 1] = '\0';
- switch(prot) {
- case OSPE_DEST_PROT_H323_SETUP:
- ast_copy_string(result->tech, "H323", sizeof(result->tech));
- snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
- break;
- case OSPE_DEST_PROT_SIP:
- ast_copy_string(result->tech, "SIP", sizeof(result->tech));
- snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
- break;
- case OSPE_DEST_PROT_IAX:
- ast_copy_string(result->tech, "IAX", sizeof(result->tech));
- snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
- break;
- default:
- ast_log(LOG_DEBUG, "Unknown destination protocol '%d', skipping...\n", prot);
- res = 0;
- }
- if (!res && result->numresults) {
- result->numresults--;
- callidlen = sizeof(callidstr);
- if (OSPPTransactionGetNextDestination(result->handle, OSPC_FAIL_INCOMPATIBLE_DEST, 0, NULL, NULL, &timelimit, &callidlen, callidstr,
- sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
- break;
- }
- }
- } else {
- ast_log(LOG_DEBUG, "Missing destination protocol\n");
- break;
- }
- } while(!res && result->numresults);
- }
- }
-
- }
- if (!res) {
- OSPPTransactionDelete(result->handle);
- result->handle = -1;
- }
-
- }
- if (!osp)
- ast_log(LOG_NOTICE, "OSP Provider '%s' does not exist!\n", provider);
- if (chan) {
- cres = ast_autoservice_stop(chan);
- if (cres < 0)
- return cres;
- }
- return res;
-}
-
-int ast_osp_next(struct ast_osp_result *result, int cause)
-{
- int res = 0;
- int tokenlen;
- unsigned int dummy=0;
- unsigned int timelimit;
- unsigned int callidlen;
- char callidstr[OSPC_CALLID_MAXSIZE] = "";
- char callednum[2048]="";
- char callingnum[2048]="";
- char destination[2048]="";
- char token[2000];
- OSPE_DEST_PROT prot;
- OSPE_DEST_OSP_ENABLED ospenabled;
-
- result->tech[0] = '\0';
- result->dest[0] = '\0';
- result->token[0] = '\0';
-
- if (result->handle > -1) {
- dummy = 0;
- if (result->numresults) {
- tokenlen = sizeof(token);
- while(!res && result->numresults) {
- result->numresults--;
- callidlen = sizeof(callidstr);
- if (!OSPPTransactionGetNextDestination(result->handle, OSPC_FAIL_INCOMPATIBLE_DEST, 0, NULL, NULL, &timelimit, &callidlen, callidstr,
- sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
- if (!OSPPTransactionIsDestOSPEnabled (result->handle, &ospenabled) && (ospenabled == OSPE_OSP_FALSE)) {
- result->token[0] = 0;
- }
- else {
- ast_base64encode(result->token, token, tokenlen, sizeof(result->token) - 1);
- }
- if ((strlen(destination) > 2) && !OSPPTransactionGetDestProtocol(result->handle, &prot)) {
- res = 1;
- /* Strip leading and trailing brackets */
- destination[strlen(destination) - 1] = '\0';
- switch(prot) {
- case OSPE_DEST_PROT_H323_SETUP:
- ast_copy_string(result->tech, "H323", sizeof(result->tech));
- snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
- break;
- case OSPE_DEST_PROT_SIP:
- ast_copy_string(result->tech, "SIP", sizeof(result->tech));
- snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
- break;
- case OSPE_DEST_PROT_IAX:
- ast_copy_string(result->tech, "IAX", sizeof(result->tech));
- snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
- break;
- default:
- ast_log(LOG_DEBUG, "Unknown destination protocol '%d', skipping...\n", prot);
- res = 0;
- }
- } else {
- ast_log(LOG_DEBUG, "Missing destination protocol\n");
- break;
- }
- }
- }
-
- }
- if (!res) {
- OSPPTransactionDelete(result->handle);
- result->handle = -1;
- }
-
- }
- return res;
-}
-
-static enum OSPEFAILREASON cause2reason(int cause)
-{
- switch(cause) {
- case AST_CAUSE_BUSY:
- return OSPC_FAIL_USER_BUSY;
- case AST_CAUSE_CONGESTION:
- return OSPC_FAIL_SWITCHING_EQUIPMENT_CONGESTION;
- case AST_CAUSE_UNALLOCATED:
- return OSPC_FAIL_UNALLOC_NUMBER;
- case AST_CAUSE_NOTDEFINED:
- return OSPC_FAIL_NORMAL_UNSPECIFIED;
- case AST_CAUSE_NOANSWER:
- return OSPC_FAIL_NO_ANSWER_FROM_USER;
- case AST_CAUSE_NORMAL:
- default:
- return OSPC_FAIL_NORMAL_CALL_CLEARING;
- }
-}
-
-int ast_osp_terminate(int handle, int cause, time_t start, time_t duration)
-{
- unsigned int dummy = 0;
- int res = -1;
- enum OSPEFAILREASON reason;
-
- time_t endTime = 0;
- time_t alertTime = 0;
- time_t connectTime = 0;
- unsigned isPddInfoPresent = 0;
- unsigned pdd = 0;
- unsigned releaseSource = 0;
- unsigned char *confId = "";
-
- reason = cause2reason(cause);
- if (OSPPTransactionRecordFailure(handle, reason))
- ast_log(LOG_WARNING, "Failed to record call termination for handle %d\n", handle);
- else if (OSPPTransactionReportUsage(handle, duration, start,
- endTime,alertTime,connectTime,isPddInfoPresent,pdd,releaseSource,confId,
- 0, 0, 0, 0, &dummy, NULL))
- ast_log(LOG_WARNING, "Failed to report duration for handle %d\n", handle);
- else {
- ast_log(LOG_DEBUG, "Completed recording handle %d\n", handle);
- OSPPTransactionDelete(handle);
- res = 0;
- }
- return res;
-}
-
-static int config_load(void)
-{
- struct ast_config *cfg;
- char *cat;
- struct osp_provider *osp, *prev = NULL, *next;
- ast_mutex_lock(&osplock);
- osp = providers;
- while(osp) {
- osp->dead = 1;
- osp = osp->next;
- }
- ast_mutex_unlock(&osplock);
- cfg = ast_config_load("osp.conf");
- if (cfg) {
- if (!initialized) {
- cat = ast_variable_retrieve(cfg, "general", "accelerate");
- if (cat && ast_true(cat))
- if (OSPPInit(1)) {
- ast_log(LOG_WARNING, "Failed to enable hardware accelleration, falling back to software mode\n");
- OSPPInit(0);
- } else
- hardware = 1;
- else
- OSPPInit(0);
- initialized = 1;
- }
- cat = ast_variable_retrieve(cfg, "general", "tokenformat");
- if (cat) {
- if ((sscanf(cat, "%d", &tokenformat) != 1) || (tokenformat < TOKEN_ALGO_SIGNED) || (tokenformat > TOKEN_ALGO_BOTH)) {
- tokenformat = TOKEN_ALGO_SIGNED;
- ast_log(LOG_WARNING, "tokenformat should be an integer from 0 to 2, not '%s'\n", cat);
- }
- }
- cat = ast_category_browse(cfg, NULL);
- while(cat) {
- if (strcasecmp(cat, "general"))
- osp_build(cfg, cat);
- cat = ast_category_browse(cfg, cat);
- }
- ast_config_destroy(cfg);
- } else
- ast_log(LOG_NOTICE, "No OSP configuration found. OSP support disabled\n");
- ast_mutex_lock(&osplock);
- osp = providers;
- while(osp) {
- next = osp->next;
- if (osp->dead) {
- if (prev)
- prev->next = next;
- else
- providers = next;
- /* XXX Cleanup OSP structure first XXX */
- free(osp);
- } else
- prev = osp;
- osp = next;
- }
- ast_mutex_unlock(&osplock);
- return 0;
-}
-
-static char show_osp_usage[] =
-"Usage: show osp\n"
-" Displays information on Open Settlement Protocol\n";
-
-static struct ast_cli_entry cli_show_osp =
-{ { "show", "osp", NULL }, show_osp, "Displays OSP information", show_osp_usage };
-
-int reload(void)
-{
- config_load();
- ast_log(LOG_NOTICE, "XXX Should reload OSP config XXX\n");
- return 0;
-}
-
-int load_module(void)
-{
- config_load();
- ast_cli_register(&cli_show_osp);
- return 0;
-}
-
-int unload_module(void)
-{
- /* Can't unload this once we're loaded */
- return -1;
-}
-
-char *description(void)
-{
- return "Open Settlement Protocol Support";
-}
-
-int usecount(void)
-{
- /* We should never be unloaded */
- return 1;
-}
-
-char *key()
-{
- return ASTERISK_GPL_KEY;
-}