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>