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>