Changes to update Tomato RAF.
[tomato.git] / release / src / router / igmpproxy / src / callout.c
blob6ac0673737aec06a439d4002ce58468728cd89a3
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.
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
19 **----------------------------------------------------------------------------
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.
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.
35 #include "igmpproxy.h"
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 */
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
49 // Method for dumping the Queue to the log.
50 static void debugQueue(void);
52 /**
53 * Initializes the callout queue
55 void callout_init() {
56 queue = NULL;
59 /**
60 * Clears all scheduled timeouts...
62 void free_all_callouts() {
63 struct timeOutQueue *p;
65 while (queue) {
66 p = queue;
67 queue = queue->next;
68 free(p);
73 /**
74 * elapsed_time seconds have passed; perform all the events that should
75 * happen.
77 void age_callout_queue(int elapsed_time) {
78 struct timeOutQueue *ptr;
79 struct timeOutQueue *_queue = NULL;
80 struct timeOutQueue *last = NULL;
81 int i = 0;
83 for (ptr = queue; ptr; ptr = ptr->next) {
84 if (ptr->time > elapsed_time) {
85 ptr->time -= elapsed_time;
86 break;
87 } else {
88 elapsed_time -= ptr->time;
89 if (_queue == NULL)
90 _queue = ptr;
91 last = ptr;
95 queue = ptr;
96 if (last) {
97 last->next = NULL;
100 /* process existing events */
101 for (ptr = _queue; ptr; ptr = _queue, i++) {
102 _queue = _queue->next;
103 my_log(LOG_DEBUG, 0, "About to call timeout %d (#%d)", ptr->id, i);
104 if (ptr->func)
105 ptr->func(ptr->data);
106 free(ptr);
111 * Return in how many seconds age_callout_queue() would like to be called.
112 * Return -1 if there are no events pending.
114 int timer_nextTimer() {
115 if (queue) {
116 if (queue->time < 0) {
117 my_log(LOG_WARNING, 0, "timer_nextTimer top of queue says %d",
118 queue->time);
119 return 0;
121 return queue->time;
123 return -1;
127 * Inserts a timer in queue.
128 * @param delay - Number of seconds the timeout should happen in.
129 * @param action - The function to call on timeout.
130 * @param data - Pointer to the function data to supply...
132 int timer_setTimer(int delay, timer_f action, void *data) {
133 struct timeOutQueue *ptr, *node, *prev;
134 int i = 0;
136 /* create a node */
137 node = (struct timeOutQueue *)malloc(sizeof(struct timeOutQueue));
138 if (node == 0) {
139 my_log(LOG_WARNING, 0, "Malloc Failed in timer_settimer\n");
140 return -1;
142 node->func = action;
143 node->data = data;
144 node->time = delay;
145 node->next = 0;
146 node->id = ++id;
148 prev = ptr = queue;
150 /* insert node in the queue */
152 /* if the queue is empty, insert the node and return */
153 if (!queue) {
154 queue = node;
156 else {
157 /* chase the pointer looking for the right place */
158 while (ptr) {
159 if (delay < ptr->time) {
160 // We found the correct node
161 node->next = ptr;
162 if (ptr == queue) {
163 queue = node;
165 else {
166 prev->next = node;
168 ptr->time -= node->time;
169 my_log(LOG_DEBUG, 0,
170 "Created timeout %d (#%d) - delay %d secs",
171 node->id, i, node->time);
172 debugQueue();
173 return node->id;
174 } else {
175 // Continur to check nodes.
176 delay -= ptr->time; node->time = delay;
177 prev = ptr;
178 ptr = ptr->next;
180 i++;
182 prev->next = node;
184 my_log(LOG_DEBUG, 0, "Created timeout %d (#%d) - delay %d secs",
185 node->id, i, node->time);
186 debugQueue();
188 return node->id;
192 * returns the time until the timer is scheduled
194 int timer_leftTimer(int timer_id) {
195 struct timeOutQueue *ptr;
196 int left = 0;
198 if (!timer_id)
199 return -1;
201 for (ptr = queue; ptr; ptr = ptr->next) {
202 left += ptr->time;
203 if (ptr->id == timer_id) {
204 return left;
207 return -1;
211 * clears the associated timer. Returns 1 if succeeded.
213 int timer_clearTimer(int timer_id) {
214 struct timeOutQueue *ptr, *prev;
215 int i = 0;
217 if (!timer_id)
218 return 0;
220 prev = ptr = queue;
223 * find the right node, delete it. the subsequent node's time
224 * gets bumped up
227 debugQueue();
228 while (ptr) {
229 if (ptr->id == timer_id) {
230 /* got the right node */
232 /* unlink it from the queue */
233 if (ptr == queue)
234 queue = queue->next;
235 else
236 prev->next = ptr->next;
238 /* increment next node if any */
239 if (ptr->next != 0)
240 (ptr->next)->time += ptr->time;
242 if (ptr->data)
243 free(ptr->data);
244 my_log(LOG_DEBUG, 0, "deleted timer %d (#%d)", ptr->id, i);
245 free(ptr);
246 debugQueue();
247 return 1;
249 prev = ptr;
250 ptr = ptr->next;
251 i++;
253 // If we get here, the timer was not deleted.
254 my_log(LOG_DEBUG, 0, "failed to delete timer %d (#%d)", timer_id, i);
255 debugQueue();
256 return 0;
260 * debugging utility
262 static void debugQueue() {
263 struct timeOutQueue *ptr;
265 for (ptr = queue; ptr; ptr = ptr->next) {
266 my_log(LOG_DEBUG, 0, "(Id:%d, Time:%d) ", ptr->id, ptr->time);