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