File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / igmpproxy / src / callout.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:00:29 2012 UTC (12 years, 4 months ago) by misho
Branches: igmpproxy, MAIN
CVS tags: v0_1p0, v0_1, HEAD
igmpproxy

    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>