Annotation of embedaddon/igmpproxy/src/callout.c, revision 1.1.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>