Initial revision
[silc.git] / lib / silccore / idcache.c
1 /*
2
3   idcache.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 2000 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* XXX: This ID cache system sucks and must be rewritten! */
21 /*
22  * $Id$
23  * $Log$
24  * Revision 1.1  2000/06/27 11:36:55  priikone
25  * Initial revision
26  *
27  *
28  */
29
30 #include "silcincludes.h"
31
32 /* qsort() sorter function. */
33
34 static int silc_idcache_sorter(const void *a, const void *b)
35 {
36   SilcIDCache *a1, *b1;
37   
38   a1 = (SilcIDCache *)a;
39   b1 = (SilcIDCache *)b;
40   
41   return a1->data[0] - b1->data[0];
42 }
43
44 /* Sorts given cache by data */
45
46 void silc_idcache_sort_by_data(SilcIDCache *cache, unsigned int count)
47 {
48   qsort(cache, count, sizeof(*cache), silc_idcache_sorter);
49 }
50
51 /* Find ID Cache entry by data. The data maybe anything that must
52    match exactly. */
53
54 int silc_idcache_find_by_data(SilcIDCache *cache, unsigned int cache_count,
55                               char *data, SilcIDCache **ret)
56 {
57   int i;
58
59   if (cache == NULL)
60     return FALSE;
61
62   if (data == NULL)
63     return FALSE;
64
65   for (i = 0; i < cache_count; i++)
66     if (cache[i].data && !memcmp(cache[i].data, data, strlen(data))) {
67       if (ret)
68         *ret = &(cache[i]);
69       return TRUE;
70     }
71
72   return FALSE;
73 }
74
75 /* Find ID Cache entry by ID. */
76
77 int silc_idcache_find_by_id(SilcIDCache *cache, unsigned int cache_count, 
78                             void *id, SilcIdType type, SilcIDCache **ret)
79 {
80   int i, id_len;
81
82   if (cache == NULL)
83     return FALSE;
84
85   if (id == NULL)
86     return FALSE;
87
88   id_len = silc_id_get_len(type);
89
90   for (i = 0; i < cache_count; i++)
91     if (cache[i].id && !memcmp(cache[i].id, id, id_len)) {
92       if (ret)
93         *ret = &(cache[i]);
94       return TRUE;
95     }
96
97   return FALSE;
98 }
99
100 /* Add new entry to the cache. Returns number of allocated cache
101    entries in the cache. */
102
103 int silc_idcache_add(SilcIDCache **cache, unsigned int cache_count,
104                      char *data, SilcIdType id_type, void *id, 
105                      void *context)
106 {
107   SilcIDCache *c;
108   int i;
109   unsigned long curtime = time(NULL);
110
111   SILC_LOG_DEBUG(("Adding cache entry"));
112
113   c = *cache;
114
115   if (c == NULL) {
116     c = silc_calloc(5, sizeof(*c));
117     if (!c)
118       return 0;
119     cache_count = 5;
120   }
121
122   /* See if it exists already */
123   if (silc_idcache_find_by_id(c, cache_count, id, id_type, NULL) == TRUE)
124     return cache_count;
125
126   for (i = 0; i < cache_count; i++) {
127     if (c[i].data == NULL) {
128       c[i].data = data;
129       c[i].type = id_type;
130       c[i].id = id;
131       c[i].expire = curtime + SILC_ID_CACHE_EXPIRE;
132       c[i].context = context;
133       break;
134     }
135   }
136
137   if (i == cache_count) {
138     c = silc_realloc(c, sizeof(*c) * (cache_count + 5));
139     if (!c)
140       return cache_count;
141     for (i = cache_count; i < cache_count + 5; i++) {
142       c[i].data = NULL;
143       c[i].id = NULL;
144     }
145     c[cache_count].data = data;
146     c[cache_count].type = id_type;
147     c[cache_count].id = id;
148     c[cache_count].expire = curtime + SILC_ID_CACHE_EXPIRE;
149     c[cache_count].context = context;
150     cache_count += 5;
151   }
152
153   *cache = c;
154
155   return cache_count;
156 }
157
158 /* Delete cache entry from cache. */
159 /* XXX */
160
161 int silc_idcache_del(SilcIDCache *cache, SilcIDCache *old)
162 {
163
164   return TRUE;
165 }
166
167 /* XXX */
168
169 int silc_idcache_del_by_data(SilcIDCache *cache, unsigned int cache_count,
170                              char *data)
171 {
172
173   return TRUE;
174 }
175
176 /* Deletes ID cache entry by ID. */
177
178 int silc_idcache_del_by_id(SilcIDCache *cache, unsigned int cache_count,
179                            SilcIdType type, void *id)
180 {
181   int i, id_len;
182
183   if (cache == NULL)
184     return FALSE;
185
186   if (id == NULL)
187     return FALSE;
188
189   id_len = silc_id_get_len(type);
190
191   for (i = 0; i < cache_count; i++)
192     if (cache[i].id && !memcmp(cache[i].id, id, id_len)) {
193       cache[i].id = NULL;
194       cache[i].data = NULL;
195       cache[i].type = 0;
196       cache[i].context = NULL;
197       return TRUE;
198     }
199
200   return FALSE;
201 }
202
203 /* Deletes all ID entries from cache. Free's memory as well. */
204
205 int silc_idcache_del_all(SilcIDCache **cache, unsigned int cache_count)
206 {
207   SilcIDCache *c = *cache;
208   int i;
209
210   if (c == NULL)
211     return FALSE;
212
213   for (i = 0; i < cache_count; i++) {
214     c[i].id = NULL;
215     c[i].data = NULL;
216     c[i].type = 0;
217     c[i].expire = 0;
218     c[i].context = NULL;
219   }
220
221   silc_free(*cache);
222   *cache = NULL;
223
224   return TRUE;
225 }
226
227 /* Purges the cache by removing expired cache entires. This does not
228    free any memory though. */
229
230 int silc_idcache_purge(SilcIDCache *cache, unsigned int cache_count)
231 {
232   unsigned long curtime = time(NULL);
233   int i;
234
235   if (cache == NULL)
236     return FALSE;
237
238   for (i = 0; i < cache_count; i++) {
239     if (cache[i].data && 
240         (cache[i].expire == 0 || cache[i].expire < curtime)) {
241       cache[i].id = NULL;
242       cache[i].data = NULL;
243       cache[i].type = 0;
244       cache[i].expire = 0;
245       cache[i].context = NULL;
246     }
247   }
248
249   return TRUE;
250 }