1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 *
22 * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*
27 * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
28 * All Rights Reserved.
29 */
30
31/*
32 * University Copyright- Copyright (c) 1982, 1986, 1988
33 * The Regents of the University of California.
34 * All Rights Reserved.
35 *
36 * University Acknowledgment- Portions of this document are derived from
37 * software developed by the University of California, Berkeley, and its
38 * contributors.
39 */
40
41/*
42 * Routines to handle insertion, deletion, etc on the table
43 * of requests kept by the daemon. Nothing fancy here, linear
44 * search on a double-linked list. A time is kept with each
45 * entry so that overly old invitations can be eliminated.
46 *
47 * Consider this a mis-guided attempt at modularity
48 */
49
50#include <sys/time.h>
51#include <string.h>
52#include <stdio.h>
53#include <malloc.h>
54#include "talkd_impl.h"
55
56#define	MAX_ID 16000 /* << 2^15 so I don't have sign troubles */
57
58typedef struct table_entry TABLE_ENTRY;
59
60struct table_entry {
61    CTL_MSG request;
62    long time;
63    TABLE_ENTRY *next;
64    TABLE_ENTRY *last;
65};
66
67static struct timeval tp;
68static TABLE_ENTRY *table = NULL;
69
70static void delete(TABLE_ENTRY *ptr);
71
72/*
73 * Look in the table for an invitation that matches the current
74 * request looking for an invitation.
75 */
76
77CTL_MSG *
78find_match(CTL_MSG *request)
79{
80	TABLE_ENTRY *ptr;
81	TABLE_ENTRY *prevp;
82	long current_time;
83
84	(void) gettimeofday(&tp, NULL);
85	current_time = tp.tv_sec;
86
87	ptr = table;
88
89	if (debug) {
90		(void) printf("Entering Look-Up with : \n");
91		print_request(request);
92	}
93
94	while (ptr != NULL) {
95
96		if ((ptr->time - current_time) > MAX_LIFE) {
97		/* the entry is too old */
98			if (debug) {
99				(void) printf("Deleting expired entry : \n");
100				print_request(&ptr->request);
101			}
102			prevp = ptr;
103			ptr = ptr->next;
104			delete(prevp);
105			continue;
106		}
107
108		if (debug)
109			print_request(&ptr->request);
110
111		if (strcmp(request->l_name, ptr->request.r_name) == 0 &&
112		    strcmp(request->r_name, ptr->request.l_name) == 0 &&
113		    ptr->request.type == LEAVE_INVITE) {
114			return (&ptr->request);
115		}
116
117		ptr = ptr->next;
118	}
119
120	return (NULL);
121}
122
123/*
124 * Look for an identical request, as opposed to a complimentary
125 * one as find_match does.
126 */
127
128CTL_MSG *
129find_request(CTL_MSG *request)
130{
131	TABLE_ENTRY *ptr;
132	TABLE_ENTRY *prevp;
133	long current_time;
134
135	(void) gettimeofday(&tp, NULL);
136	current_time = tp.tv_sec;
137
138	/*
139	 * See if this is a repeated message, and check for
140	 * out of date entries in the table while we are it.
141	 */
142
143	ptr = table;
144
145	if (debug) {
146		(void) printf("Entering find_request with : \n");
147		print_request(request);
148	}
149
150	while (ptr != NULL) {
151
152		if ((ptr->time - current_time) > MAX_LIFE) {
153			/* the entry is too old */
154			if (debug) {
155				(void) printf("Deleting expired entry : \n");
156				print_request(&ptr->request);
157			}
158			prevp = ptr;
159			ptr = ptr->next;
160			delete(prevp);
161			continue;
162		}
163
164		if (debug)
165			print_request(&ptr->request);
166
167		if (strcmp(request->r_name, ptr->request.r_name) == 0 &&
168		    strcmp(request->l_name, ptr->request.l_name) == 0 &&
169		    request->type == ptr->request.type &&
170		    request->pid == ptr->request.pid) {
171
172			/* update the time if we 'touch' it */
173			ptr->time = current_time;
174			return (&ptr->request);
175		}
176
177		ptr = ptr->next;
178	}
179
180	return (NULL);
181}
182
183void
184insert_table(CTL_MSG *request, CTL_RESPONSE *response)
185{
186	TABLE_ENTRY *ptr;
187	long current_time;
188
189	(void) gettimeofday(&tp, NULL);
190	current_time = tp.tv_sec;
191
192	response->id_num = request->id_num = new_id();
193
194	/*
195	 * Insert a new entry into the top of the list.
196	 */
197	ptr = (TABLE_ENTRY *) malloc(sizeof (TABLE_ENTRY));
198
199	if (ptr == NULL) {
200		print_error("malloc in insert_table");
201	}
202
203	ptr->time = current_time;
204	ptr->request = *request;
205
206	ptr->next = table;
207	if (ptr->next != NULL) {
208		ptr->next->last = ptr;
209	}
210	ptr->last = NULL;
211	table = ptr;
212}
213
214/*
215 * Generate a unique non-zero sequence number.
216 */
217
218int
219new_id(void)
220{
221	static int current_id = 0;
222
223	current_id = (current_id + 1) % MAX_ID;
224
225	/* 0 is reserved, helps to pick up bugs */
226	if (current_id == 0)
227		current_id = 1;
228
229	return (current_id);
230}
231
232/*
233 * Delete the invitation with id 'id_num'.
234 */
235
236int
237delete_invite(int id_num)
238{
239	TABLE_ENTRY *ptr;
240
241	ptr = table;
242
243	if (debug)
244		(void) printf("Entering delete_invite with %d\n", id_num);
245
246	while (ptr != NULL && ptr->request.id_num != id_num) {
247		if (debug)
248			print_request(&ptr->request);
249		ptr = ptr->next;
250	}
251
252	if (ptr != NULL) {
253		delete(ptr);
254		return (SUCCESS);
255	}
256
257	return (NOT_HERE);
258}
259
260/*
261 * Classic delete from a double-linked list.
262 */
263
264static void
265delete(TABLE_ENTRY *ptr)
266{
267	if (debug) {
268		(void) printf("Deleting : ");
269		print_request(&ptr->request);
270	}
271	if (table == ptr) {
272		table = ptr->next;
273	} else if (ptr->last != NULL) {
274		ptr->last->next = ptr->next;
275	}
276
277	if (ptr->next != NULL) {
278		ptr->next->last = ptr->last;
279	}
280
281	free(ptr);
282}
283