X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fhash.c;h=aa264ddb158500431bc94d4830e4d9b00e48a4bc;hb=refs%2Fheads%2Fupstream;hp=7d335022e7e9ee13137cedf6fafc4e8e015b5b2e;hpb=b068efa5821ba43e3ef7d723b116c8cff4b59045;p=ircu2.10.12-pk.git diff --git a/ircd/hash.c b/ircd/hash.c index 7d33502..aa264dd 100644 --- a/ircd/hash.c +++ b/ircd/hash.c @@ -24,16 +24,21 @@ #include "hash.h" #include "client.h" #include "channel.h" +#include "ircd_alloc.h" #include "ircd_chattr.h" +#include "ircd_log.h" +#include "ircd_reply.h" #include "ircd_string.h" #include "ircd.h" +#include "match.h" #include "msg.h" +#include "numeric.h" #include "random.h" #include "send.h" #include "struct.h" #include "sys.h" -#include +/* #include -- Now using assert in ircd_log.h */ #include #include #include @@ -69,20 +74,14 @@ void init_hash(void) crc32hash[ii] = rand; } - /* Now reorder the hash table. To make it case-insensitive, skip - * upper-case letters, and have lower-case letters write to the - * corresponding upper-case character. - */ + /* Now reorder the hash table. */ for (ii = 0, rand = 0; ii < 256; ii++) { - char ch = ii + CHAR_MIN; - if (ch != ToLower(ch)) - continue; if (!rand) rand = ircrandom(); poly = ii + rand % (256 - ii); jj = crc32hash[ii]; - crc32hash[ToUpper(ch) - CHAR_MIN] = crc32hash[ii] = crc32hash[poly]; + crc32hash[ii] = crc32hash[poly]; crc32hash[poly] = jj; rand >>= 8; } @@ -97,9 +96,9 @@ typedef unsigned int HASHREGS; */ static HASHREGS strhash(const char *n) { - HASHREGS hash = crc32hash[*n++ & 255]; + HASHREGS hash = crc32hash[ToLower(*n++) & 255]; while (*n) - hash = (hash >> 8) ^ crc32hash[(hash ^ *n++) & 255]; + hash = (hash >> 8) ^ crc32hash[(hash ^ ToLower(*n++)) & 255]; return hash % HASHSIZE; } @@ -110,7 +109,7 @@ static HASHREGS strhash(const char *n) * I avoided introducing new variables to do the work myself and I did let * the optimizer play with more free registers, actual tests proved this * solution to be faster than doing things like tmp2=tmp->hnext... and then - * use tmp2 myself wich would have given less freedom to the optimizer. + * use tmp2 myself which would have given less freedom to the optimizer. */ /** Prepend a client to the appropriate hash bucket. @@ -409,3 +408,74 @@ void clearNickJupes(void) for (i = 0; i < JUPEHASHSIZE; i++) jupeTable[i][0] = '\000'; } + +/** Report all nick jupes to a user. + * @param[in] to Client requesting statistics. + * @param[in] sd Stats descriptor for request (ignored). + * @param[in] param Extra parameter from user (ignored). + */ +void +stats_nickjupes(struct Client* to, const struct StatDesc* sd, char* param) +{ + int i; + for (i = 0; i < JUPEHASHSIZE; i++) + if (jupeTable[i][0]) + send_reply(to, RPL_STATSJLINE, jupeTable[i]); +} + +/** Send more channels to a client in mid-LIST. + * @param[in] cptr Client to send the list to. + */ +void list_next_channels(struct Client *cptr) +{ + struct ListingArgs *args; + struct Channel *chptr; + + /* Walk consecutive buckets until we hit the end. */ + for (args = cli_listing(cptr); args->bucket < HASHSIZE; args->bucket++) + { + /* Send all the matching channels in the bucket. */ + for (chptr = channelTable[args->bucket]; chptr; chptr = chptr->hnext) + { + if (chptr->users > args->min_users + && chptr->users < args->max_users + && chptr->creationtime > args->min_time + && chptr->creationtime < args->max_time + && (!args->wildcard[0] || (args->flags & LISTARG_NEGATEWILDCARD) || + (!match(args->wildcard, chptr->chname))) + && (!(args->flags & LISTARG_NEGATEWILDCARD) || + match(args->wildcard, chptr->chname)) + && (!(args->flags & LISTARG_TOPICLIMITS) + || (chptr->topic[0] + && chptr->topic_time > args->min_topic_time + && chptr->topic_time < args->max_topic_time)) + && ((args->flags & LISTARG_SHOWSECRET) + || ShowChannel(cptr, chptr))) + { + if (args->flags & LISTARG_SHOWMODES) { + char modebuf[MODEBUFLEN]; + char parabuf[MODEBUFLEN]; + + modebuf[0] = modebuf[1] = parabuf[0] = '\0'; + channel_modes(cptr, modebuf, parabuf, sizeof(parabuf), chptr, NULL); + send_reply(cptr, RPL_LIST | SND_EXPLICIT, "%s %u %s %s :%s", + chptr->chname, chptr->users, modebuf, parabuf, chptr->topic); + } else { + send_reply(cptr, RPL_LIST, chptr->chname, chptr->users, chptr->topic); + } + } + } + /* If, at the end of the bucket, client sendq is more than half + * full, stop. */ + if (MsgQLength(&cli_sendQ(cptr)) > cli_max_sendq(cptr) / 2) + break; + } + + /* If we did all buckets, clean the client and send RPL_LISTEND. */ + if (args->bucket >= HASHSIZE) + { + MyFree(cli_listing(cptr)); + cli_listing(cptr) = NULL; + send_reply(cptr, RPL_LISTEND); + } +}