Added command lagging support. Added idle counting support.
[silc.git] / apps / silcd / idlist.c
1 /*
2
3   idlist.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 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 /*
21  * $Id$
22  * $Log$
23  * Revision 1.6  2000/07/17 11:47:30  priikone
24  *      Added command lagging support. Added idle counting support.
25  *
26  * Revision 1.5  2000/07/12 05:59:41  priikone
27  *      Major rewrite of ID Cache system. Support added for the new
28  *      ID cache system. Major rewrite of ID List stuff on server.  All
29  *      SilcXXXList's are now called SilcXXXEntry's and they are pointers
30  *      by default. A lot rewritten ID list functions.
31  *
32  * Revision 1.4  2000/07/06 07:16:13  priikone
33  *      Added SilcPublicKey's
34  *
35  * Revision 1.3  2000/07/05 06:14:01  priikone
36  *      Global costemic changes.
37  *
38  * Revision 1.2  2000/07/03 05:52:11  priikone
39  *      Fixed typo and a bug.
40  *
41  * Revision 1.1.1.1  2000/06/27 11:36:56  priikone
42  *      Imported from internal CVS/Added Log headers.
43  *
44  *
45  */
46
47 #include "serverincludes.h"
48 #include "idlist.h"
49
50 /******************************************************************************
51
52                           Server entry functions
53
54 ******************************************************************************/
55
56 /* Add new server entry. This adds the new server entry to ID cache and
57    returns the allocated entry object or NULL on error. This is called
58    when new server connects to us. We also add ourselves to cache with
59    this function. */
60
61 SilcServerEntry 
62 silc_idlist_add_server(SilcIDList id_list, 
63                        char *server_name, int server_type,
64                        SilcServerID *id, SilcServerEntry router,
65                        SilcCipher send_key, SilcCipher receive_key,
66                        SilcPKCS pkcs, SilcHmac hmac, 
67                        SilcPublicKey public_key, void *connection)
68 {
69   SilcServerEntry server;
70
71   SILC_LOG_DEBUG(("Adding new server entry"));
72
73   server = silc_calloc(1, sizeof(*server));
74   server->server_name = server_name;
75   server->server_type = server_type;
76   server->id = id;
77   server->router = router;
78   server->send_key = send_key;
79   server->receive_key = receive_key;
80   server->pkcs = pkcs;
81   server->hmac = hmac;
82   server->public_key = public_key;
83   server->connection = connection;
84
85   if (!silc_idcache_add(id_list->servers, server->server_name, SILC_ID_SERVER,
86                         (void *)server->id, (void *)server, TRUE)) {
87     silc_free(server);
88     return NULL;
89   }
90
91   return server;
92 }
93
94 /******************************************************************************
95
96                           Client entry functions
97
98 ******************************************************************************/
99
100 /* Add new client entry. This adds the client entry to ID cache system
101    and returns the allocated client entry or NULL on error.  This is
102    called when new client connection is accepted to the server. */
103
104 SilcClientEntry
105 silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
106                        char *userinfo, SilcClientID *id, 
107                        SilcServerEntry router,
108                        SilcCipher send_key, SilcCipher receive_key,
109                        SilcPKCS pkcs, SilcHmac hmac, 
110                        SilcPublicKey public_key, void *connection)
111 {
112   SilcClientEntry client;
113
114   SILC_LOG_DEBUG(("Adding new client entry"));
115
116   client = silc_calloc(1, sizeof(*client));
117   client->nickname = nickname;
118   client->username = username;
119   client->userinfo = userinfo;
120   client->id = id;
121   client->router = router;
122   client->send_key = send_key;
123   client->receive_key = receive_key;
124   client->pkcs = pkcs;
125   client->hmac = hmac;
126   client->public_key = public_key;
127   client->connection = connection;
128
129   if (!silc_idcache_add(id_list->clients, client->nickname, SILC_ID_CLIENT,
130                         (void *)client->id, (void *)client, TRUE)) {
131     silc_free(client);
132     return NULL;
133   }
134
135   return client;
136 }
137
138 /* Free client entry. This free's everything and removes the entry
139    from ID cache. */
140
141 void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
142 {
143   if (entry) {
144     /* Remove from cache */
145     if (entry->id)
146       silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT, 
147                              (void *)entry->id);
148
149     /* Free data */
150     if (entry->nickname)
151       silc_free(entry->nickname);
152     if (entry->username)
153       silc_free(entry->username);
154     if (entry->userinfo)
155       silc_free(entry->userinfo);
156     if (entry->id)
157       silc_free(entry->id);
158     if (entry->send_key)
159       silc_cipher_free(entry->send_key);
160     if (entry->receive_key)
161       silc_cipher_free(entry->receive_key);
162     if (entry->pkcs)
163       silc_pkcs_free(entry->pkcs);
164     if (entry->public_key)
165       silc_pkcs_public_key_free(entry->public_key);
166     if (entry->hmac)
167       silc_hmac_free(entry->hmac);
168   }
169 }
170
171 /* Finds client entry by nickname. */
172
173 SilcClientEntry
174 silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
175                                     char *server)
176 {
177   SilcIDCacheList list = NULL;
178   SilcIDCacheEntry id_cache = NULL;
179   SilcClientEntry client = NULL;
180
181   SILC_LOG_DEBUG(("Finding client by nickname"));
182
183   if (server) {
184     if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
185       return NULL;
186
187 #if 0
188     while (silc_idcache_list_next(list, &id_cache)) {
189       client = (SilcClientEntry)id_cache->context;
190
191       if (!strcmp(server, XXX, strlen(server)))
192         break;
193
194       client = NULL;
195     }
196 #endif
197
198    if (!client)
199      return NULL;
200
201    silc_idcache_list_free(list);
202   } else {
203     if (!silc_idcache_find_by_data_one(id_list->clients, nickname, &id_cache))
204       return NULL;
205
206     client = (SilcClientEntry)id_cache->context;
207   }
208
209   return client;
210 }
211
212 /* Finds client by nickname hash. */
213
214 SilcClientEntry
215 silc_idlist_find_client_by_hash(SilcIDList id_list, unsigned char *hash,
216                                 SilcHash md5hash)
217 {
218
219   return NULL;
220 }
221
222 /* Finds client by Client ID */
223
224 SilcClientEntry
225 silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id)
226 {
227   SilcIDCacheEntry id_cache = NULL;
228   SilcClientEntry client;
229
230   if (!id)
231     return NULL;
232
233   SILC_LOG_DEBUG(("Finding client by ID"));
234
235   if (!silc_idcache_find_by_id_one(id_list->clients, (void *)id, 
236                                    SILC_ID_CLIENT, &id_cache))
237     return NULL;
238
239   client = (SilcClientEntry)id_cache->context;
240
241   return client;
242 }
243
244 /******************************************************************************
245
246                           Channel entry functions
247
248 ******************************************************************************/
249
250 /* Add new channel entry. This add the new channel entry to the ID cache
251    system and returns the allocated entry or NULL on error. */
252
253 SilcChannelEntry
254 silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
255                         SilcChannelID *id, SilcServerEntry router,
256                         SilcCipher channel_key)
257 {
258   SilcChannelEntry channel;
259
260   channel = silc_calloc(1, sizeof(*channel));
261   channel->channel_name = channel_name;
262   channel->mode = mode;
263   channel->id = id;
264   channel->router = router;
265   channel->channel_key = channel_key;
266
267   if (!silc_idcache_add(id_list->channels, channel->channel_name, 
268                         SILC_ID_CHANNEL, (void *)channel->id, 
269                         (void *)channel, TRUE)) {
270     silc_free(channel);
271     return NULL;
272   }
273
274   return channel;
275 }
276
277 /* Free channel entry.  This free's everything. */
278
279 void silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
280 {
281   if (entry) {
282     /* Remove from cache */
283     if (entry->id)
284       silc_idcache_del_by_id(id_list->channels, SILC_ID_CHANNEL, 
285                              (void *)entry->id);
286
287     /* Free data */
288     if (entry->channel_name)
289       silc_free(entry->channel_name);
290     if (entry->id)
291       silc_free(entry->id);
292     if (entry->topic)
293       silc_free(entry->topic);
294     if (entry->channel_key)
295       silc_cipher_free(entry->channel_key);
296     if (entry->key) {
297       memset(entry->key, 0, entry->key_len / 8);
298       silc_free(entry->key);
299     }
300     memset(entry->iv, 0, sizeof(entry->iv));
301
302     if (entry->user_list_count)
303       silc_free(entry->user_list);
304   }
305 }
306
307 /* Finds channel by channel name. Channel names are unique and they
308    are not case-sensitive. */
309
310 SilcChannelEntry
311 silc_idlist_find_channel_by_name(SilcIDList id_list, char *name)
312 {
313   SilcIDCacheList list = NULL;
314   SilcIDCacheEntry id_cache = NULL;
315   SilcChannelEntry channel;
316
317   SILC_LOG_DEBUG(("Finding channel by name"));
318
319   if (!silc_idcache_find_by_data_loose(id_list->channels, name, &list))
320     return NULL;
321   
322   if (!silc_idcache_list_first(list, &id_cache))
323     return NULL;
324
325   channel = (SilcChannelEntry)id_cache->context;
326
327   silc_idcache_list_free(list);
328
329   return channel;
330 }
331
332 /* Finds channel by Channel ID. */
333
334 SilcChannelEntry
335 silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id)
336 {
337   SilcIDCacheEntry id_cache = NULL;
338   SilcChannelEntry channel;
339
340   if (!id)
341     return NULL;
342
343   SILC_LOG_DEBUG(("Finding channel by ID"));
344
345   if (!silc_idcache_find_by_id_one(id_list->channels, (void *)id, 
346                                    SILC_ID_CHANNEL, &id_cache))
347     return NULL;
348
349   channel = (SilcChannelEntry)id_cache->context;
350
351   return channel;
352 }