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 9250 by michael, Sat Feb 1 13:36:10 2020 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-2020 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"
34 #include "modules.h"
33   #include "hash.h"
34 < #include "resv.h"
34 > #include "id.h"
35   #include "rng_mt.h"
38 #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"
45 #include "s_user.h"
46
42  
48 static BlockHeap *userhost_heap = NULL;
49 static BlockHeap *namehost_heap = NULL;
50 static struct UserHost *find_or_add_userhost(const char *);
51
52 static unsigned int hashf_xor_key = 0;
43  
44   /* The actual hash tables, They MUST be of the same HASHSIZE, variable
45   * size tables could be supported but the rehash routine should also
46 < * rebuild the transformation maps, I kept the tables of equal size
46 > * rebuild the transformation maps, I kept the tables of equal size
47   * so that I can use one hash function.
48   */
49   static struct Client *idTable[HASHSIZE];
50   static struct Client *clientTable[HASHSIZE];
51   static struct Channel *channelTable[HASHSIZE];
62 static struct UserHost *userhostTable[HASHSIZE];
63 static struct ResvChannel *resvchannelTable[HASHSIZE];
52  
53  
66 /* init_hash()
67 *
68 * inputs       - NONE
69 * output       - NONE
70 * side effects - Initialize the maps used by hash
71 *                functions and clear the tables
72 */
73 void
74 init_hash(void)
75 {
76  unsigned int i;
77
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);
84
85  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  }
96 }
97
54   /*
55   * New hash function based on the Fowler/Noll/Vo (FNV) algorithm from
56   * http://www.isthe.com/chongo/tech/comp/fnv/
# Line 105 | Line 61 | init_hash(void)
61   unsigned int
62   strhash(const char *name)
63   {
64 +  static unsigned int hashf_xor_key = 0;
65    const unsigned char *p = (const unsigned char *)name;
66    unsigned int hval = FNV1_32_INIT;
67  
68 <  if (*p == '\0')
68 >  if (EmptyString(p))
69      return 0;
70 <  for (; *p != '\0'; ++p)
70 >
71 >  if (hashf_xor_key == 0)
72 >    do
73 >      hashf_xor_key = genrand_int32() % 256;  /* better than nothing --adx */
74 >    while (hashf_xor_key == 0);
75 >
76 >  for (; *p; ++p)
77    {
78 <    hval += (hval << 1) + (hval <<  4) + (hval << 7) +
79 <            (hval << 8) + (hval << 24);
78 >    hval += (hval << 1) + (hval << 4) +
79 >            (hval << 7) + (hval << 8) + (hval << 24);
80      hval ^= (ToLower(*p) ^ hashf_xor_key);
81    }
82  
# Line 135 | Line 98 | strhash(const char *name)
98   * inputs       - pointer to client
99   * output       - NONE
100   * side effects - Adds a client's name in the proper hash linked
101 < *                list, can't fail, client_p must have a non-null
101 > *                list, can't fail, client must have a non-null
102   *                name or expect a coredump, the name is infact
103 < *                taken from client_p->name
103 > *                taken from client->name
104   */
105   void
106 < hash_add_client(struct Client *client_p)
106 > hash_add_client(struct Client *client)
107   {
108 <  unsigned int hashv = strhash(client_p->name);
108 >  const unsigned int hashv = strhash(client->name);
109  
110 <  client_p->hnext = clientTable[hashv];
111 <  clientTable[hashv] = client_p;
110 >  client->hnext = clientTable[hashv];
111 >  clientTable[hashv] = client;
112   }
113  
114   /* hash_add_channel()
# Line 153 | Line 116 | hash_add_client(struct Client *client_p)
116   * inputs       - pointer to channel
117   * output       - NONE
118   * side effects - Adds a channel's name in the proper hash linked
119 < *                list, can't fail. chptr must have a non-null name
119 > *                list, can't fail. channel must have a non-null name
120   *                or expect a coredump. As before the name is taken
121 < *                from chptr->name, we do hash its entire lenght
121 > *                from channel->name, we do hash its entire lenght
122   *                since this proved to be statistically faster
123   */
124   void
125 < hash_add_channel(struct Channel *chptr)
163 < {
164 <  unsigned int hashv = strhash(chptr->chname);
165 <
166 <  chptr->hnextch = channelTable[hashv];
167 <  channelTable[hashv] = chptr;
168 < }
169 <
170 < void
171 < hash_add_resv(struct ResvChannel *chptr)
125 > hash_add_channel(struct Channel *channel)
126   {
127 <  unsigned int hashv = strhash(chptr->name);
127 >  const unsigned int hashv = strhash(channel->name);
128  
129 <  chptr->hnext = resvchannelTable[hashv];
130 <  resvchannelTable[hashv] = chptr;
129 >  channel->hnextch = channelTable[hashv];
130 >  channelTable[hashv] = channel;
131   }
132  
133   void
134 < hash_add_userhost(struct UserHost *userhost)
134 > hash_add_id(struct Client *client)
135   {
136 <  unsigned int hashv = strhash(userhost->host);
136 >  const unsigned int hashv = strhash(client->id);
137  
138 <  userhost->next = userhostTable[hashv];
139 <  userhostTable[hashv] = userhost;
186 < }
187 <
188 < void
189 < hash_add_id(struct Client *client_p)
190 < {
191 <  unsigned int hashv = strhash(client_p->id);
192 <
193 <  client_p->idhnext = idTable[hashv];
194 <  idTable[hashv] = client_p;
138 >  client->idhnext = idTable[hashv];
139 >  idTable[hashv] = client;
140   }
141  
142   /* hash_del_id()
# Line 201 | Line 146 | hash_add_id(struct Client *client_p)
146   * side effects - Removes an ID from the hash linked list
147   */
148   void
149 < hash_del_id(struct Client *client_p)
149 > hash_del_id(struct Client *client)
150   {
151 <  unsigned int hashv = strhash(client_p->id);
151 >  const unsigned int hashv = strhash(client->id);
152    struct Client *tmp = idTable[hashv];
153  
154 <  if (tmp != NULL)
154 >  if (tmp)
155    {
156 <    if (tmp == client_p)
156 >    if (tmp == client)
157      {
158 <      idTable[hashv] = client_p->idhnext;
159 <      client_p->idhnext = client_p;
158 >      idTable[hashv] = client->idhnext;
159 >      client->idhnext = client;
160      }
161      else
162      {
163 <      while (tmp->idhnext != client_p)
219 <      {
163 >      while (tmp->idhnext != client)
164          if ((tmp = tmp->idhnext) == NULL)
165            return;
222      }
166  
167        tmp->idhnext = tmp->idhnext->idhnext;
168 <      client_p->idhnext = client_p;
168 >      client->idhnext = client;
169      }
170    }
171   }
# Line 234 | Line 177 | hash_del_id(struct Client *client_p)
177   * side effects - Removes a Client's name from the hash linked list
178   */
179   void
180 < hash_del_client(struct Client *client_p)
180 > hash_del_client(struct Client *client)
181   {
182 <  unsigned int hashv = strhash(client_p->name);
182 >  const unsigned int hashv = strhash(client->name);
183    struct Client *tmp = clientTable[hashv];
184  
185 <  if (tmp != NULL)
185 >  if (tmp)
186    {
187 <    if (tmp == client_p)
187 >    if (tmp == client)
188      {
189 <      clientTable[hashv] = client_p->hnext;
190 <      client_p->hnext = client_p;
189 >      clientTable[hashv] = client->hnext;
190 >      client->hnext = client;
191      }
192      else
193      {
194 <      while (tmp->hnext != client_p)
252 <      {
194 >      while (tmp->hnext != client)
195          if ((tmp = tmp->hnext) == NULL)
196            return;
255      }
197  
198        tmp->hnext = tmp->hnext->hnext;
199 <      client_p->hnext = client_p;
259 <    }
260 <  }
261 < }
262 <
263 < /* hash_del_userhost()
264 < *
265 < * inputs       - pointer to userhost
266 < * output       - NONE
267 < * side effects - Removes a userhost from the hash linked list
268 < */
269 < void
270 < hash_del_userhost(struct UserHost *userhost)
271 < {
272 <  unsigned int hashv = strhash(userhost->host);
273 <  struct UserHost *tmp = userhostTable[hashv];
274 <
275 <  if (tmp != NULL)
276 <  {
277 <    if (tmp == userhost)
278 <    {
279 <      userhostTable[hashv] = userhost->next;
280 <      userhost->next = userhost;
281 <    }
282 <    else
283 <    {
284 <      while (tmp->next != userhost)
285 <      {
286 <        if ((tmp = tmp->next) == NULL)
287 <          return;
288 <      }
289 <
290 <      tmp->next = tmp->next->next;
291 <      userhost->next = userhost;
199 >      client->hnext = client;
200      }
201    }
202   }
# Line 301 | Line 209 | hash_del_userhost(struct UserHost *userh
209   *                hash linked list
210   */
211   void
212 < hash_del_channel(struct Channel *chptr)
212 > hash_del_channel(struct Channel *channel)
213   {
214 <  unsigned int hashv = strhash(chptr->chname);
214 >  const unsigned int hashv = strhash(channel->name);
215    struct Channel *tmp = channelTable[hashv];
216  
217 <  if (tmp != NULL)
217 >  if (tmp)
218    {
219 <    if (tmp == chptr)
219 >    if (tmp == channel)
220      {
221 <      channelTable[hashv] = chptr->hnextch;
222 <      chptr->hnextch = chptr;
221 >      channelTable[hashv] = channel->hnextch;
222 >      channel->hnextch = channel;
223      }
224      else
225      {
226 <      while (tmp->hnextch != chptr)
319 <      {
226 >      while (tmp->hnextch != channel)
227          if ((tmp = tmp->hnextch) == NULL)
228            return;
322      }
229  
230        tmp->hnextch = tmp->hnextch->hnextch;
231 <      chptr->hnextch = chptr;
231 >      channel->hnextch = channel;
232      }
233    }
234   }
235  
236 < 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()
236 > /* hash_find_client()
237   *
238   * inputs       - pointer to name
239   * output       - NONE
# Line 363 | Line 242 | hash_del_resv(struct ResvChannel *chptr)
242   *                it to the top of the list and returns it.
243   */
244   struct Client *
245 < find_client(const char *name)
245 > hash_find_client(const char *name)
246   {
247 <  unsigned int hashv = strhash(name);
248 <  struct Client *client_p;
247 >  const unsigned int hashv = strhash(name);
248 >  struct Client *client;
249  
250 <  if ((client_p = clientTable[hashv]) != NULL)
250 >  if ((client = clientTable[hashv]))
251    {
252 <    if (irccmp(name, client_p->name))
252 >    if (irccmp(name, client->name))
253      {
254        struct Client *prev;
255  
256 <      while (prev = client_p, (client_p = client_p->hnext) != NULL)
256 >      while (prev = client, (client = client->hnext))
257        {
258 <        if (!irccmp(name, client_p->name))
258 >        if (irccmp(name, client->name) == 0)
259          {
260 <          prev->hnext = client_p->hnext;
261 <          client_p->hnext = clientTable[hashv];
262 <          clientTable[hashv] = client_p;
260 >          prev->hnext = client->hnext;
261 >          client->hnext = clientTable[hashv];
262 >          clientTable[hashv] = client;
263            break;
264          }
265        }
266      }
267    }
268  
269 <  return client_p;
269 >  return client;
270   }
271  
272   struct Client *
273   hash_find_id(const char *name)
274   {
275 <  unsigned int hashv = strhash(name);
276 <  struct Client *client_p;
275 >  const unsigned int hashv = strhash(name);
276 >  struct Client *client;
277  
278 <  if ((client_p = idTable[hashv]) != NULL)
278 >  if ((client = idTable[hashv]))
279    {
280 <    if (strcmp(name, client_p->id))
280 >    if (strcmp(name, client->id))
281      {
282        struct Client *prev;
283  
284 <      while (prev = client_p, (client_p = client_p->idhnext) != NULL)
284 >      while (prev = client, (client = client->idhnext))
285        {
286 <        if (!strcmp(name, client_p->id))
286 >        if (strcmp(name, client->id) == 0)
287          {
288 <          prev->idhnext = client_p->idhnext;
289 <          client_p->idhnext = idTable[hashv];
290 <          idTable[hashv] = client_p;
288 >          prev->idhnext = client->idhnext;
289 >          client->idhnext = idTable[hashv];
290 >          idTable[hashv] = client;
291            break;
292          }
293        }
294      }
295    }
296  
297 <  return client_p;
297 >  return client;
298   }
299  
300   struct Client *
301 < find_server(const char *name)
301 > hash_find_server(const char *name)
302   {
303 <  unsigned int hashv = strhash(name);
304 <  struct Client *client_p = NULL;
303 >  const unsigned int hashv = strhash(name);
304 >  struct Client *client;
305  
306    if (IsDigit(*name) && strlen(name) == IRC_MAXSID)
307 <    client_p = hash_find_id(name);
307 >    return hash_find_id(name);
308  
309 <  if ((client_p == NULL) && (client_p = clientTable[hashv]) != NULL)
309 >  if ((client = clientTable[hashv]))
310    {
311 <    if ((!IsServer(client_p) && !IsMe(client_p)) ||
312 <        irccmp(name, client_p->name))
311 >    if ((!IsServer(client) && !IsMe(client)) ||
312 >        irccmp(name, client->name))
313      {
314        struct Client *prev;
315  
316 <      while (prev = client_p, (client_p = client_p->hnext) != NULL)
316 >      while (prev = client, (client = client->hnext))
317        {
318 <        if ((IsServer(client_p) || IsMe(client_p)) &&
319 <            !irccmp(name, client_p->name))
318 >        if ((IsServer(client) || IsMe(client)) &&
319 >            irccmp(name, client->name) == 0)
320          {
321 <          prev->hnext = client_p->hnext;
322 <          client_p->hnext = clientTable[hashv];
323 <          clientTable[hashv] = client_p;
321 >          prev->hnext = client->hnext;
322 >          client->hnext = clientTable[hashv];
323 >          clientTable[hashv] = client;
324            break;
325          }
326        }
327      }
328    }
329  
330 <  return client_p;
330 >  return client;
331   }
332  
333   /* hash_find_channel()
334   *
335   * inputs       - pointer to name
336   * output       - NONE
337 < * side effects - New semantics: finds a channel whose name is 'name',
337 > * side effects - New semantics: finds a channel whose name is 'name',
338   *                if can't find one returns NULL, if can find it moves
339   *                it to the top of the list and returns it.
340   */
341   struct Channel *
342   hash_find_channel(const char *name)
343   {
344 <  unsigned int hashv = strhash(name);
345 <  struct Channel *chptr = NULL;
344 >  const unsigned int hashv = strhash(name);
345 >  struct Channel *channel;
346  
347 <  if ((chptr = channelTable[hashv]) != NULL)
347 >  if ((channel = channelTable[hashv]))
348    {
349 <    if (irccmp(name, chptr->chname))
349 >    if (irccmp(name, channel->name))
350      {
351        struct Channel *prev;
352  
353 <      while (prev = chptr, (chptr = chptr->hnextch) != NULL)
353 >      while (prev = channel, (channel = channel->hnextch))
354        {
355 <        if (!irccmp(name, chptr->chname))
355 >        if (irccmp(name, channel->name) == 0)
356          {
357 <          prev->hnextch = chptr->hnextch;
358 <          chptr->hnextch = channelTable[hashv];
359 <          channelTable[hashv] = chptr;
357 >          prev->hnextch = channel->hnextch;
358 >          channel->hnextch = channelTable[hashv];
359 >          channelTable[hashv] = channel;
360            break;
361          }
362        }
363      }
364    }
365  
366 <  return chptr;
366 >  return channel;
367   }
368  
369   /* hash_get_bucket(int type, unsigned int hashv)
# Line 501 | Line 380 | void *
380   hash_get_bucket(int type, unsigned int hashv)
381   {
382    assert(hashv < HASHSIZE);
383 +
384    if (hashv >= HASHSIZE)
385 <      return NULL;
385 >    return NULL;
386  
387    switch (type)
388    {
# Line 515 | Line 395 | hash_get_bucket(int type, unsigned int h
395      case HASH_TYPE_CLIENT:
396        return clientTable[hashv];
397        break;
518    case HASH_TYPE_USERHOST:
519      return userhostTable[hashv];
520      break;
521    case HASH_TYPE_RESERVED:
522      return resvchannelTable[hashv];
523      break;
398      default:
399        assert(0);
400    }
# Line 528 | Line 402 | hash_get_bucket(int type, unsigned int h
402    return NULL;
403   }
404  
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
567 struct UserHost *
568 hash_find_userhost(const char *host)
569 {
570  unsigned int hashv = strhash(host);
571  struct UserHost *userhost;
572
573  if ((userhost = userhostTable[hashv]))
574  {
575    if (irccmp(host, userhost->host))
576    {
577      struct UserHost *prev;
578
579      while (prev = userhost, (userhost = userhost->next) != NULL)
580      {
581        if (!irccmp(host, userhost->host))
582        {
583          prev->next = userhost->next;
584          userhost->next = userhostTable[hashv];
585          userhostTable[hashv] = userhost;
586          break;
587        }
588      }
589    }
590  }
591
592  return userhost;
593 }
594
595 /* count_user_host()
596 *
597 * inputs       - user name
598 *              - hostname
599 *              - int flag 1 if global, 0 if local
600 *              - pointer to where global count should go
601 *              - pointer to where local count should go
602 *              - pointer to where identd count should go (local clients only)
603 * output       - none
604 * side effects -
605 */
606 void
607 count_user_host(const char *user, const char *host, int *global_p,
608                int *local_p, int *icount_p)
609 {
610  dlink_node *ptr;
611  struct UserHost *found_userhost;
612  struct NameHost *nameh;
613
614  if ((found_userhost = hash_find_userhost(host)) == NULL)
615    return;
616
617  DLINK_FOREACH(ptr, found_userhost->list.head)
618  {
619    nameh = ptr->data;
620
621    if (!irccmp(user, nameh->name))
622    {
623      if (global_p != NULL)
624        *global_p = nameh->gcount;
625      if (local_p != NULL)
626        *local_p  = nameh->lcount;
627      if (icount_p != NULL)
628        *icount_p = nameh->icount;
629      return;
630    }
631  }
632 }
633
634 /* add_user_host()
635 *
636 * inputs       - user name
637 *              - hostname
638 *              - int flag 1 if global, 0 if local
639 * output       - none
640 * side effects - add given user@host to hash tables
641 */
642 void
643 add_user_host(const char *user, const char *host, int global)
644 {
645  dlink_node *ptr;
646  struct UserHost *found_userhost;
647  struct NameHost *nameh;
648  int hasident = 1;
649
650  if (*user == '~')
651  {
652    hasident = 0;
653    ++user;
654  }
655
656  if ((found_userhost = find_or_add_userhost(host)) == NULL)
657    return;
658
659  DLINK_FOREACH(ptr, found_userhost->list.head)
660  {
661    nameh = ptr->data;
662
663    if (!irccmp(user, nameh->name))
664    {
665      nameh->gcount++;
666      if (!global)
667      {
668        if (hasident)
669          nameh->icount++;
670        nameh->lcount++;
671      }
672      return;
673    }
674  }
675
676  nameh = BlockHeapAlloc(namehost_heap);
677  strlcpy(nameh->name, user, sizeof(nameh->name));
678
679  nameh->gcount = 1;
680  if (!global)
681  {
682    if (hasident)
683      nameh->icount = 1;
684    nameh->lcount = 1;
685  }
686
687  dlinkAdd(nameh, &nameh->node, &found_userhost->list);
688 }
689
690 /* delete_user_host()
691 *
692 * inputs       - user name
693 *              - hostname
694 *              - int flag 1 if global, 0 if local
695 * output       - none
696 * side effects - delete given user@host to hash tables
697 */
698 void
699 delete_user_host(const char *user, const char *host, int global)
700 {
701  dlink_node *ptr = NULL, *next_ptr = NULL;
702  struct UserHost *found_userhost;
703  struct NameHost *nameh;
704  int hasident = 1;
705
706  if (*user == '~')
707  {
708    hasident = 0;
709    ++user;
710  }
711
712  if ((found_userhost = hash_find_userhost(host)) == NULL)
713    return;
714
715  DLINK_FOREACH_SAFE(ptr, next_ptr, found_userhost->list.head)
716  {
717    nameh = ptr->data;
718
719    if (!irccmp(user, nameh->name))
720    {
721      if (nameh->gcount > 0)
722        nameh->gcount--;
723      if (!global)
724      {
725        if (nameh->lcount > 0)
726          nameh->lcount--;
727        if (hasident && nameh->icount > 0)
728          nameh->icount--;
729      }
730
731      if (nameh->gcount == 0 && nameh->lcount == 0)
732      {
733        dlinkDelete(&nameh->node, &found_userhost->list);
734        BlockHeapFree(namehost_heap, nameh);
735      }
736
737      if (dlink_list_length(&found_userhost->list) == 0)
738      {
739        hash_del_userhost(found_userhost);
740        BlockHeapFree(userhost_heap, found_userhost);
741      }
742
743      return;
744    }
745  }
746 }
747
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
405   /*
406   * Safe list code.
407   *
# Line 788 | Line 424 | find_or_add_userhost(const char *host)
424   *
425   * Sendq limit is fairly conservative at 1/2 (In original anyway)
426   */
427 < static int
428 < exceeding_sendq(struct Client *to)
427 > static bool
428 > exceeding_sendq(const struct Client *to)
429   {
430 <  if (dbuf_length(&to->localClient->buf_sendq) > (get_sendq(to) / 2))
431 <    return 1;
430 >  if (dbuf_length(&to->connection->buf_sendq) > (get_sendq(&to->connection->confs) / 2))
431 >    return true;
432    else
433 <    return 0;
433 >    return false;
434   }
435  
436   void
437 < free_list_task(struct ListTask *lt, struct Client *source_p)
437 > free_list_task(struct Client *client)
438   {
439 <  dlink_node *dl, *dln;
439 >  struct ListTask *const lt = client->connection->list_task;
440 >  dlink_node *node, *node_next;
441  
442 <  if ((dl = dlinkFindDelete(&listing_client_list, source_p)) != NULL)
806 <    free_dlink_node(dl);
442 >  dlinkDelete(&lt->node, &listing_client_list);
443  
444 <  DLINK_FOREACH_SAFE(dl, dln, lt->show_mask.head)
444 >  DLINK_FOREACH_SAFE(node, node_next, lt->show_mask.head)
445    {
446 <    MyFree(dl->data);
447 <    free_dlink_node(dl);
446 >    xfree(node->data);
447 >    dlinkDelete(node, &lt->show_mask);
448 >    free_dlink_node(node);
449    }
450  
451 <  DLINK_FOREACH_SAFE(dl, dln, lt->hide_mask.head)
451 >  DLINK_FOREACH_SAFE(node, node_next, lt->hide_mask.head)
452    {
453 <    MyFree(dl->data);
454 <    free_dlink_node(dl);
453 >    xfree(node->data);
454 >    dlinkDelete(node, &lt->hide_mask);
455 >    free_dlink_node(node);
456    }
457  
458 <  MyFree(lt);
459 <
822 <  if (MyConnect(source_p))
823 <    source_p->localClient->list_task = NULL;
458 >  xfree(lt);
459 >  client->connection->list_task = NULL;
460   }
461  
462   /* list_allow_channel()
# Line 831 | Line 467 | free_list_task(struct ListTask *lt, stru
467   *                0 otherwise
468   * side effects -
469   */
470 < static int
471 < list_allow_channel(const char *chname, struct ListTask *lt)
470 > static bool
471 > list_allow_channel(const char *name, const struct ListTask *lt)
472   {
473 <  dlink_node *dl = NULL;
473 >  dlink_node *node;
474  
475 <  DLINK_FOREACH(dl, lt->show_mask.head)
476 <    if (!match_chan(dl->data, chname))
477 <      return 0;
475 >  DLINK_FOREACH(node, lt->show_mask.head)
476 >    if (match(node->data, name) != 0)
477 >      return false;
478  
479 <  DLINK_FOREACH(dl, lt->hide_mask.head)
480 <    if (match_chan(dl->data, chname))
481 <      return 0;
479 >  DLINK_FOREACH(node, lt->hide_mask.head)
480 >    if (match(node->data, name) == 0)
481 >      return false;
482  
483 <  return 1;
483 >  return true;
484   }
485  
486   /* list_one_channel()
# Line 856 | Line 492 | list_allow_channel(const char *chname, s
492   * side effects -
493   */
494   static void
495 < list_one_channel(struct Client *source_p, struct Channel *chptr,
860 <                 struct ListTask *list_task)
495 > list_one_channel(struct Client *client, struct Channel *channel)
496   {
497 <  if (SecretChannel(chptr) && !IsMember(source_p, chptr))
497 >  const struct ListTask *const lt = client->connection->list_task;
498 >  char listbuf[MODEBUFLEN] = "";
499 >  char modebuf[MODEBUFLEN] = "";
500 >  char parabuf[MODEBUFLEN] = "";
501 >
502 >  if (SecretChannel(channel) &&
503 >      !(HasUMode(client, UMODE_ADMIN) || IsMember(client, channel)))
504      return;
505 <  if (dlink_list_length(&chptr->members) < list_task->users_min ||
506 <      dlink_list_length(&chptr->members) > list_task->users_max ||
507 <      (chptr->channelts != 0 &&
508 <       ((unsigned int)chptr->channelts < list_task->created_min ||
509 <        (unsigned int)chptr->channelts > list_task->created_max)) ||
510 <      (unsigned int)chptr->topic_time < list_task->topicts_min ||
511 <      (chptr->topic_time ? (unsigned int)chptr->topic_time : UINT_MAX) >
512 <      list_task->topicts_max)
505 >
506 >  if (dlink_list_length(&channel->members) < lt->users_min ||
507 >      dlink_list_length(&channel->members) > lt->users_max ||
508 >      (channel->creation_time != 0 &&
509 >       ((unsigned int)channel->creation_time < lt->created_min ||
510 >        (unsigned int)channel->creation_time > lt->created_max)) ||
511 >      (unsigned int)channel->topic_time < lt->topicts_min ||
512 >      (channel->topic_time ? (unsigned int)channel->topic_time : UINT_MAX) >
513 >      lt->topicts_max)
514 >    return;
515 >
516 >  if (lt->topic[0] && match(lt->topic, channel->topic))
517      return;
518  
519 <  if (!list_allow_channel(chptr->chname, list_task))
519 >  if (list_allow_channel(channel->name, lt) == false)
520      return;
521 <  sendto_one(source_p, form_str(RPL_LIST), me.name, source_p->name,
522 <             chptr->chname, dlink_list_length(&chptr->members),
523 <             chptr->topic == NULL ? "" : chptr->topic);
521 >
522 >  channel_modes(channel, client, modebuf, parabuf);
523 >
524 >  if (channel->topic[0])
525 >    snprintf(listbuf, sizeof(listbuf), "[%s] ", modebuf);
526 >  else
527 >    snprintf(listbuf, sizeof(listbuf), "[%s]",  modebuf);
528 >
529 >  sendto_one_numeric(client, &me, RPL_LIST, channel->name,
530 >                     dlink_list_length(&channel->members),
531 >                     listbuf, channel->topic);
532   }
533  
534   /* safe_list_channels()
535   *
536   * inputs       - pointer to client requesting list
537   * output       - 0/1
538 < * side effects - safely list all channels to source_p
538 > * side effects - safely list all channels to client
539   *
540   * Walk the channel buckets, ensure all pointers in a bucket are
541   * traversed before blocking on a sendq. This means, no locking is needed.
542   *
890 * N.B. This code is "remote" safe, but is not currently used for
891 * remote clients.
892 *
543   * - Dianora
544   */
545   void
546 < safe_list_channels(struct Client *source_p, struct ListTask *list_task,
897 <                   int only_unmasked_channels)
546 > safe_list_channels(struct Client *client, bool only_unmasked_channels)
547   {
548 <  struct Channel *chptr = NULL;
548 >  struct ListTask *const lt = client->connection->list_task;
549 >  struct Channel *channel;
550  
551 <  if (!only_unmasked_channels)
551 >  if (only_unmasked_channels == false)
552    {
553 <    unsigned int i;
904 <
905 <    for (i = list_task->hash_index; i < HASHSIZE; ++i)
553 >    for (unsigned int i = lt->hash_index; i < HASHSIZE; ++i)
554      {
555 <      if (exceeding_sendq(source_p->from))
555 >      if (exceeding_sendq(client) == true)
556        {
557 <        list_task->hash_index = i;
558 <        return;    /* still more to do */
557 >        lt->hash_index = i;
558 >        return;  /* Still more to do */
559        }
560  
561 <      for (chptr = channelTable[i]; chptr; chptr = chptr->hnextch)
562 <        list_one_channel(source_p, chptr, list_task);
561 >      for (channel = channelTable[i]; channel; channel = channel->hnextch)
562 >        list_one_channel(client, channel);
563      }
564    }
565    else
566    {
567 <    dlink_node *dl;
567 >    dlink_node *node;
568  
569 <    DLINK_FOREACH(dl, list_task->show_mask.head)
570 <      if ((chptr = hash_find_channel(dl->data)) != NULL)
571 <        list_one_channel(source_p, chptr, list_task);
569 >    DLINK_FOREACH(node, lt->show_mask.head)
570 >      if ((channel = hash_find_channel(node->data)))
571 >        list_one_channel(client, channel);
572    }
573  
574 <  free_list_task(list_task, source_p);
575 <  sendto_one(source_p, form_str(RPL_LISTEND),
928 <             me.name, source_p->name);
574 >  free_list_task(client);
575 >  sendto_one_numeric(client, &me, RPL_LISTEND);
576   }

Comparing:
ircd-hybrid-7.3/src/hash.c (property svn:keywords), Revision 1118 by michael, Thu Jan 6 13:39:10 2011 UTC vs.
ircd-hybrid/trunk/src/hash.c (property svn:keywords), Revision 9250 by michael, Sat Feb 1 13:36:10 2020 UTC

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

Diff Legend

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