/* * OpenPBX -- An open source telephony toolkit. * * Copyright (C) 2005, Roy Sigurd Karlsbakk * * Roy Sigurd Karlsbakk * * See http://www.openpbx.org for more information about * the OpenPBX 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. */ /* * * RRDial application * */ #ifdef HAVE_CONFIG_H #include "confdefs.h" #endif #include #include #include #include "openpbx.h" OPENPBX_FILE_VERSION("$HeadURL: svn://svn.openpbx.org/openpbx/trunk/apps/app_rrdial.c $", "$Revision: 822 $") #include "openpbx/file.h" #include "openpbx/logger.h" #include "openpbx/channel.h" #include "openpbx/pbx.h" #include "openpbx/module.h" #include "openpbx/lock.h" #include "openpbx/app.h" #define RRDIAL_MAX_MEMBER_NAME 64 #define RRDIAL_MAX_MEMBERS 10 #define RRDIAL_MAX_POOLS 10 static char *tdesc = "Round Robin Dial Application"; static char *app = "RRDial"; static char *synopsis = "Round Robin Dial application."; static char *descrip = "Dial one server out of a pool of servers givin in pools.conf\n" "in a weighted random order.\n"; static char *config_file = "pools.conf"; STANDARD_LOCAL_USER; LOCAL_USER_DECL; struct opbx_rrdial_member { char name[RRDIAL_MAX_MEMBER_NAME]; int weight; }; struct opbx_rrdial_pool { struct opbx_rrdial_member members[RRDIAL_MAX_MEMBERS]; }; static struct opbx_rrdial_members[RRDIAL_MAX_MEMBERS]; static int app_exec(struct opbx_channel *chan, void *data) { int res = 0; struct opbx_flags flags; struct localuser *u; char *options=NULL; char *dummy = NULL; char *args; int argc = 0; char *opts[2]; char *argv[2]; if (!(args = opbx_strdupa((char *)data))) { opbx_log(LOG_ERROR, "%s: Out of memory!\n",app); return -1; } if (!data) { opbx_log(LOG_WARNING, "%s requires an argument (pool)\n",app); return -1; } LOCAL_USER_ADD(u); /* Do our thing here */ opbx_log(LOG_WARNING, "%s isn't finished yet. sorry.\n",app); /* Clean up */ LOCAL_USER_REMOVE(u); return res; } /* * this is a mess. it really is * * opbx_variable_retrieve(cfg, "section", "key"); * get variable key 'key' from section [section] * * var = opbx_variable_browse(cfg, cat); * * char * opbx_category_browse (struct opbx_config *config, const char *prev) * * many A pointer to a previous category. This funtion is kind of non- * intuitive in it's use. To begin, one passes NULL as the second arguement. * It will return a pointer to the string of the first category in the file. * From here on after, one must then pass the previous usage's return value * as the second pointer, and it will return a pointer to the category name * afterwards. * * /usr/local/openpbx.org/etc/pools.conf * */ static int reload_rrdial(void) { struct opbx_config *cfg; struct opbx_variable *var; char *cat = NULL; char *tmp; char weight_s[8]; int members, weight; int member_count; int pool_count=0; /* clean up old config */ memset(&opbx_rrdial_members, 0, sizeof opbx_rrdial_members); /* get the new config */ cfg = opbx_config_load(config_file); if (!cfg) { opbx_log(LOG_WARNING, "No server pool config file (%s), so no server pools\n", config_file); return -1; } while (cat = opbx_category_browse (cfg, cat)) { if (strcasecmp(cat, "general") == 0) { opbx_log(LOG_DEBUG, "Category 'general' is not currently in use, ignored.\n", cat); continue; } else { opbx_log(LOG_DEBUG, "Adding pool '%s'\n", cat); pool_count++; member_count=0; if (pool_count > 1) { opbx_log(LOG_WARNING, "%s doesn't support more than one pool yet. sorry...\n", app); return 0; } for (var = opbx_variable_browse(cfg, cat); var ; var = var->next) { opbx_log(LOG_DEBUG, "Server pool conf '%s' has line '%s'\n", cat, var->value); /* Just check if this is a 'member'. It should be... We don't have much else at them moment */ if (strcasecmp(var->name, "member") == 0) { if ((tmp = strchr(var->value, ','))) { memset(&servername, 0, sizeof servername); strncpy((char *)&opbx_rrdial_members[member_count], var->value, RRDIAL_MAX_MEMBER_NAME-1); tmp = strchr(servername,','); if (tmp) { *tmp = 0; tmp++; strncpy(weight_s, tmp, sizeof weight_s); weight = strtol(weight_s, NULL, 0); opbx_log(LOG_DEBUG, "Server pool '%s' has member '%s' with weight %d\n", cat, var->value, weight); } else { opbx_log(LOG_DEBUG, "Line '%s' doesn't give a weight. Ignored.\n", var->value); } } else { opbx_log(LOG_DEBUG, "Line '%s' doesn't give a weight. Ignored.\n", var->value); } } else { opbx_log(LOG_DEBUG, "I don't know what to do with a '%s' type", cat, var->name); } } if (members == 0) opbx_log(LOG_NOTICE, "Server pool '%s' has no members.\n", cat); else opbx_log(LOG_DEBUG, "Server pool '%s' has %i members.\n", cat, members); } } return 0; } int reload(void) { return reload_rrdial(); } int unload_module(void) { STANDARD_HANGUP_LOCALUSERS; return opbx_unregister_application(app); } int load_module(void) { int res; res = opbx_register_application(app, app_exec, synopsis, descrip); if (res != 0) { opbx_log(LOG_DEBUG, "opbx_register_application returned %i\n", res); return res; } res = reload_rrdial(); if (res != 0) opbx_log(LOG_DEBUG, "reload_rrdial returned %i\n", res); return res; } char *description(void) { return tdesc; } int usecount(void) { int res; STANDARD_USECOUNT(res); return res; }