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/trunk/src/hash.c (file contents):
Revision 1592 by michael, Sat Oct 27 21:02:32 2012 UTC vs.
Revision 8752 by michael, Tue Jan 1 11:07:01 2019 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-2019 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"
27 #include "balloc.h"
29   #include "conf.h"
30   #include "channel.h"
31   #include "channel_mode.h"
32   #include "client.h"
32 #include "modules.h"
33   #include "hash.h"
34 < #include "resv.h"
34 > #include "id.h"
35   #include "rng_mt.h"
36 #include "userhost.h"
36   #include "irc_string.h"
37   #include "ircd.h"
38   #include "numeric.h"
39   #include "send.h"
40   #include "memory.h"
41   #include "dbuf.h"
43 #include "s_user.h"
42  
43  
44 < static BlockHeap *userhost_heap = NULL;
47 < static BlockHeap *namehost_heap = NULL;
48 <
49 < static unsigned int hashf_xor_key = 0;
44 > static unsigned int hashf_xor_key;
45  
46   /* The actual hash tables, They MUST be of the same HASHSIZE, variable
47   * size tables could be supported but the rehash routine should also
48 < * rebuild the transformation maps, I kept the tables of equal size
48 > * rebuild the transformation maps, I kept the tables of equal size
49   * so that I can use one hash function.
50   */
51   static struct Client *idTable[HASHSIZE];
52   static struct Client *clientTable[HASHSIZE];
53   static struct Channel *channelTable[HASHSIZE];
59 static struct UserHost *userhostTable[HASHSIZE];
60 static struct ResvChannel *resvchannelTable[HASHSIZE];
54  
55  
56 < /* init_hash()
56 > /* hash_init()
57   *
58   * inputs       - NONE
59   * output       - NONE
# Line 68 | Line 61 | static struct ResvChannel *resvchannelTa
61   *                functions and clear the tables
62   */
63   void
64 < init_hash(void)
64 > hash_init(void)
65   {
66 <  /* Default the userhost/namehost sizes to CLIENT_HEAP_SIZE for now,
67 <   * should be a good close approximation anyway
68 <   * - Dianora
76 <   */
77 <  userhost_heap = BlockHeapCreate("userhost", sizeof(struct UserHost), CLIENT_HEAP_SIZE);
78 <  namehost_heap = BlockHeapCreate("namehost", sizeof(struct NameHost), CLIENT_HEAP_SIZE);
79 <
80 <  hashf_xor_key = genrand_int32() % 256;  /* better than nothing --adx */
66 >  do
67 >    hashf_xor_key = genrand_int32() % 256;  /* better than nothing --adx */
68 >  while (!hashf_xor_key);
69   }
70  
71   /*
# Line 93 | Line 81 | strhash(const char *name)
81    const unsigned char *p = (const unsigned char *)name;
82    unsigned int hval = FNV1_32_INIT;
83  
84 <  if (*p == '\0')
84 >  if (EmptyString(p))
85      return 0;
86 <  for (; *p != '\0'; ++p)
86 >
87 >  for (; *p; ++p)
88    {
89 <    hval += (hval << 1) + (hval <<  4) + (hval << 7) +
90 <            (hval << 8) + (hval << 24);
89 >    hval += (hval << 1) + (hval << 4) +
90 >            (hval << 7) + (hval << 8) + (hval << 24);
91      hval ^= (ToLower(*p) ^ hashf_xor_key);
92    }
93  
# Line 127 | Line 116 | strhash(const char *name)
116   void
117   hash_add_client(struct Client *client_p)
118   {
119 <  unsigned int hashv = strhash(client_p->name);
119 >  const unsigned int hashv = strhash(client_p->name);
120  
121    client_p->hnext = clientTable[hashv];
122    clientTable[hashv] = client_p;
# Line 146 | Line 135 | hash_add_client(struct Client *client_p)
135   void
136   hash_add_channel(struct Channel *chptr)
137   {
138 <  unsigned int hashv = strhash(chptr->chname);
138 >  const unsigned int hashv = strhash(chptr->name);
139  
140    chptr->hnextch = channelTable[hashv];
141    channelTable[hashv] = chptr;
142   }
143  
144   void
156 hash_add_resv(struct ResvChannel *chptr)
157 {
158  unsigned int hashv = strhash(chptr->name);
159
160  chptr->hnext = resvchannelTable[hashv];
161  resvchannelTable[hashv] = chptr;
162 }
163
164 void
165 hash_add_userhost(struct UserHost *userhost)
166 {
167  unsigned int hashv = strhash(userhost->host);
168
169  userhost->next = userhostTable[hashv];
170  userhostTable[hashv] = userhost;
171 }
172
173 void
145   hash_add_id(struct Client *client_p)
146   {
147 <  unsigned int hashv = strhash(client_p->id);
147 >  const unsigned int hashv = strhash(client_p->id);
148  
149    client_p->idhnext = idTable[hashv];
150    idTable[hashv] = client_p;
# Line 188 | Line 159 | hash_add_id(struct Client *client_p)
159   void
160   hash_del_id(struct Client *client_p)
161   {
162 <  unsigned int hashv = strhash(client_p->id);
162 >  const unsigned int hashv = strhash(client_p->id);
163    struct Client *tmp = idTable[hashv];
164  
165 <  if (tmp != NULL)
165 >  if (tmp)
166    {
167      if (tmp == client_p)
168      {
# Line 219 | Line 190 | hash_del_id(struct Client *client_p)
190   void
191   hash_del_client(struct Client *client_p)
192   {
193 <  unsigned int hashv = strhash(client_p->name);
193 >  const unsigned int hashv = strhash(client_p->name);
194    struct Client *tmp = clientTable[hashv];
195  
196 <  if (tmp != NULL)
196 >  if (tmp)
197    {
198      if (tmp == client_p)
199      {
# Line 241 | Line 212 | hash_del_client(struct Client *client_p)
212    }
213   }
214  
244 /* hash_del_userhost()
245 *
246 * inputs       - pointer to userhost
247 * output       - NONE
248 * side effects - Removes a userhost from the hash linked list
249 */
250 void
251 hash_del_userhost(struct UserHost *userhost)
252 {
253  unsigned int hashv = strhash(userhost->host);
254  struct UserHost *tmp = userhostTable[hashv];
255
256  if (tmp != NULL)
257  {
258    if (tmp == userhost)
259    {
260      userhostTable[hashv] = userhost->next;
261      userhost->next = userhost;
262    }
263    else
264    {
265      while (tmp->next != userhost)
266        if ((tmp = tmp->next) == NULL)
267          return;
268
269      tmp->next = tmp->next->next;
270      userhost->next = userhost;
271    }
272  }
273 }
274
215   /* hash_del_channel()
216   *
217   * inputs       - pointer to client
# Line 282 | Line 222 | hash_del_userhost(struct UserHost *userh
222   void
223   hash_del_channel(struct Channel *chptr)
224   {
225 <  unsigned int hashv = strhash(chptr->chname);
225 >  const unsigned int hashv = strhash(chptr->name);
226    struct Channel *tmp = channelTable[hashv];
227  
228 <  if (tmp != NULL)
228 >  if (tmp)
229    {
230      if (tmp == chptr)
231      {
# Line 304 | Line 244 | hash_del_channel(struct Channel *chptr)
244    }
245   }
246  
307 void
308 hash_del_resv(struct ResvChannel *chptr)
309 {
310  unsigned int hashv = strhash(chptr->name);
311  struct ResvChannel *tmp = resvchannelTable[hashv];
312
313  if (tmp != NULL)
314  {
315    if (tmp == chptr)
316    {
317      resvchannelTable[hashv] = chptr->hnext;
318      chptr->hnext = chptr;
319    }
320    else
321    {
322      while (tmp->hnext != chptr)
323        if ((tmp = tmp->hnext) == NULL)
324          return;
325
326      tmp->hnext = tmp->hnext->hnext;
327      chptr->hnext = chptr;
328    }
329  }
330 }
331
247   /* hash_find_client()
248   *
249   * inputs       - pointer to name
# Line 340 | Line 255 | hash_del_resv(struct ResvChannel *chptr)
255   struct Client *
256   hash_find_client(const char *name)
257   {
258 <  unsigned int hashv = strhash(name);
258 >  const unsigned int hashv = strhash(name);
259    struct Client *client_p;
260  
261 <  if ((client_p = clientTable[hashv]) != NULL)
261 >  if ((client_p = clientTable[hashv]))
262    {
263      if (irccmp(name, client_p->name))
264      {
265        struct Client *prev;
266  
267 <      while (prev = client_p, (client_p = client_p->hnext) != NULL)
267 >      while (prev = client_p, (client_p = client_p->hnext))
268        {
269          if (!irccmp(name, client_p->name))
270          {
# Line 368 | Line 283 | hash_find_client(const char *name)
283   struct Client *
284   hash_find_id(const char *name)
285   {
286 <  unsigned int hashv = strhash(name);
286 >  const unsigned int hashv = strhash(name);
287    struct Client *client_p;
288  
289 <  if ((client_p = idTable[hashv]) != NULL)
289 >  if ((client_p = idTable[hashv]))
290    {
291      if (strcmp(name, client_p->id))
292      {
293        struct Client *prev;
294  
295 <      while (prev = client_p, (client_p = client_p->idhnext) != NULL)
295 >      while (prev = client_p, (client_p = client_p->idhnext))
296        {
297          if (!strcmp(name, client_p->id))
298          {
# Line 396 | Line 311 | hash_find_id(const char *name)
311   struct Client *
312   hash_find_server(const char *name)
313   {
314 <  unsigned int hashv = strhash(name);
314 >  const unsigned int hashv = strhash(name);
315    struct Client *client_p = NULL;
316  
317    if (IsDigit(*name) && strlen(name) == IRC_MAXSID)
318      return hash_find_id(name);
319  
320 <  if ((client_p = clientTable[hashv]) != NULL)
320 >  if ((client_p = clientTable[hashv]))
321    {
322      if ((!IsServer(client_p) && !IsMe(client_p)) ||
323          irccmp(name, client_p->name))
324      {
325        struct Client *prev;
326  
327 <      while (prev = client_p, (client_p = client_p->hnext) != NULL)
327 >      while (prev = client_p, (client_p = client_p->hnext))
328        {
329          if ((IsServer(client_p) || IsMe(client_p)) &&
330              !irccmp(name, client_p->name))
# Line 430 | Line 345 | hash_find_server(const char *name)
345   *
346   * inputs       - pointer to name
347   * output       - NONE
348 < * side effects - New semantics: finds a channel whose name is 'name',
348 > * side effects - New semantics: finds a channel whose name is 'name',
349   *                if can't find one returns NULL, if can find it moves
350   *                it to the top of the list and returns it.
351   */
352   struct Channel *
353   hash_find_channel(const char *name)
354   {
355 <  unsigned int hashv = strhash(name);
355 >  const unsigned int hashv = strhash(name);
356    struct Channel *chptr = NULL;
357  
358 <  if ((chptr = channelTable[hashv]) != NULL)
358 >  if ((chptr = channelTable[hashv]))
359    {
360 <    if (irccmp(name, chptr->chname))
360 >    if (irccmp(name, chptr->name))
361      {
362        struct Channel *prev;
363  
364 <      while (prev = chptr, (chptr = chptr->hnextch) != NULL)
364 >      while (prev = chptr, (chptr = chptr->hnextch))
365        {
366 <        if (!irccmp(name, chptr->chname))
366 >        if (!irccmp(name, chptr->name))
367          {
368            prev->hnextch = chptr->hnextch;
369            chptr->hnextch = channelTable[hashv];
# Line 476 | Line 391 | void *
391   hash_get_bucket(int type, unsigned int hashv)
392   {
393    assert(hashv < HASHSIZE);
394 +
395    if (hashv >= HASHSIZE)
396 <      return NULL;
396 >    return NULL;
397  
398    switch (type)
399    {
# Line 490 | Line 406 | hash_get_bucket(int type, unsigned int h
406      case HASH_TYPE_CLIENT:
407        return clientTable[hashv];
408        break;
493    case HASH_TYPE_USERHOST:
494      return userhostTable[hashv];
495      break;
496    case HASH_TYPE_RESERVED:
497      return resvchannelTable[hashv];
498      break;
409      default:
410        assert(0);
411    }
# Line 503 | Line 413 | hash_get_bucket(int type, unsigned int h
413    return NULL;
414   }
415  
506 /* hash_find_resv()
507 *
508 * inputs       - pointer to name
509 * output       - NONE
510 * side effects - New semantics: finds a reserved channel whose name is 'name',
511 *                if can't find one returns NULL, if can find it moves
512 *                it to the top of the list and returns it.
513 */
514 struct ResvChannel *
515 hash_find_resv(const char *name)
516 {
517  unsigned int hashv = strhash(name);
518  struct ResvChannel *chptr;
519
520  if ((chptr = resvchannelTable[hashv]) != NULL)
521  {
522    if (irccmp(name, chptr->name))
523    {
524      struct ResvChannel *prev;
525
526      while (prev = chptr, (chptr = chptr->hnext) != NULL)
527      {
528        if (!irccmp(name, chptr->name))
529        {
530          prev->hnext = chptr->hnext;
531          chptr->hnext = resvchannelTable[hashv];
532          resvchannelTable[hashv] = chptr;
533          break;
534        }
535      }
536    }
537  }
538
539  return chptr;
540 }
541
542 struct UserHost *
543 hash_find_userhost(const char *host)
544 {
545  unsigned int hashv = strhash(host);
546  struct UserHost *userhost;
547
548  if ((userhost = userhostTable[hashv]))
549  {
550    if (irccmp(host, userhost->host))
551    {
552      struct UserHost *prev;
553
554      while (prev = userhost, (userhost = userhost->next) != NULL)
555      {
556        if (!irccmp(host, userhost->host))
557        {
558          prev->next = userhost->next;
559          userhost->next = userhostTable[hashv];
560          userhostTable[hashv] = userhost;
561          break;
562        }
563      }
564    }
565  }
566
567  return userhost;
568 }
569
570 /* count_user_host()
571 *
572 * inputs       - user name
573 *              - hostname
574 *              - int flag 1 if global, 0 if local
575 *              - pointer to where global count should go
576 *              - pointer to where local count should go
577 *              - pointer to where identd count should go (local clients only)
578 * output       - none
579 * side effects -
580 */
581 void
582 count_user_host(const char *user, const char *host, int *global_p,
583                int *local_p, int *icount_p)
584 {
585  dlink_node *ptr;
586  struct UserHost *found_userhost;
587  struct NameHost *nameh;
588
589  if ((found_userhost = hash_find_userhost(host)) == NULL)
590    return;
591
592  DLINK_FOREACH(ptr, found_userhost->list.head)
593  {
594    nameh = ptr->data;
595
596    if (!irccmp(user, nameh->name))
597    {
598      if (global_p != NULL)
599        *global_p = nameh->gcount;
600      if (local_p != NULL)
601        *local_p  = nameh->lcount;
602      if (icount_p != NULL)
603        *icount_p = nameh->icount;
604      return;
605    }
606  }
607 }
608
609 /* find_or_add_userhost()
610 *
611 * inputs       - host name
612 * output       - none
613 * side effects - find UserHost * for given host name
614 */
615 static struct UserHost *
616 find_or_add_userhost(const char *host)
617 {
618  struct UserHost *userhost;
619
620  if ((userhost = hash_find_userhost(host)) != NULL)
621    return userhost;
622
623  userhost = BlockHeapAlloc(userhost_heap);
624  strlcpy(userhost->host, host, sizeof(userhost->host));
625  hash_add_userhost(userhost);
626
627  return userhost;
628 }
629
630 /* add_user_host()
631 *
632 * inputs       - user name
633 *              - hostname
634 *              - int flag 1 if global, 0 if local
635 * output       - none
636 * side effects - add given user@host to hash tables
637 */
638 void
639 add_user_host(const char *user, const char *host, int global)
640 {
641  dlink_node *ptr;
642  struct UserHost *found_userhost;
643  struct NameHost *nameh;
644  int hasident = 1;
645
646  if (*user == '~')
647  {
648    hasident = 0;
649    ++user;
650  }
651
652  if ((found_userhost = find_or_add_userhost(host)) == NULL)
653    return;
654
655  DLINK_FOREACH(ptr, found_userhost->list.head)
656  {
657    nameh = ptr->data;
658
659    if (!irccmp(user, nameh->name))
660    {
661      nameh->gcount++;
662
663      if (!global)
664      {
665        if (hasident)
666          nameh->icount++;
667        nameh->lcount++;
668      }
669
670      return;
671    }
672  }
673
674  nameh = BlockHeapAlloc(namehost_heap);
675  strlcpy(nameh->name, user, sizeof(nameh->name));
676
677  nameh->gcount = 1;
678
679  if (!global)
680  {
681    if (hasident)
682      nameh->icount = 1;
683    nameh->lcount = 1;
684  }
685
686  dlinkAdd(nameh, &nameh->node, &found_userhost->list);
687 }
688
689 /* delete_user_host()
690 *
691 * inputs       - user name
692 *              - hostname
693 *              - int flag 1 if global, 0 if local
694 * output       - none
695 * side effects - delete given user@host to hash tables
696 */
697 void
698 delete_user_host(const char *user, const char *host, int global)
699 {
700  dlink_node *ptr = NULL, *next_ptr = NULL;
701  struct UserHost *found_userhost;
702  struct NameHost *nameh;
703  int hasident = 1;
704
705  if (*user == '~')
706  {
707    hasident = 0;
708    ++user;
709  }
710
711  if ((found_userhost = hash_find_userhost(host)) == NULL)
712    return;
713
714  DLINK_FOREACH_SAFE(ptr, next_ptr, found_userhost->list.head)
715  {
716    nameh = ptr->data;
717
718    if (!irccmp(user, nameh->name))
719    {
720      if (nameh->gcount > 0)
721        nameh->gcount--;
722      if (!global)
723      {
724        if (nameh->lcount > 0)
725          nameh->lcount--;
726        if (hasident && nameh->icount > 0)
727          nameh->icount--;
728      }
729
730      if (nameh->gcount == 0 && nameh->lcount == 0)
731      {
732        dlinkDelete(&nameh->node, &found_userhost->list);
733        BlockHeapFree(namehost_heap, nameh);
734      }
735
736      if (dlink_list_length(&found_userhost->list) == 0)
737      {
738        hash_del_userhost(found_userhost);
739        BlockHeapFree(userhost_heap, found_userhost);
740      }
741
742      return;
743    }
744  }
745 }
746
416   /*
417   * Safe list code.
418   *
# Line 766 | Line 435 | delete_user_host(const char *user, const
435   *
436   * Sendq limit is fairly conservative at 1/2 (In original anyway)
437   */
438 < static int
439 < exceeding_sendq(struct Client *to)
438 > static bool
439 > exceeding_sendq(const struct Client *to)
440   {
441 <  if (dbuf_length(&to->localClient->buf_sendq) > (get_sendq(to) / 2))
442 <    return 1;
441 >  if (dbuf_length(&to->connection->buf_sendq) > (get_sendq(&to->connection->confs) / 2))
442 >    return true;
443    else
444 <    return 0;
444 >    return false;
445   }
446  
447   void
448 < free_list_task(struct ListTask *lt, struct Client *source_p)
448 > free_list_task(struct Client *source_p)
449   {
450 <  dlink_node *dl, *dln;
450 >  struct ListTask *const lt = source_p->connection->list_task;
451 >  dlink_node *node, *node_next;
452  
453 <  if ((dl = dlinkFindDelete(&listing_client_list, source_p)) != NULL)
784 <    free_dlink_node(dl);
453 >  dlinkDelete(&lt->node, &listing_client_list);
454  
455 <  DLINK_FOREACH_SAFE(dl, dln, lt->show_mask.head)
455 >  DLINK_FOREACH_SAFE(node, node_next, lt->show_mask.head)
456    {
457 <    MyFree(dl->data);
458 <    free_dlink_node(dl);
457 >    xfree(node->data);
458 >    dlinkDelete(node, &lt->show_mask);
459 >    free_dlink_node(node);
460    }
461  
462 <  DLINK_FOREACH_SAFE(dl, dln, lt->hide_mask.head)
462 >  DLINK_FOREACH_SAFE(node, node_next, lt->hide_mask.head)
463    {
464 <    MyFree(dl->data);
465 <    free_dlink_node(dl);
464 >    xfree(node->data);
465 >    dlinkDelete(node, &lt->hide_mask);
466 >    free_dlink_node(node);
467    }
468  
469 <  MyFree(lt);
470 <
800 <  if (MyConnect(source_p))
801 <    source_p->localClient->list_task = NULL;
469 >  xfree(lt);
470 >  source_p->connection->list_task = NULL;
471   }
472  
473   /* list_allow_channel()
# Line 809 | Line 478 | free_list_task(struct ListTask *lt, stru
478   *                0 otherwise
479   * side effects -
480   */
481 < static int
482 < list_allow_channel(const char *chname, struct ListTask *lt)
481 > static bool
482 > list_allow_channel(const char *name, const struct ListTask *lt)
483   {
484 <  dlink_node *dl = NULL;
484 >  dlink_node *node;
485  
486 <  DLINK_FOREACH(dl, lt->show_mask.head)
487 <    if (!match_chan(dl->data, chname))
488 <      return 0;
486 >  DLINK_FOREACH(node, lt->show_mask.head)
487 >    if (match(node->data, name) != 0)
488 >      return false;
489  
490 <  DLINK_FOREACH(dl, lt->hide_mask.head)
491 <    if (match_chan(dl->data, chname))
492 <      return 0;
490 >  DLINK_FOREACH(node, lt->hide_mask.head)
491 >    if (match(node->data, name) == 0)
492 >      return false;
493  
494 <  return 1;
494 >  return true;
495   }
496  
497   /* list_one_channel()
# Line 834 | Line 503 | list_allow_channel(const char *chname, s
503   * side effects -
504   */
505   static void
506 < list_one_channel(struct Client *source_p, struct Channel *chptr,
838 <                 struct ListTask *list_task)
506 > list_one_channel(struct Client *source_p, struct Channel *chptr)
507   {
508 <  if (SecretChannel(chptr) && !IsMember(source_p, chptr))
508 >  const struct ListTask *const lt = source_p->connection->list_task;
509 >  char listbuf[MODEBUFLEN] = "";
510 >  char modebuf[MODEBUFLEN] = "";
511 >  char parabuf[MODEBUFLEN] = "";
512 >
513 >  if (SecretChannel(chptr) &&
514 >      !(HasUMode(source_p, UMODE_ADMIN) || IsMember(source_p, chptr)))
515      return;
516 <  if (dlink_list_length(&chptr->members) < list_task->users_min ||
517 <      dlink_list_length(&chptr->members) > list_task->users_max ||
518 <      (chptr->channelts != 0 &&
519 <       ((unsigned int)chptr->channelts < list_task->created_min ||
520 <        (unsigned int)chptr->channelts > list_task->created_max)) ||
521 <      (unsigned int)chptr->topic_time < list_task->topicts_min ||
516 >
517 >  if (dlink_list_length(&chptr->members) < lt->users_min ||
518 >      dlink_list_length(&chptr->members) > lt->users_max ||
519 >      (chptr->creationtime != 0 &&
520 >       ((unsigned int)chptr->creationtime < lt->created_min ||
521 >        (unsigned int)chptr->creationtime > lt->created_max)) ||
522 >      (unsigned int)chptr->topic_time < lt->topicts_min ||
523        (chptr->topic_time ? (unsigned int)chptr->topic_time : UINT_MAX) >
524 <      list_task->topicts_max)
524 >      lt->topicts_max)
525      return;
526  
527 <  if (!list_allow_channel(chptr->chname, list_task))
527 >  if (lt->topic[0] && match(lt->topic, chptr->topic))
528      return;
529 <  sendto_one(source_p, form_str(RPL_LIST), me.name, source_p->name,
530 <             chptr->chname, dlink_list_length(&chptr->members),
531 <             chptr->topic);
529 >
530 >  if (list_allow_channel(chptr->name, lt) == false)
531 >    return;
532 >
533 >  channel_modes(chptr, source_p, modebuf, parabuf);
534 >
535 >  if (chptr->topic[0])
536 >    snprintf(listbuf, sizeof(listbuf), "[%s] ", modebuf);
537 >  else
538 >    snprintf(listbuf, sizeof(listbuf), "[%s]",  modebuf);
539 >
540 >  sendto_one_numeric(source_p, &me, RPL_LIST, chptr->name,
541 >                     dlink_list_length(&chptr->members),
542 >                     listbuf, chptr->topic);
543   }
544  
545   /* safe_list_channels()
# Line 865 | Line 551 | list_one_channel(struct Client *source_p
551   * Walk the channel buckets, ensure all pointers in a bucket are
552   * traversed before blocking on a sendq. This means, no locking is needed.
553   *
868 * N.B. This code is "remote" safe, but is not currently used for
869 * remote clients.
870 *
554   * - Dianora
555   */
556   void
557 < safe_list_channels(struct Client *source_p, struct ListTask *list_task,
875 <                   int only_unmasked_channels)
557 > safe_list_channels(struct Client *source_p, bool only_unmasked_channels)
558   {
559 +  struct ListTask *const lt = source_p->connection->list_task;
560    struct Channel *chptr = NULL;
561  
562 <  if (!only_unmasked_channels)
562 >  if (only_unmasked_channels == false)
563    {
564 <    unsigned int i;
882 <
883 <    for (i = list_task->hash_index; i < HASHSIZE; ++i)
564 >    for (unsigned int i = lt->hash_index; i < HASHSIZE; ++i)
565      {
566 <      if (exceeding_sendq(source_p->from))
566 >      if (exceeding_sendq(source_p) == true)
567        {
568 <        list_task->hash_index = i;
569 <        return;    /* still more to do */
568 >        lt->hash_index = i;
569 >        return;  /* Still more to do */
570        }
571  
572        for (chptr = channelTable[i]; chptr; chptr = chptr->hnextch)
573 <        list_one_channel(source_p, chptr, list_task);
573 >        list_one_channel(source_p, chptr);
574      }
575    }
576    else
577    {
578 <    dlink_node *dl;
578 >    dlink_node *node;
579  
580 <    DLINK_FOREACH(dl, list_task->show_mask.head)
581 <      if ((chptr = hash_find_channel(dl->data)) != NULL)
582 <        list_one_channel(source_p, chptr, list_task);
580 >    DLINK_FOREACH(node, lt->show_mask.head)
581 >      if ((chptr = hash_find_channel(node->data)))
582 >        list_one_channel(source_p, chptr);
583    }
584  
585 <  free_list_task(list_task, source_p);
586 <  sendto_one(source_p, form_str(RPL_LISTEND),
906 <             me.name, source_p->name);
585 >  free_list_task(source_p);
586 >  sendto_one_numeric(source_p, &me, RPL_LISTEND);
587   }

Comparing ircd-hybrid/trunk/src/hash.c (property svn:keywords):
Revision 1592 by michael, Sat Oct 27 21:02:32 2012 UTC vs.
Revision 8752 by michael, Tue Jan 1 11:07:01 2019 UTC

# Line 1 | Line 1
1 < Id Revision
1 > Id

Diff Legend

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