ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hash.c
(Generate patch)

Comparing:
ircd-hybrid-7.3/src/hash.c (file contents), Revision 1118 by michael, Thu Jan 6 13:39:10 2011 UTC vs.
ircd-hybrid/trunk/src/hash.c (file contents), Revision 4565 by michael, Sun Aug 24 10:27:40 2014 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  hash.c: Maintains hashtables.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2002 by the past and present ircd coders, and others.
4 > *  Copyright (c) 1997-2014 ircd-hybrid development team
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 16 | Line 15
15   *
16   *  You should have received a copy of the GNU General Public License
17   *  along with this program; if not, write to the Free Software
18 < *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18 > *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19   *  USA
20 < *
21 < *  $Id$
20 > */
21 >
22 > /*! \file hash.c
23 > * \brief Hash table management.
24 > * \version $Id$
25   */
26  
27   #include "stdinc.h"
28   #include "list.h"
29 < #include "balloc.h"
28 < #include "s_conf.h"
29 > #include "conf.h"
30   #include "channel.h"
31   #include "channel_mode.h"
32   #include "client.h"
32 #include "common.h"
33 #include "handlers.h"
33   #include "modules.h"
34   #include "hash.h"
35   #include "resv.h"
# Line 41 | Line 40
40   #include "numeric.h"
41   #include "send.h"
42   #include "memory.h"
43 + #include "mempool.h"
44   #include "dbuf.h"
45 < #include "s_user.h"
45 > #include "user.h"
46  
47  
48 < static BlockHeap *userhost_heap = NULL;
49 < static BlockHeap *namehost_heap = NULL;
50 < static struct UserHost *find_or_add_userhost(const char *);
48 > static mp_pool_t *userhost_pool = NULL;
49 > static mp_pool_t *namehost_pool = NULL;
50  
51   static unsigned int hashf_xor_key = 0;
52  
53   /* The actual hash tables, They MUST be of the same HASHSIZE, variable
54   * size tables could be supported but the rehash routine should also
55 < * rebuild the transformation maps, I kept the tables of equal size
55 > * rebuild the transformation maps, I kept the tables of equal size
56   * so that I can use one hash function.
57   */
58   static struct Client *idTable[HASHSIZE];
59   static struct Client *clientTable[HASHSIZE];
60   static struct Channel *channelTable[HASHSIZE];
61   static struct UserHost *userhostTable[HASHSIZE];
63 static struct ResvChannel *resvchannelTable[HASHSIZE];
62  
63  
64   /* init_hash()
# Line 71 | Line 69 | static struct ResvChannel *resvchannelTa
69   *                functions and clear the tables
70   */
71   void
72 < init_hash(void)
72 > hash_init(void)
73   {
74 <  unsigned int i;
75 <
78 <  /* Default the userhost/namehost sizes to CLIENT_HEAP_SIZE for now,
79 <   * should be a good close approximation anyway
80 <   * - Dianora
81 <   */
82 <  userhost_heap = BlockHeapCreate("userhost", sizeof(struct UserHost), CLIENT_HEAP_SIZE);
83 <  namehost_heap = BlockHeapCreate("namehost", sizeof(struct NameHost), CLIENT_HEAP_SIZE);
74 >  userhost_pool = mp_pool_new(sizeof(struct UserHost), MP_CHUNK_SIZE_USERHOST);
75 >  namehost_pool = mp_pool_new(sizeof(struct NameHost), MP_CHUNK_SIZE_NAMEHOST);
76  
77    hashf_xor_key = genrand_int32() % 256;  /* better than nothing --adx */
86
87  /* Clear the hash tables first */
88  for (i = 0; i < HASHSIZE; ++i)
89  {
90    idTable[i]          = NULL;
91    clientTable[i]      = NULL;
92    channelTable[i]     = NULL;
93    userhostTable[i]    = NULL;
94    resvchannelTable[i] = NULL;
95  }
78   }
79  
80   /*
# Line 108 | Line 90 | strhash(const char *name)
90    const unsigned char *p = (const unsigned char *)name;
91    unsigned int hval = FNV1_32_INIT;
92  
93 <  if (*p == '\0')
93 >  if (EmptyString(p))
94      return 0;
95    for (; *p != '\0'; ++p)
96    {
# Line 168 | Line 150 | hash_add_channel(struct Channel *chptr)
150   }
151  
152   void
171 hash_add_resv(struct ResvChannel *chptr)
172 {
173  unsigned int hashv = strhash(chptr->name);
174
175  chptr->hnext = resvchannelTable[hashv];
176  resvchannelTable[hashv] = chptr;
177 }
178
179 void
153   hash_add_userhost(struct UserHost *userhost)
154   {
155    unsigned int hashv = strhash(userhost->host);
# Line 206 | Line 179 | hash_del_id(struct Client *client_p)
179    unsigned int hashv = strhash(client_p->id);
180    struct Client *tmp = idTable[hashv];
181  
182 <  if (tmp != NULL)
182 >  if (tmp)
183    {
184      if (tmp == client_p)
185      {
# Line 216 | Line 189 | hash_del_id(struct Client *client_p)
189      else
190      {
191        while (tmp->idhnext != client_p)
219      {
192          if ((tmp = tmp->idhnext) == NULL)
193            return;
222      }
194  
195        tmp->idhnext = tmp->idhnext->idhnext;
196        client_p->idhnext = client_p;
# Line 239 | Line 210 | hash_del_client(struct Client *client_p)
210    unsigned int hashv = strhash(client_p->name);
211    struct Client *tmp = clientTable[hashv];
212  
213 <  if (tmp != NULL)
213 >  if (tmp)
214    {
215      if (tmp == client_p)
216      {
# Line 249 | Line 220 | hash_del_client(struct Client *client_p)
220      else
221      {
222        while (tmp->hnext != client_p)
252      {
223          if ((tmp = tmp->hnext) == NULL)
224            return;
255      }
225  
226        tmp->hnext = tmp->hnext->hnext;
227        client_p->hnext = client_p;
# Line 272 | Line 241 | hash_del_userhost(struct UserHost *userh
241    unsigned int hashv = strhash(userhost->host);
242    struct UserHost *tmp = userhostTable[hashv];
243  
244 <  if (tmp != NULL)
244 >  if (tmp)
245    {
246      if (tmp == userhost)
247      {
# Line 282 | Line 251 | hash_del_userhost(struct UserHost *userh
251      else
252      {
253        while (tmp->next != userhost)
285      {
254          if ((tmp = tmp->next) == NULL)
255            return;
288      }
256  
257        tmp->next = tmp->next->next;
258        userhost->next = userhost;
# Line 306 | Line 273 | hash_del_channel(struct Channel *chptr)
273    unsigned int hashv = strhash(chptr->chname);
274    struct Channel *tmp = channelTable[hashv];
275  
276 <  if (tmp != NULL)
276 >  if (tmp)
277    {
278      if (tmp == chptr)
279      {
# Line 316 | Line 283 | hash_del_channel(struct Channel *chptr)
283      else
284      {
285        while (tmp->hnextch != chptr)
319      {
286          if ((tmp = tmp->hnextch) == NULL)
287            return;
322      }
288  
289        tmp->hnextch = tmp->hnextch->hnextch;
290        chptr->hnextch = chptr;
# Line 327 | Line 292 | hash_del_channel(struct Channel *chptr)
292    }
293   }
294  
295 < void
331 < hash_del_resv(struct ResvChannel *chptr)
332 < {
333 <  unsigned int hashv = strhash(chptr->name);
334 <  struct ResvChannel *tmp = resvchannelTable[hashv];
335 <
336 <  if (tmp != NULL)
337 <  {
338 <    if (tmp == chptr)
339 <    {
340 <      resvchannelTable[hashv] = chptr->hnext;
341 <      chptr->hnext = chptr;
342 <    }
343 <    else
344 <    {
345 <      while (tmp->hnext != chptr)
346 <      {
347 <        if ((tmp = tmp->hnext) == NULL)
348 <          return;
349 <      }
350 <
351 <      tmp->hnext = tmp->hnext->hnext;
352 <      chptr->hnext = chptr;
353 <    }
354 <  }
355 < }
356 <
357 < /* find_client()
295 > /* hash_find_client()
296   *
297   * inputs       - pointer to name
298   * output       - NONE
# Line 363 | Line 301 | hash_del_resv(struct ResvChannel *chptr)
301   *                it to the top of the list and returns it.
302   */
303   struct Client *
304 < find_client(const char *name)
304 > hash_find_client(const char *name)
305   {
306    unsigned int hashv = strhash(name);
307    struct Client *client_p;
308  
309 <  if ((client_p = clientTable[hashv]) != NULL)
309 >  if ((client_p = clientTable[hashv]))
310    {
311      if (irccmp(name, client_p->name))
312      {
313        struct Client *prev;
314  
315 <      while (prev = client_p, (client_p = client_p->hnext) != NULL)
315 >      while (prev = client_p, (client_p = client_p->hnext))
316        {
317          if (!irccmp(name, client_p->name))
318          {
# Line 396 | Line 334 | hash_find_id(const char *name)
334    unsigned int hashv = strhash(name);
335    struct Client *client_p;
336  
337 <  if ((client_p = idTable[hashv]) != NULL)
337 >  if ((client_p = idTable[hashv]))
338    {
339      if (strcmp(name, client_p->id))
340      {
341        struct Client *prev;
342  
343 <      while (prev = client_p, (client_p = client_p->idhnext) != NULL)
343 >      while (prev = client_p, (client_p = client_p->idhnext))
344        {
345          if (!strcmp(name, client_p->id))
346          {
# Line 419 | Line 357 | hash_find_id(const char *name)
357   }
358  
359   struct Client *
360 < find_server(const char *name)
360 > hash_find_server(const char *name)
361   {
362    unsigned int hashv = strhash(name);
363    struct Client *client_p = NULL;
364  
365    if (IsDigit(*name) && strlen(name) == IRC_MAXSID)
366 <    client_p = hash_find_id(name);
366 >    return hash_find_id(name);
367  
368 <  if ((client_p == NULL) && (client_p = clientTable[hashv]) != NULL)
368 >  if ((client_p = clientTable[hashv]))
369    {
370      if ((!IsServer(client_p) && !IsMe(client_p)) ||
371          irccmp(name, client_p->name))
372      {
373        struct Client *prev;
374  
375 <      while (prev = client_p, (client_p = client_p->hnext) != NULL)
375 >      while (prev = client_p, (client_p = client_p->hnext))
376        {
377          if ((IsServer(client_p) || IsMe(client_p)) &&
378              !irccmp(name, client_p->name))
# Line 455 | Line 393 | find_server(const char *name)
393   *
394   * inputs       - pointer to name
395   * output       - NONE
396 < * side effects - New semantics: finds a channel whose name is 'name',
396 > * side effects - New semantics: finds a channel whose name is 'name',
397   *                if can't find one returns NULL, if can find it moves
398   *                it to the top of the list and returns it.
399   */
# Line 465 | Line 403 | hash_find_channel(const char *name)
403    unsigned int hashv = strhash(name);
404    struct Channel *chptr = NULL;
405  
406 <  if ((chptr = channelTable[hashv]) != NULL)
406 >  if ((chptr = channelTable[hashv]))
407    {
408      if (irccmp(name, chptr->chname))
409      {
410        struct Channel *prev;
411  
412 <      while (prev = chptr, (chptr = chptr->hnextch) != NULL)
412 >      while (prev = chptr, (chptr = chptr->hnextch))
413        {
414          if (!irccmp(name, chptr->chname))
415          {
# Line 518 | Line 456 | hash_get_bucket(int type, unsigned int h
456      case HASH_TYPE_USERHOST:
457        return userhostTable[hashv];
458        break;
521    case HASH_TYPE_RESERVED:
522      return resvchannelTable[hashv];
523      break;
459      default:
460        assert(0);
461    }
# Line 528 | Line 463 | hash_get_bucket(int type, unsigned int h
463    return NULL;
464   }
465  
531 /* hash_find_resv()
532 *
533 * inputs       - pointer to name
534 * output       - NONE
535 * side effects - New semantics: finds a reserved channel whose name is 'name',
536 *                if can't find one returns NULL, if can find it moves
537 *                it to the top of the list and returns it.
538 */
539 struct ResvChannel *
540 hash_find_resv(const char *name)
541 {
542  unsigned int hashv = strhash(name);
543  struct ResvChannel *chptr;
544
545  if ((chptr = resvchannelTable[hashv]) != NULL)
546  {
547    if (irccmp(name, chptr->name))
548    {
549      struct ResvChannel *prev;
550
551      while (prev = chptr, (chptr = chptr->hnext) != NULL)
552      {
553        if (!irccmp(name, chptr->name))
554        {
555          prev->hnext = chptr->hnext;
556          chptr->hnext = resvchannelTable[hashv];
557          resvchannelTable[hashv] = chptr;
558          break;
559        }
560      }
561    }
562  }
563
564  return chptr;
565 }
566
466   struct UserHost *
467   hash_find_userhost(const char *host)
468   {
# Line 576 | Line 475 | hash_find_userhost(const char *host)
475      {
476        struct UserHost *prev;
477  
478 <      while (prev = userhost, (userhost = userhost->next) != NULL)
478 >      while (prev = userhost, (userhost = userhost->next))
479        {
480          if (!irccmp(host, userhost->host))
481          {
# Line 604 | Line 503 | hash_find_userhost(const char *host)
503   * side effects -
504   */
505   void
506 < count_user_host(const char *user, const char *host, int *global_p,
507 <                int *local_p, int *icount_p)
506 > count_user_host(const char *user, const char *host, unsigned int *global_p,
507 >                unsigned int *local_p, unsigned int *icount_p)
508   {
509    dlink_node *ptr;
510    struct UserHost *found_userhost;
# Line 620 | Line 519 | count_user_host(const char *user, const
519  
520      if (!irccmp(user, nameh->name))
521      {
522 <      if (global_p != NULL)
522 >      if (global_p)
523          *global_p = nameh->gcount;
524 <      if (local_p != NULL)
524 >      if (local_p)
525          *local_p  = nameh->lcount;
526 <      if (icount_p != NULL)
526 >      if (icount_p)
527          *icount_p = nameh->icount;
528        return;
529      }
530    }
531   }
532  
533 + /* find_or_add_userhost()
534 + *
535 + * inputs       - host name
536 + * output       - none
537 + * side effects - find UserHost * for given host name
538 + */
539 + static struct UserHost *
540 + find_or_add_userhost(const char *host)
541 + {
542 +  struct UserHost *userhost = NULL;
543 +
544 +  if ((userhost = hash_find_userhost(host)))
545 +    return userhost;
546 +
547 +  userhost = mp_pool_get(userhost_pool);
548 +
549 +  strlcpy(userhost->host, host, sizeof(userhost->host));
550 +  hash_add_userhost(userhost);
551 +
552 +  return userhost;
553 + }
554 +
555   /* add_user_host()
556   *
557   * inputs       - user name
# Line 645 | Line 566 | add_user_host(const char *user, const ch
566    dlink_node *ptr;
567    struct UserHost *found_userhost;
568    struct NameHost *nameh;
569 <  int hasident = 1;
569 >  unsigned int hasident = 1;
570  
571    if (*user == '~')
572    {
# Line 663 | Line 584 | add_user_host(const char *user, const ch
584      if (!irccmp(user, nameh->name))
585      {
586        nameh->gcount++;
587 +
588        if (!global)
589        {
590 <        if (hasident)
591 <          nameh->icount++;
592 <        nameh->lcount++;
590 >        if (hasident)
591 >          nameh->icount++;
592 >        nameh->lcount++;
593        }
594 +
595        return;
596      }
597    }
598  
599 <  nameh = BlockHeapAlloc(namehost_heap);
599 >  nameh = mp_pool_get(namehost_pool);
600 >
601    strlcpy(nameh->name, user, sizeof(nameh->name));
602  
603    nameh->gcount = 1;
604 +
605    if (!global)
606    {
607      if (hasident)
# Line 698 | Line 623 | add_user_host(const char *user, const ch
623   void
624   delete_user_host(const char *user, const char *host, int global)
625   {
626 <  dlink_node *ptr = NULL, *next_ptr = NULL;
627 <  struct UserHost *found_userhost;
628 <  struct NameHost *nameh;
704 <  int hasident = 1;
626 >  dlink_node *ptr = NULL;
627 >  struct UserHost *found_userhost = NULL;
628 >  unsigned int hasident = 1;
629  
630    if (*user == '~')
631    {
# Line 712 | Line 636 | delete_user_host(const char *user, const
636    if ((found_userhost = hash_find_userhost(host)) == NULL)
637      return;
638  
639 <  DLINK_FOREACH_SAFE(ptr, next_ptr, found_userhost->list.head)
639 >  DLINK_FOREACH(ptr, found_userhost->list.head)
640    {
641 <    nameh = ptr->data;
641 >    struct NameHost *nameh = ptr->data;
642  
643      if (!irccmp(user, nameh->name))
644      {
# Line 722 | Line 646 | delete_user_host(const char *user, const
646          nameh->gcount--;
647        if (!global)
648        {
649 <        if (nameh->lcount > 0)
650 <          nameh->lcount--;
651 <        if (hasident && nameh->icount > 0)
652 <          nameh->icount--;
649 >        if (nameh->lcount > 0)
650 >          nameh->lcount--;
651 >        if (hasident && nameh->icount > 0)
652 >          nameh->icount--;
653        }
654  
655        if (nameh->gcount == 0 && nameh->lcount == 0)
656        {
657 <        dlinkDelete(&nameh->node, &found_userhost->list);
658 <        BlockHeapFree(namehost_heap, nameh);
657 >        dlinkDelete(&nameh->node, &found_userhost->list);
658 >        mp_pool_release(nameh);
659        }
660  
661        if (dlink_list_length(&found_userhost->list) == 0)
662        {
663 <        hash_del_userhost(found_userhost);
664 <        BlockHeapFree(userhost_heap, found_userhost);
663 >        hash_del_userhost(found_userhost);
664 >        mp_pool_release(found_userhost);
665        }
666  
667        return;
# Line 745 | Line 669 | delete_user_host(const char *user, const
669    }
670   }
671  
748 /* find_or_add_userhost()
749 *
750 * inputs       - host name
751 * output       - none
752 * side effects - find UserHost * for given host name
753 */
754 static struct UserHost *
755 find_or_add_userhost(const char *host)
756 {
757  struct UserHost *userhost;
758
759  if ((userhost = hash_find_userhost(host)) != NULL)
760    return userhost;
761
762  userhost = BlockHeapAlloc(userhost_heap);
763  strlcpy(userhost->host, host, sizeof(userhost->host));
764  hash_add_userhost(userhost);
765
766  return userhost;
767 }
768
672   /*
673   * Safe list code.
674   *
# Line 789 | Line 692 | find_or_add_userhost(const char *host)
692   * Sendq limit is fairly conservative at 1/2 (In original anyway)
693   */
694   static int
695 < exceeding_sendq(struct Client *to)
695 > exceeding_sendq(const struct Client *to)
696   {
697 <  if (dbuf_length(&to->localClient->buf_sendq) > (get_sendq(to) / 2))
697 >  if (dbuf_length(&to->localClient->buf_sendq) > (get_sendq(&to->localClient->confs) / 2))
698      return 1;
699    else
700      return 0;
701   }
702  
703   void
704 < free_list_task(struct ListTask *lt, struct Client *source_p)
704 > free_list_task(struct Client *source_p)
705   {
706 <  dlink_node *dl, *dln;
706 >  struct ListTask *lt = source_p->localClient->list_task;
707 >  dlink_node *ptr = NULL, *ptr_next = NULL;
708  
709 <  if ((dl = dlinkFindDelete(&listing_client_list, source_p)) != NULL)
710 <    free_dlink_node(dl);
709 >  if ((ptr = dlinkFindDelete(&listing_client_list, source_p)))
710 >    free_dlink_node(ptr);
711  
712 <  DLINK_FOREACH_SAFE(dl, dln, lt->show_mask.head)
712 >  DLINK_FOREACH_SAFE(ptr, ptr_next, lt->show_mask.head)
713    {
714 <    MyFree(dl->data);
715 <    free_dlink_node(dl);
714 >    MyFree(ptr->data);
715 >    free_dlink_node(ptr);
716    }
717  
718 <  DLINK_FOREACH_SAFE(dl, dln, lt->hide_mask.head)
718 >  DLINK_FOREACH_SAFE(ptr, ptr_next, lt->hide_mask.head)
719    {
720 <    MyFree(dl->data);
721 <    free_dlink_node(dl);
720 >    MyFree(ptr->data);
721 >    free_dlink_node(ptr);
722    }
723  
724    MyFree(lt);
# Line 832 | Line 736 | free_list_task(struct ListTask *lt, stru
736   * side effects -
737   */
738   static int
739 < list_allow_channel(const char *chname, struct ListTask *lt)
739 > list_allow_channel(const char *chname, const struct ListTask *lt)
740   {
741 <  dlink_node *dl = NULL;
741 >  const dlink_node *ptr = NULL;
742  
743 <  DLINK_FOREACH(dl, lt->show_mask.head)
744 <    if (!match_chan(dl->data, chname))
743 >  DLINK_FOREACH(ptr, lt->show_mask.head)
744 >    if (match(ptr->data, chname) != 0)
745        return 0;
746  
747 <  DLINK_FOREACH(dl, lt->hide_mask.head)
748 <    if (match_chan(dl->data, chname))
747 >  DLINK_FOREACH(ptr, lt->hide_mask.head)
748 >    if (match(ptr->data, chname) == 0)
749        return 0;
750  
751    return 1;
# Line 856 | Line 760 | list_allow_channel(const char *chname, s
760   * side effects -
761   */
762   static void
763 < list_one_channel(struct Client *source_p, struct Channel *chptr,
860 <                 struct ListTask *list_task)
763 > list_one_channel(struct Client *source_p, struct Channel *chptr)
764   {
765 <  if (SecretChannel(chptr) && !IsMember(source_p, chptr))
765 >  const struct ListTask *lt = source_p->localClient->list_task;
766 >  char listbuf[MODEBUFLEN] = "";
767 >  char modebuf[MODEBUFLEN] = "";
768 >  char parabuf[MODEBUFLEN] = "";
769 >
770 >  if (SecretChannel(chptr) &&
771 >      !(HasUMode(source_p, UMODE_ADMIN) || IsMember(source_p, chptr)))
772      return;
773 <  if (dlink_list_length(&chptr->members) < list_task->users_min ||
774 <      dlink_list_length(&chptr->members) > list_task->users_max ||
773 >  if (dlink_list_length(&chptr->members) < lt->users_min ||
774 >      dlink_list_length(&chptr->members) > lt->users_max ||
775        (chptr->channelts != 0 &&
776 <       ((unsigned int)chptr->channelts < list_task->created_min ||
777 <        (unsigned int)chptr->channelts > list_task->created_max)) ||
778 <      (unsigned int)chptr->topic_time < list_task->topicts_min ||
776 >       ((unsigned int)chptr->channelts < lt->created_min ||
777 >        (unsigned int)chptr->channelts > lt->created_max)) ||
778 >      (unsigned int)chptr->topic_time < lt->topicts_min ||
779        (chptr->topic_time ? (unsigned int)chptr->topic_time : UINT_MAX) >
780 <      list_task->topicts_max)
780 >      lt->topicts_max)
781 >    return;
782 >
783 >  if (lt->topic[0] && match(lt->topic, chptr->topic))
784      return;
785  
786 <  if (!list_allow_channel(chptr->chname, list_task))
786 >  if (!list_allow_channel(chptr->chname, lt))
787      return;
788 <  sendto_one(source_p, form_str(RPL_LIST), me.name, source_p->name,
789 <             chptr->chname, dlink_list_length(&chptr->members),
790 <             chptr->topic == NULL ? "" : chptr->topic);
788 >
789 >  channel_modes(chptr, source_p, modebuf, parabuf);
790 >
791 >  if (chptr->topic[0])
792 >    snprintf(listbuf, sizeof(listbuf), "[%s] ", modebuf);
793 >  else
794 >    snprintf(listbuf, sizeof(listbuf), "[%s]",  modebuf);
795 >
796 >  sendto_one_numeric(source_p, &me, RPL_LIST, chptr->chname,
797 >                     dlink_list_length(&chptr->members),
798 >                     listbuf, chptr->topic);
799   }
800  
801   /* safe_list_channels()
# Line 887 | Line 807 | list_one_channel(struct Client *source_p
807   * Walk the channel buckets, ensure all pointers in a bucket are
808   * traversed before blocking on a sendq. This means, no locking is needed.
809   *
890 * N.B. This code is "remote" safe, but is not currently used for
891 * remote clients.
892 *
810   * - Dianora
811   */
812   void
813 < safe_list_channels(struct Client *source_p, struct ListTask *list_task,
897 <                   int only_unmasked_channels)
813 > safe_list_channels(struct Client *source_p, int only_unmasked_channels)
814   {
815 +  struct ListTask *lt = source_p->localClient->list_task;
816    struct Channel *chptr = NULL;
817  
818    if (!only_unmasked_channels)
819    {
820 <    unsigned int i;
904 <
905 <    for (i = list_task->hash_index; i < HASHSIZE; ++i)
820 >    for (unsigned int i = lt->hash_index; i < HASHSIZE; ++i)
821      {
822 <      if (exceeding_sendq(source_p->from))
822 >      if (exceeding_sendq(source_p))
823        {
824 <        list_task->hash_index = i;
825 <        return;    /* still more to do */
824 >        lt->hash_index = i;
825 >        return;  /* Still more to do */
826        }
827  
828        for (chptr = channelTable[i]; chptr; chptr = chptr->hnextch)
829 <        list_one_channel(source_p, chptr, list_task);
829 >        list_one_channel(source_p, chptr);
830      }
831    }
832    else
833    {
834 <    dlink_node *dl;
834 >    dlink_node *ptr = NULL;
835  
836 <    DLINK_FOREACH(dl, list_task->show_mask.head)
837 <      if ((chptr = hash_find_channel(dl->data)) != NULL)
838 <        list_one_channel(source_p, chptr, list_task);
836 >    DLINK_FOREACH(ptr, lt->show_mask.head)
837 >      if ((chptr = hash_find_channel(ptr->data)))
838 >        list_one_channel(source_p, chptr);
839    }
840  
841 <  free_list_task(list_task, source_p);
842 <  sendto_one(source_p, form_str(RPL_LISTEND),
928 <             me.name, source_p->name);
841 >  free_list_task(source_p);
842 >  sendto_one_numeric(source_p, &me, RPL_LISTEND);
843   }

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)