From 891ed0c02a474287b9f104a531ff9333ae712784 Mon Sep 17 00:00:00 2001 From: Mark Spencer <markster@digium.com> Date: Wed, 13 Oct 1999 04:15:49 +0000 Subject: [PATCH] Version 0.1.0 from FTP git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- pbx/pbx_config.c | 91 +++++++++++++ sched.c | 336 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 427 insertions(+) create mode 100755 pbx/pbx_config.c create mode 100755 sched.c diff --git a/pbx/pbx_config.c b/pbx/pbx_config.c new file mode 100755 index 0000000000..359cec911c --- /dev/null +++ b/pbx/pbx_config.c @@ -0,0 +1,91 @@ +/* + * Asterisk -- A telephony toolkit for Linux. + * + * Populate and remember extensions from static config file + * + * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC + * + * Mark Spencer <markster@linux-support.net> + * + * This program is free software, distributed under the terms of + * the GNU General Public License + */ + +#include <asterisk/pbx.h> +#include <asterisk/config.h> +#include <asterisk/module.h> +#include <asterisk/logger.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +/* For where to put dynamic tables */ +#include "../asterisk.h" + +static char *dtext = "Text Extension Configuration"; +static char *config = "extensions.conf"; + +static int static_config = 0; + +int unload_module(void) +{ + return 0; +} + +int load_module(void) +{ + struct ast_config *cfg; + struct ast_variable *v; + char *cxt, *ext, *pri, *appl, *data, *tc; + struct ast_context *con; + + + cfg = ast_load(config); + if (cfg) { + /* Use existing config to populate the PBX table */ + static_config = ast_true(ast_variable_retrieve(cfg, "general", "static")); + cxt = ast_category_browse(cfg, NULL); + while(cxt) { + /* All categories but "general" are considered contexts */ + if (!strcasecmp(cxt, "general")) { + cxt = ast_category_browse(cfg, cxt); + continue; + } + if ((con=ast_context_create(cxt))) { + v = ast_variable_browse(cfg, cxt); + while(v) { + tc = strdup(v->value); + ext = strtok(tc, ","); + if (!ext) + ext=""; + pri = strtok(NULL, ","); + if (!pri) + pri=""; + appl = strtok(NULL, ","); + if (!appl) + appl=""; + data = strtok(NULL, ","); + if (!data) + data=""; + if (ast_add_extension2(con, 0, ext, atoi(pri), appl, strdup(data), free)) { + ast_log(LOG_WARNING, "Unable to register extension\n"); + } + v = v->next; + free(tc); + } + } + cxt = ast_category_browse(cfg, cxt); + } + } + ast_destroy(cfg); + return 0; +} + +int usecount(void) +{ + return 0; +} + +char *description(void) +{ + return dtext; +} diff --git a/sched.c b/sched.c new file mode 100755 index 0000000000..a6a2ca5d32 --- /dev/null +++ b/sched.c @@ -0,0 +1,336 @@ +/* + * Asterisk + * + * Mark Spencer <markster@marko.net> + * + * Copyright(C) 1999, Adtran, Inc. + * + * Distributed under the terms of the GNU General Public License (GPL) Version 2 + * + * Scheduler Routines (form cheops-NG) + * + */ + +#ifdef DEBUG_SCHEDULER +#define DEBUG(a) DEBUG_M(a) +#else +#define DEBUG(a) +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <unistd.h> +#include <asterisk/sched.h> +#include <asterisk/logger.h> + +/* Determine if a is sooner than b */ +#define SOONER(a,b) (((b).tv_sec > (a).tv_sec) || \ + (((b).tv_sec == (a).tv_sec) && ((b).tv_usec > (a).tv_usec))) + +struct sched { + struct sched *next; /* Next event in the list */ + int id; /* ID number of event */ + struct timeval when; /* Absolute time event should take place */ + int resched; /* When to reschedule */ + void *data; /* Data */ + ast_sched_cb callback; /* Callback */ +}; + +struct sched_context { + /* Number of events processed */ + int eventcnt; + + /* Number of outstanding schedule events */ + int schedcnt; + + /* Schedule entry and main queue */ + struct sched *schedq; + +#ifdef SCHED_MAX_CACHE + /* Cache of unused schedule structures and how many */ + struct sched *schedc; + int schedccnt; +#endif +}; + +struct sched_context *sched_context_create(void) +{ + struct sched_context *tmp; + tmp = malloc(sizeof(struct sched_context)); + if (tmp) { + tmp->eventcnt = 1; + tmp->schedcnt = 0; + tmp->schedq = NULL; + tmp->schedc = NULL; + tmp->schedccnt = 0; + } + return tmp; +} + +void sched_context_destroy(struct sched_context *con) +{ + struct sched *s, *sl; + /* Eliminate the cache */ + s = con->schedc; + while(s) { + sl = s; + s = s->next; + free(sl); + } + /* And the queue */ + s = con->schedq; + while(s) { + sl = s; + s = s->next; + free(sl); + } + /* And the context */ + free(con); +} + +static struct sched *sched_alloc(struct sched_context *con) +{ + /* + * We keep a small cache of schedule entries + * to minimize the number of necessary malloc()'s + */ + struct sched *tmp; +#ifdef SCHED_MAX_CACHE + if (con->schedc) { + tmp = con->schedc; + con->schedc = con->schedc->next; + con->schedccnt--; + } else +#endif + tmp = malloc(sizeof(struct sched)); + return tmp; +} + +static void sched_release(struct sched_context *con, struct sched *tmp) +{ + /* + * Add to the cache, or just free() if we + * already have too many cache entries + */ + +#ifdef SCHED_MAX_CACHE + if (con->schedccnt < SCHED_MAX_CACHE) { + tmp->next = con->schedc; + con->schedc = tmp; + con->schedccnt++; + } else +#endif + free(tmp); +} + +int ast_sched_wait(struct sched_context *con) +{ + /* + * Return the number of milliseconds + * until the next scheduled event + */ + struct timeval tv; + int ms; + DEBUG(ast_log(LOG_DEBUG, "ast_sched_wait()\n")); + if (!con->schedq) + return -1; + if (gettimeofday(&tv, NULL) < 0) { + /* This should never happen */ + return 0; + }; + ms = (con->schedq->when.tv_sec - tv.tv_sec) * 1000; + ms += (con->schedq->when.tv_usec - tv.tv_usec) / 1000; + if (ms < 0) + ms = 0; + return ms; + +} + + +static void schedule(struct sched_context *con, struct sched *s) +{ + /* + * Take a sched structure and put it in the + * queue, such that the soonest event is + * first in the list. + */ + + struct sched *last=NULL; + struct sched *current=con->schedq; + while(current) { + if (SOONER(s->when, current->when)) + break; + last = current; + current = current->next; + } + /* Insert this event into the schedule */ + s->next = current; + if (last) + last->next = s; + else + con->schedq = s; + con->schedcnt++; +} + +static inline int sched_settime(struct timeval *tv, int when) +{ + if (gettimeofday(tv, NULL) < 0) { + /* This shouldn't ever happen, but let's be sure */ + ast_log(LOG_NOTICE, "gettimeofday() failed!\n"); + return -1; + } + tv->tv_sec += when/1000; + tv->tv_usec += (when % 1000) * 1000; + if (tv->tv_usec > 1000000) { + tv->tv_sec++; + tv->tv_usec-= 1000000; + } + return 0; +} + +int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, void *data) +{ + /* + * Schedule callback(data) to happen when ms into the future + */ + struct sched *tmp; + DEBUG(ast_log(LOG_DEBUG, "ast_sched_add()\n")); + if (!when) { + ast_log(LOG_NOTICE, "Scheduled event in 0 ms?"); + return -1; + } + if ((tmp = sched_alloc(con))) { + tmp->id = con->eventcnt++; + tmp->callback = callback; + tmp->data = data; + tmp->resched = when; + if (sched_settime(&tmp->when, when)) { + sched_release(con, tmp); + return -1; + } else + schedule(con, tmp); + } else + return -1; + return tmp->id; +} + +int ast_sched_del(struct sched_context *con, int id) +{ + /* + * Delete the schedule entry with number + * "id". It's nearly impossible that there + * would be two or more in the list with that + * id. + */ + struct sched *last=NULL, *s; + DEBUG(ast_log(LOG_DEBUG, "ast_sched_del()\n")); + s = con->schedq; + while(s) { + if (s->id == id) { + if (last) + last->next = s->next; + else + con->schedq = s->next; + con->schedcnt--; + return 0; + } + last = s; + s = s->next; + } + ast_log(LOG_NOTICE, "Attempted to delete non-existant schedule entry %d!\n", id); +#ifdef FORCE_CRASH + crash(); +#endif + return -1; +} + +void ast_sched_dump(struct sched_context *con) +{ + /* + * Dump the contents of the scheduler to + * stderr + */ + struct sched *q; + struct timeval tv; + time_t s, ms; + gettimeofday(&tv, NULL); + ast_log(LOG_DEBUG, "Cheops Schedule Dump (%d in Q, %d Total, %d Cache)\n", + con-> schedcnt, con->eventcnt - 1, con->schedccnt); + ast_log(LOG_DEBUG, "=================================================\n"); + ast_log(LOG_DEBUG, "|ID Callback Data Time (sec:ms) |\n"); + ast_log(LOG_DEBUG, "+-----+-----------+-----------+-----------------+\n"); + q = con->schedq; + while(q) { + s = q->when.tv_sec - tv.tv_sec; + ms = q->when.tv_usec - tv.tv_usec; + if (ms < 0) { + ms += 1000000; + s--; + } + ast_log(LOG_DEBUG, "|%.4d | %p | %p | %.6ld : %.6ld |\n", + q->id, + q->callback, + q->data, + s, + ms); + q=q->next; + } + ast_log(LOG_DEBUG, "=================================================\n"); + +} + +int ast_sched_runq(struct sched_context *con) +{ + /* + * Launch all events which need to be run at this time. + */ + struct sched *current; + struct timeval tv; + int x=0; + DEBUG(ast_log(LOG_DEBUG, "ast_sched_runq()\n")); + + for(;;) { + if (!con->schedq) + break; + if (gettimeofday(&tv, NULL)) { + /* This should never happen */ + ast_log(LOG_NOTICE, "gettimeofday() failed!\n"); + return 0; + } + /* We only care about millisecond accuracy anyway, so this will + help us get more than one event at one time if they are very + close together. */ + tv.tv_usec += 1000; + if (SOONER(con->schedq->when, tv)) { + current = con->schedq; + con->schedq = con->schedq->next; + con->schedcnt--; + + /* + * At this point, the schedule queue is still intact. We + * have removed the first event and the rest is still there, + * so it's permissible for the callback to add new events, but + * trying to delete itself won't work because it isn't in + * the schedule queue. If that's what it wants to do, it + * should return 0. + */ + if (current->callback(current->data)) { + /* + * If they return non-zero, we should schedule them to be + * run again. + */ + if (sched_settime(¤t->when, current->resched)) { + sched_release(con, current); + } else + schedule(con, current); + } else { + /* No longer needed, so release it */ + sched_release(con, current); + } + x++; + } else + break; + } + return x; +} -- GitLab