]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zhm/queue.c
unpack of new upstream
[1ts-debian.git] / zhm / queue.c
1 /* This file is part of the Project Athena Zephyr Notification System.
2  * It contains the hostmanager queueing routines.
3  *
4  *      Created by:     David C. Jedlinsky
5  *
6  *      $Id: queue.c,v 1.22 1999/10/20 16:44:11 ghudson Exp $
7  *
8  *      Copyright (c) 1987 by the Massachusetts Institute of Technology.
9  *      For copying and distribution information, see the file
10  *      "mit-copyright.h". 
11  */
12
13 #include "zhm.h"
14
15 #ifndef lint
16 #ifndef SABER
17 static char rcsid_queue_c[] = "$Id: queue.c,v 1.22 1999/10/20 16:44:11 ghudson Exp $";
18 #endif /* SABER */
19 #endif /* lint */
20
21 typedef struct _Queue {
22     Timer *timer;
23     int retries;
24     ZNotice_t notice;
25     caddr_t packet;
26     struct sockaddr_in reply;
27     struct _Queue *next, **prev_p;
28 } Queue;
29
30 static Queue *hm_queue;
31 static int retransmits_enabled = 0;
32
33 static Queue *find_notice_in_queue __P((ZNotice_t *notice));
34 static Code_t dump_queue __P((void));
35 static void queue_timeout __P((void *arg));
36
37 int rexmit_times[] = { 2, 2, 4, 4, 8, -1 };
38
39 #ifdef DEBUG
40 Code_t dump_queue();
41 #endif
42
43 void init_queue()
44 {
45     Queue *q;
46
47     while (hm_queue) {
48         q = hm_queue;
49         if (q->timer)
50             timer_reset(q->timer);
51         free(q->packet);
52         hm_queue = q->next;
53         free(q);
54     }
55
56     DPR("Queue initialized and flushed.\n");
57 }
58
59 Code_t add_notice_to_queue(notice, packet, repl, len)
60     ZNotice_t *notice;
61     char * packet;
62     struct sockaddr_in *repl;
63     int len;
64 {
65     Queue *entry;
66
67     DPR("Adding notice to queue...\n");
68     if (!find_notice_in_queue(notice)) {
69         entry = (Queue *) malloc(sizeof(Queue));
70         if (entry == NULL)
71             return(ZERR_NONOTICE);
72         entry->retries = 0;
73         entry->packet = (char *) malloc(Z_MAXPKTLEN);
74         if (entry->packet == NULL) {
75             free(entry);
76             return(ZERR_NONOTICE);
77         }
78         memcpy(entry->packet, packet, Z_MAXPKTLEN);
79         if (ZParseNotice(entry->packet, len, &entry->notice) != ZERR_NONE) {
80             syslog(LOG_ERR, "ZParseNotice failed, but succeeded before");
81             free(entry->packet);
82         } else {
83             entry->reply = *repl;
84             LIST_INSERT(&hm_queue, entry);
85         }
86         entry->timer = (retransmits_enabled) ?
87             timer_set_rel(rexmit_times[0], queue_timeout, entry) : NULL;
88     }
89     return(ZERR_NONE);
90 }
91
92 Code_t remove_notice_from_queue(notice, kind, repl)
93     ZNotice_t *notice;
94     ZNotice_Kind_t *kind;
95     struct sockaddr_in *repl;
96 {
97     Queue *entry;
98
99     DPR("Removing notice from queue...\n");
100     entry = find_notice_in_queue(notice);
101     if (entry == NULL)
102         return(ZERR_NONOTICE);
103
104     *kind = entry->notice.z_kind;
105     *repl = entry->reply;
106     if (entry->timer)
107         timer_reset(entry->timer);
108     free(entry->packet);
109     LIST_DELETE(entry);
110 #ifdef DEBUG
111     dump_queue();
112 #endif /* DEBUG */
113     free(entry);
114     return(ZERR_NONE);
115 }
116
117 /* We have a server; transmit all of our packets. */
118 void retransmit_queue(sin)
119     struct sockaddr_in *sin;
120 {
121     Queue *entry;
122     Code_t ret;
123
124     DPR("Retransmitting queue to new server...\n");
125     ret = ZSetDestAddr(sin);
126     if (ret != ZERR_NONE) {
127         Zperr (ret);
128         com_err("queue", ret, "setting destination");
129     }
130     for (entry = hm_queue; entry; entry = entry->next) {
131         DPR("notice:\n");
132         DPR2("\tz_kind: %d\n", entry->notice.z_kind);
133         DPR2("\tz_port: %u\n", ntohs(entry->notice.z_port));
134         DPR2("\tz_class: %s\n", entry->notice.z_class);
135         DPR2("\tz_clss_inst: %s\n", entry->notice.z_class_inst);
136         DPR2("\tz_opcode: %s\n", entry->notice.z_opcode);
137         DPR2("\tz_sender: %s\n", entry->notice.z_sender);
138         DPR2("\tz_recip: %s\n", entry->notice.z_recipient);
139         ret = send_outgoing(&entry->notice);
140         if (ret != ZERR_NONE) {
141             Zperr(ret);
142             com_err("queue", ret, "sending raw notice");
143         }
144         entry->timer = timer_set_rel(rexmit_times[0], queue_timeout, entry);
145         entry->retries = 0;
146     }
147     retransmits_enabled = 1;
148 }
149
150 /* We lost our server; nuke all of our timers. */
151 void disable_queue_retransmits()
152 {
153     Queue *entry;
154
155     for (entry = hm_queue; entry; entry = entry->next) {
156         if (entry->timer)
157             timer_reset(entry->timer);
158         entry->timer = NULL;
159     }
160     retransmits_enabled = 0;
161 }
162
163 #ifdef DEBUG
164 static Code_t dump_queue()
165 {
166     Queue *entry;
167     caddr_t mp;
168     int ml;
169
170     DPR("Dumping queue...\n");
171     if (!hm_queue) {
172         printf("Queue is empty.\n");
173         return;
174     }
175
176     for (entry = hm_queue; entry; entry = entry->next) {
177         printf("notice:\n");
178         printf("\tz_kind: %d\n", entry->notice.z_kind);
179         printf("\tz_port: %u\n", ntohs(entry->notice.z_port));
180         printf("\tz_class: %s\n", entry->notice.z_class);
181         printf("\tz_clss_inst: %s\n", entry->notice.z_class_inst);
182         printf("\tz_opcode: %s\n", entry->notice.z_opcode);
183         printf("\tz_sender: %s\n", entry->notice.z_sender);
184         printf("\tz_recip: %s\n", entry->notice.z_recipient);
185         printf("\tMessage:\n");
186         mp = entry->notice.z_message;
187         for (ml = strlen(mp) + 1; ml <= entry->notice.z_message_len; ml++) {
188             printf("\t%s\n", mp);
189             mp += strlen(mp)+1;
190             ml += strlen(mp);
191         }
192     }
193 }
194 #endif /* DEBUG */
195
196 int queue_len()
197 {
198     int length = 0;
199     Queue *entry;
200
201     for (entry = hm_queue; entry; entry = entry->next)
202         length++;
203     return length;
204 }
205
206 static Queue *find_notice_in_queue(notice)
207     ZNotice_t *notice;
208 {
209     Queue *entry;
210
211     for (entry = hm_queue; entry; entry = entry->next) {
212         if (ZCompareUID(&entry->notice.z_uid, &notice->z_uid))
213             return entry;
214     }
215     return NULL;
216 }
217
218 static void queue_timeout(arg)
219     void *arg;
220 {
221     Queue *entry = (Queue *) arg;
222     Code_t ret;
223
224     entry->timer = NULL;
225     ret = ZSetDestAddr(&serv_sin);
226     if (ret != ZERR_NONE) {
227         Zperr(ret);
228         com_err("queue", ret, "setting destination");
229     }
230     entry->retries++;
231     if (rexmit_times[entry->retries] == -1) {
232         new_server(NULL);
233         return;
234     }
235     DPR("Resending notice:\n");
236     DPR2("\tz_kind: %d\n", entry->notice.z_kind);
237     DPR2("\tz_port: %u\n", ntohs(entry->notice.z_port));
238     DPR2("\tz_class: %s\n", entry->notice.z_class);
239     DPR2("\tz_clss_inst: %s\n", entry->notice.z_class_inst);
240     DPR2("\tz_opcode: %s\n", entry->notice.z_opcode);
241     DPR2("\tz_sender: %s\n", entry->notice.z_sender);
242     DPR2("\tz_recip: %s\n", entry->notice.z_recipient);
243     ret = send_outgoing(&entry->notice);
244     if (ret != ZERR_NONE) {
245         Zperr(ret);
246         com_err("queue", ret, "sending raw notice");
247     }
248     entry->timer = timer_set_rel(rexmit_times[entry->retries], queue_timeout,
249                                  entry);
250 }
251