Index: channels/chan_zap.c =================================================================== --- channels/chan_zap.c (revision 10446) +++ channels/chan_zap.c (working copy) @@ -9730,6 +9757,36 @@ return RESULT_FAILURE; } +int zap_channel_count(int span,int *count,int *used) { + struct zt_pri *pri; + ast_mutex_t *lock; + int i; + + if (span >= NUM_SPANS || span < 0) { + ast_log(LOG_WARNING,"zap_channel_count: span should be 0 <= x < %d\n",NUM_SPANS); + return RESULT_FAILURE; + } + + pri = &pris[span]; + lock = &pri->lock; + + ast_mutex_lock(lock); + + *count=0; + *used=0; + + for (i=0; ipvts[i]) { + *count+=1; + if (pri->pvts[i]->owner != NULL) + *used+=1; + } + } + + ast_mutex_unlock(lock); + return RESULT_SUCCESS; +} + static int zap_show_channels(int fd, int argc, char **argv) { #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" Index: apps/app_trunkisavail.c =================================================================== --- apps/app_trunkisavail.c (revision 0) +++ apps/app_trunkisavail.c (revision 0) @@ -0,0 +1,279 @@ +/* +* Asterisk -- An open source telephony toolkit. +* +* Copyright (C) 1999 - 2005, Digium, Inc. +* +* Mark Spencer +* James Golovich +* +* This file app_trunkisavail.c is donated by +* Edwin Groothuis +* +* 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 Check if Trunk is Available + * + * \author Mark Spencer + * \author James Golovich + * \author Edwin Groothuis + * + * \ingroup applications + */ + +#include +#include +#include +#include +#include +#include + +#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/module.h" +#include "asterisk/app.h" +#include "asterisk/devicestate.h" +#include "asterisk/options.h" +#include "asterisk/cli.h" + +static char *tdesc = "Check trunk availability"; + +static char *app = "TrunkIsAvail"; + +static char *synopsis = "Check trunk availability"; + +static char *descrip = +" TrunkIsAvail(trunkgroup[&trunkgroup]): \n" +"This application will check to see if any of the specified trunks are\n" +"available. The following variables will be set by this application:\n" +" ${AVAILTRUNK} - the name of the available trunk, if one exists\n" +" ${AVAILSTATUS} - the status code for the available channel\n" +" Options:\n" +" f - Pick the first trunk with an unused channel\n" +" l - Pick the trunk with the least used channels (default)\n"; + +STANDARD_LOCAL_USER; + +LOCAL_USER_DECL; + +static int trunkavail_exec(struct ast_channel *chan, void *data) +{ + int res=-1, inuse=-1, option_state=0, priority_jump=0; + int option_first=0; + int option_least=1; + int status; + struct ast_channel *tempchan; + struct localuser *u; + char *info, tmp[512], trychan[512], *peers, *trunk, *s, *rest, *cur; + + + AST_DECLARE_APP_ARGS(args, + AST_APP_ARG(reqchans); + AST_APP_ARG(options); + ); + + if (ast_strlen_zero(data)) { + ast_log(LOG_WARNING, "TrunkIsAvail requires an argument (Zap/g1&Zap/g2)\n"); + return -1; + } + + LOCAL_USER_ADD(u); + + info = ast_strdupa(data); + + AST_STANDARD_APP_ARGS(args, info); + + if (args.options) { + if (strchr(args.options, 'f')) { + option_first=1; + option_least=0; + } + if (strchr(args.options, 'l')) { + option_first=0; + option_least=1; + } + } + + /* + * Find the first free one. And return that one. + */ + if (option_first) { + + peers = args.reqchans; + if (peers) { + cur = peers; + do { + /* remember where to start next time */ + rest = strchr(cur, '&'); + if (rest) { + *rest = 0; + rest++; + } + trunk = cur; + if ((s = strchr(trunk, '/')) !=NULL) + trunk = s + 1; + + /* If the pbx says in use then don't bother trying further. + This is to permit testing if someone's on a call, even if the + channel can permit more calls (ie callwaiting, sip calls, etc). */ + + snprintf(trychan, sizeof(trychan), "Zap/%s",trunk); + inuse = status = ast_device_state(trychan); + + if ((status <= 1) && (tempchan = ast_request("Zap", chan->nativeformats, trunk, &status))) { + ast_hangup(tempchan); + pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name); + pbx_builtin_setvar_helper(chan, "AVAILTRUNK", trychan); + snprintf(tmp, sizeof(tmp), "%d", inuse); + pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp); + tempchan = NULL; + res = 1; + break; + } + cur = rest; + } while (cur); + } + if (res < 1) { + pbx_builtin_setvar_helper(chan, "AVAILSTATUS", "0"); + pbx_builtin_setvar_helper(chan, "AVAILTRUNK", ""); + } + } + + /* + * Find the trunk with the least in use. + */ + if (option_least) { + #define NUM_SPANS 32 /* From channels/chan_zap.c */ + + int least[NUM_SPANS]; + char *trunks[NUM_SPANS]; + int span; + int count, used; + int numtrunks, maxfree; + int x; + + memset(&least,0,sizeof(int)*NUM_SPANS); + + numtrunks=0; + maxfree=0; + peers = args.reqchans; + if (peers) { + /* + * First find the number of used channels per trunk + */ + cur = peers; + do { + /* remember where to start next time */ + rest = strchr(cur, '&'); + if (rest) { + *rest = 0; + rest++; + } + trunk = cur; + if ((s = strchr(trunk, '/')) !=NULL) + trunk = s + 1; + + snprintf(trychan, sizeof(trychan), "Zap/%s",trunk); + span = atoi(trunk+1)-1; + if (zap_channel_count(span, &count, &used) == RESULT_SUCCESS) { + least[numtrunks]=count-used; + trunks[numtrunks]=trunk; + if (maxfree 0) { + for (x=0; xnativeformats, trunks[x], &status))) { + ast_hangup(tempchan); + pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name); + pbx_builtin_setvar_helper(chan, "AVAILTRUNK", trychan); + snprintf(tmp, sizeof(tmp), "%d", inuse); + pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp); + tempchan = NULL; + res = 1; + break; + } + } + } + if (res == 1) break; + maxfree--; + } + + } + if (res < 1) { + pbx_builtin_setvar_helper(chan, "AVAILSTATUS", "0"); + pbx_builtin_setvar_helper(chan, "AVAILTRUNK", ""); + } + } + + LOCAL_USER_REMOVE(u); + return 0; +} + +int unload_module(void) +{ + int res = 0; + + res = ast_unregister_application(app); + + STANDARD_HANGUP_LOCALUSERS; + + return res; +} + +int load_module(void) +{ + return ast_register_application(app, trunkavail_exec, synopsis, descrip); +} + +char *description(void) +{ + return tdesc; +} + +int usecount(void) +{ + int res; + STANDARD_USECOUNT(res); + return res; +} + +char *key() +{ + return ASTERISK_GPL_KEY; +}