From f049124905bd9f53439293e873003cb027a17b91 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 14 May 2010 20:35:38 -0400 Subject: Rewrote the hashing system to use std::tr1::unordered_map --- docs/WIN32.txt | 16 +- include/Makefile | 2 +- include/account.h | 15 +- include/bots.h | 24 +- include/channels.h | 4 +- include/commands.h | 62 ++--- include/extern.h | 50 ++-- include/hashcomp.h | 58 +++- include/messages.h | 22 -- include/modules.h | 196 +++++-------- include/regchannel.h | 4 +- include/services.h | 25 +- include/users.h | 11 +- src/Makefile | 2 +- src/actions.c | 26 +- src/bots.cpp | 67 ++--- src/botserv.c | 90 ++---- src/channels.c | 151 ++++------ src/chanserv.c | 282 +++++++++---------- src/command.cpp | 10 +- src/commands.c | 113 +++----- src/config.c | 8 +- src/core/bs_act.c | 2 +- src/core/bs_assign.c | 2 +- src/core/bs_badwords.c | 2 +- src/core/bs_bot.c | 2 +- src/core/bs_botlist.c | 44 +-- src/core/bs_help.c | 4 +- src/core/bs_info.c | 27 +- src/core/bs_kick.c | 2 +- src/core/bs_say.c | 2 +- src/core/bs_set.c | 2 +- src/core/bs_unassign.c | 2 +- src/core/cs_access.c | 4 +- src/core/cs_akick.c | 49 ++-- src/core/cs_ban.c | 4 +- src/core/cs_clear.c | 2 +- src/core/cs_drop.c | 4 +- src/core/cs_forbid.c | 6 +- src/core/cs_getkey.c | 2 +- src/core/cs_help.c | 4 +- src/core/cs_info.c | 2 +- src/core/cs_invite.c | 2 +- src/core/cs_kick.c | 4 +- src/core/cs_list.c | 88 +++--- src/core/cs_modes.c | 32 +-- src/core/cs_register.c | 4 +- src/core/cs_set.c | 8 +- src/core/cs_status.c | 2 +- src/core/cs_suspend.c | 8 +- src/core/cs_topic.c | 10 +- src/core/cs_unban.c | 2 +- src/core/cs_xop.c | 14 +- src/core/db_plain.cpp | 444 ++++++++++++++--------------- src/core/hs_del.c | 2 +- src/core/hs_delall.c | 2 +- src/core/hs_group.c | 2 +- src/core/hs_help.c | 4 +- src/core/hs_list.c | 69 +++-- src/core/hs_off.c | 2 +- src/core/hs_on.c | 2 +- src/core/hs_set.c | 2 +- src/core/hs_setall.c | 2 +- src/core/ms_cancel.c | 2 +- src/core/ms_check.c | 2 +- src/core/ms_del.c | 2 +- src/core/ms_help.c | 4 +- src/core/ms_info.c | 2 +- src/core/ms_list.c | 2 +- src/core/ms_read.c | 2 +- src/core/ms_rsend.c | 2 +- src/core/ms_send.c | 2 +- src/core/ms_sendall.c | 20 +- src/core/ms_set.c | 2 +- src/core/ms_staff.c | 17 +- src/core/ns_access.c | 2 +- src/core/ns_alist.c | 36 ++- src/core/ns_drop.c | 6 +- src/core/ns_forbid.c | 4 +- src/core/ns_getemail.c | 23 +- src/core/ns_getpass.c | 6 +- src/core/ns_ghost.c | 2 +- src/core/ns_group.c | 8 +- src/core/ns_help.c | 4 +- src/core/ns_identify.c | 4 +- src/core/ns_info.c | 2 +- src/core/ns_list.c | 95 +++---- src/core/ns_logout.c | 2 +- src/core/ns_recover.c | 2 +- src/core/ns_register.c | 6 +- src/core/ns_release.c | 2 +- src/core/ns_resetpass.c | 2 +- src/core/ns_saset.c | 4 +- src/core/ns_sendpass.c | 2 +- src/core/ns_set.c | 2 +- src/core/ns_status.c | 2 +- src/core/ns_suspend.c | 8 +- src/core/ns_update.c | 2 +- src/core/os_akill.c | 4 +- src/core/os_chankill.c | 4 +- src/core/os_chanlist.c | 31 +-- src/core/os_clearmodes.c | 4 +- src/core/os_defcon.c | 24 +- src/core/os_global.c | 4 +- src/core/os_help.c | 4 +- src/core/os_ignore.c | 2 +- src/core/os_jupe.c | 4 +- src/core/os_kick.c | 6 +- src/core/os_mode.c | 6 +- src/core/os_modinfo.c | 49 ++-- src/core/os_modlist.c | 109 ++++---- src/core/os_modload.c | 12 +- src/core/os_modunload.c | 12 +- src/core/os_news.c | 6 +- src/core/os_noop.c | 12 +- src/core/os_oline.c | 8 +- src/core/os_quit.c | 2 +- src/core/os_reload.c | 2 +- src/core/os_restart.c | 2 +- src/core/os_session.c | 19 +- src/core/os_set.c | 10 +- src/core/os_sgline.c | 4 +- src/core/os_shutdown.c | 2 +- src/core/os_sqline.c | 4 +- src/core/os_staff.c | 6 +- src/core/os_stats.c | 2 +- src/core/os_svsnick.c | 4 +- src/core/os_szline.c | 4 +- src/core/os_umode.c | 6 +- src/core/os_update.c | 2 +- src/core/os_userlist.c | 32 +-- src/core/ss_main.c | 19 +- src/hashcomp.cpp | 43 +++ src/hostserv.c | 33 +-- src/init.c | 90 +++--- src/log.c | 2 +- src/main.c | 19 +- src/memoserv.c | 4 +- src/messages.c | 22 +- src/misc.c | 21 +- src/module.cpp | 151 +++++----- src/modulemanager.cpp | 35 ++- src/modules.c | 496 +++++---------------------------- src/modules/cs_appendtopic.c | 2 +- src/modules/cs_enforce.c | 2 +- src/modules/cs_tban.c | 2 +- src/modules/hs_request.c | 10 +- src/modules/mysql/db_mysql.h | 7 - src/modules/mysql/db_mysql_execute.cpp | 25 +- src/modules/mysql/db_mysql_read.cpp | 8 +- src/modules/mysql/db_mysql_write.cpp | 174 +++++------- src/modules/ns_maxemail.c | 13 +- src/modules/os_info.c | 27 +- src/nickalias.cpp | 24 +- src/nickcore.cpp | 13 +- src/nickserv.c | 343 ++++++++--------------- src/operserv.c | 60 ++-- src/process.c | 29 +- src/protocol/bahamut.c | 62 ++--- src/protocol/inspircd11.c | 79 +++--- src/protocol/inspircd12.cpp | 103 ++++--- src/protocol/ratbox.c | 60 ++-- src/protocol/unreal32.c | 139 +++++---- src/regchannel.cpp | 14 +- src/servers.cpp | 10 +- src/sessions.c | 78 ++---- src/users.c | 210 +++++--------- 167 files changed, 2136 insertions(+), 3091 deletions(-) delete mode 100644 include/messages.h diff --git a/docs/WIN32.txt b/docs/WIN32.txt index c9035dfd0..102c36702 100644 --- a/docs/WIN32.txt +++ b/docs/WIN32.txt @@ -25,28 +25,20 @@ Anope for Windows (NOTE: When installing, tell CMake to add itself to the PATH.) - If you have Visual C++ 6, 7 (.NET 2002/2003), 8 (2005), or 9 (2008) skip ahead to step 2, else you + If you have Visual C++ 10 (2010) skip ahead to step 2, else you need to download the following free components from Microsoft. Once downloaded, install these packages. - * Microsoft Visual C++ 2008 Express Edition: + * Microsoft Visual C++ 2010 Express Edition: http://www.microsoft.com/express/vc/ or - * Microsoft Visual C++ 2005 Express Edition: - http://www.microsoft.com/downloads/details.aspx?FamilyId=7B0B0339-613A-46E6-AB4D-080D4D4A8C4E&displaylang=en - then download and install: * Microsoft Windows 2008 SDK: http://www.microsoft.com/downloads/details.aspx?FamilyId=E6E1C3DF-A74F-4207-8586-711EBE331CDC&displaylang=en - or (if you prefer a smaller download) - - * Microsoft Windows 2003 Platform SDK: (Requires WGA validation) - http://www.microsoft.com/downloads/details.aspx?FamilyId=0BAF2B35-C656-4969-ACE8-E4C0C0716ADB&displaylang=en - (NOTE: Although they say for Windows Server 2003 or 2008, they do infact work on all supported versions of Windows. When installing the 2003 SDK, you should select the Custom option, and only select to have the Microsoft Windows Core SDK installed. When installing the 2008 SDK, you should select the @@ -54,10 +46,6 @@ Anope for Windows the Visual C++ Compilers as well as the Mobile Tools. Doing this will decrease the install time as well as the space used by the SDK.) - If you chose to download the 2003 SDK, it will not work out-of-the-box on either Visual C++ 2005 Express or - Visual C++ 2008 Express. The 2008 SDK will work out-of-the-box with Visual C++ 2008 Express but not with - Visual C++ 2005 Express. - 2) Unpack the Anope tarball with your favorite uncompression program (WinZip or WinRAR, etc). diff --git a/include/Makefile b/include/Makefile index 3d8067aa6..69e2473f6 100644 --- a/include/Makefile +++ b/include/Makefile @@ -1,7 +1,7 @@ all: services.h extern.h pseudo.h version.h -version.h: Makefile version.sh services.h pseudo.h messages.h $(SRCS) +version.h: Makefile version.sh services.h pseudo.h $(SRCS) sh version.sh ../version.log $@ services.h: sysconf.h config.h extern.h diff --git a/include/account.h b/include/account.h index 5449bd93a..1a567c317 100644 --- a/include/account.h +++ b/include/account.h @@ -1,3 +1,14 @@ +class NickAlias; +class NickCore; +class NickRequest; + +typedef unordered_map_namespace::unordered_map nickalias_map; +typedef unordered_map_namespace::unordered_map nickcore_map; +typedef unordered_map_namespace::unordered_map nickrequest_map; + +extern CoreExport nickalias_map NickAliasList; +extern CoreExport nickcore_map NickCoreList; +extern CoreExport nickrequest_map NickRequestList; /* NickServ nickname structures. */ @@ -76,7 +87,6 @@ class CoreExport NickRequest : public Extensible ~NickRequest(); - NickRequest *next, *prev; char *nick; std::string passcode; std::string password; @@ -100,7 +110,6 @@ class CoreExport NickAlias : public Extensible, public Flags */ ~NickAlias(); - NickAlias *next, *prev; char *nick; /* Nickname */ char *last_quit; /* Last quit message */ char *last_realname; /* Last realname */ @@ -135,8 +144,6 @@ class CoreExport NickCore : public Extensible, public Flags */ ~NickCore(); - NickCore *next, *prev; - std::list Users; char *display; /* How the nick is displayed */ diff --git a/include/bots.h b/include/bots.h index 3b4987bb7..b73b39879 100644 --- a/include/bots.h +++ b/include/bots.h @@ -8,6 +8,12 @@ * */ +#include "commands.h" + +class BotInfo; +typedef unordered_map_namespace::unordered_map botinfo_map; +extern CoreExport botinfo_map BotList; + /** Flags settable on a bot */ enum BotFlag @@ -16,29 +22,13 @@ enum BotFlag /* This bot can only be assigned by IRCops */ BI_PRIVATE, - /* The following flags are used to determin what bot really is what. - * Since you *could* have ChanServ really named BotServ or something stupid, - * this keeps track of them and allows them to be renamed in the config - * at any time, even if they already exist in the database - */ - BI_CHANSERV, - BI_BOTSERV, - BI_HOSTSERV, - BI_OPERSERV, - BI_MEMOSERV, - BI_NICKSERV, - BI_GLOBAL, BI_END }; -struct CommandHash; - class CoreExport BotInfo : public Extensible, public Flags { public: - BotInfo *next, *prev; - std::string uid; /* required for UID supporting servers, as opposed to the shitty struct Uid. */ std::string nick; /* Nickname of the bot */ std::string user; /* Its user name */ @@ -48,7 +38,7 @@ class CoreExport BotInfo : public Extensible, public Flags int16 chancount; /* Number of channels that use the bot. */ /* Dynamic data */ time_t lastmsg; /* Last time we said something */ - CommandHash **cmdTable; + CommandMap Commands; /** Create a new bot. * @param nick The nickname to assign to the bot. diff --git a/include/channels.h b/include/channels.h index 51b830c03..4285a9f21 100644 --- a/include/channels.h +++ b/include/channels.h @@ -8,6 +8,9 @@ * */ +typedef unordered_map_namespace::unordered_map channel_map; +extern CoreExport channel_map ChannelList; + struct UserData { UserData() @@ -72,7 +75,6 @@ class CoreExport Channel : public Extensible, public Flags */ ~Channel(); - Channel *next, *prev; std::string name; /* Channel name */ ChannelInfo *ci; /* Corresponding ChannelInfo */ time_t creation_time; /* When channel was created */ diff --git a/include/commands.h b/include/commands.h index 5d43f556b..5d381084e 100644 --- a/include/commands.h +++ b/include/commands.h @@ -14,25 +14,13 @@ #ifndef COMMAND_H_ #define COMMAND_H_ -#define MAX_CMD_HASH 1024 -#define CMD_HASH(x) (((x)[0]&31)<<5 | ((x)[1]&31)) /* Will gen a hash from a string :) */ - -#define HOSTSERV HS_cmdTable /* using HOSTSERV etc. looks nicer than HS_cmdTable for modules */ -#define BOTSERV BS_cmdTable -#define MEMOSERV MS_cmdTable -#define NICKSERV NS_cmdTable -#define CHANSERV CS_cmdTable -#define OPERSERV OS_cmdTable - -#ifndef _WIN32 -#define MDE -#else -#ifndef MODULE_COMPILE -#define MDE __declspec(dllexport) -#else -#define MDE __declspec(dllimport) -#endif -#endif +#include "services.h" + +class Module; +class BotInfo; +class Command; + +typedef std::map CommandMap; /** The return value from commands. * */ @@ -42,24 +30,9 @@ enum CommandReturn MOD_STOP }; -class Command; - -extern MDE Command *lookup_cmd(Command *list, char *name); -extern MDE void mod_help_cmd(char *service, User *u, CommandHash *cmdTable[], const char *cmd); -extern MDE void mod_run_cmd(const std::string &service, User *u, CommandHash *cmdTable[], const char *cmd); - -struct CommandHash { - char *name; /* Name of the command */ - Command *c; /* Actual command */ - CommandHash *next; /* Next command */ -}; - -extern MDE CommandHash *HOSTSERV[MAX_CMD_HASH]; -extern MDE CommandHash *BOTSERV[MAX_CMD_HASH]; -extern MDE CommandHash *MEMOSERV[MAX_CMD_HASH]; -extern MDE CommandHash *NICKSERV[MAX_CMD_HASH]; -extern MDE CommandHash *CHANSERV[MAX_CMD_HASH]; -extern MDE CommandHash *OPERSERV[MAX_CMD_HASH]; +extern CoreExport Command *FindCommand(BotInfo *bi, const ci::string &cmd); +extern CoreExport void mod_help_cmd(BotInfo *bi, User *u, const ci::string &cmd); +extern CoreExport void mod_run_cmd(BotInfo *bi, User *u, const ci::string &cmd); enum CommandFlag { @@ -76,11 +49,20 @@ enum CommandFlag class CoreExport Command : public Flags { public: + /* Maximum paramaters accepted by this command */ size_t MaxParams; + /* Minimum parameters required to use this command */ size_t MinParams; + /* Command name */ ci::string name; + /* Permission needed to use this comand */ std::string permission; + /* Module which owns us */ + Module *module; + /* Service this command is on */ + BotInfo *service; + /** Create a new command. * @param sname The command name * @param min_params The minimum number of parameters the parser will require to execute this command @@ -114,12 +96,6 @@ class CoreExport Command : public Flags * @param reststr The permission required to successfully execute this command */ void SetPermission(const std::string &reststr); - - /* Module related stuff */ - int core; /* Can this command be deleted? */ - char *mod_name; /* Name of the module who owns us, NULL for core's */ - char *service; /* Service we provide this command for */ - Command *next; }; #endif diff --git a/include/extern.h b/include/extern.h index 67364c0f5..a10585e69 100644 --- a/include/extern.h +++ b/include/extern.h @@ -46,14 +46,14 @@ E BotInfo *OperServ; /**** botserv.c ****/ -E BotInfo *botlists[256]; -E int nbots; E void get_botserv_stats(long *nrec, long *memuse); E void bs_init(); E void botserv(User *u, char *buf); E void botmsgs(User *u, BotInfo *bi, char *buf); E void botchanmsgs(User *u, ChannelInfo *ci, char *buf); +E BotInfo *findbot(const char *nick); E BotInfo *findbot(const std::string &nick); +E BotInfo *findbot(const ci::string &nick); /** Finds a pseudoclient, given a UID. Useful for TS6 protocol modules. * @param uid The UID to search for @@ -61,7 +61,6 @@ E BotInfo *findbot(const std::string &nick); */ E void bot_join(ChannelInfo *ci); E char *normalizeBuffer(const char *); -E void insert_bot(BotInfo * bi); E void bot_raw_ban(User * requester, ChannelInfo * ci, char *nick, const char *reason); E void bot_raw_kick(User * requester, ChannelInfo * ci, char *nick, const char *reason); @@ -69,12 +68,11 @@ E void bot_raw_mode(User * requester, ChannelInfo * ci, const char *mode, char * /**** channels.c ****/ -E Channel *chanlist[1024]; - E void get_channel_stats(long *nrec, long *memuse); + E Channel *findchan(const char *chan); -E Channel *firstchan(); -E Channel *nextchan(); +E Channel *findchan(const std::string &chan); +E Channel *findchan(const ci::string &chan); E void ChanSetInternalModes(Channel *c, int ac, const char **av); @@ -112,12 +110,10 @@ E long get_memuse(EList *list); /**** chanserv.c ****/ -E ChannelInfo *chanlists[256]; E LevelInfo levelinfo[]; E void get_chanserv_stats(long *nrec, long *memuse); -E void alpha_insert_chan(ChannelInfo * ci); E void reset_levels(ChannelInfo * ci); E void cs_init(); E void chanserv(User * u, char *buf); @@ -136,7 +132,9 @@ E void record_topic(const char *chan); E void restore_topic(const char *chan); E int check_topiclock(Channel * c, time_t topic_time); +E ChannelInfo *cs_findchan(const char *chan); E ChannelInfo *cs_findchan(const std::string &chan); +E ChannelInfo *cs_findchan(const ci::string &chan); E int check_access(User * user, ChannelInfo * ci, int what); E bool IsFounder(User *user, ChannelInfo *ci); E bool IsRealFounder(User *user, ChannelInfo *ci); @@ -359,18 +357,11 @@ E std::map DefMLockParams; E std::list BotModes; E void SetDefaultMLock(); -/**** modules.c ****/ -E void modules_unload_all(bool unload_proto); /* Read warnings near function source */ - /**** nickserv.c ****/ -E NickAlias *nalists[1024]; -E NickCore *nclists[1024]; -E NickRequest *nrlists[1024]; E NickRequest *findrequestnick(const char *nick); -E void insert_requestnick(NickRequest * nr); -E void alpha_insert_alias(NickAlias * na); -E void insert_core(NickCore * nc); +E NickRequest *findrequestnick(const std::string &nick); +E NickRequest *findrequestnick(const ci::string &nick); E void get_aliases_stats(long *nrec, long *memuse); E void get_core_stats(long *nrec, long *memuse); E void change_core_display(NickCore * nc); @@ -384,7 +375,10 @@ E void expire_nicks(); E void expire_requests(); E NickAlias *findnick(const char *nick); E NickAlias *findnick(const std::string &nick); -E NickCore *findcore(const char *nick); +E NickAlias *findnick(const ci::string &nick); +E NickCore *findcore(const char *nick); +E NickCore *findcore(const std::string &nick); +E NickCore *findcore(const ci::string &nick); E bool is_on_access(User *u, NickCore *nc); /**** operserv.c ****/ @@ -462,9 +456,6 @@ E void notice_help(const char *source, User *dest, int message, ...); // MARK_DE E Exception *exceptions; E int16 nexceptions; -E Session *sessionlist[1024]; -E int32 nsessions; - E void get_session_stats(long *nrec, long *memuse); E void get_exception_stats(long *nrec, long *memuse); @@ -473,7 +464,7 @@ E void del_session(const char *host); E void expire_exceptions(); -E Session *findsession(const char *host); +E Session *findsession(const std::string &host); E Exception *find_host_exception(const char *host); E Exception *find_hostip_exception(const char *host, const char *hostip); @@ -501,20 +492,19 @@ E int32 TotalWritten; /**** users.c ****/ -E User *userlist[1024]; - E int32 opcnt; E uint32 maxusercnt, usercnt; E time_t maxusertime; E void get_user_stats(long *nusers, long *memuse); -E User *finduser(const std::string &nick); -E User *firstuser(); -E User *nextuser(); +E User *finduser(const char *nick); +E User *finduser(const std::string &nick); +E User *finduser(const ci::string &nick); +E User *find_byuid(const char *uid); +E User *find_byuid(const ci::string &uid); E User *find_byuid(const std::string &uid); -E User *first_uid(); -E User *next_uid(); + E Server *findserver_uid(Server * s, const char *name); E char *TS6SID; diff --git a/include/hashcomp.h b/include/hashcomp.h index becebb48e..a0d456b40 100644 --- a/include/hashcomp.h +++ b/include/hashcomp.h @@ -15,6 +15,23 @@ #include +#ifndef _WIN32 + #ifdef HASHMAP_DEPRECATED /* If gcc ver > 4.3 */ + /* GCC4.3+ has deprecated hash_map and uses tr1. But of course, uses a different include to MSVC. */ + #include + #define unordered_map_namespace std::tr1 + #else + #include + /* Oddball linux namespace for hash_map */ + #define unordered_map_namespace __gnu_cxx + #define unordered_map hash_map + #endif +#else + /* MSVC 2010+ has tr1. Though MSVC and GCC use different includes! */ + #include + #define unordered_map_namespace std::tr1 +#endif + /******************************************************* * This file contains classes and templates that deal * with the comparison and hashing of 'irc strings'. @@ -30,9 +47,6 @@ * aware of irc::string. *******************************************************/ -#ifndef LOWERMAP -#define LOWERMAP - /** A mapping of uppercase to lowercase, including scandinavian * 'oddities' as specified by RFC1459, e.g. { -> [, and | -> \ */ @@ -72,8 +86,6 @@ unsigned const char ascii_case_insensitive_map[256] = { 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 /* 240-255 */ }; -#endif - /** The irc namespace contains a number of helper classes. */ namespace irc @@ -470,4 +482,40 @@ class spacesepstream : public sepstream spacesepstream(const char *source) : sepstream(source, ' ') { } }; +/** Class used to hash a std::string, given as the third argument to the unordered_map template + */ +class CoreExport hash_compare_std_string +{ + public: + /** Return a hash value for a string + * @param s The string + * @return The hash value + */ + size_t operator()(const std::string &s) const; +}; + +/** Class used to hash a ci::string, given as the third argument to the unordered_map template + */ +class CoreExport hash_compare_ci_string +{ + public: + /** Return a hash value for a string using case insensitivity + * @param s The string + * @return The hash value + */ + size_t operator()(const ci::string &s) const; +}; + +/** Class used to hash a irc::string, given as the third argument to the unordered_map template + */ +class CoreExport hash_compare_irc_string +{ + public: + /** Return a hash value for a string using RFC1459 case sensitivity rules + * @param s The stirng + * @return The hash value + */ + size_t operator()(const irc::string &s) const; +}; + #endif diff --git a/include/messages.h b/include/messages.h deleted file mode 100644 index a5505471e..000000000 --- a/include/messages.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Declarations of IRC message structures, variables, and functions. - * - * (C) 2003-2010 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for furhter details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - * - * - */ - -/*************************************************************************/ -#include "modules.h" - -extern Message messages[]; -extern void moduleAddMsgs(); -extern Message *find_message(const char *name); - - -/*************************************************************************/ diff --git a/include/modules.h b/include/modules.h index f3bc20bfb..d76b8f70b 100644 --- a/include/modules.h +++ b/include/modules.h @@ -104,52 +104,6 @@ do { \ } \ } while(0); - - -/** Priority types which can be returned from Module::Prioritize() - */ -enum Priority { PRIORITY_FIRST, PRIORITY_DONTCARE, PRIORITY_LAST, PRIORITY_BEFORE, PRIORITY_AFTER }; - - - -/*************************************************************************/ - -#define IRCD IRCD_cmdTable -#define MODULE_HASH Module_table -#define EVENT EVENT_cmdTable -#define EVENTHOOKS HOOK_cmdTable - -/********************************************************************** - * Module Returns - **********************************************************************/ -#define MOD_ERR_OK 0 -#define MOD_ERR_MEMORY 1 -#define MOD_ERR_PARAMS 2 -#define MOD_ERR_EXISTS 3 -#define MOD_ERR_NOEXIST 4 -#define MOD_ERR_NOUSER 5 -#define MOD_ERR_NOLOAD 6 -#define MOD_ERR_NOUNLOAD 7 -#define MOD_ERR_SYNTAX 8 -#define MOD_ERR_NODELETE 9 -#define MOD_ERR_UNKNOWN 10 -#define MOD_ERR_FILE_IO 11 -#define MOD_ERR_NOSERVICE 12 -#define MOD_ERR_NO_MOD_NAME 13 - -/*************************************************************************/ -/* Macros to export the Module API functions/variables */ -#ifndef _WIN32 -#define MDE -#else -#ifndef MODULE_COMPILE -#define MDE __declspec(dllexport) -#else -#define MDE __declspec(dllimport) -#endif -#endif -/*************************************************************************/ - #if !defined(_WIN32) #include /* Define these for systems without them */ @@ -169,26 +123,42 @@ enum Priority { PRIORITY_FIRST, PRIORITY_DONTCARE, PRIORITY_LAST, PRIORITY_BEFOR const char *ano_moderr(); #endif -typedef enum { CORE,PROTOCOL,THIRD,SUPPORTED,QATESTED,ENCRYPTION,DATABASE } MODType; -typedef enum { MOD_OP_LOAD, MOD_OP_UNLOAD } ModuleOperation; - -/*************************************************************************/ -/* Structure for information about a *Serv command. */ +extern CoreExport Module *FindModule(const std::string &name); +int protocol_module_init(); +extern CoreExport Message *createMessage(const char *name, int (*func)(const char *source, int ac, const char **av)); +std::vector FindMessage(const std::string &name); +extern CoreExport bool moduleMinVersion(int major,int minor,int patch,int build); -typedef struct ModuleLang_ ModuleLang; -typedef struct ModuleHash_ ModuleHash; -typedef struct Message_ Message; -typedef struct MessageHash_ MessageHash; +enum ModuleReturn +{ + MOD_ERR_OK, + MOD_ERR_MEMORY, + MOD_ERR_PARAMS, + MOD_ERR_EXISTS, + MOD_ERR_NOEXIST, + MOD_ERR_NOUSER, + MOD_ERR_NOLOAD, + MOD_ERR_NOUNLOAD, + MOD_ERR_SYNTAX, + MOD_ERR_NODELETE, + MOD_ERR_UNKNOWN, + MOD_ERR_FILE_IO, + MOD_ERR_NOSERVICE, + MOD_ERR_NO_MOD_NAME +}; -/*************************************************************************/ +/** Priority types which can be returned from Module::Prioritize() + */ +enum Priority { PRIORITY_FIRST, PRIORITY_DONTCARE, PRIORITY_LAST, PRIORITY_BEFORE, PRIORITY_AFTER }; +enum MODType { CORE, PROTOCOL, THIRD, SUPPORTED, QATESTED, ENCRYPTION, DATABASE }; -extern MDE MessageHash *IRCD[MAX_CMD_HASH]; -extern MDE ModuleHash *MODULE_HASH[MAX_CMD_HASH]; +struct Message; +extern CoreExport std::multimap MessageMap; +class Module; +extern CoreExport std::deque Modules; -struct ModuleLang_ { - int argc; - char **argv; -}; +/*************************************************************************/ +/* Structure for information about a *Serv command. */ class Version { @@ -247,15 +217,31 @@ class CoreExport Module */ std::list CallBacks; + /** Handle for this module, obtained from dlopen() + */ ano_module_t handle; + + /** Time this module was created + */ time_t created; + + /** Version of this module + */ std::string version; + + /** Author of the module + */ std::string author; + /** What type this module is + */ MODType type; - MessageHash *msgList[MAX_CMD_HASH]; - ModuleLang lang[NUM_LANGS]; + struct ModuleLang + { + int argc; + char **argv; + } lang[NUM_LANGS]; /** Creates and initialises a new module. * @param loadernick The nickname of the user loading the module. @@ -299,7 +285,7 @@ class CoreExport Module * compiled against * @return The version */ - virtual Version GetVersion() { return Version(VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD); } + Version GetVersion() { return Version(VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD); } /** * Allow a module to add a set of language strings to anope @@ -334,20 +320,19 @@ class CoreExport Module /** * Add a module provided command to the given service. - * e.g. AddCommand(NICKSERV,c,MOD_HEAD); - * @param cmdTable the services to add the command to - * @param c the command to add + * @param bi The service to add the command to + * @param c The command to add * @return MOD_ERR_OK on successfully adding the command */ - int AddCommand(CommandHash *cmdTable[], Command * c); + int AddCommand(BotInfo *bi, Command *c); /** * Delete a command from the service given. - * @param cmdTable the cmdTable for the services to remove the command from - * @param name the name of the command to delete from the service + * @param bi The service to remove the command from + * @param c Thec command to delete * @return returns MOD_ERR_OK on success */ - int DelCommand(CommandHash * cmdTable[], const char *name); + int DelCommand(BotInfo *bi, Command *c); /** Called on NickServ HELP * @param u The user requesting help @@ -434,13 +419,13 @@ class CoreExport Module virtual void OnUserNickChange(User *u, const std::string &oldnick) { } /** Called immediatly when a user tries to run a command - * @param service The service + * @param bi The bot the command is being run from * @param u The user * @param cmd The command * @param c The command class (if it exists) * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it */ - virtual EventReturn OnPreCommandRun(const std::string &service, User *u, const char *cmd, Command *c) { return EVENT_CONTINUE; } + virtual EventReturn OnPreCommandRun(BotInfo *bi, User *u, const ci::string &cmd, Command *c) { return EVENT_CONTINUE; } /** Called before a command is due to be executed. * @param u The user executing the command @@ -449,7 +434,7 @@ class CoreExport Module * @param params The parameters the user is sending * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it */ - virtual EventReturn OnPreCommand(User *u, const std::string &service, const ci::string &command, const std::vector ¶ms) { return EVENT_CONTINUE; } + virtual EventReturn OnPreCommand(User *u, BotInfo *service, const ci::string &command, const std::vector ¶ms) { return EVENT_CONTINUE; } /** Called after a command has been executed. * @param u The user executing the command @@ -457,7 +442,7 @@ class CoreExport Module * @param command The command the user executed * @param params The parameters the user sent */ - virtual void OnPostCommand(User *u, const std::string &service, const ci::string &command, const std::vector ¶ms) { } + virtual void OnPostCommand(User *u, BotInfo *service, const ci::string &command, const std::vector ¶ms) { } /** Called after the core has finished loading the databases, but before * we connect to the server @@ -714,9 +699,9 @@ class CoreExport Module virtual EventReturn OnPreNickExpire(NickAlias *na) { return EVENT_CONTINUE; } /** Called when a nick drops - * @param nick The nick + * @param na The nick */ - virtual void OnNickExpire(const char *nick) { } + virtual void OnNickExpire(NickAlias *na) { } /** Called when defcon level changes * @param level The level @@ -1238,7 +1223,13 @@ class CoreExport ModuleManager */ static void ClearCallBacks(Module *m); -private: + /** Unloading all modules, NEVER call this when Anope isn't shutting down. + * Ever. + * @param unload_proto true to unload the protocol module + */ + static void UnloadAll(bool unload_proto); + + private: /** Call the module_delete function to safely delete the module * @param m the module to delete */ @@ -1267,51 +1258,10 @@ class CallBack : public Timer } }; -struct ModuleHash_ { - char *name; - Module *m; - ModuleHash *next; -}; - -struct Message_ { - char *name; +struct Message +{ + std::string name; int (*func)(const char *source, int ac, const char **av); - int core; - Message *next; }; -struct MessageHash_ { - char *name; - Message *m; - MessageHash *next; -}; - -/*************************************************************************/ -/* Module Managment Functions */ -MDE Module *findModule(const char *name); /* Find a module */ - -int protocol_module_init(); /* Load the IRCD Protocol Module up*/ - -/*************************************************************************/ -/*************************************************************************/ -/* Command Managment Functions */ -MDE Command *findCommand(CommandHash *cmdTable[], const char *name); /* Find a command */ - -/*************************************************************************/ - -/* Message Managment Functions */ -MDE Message *createMessage(const char *name,int (*func)(const char *source, int ac, const char **av)); -Message *findMessage(MessageHash *msgTable[], const char *name); /* Find a Message */ -MDE int addMessage(MessageHash *msgTable[], Message *m, int pos); /* Add a Message to a Message table */ -MDE int addCoreMessage(MessageHash *msgTable[], Message *m); /* Add a Message to a Message table */ -int delMessage(MessageHash *msgTable[], Message *m); /* Del a Message from a msg table */ -int destroyMessage(Message *m); /* destroy a Message*/ - -/*************************************************************************/ - -MDE bool moduleMinVersion(int major,int minor,int patch,int build); /* Checks if the current version of anope is before or after a given verison */ - -/************************************************************************/ - #endif -/* EOF */ diff --git a/include/regchannel.h b/include/regchannel.h index bd5a50ced..4a571182b 100644 --- a/include/regchannel.h +++ b/include/regchannel.h @@ -8,6 +8,9 @@ * */ +typedef unordered_map_namespace::unordered_map registered_channel_map; +extern CoreExport registered_channel_map RegisteredChannelList; + /** Flags used for the ChannelInfo class */ enum ChannelInfoFlag @@ -78,7 +81,6 @@ class CoreExport ChannelInfo : public Extensible, public Flags */ ~ChannelInfo(); - ChannelInfo *next, *prev; std::string name; /* Channel name */ NickCore *founder; NickCore *successor; /* Who gets the channel if the founder diff --git a/include/services.h b/include/services.h index 4a8eb8d77..c05b44eac 100644 --- a/include/services.h +++ b/include/services.h @@ -198,6 +198,7 @@ extern int strncasecmp(const char *, const char *, size_t); #endif /* Miscellaneous definitions. */ +#include "hashcomp.h" #include "defs.h" #include "slist.h" @@ -352,12 +353,12 @@ class ChannelInfo; class Channel; class Server; struct EList; +struct Session; typedef struct bandata_ BanData; typedef struct mailinfo_ MailInfo; typedef struct akill_ Akill; typedef struct exception_ Exception; -typedef struct session_ Session; #include "extensible.h" #include "threadengine.h" @@ -827,8 +828,11 @@ struct exception_ { /*************************************************************************/ -struct session_ { - Session *prev, *next; +typedef unordered_map_namespace::unordered_map session_map; +extern CoreExport session_map SessionList; + +struct Session +{ char *host; int count; /* Number of clients with this host */ int hits; /* Number of subsequent kills for a host */ @@ -1054,6 +1058,7 @@ class CoreExport Alog } }; +class Message; // XXX class CoreExport Anope { @@ -1065,6 +1070,20 @@ class CoreExport Anope */ static bool Match(const std::string &str, const std::string &mask, bool case_sensitive = false); inline static bool Match(const ci::string &str, const ci::string &mask) { return Match(str.c_str(), mask.c_str(), false); } + + /** Add a message to Anope + * @param name The message name as sent by the IRCd + * @param func A callback function that will be called when this message is received + * @return The new message object + */ + static Message *AddMessage(const std::string &name, int (*func)(const char *source, int ac, const char **av)); + + /** Deletes a message from Anope + * XXX Im not sure what will happen if this function is called indirectly from message function pointed to by this message.. must check + * @param m The message + * @return true if the message was found and deleted, else false + */ + static bool DelMessage(Message *m); }; /*************************************************************************/ diff --git a/include/users.h b/include/users.h index b11c17875..3937e2ebe 100644 --- a/include/users.h +++ b/include/users.h @@ -8,6 +8,15 @@ * */ +/* Hash maps used for users. Note UserListByUID will not be used on non-TS6 IRCds, and should never + * be assumed to have users + */ +typedef unordered_map_namespace::unordered_map user_map; +typedef unordered_map_namespace::unordered_map user_uid_map; + +extern CoreExport user_map UserListByNick; +extern CoreExport user_uid_map UserListByUID; + struct ChannelContainer { Channel *chan; @@ -32,8 +41,6 @@ class CoreExport User : public Extensible NickCore *nc; /* NickCore account the user is currently loggged in as */ public: // XXX: exposing a tiny bit too much - User *next, *prev; - std::string nick; /* User's current nick */ char *host; /* User's real hostname */ diff --git a/src/Makefile b/src/Makefile index c82f9f5b4..1756e6702 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,7 +6,7 @@ OBJS = actions.o base64.o bots.o botserv.o channels.o chanserv.o command.o comm INCLUDES = ../include/commands.h ../include/defs.h ../include/language.h \ ../include/pseudo.h ../include/sysconf.h ../include/config.h \ - ../include/messages.h ../include/services.h \ + ../include/services.h \ ../include/timers.h ../include/extern.h \ ../include/modules.h ../include/slist.h ../include/hashcomp.h \ ../include/threadengine.h ../include/mail.h diff --git a/src/actions.c b/src/actions.c index 471e1273f..e3f199e80 100644 --- a/src/actions.c +++ b/src/actions.c @@ -77,32 +77,26 @@ void kill_user(const std::string &source, const std::string &user, const std::st */ void sqline(const std::string &mask, const std::string &reason) { - int i; - Channel *c, *next; - if (ircd->chansqline) { if (mask[0] == '#') { ircdproto->SendSQLine(mask, reason); - for (i = 0; i < 1024; ++i) + for (channel_map::const_iterator cit = ChannelList.begin(); cit != ChannelList.end(); ++cit) { - for (c = chanlist[i]; c; c = next) + Channel *c = cit->second; + + if (!Anope::Match(c->name, mask, false)) + continue; + for (CUserList::iterator it = c->users.begin(); it != c->users.end();) { - next = c->next; + UserContainer *uc = *it; + ++it; - if (!Anope::Match(c->name, mask, false)) + if (is_oper(uc->user)) continue; - for (CUserList::iterator it = c->users.begin(); it != c->users.end();) - { - UserContainer *uc = *it; - ++it; - - if (is_oper(uc->user)) - continue; - c->Kick(NULL, uc->user, "%s", reason.c_str()); - } + c->Kick(NULL, uc->user, "%s", reason.c_str()); } } } diff --git a/src/bots.cpp b/src/bots.cpp index 6f544a64a..a8cc86654 100644 --- a/src/bots.cpp +++ b/src/bots.cpp @@ -12,6 +12,8 @@ #include "modules.h" #include "commands.h" +botinfo_map BotList; + BotInfo *BotServ = NULL; BotInfo *ChanServ = NULL; BotInfo *Global = NULL; @@ -28,54 +30,39 @@ BotInfo::BotInfo(const std::string &nnick, const std::string &nuser, const std:: this->real = nreal; this->lastmsg = this->created = time(NULL); this->uid = ts6_uid_retrieve(); - this->cmdTable = NULL; - ++nbots; this->chancount = 0; ci::string ci_nick(nnick.c_str()); if (Config.s_ChanServ && ci_nick == Config.s_ChanServ) { ChanServ = this; - this->cmdTable = CHANSERV; - this->SetFlag(BI_CHANSERV); } else if (Config.s_BotServ && ci_nick == Config.s_BotServ) { BotServ = this; - this->cmdTable = BOTSERV; - this->SetFlag(BI_BOTSERV); } else if (Config.s_HostServ && ci_nick == Config.s_HostServ) { HostServ = this; - this->cmdTable = HOSTSERV; - this->SetFlag(BI_HOSTSERV); } else if (Config.s_OperServ && ci_nick == Config.s_OperServ) { OperServ = this; - this->cmdTable = OPERSERV; - this->SetFlag(BI_OPERSERV); } else if (Config.s_MemoServ && ci_nick == Config.s_MemoServ) { MemoServ = this; - this->cmdTable = MEMOSERV; - this->SetFlag(BI_MEMOSERV); } else if (Config.s_NickServ && ci_nick == Config.s_NickServ) { NickServ = this; - this->cmdTable = NICKSERV; - this->SetFlag(BI_NICKSERV); } else if (Config.s_GlobalNoticer && ci_nick == Config.s_GlobalNoticer) { Global = this; - this->SetFlag(BI_GLOBAL); } - insert_bot(this); // XXX, this is ugly, but it needs to stay until hashing of bots is redone in STL. + BotList[this->nick.c_str()] = this; // If we're synchronised with the uplink already, call introduce_user() for this bot. if (Me && Me->GetUplink()->IsSynced()) @@ -86,48 +73,38 @@ BotInfo::BotInfo(const std::string &nnick, const std::string &nuser, const std:: BotInfo::~BotInfo() { - int i; - ChannelInfo *ci; - - for (i = 0; i < 256; ++i) - for (ci = chanlists[i]; ci; ci = ci->next) - if (ci->bi == this) - ci->bi = NULL; - - if (this->next) - this->next->prev = this->prev; - if (this->prev) - this->prev->next = this->next; - else - botlists[tolower(this->nick[0])] = this->next; - - --nbots; + for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(); it != RegisteredChannelList.end(); ++it) + { + ChannelInfo *ci = it->second; + + if (ci->bi == this) + { + ci->bi = NULL; + } + } + + BotList.erase(this->nick.c_str()); } void BotInfo::ChangeNick(const char *newnick) { - if (this->next) - this->next->prev = this->prev; - if (this->prev) - this->prev->next = this->next; - else - botlists[tolower(this->nick[0])] = this->next; + BotList.erase(this->nick.c_str()); this->nick = newnick; - insert_bot(this); + BotList[this->nick.c_str()] = this; } void BotInfo::RejoinAll() { - int i; - ChannelInfo *ci; + for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(); it != RegisteredChannelList.end(); ++it) + { + ChannelInfo *ci = it->second; - for (i = 0; i < 256; ++i) - for (ci = chanlists[i]; ci; ci = ci->next) - if (ci->bi == this && ci->c && (ci->c->users.size() >= Config.BSMinUsers)) - bot_join(ci); + if (ci->bi == this && ci->c && ci->c->users.size() >= Config.BSMinUsers) + bot_join(ci); + } } void BotInfo::Assign(User *u, ChannelInfo *ci) diff --git a/src/botserv.c b/src/botserv.c index d0862c119..ea675ea60 100644 --- a/src/botserv.c +++ b/src/botserv.c @@ -18,11 +18,6 @@ /*************************************************************************/ -BotInfo *botlists[256]; /* Hash list of bots */ -int nbots = 0; - -/*************************************************************************/ - static UserData *get_user_data(Channel * c, User * u); static void check_ban(ChannelInfo * ci, User * u, int ttbtype); @@ -44,18 +39,17 @@ void moduleAddBotServCmds() { void get_botserv_stats(long *nrec, long *memuse) { long count = 0, mem = 0; - int i; - BotInfo *bi; - - for (i = 0; i < 256; i++) { - for (bi = botlists[i]; bi; bi = bi->next) { - count++; - mem += sizeof(*bi); - mem += bi->nick.size() + 1; - mem += bi->user.size() + 1; - mem += bi->host.size() + 1; - mem += bi->real.size() + 1; - } + + for (botinfo_map::const_iterator it = BotList.begin(); it != BotList.end(); ++it) + { + BotInfo *bi = it->second; + + count++; + mem += sizeof(*bi); + mem += bi->nick.size() + 1; + mem += bi->user.size() + 1; + mem += bi->host.size() + 1; + mem += bi->real.size() + 1; } *nrec = count; @@ -90,9 +84,9 @@ void botserv(User * u, char *buf) if (!(s = strtok(NULL, ""))) { *s = 0; } - ircdproto->SendCTCP(findbot(Config.s_BotServ), u->nick.c_str(), "PING %s", s); + ircdproto->SendCTCP(BotServ, u->nick.c_str(), "PING %s", s); } else { - mod_run_cmd(Config.s_BotServ, u, BOTSERV, cmd); + mod_run_cmd(BotServ, u, cmd); } } @@ -106,7 +100,7 @@ void botmsgs(User * u, BotInfo * bi, char *buf) char *cmd = strtok(buf, " "); char *s; - if (!cmd || !u) + if (!cmd || !u || !bi) return; if (!stricmp(cmd, "\1PING")) { @@ -115,9 +109,9 @@ void botmsgs(User * u, BotInfo * bi, char *buf) } ircdproto->SendCTCP(bi, u->nick.c_str(), "PING %s", s); } - else if (cmd && bi->cmdTable) + else if (cmd && !bi->Commands.empty()) { - mod_run_cmd(bi->nick, u, bi->cmdTable, cmd); + mod_run_cmd(bi, u, cmd); } } @@ -134,7 +128,6 @@ void botchanmsgs(User * u, ChannelInfo * ci, char *buf) char *cmd; UserData *ud; bool was_action = false; - Command *command; std::string bbuf; if (!u || !buf || !ci || !ci->c) @@ -424,7 +417,7 @@ void botchanmsgs(User * u, ChannelInfo * ci, char *buf) if (check_access(u, ci, CA_FANTASIA)) { - command = findCommand(CHANSERV, cmd); + Command *command = FindCommand(ChanServ, cmd); /* Command exists and can not be called by fantasy */ if (command && !command->HasFlag(CFLAG_DISABLE_FANTASY)) @@ -459,53 +452,22 @@ void botchanmsgs(User * u, ChannelInfo * ci, char *buf) /*************************************************************************/ -/* Inserts a bot in the bot list. I can't be much explicit mh? */ - -void insert_bot(BotInfo *bi) +BotInfo *findbot(const char *nick) { - BotInfo *ptr, *prev; - - ci::string ci_bi_nick(bi->nick.c_str()); - for (prev = NULL, ptr = botlists[tolower(bi->nick[0])]; - ptr != NULL && ci_bi_nick > ptr->nick.c_str(); - prev = ptr, ptr = ptr->next); - bi->prev = prev; - bi->next = ptr; - if (!prev) - botlists[tolower(bi->nick[0])] = bi; - else - prev->next = bi; - if (ptr) - ptr->prev = bi; + return findbot(ci::string(nick)); } -/*************************************************************************/ -/*************************************************************************/ - BotInfo *findbot(const std::string &nick) { - BotInfo *bi; - - if (nick.empty()) - return NULL; - - ci::string ci_nick(nick.c_str()); - - /* - * XXX Less than efficient, but we need to do this for good TS6 support currently. This *will* improve. -- w00t - */ - for (int i = 0; i < 256; i++) - { - for (bi = botlists[i]; bi; bi = bi->next) - { - if (ci_nick == bi->nick) - return bi; + return findbot(ci::string(nick.c_str())); +} - if (ci_nick == bi->uid) - return bi; - } - } +BotInfo *findbot(const ci::string &nick) +{ + botinfo_map::const_iterator it = BotList.find(nick); + if (it != BotList.end()) + return it->second; return NULL; } diff --git a/src/channels.c b/src/channels.c index a4cf3b167..6250d2342 100644 --- a/src/channels.c +++ b/src/channels.c @@ -15,11 +15,7 @@ #include "language.h" #include "modules.h" -Channel *chanlist[1024]; - -#define HASH(chan) ((chan)[1] ? ((chan)[1]&31)<<5 | ((chan)[2]&31) : 0) - -/*************************************************************************/ +channel_map ChannelList; /** Default constructor * @param name The channel name @@ -27,18 +23,12 @@ Channel *chanlist[1024]; */ Channel::Channel(const std::string &name, time_t ts) { - Channel **list; - if (name.empty()) throw CoreException("A channel without a name ?"); this->name = name; - list = &chanlist[HASH(this->name)]; - this->prev = NULL; - this->next = *list; - if (*list) - (*list)->prev = this; - *list = this; + + ChannelList[this->name.c_str()] = this; this->creation_time = ts; this->topic = NULL; @@ -102,12 +92,7 @@ Channel::~Channel() } } - if (this->next) - this->next->prev = this->prev; - if (this->prev) - this->prev->next = this->next; - else - chanlist[HASH(this->name)] = this->next; + ChannelList.erase(this->name.c_str()); } void Channel::Sync() @@ -1051,61 +1036,23 @@ char *chan_get_modes(Channel * chan, int complete, int plus) /*************************************************************************/ -/* Return the Channel structure corresponding to the named channel, or NULL - * if the channel was not found. chan is assumed to be non-NULL and valid - * (i.e. pointing to a channel name of 2 or more characters). */ - Channel *findchan(const char *chan) { - Channel *c; - - if (!chan || !*chan) - { - Alog(LOG_DEBUG) << "findchan() called with NULL values"; - return NULL; - } - - c = chanlist[HASH(chan)]; - while (c) - { - if (stricmp(c->name.c_str(), chan) == 0) - { - Alog(LOG_DEBUG_3) << "findchan(" << chan << ") -> " << static_cast(c); - return c; - } - c = c->next; - } - return NULL; + return findchan(ci::string(chan)); } -/*************************************************************************/ - -/* Iterate over all channels in the channel list. Return NULL at end of - * list. - */ - -static Channel *current; -static int next_index; - -Channel *firstchan() +Channel *findchan(const std::string &chan) { - next_index = 0; - while (next_index < 1024 && current == NULL) - current = chanlist[next_index++]; - Alog(LOG_DEBUG_3) << "firstchan() returning " << (current ? current->name : "NULL (end of list)"); - return current; + return findchan(ci::string(chan.c_str())); } -Channel *nextchan() +Channel *findchan(const ci::string &chan) { - if (current) - current = current->next; - if (!current && next_index < 1024) { - while (next_index < 1024 && current == NULL) - current = chanlist[next_index++]; - } - Alog(LOG_DEBUG_3) << "nextchan() returning " << (current ? current->name : "NULL (end of list)"); - return current; + channel_map::const_iterator it = ChannelList.find(chan); + + if (it != ChannelList.end()) + return it->second; + return NULL; } /*************************************************************************/ @@ -1115,40 +1062,39 @@ Channel *nextchan() void get_channel_stats(long *nrec, long *memuse) { long count = 0, mem = 0; - Channel *chan; BanData *bd; - int i; std::string buf; - for (i = 0; i < 1024; i++) { - for (chan = chanlist[i]; chan; chan = chan->next) { - count++; - mem += sizeof(*chan); - if (chan->topic) - mem += strlen(chan->topic) + 1; - if (chan->GetParam(CMODE_KEY, buf)) - mem += buf.length() + 1; - if (chan->GetParam(CMODE_FLOOD, buf)) - mem += buf.length() + 1; - if (chan->GetParam(CMODE_REDIRECT, buf)) - mem += buf.length() + 1; - mem += get_memuse(chan->bans); - if (ModeManager::FindChannelModeByName(CMODE_EXCEPT)) - mem += get_memuse(chan->excepts); - if (ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE)) - mem += get_memuse(chan->invites); - for (CUserList::iterator it = chan->users.begin(); it != chan->users.end(); ++it) - { - mem += sizeof(*it); - mem += sizeof((*it)->ud); - if ((*it)->ud.lastline) - mem += strlen((*it)->ud.lastline) + 1; - } - for (bd = chan->bd; bd; bd = bd->next) { - if (bd->mask) - mem += strlen(bd->mask) + 1; - mem += sizeof(*bd); - } + for (channel_map::const_iterator cit = ChannelList.begin(); cit != ChannelList.end(); ++cit) + { + Channel *chan = cit->second; + + count++; + mem += sizeof(*chan); + if (chan->topic) + mem += strlen(chan->topic) + 1; + if (chan->GetParam(CMODE_KEY, buf)) + mem += buf.length() + 1; + if (chan->GetParam(CMODE_FLOOD, buf)) + mem += buf.length() + 1; + if (chan->GetParam(CMODE_REDIRECT, buf)) + mem += buf.length() + 1; + mem += get_memuse(chan->bans); + if (ModeManager::FindChannelModeByName(CMODE_EXCEPT)) + mem += get_memuse(chan->excepts); + if (ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE)) + mem += get_memuse(chan->invites); + for (CUserList::iterator it = chan->users.begin(); it != chan->users.end(); ++it) + { + mem += sizeof(*it); + mem += sizeof((*it)->ud); + if ((*it)->ud.lastline) + mem += strlen((*it)->ud.lastline) + 1; + } + for (bd = chan->bd; bd; bd = bd->next) { + if (bd->mask) + mem += strlen(bd->mask) + 1; + mem += sizeof(*bd); } } *nrec = count; @@ -1542,10 +1488,10 @@ void chan_set_correct_modes(User * user, Channel * c, int give_modes) */ void MassChannelModes(BotInfo *bi, const std::string &modes) { - Channel *c; - - for (c = firstchan(); c; c = nextchan()) + for (channel_map::const_iterator it = ChannelList.begin(); it != ChannelList.end(); ++it) { + Channel *c = it->second; + if (c->bouncy_modes) return; c->SetModes(bi, false, modes.c_str()); @@ -1556,9 +1502,10 @@ void MassChannelModes(BotInfo *bi, const std::string &modes) void restore_unsynced_topics() { - Channel *c; + for (channel_map::const_iterator it = ChannelList.begin(); it != ChannelList.end(); ++it) + { + Channel *c = it->second; - for (c = firstchan(); c; c = nextchan()) { if (!(c->topic_sync)) restore_topic(c->name.c_str()); } diff --git a/src/chanserv.c b/src/chanserv.c index 377a04323..872055df1 100644 --- a/src/chanserv.c +++ b/src/chanserv.c @@ -19,7 +19,7 @@ /*************************************************************************/ /* *INDENT-OFF* */ -ChannelInfo *chanlists[256]; +registered_channel_map RegisteredChannelList; static int def_levels[][2] = { { CA_AUTOOP, 5 }, @@ -195,51 +195,51 @@ char *get_mlock_modes(ChannelInfo * ci, int complete) void get_chanserv_stats(long *nrec, long *memuse) { long count = 0, mem = 0; - unsigned i, j; - ChannelInfo *ci; std::string param; - for (i = 0; i < 256; i++) { - for (ci = chanlists[i]; ci; ci = ci->next) { - count++; - mem += sizeof(*ci); - if (ci->desc) - mem += strlen(ci->desc) + 1; - if (ci->url) - mem += strlen(ci->url) + 1; - if (ci->email) - mem += strlen(ci->email) + 1; - mem += ci->GetAccessCount() * sizeof(ChanAccess); - mem += ci->GetAkickCount() * sizeof(AutoKick); - - if (ci->GetParam(CMODE_KEY, param)) - mem += param.length() + 1; - - if (ci->GetParam(CMODE_FLOOD, param)) - mem += param.length() + 1; - - if (ci->GetParam(CMODE_REDIRECT, param)) - mem += param.length() + 1; - - if (ci->last_topic) - mem += strlen(ci->last_topic) + 1; - if (ci->entry_message) - mem += strlen(ci->entry_message) + 1; - if (ci->forbidby) - mem += strlen(ci->forbidby) + 1; - if (ci->forbidreason) - mem += strlen(ci->forbidreason) + 1; - if (ci->levels) - mem += sizeof(*ci->levels) * CA_SIZE; - mem += ci->memos.memos.size() * sizeof(Memo); - for (j = 0; j < ci->memos.memos.size(); j++) { - if (ci->memos.memos[j]->text) - mem += strlen(ci->memos.memos[j]->text) + 1; - } - if (ci->ttb) - mem += sizeof(*ci->ttb) * TTB_SIZE; - mem += ci->GetBadWordCount() * sizeof(BadWord); + for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(); it != RegisteredChannelList.end(); ++it) + { + ChannelInfo *ci = it->second; + + count++; + mem += sizeof(*ci); + if (ci->desc) + mem += strlen(ci->desc) + 1; + if (ci->url) + mem += strlen(ci->url) + 1; + if (ci->email) + mem += strlen(ci->email) + 1; + mem += ci->GetAccessCount() * sizeof(ChanAccess); + mem += ci->GetAkickCount() * sizeof(AutoKick); + + if (ci->GetParam(CMODE_KEY, param)) + mem += param.length() + 1; + + if (ci->GetParam(CMODE_FLOOD, param)) + mem += param.length() + 1; + + if (ci->GetParam(CMODE_REDIRECT, param)) + mem += param.length() + 1; + + if (ci->last_topic) + mem += strlen(ci->last_topic) + 1; + if (ci->entry_message) + mem += strlen(ci->entry_message) + 1; + if (ci->forbidby) + mem += strlen(ci->forbidby) + 1; + if (ci->forbidreason) + mem += strlen(ci->forbidreason) + 1; + if (ci->levels) + mem += sizeof(*ci->levels) * CA_SIZE; + mem += ci->memos.memos.size() * sizeof(Memo); + for (unsigned j = 0; j < ci->memos.memos.size(); j++) + { + if (ci->memos.memos[j]->text) + mem += strlen(ci->memos.memos[j]->text) + 1; } + if (ci->ttb) + mem += sizeof(*ci->ttb) * TTB_SIZE; + mem += ci->GetBadWordCount() * sizeof(BadWord); } *nrec = count; *memuse = mem; @@ -271,9 +271,9 @@ void chanserv(User * u, char *buf) if (!(s = strtok(NULL, ""))) { *s = 0; } - ircdproto->SendCTCP(findbot(Config.s_ChanServ), u->nick.c_str(), "PING %s", s); + ircdproto->SendCTCP(ChanServ, u->nick.c_str(), "PING %s", s); } else { - mod_run_cmd(Config.s_ChanServ, u, CHANSERV, cmd); + mod_run_cmd(ChanServ, u, cmd); } } @@ -632,15 +632,15 @@ void restore_topic(const char *chan) c->topic_setter = whosends(ci)->nick; } if (ircd->join2set) { - if (whosends(ci) == findbot(Config.s_ChanServ)) { - ircdproto->SendJoin(findbot(Config.s_ChanServ), chan, c->creation_time); + if (whosends(ci) == ChanServ) { + ircdproto->SendJoin(ChanServ, chan, c->creation_time); c->SetMode(NULL, CMODE_OP, Config.s_ChanServ); } } ircdproto->SendTopic(whosends(ci), c, c->topic_setter.c_str(), c->topic ? c->topic : ""); if (ircd->join2set) { - if (whosends(ci) == findbot(Config.s_ChanServ)) { - ircdproto->SendPart(findbot(Config.s_ChanServ), c, NULL); + if (whosends(ci) == ChanServ) { + ircdproto->SendPart(ChanServ, c, NULL); } } } @@ -692,8 +692,8 @@ int check_topiclock(Channel * c, time_t topic_time) } if (ircd->join2set) { - if (whosends(ci) == findbot(Config.s_ChanServ)) { - ircdproto->SendJoin(findbot(Config.s_ChanServ), c->name.c_str(), c->creation_time); + if (whosends(ci) == ChanServ) { + ircdproto->SendJoin(ChanServ, c->name.c_str(), c->creation_time); c->SetMode(NULL, CMODE_OP, Config.s_ChanServ); } } @@ -701,8 +701,8 @@ int check_topiclock(Channel * c, time_t topic_time) ircdproto->SendTopic(whosends(ci), c, c->topic_setter.c_str(), c->topic ? c->topic : ""); if (ircd->join2set) { - if (whosends(ci) == findbot(Config.s_ChanServ)) { - ircdproto->SendPart(findbot(Config.s_ChanServ), c, NULL); + if (whosends(ci) == ChanServ) { + ircdproto->SendPart(ChanServ, c, NULL); } } return 1; @@ -714,118 +714,113 @@ int check_topiclock(Channel * c, time_t topic_time) void expire_chans() { - ChannelInfo *ci, *next; - int i; - time_t now = time(NULL); - if (!Config.CSExpire) return; + + time_t now = time(NULL); - for (i = 0; i < 256; i++) { - for (ci = chanlists[i]; ci; ci = next) { - next = ci->next; - if (!ci->c && now - ci->last_used >= Config.CSExpire && !ci->HasFlag(CI_FORBIDDEN) && !ci->HasFlag(CI_NO_EXPIRE) && !ci->HasFlag(CI_SUSPENDED)) - { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreChanExpire, OnPreChanExpire(ci)); - if (MOD_RESULT == EVENT_STOP) - continue; + for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(); it != RegisteredChannelList.end();) + { + ChannelInfo *ci = it->second; + ++it; - char *chname = sstrdup(ci->name.c_str()); - Alog() << "Expiring channel " << ci->name << " (founder: " << (ci->founder ? ci->founder->display : "(none)") << " )"; - delete ci; - FOREACH_MOD(I_OnChanExpire, OnChanExpire(chname)); - delete [] chname; - } + if (!ci->c && now - ci->last_used >= Config.CSExpire && !ci->HasFlag(CI_FORBIDDEN) && !ci->HasFlag(CI_NO_EXPIRE) && !ci->HasFlag(CI_SUSPENDED)) + { + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreChanExpire, OnPreChanExpire(ci)); + if (MOD_RESULT == EVENT_STOP) + continue; + + char *chname = sstrdup(ci->name.c_str()); + Alog() << "Expiring channel " << ci->name << " (founder: " << (ci->founder ? ci->founder->display : "(none)") << " )"; + delete ci; + FOREACH_MOD(I_OnChanExpire, OnChanExpire(chname)); + delete [] chname; } } } /*************************************************************************/ -/* Remove a (deleted or expired) nickname from all channel lists. */ - +// XXX this is slightly inefficient void cs_remove_nick(const NickCore * nc) { - int i, j; - ChannelInfo *ci, *next; + int j; ChanAccess *ca; AutoKick *akick; - for (i = 0; i < 256; i++) { - for (ci = chanlists[i]; ci; ci = next) { - next = ci->next; - if (ci->founder == nc) { - if (ci->successor) { - NickCore *nc2 = ci->successor; - if (!nc2->IsServicesOper() && Config.CSMaxReg && nc2->channelcount >= Config.CSMaxReg) { - Alog() << Config.s_ChanServ << ": Successor (" << nc2->display << " ) of " << ci->name << " owns too many channels, deleting channel", - delete ci; - continue; - } else { - Alog() << Config.s_ChanServ << ": Transferring foundership of " << ci->name << " from deleted nick " << nc->display << " to successor " << nc2->display; - ci->founder = nc2; - ci->successor = NULL; - nc2->channelcount++; - } + for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(); it != RegisteredChannelList.end(); ++it) + { + ChannelInfo *ci = it->second; + + if (ci->founder == nc) { + if (ci->successor) { + NickCore *nc2 = ci->successor; + if (!nc2->IsServicesOper() && Config.CSMaxReg && nc2->channelcount >= Config.CSMaxReg) { + Alog() << Config.s_ChanServ << ": Successor (" << nc2->display << " ) of " << ci->name << " owns too many channels, deleting channel", + delete ci; + continue; } else { - Alog() << Config.s_ChanServ << ": Deleting channel " << ci->name << "owned by deleted nick " << nc->display; + Alog() << Config.s_ChanServ << ": Transferring foundership of " << ci->name << " from deleted nick " << nc->display << " to successor " << nc2->display; + ci->founder = nc2; + ci->successor = NULL; + nc2->channelcount++; + } + } else { + Alog() << Config.s_ChanServ << ": Deleting channel " << ci->name << "owned by deleted nick " << nc->display; - if ((ModeManager::FindChannelModeByName(CMODE_REGISTERED))) + if ((ModeManager::FindChannelModeByName(CMODE_REGISTERED))) + { + /* Maybe move this to delchan() ? */ + if (ci->c && ci->c->HasMode(CMODE_REGISTERED)) { - /* Maybe move this to delchan() ? */