Annotation of embedaddon/igmpproxy/src/callout.c, revision 1.1
1.1 ! misho 1: /*
! 2: ** igmpproxy - IGMP proxy based multicast router
! 3: ** Copyright (C) 2005 Johnny Egeland <johnny@rlo.org>
! 4: **
! 5: ** This program is free software; you can redistribute it and/or modify
! 6: ** it under the terms of the GNU General Public License as published by
! 7: ** the Free Software Foundation; either version 2 of the License, or
! 8: ** (at your option) any later version.
! 9: **
! 10: ** This program is distributed in the hope that it will be useful,
! 11: ** but WITHOUT ANY WARRANTY; without even the implied warranty of
! 12: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 13: ** GNU General Public License for more details.
! 14: **
! 15: ** You should have received a copy of the GNU General Public License
! 16: ** along with this program; if not, write to the Free Software
! 17: ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
! 18: **
! 19: **----------------------------------------------------------------------------
! 20: **
! 21: ** This software is derived work from the following software. The original
! 22: ** source code has been modified from it's original state by the author
! 23: ** of igmpproxy.
! 24: **
! 25: ** smcroute 0.92 - Copyright (C) 2001 Carsten Schill <carsten@cschill.de>
! 26: ** - Licensed under the GNU General Public License, version 2
! 27: **
! 28: ** mrouted 3.9-beta3 - COPYRIGHT 1989 by The Board of Trustees of
! 29: ** Leland Stanford Junior University.
! 30: ** - Original license can be found in the Stanford.txt file.
! 31: **
! 32: */
! 33:
! 34:
! 35: #include "igmpproxy.h"
! 36:
! 37: /* the code below implements a callout queue */
! 38: static int id = 0;
! 39: static struct timeOutQueue *queue = 0; /* pointer to the beginning of timeout queue */
! 40:
! 41: struct timeOutQueue {
! 42: struct timeOutQueue *next; // Next event in queue
! 43: int id;
! 44: timer_f func; // function to call
! 45: void *data; // Data for function
! 46: int time; // Time offset for next event
! 47: };
! 48:
! 49: // Method for dumping the Queue to the log.
! 50: static void debugQueue(void);
! 51:
! 52: /**
! 53: * Initializes the callout queue
! 54: */
! 55: void callout_init() {
! 56: queue = NULL;
! 57: }
! 58:
! 59: /**
! 60: * Clears all scheduled timeouts...
! 61: */
! 62: void free_all_callouts() {
! 63: struct timeOutQueue *p;
! 64:
! 65: while (queue) {
! 66: p = queue;
! 67: queue = queue->next;
! 68: free(p);
! 69: }
! 70: }
! 71:
! 72:
! 73: /**
! 74: * elapsed_time seconds have passed; perform all the events that should
! 75: * happen.
! 76: */
! 77: void age_callout_queue(int elapsed_time) {
! 78: struct timeOutQueue *ptr;
! 79: int i = 0;
! 80:
! 81: for (ptr = queue; ptr; ptr = queue, i++) {
! 82: if (ptr->time > elapsed_time) {
! 83: ptr->time -= elapsed_time;
! 84: return;
! 85: } else {
! 86: elapsed_time -= ptr->time;
! 87: queue = queue->next;
! 88: my_log(LOG_DEBUG, 0, "About to call timeout %d (#%d)", ptr->id, i);
! 89:
! 90: if (ptr->func)
! 91: ptr->func(ptr->data);
! 92: free(ptr);
! 93: }
! 94: }
! 95: }
! 96:
! 97: /**
! 98: * Return in how many seconds age_callout_queue() would like to be called.
! 99: * Return -1 if there are no events pending.
! 100: */
! 101: int timer_nextTimer() {
! 102: if (queue) {
! 103: if (queue->time < 0) {
! 104: my_log(LOG_WARNING, 0, "timer_nextTimer top of queue says %d",
! 105: queue->time);
! 106: return 0;
! 107: }
! 108: return queue->time;
! 109: }
! 110: return -1;
! 111: }
! 112:
! 113: /**
! 114: * Inserts a timer in queue.
! 115: * @param delay - Number of seconds the timeout should happen in.
! 116: * @param action - The function to call on timeout.
! 117: * @param data - Pointer to the function data to supply...
! 118: */
! 119: int timer_setTimer(int delay, timer_f action, void *data) {
! 120: struct timeOutQueue *ptr, *node, *prev;
! 121: int i = 0;
! 122:
! 123: /* create a node */
! 124: node = (struct timeOutQueue *)malloc(sizeof(struct timeOutQueue));
! 125: if (node == 0) {
! 126: my_log(LOG_WARNING, 0, "Malloc Failed in timer_settimer\n");
! 127: return -1;
! 128: }
! 129: node->func = action;
! 130: node->data = data;
! 131: node->time = delay;
! 132: node->next = 0;
! 133: node->id = ++id;
! 134:
! 135: prev = ptr = queue;
! 136:
! 137: /* insert node in the queue */
! 138:
! 139: /* if the queue is empty, insert the node and return */
! 140: if (!queue) {
! 141: queue = node;
! 142: }
! 143: else {
! 144: /* chase the pointer looking for the right place */
! 145: while (ptr) {
! 146: if (delay < ptr->time) {
! 147: // We found the correct node
! 148: node->next = ptr;
! 149: if (ptr == queue) {
! 150: queue = node;
! 151: }
! 152: else {
! 153: prev->next = node;
! 154: }
! 155: ptr->time -= node->time;
! 156: my_log(LOG_DEBUG, 0,
! 157: "Created timeout %d (#%d) - delay %d secs",
! 158: node->id, i, node->time);
! 159: debugQueue();
! 160: return node->id;
! 161: } else {
! 162: // Continur to check nodes.
! 163: delay -= ptr->time; node->time = delay;
! 164: prev = ptr;
! 165: ptr = ptr->next;
! 166: }
! 167: i++;
! 168: }
! 169: prev->next = node;
! 170: }
! 171: my_log(LOG_DEBUG, 0, "Created timeout %d (#%d) - delay %d secs",
! 172: node->id, i, node->time);
! 173: debugQueue();
! 174:
! 175: return node->id;
! 176: }
! 177:
! 178: /**
! 179: * returns the time until the timer is scheduled
! 180: */
! 181: int timer_leftTimer(int timer_id) {
! 182: struct timeOutQueue *ptr;
! 183: int left = 0;
! 184:
! 185: if (!timer_id)
! 186: return -1;
! 187:
! 188: for (ptr = queue; ptr; ptr = ptr->next) {
! 189: left += ptr->time;
! 190: if (ptr->id == timer_id) {
! 191: return left;
! 192: }
! 193: }
! 194: return -1;
! 195: }
! 196:
! 197: /**
! 198: * clears the associated timer. Returns 1 if succeeded.
! 199: */
! 200: int timer_clearTimer(int timer_id) {
! 201: struct timeOutQueue *ptr, *prev;
! 202: int i = 0;
! 203:
! 204: if (!timer_id)
! 205: return 0;
! 206:
! 207: prev = ptr = queue;
! 208:
! 209: /*
! 210: * find the right node, delete it. the subsequent node's time
! 211: * gets bumped up
! 212: */
! 213:
! 214: debugQueue();
! 215: while (ptr) {
! 216: if (ptr->id == timer_id) {
! 217: /* got the right node */
! 218:
! 219: /* unlink it from the queue */
! 220: if (ptr == queue)
! 221: queue = queue->next;
! 222: else
! 223: prev->next = ptr->next;
! 224:
! 225: /* increment next node if any */
! 226: if (ptr->next != 0)
! 227: (ptr->next)->time += ptr->time;
! 228:
! 229: if (ptr->data)
! 230: free(ptr->data);
! 231: my_log(LOG_DEBUG, 0, "deleted timer %d (#%d)", ptr->id, i);
! 232: free(ptr);
! 233: debugQueue();
! 234: return 1;
! 235: }
! 236: prev = ptr;
! 237: ptr = ptr->next;
! 238: i++;
! 239: }
! 240: // If we get here, the timer was not deleted.
! 241: my_log(LOG_DEBUG, 0, "failed to delete timer %d (#%d)", timer_id, i);
! 242: debugQueue();
! 243: return 0;
! 244: }
! 245:
! 246: /**
! 247: * debugging utility
! 248: */
! 249: static void debugQueue() {
! 250: struct timeOutQueue *ptr;
! 251:
! 252: for (ptr = queue; ptr; ptr = ptr->next) {
! 253: my_log(LOG_DEBUG, 0, "(Id:%d, Time:%d) ", ptr->id, ptr->time);
! 254: }
! 255: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>