/*
* OpenPBX -- An open source telephony toolkit.
*
* Copyright (C) 2005, Roy Sigurd Karlsbakk
*
* Roy Sigurd Karlsbakk <roy@karlsbakk.net>
*
* 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 <stdlib.h>
#include <unistd.h>
#include <string.h>
#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;
}