/* * CallWeaver -- An open source telephony toolkit. * * Copyright (C) 2007, Eris Associates Ltd., UK * * Mike Jagdis * * See http://www.callweaver.org for more information about * the CallWeaver 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 Core functions * */ #ifdef HAVE_CONFIG_H #include "confdefs.h" #endif #include #include #include #include #include #include "callweaver.h" CALLWEAVER_FILE_VERSION("$HeadURL$", "$Revision$") #include "callweaver/musiconhold.h" #include "callweaver/say.h" #include "callweaver/file.h" #include "callweaver/logger.h" #include "callweaver/callweaver_keywords.h" #include "callweaver/channel.h" #include "callweaver/options.h" #include "callweaver/pbx.h" #include "callweaver/module.h" #include "callweaver/lock.h" #include "callweaver/app.h" #ifndef VAR_BUF_SIZE # define VAR_BUF_SIZE 4096 #endif static const char tdesc[] = "Core functions"; #define BACKGROUND_SKIP (1 << 0) #define BACKGROUND_NOANSWER (1 << 1) #define BACKGROUND_MATCHEXTEN (1 << 2) #define BACKGROUND_PLAYBACK (1 << 3) CW_DECLARE_OPTIONS(background_opts,{ ['s'] = { BACKGROUND_SKIP }, ['n'] = { BACKGROUND_NOANSWER }, ['m'] = { BACKGROUND_MATCHEXTEN }, ['p'] = { BACKGROUND_PLAYBACK }, }); #define WAITEXTEN_MOH (1 << 0) CW_DECLARE_OPTIONS(waitexten_opts,{ ['m'] = { WAITEXTEN_MOH, 1 }, }); static void wait_for_hangup(struct cw_channel *chan, char *s) { struct cw_frame *f; int waittime; if (!s || !strlen(s) || (sscanf(s, "%d", &waittime) != 1) || (waittime < 0)) waittime = -1; if (waittime > -1) cw_safe_sleep(chan, waittime * 1000); else { while (cw_waitfor(chan, -1) >= 0 && (f = cw_read(chan))) cw_fr_free(f); } } static int pbx_builtin_progress(struct cw_channel *chan, int argc, char **argv, char *result, size_t result_max) { cw_indicate(chan, CW_CONTROL_PROGRESS); return 0; } static int pbx_builtin_ringing(struct cw_channel *chan, int argc, char **argv, char *result, size_t result_max) { cw_indicate(chan, CW_CONTROL_RINGING); return 0; } static int pbx_builtin_busy(struct cw_channel *chan, int argc, char **argv, char *result, size_t result_max) { cw_indicate(chan, CW_CONTROL_BUSY); if (chan->_state != CW_STATE_UP) cw_setstate(chan, CW_STATE_BUSY); wait_for_hangup(chan, (argc > 0 ? argv[0] : NULL)); return -1; } static int pbx_builtin_congestion(struct cw_channel *chan, int argc, char **argv, char *result, size_t result_max) { cw_indicate(chan, CW_CONTROL_CONGESTION); if (chan->_state != CW_STATE_UP) cw_setstate(chan, CW_STATE_BUSY); wait_for_hangup(chan, (argc > 0 ? argv[0] : NULL)); return -1; } static int pbx_builtin_answer(struct cw_channel *chan, int argc, char **argv, char *result, size_t result_max) { int delay = (argc > 0 ? atoi(argv[0]) : 0); int res; if (chan->_state == CW_STATE_UP) delay = 0; res = cw_answer(chan); if (res) return res; if (delay) res = cw_safe_sleep(chan, delay); return res; } static int pbx_builtin_setlanguage(struct cw_channel *chan, int argc, char **argv, char *result, size_t result_max) { static int deprecation_warning = 0; if (!deprecation_warning) { cw_log(CW_LOG_WARNING, "SetLanguage is deprecated, please use Set(LANGUAGE()=language) instead.\n"); deprecation_warning = 1; } /* Copy the language as specified */ if (argc > 0) cw_copy_string(chan->language, argv[0], sizeof(chan->language)); return 0; } static int pbx_builtin_resetcdr(struct cw_channel *chan, int argc, char **argv, char *result, size_t result_max) { char *p; int flags = 0; for (; argc; argv++, argc--) { for (p = argv[0]; *p; p++) { switch (*p) { case 'a': flags |= CW_CDR_FLAG_LOCKED; break; case 'v': flags |= CW_CDR_FLAG_KEEP_VARS; break; case 'w': flags |= CW_CDR_FLAG_POSTED; break; } } } cw_cdr_reset(chan->cdr, flags); return 0; } static int pbx_builtin_setaccount(struct cw_channel *chan, int argc, char **argv, char *result, size_t result_max) { cw_cdr_setaccount(chan, (argc > 0 ? argv[0] : "")); return 0; } static int pbx_builtin_setamaflags(struct cw_channel *chan, int argc, char **argv, char *result, size_t result_max) { cw_cdr_setamaflags(chan, (argc > 0 ? argv[0] : "")); return 0; } static int pbx_builtin_hangup(struct cw_channel *chan, int argc, char **argv, char *result, size_t result_max) { int n; if (argc > 0 && (n = atoi(argv[0])) > 0) chan->hangupcause = n; /* Just return non-zero and it will hang up */ return -1; } static int pbx_builtin_goto(struct cw_channel *chan, int argc, char **argv, char *result, size_t result_max) { char *context, *exten; int res; context = exten = NULL; if (argc > 2) context = (argv++)[0]; if (argc > 1) exten = (argv++)[0]; res = cw_explicit_goto(chan, context, exten, argv[0]); if (!res && option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "Goto (%s, %s, %d)\n", chan->context, chan->exten, chan->priority + 1); return res; } static int pbx_builtin_gotoiftime(struct cw_channel *chan, int argc, char **argv, char *result, size_t result_max) { char tmp[1024]; struct cw_timing timing; char *s; s = NULL; if (argc > 3) { if ((s = strchr(argv[3], '?'))) do { *(s++) = '\0'; } while (isspace(*s)); } if (!s || !*s || argc > 6) { cw_log(CW_LOG_WARNING, "GotoIfTime requires an argument:\n