1 /****************************************************************************
2  * Copyright (C) 1998 WIDE Project. All rights reserved.
3  * Copyright (C) 1999,2000,2001,2002 University of Tromso. All rights reserved.
4  * Copyright (C) 2002 Invenia Innovation AS. All rights reserved.
5  *
6  * Author: Feike W. Dillema, feico@pasta.cs.uit.no.
7  *         based on newbie code by Yusuke DOI, Keio Univ. Murai Lab.
8  ****************************************************************************/
9 
10 /*
11  * <$Id: ev_timeout.c,v 3.27 2002/12/11 16:39:49 dillema Exp $>
12  */
13 
14 #include "totd.h"
15 
16 static Q_Set *ev_to_queue;
17 
ev_to_init(void)18 int ev_to_init (void) {
19 
20 	if (ev_to_queue)
21 		return -1;
22 
23 	ev_to_queue = queue_create ();
24 	if (!ev_to_queue)
25 		return -1;
26 
27 	return 0;
28 }
29 
ev_to_register(Ev_TO_Data * td)30 int ev_to_register (Ev_TO_Data *td) {
31 	char *fn = "ev_to_register()";
32 	G_Queue *gq_new, *gq_tmp, *gq_prev;
33 
34 	gq_new = malloc (sizeof (G_Queue));
35 	if (!gq_new)
36         	syslog (LOG_ERR, "%s: Cannot allocate memory", fn);
37 	else {
38 		gq_prev = NULL;
39 		/* find place insertion sort style */
40 		for (gq_tmp = ev_to_queue->head; gq_tmp->next &&
41 		     ((Ev_TO_Data *) (gq_tmp->p))->at < td->at;
42 		     gq_tmp = gq_tmp->next)
43 			gq_prev = gq_tmp;	/* just skip */
44 
45 		if (!gq_prev) {
46 			if (T.debug > 3)
47 				syslog (LOG_DEBUG, "%s: add event to head", fn);
48 			gq_new->p = (void *) td;
49 			gq_new->next = ev_to_queue->head;
50 			ev_to_queue->head = gq_new;
51 		} else {
52 			while (gq_tmp->p &&
53 			       (((Ev_TO_Data *) (gq_tmp->p))->at == td->at)) {
54 				gq_prev = gq_tmp;
55 				gq_tmp = gq_tmp->next;
56 			}
57 
58 			if (!gq_tmp->p) {
59 				if (T.debug > 3)
60 					syslog (LOG_DEBUG, "%s: add to tail",
61 						fn);
62 				ev_to_queue->tail->p = (void *) td;
63 				ev_to_queue->tail->next = gq_new;
64 				gq_new->p = NULL;
65 				gq_new->next = NULL;
66 				ev_to_queue->tail = gq_new;
67 			} else {
68 				if (T.debug > 3)
69 					syslog (LOG_DEBUG, "%s: add to middle",
70 						fn);
71 				gq_new->p = (void *) td;
72 				gq_prev->next = gq_new;
73 				gq_new->next = gq_tmp;
74 			}
75 		}
76 		/* SUCCESS */
77 		return 0;
78 	}
79 
80 	/* FAILURE */
81 	return -1;
82 }
83 
ev_timeout_process(void)84 time_t ev_timeout_process (void) {
85 	char *fn = "ev_timeout_process()";
86 	Ev_TO_Data *td_tmp;
87 
88 	while ((td_tmp = (Ev_TO_Data *) queue_peek (ev_to_queue))
89 	       && (td_tmp->at <= time (NULL))) {
90 		/* process the event */
91 		td_tmp = dequeue (ev_to_queue);
92 		/* call timeout handler, if any */
93 		if (td_tmp->handler) {
94 			if (T.debug > 3)
95 				syslog (LOG_DEBUG, "%s: call timeout handler",
96 					fn);
97 			(td_tmp->handler) (td_tmp);
98 		} else
99 			if (T.debug > 3)
100 				syslog (LOG_DEBUG, "%s: cancel timeout event",
101 					fn);
102 		ev_to_data_free (td_tmp);
103 	}
104 
105 	td_tmp = (Ev_TO_Data *) queue_peek (ev_to_queue);
106 	if (td_tmp)
107 		return td_tmp->at;	/* next event scheduled time */
108 	else
109 		return 0;	/* no event scheduled */
110 }
111 
ev_to_data_free(Ev_TO_Data * td)112 void ev_to_data_free (Ev_TO_Data *td) {
113 	char *fn = "ev_to_data_free()";
114 
115 	switch (td->type) {
116 	case EV_TIMEOUT_NULL:
117 		if (td->data.p)
118 			free (td->data.p);
119 		break;
120 	case EV_TIMEOUT_CONTEXT:
121 		/*
122 		 * don't free td->data.cont because transaction itself will
123 		 * free its context
124 		 */
125 		break;
126 	default:
127 		syslog (LOG_CRIT, "%s: unknown type for timeout event", fn);
128 		break;
129 	}
130 
131 	free (td);
132 }
133 
ev_to_data_free_v(void * td_v)134 void ev_to_data_free_v (void *td_v) {
135 	ev_to_data_free ((Ev_TO_Data *) td_v);
136 }
137 
ev_to_finish(void)138 void ev_to_finish (void) {
139 	queue_destroy (ev_to_queue, ev_to_data_free_v);
140 }
141 
ev_to_flush(int type)142 void ev_to_flush (int type) {
143 	G_Queue *gqp;
144 	Ev_TO_Data *etdp;
145 
146 	/* check one by one */
147 	for (gqp = ev_to_queue->head; gqp->next; gqp = gqp->next) {
148 		if (gqp->p) {
149 			etdp = (Ev_TO_Data *) (gqp->p);
150 			if (etdp->type == type) {
151 				if (etdp->handler)
152 					(etdp->handler) (etdp);
153 				etdp->handler = NULL;	/* disable the queue */
154 			}
155 		}
156 	}
157 	return;
158 }
159 
ev_to_register_ifcheck(void)160 int ev_to_register_ifcheck (void) {
161 	char *fn = "ev_to_register_ifcheck()";
162 	Ev_TO_Data *td_new;
163 
164 	if (T.debug > 2)
165 		syslog (LOG_DEBUG, "%s: start", fn);
166 
167 	if (!ev_to_queue)
168 		return -1;
169 
170 	td_new = malloc (sizeof (Ev_TO_Data));
171 	if (!td_new) {
172 		syslog (LOG_ERR, "%s: can't allocate new event", fn);
173 		return -1;
174 	}
175 	td_new->at = time (NULL) + IF_CHECK_INTERVAL;
176 	td_new->handler = ev_to_handler_ifcheck;
177 	td_new->type = EV_TIMEOUT_NULL;
178 	td_new->data.p = NULL;
179 
180 	ev_to_register (td_new);
181 	return 0;
182 }
183 
ev_to_handler_ifcheck(Ev_TO_Data * td)184 int ev_to_handler_ifcheck (Ev_TO_Data *td) {
185 	char *fn = "ev_to_handler_ifcheck()";
186 
187 	if (T.debug > 2)
188 		syslog (LOG_DEBUG, "%s: start", fn);
189 
190 	if (td) {
191 		switch (net_reinit_socketlist (T.port, 0)) {
192 		case 0:
193 			/* no change */
194 			syslog (LOG_DEBUG, "%s: Socket List still the same", fn);
195 			break;
196 		case 1:
197 			/* change, bound new sockets */
198 			syslog (LOG_DEBUG, "%s: Socket List updated", fn);
199 			break;
200 		default:
201 			syslog (LOG_ERR, "%s: Can't get new socket list!", fn);
202 		}
203 	}
204 
205 	/* (re-) register my event */
206 	return (ev_to_register_ifcheck());
207 }
208