ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hash.c
Revision: 1332
Committed: Sun Apr 1 16:25:50 2012 UTC (13 years, 4 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/hash.c
File size: 21501 byte(s)
Log Message:
- init_hash(): remove unused variable

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * hash.c: Maintains hashtables.
4     *
5     * Copyright (C) 2002 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22 knight 31 * $Id$
23 adx 30 */
24    
25     #include "stdinc.h"
26 michael 1011 #include "list.h"
27     #include "balloc.h"
28 michael 1309 #include "conf.h"
29 adx 30 #include "channel.h"
30     #include "channel_mode.h"
31     #include "client.h"
32     #include "modules.h"
33     #include "hash.h"
34     #include "resv.h"
35 michael 982 #include "rng_mt.h"
36 adx 30 #include "userhost.h"
37     #include "irc_string.h"
38     #include "ircd.h"
39     #include "numeric.h"
40     #include "send.h"
41     #include "memory.h"
42     #include "dbuf.h"
43     #include "s_user.h"
44    
45    
46     static BlockHeap *userhost_heap = NULL;
47     static BlockHeap *namehost_heap = NULL;
48     static struct UserHost *find_or_add_userhost(const char *);
49    
50 michael 982 static unsigned int hashf_xor_key = 0;
51 adx 30
52     /* The actual hash tables, They MUST be of the same HASHSIZE, variable
53     * size tables could be supported but the rehash routine should also
54     * rebuild the transformation maps, I kept the tables of equal size
55     * so that I can use one hash function.
56     */
57     static struct Client *idTable[HASHSIZE];
58     static struct Client *clientTable[HASHSIZE];
59     static struct Channel *channelTable[HASHSIZE];
60     static struct UserHost *userhostTable[HASHSIZE];
61     static struct ResvChannel *resvchannelTable[HASHSIZE];
62    
63    
64     /* init_hash()
65     *
66     * inputs - NONE
67     * output - NONE
68     * side effects - Initialize the maps used by hash
69     * functions and clear the tables
70     */
71     void
72     init_hash(void)
73     {
74     /* Default the userhost/namehost sizes to CLIENT_HEAP_SIZE for now,
75     * should be a good close approximation anyway
76     * - Dianora
77     */
78     userhost_heap = BlockHeapCreate("userhost", sizeof(struct UserHost), CLIENT_HEAP_SIZE);
79     namehost_heap = BlockHeapCreate("namehost", sizeof(struct NameHost), CLIENT_HEAP_SIZE);
80    
81 michael 982 hashf_xor_key = genrand_int32() % 256; /* better than nothing --adx */
82 adx 30 }
83    
84     /*
85     * New hash function based on the Fowler/Noll/Vo (FNV) algorithm from
86     * http://www.isthe.com/chongo/tech/comp/fnv/
87     *
88     * Here, we use the FNV-1 method, which gives slightly better results
89     * than FNV-1a. -Michael
90     */
91     unsigned int
92     strhash(const char *name)
93     {
94     const unsigned char *p = (const unsigned char *)name;
95     unsigned int hval = FNV1_32_INIT;
96    
97     if (*p == '\0')
98     return 0;
99     for (; *p != '\0'; ++p)
100     {
101     hval += (hval << 1) + (hval << 4) + (hval << 7) +
102     (hval << 8) + (hval << 24);
103 michael 982 hval ^= (ToLower(*p) ^ hashf_xor_key);
104 adx 30 }
105    
106 michael 982 return (hval >> FNV1_32_BITS) ^ (hval & ((1 << FNV1_32_BITS) - 1));
107 adx 30 }
108    
109     /************************** Externally visible functions ********************/
110    
111     /* Optimization note: in these functions I supposed that the CSE optimization
112     * (Common Subexpression Elimination) does its work decently, this means that
113     * I avoided introducing new variables to do the work myself and I did let
114     * the optimizer play with more free registers, actual tests proved this
115     * solution to be faster than doing things like tmp2=tmp->hnext... and then
116     * use tmp2 myself which would have given less freedom to the optimizer.
117     */
118    
119     /* hash_add_client()
120     *
121     * inputs - pointer to client
122     * output - NONE
123     * side effects - Adds a client's name in the proper hash linked
124     * list, can't fail, client_p must have a non-null
125     * name or expect a coredump, the name is infact
126     * taken from client_p->name
127     */
128     void
129     hash_add_client(struct Client *client_p)
130     {
131     unsigned int hashv = strhash(client_p->name);
132    
133     client_p->hnext = clientTable[hashv];
134     clientTable[hashv] = client_p;
135     }
136    
137     /* hash_add_channel()
138     *
139     * inputs - pointer to channel
140     * output - NONE
141     * side effects - Adds a channel's name in the proper hash linked
142     * list, can't fail. chptr must have a non-null name
143     * or expect a coredump. As before the name is taken
144     * from chptr->name, we do hash its entire lenght
145     * since this proved to be statistically faster
146     */
147     void
148     hash_add_channel(struct Channel *chptr)
149     {
150     unsigned int hashv = strhash(chptr->chname);
151    
152     chptr->hnextch = channelTable[hashv];
153     channelTable[hashv] = chptr;
154     }
155    
156     void
157     hash_add_resv(struct ResvChannel *chptr)
158     {
159     unsigned int hashv = strhash(chptr->name);
160    
161     chptr->hnext = resvchannelTable[hashv];
162     resvchannelTable[hashv] = chptr;
163     }
164    
165     void
166     hash_add_userhost(struct UserHost *userhost)
167     {
168     unsigned int hashv = strhash(userhost->host);
169    
170     userhost->next = userhostTable[hashv];
171     userhostTable[hashv] = userhost;
172     }
173    
174     void
175     hash_add_id(struct Client *client_p)
176     {
177     unsigned int hashv = strhash(client_p->id);
178    
179     client_p->idhnext = idTable[hashv];
180     idTable[hashv] = client_p;
181     }
182    
183     /* hash_del_id()
184     *
185     * inputs - pointer to client
186     * output - NONE
187     * side effects - Removes an ID from the hash linked list
188     */
189     void
190     hash_del_id(struct Client *client_p)
191     {
192     unsigned int hashv = strhash(client_p->id);
193     struct Client *tmp = idTable[hashv];
194    
195     if (tmp != NULL)
196     {
197     if (tmp == client_p)
198     {
199     idTable[hashv] = client_p->idhnext;
200     client_p->idhnext = client_p;
201     }
202     else
203     {
204     while (tmp->idhnext != client_p)
205     if ((tmp = tmp->idhnext) == NULL)
206     return;
207    
208     tmp->idhnext = tmp->idhnext->idhnext;
209     client_p->idhnext = client_p;
210     }
211     }
212     }
213    
214     /* hash_del_client()
215     *
216     * inputs - pointer to client
217     * output - NONE
218     * side effects - Removes a Client's name from the hash linked list
219     */
220     void
221     hash_del_client(struct Client *client_p)
222     {
223     unsigned int hashv = strhash(client_p->name);
224     struct Client *tmp = clientTable[hashv];
225    
226     if (tmp != NULL)
227     {
228     if (tmp == client_p)
229     {
230     clientTable[hashv] = client_p->hnext;
231     client_p->hnext = client_p;
232     }
233     else
234     {
235     while (tmp->hnext != client_p)
236     if ((tmp = tmp->hnext) == NULL)
237     return;
238    
239     tmp->hnext = tmp->hnext->hnext;
240     client_p->hnext = client_p;
241     }
242     }
243     }
244    
245     /* hash_del_userhost()
246     *
247     * inputs - pointer to userhost
248     * output - NONE
249     * side effects - Removes a userhost from the hash linked list
250     */
251     void
252     hash_del_userhost(struct UserHost *userhost)
253     {
254     unsigned int hashv = strhash(userhost->host);
255     struct UserHost *tmp = userhostTable[hashv];
256    
257     if (tmp != NULL)
258     {
259     if (tmp == userhost)
260     {
261     userhostTable[hashv] = userhost->next;
262     userhost->next = userhost;
263     }
264     else
265     {
266     while (tmp->next != userhost)
267     if ((tmp = tmp->next) == NULL)
268     return;
269    
270     tmp->next = tmp->next->next;
271     userhost->next = userhost;
272     }
273     }
274     }
275    
276     /* hash_del_channel()
277     *
278     * inputs - pointer to client
279     * output - NONE
280     * side effects - Removes the channel's name from the corresponding
281     * hash linked list
282     */
283     void
284     hash_del_channel(struct Channel *chptr)
285     {
286     unsigned int hashv = strhash(chptr->chname);
287     struct Channel *tmp = channelTable[hashv];
288    
289     if (tmp != NULL)
290     {
291     if (tmp == chptr)
292     {
293     channelTable[hashv] = chptr->hnextch;
294     chptr->hnextch = chptr;
295     }
296     else
297     {
298     while (tmp->hnextch != chptr)
299     if ((tmp = tmp->hnextch) == NULL)
300     return;
301    
302     tmp->hnextch = tmp->hnextch->hnextch;
303     chptr->hnextch = chptr;
304     }
305     }
306     }
307    
308     void
309     hash_del_resv(struct ResvChannel *chptr)
310     {
311     unsigned int hashv = strhash(chptr->name);
312     struct ResvChannel *tmp = resvchannelTable[hashv];
313    
314     if (tmp != NULL)
315     {
316     if (tmp == chptr)
317     {
318     resvchannelTable[hashv] = chptr->hnext;
319     chptr->hnext = chptr;
320     }
321     else
322     {
323     while (tmp->hnext != chptr)
324     if ((tmp = tmp->hnext) == NULL)
325     return;
326    
327     tmp->hnext = tmp->hnext->hnext;
328     chptr->hnext = chptr;
329     }
330     }
331     }
332    
333 michael 1169 /* hash_find_client()
334 adx 30 *
335     * inputs - pointer to name
336     * output - NONE
337     * side effects - New semantics: finds a client whose name is 'name'
338     * if can't find one returns NULL. If it finds one moves
339     * it to the top of the list and returns it.
340     */
341     struct Client *
342 michael 1169 hash_find_client(const char *name)
343 adx 30 {
344     unsigned int hashv = strhash(name);
345     struct Client *client_p;
346    
347     if ((client_p = clientTable[hashv]) != NULL)
348     {
349     if (irccmp(name, client_p->name))
350     {
351     struct Client *prev;
352    
353     while (prev = client_p, (client_p = client_p->hnext) != NULL)
354     {
355     if (!irccmp(name, client_p->name))
356     {
357     prev->hnext = client_p->hnext;
358     client_p->hnext = clientTable[hashv];
359     clientTable[hashv] = client_p;
360     break;
361     }
362     }
363     }
364     }
365    
366     return client_p;
367     }
368    
369     struct Client *
370     hash_find_id(const char *name)
371     {
372     unsigned int hashv = strhash(name);
373     struct Client *client_p;
374    
375     if ((client_p = idTable[hashv]) != NULL)
376     {
377 michael 880 if (strcmp(name, client_p->id))
378 adx 30 {
379     struct Client *prev;
380    
381     while (prev = client_p, (client_p = client_p->idhnext) != NULL)
382     {
383 michael 880 if (!strcmp(name, client_p->id))
384 adx 30 {
385     prev->idhnext = client_p->idhnext;
386     client_p->idhnext = idTable[hashv];
387     idTable[hashv] = client_p;
388     break;
389     }
390     }
391     }
392     }
393    
394     return client_p;
395     }
396    
397     struct Client *
398 michael 1169 hash_find_server(const char *name)
399 adx 30 {
400     unsigned int hashv = strhash(name);
401     struct Client *client_p = NULL;
402    
403     if (IsDigit(*name) && strlen(name) == IRC_MAXSID)
404     client_p = hash_find_id(name);
405    
406     if ((client_p == NULL) && (client_p = clientTable[hashv]) != NULL)
407     {
408     if ((!IsServer(client_p) && !IsMe(client_p)) ||
409     irccmp(name, client_p->name))
410     {
411     struct Client *prev;
412    
413     while (prev = client_p, (client_p = client_p->hnext) != NULL)
414     {
415     if ((IsServer(client_p) || IsMe(client_p)) &&
416     !irccmp(name, client_p->name))
417     {
418     prev->hnext = client_p->hnext;
419     client_p->hnext = clientTable[hashv];
420     clientTable[hashv] = client_p;
421     break;
422     }
423     }
424     }
425     }
426    
427 michael 1118 return client_p;
428 adx 30 }
429    
430     /* hash_find_channel()
431     *
432     * inputs - pointer to name
433     * output - NONE
434     * side effects - New semantics: finds a channel whose name is 'name',
435     * if can't find one returns NULL, if can find it moves
436     * it to the top of the list and returns it.
437     */
438     struct Channel *
439     hash_find_channel(const char *name)
440     {
441     unsigned int hashv = strhash(name);
442     struct Channel *chptr = NULL;
443    
444     if ((chptr = channelTable[hashv]) != NULL)
445     {
446     if (irccmp(name, chptr->chname))
447     {
448     struct Channel *prev;
449    
450     while (prev = chptr, (chptr = chptr->hnextch) != NULL)
451     {
452     if (!irccmp(name, chptr->chname))
453     {
454     prev->hnextch = chptr->hnextch;
455     chptr->hnextch = channelTable[hashv];
456     channelTable[hashv] = chptr;
457     break;
458     }
459     }
460     }
461     }
462    
463     return chptr;
464     }
465    
466     /* hash_get_bucket(int type, unsigned int hashv)
467     *
468     * inputs - hash value (must be between 0 and HASHSIZE - 1)
469     * output - NONE
470     * returns - pointer to first channel in channelTable[hashv]
471     * if that exists;
472     * NULL if there is no channel in that place;
473     * NULL if hashv is an invalid number.
474     * side effects - NONE
475     */
476     void *
477     hash_get_bucket(int type, unsigned int hashv)
478     {
479     assert(hashv < HASHSIZE);
480     if (hashv >= HASHSIZE)
481     return NULL;
482    
483     switch (type)
484     {
485     case HASH_TYPE_ID:
486     return idTable[hashv];
487     break;
488     case HASH_TYPE_CHANNEL:
489     return channelTable[hashv];
490     break;
491     case HASH_TYPE_CLIENT:
492     return clientTable[hashv];
493     break;
494     case HASH_TYPE_USERHOST:
495     return userhostTable[hashv];
496     break;
497     case HASH_TYPE_RESERVED:
498     return resvchannelTable[hashv];
499     break;
500     default:
501     assert(0);
502     }
503    
504     return NULL;
505     }
506    
507     /* hash_find_resv()
508     *
509     * inputs - pointer to name
510     * output - NONE
511     * side effects - New semantics: finds a reserved channel whose name is 'name',
512     * if can't find one returns NULL, if can find it moves
513     * it to the top of the list and returns it.
514     */
515     struct ResvChannel *
516     hash_find_resv(const char *name)
517     {
518     unsigned int hashv = strhash(name);
519     struct ResvChannel *chptr;
520    
521     if ((chptr = resvchannelTable[hashv]) != NULL)
522     {
523     if (irccmp(name, chptr->name))
524     {
525     struct ResvChannel *prev;
526    
527     while (prev = chptr, (chptr = chptr->hnext) != NULL)
528     {
529     if (!irccmp(name, chptr->name))
530     {
531     prev->hnext = chptr->hnext;
532     chptr->hnext = resvchannelTable[hashv];
533     resvchannelTable[hashv] = chptr;
534     break;
535     }
536     }
537     }
538     }
539    
540     return chptr;
541     }
542    
543     struct UserHost *
544     hash_find_userhost(const char *host)
545     {
546     unsigned int hashv = strhash(host);
547     struct UserHost *userhost;
548    
549     if ((userhost = userhostTable[hashv]))
550     {
551     if (irccmp(host, userhost->host))
552     {
553     struct UserHost *prev;
554    
555     while (prev = userhost, (userhost = userhost->next) != NULL)
556     {
557     if (!irccmp(host, userhost->host))
558     {
559     prev->next = userhost->next;
560     userhost->next = userhostTable[hashv];
561     userhostTable[hashv] = userhost;
562     break;
563     }
564     }
565     }
566     }
567    
568     return userhost;
569     }
570    
571     /* count_user_host()
572     *
573     * inputs - user name
574     * - hostname
575     * - int flag 1 if global, 0 if local
576     * - pointer to where global count should go
577     * - pointer to where local count should go
578     * - pointer to where identd count should go (local clients only)
579     * output - none
580     * side effects -
581     */
582     void
583     count_user_host(const char *user, const char *host, int *global_p,
584     int *local_p, int *icount_p)
585     {
586     dlink_node *ptr;
587     struct UserHost *found_userhost;
588     struct NameHost *nameh;
589    
590     if ((found_userhost = hash_find_userhost(host)) == NULL)
591     return;
592    
593     DLINK_FOREACH(ptr, found_userhost->list.head)
594     {
595     nameh = ptr->data;
596    
597     if (!irccmp(user, nameh->name))
598     {
599     if (global_p != NULL)
600     *global_p = nameh->gcount;
601     if (local_p != NULL)
602     *local_p = nameh->lcount;
603     if (icount_p != NULL)
604     *icount_p = nameh->icount;
605     return;
606     }
607     }
608     }
609    
610     /* add_user_host()
611     *
612     * inputs - user name
613     * - hostname
614     * - int flag 1 if global, 0 if local
615     * output - none
616     * side effects - add given user@host to hash tables
617     */
618     void
619     add_user_host(const char *user, const char *host, int global)
620     {
621     dlink_node *ptr;
622     struct UserHost *found_userhost;
623     struct NameHost *nameh;
624     int hasident = 1;
625    
626     if (*user == '~')
627     {
628     hasident = 0;
629     ++user;
630     }
631    
632     if ((found_userhost = find_or_add_userhost(host)) == NULL)
633     return;
634    
635     DLINK_FOREACH(ptr, found_userhost->list.head)
636     {
637     nameh = ptr->data;
638    
639     if (!irccmp(user, nameh->name))
640     {
641     nameh->gcount++;
642     if (!global)
643     {
644     if (hasident)
645     nameh->icount++;
646     nameh->lcount++;
647     }
648     return;
649     }
650     }
651    
652     nameh = BlockHeapAlloc(namehost_heap);
653     strlcpy(nameh->name, user, sizeof(nameh->name));
654    
655     nameh->gcount = 1;
656     if (!global)
657     {
658     if (hasident)
659     nameh->icount = 1;
660     nameh->lcount = 1;
661     }
662    
663     dlinkAdd(nameh, &nameh->node, &found_userhost->list);
664     }
665    
666     /* delete_user_host()
667     *
668     * inputs - user name
669     * - hostname
670     * - int flag 1 if global, 0 if local
671     * output - none
672     * side effects - delete given user@host to hash tables
673     */
674     void
675     delete_user_host(const char *user, const char *host, int global)
676     {
677     dlink_node *ptr = NULL, *next_ptr = NULL;
678     struct UserHost *found_userhost;
679     struct NameHost *nameh;
680     int hasident = 1;
681    
682     if (*user == '~')
683     {
684     hasident = 0;
685     ++user;
686     }
687    
688     if ((found_userhost = hash_find_userhost(host)) == NULL)
689     return;
690    
691     DLINK_FOREACH_SAFE(ptr, next_ptr, found_userhost->list.head)
692     {
693     nameh = ptr->data;
694    
695     if (!irccmp(user, nameh->name))
696     {
697     if (nameh->gcount > 0)
698     nameh->gcount--;
699     if (!global)
700     {
701     if (nameh->lcount > 0)
702     nameh->lcount--;
703     if (hasident && nameh->icount > 0)
704     nameh->icount--;
705     }
706    
707     if (nameh->gcount == 0 && nameh->lcount == 0)
708     {
709     dlinkDelete(&nameh->node, &found_userhost->list);
710     BlockHeapFree(namehost_heap, nameh);
711     }
712    
713     if (dlink_list_length(&found_userhost->list) == 0)
714     {
715     hash_del_userhost(found_userhost);
716     BlockHeapFree(userhost_heap, found_userhost);
717     }
718    
719     return;
720     }
721     }
722     }
723    
724     /* find_or_add_userhost()
725     *
726     * inputs - host name
727     * output - none
728     * side effects - find UserHost * for given host name
729     */
730     static struct UserHost *
731     find_or_add_userhost(const char *host)
732     {
733     struct UserHost *userhost;
734    
735     if ((userhost = hash_find_userhost(host)) != NULL)
736     return userhost;
737    
738     userhost = BlockHeapAlloc(userhost_heap);
739     strlcpy(userhost->host, host, sizeof(userhost->host));
740     hash_add_userhost(userhost);
741    
742     return userhost;
743     }
744    
745     /*
746     * Safe list code.
747     *
748     * The idea is really quite simple. As the link lists pointed to in
749     * each "bucket" of the channel hash table are traversed atomically
750     * there is no locking needed. Overall, yes, inconsistent reported
751     * state can still happen, but normally this isn't a big deal.
752     * I don't like sticking the code into hash.c but oh well. Moreover,
753     * if a hash isn't used in future, oops.
754     *
755     * - Dianora
756     */
757    
758     /* exceeding_sendq()
759     *
760     * inputs - pointer to client to check
761     * output - 1 if client is in danger of blowing its sendq
762     * 0 if it is not.
763     * side effects -
764     *
765     * Sendq limit is fairly conservative at 1/2 (In original anyway)
766     */
767     static int
768     exceeding_sendq(struct Client *to)
769     {
770     if (dbuf_length(&to->localClient->buf_sendq) > (get_sendq(to) / 2))
771     return 1;
772     else
773     return 0;
774     }
775    
776     void
777     free_list_task(struct ListTask *lt, struct Client *source_p)
778     {
779     dlink_node *dl, *dln;
780    
781     if ((dl = dlinkFindDelete(&listing_client_list, source_p)) != NULL)
782     free_dlink_node(dl);
783    
784     DLINK_FOREACH_SAFE(dl, dln, lt->show_mask.head)
785     {
786     MyFree(dl->data);
787     free_dlink_node(dl);
788     }
789    
790     DLINK_FOREACH_SAFE(dl, dln, lt->hide_mask.head)
791     {
792     MyFree(dl->data);
793     free_dlink_node(dl);
794     }
795    
796     MyFree(lt);
797    
798     if (MyConnect(source_p))
799     source_p->localClient->list_task = NULL;
800     }
801    
802     /* list_allow_channel()
803     *
804     * inputs - channel name
805     * - pointer to a list task
806     * output - 1 if the channel is to be displayed
807     * 0 otherwise
808     * side effects -
809     */
810     static int
811     list_allow_channel(const char *chname, struct ListTask *lt)
812     {
813     dlink_node *dl = NULL;
814    
815     DLINK_FOREACH(dl, lt->show_mask.head)
816     if (!match_chan(dl->data, chname))
817     return 0;
818    
819     DLINK_FOREACH(dl, lt->hide_mask.head)
820     if (match_chan(dl->data, chname))
821     return 0;
822    
823     return 1;
824     }
825    
826     /* list_one_channel()
827     *
828     * inputs - client pointer to return result to
829     * - pointer to channel to list
830     * - pointer to ListTask structure
831     * output - none
832     * side effects -
833     */
834     static void
835     list_one_channel(struct Client *source_p, struct Channel *chptr,
836 michael 896 struct ListTask *list_task)
837 adx 30 {
838 michael 896 if (SecretChannel(chptr) && !IsMember(source_p, chptr))
839 adx 30 return;
840 michael 1013 if (dlink_list_length(&chptr->members) < list_task->users_min ||
841     dlink_list_length(&chptr->members) > list_task->users_max ||
842 adx 30 (chptr->channelts != 0 &&
843     ((unsigned int)chptr->channelts < list_task->created_min ||
844     (unsigned int)chptr->channelts > list_task->created_max)) ||
845     (unsigned int)chptr->topic_time < list_task->topicts_min ||
846     (chptr->topic_time ? (unsigned int)chptr->topic_time : UINT_MAX) >
847     list_task->topicts_max)
848     return;
849    
850     if (!list_allow_channel(chptr->chname, list_task))
851     return;
852     sendto_one(source_p, form_str(RPL_LIST), me.name, source_p->name,
853     chptr->chname, dlink_list_length(&chptr->members),
854 michael 1203 chptr->topic);
855 adx 30 }
856    
857     /* safe_list_channels()
858     *
859     * inputs - pointer to client requesting list
860     * output - 0/1
861     * side effects - safely list all channels to source_p
862     *
863     * Walk the channel buckets, ensure all pointers in a bucket are
864     * traversed before blocking on a sendq. This means, no locking is needed.
865     *
866     * N.B. This code is "remote" safe, but is not currently used for
867     * remote clients.
868     *
869     * - Dianora
870     */
871     void
872     safe_list_channels(struct Client *source_p, struct ListTask *list_task,
873 michael 896 int only_unmasked_channels)
874 adx 30 {
875     struct Channel *chptr = NULL;
876    
877     if (!only_unmasked_channels)
878     {
879 michael 1013 unsigned int i;
880 adx 30
881 michael 896 for (i = list_task->hash_index; i < HASHSIZE; ++i)
882 adx 30 {
883     if (exceeding_sendq(source_p->from))
884     {
885     list_task->hash_index = i;
886 michael 880 return; /* still more to do */
887 adx 30 }
888    
889     for (chptr = channelTable[i]; chptr; chptr = chptr->hnextch)
890 michael 896 list_one_channel(source_p, chptr, list_task);
891 adx 30 }
892     }
893     else
894     {
895     dlink_node *dl;
896    
897     DLINK_FOREACH(dl, list_task->show_mask.head)
898     if ((chptr = hash_find_channel(dl->data)) != NULL)
899 michael 896 list_one_channel(source_p, chptr, list_task);
900 adx 30 }
901    
902     free_list_task(list_task, source_p);
903     sendto_one(source_p, form_str(RPL_LISTEND),
904     me.name, source_p->name);
905     }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision