]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - include/inspircd.h
This is a bit better
[user/henk/code/inspircd.git] / include / inspircd.h
index 44f5b519c41a415d42e5d7b3a92af7d07fe12978..5e9bed45dea9afd4b490a8ab979d239e95a19f07 100644 (file)
@@ -2,14 +2,11 @@
  *       | Inspire Internet Relay Chat Daemon |
  *       +------------------------------------+
  *
- *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
- *                    E-mail:
- *             <brain@chatspike.net>
- *               <Craig@chatspike.net>
- *     
- * Written by Craig Edwards, Craig McLure, and others.
+ *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
  * This program is free but copyrighted software; see
- *         the file COPYING for details.
+ *            the file COPYING for details.
  *
  * ---------------------------------------------------
  */
 #include "channels.h"
 #include "socket.h"
 #include "mode.h"
-
 #include "socketengine.h"
 #include "command_parse.h"
+#include "snomasks.h"
 
-/** Returned by some functions to indicate failure,
- * and the exit code of the program if it terminates.
+/** Returned by some functions to indicate failure.
  */
 #define ERROR -1
 
-/** Crucial defines
+/** Support for librodent -
+ * see http://www.chatspike.net/index.php?z=64
  */
-#define ETIREDGERBILS EAGAIN
+#define ETIREDHAMSTERS EAGAIN
 
 /** Debug levels for use with InspIRCd::Log()
  */
@@ -59,17 +56,88 @@ enum DebugLevel
 
 /** Delete a pointer, and NULL its value
  */
-#define DELETE(x) {if (x) { delete x; x = NULL; }}
+template<typename T> inline void DELETE(T* x)
+{
+       delete x;
+       x = NULL;
+}
 
-/** Template function to convert any input type to std::string
+/** Template functions to convert any input type to std::string
  */
-template<typename T> inline std::string ConvToStr(const T &in)
+template<typename N> std::string ConvNumeric(N in)
+{
+       char res[MAXBUF];
+       char* out = res;
+       long quotient = in;
+       while (quotient) {
+               *out = "0123456789"[ std::abs( quotient % 10 ) ];
+               ++out;
+               quotient /= 10;
+       }
+       if ( in < 0)
+               *out++ = '-';
+       *out = 0;
+       return std::reverse(res,out);
+}
+
+template <int> inline std::string ConvToStr(const int in)
+{
+       return ConvNumeric(in);
+}
+
+template <long> inline std::string ConvToStr(const long in)
+{
+       return ConvNumeric(in);
+}
+
+template <unsigned long> inline std::string ConvToStr(const unsigned long in)
+{
+       return ConvNumeric(in);
+}
+
+template <const char*> inline std::string ConvToStr(const char* in)
+{
+       return in;
+}
+
+template <bool> inline std::string ConvToStr(const long in)
+{
+       return (in ? "1" : "0");
+}
+
+template <typename T> inline std::string ConvToStr(const T &in)
 {
        std::stringstream tmp;
        if (!(tmp << in)) return std::string();
        return tmp.str();
 }
 
+template<typename T> inline long ConvToInt(const T &in)
+{
+       std::stringstream tmp;
+       if (!(tmp << in)) return 0;
+       return atoi(tmp.str().c_str());
+}
+
+/** Template function to convert integer to char, storing result in *res and
+ * also returning the pointer to res. Based on Stuart Lowe's C/C++ Pages.
+ */
+template<typename T, typename V, typename R> inline char* itoa(const T &in, V *res, R base)
+{
+       if (base < 2 || base > 16) { *res = 0; return res; }
+       char* out = res;
+       int quotient = in;
+       while (quotient) {
+               *out = "0123456789abcdef"[ std::abs( quotient % base ) ];
+               ++out;
+               quotient /= base;
+       }
+       if ( in < 0 && base == 10) *out++ = '-';
+       std::reverse( res, out );
+       *out = 0;
+       return res;
+}
+
 /** This class contains various STATS counters
  * It is used by the InspIRCd class, which internally
  * has an instance of it.
@@ -115,6 +183,14 @@ class serverstats : public classbase
         */
        unsigned long BoundPortCount;
 
+       /** Cpu usage at last sample
+        */
+       timeval LastCPU;
+
+       /** Time last sample was read
+        */
+       timeval LastSampled;
+
        /** The constructor initializes all the counts to zero
         */
        serverstats()
@@ -125,9 +201,76 @@ class serverstats : public classbase
        }
 };
 
+class InspIRCd;
+
+/** This class implements a nonblocking log-writer.
+ * Most people writing an ircd give little thought to their disk
+ * i/o. On a congested system, disk writes can block for long
+ * periods of time (e.g. if the system is busy and/or swapping
+ * a lot). If we just use a blocking fprintf() call, this could
+ * block for undesirable amounts of time (half of a second through
+ * to whole seconds). We DO NOT want this, so we make our logfile
+ * nonblocking and hook it into the SocketEngine.
+ * NB: If the operating system does not support nonblocking file
+ * I/O (linux seems to, as does freebsd) this will default to
+ * blocking behaviour.
+ */
+class FileLogger : public EventHandler
+{
+ protected:
+       /** The creator/owner of this object
+        */
+       InspIRCd* ServerInstance;
+       /** The log file (fd is inside this somewhere,
+        * we get it out with fileno())
+        */
+       FILE* log;
+       /** Buffer of pending log lines to be written
+        */
+       std::string buffer;
+       /** Number of write operations that have occured
+        */
+       int writeops;
+ public:
+       /** The constructor takes an already opened logfile.
+        */
+       FileLogger(InspIRCd* Instance, FILE* logfile);
+       /** This returns false, logfiles are writeable.
+        */
+       virtual bool Readable();
+       /** Handle pending write events.
+        * This will flush any waiting data to disk.
+        * If any data remains after the fprintf call,
+        * another write event is scheduled to write
+        * the rest of the data when possible.
+        */
+       virtual void HandleEvent(EventType et, int errornum = 0);
+       /** Write one or more preformatted log lines.
+        * If the data cannot be written immediately,
+        * this class will insert itself into the
+        * SocketEngine, and register a write event,
+        * and when the write event occurs it will
+        * attempt again to write the data.
+        */
+       void WriteLogLine(const std::string &line);
+       /** Close the log file and cancel any events.
+        */
+       virtual void Close();
+       /** Close the log file and cancel any events.
+        * (indirectly call Close()
+        */
+       virtual ~FileLogger();
+};
+
+/** A list of failed port bindings, used for informational purposes on startup */
+typedef std::vector<std::pair<std::string, long> > FailedPortList;
+
+/** A list of ip addresses cross referenced against clone counts */
+typedef std::map<irc::string, unsigned int> clonemap;
+
 class XLineManager;
 
-/** The main singleton class of the irc server.
+/** The main class of the irc server.
  * This class contains instances of all the other classes
  * in this software, with the exception of the base class,
  * classbase. Amongst other things, it contains a ModeParser,
@@ -146,14 +289,6 @@ class InspIRCd : public classbase
        /** Holds a string describing the last module error to occur
         */
        char MODERR[MAXBUF];
-
-       /** This is an internal flag used by the mainloop
-        */
-       bool expire_run;
-
-       /** List of server names we've seen.
-        */
-       servernamelist servernames;
  
        /** Remove a ModuleFactory pointer
         * @param j Index number of the ModuleFactory to remove
@@ -180,9 +315,8 @@ class InspIRCd : public classbase
        void Start();
 
        /** Set up the signal handlers
-        * @param SEGVHandler create a handler for segfaults (deprecated)
         */
-       void SetSignals(bool SEGVHandler);
+       void SetSignals();
 
        /** Daemonize the ircd and close standard input/output streams
         * @return True if the program daemonized succesfully
@@ -239,6 +373,10 @@ class InspIRCd : public classbase
         */
        featurelist Features;
 
+       /** The interface names published by various modules
+        */
+       interfacelist Interfaces;
+
        /** The current time, updated in the mainloop
         */
        time_t TIME;
@@ -279,11 +417,26 @@ class InspIRCd : public classbase
         */
        socklen_t length;
 
-       /** Used to count iterations around the mainloop
+       /** Nonblocking file writer
+        */
+       FileLogger* Logger;
+
+       /** Time offset in seconds
+        * This offset is added to all calls to Time(). Use SetTimeDelta() to update
         */
-       int iterations;
+       int time_delta;
 
  public:
+
+       /** Number of unregistered users online right now.
+        * (Unregistered means before USER/NICK/dns)
+        */
+       int unregistered_count;
+
+        /** List of server names we've seen.
+        */
+       servernamelist servernames;
+
        /** Time this ircd was booted
         */
        time_t startup_time;
@@ -308,17 +461,18 @@ class InspIRCd : public classbase
         */
        ServerConfig* Config;
 
-       /** Module sockets list, holds the active set of InspSocket classes
+       /** Snomask manager - handles routing of snomask messages
+        * to opers.
         */
-       std::vector<InspSocket*> module_sockets;
+       SnomaskManager* SNO;
 
        /** Client list, a hash_map containing all clients, local and remote
         */
-       user_hash clientlist;
+       user_hash* clientlist;
 
        /** Channel list, a hash_map containing all channels
         */
-       chan_hash chanlist;
+       chan_hash* chanlist;
 
        /** Local client list, a vector containing only local clients
         */
@@ -328,9 +482,9 @@ class InspIRCd : public classbase
         */
        std::vector<userrec*> all_opers;
 
-       /** Whowas container, contains a map of vectors of users tracked by WHOWAS
-        */
-       irc::whowas::whowas_users whowas;
+       clonemap local_clones;
+
+       clonemap global_clones;
 
        /** DNS class, provides resolver facilities to the core and modules
         */
@@ -356,12 +510,38 @@ class InspIRCd : public classbase
         */
        FactoryList factory;
 
+       /** The time we next call our ping timeout and reg timeout checks
+        */
+       time_t next_call;
+
        /** Get the current time
         * Because this only calls time() once every time around the mainloop,
         * it is much faster than calling time() directly.
+        * @param delta True to use the delta as an offset, false otherwise
         * @return The current time as an epoch value (time_t)
         */
-       time_t Time();
+       time_t Time(bool delta = false);
+
+       /** Set the time offset in seconds
+        * This offset is added to Time() to offset the system time by the specified
+        * number of seconds.
+        * @param delta The number of seconds to offset
+        * @return The old time delta
+        */
+       int SetTimeDelta(int delta);
+
+       void AddLocalClone(userrec* user);
+
+       void AddGlobalClone(userrec* user);
+
+       /** Number of users with a certain mode set on them
+        */
+       int ModeCount(const char mode);
+
+       /** Get the time offset in seconds
+        * @return The current time delta (in seconds)
+        */
+       int GetTimeDelta();
 
        /** Process a user whos socket has been flagged as active
         * @param cu The user to process
@@ -383,9 +563,10 @@ class InspIRCd : public classbase
 
        /** Bind all ports specified in the configuration file.
         * @param bail True if the function should bail back to the shell on failure
+        * @param found_ports The actual number of ports found in the config, as opposed to the number actually bound
         * @return The number of ports actually bound without error
         */
-       int BindPorts(bool bail);
+       int BindPorts(bool bail, int &found_ports, FailedPortList &failed_ports);
 
        /** Returns true if this server has the given port bound to the given address
         * @param port The port number
@@ -486,6 +667,8 @@ class InspIRCd : public classbase
         */
        void OpenLog(char** argv, int argc);
 
+       void CloseLog();
+
        /** Convert a user to a pseudoclient, disconnecting the real user
         * @param user The user to convert
         * @param message The quit message to display when exiting the user
@@ -536,6 +719,7 @@ class InspIRCd : public classbase
 
        /** Causes the server to exit immediately
         * @param The exit code to give to the operating system
+        * (See the ExitStatus enum for valid values)
         */
        static void Exit(int status);
 
@@ -577,7 +761,7 @@ class InspIRCd : public classbase
        /** Send an error notice to all local users, opered and unopered
         * @param s The error string to send
         */
-       void SendError(const char *s);
+       void SendError(const std::string &s);
 
        /** For use with Module::Prioritize().
         * When the return value of this function is returned from
@@ -615,6 +799,47 @@ class InspIRCd : public classbase
         */
        bool PublishFeature(const std::string &FeatureName, Module* Mod);
 
+       /** Publish a module to an 'interface'.
+        * Modules which implement the same interface (the same way of communicating
+        * with other modules) can publish themselves to an interface, using this
+        * method. When they do so, they become part of a list of related or
+        * compatible modules, and a third module may then query for that list
+        * and know that all modules within that list offer the same API.
+        * A prime example of this is the hashing modules, which all accept the
+        * same types of Request class. Consider this to be similar to PublishFeature,
+        * except for that multiple modules may publish the same 'feature'.
+        * @param InterfaceName The case sensitive interface name to make available
+        * @param Mod a pointer to your module class
+        * @returns True on success, false on failure (there are currently no failure
+        * cases)
+        */
+       bool PublishInterface(const std::string &InterfaceName, Module* Mod);
+
+       /** Return a pair saying how many other modules are currently using the
+        * interfaces provided by module m.
+        * @param m The module to count usage for
+        * @return A pair, where the first value is the number of uses of the interface,
+        * and the second value is the interface name being used.
+        */
+       std::pair<int,std::string> GetInterfaceInstanceCount(Module* m);
+
+       /** Mark your module as using an interface.
+        * If you mark your module as using an interface, then that interface
+        * module may not unload until your module has unloaded first.
+        * This can be used to prevent crashes by ensuring code you depend on
+        * is always in memory while your module is active.
+        * @param InterfaceName The interface to use
+        */
+       void UseInterface(const std::string &InterfaceName);
+
+       /** Mark your module as finished with an interface.
+        * If you used UseInterface() above, you should use this method when
+        * your module is finished with the interface (usually in its destructor)
+        * to allow the modules which implement the given interface to be unloaded.
+        * @param InterfaceName The interface you are finished with using.
+        */
+       void DoneWithInterface(const std::string &InterfaceName);
+
        /** Unpublish a 'feature'.
         * When your module exits, it must call this method for every feature it
         * is providing so that the feature table is cleaned up.
@@ -622,6 +847,16 @@ class InspIRCd : public classbase
         */
        bool UnpublishFeature(const std::string &FeatureName);
 
+       /** Unpublish your module from an interface
+        * When your module exits, it must call this method for every interface
+        * it is part of so that the interfaces table is cleaned up. Only when
+        * the last item is deleted from an interface does the interface get
+        * removed.
+        * @param InterfaceName the interface to be removed from
+        * @param Mod The module to remove from the interface list
+        */
+       bool UnpublishInterface(const std::string &InterfaceName, Module* Mod);
+
        /** Find a 'feature'.
         * There are two ways for a module to find another module it depends on.
         * Either by name, using InspIRCd::FindModule, or by feature, using the
@@ -636,6 +871,15 @@ class InspIRCd : public classbase
         */
        Module* FindFeature(const std::string &FeatureName);
 
+       /** Find an 'interface'.
+        * An interface is a list of modules which all implement the same API.
+        * @param InterfaceName The Interface you wish to obtain the module
+        * list of.
+        * @return A pointer to a deque of Module*, or NULL if the interface
+        * does not exist.
+        */
+       modulelist* FindInterface(const std::string &InterfaceName);
+
        /** Given a pointer to a Module, return its filename
         * @param m The module pointer to identify
         * @return The module name or an empty string
@@ -682,9 +926,21 @@ class InspIRCd : public classbase
 
        /** Add a dns Resolver class to this server's active set
         * @param r The resolver to add
-        * @return True if the resolver was added
-        */
-        bool AddResolver(Resolver* r);
+        * @param cached If this value is true, then the cache will
+        * be searched for the DNS result, immediately. If the value is
+        * false, then a request will be sent to the nameserver, and the
+        * result will not be immediately available. You should usually
+        * use the boolean value which you passed to the Resolver
+        * constructor, which Resolver will set appropriately depending
+        * on if cached results are available and haven't expired. It is
+        * however safe to force this value to false, forcing a remote DNS
+        * lookup, but not an update of the cache.
+        * @return True if the operation completed successfully. Note that
+        * if this method returns true, you should not attempt to access
+        * the resolver class you pass it after this call, as depending upon
+        * the request given, the object may be deleted!
+        */
+        bool AddResolver(Resolver* r, bool cached);
 
        /** Add a command to this server's command parser
         * @param f A command_t command handler object to add
@@ -803,21 +1059,6 @@ class InspIRCd : public classbase
         */
         bool IsValidMask(const std::string &mask);
 
-       /** Add an InspSocket class to the active set
-        * @param sock A socket to add to the active set
-        */
-        void AddSocket(InspSocket* sock);
-
-       /** Remove an InspSocket class from the active set at next time around the loop
-        * @param sock A socket to remove from the active set
-        */
-        void RemoveSocket(InspSocket* sock);
-
-       /** Delete a socket immediately without waiting for the next iteration of the mainloop
-        * @param sock A socket to delete from the active set
-        */
-        void DelSocket(InspSocket* sock);
-
        /** Rehash the local server
         */
         void RehashServer();
@@ -868,9 +1109,10 @@ class InspIRCd : public classbase
         * against possible hashed equivalents in the input string.
         * @param data The data from the config file
         * @param input The data input by the oper
+        * @param tagnum the tag number of the oper's tag in the config file
         * @return 0 if the strings match, 1 or -1 if they do not
         */
-       int OperPassCompare(const char* data,const char* input);
+       int OperPassCompare(const char* data,const char* input, int tagnum);
 
        /** Check if a given server is a uline.
         * An empty string returns true, this is by design.
@@ -944,6 +1186,35 @@ class InspIRCd : public classbase
         */
        void Log(int level, const std::string &text);
 
+       void SendWhoisLine(userrec* user, userrec* dest, int numeric, const std::string &text);
+
+       void SendWhoisLine(userrec* user, userrec* dest, int numeric, const char* format, ...);
+
+       /** Restart the server.
+        * This function will not return. If an error occurs,
+        * it will throw an instance of CoreException.
+        * @param reason The restart reason to show to all clients
+        * @throw CoreException An instance of CoreException indicating the error from execv().
+        */
+       void Restart(const std::string &reason);
+
+       /** Prepare the ircd for restart or shutdown.
+        * This function unloads all modules which can be unloaded,
+        * closes all open sockets, and closes the logfile.
+        */
+       void Cleanup();
+
+       /** This copies the user and channel hash_maps into new hash maps.
+        * This frees memory used by the hash_map allocator (which it neglects
+        * to free, most of the time, using tons of ram)
+        */
+       void RehashUsersAndChans();
+
+       /** Resets the cached max bans value on all channels.
+        * Called by rehash.
+        */
+       void ResetMaxBans();
+
        /** Begin execution of the server.
         * NOTE: this function NEVER returns. Internally,
         * after performing some initialisation routines,