summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2006-08-18 01:08:14 +0000
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2006-08-18 01:08:14 +0000
commite381b06561228aaea752deda20a62c6dc99a560e (patch)
tree2119fe8bc8895597261935f389004e3c6bafe6a8
parent3c82d2d767186dd6d386dbbe08219ad8612e299e (diff)
EventHandler class, an abstraction for raw i/o
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@4941 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r--include/configreader.h4
-rw-r--r--include/connection.h15
-rw-r--r--include/dns.h18
-rw-r--r--include/inspircd.h20
-rw-r--r--include/inspsocket.h12
-rw-r--r--include/modules.h6
-rw-r--r--include/socket.h11
-rw-r--r--include/socketengine.h206
-rw-r--r--include/socketengine_epoll.h6
-rw-r--r--include/socketengine_kqueue.h6
-rw-r--r--include/socketengine_select.h6
-rw-r--r--include/users.h5
-rw-r--r--src/channels.cpp4
-rw-r--r--src/cmd_notice.cpp2
-rw-r--r--src/cmd_privmsg.cpp2
-rw-r--r--src/cmd_quit.cpp9
-rw-r--r--src/dns.cpp133
-rw-r--r--src/inspircd.cpp142
-rw-r--r--src/inspsocket.cpp56
-rw-r--r--src/modules.cpp16
-rw-r--r--src/modules/extra/m_pgsql.cpp7
-rw-r--r--src/modules/m_cgiirc.cpp10
-rw-r--r--src/modules/m_ident.cpp14
-rw-r--r--src/modules/m_samode.cpp2
-rw-r--r--src/modules/m_spanningtree.cpp14
-rw-r--r--src/modules/m_timedbans.cpp2
-rw-r--r--src/socket.cpp128
-rw-r--r--src/socketengine.cpp51
-rw-r--r--src/socketengine_epoll.cpp31
-rw-r--r--src/socketengine_kqueue.cpp24
-rw-r--r--src/socketengine_select.cpp22
-rw-r--r--src/userprocess.cpp19
-rw-r--r--src/users.cpp23
33 files changed, 518 insertions, 508 deletions
diff --git a/include/configreader.h b/include/configreader.h
index a63e31d71..467b5bde3 100644
--- a/include/configreader.h
+++ b/include/configreader.h
@@ -25,6 +25,8 @@
#include "inspircd.h"
#include "globals.h"
#include "modules.h"
+#include "socketengine.h"
+#include "socket.h"
class ServerConfig;
class InspIRCd;
@@ -310,7 +312,7 @@ class ServerConfig : public Extensible
/** A list of the file descriptors for the listening client ports
*/
- int openSockfd[MAX_DESCRIPTORS];
+ ListenSocket* openSockfd[255];
/** Boolean sets of which modules implement which functions
*/
diff --git a/include/connection.h b/include/connection.h
index bb9f7a580..55d6204a1 100644
--- a/include/connection.h
+++ b/include/connection.h
@@ -20,18 +20,14 @@
#include <time.h>
#include "inspircd_config.h"
#include "base.h"
+#include "socketengine.h"
/** connection is the base class of userrec, and holds basic user properties.
* This can be extended for holding other user-like objects in the future.
*/
-class connection : public Extensible
+class connection : public EventHandler
{
public:
- /** File descriptor of the connection.
- * For a remote connection, this will have a negative value.
- */
- int fd;
-
/** Hostname of connection.
* This should be valid as per RFC1035.
*/
@@ -80,13 +76,6 @@ class connection : public Extensible
/** Used by PING checking code
*/
time_t nping;
-
- /** Default constructor, creates the user as remote.
- */
- connection()
- {
- this->fd = -1;
- }
};
diff --git a/include/dns.h b/include/dns.h
index c3b74fdca..6c690dc87 100644
--- a/include/dns.h
+++ b/include/dns.h
@@ -37,8 +37,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include <string>
#include "inspircd_config.h"
-#include "socket.h"
#include "base.h"
+#include "socketengine.h"
+#include "socket.h"
using namespace std;
using irc::sockets::insp_aton;
@@ -225,7 +226,7 @@ class Resolver : public Extensible
* back to Resolver objects, based upon the request ID. You
* should never use this class yourself.
*/
-class DNS : public Extensible
+class DNS : public EventHandler
{
private:
@@ -248,11 +249,6 @@ class DNS : public Extensible
insp_inaddr myserver;
/**
- * File descriptor being used to perform queries
- */
- static int MasterSocket;
-
- /**
* A counter used to form part of the pseudo-random id
*/
int currid;
@@ -295,11 +291,6 @@ class DNS : public Extensible
*/
static void EmptyHeader(unsigned char *output, const DNSHeader *header, const int length);
/**
- * Get the master socket fd, used internally
- */
- static int GetMasterSocket();
-
- /**
* Start the lookup of an ipv4 from a hostname
*/
int GetIP(const char* name);
@@ -337,8 +328,9 @@ class DNS : public Extensible
/**
* Handle a SocketEngine read event
+ * Inherited from EventHandler
*/
- void MarshallReads(int fd);
+ void HandleEvent(EventType et);
/**
* Add a Resolver* to the list of active classes
diff --git a/include/inspircd.h b/include/inspircd.h
index f404cce80..77a1e45ac 100644
--- a/include/inspircd.h
+++ b/include/inspircd.h
@@ -215,12 +215,6 @@ class InspIRCd : public classbase
*/
void MoveBefore(std::string modulename, std::string before);
- /** Process a user whos socket has been flagged as active
- * @param cu The user to process
- * @return There is no actual return value, however upon exit, the user 'cu' may have been deleted
- */
- void ProcessUser(userrec* cu);
-
/** Iterate the list of InspSocket objects, removing ones which have timed out
* @param TIME the current time
*/
@@ -322,14 +316,6 @@ class InspIRCd : public classbase
*/
std::vector<InspSocket*> module_sockets;
- /** Socket reference table, provides fast lookup of fd to InspSocket*
- */
- InspSocket* socket_ref[MAX_DESCRIPTORS];
-
- /** user reference table, provides fast lookup of fd to userrec*
- */
- userrec* fd_ref_table[MAX_DESCRIPTORS];
-
/** Client list, a hash_map containing all clients, local and remote
*/
user_hash clientlist;
@@ -381,6 +367,12 @@ class InspIRCd : public classbase
*/
time_t Time();
+ /** Process a user whos socket has been flagged as active
+ * @param cu The user to process
+ * @return There is no actual return value, however upon exit, the user 'cu' may have been deleted
+ */
+ void ProcessUser(userrec* cu);
+
/** Get the total number of currently loaded modules
* @return The number of loaded modules
*/
diff --git a/include/inspsocket.h b/include/inspsocket.h
index ddb0baedb..3791aa3e0 100644
--- a/include/inspsocket.h
+++ b/include/inspsocket.h
@@ -23,6 +23,7 @@
#include "dns.h"
#include "inspircd_config.h"
#include "socket.h"
+#include "inspsocket.h"
/**
* States which a socket may be in
@@ -53,7 +54,7 @@ using irc::sockets::insp_aton;
* and use the InspSocket constructors to establish connections
* and bindings.
*/
-class InspSocket : public Extensible
+class InspSocket : public EventHandler
{
public:
InspIRCd* Instance;
@@ -61,11 +62,6 @@ class InspSocket : public Extensible
std::deque<std::string> outbuffer;
/**
- * The file descriptor of this socket
- */
- int fd;
-
- /**
* The hostname connected to
*/
char host[MAXBUF];
@@ -365,6 +361,10 @@ class InspSocket : public Extensible
* memory reclaimed.
*/
void MarkAsClosed();
+
+ void HandleEvent(EventType et);
+
+ bool Readable();
};
#endif
diff --git a/include/modules.h b/include/modules.h
index aa36bed3a..87d76e668 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -166,9 +166,9 @@ typedef std::map<std::string,Module*> featurelist;
// useful macros
-#define IS_LOCAL(x) ((x->fd > -1) && (x->fd <= MAX_DESCRIPTORS))
-#define IS_REMOTE(x) (x->fd < 0)
-#define IS_MODULE_CREATED(x) (x->fd == FD_MAGIC_NUMBER)
+#define IS_LOCAL(x) ((x->GetFd() > -1) && (x->GetFd() <= MAX_DESCRIPTORS))
+#define IS_REMOTE(x) (x->GetFd() < 0)
+#define IS_MODULE_CREATED(x) (x->GetFd() == FD_MAGIC_NUMBER)
/** Holds a module's Version information
* The four members (set by the constructor only) indicate details as to the version number
diff --git a/include/socket.h b/include/socket.h
index 8fd2df0df..c00c7f131 100644
--- a/include/socket.h
+++ b/include/socket.h
@@ -26,10 +26,10 @@
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
-#include <poll.h>
#include <netdb.h>
#include <errno.h>
#include "inspircd_config.h"
+#include "socketengine.h"
namespace irc
{
@@ -138,4 +138,13 @@ namespace irc
};
};
+class ListenSocket : public EventHandler
+{
+ protected:
+ InspIRCd* ServerInstance;
+ public:
+ ListenSocket(InspIRCd* Instance, int sockfd, irc::sockets::insp_sockaddr client, irc::sockets::insp_sockaddr server, int port, char* addr);
+ void HandleEvent(EventType et);
+};
+
#endif
diff --git a/include/socketengine.h b/include/socketengine.h
index 5ccfa801e..fd01b4cf8 100644
--- a/include/socketengine.h
+++ b/include/socketengine.h
@@ -21,34 +21,103 @@
#include <string>
#include <map>
#include "inspircd_config.h"
-#include "globals.h"
-#include "inspircd.h"
-
-/**
- * Each of these values represents a socket
- * type in our reference table (the reference
- * table itself is only accessible to
- * socketengine.cpp)
- */
-const char X_EMPTY_SLOT = 0;
-const char X_LISTEN = 1;
-const char X_ESTAB_CLIENT = 2;
-const char X_ESTAB_MODULE = 3;
-const char X_ESTAB_DNS = 4;
-
-/**
- * To indicate that a socket is readable, we
- * mask its top bit with this X_READBIT value.
- * The socket engine can handle two types of
- * socket, readable and writeable (;error sockets
- * are dealt with when read() and write() return
- * negative or zero values).
+#include "base.h"
+
+/** Types of event an EventHandler may receive.
+ * EVENT_READ is a readable file descriptor,
+ * and EVENT_WRITE is a writeable file descriptor.
*/
-const char X_READBIT = 0x80;
+enum EventType
+{
+ EVENT_READ = 0,
+ EVENT_WRITE = 1
+};
class InspIRCd;
-/**
+/** This class is a basic I/O handler class.
+ * Any object which wishes to receive basic I/O events
+ * from the socketengine must derive from this class and
+ * implement the HandleEvent() method. The derived class
+ * must then be added to SocketEngine using the method
+ * SocketEngine::AddFd(), after which point the derived
+ * class will receive events to its HandleEvent() method.
+ * The derived class should also implement one of Readable()
+ * and Writeable(). In the current implementation, only
+ * Readable() is used. If this returns true, the socketengine
+ * inserts a readable socket. If it is false, the socketengine
+ * inserts a writeable socket. The derived class should never
+ * change the value this function returns without first
+ * deleting the socket from the socket engine. The only
+ * requirement beyond this for an event handler is that it
+ * must have a file descriptor. What this file descriptor
+ * is actually attached to is completely up to you.
+ */
+class EventHandler : public Extensible
+{
+ protected:
+ /** File descriptor.
+ * All events which can be handled
+ * must have a file descriptor.
+ * This allows you to add events for
+ * sockets, fifo's, pipes, and various
+ * other forms of IPC.
+ */
+ int fd;
+ public:
+ /** Get the current file descriptor
+ * @return The file descriptor of this handler
+ */
+ int GetFd();
+
+ /** Set a new file desciptor
+ * @param FD The new file descriptor. Do not
+ * call this method without first deleting the
+ * object from the SocketEngine if you have
+ * added it to a SocketEngine instance.
+ */
+ void SetFd(int FD);
+
+ /** Constructor
+ */
+ EventHandler() {}
+
+ /** Destructor
+ */
+ virtual ~EventHandler() {}
+
+ /** Override this function to indicate readability.
+ * @return This should return true if the function
+ * wishes to receive EVENT_READ events. Do not change
+ * what this function returns while the event handler
+ * is still added to a SocketEngine instance!
+ * If this function is unimplemented, the base class
+ * will return true.
+ */
+ virtual bool Readable();
+
+ /** Override this function to indicate writeability.
+ * @return This should return true if the function
+ * wishes to receive EVENT_WRITE events. Do not change
+ * what this function returns while the event handler
+ * is still added to a SocketEngine instance!
+ * If this function is unimplemented, the base class
+ * will return false.
+ */
+ virtual bool Writeable();
+
+ /** Process an I/O event.
+ * You MUST implement this function in your derived
+ * class, and it will be called whenever read or write
+ * events are received, depending on what your functions
+ * Readable() and Writeable() returns.
+ * @param et either one of EVENT_READ for read events,
+ * and EVENT_WRITE for write events.
+ */
+ virtual void HandleEvent(EventType et) = 0;
+};
+
+/** Provides basic file-descriptor-based I/O support.
* The actual socketengine class presents the
* same interface on all operating systems, but
* its private members and internal behaviour
@@ -69,84 +138,103 @@ class InspIRCd;
class SocketEngine : public Extensible
{
protected:
+ /** Owner/Creator
+ */
InspIRCd* ServerInstance;
- int EngineHandle; /* Handle to the socket engine if needed */
- int CurrentSetSize; /* Current number of descriptors in the engine */
- char ref[MAX_DESCRIPTORS]; /* Reference table */
+ /** Handle to socket engine, where needed.
+ */
+ int EngineHandle;
+ /** Current number of descriptors in the engine
+ */
+ int CurrentSetSize;
+ /** Reference table, contains all current handlers
+ */
+ EventHandler* ref[MAX_DESCRIPTORS];
public:
- /** Constructor
+ /** Constructor.
* The constructor transparently initializes
* the socket engine which the ircd is using.
* Please note that if there is a catastrophic
* failure (for example, you try and enable
* epoll on a 2.4 linux kernel) then this
* function may bail back to the shell.
+ * @param Instance The creator/owner of this object
*/
SocketEngine(InspIRCd* Instance);
- /** Destructor
+ /** Destructor.
* The destructor transparently tidies up
* any resources used by the socket engine.
*/
virtual ~SocketEngine();
- /** Add a file descriptor to the engine
+ /** Add an EventHandler object to the engine.
* Use AddFd to add a file descriptor to the
* engine and have the socket engine monitor
- * it. You must provide a type (see the consts
- * in socketengine.h) and a boolean flag to
- * indicate wether to watch this fd for read
- * or write events (there is currently no
- * need for support of both).
- */
- virtual bool AddFd(int fd, bool readable, char type);
-
- /** Returns the type value for this file descriptor
- * This function masks off the X_READBIT value
- * so that the type of the socket can be obtained.
- * The core uses this to decide where to dispatch
- * the event to. Please note that some engines
- * such as select() have an upper limit of 1024
- * descriptors which may be active at any one time,
- * where others such as kqueue have no practical
- * limits at all.
- */
- char GetType(int fd);
+ * it. You must provide an object derived from
+ * EventHandler which implements HandleEvent()
+ * and optionally Readable() and Writeable().
+ * @param eh An event handling object to add
+ */
+ virtual bool AddFd(EventHandler* eh);
/** Returns the maximum number of file descriptors
* you may store in the socket engine at any one time.
+ * @return The maximum fd value
*/
virtual int GetMaxFds();
/** Returns the number of file descriptor slots
* which are available for storing fds.
+ * @return The number of remaining fd's
*/
virtual int GetRemainingFds();
- /** Delete a file descriptor from the engine
- * This function call deletes a file descriptor
+ /** Delete an event handler from the engine.
+ * This function call deletes an EventHandler
* from the engine, returning true if it succeeded
- * and false if it failed.
+ * and false if it failed. This does not free the
+ * EventHandler pointer using delete, if this is
+ * required you must do this yourself.
+ * @param eh The event handler object to remove
+ * @return True if the event handler was removed
*/
- virtual bool DelFd(int fd);
+ virtual bool DelFd(EventHandler* eh);
- /** Returns true if a socket exists in the socket
- * engine's list.
+ /** Returns true if a file descriptor exists in
+ * the socket engine's list.
+ * @param fd The event handler to look for
+ * @return True if this fd has an event handler
*/
bool HasFd(int fd);
+ /** Returns the EventHandler attached to a specific fd.
+ * If the fd isnt in the socketengine, returns NULL.
+ * @param fd The event handler to look for
+ * @return A pointer to the event handler, or NULL
+ */
+ EventHandler* GetRef(int fd);
+
/** Waits for an event.
* Please note that this doesnt wait long, only
* a couple of milliseconds. It returns a list
- * of active file descriptors in the vector
- * fdlist which the core may then act upon.
+ * of active EventHandlers in the array fdlist
+ * which the core will then dispatch events to
+ * by calling their EventHandler::HandleEvent()
+ * methods with the neccessary EventType value.
+ * @param fdlist A pointer to a set of EventHandler
+ * classes. You should ensure that the array you pass
+ * is at least MAX_DESCRIPTORS in size, to accomodate
+ * for the maximum number of events which can occur.
+ * @return The number of events which have occured.
*/
- virtual int Wait(int* fdlist);
+ virtual int Wait(EventHandler** fdlist);
- /** Returns the socket engines name
+ /** Returns the socket engines name.
* This returns the name of the engine for use
* in /VERSION responses.
+ * @return The socket engine name
*/
virtual std::string GetName();
};
diff --git a/include/socketengine_epoll.h b/include/socketengine_epoll.h
index f675671e2..04ede734d 100644
--- a/include/socketengine_epoll.h
+++ b/include/socketengine_epoll.h
@@ -45,11 +45,11 @@ public:
/** Delete an EPollEngine
*/
virtual ~EPollEngine();
- virtual bool AddFd(int fd, bool readable, char type);
+ virtual bool AddFd(EventHandler* eh);
virtual int GetMaxFds();
virtual int GetRemainingFds();
- virtual bool DelFd(int fd);
- virtual int Wait(int* fdlist);
+ virtual bool DelFd(EventHandler* eh);
+ virtual int Wait(EventHandler** fdlist);
virtual std::string GetName();
};
diff --git a/include/socketengine_kqueue.h b/include/socketengine_kqueue.h
index 2010949ed..392843697 100644
--- a/include/socketengine_kqueue.h
+++ b/include/socketengine_kqueue.h
@@ -49,11 +49,11 @@ public:
/** Delete a KQueueEngine
*/
virtual ~KQueueEngine();
- virtual bool AddFd(int fd, bool readable, char type);
+ virtual bool AddFd(EventHandler* eh);
virtual int GetMaxFds();
virtual int GetRemainingFds();
- virtual bool DelFd(int fd);
- virtual int Wait(int* fdlist);
+ virtual bool DelFd(EventHandler* eh);
+ virtual int Wait(EventHandler** fdlist);
virtual std::string GetName();
};
diff --git a/include/socketengine_select.h b/include/socketengine_select.h
index a6db96ee5..d4b366b21 100644
--- a/include/socketengine_select.h
+++ b/include/socketengine_select.h
@@ -47,11 +47,11 @@ public:
/** Delete a SelectEngine
*/
virtual ~SelectEngine();
- virtual bool AddFd(int fd, bool readable, char type);
+ virtual bool AddFd(EventHandler* eh);
virtual int GetMaxFds();
virtual int GetRemainingFds();
- virtual bool DelFd(int fd);
- virtual int Wait(int* fdlist);
+ virtual bool DelFd(EventHandler* eh);
+ virtual int Wait(EventHandler** fdlist);
virtual std::string GetName();
};
diff --git a/include/users.h b/include/users.h
index b292cd998..3b1c2a3ec 100644
--- a/include/users.h
+++ b/include/users.h
@@ -743,6 +743,11 @@ class userrec : public connection
*/
void ShowRULES();
+ /** Handle socket event.
+ * From EventHandler class.
+ */
+ void HandleEvent(EventType et);
+
/** Default destructor
*/
virtual ~userrec();
diff --git a/src/channels.cpp b/src/channels.cpp
index 29373e906..a89b9b2c4 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -222,7 +222,7 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo
if (!Ptr)
{
- if (user->fd > -1)
+ if (IS_LOCAL(user))
{
MOD_RESULT = 0;
FOREACH_RESULT_I(Instance,I_OnUserPreJoin,OnUserPreJoin(user,NULL,cname));
@@ -654,7 +654,7 @@ void chanrec::WriteChannel(userrec* user, const std::string &text)
for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++)
{
- if (i->second->fd != FD_MAGIC_NUMBER)
+ if (IS_LOCAL(i->second))
user->WriteTo(i->second,text);
}
}
diff --git a/src/cmd_notice.cpp b/src/cmd_notice.cpp
index 209972400..006036145 100644
--- a/src/cmd_notice.cpp
+++ b/src/cmd_notice.cpp
@@ -118,7 +118,7 @@ void cmd_notice::Handle (const char** parameters, int pcnt, userrec *user)
}
parameters[1] = (char*)temp.c_str();
- if (dest->fd > -1)
+ if (IS_LOCAL(dest))
{
// direct write, same server
user->WriteTo(dest, "NOTICE %s :%s", dest->nick, parameters[1]);
diff --git a/src/cmd_privmsg.cpp b/src/cmd_privmsg.cpp
index 3f9e33652..ce5ece2a2 100644
--- a/src/cmd_privmsg.cpp
+++ b/src/cmd_privmsg.cpp
@@ -120,7 +120,7 @@ void cmd_privmsg::Handle (const char** parameters, int pcnt, userrec *user)
}
parameters[1] = (char*)temp.c_str();
- if (dest->fd > -1)
+ if (IS_LOCAL(dest))
{
// direct write, same server
user->WriteTo(dest, "PRIVMSG %s :%s", dest->nick, parameters[1]);
diff --git a/src/cmd_quit.cpp b/src/cmd_quit.cpp
index 7430e0fd2..c1e73bc84 100644
--- a/src/cmd_quit.cpp
+++ b/src/cmd_quit.cpp
@@ -52,7 +52,7 @@ void cmd_quit::Handle (const char** parameters, int pcnt, userrec *user)
/* We should only prefix the quit for a local user. Remote users have
* already been prefixed, where neccessary, by the upstream server.
*/
- if (user->fd > -1)
+ if (IS_LOCAL(user))
{
user->Write("ERROR :Closing link (%s@%s) [%s%s]",user->ident,user->host,ServerInstance->Config->PrefixQuit,parameters[0]);
ServerInstance->WriteOpers("*** Client exiting: %s!%s@%s [%s%s]",user->nick,user->ident,user->host,ServerInstance->Config->PrefixQuit,parameters[0]);
@@ -80,9 +80,9 @@ void cmd_quit::Handle (const char** parameters, int pcnt, userrec *user)
FOREACH_MOD(I_OnUserDisconnect,OnUserDisconnect(user));
/* push the socket on a stack of sockets due to be closed at the next opportunity */
- if (user->fd > -1)
+ if (IS_LOCAL(user))
{
- ServerInstance->SE->DelFd(user->fd);
+ ServerInstance->SE->DelFd(user);
if (find(ServerInstance->local_users.begin(),ServerInstance->local_users.end(),user) != ServerInstance->local_users.end())
{
ServerInstance->Log(DEBUG,"Delete local user");
@@ -99,7 +99,6 @@ void cmd_quit::Handle (const char** parameters, int pcnt, userrec *user)
if (user->registered == REG_ALL) {
user->PurgeEmptyChannels();
}
- if (user->fd > -1)
- ServerInstance->fd_ref_table[user->fd] = NULL;
DELETE(user);
}
+
diff --git a/src/dns.cpp b/src/dns.cpp
index 50aae9c82..8f23eaa6c 100644
--- a/src/dns.cpp
+++ b/src/dns.cpp
@@ -50,9 +50,6 @@ using irc::sockets::insp_inaddr;
using irc::sockets::insp_ntoa;
using irc::sockets::insp_aton;
-/* Master file descriptor */
-int DNS::MasterSocket;
-
/* Masks to mask off the responses we get from the DNSRequest methods */
enum QueryInfo
{
@@ -109,9 +106,10 @@ class DNSRequest
unsigned int rr_class; /* Request class */
QueryType type; /* Request type */
insp_inaddr myserver; /* DNS server address*/
+ DNS* dnsobj; /* DNS caller (where we get our FD from) */
/* Allocate the processing buffer */
- DNSRequest(insp_inaddr server)
+ DNSRequest(DNS* dns, insp_inaddr server) : dnsobj(dns)
{
res = new unsigned char[512];
*res = 0;
@@ -193,7 +191,7 @@ int DNSRequest::SendRequests(const DNSHeader *header, const int length, QueryTyp
addr.sin_family = AF_FAMILY;
addr.sin_port = htons(DNS::QUERY_PORT);
#endif
- if (sendto(DNS::GetMasterSocket(), payload, length + 12, 0, (sockaddr *) &addr, sizeof(addr)) == -1)
+ if (sendto(dnsobj->GetFd(), payload, length + 12, 0, (sockaddr *) &addr, sizeof(addr)) == -1)
return -1;
return 0;
@@ -203,7 +201,7 @@ int DNSRequest::SendRequests(const DNSHeader *header, const int length, QueryTyp
DNSRequest* DNS::AddQuery(DNSHeader *header, int &id)
{
/* Is the DNS connection down? */
- if (MasterSocket == -1)
+ if (this->GetFd() == -1)
return NULL;
/* Are there already the max number of requests on the go? */
@@ -217,7 +215,7 @@ DNSRequest* DNS::AddQuery(DNSHeader *header, int &id)
while (requests.find(id) != requests.end())
id = this->PRNG() & DNS::MAX_REQUEST_ID;
- DNSRequest* req = new DNSRequest(this->myserver);
+ DNSRequest* req = new DNSRequest(this, this->myserver);
header->id[0] = req->id[0] = id >> 8;
header->id[1] = req->id[1] = id & 0xFF;
@@ -237,11 +235,6 @@ DNSRequest* DNS::AddQuery(DNSHeader *header, int &id)
return req;
}
-int DNS::GetMasterSocket()
-{
- return MasterSocket;
-}
-
/* Initialise the DNS UDP socket so that we can send requests */
DNS::DNS(InspIRCd* Instance) : ServerInstance(Instance)
{
@@ -282,16 +275,16 @@ DNS::DNS(InspIRCd* Instance) : ServerInstance(Instance)
}
/* Initialize mastersocket */
- MasterSocket = socket(PF_PROTOCOL, SOCK_DGRAM, 0);
- if (MasterSocket != -1)
+ this->SetFd(socket(PF_PROTOCOL, SOCK_DGRAM, 0));
+ if (this->GetFd() != -1)
{
/* Did it succeed? */
- if (fcntl(MasterSocket, F_SETFL, O_NONBLOCK) != 0)
+ if (fcntl(this->GetFd(), F_SETFL, O_NONBLOCK) != 0)
{
/* Couldn't make the socket nonblocking */
- shutdown(MasterSocket,2);
- close(MasterSocket);
- MasterSocket = -1;
+ shutdown(this->GetFd(),2);
+ close(this->GetFd());
+ this->SetFd(-1);
}
}
else
@@ -299,7 +292,7 @@ DNS::DNS(InspIRCd* Instance) : ServerInstance(Instance)
ServerInstance->Log(DEBUG,"I cant socket() this socket! (%s)",strerror(errno));
}
/* Have we got a socket and is it nonblocking? */
- if (MasterSocket != -1)
+ if (this->GetFd() != -1)
{
#ifdef IPV6
insp_sockaddr addr;
@@ -315,27 +308,27 @@ DNS::DNS(InspIRCd* Instance) : ServerInstance(Instance)
addr.sin_addr.s_addr = INADDR_ANY;
#endif
/* Bind the port */
- if (bind(MasterSocket,(sockaddr *)&addr,sizeof(addr)) != 0)
+ if (bind(this->GetFd(),(sockaddr *)&addr,sizeof(addr)) != 0)
{
/* Failed to bind */
- ServerInstance->Log(DEBUG,"Cant bind DNS::MasterSocket");
- shutdown(MasterSocket,2);
- close(MasterSocket);
- MasterSocket = -1;
+ ServerInstance->Log(DEBUG,"Cant bind DNS fd");
+ shutdown(this->GetFd(),2);
+ close(this->GetFd());
+ this->SetFd(-1);
}
- if (MasterSocket >= 0)
+ if (this->GetFd() >= 0)
{
- ServerInstance->Log(DEBUG,"Add master socket %d",MasterSocket);
+ ServerInstance->Log(DEBUG,"Add master socket %d",this->GetFd());
/* Hook the descriptor into the socket engine */
if (ServerInstance && ServerInstance->SE)
{
- if (!ServerInstance->SE->AddFd(MasterSocket,true,X_ESTAB_DNS))
+ if (!ServerInstance->SE->AddFd(this))
{
ServerInstance->Log(DEFAULT,"Internal error starting DNS - hostnames will NOT resolve.");
- shutdown(MasterSocket,2);
- close(MasterSocket);
- MasterSocket = -1;
+ shutdown(this->GetFd(),2);
+ close(this->GetFd());
+ this->SetFd(-1);
}
}
}
@@ -538,7 +531,7 @@ DNSResult DNS::GetResult()
const char* ipaddr_from = "";
unsigned short int port_from = 0;
- int length = recvfrom(MasterSocket,buffer,sizeof(DNSHeader),0,&from,&x);
+ int length = recvfrom(this->GetFd(),buffer,sizeof(DNSHeader),0,&from,&x);
if (length < 0)
ServerInstance->Log(DEBUG,"Error in recvfrom()! (%s)",strerror(errno));
@@ -594,7 +587,7 @@ DNSResult DNS::GetResult()
if (n_iter == requests.end())
{
/* Somehow we got a DNS response for a request we never made... */
- ServerInstance->Log(DEBUG,"DNS: got a response for a query we didnt send with fd=%d queryid=%d",MasterSocket,this_id);
+ ServerInstance->Log(DEBUG,"DNS: got a response for a query we didnt send with fd=%d queryid=%d",this->GetFd(),this_id);
return std::make_pair(-1,"");
}
else
@@ -832,8 +825,8 @@ DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, int length)
/* Close the master socket */
DNS::~DNS()
{
- shutdown(MasterSocket, 2);
- close(MasterSocket);
+ shutdown(this->GetFd(), 2);
+ close(this->GetFd());
}
/* High level abstraction of dns used by application at large */
@@ -914,53 +907,47 @@ int Resolver::GetId()
}
/* Process a socket read event */
-void DNS::MarshallReads(int fd)
+void DNS::HandleEvent(EventType et)
{
- ServerInstance->Log(DEBUG,"Marshall reads: %d %d",fd,GetMasterSocket());
- /* We are only intrested in our single fd */
- if (fd == GetMasterSocket())
+ ServerInstance->Log(DEBUG,"Marshall reads: %d",this->GetFd());
+ /* Fetch the id and result of the next available packet */
+ DNSResult res = this->GetResult();
+ /* Is there a usable request id? */
+ if (res.first != -1)
{
- /* Fetch the id and result of the next available packet */
- DNSResult res = this->GetResult();
- /* Is there a usable request id? */
- if (res.first != -1)
+ /* Its an error reply */
+ if (res.first & ERROR_MASK)
{
- /* Its an error reply */
- if (res.first & ERROR_MASK)
+ /* Mask off the error bit */
+ res.first -= ERROR_MASK;
+ /* Marshall the error to the correct class */
+ ServerInstance->Log(DEBUG,"Error available, id=%d",res.first);
+ if (Classes[res.first])
{
- /* Mask off the error bit */
- res.first -= ERROR_MASK;
-
- /* Marshall the error to the correct class */
- ServerInstance->Log(DEBUG,"Error available, id=%d",res.first);
- if (Classes[res.first])
- {
- if (ServerInstance && ServerInstance->stats)
- ServerInstance->stats->statsDnsBad++;
- Classes[res.first]->OnError(RESOLVER_NXDOMAIN, res.second);
- delete Classes[res.first];
- Classes[res.first] = NULL;
- }
+ if (ServerInstance && ServerInstance->stats)
+ ServerInstance->stats->statsDnsBad++;
+ Classes[res.first]->OnError(RESOLVER_NXDOMAIN, res.second);
+ delete Classes[res.first];
+ Classes[res.first] = NULL;
}
- else
+ }
+ else
+ {
+ /* It is a non-error result */
+ ServerInstance->Log(DEBUG,"Result available, id=%d",res.first);
+ /* Marshall the result to the correct class */
+ if (Classes[res.first])
{
- /* It is a non-error result */
- ServerInstance->Log(DEBUG,"Result available, id=%d",res.first);
- /* Marshall the result to the correct class */
- if (Classes[res.first])
- {
- if (ServerInstance && ServerInstance->stats)
- ServerInstance->stats->statsDnsGood++;
- Classes[res.first]->OnLookupComplete(res.second);
- delete Classes[res.first];
- Classes[res.first] = NULL;
- }
+ if (ServerInstance && ServerInstance->stats)
+ ServerInstance->stats->statsDnsGood++;
+ Classes[res.first]->OnLookupComplete(res.second);
+ delete Classes[res.first];
+ Classes[res.first] = NULL;
}
-
- if (ServerInstance && ServerInstance->stats)
- ServerInstance->stats->statsDns++;
-
}
+
+ if (ServerInstance && ServerInstance->stats)
+ ServerInstance->stats->statsDns++;
}
}
diff --git a/src/inspircd.cpp b/src/inspircd.cpp
index 92c05f557..41e0897b7 100644
--- a/src/inspircd.cpp
+++ b/src/inspircd.cpp
@@ -171,13 +171,9 @@ InspIRCd::InspIRCd(int argc, char** argv)
: ModCount(-1), duration_m(60), duration_h(60*60), duration_d(60*60*24), duration_w(60*60*24*7), duration_y(60*60*24*365)
{
bool SEGVHandler = false;
- //ServerInstance = this;
modules.resize(255);
factory.resize(255);
-
- memset(fd_ref_table, 0, sizeof(fd_ref_table));
- memset(socket_ref, 0, sizeof(socket_ref));
this->Config = new ServerConfig(this);
this->Start();
@@ -294,7 +290,7 @@ InspIRCd::InspIRCd(int argc, char** argv)
if (!stats->BoundPortCount)
{
- printf("\nI couldn't bind any ports! Are you sure you didn't start InspIRCd twice?\n");
+ printf("\nERROR: I couldn't bind any ports! Are you sure you didn't start InspIRCd twice?\n");
Exit(ERROR);
}
@@ -305,7 +301,7 @@ InspIRCd::InspIRCd(int argc, char** argv)
for (unsigned long count = 0; count < stats->BoundPortCount; count++)
{
this->Log(DEBUG,"Add listener: %d",Config->openSockfd[count]);
- if (!SE->AddFd(Config->openSockfd[count],true,X_LISTEN))
+ if (!SE->AddFd(Config->openSockfd[count]))
{
printf("\nEH? Could not add listener to socketengine. You screwed up, aborting.\n");
Exit(ERROR);
@@ -667,15 +663,8 @@ bool InspIRCd::LoadModule(const char* filename)
void InspIRCd::DoOneIteration(bool process_module_sockets)
{
- int activefds[MAX_DESCRIPTORS];
- int incomingSockfd;
- int in_port;
- userrec* cu = NULL;
- InspSocket* s = NULL;
- InspSocket* s_del = NULL;
+ EventHandler* activefds[MAX_DESCRIPTORS];
unsigned int numberactive;
- insp_sockaddr sock_us; // our port number
- socklen_t uslen; // length of our port number
/* time() seems to be a pretty expensive syscall, so avoid calling it too much.
* Once per loop iteration is pleanty.
@@ -728,129 +717,8 @@ void InspIRCd::DoOneIteration(bool process_module_sockets)
for (unsigned int activefd = 0; activefd < numberactive; activefd++)
{
- int socket_type = SE->GetType(activefds[activefd]);
- switch (socket_type)
- {
- case X_ESTAB_CLIENT:
-
- this->Log(DEBUG,"Type: X_ESTAB_CLIENT: fd=%d",activefds[activefd]);
- cu = this->fd_ref_table[activefds[activefd]];
- if (cu)
- this->ProcessUser(cu);
-
- break;
-
- case X_ESTAB_MODULE:
-
- this->Log(DEBUG,"Type: X_ESTAB_MODULE: fd=%d",activefds[activefd]);
-
- if (!process_module_sockets)
- break;
-
- /* Process module-owned sockets.
- * Modules are encouraged to inherit their sockets from
- * InspSocket so we can process them neatly like this.
- */
- s = this->socket_ref[activefds[activefd]];
-
- if ((s) && (!s->Poll()))
- {
- this->Log(DEBUG,"Socket poll returned false, close and bail");
- SE->DelFd(s->GetFd());
- this->socket_ref[activefds[activefd]] = NULL;
- for (std::vector<InspSocket*>::iterator a = module_sockets.begin(); a < module_sockets.end(); a++)
- {
- s_del = *a;
- if ((s_del) && (s_del->GetFd() == activefds[activefd]))
- {
- module_sockets.erase(a);
- break;
- }
- }
- s->Close();
- DELETE(s);
- }
- else if (!s)
- {
- this->Log(DEBUG,"WTF, X_ESTAB_MODULE for nonexistent InspSocket, removed!");
- SE->DelFd(s->GetFd());
- }
- break;
-
- case X_ESTAB_DNS:
- /* Handles instances of the Resolver class,
- * a simple class extended by modules and the core for
- * nonblocking resolving of addresses.
- */
- this->Res->MarshallReads(activefds[activefd]);
- break;
-
- case X_LISTEN:
-
- this->Log(DEBUG,"Type: X_LISTEN: fd=%d",activefds[activefd]);
-
- /* It's a listener */
- uslen = sizeof(sock_us);
- length = sizeof(client);
- incomingSockfd = accept (activefds[activefd],(struct sockaddr*)&client,&length);
-
- if ((incomingSockfd > -1) && (!getsockname(incomingSockfd,(sockaddr*)&sock_us,&uslen)))
- {
-#ifdef IPV6
- in_port = ntohs(sock_us.sin6_port);
-#else
- in_port = ntohs(sock_us.sin_port);
-#endif
- this->Log(DEBUG,"Accepted socket %d",incomingSockfd);
- /* Years and years ago, we used to resolve here
- * using gethostbyaddr(). That is sucky and we
- * don't do that any more...
- */
- NonBlocking(incomingSockfd);
- if (Config->GetIOHook(in_port))
- {
- try
- {
-#ifdef IPV6
- Config->GetIOHook(in_port)->OnRawSocketAccept(incomingSockfd, insp_ntoa(client.sin6_addr), in_port);
-#else
- Config->GetIOHook(in_port)->OnRawSocketAccept(incomingSockfd, insp_ntoa(client.sin_addr), in_port);
-#endif
- }
- catch (ModuleException& modexcept)
- {
- this->Log(DEBUG,"Module exception cought: %s",modexcept.GetReason());
- }
- }
- stats->statsAccept++;
-#ifdef IPV6
- this->Log(DEBUG,"Add ipv6 client");
- userrec::AddClient(this, incomingSockfd, in_port, false, client.sin6_addr);
-#else
- this->Log(DEBUG,"Add ipv4 client");
- userrec::AddClient(this, incomingSockfd, in_port, false, client.sin_addr);
-#endif
- this->Log(DEBUG,"Adding client on port %d fd=%d",in_port,incomingSockfd);
- }
- else
- {
- this->Log(DEBUG,"Accept failed on fd %d: %s",incomingSockfd,strerror(errno));
- shutdown(incomingSockfd,2);
- close(incomingSockfd);
- stats->statsRefused++;
- }
- break;
-
- default:
- /* Something went wrong if we're in here.
- * In fact, so wrong, im not quite sure
- * what we would do, so for now, its going
- * to safely do bugger all.
- */
- this->Log(DEBUG,"Type: X_WHAT_THE_FUCK_BBQ: fd=%d",activefds[activefd]);
- SE->DelFd(activefds[activefd]);
- break;
- }
+ this->Log(DEBUG,"Handle %s event on fd %d",activefds[activefd]->Readable() ? "read" : "write", activefds[activefd]->GetFd());
+ activefds[activefd]->HandleEvent(activefds[activefd]->Readable() ? EVENT_READ : EVENT_WRITE);
}
}
diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp
index 75f8dc250..c44ad130f 100644
--- a/src/inspsocket.cpp
+++ b/src/inspsocket.cpp
@@ -23,7 +23,6 @@
#include "socket.h"
#include "configreader.h"
#include "inspstring.h"
-
#include "socketengine.h"
#include "inspircd.h"
@@ -31,10 +30,16 @@ using irc::sockets::OpenTCPSocket;
using irc::sockets::insp_inaddr;
using irc::sockets::insp_sockaddr;
+bool InspSocket::Readable()
+{
+ return ((this->state != I_CONNECTING) && (this->WaitingForWriteEvent == false));
+}
+
InspSocket::InspSocket(InspIRCd* SI)
{
this->state = I_DISCONNECTED;
this->fd = -1;
+ this->WaitingForWriteEvent = false;
this->ClosePending = false;
this->Instance = SI;
}
@@ -45,20 +50,21 @@ InspSocket::InspSocket(InspIRCd* SI, int newfd, const char* ip)
this->state = I_CONNECTED;
strlcpy(this->IP,ip,MAXBUF);
this->ClosePending = false;
+ this->WaitingForWriteEvent = false;
this->Instance = SI;
if (this->fd > -1)
- {
- this->ClosePending = (!this->Instance->SE->AddFd(this->fd,true,X_ESTAB_MODULE));
- this->Instance->socket_ref[this->fd] = this;
- }
+ this->ClosePending = (!this->Instance->SE->AddFd(this));
}
-InspSocket::InspSocket(InspIRCd* SI, const std::string &ipaddr, int aport, bool listening, unsigned long maxtime) : fd(-1)
+InspSocket::InspSocket(InspIRCd* SI, const std::string &ipaddr, int aport, bool listening, unsigned long maxtime)
{
+ this->fd = -1;
this->Instance = SI;
strlcpy(host,ipaddr.c_str(),MAXBUF);
this->ClosePending = false;
- if (listening) {
+ this->WaitingForWriteEvent = false;
+ if (listening)
+ {
if ((this->fd = OpenTCPSocket()) == ERROR)
{
this->fd = -1;
@@ -85,14 +91,13 @@ InspSocket::InspSocket(InspIRCd* SI, const std::string &ipaddr, int aport, bool
this->state = I_LISTENING;
if (this->fd > -1)
{
- if (!this->Instance->SE->AddFd(this->fd,true,X_ESTAB_MODULE))
+ if (!this->Instance->SE->AddFd(this))
{
this->Close();
this->state = I_ERROR;
this->OnError(I_ERR_NOMOREFDS);
this->ClosePending = true;
}
- this->Instance->socket_ref[this->fd] = this;
}
this->Instance->Log(DEBUG,"New socket now in I_LISTENING state");
return;
@@ -136,9 +141,9 @@ void InspSocket::WantWrite()
*
* This behaviour may be fixed in a later version.
*/
+ this->Instance->SE->DelFd(this);
this->WaitingForWriteEvent = true;
- this->Instance->SE->DelFd(this->fd);
- if (!this->Instance->SE->AddFd(this->fd,false,X_ESTAB_MODULE))
+ if (!this->Instance->SE->AddFd(this))
{
this->Close();
this->fd = -1;
@@ -263,7 +268,7 @@ bool InspSocket::DoConnect()
this->state = I_CONNECTING;
if (this->fd > -1)
{
- if (!this->Instance->SE->AddFd(this->fd,false,X_ESTAB_MODULE))
+ if (!this->Instance->SE->AddFd(this))
{
this->OnError(I_ERR_NOMOREFDS);
this->Close();
@@ -272,7 +277,6 @@ bool InspSocket::DoConnect()
this->ClosePending = true;
return false;
}
- this->Instance->socket_ref[this->fd] = this;
this->SetQueues(this->fd);
}
this->Instance->Log(DEBUG,"Returning true from InspSocket::DoConnect");
@@ -287,7 +291,6 @@ void InspSocket::Close()
this->OnClose();
shutdown(this->fd,2);
close(this->fd);
- this->Instance->socket_ref[this->fd] = NULL;
this->ClosePending = true;
this->fd = -1;
}
@@ -388,7 +391,7 @@ bool InspSocket::FlushWriteBuffer()
bool InspSocket::Timeout(time_t current)
{
- if (!this->Instance->socket_ref[this->fd] || !this->Instance->SE->HasFd(this->fd))
+ if (this->Instance->SE->GetRef(this->fd) != this)
{
this->Instance->Log(DEBUG,"No FD or socket ref");
return false;
@@ -419,7 +422,7 @@ bool InspSocket::Timeout(time_t current)
bool InspSocket::Poll()
{
- if (!this->Instance->socket_ref[this->fd] || !this->Instance->SE->HasFd(this->fd))
+ if (this->Instance->SE->GetRef(this->fd) != this)
return false;
int incoming = -1;
@@ -432,14 +435,14 @@ bool InspSocket::Poll()
{
case I_CONNECTING:
this->Instance->Log(DEBUG,"State = I_CONNECTING");
- this->SetState(I_CONNECTED);
/* Our socket was in write-state, so delete it and re-add it
* in read-state.
*/
if (this->fd > -1)
{
- this->Instance->SE->DelFd(this->fd);
- if (!this->Instance->SE->AddFd(this->fd,true,X_ESTAB_MODULE))
+ this->Instance->SE->DelFd(this);
+ this->SetState(I_CONNECTED);
+ if (!this->Instance->SE->AddFd(this))
return false;
}
return this->OnConnected();
@@ -460,8 +463,9 @@ bool InspSocket::Poll()
if (this->WaitingForWriteEvent)
{
/* Switch back to read events */
- this->Instance->SE->DelFd(this->fd);
- if (!this->Instance->SE->AddFd(this->fd,true,X_ESTAB_MODULE))
+ this->Instance->SE->DelFd(this);
+ this->WaitingForWriteEvent = false;
+ if (!this->Instance->SE->AddFd(this))
return false;
/* Trigger the write event */
@@ -516,3 +520,13 @@ InspSocket::~InspSocket()
{
this->Close();
}
+
+void InspSocket::HandleEvent(EventType et)
+{
+ if (!this->Poll())
+ {
+ this->Instance->SE->DelFd(this);
+ delete this;
+ }
+}
+
diff --git a/src/modules.cpp b/src/modules.cpp
index b78b84d12..eaff59c2d 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -380,7 +380,7 @@ void InspIRCd::DumpText(userrec* User, const std::string &LinePrefix, stringstre
userrec* InspIRCd::FindDescriptor(int socket)
{
- return ((socket < MAX_DESCRIPTORS && socket > -1) ? this->fd_ref_table[socket] : NULL);
+ return reinterpret_cast<userrec*>(this->SE->GetRef(socket));
}
bool InspIRCd::AddMode(ModeHandler* mh, const unsigned char mode)
@@ -405,18 +405,18 @@ bool InspIRCd::AddResolver(Resolver* r)
bool InspIRCd::UserToPseudo(userrec* user, const std::string &message)
{
- unsigned int old_fd = user->fd;
+ unsigned int old_fd = user->GetFd();
user->Write("ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,message.c_str());
user->FlushWriteBuf();
user->ClearBuffer();
- user->fd = FD_MAGIC_NUMBER;
+ user->SetFd(FD_MAGIC_NUMBER);
if (find(local_users.begin(),local_users.end(),user) != local_users.end())
{
local_users.erase(find(local_users.begin(),local_users.end(),user));
}
- this->SE->DelFd(old_fd);
+ this->SE->DelFd(user);
shutdown(old_fd,2);
close(old_fd);
return true;
@@ -424,9 +424,9 @@ bool InspIRCd::UserToPseudo(userrec* user, const std::string &message)
bool InspIRCd::PseudoToUser(userrec* alive, userrec* zombie, const std::string &message)
{
- zombie->fd = alive->fd;
+ zombie->SetFd(alive->GetFd());
FOREACH_MOD_I(this,I_OnUserQuit,OnUserQuit(alive,message));
- alive->fd = FD_MAGIC_NUMBER;
+ alive->SetFd(FD_MAGIC_NUMBER);
alive->FlushWriteBuf();
alive->ClearBuffer();
// save these for later
@@ -439,7 +439,6 @@ bool InspIRCd::PseudoToUser(userrec* alive, userrec* zombie, const std::string &
local_users.erase(find(local_users.begin(),local_users.end(),alive));
}
// Fix by brain - cant write the user until their fd table entry is updated
- this->fd_ref_table[zombie->fd] = zombie;
zombie->Write(":%s!%s@%s NICK %s",oldnick.c_str(),oldident.c_str(),oldhost.c_str(),zombie->nick);
for (std::vector<ucrec*>::const_iterator i = zombie->chans.begin(); i != zombie->chans.end(); i++)
{
@@ -456,9 +455,8 @@ bool InspIRCd::PseudoToUser(userrec* alive, userrec* zombie, const std::string &
zombie->WriteServ("366 %s %s :End of /NAMES list.", zombie->nick, Ptr->name);
}
}
- if ((find(local_users.begin(),local_users.end(),zombie) == local_users.end()) && (zombie->fd != FD_MAGIC_NUMBER))
+ if ((find(local_users.begin(),local_users.end(),zombie) == local_users.end()) && (zombie->GetFd() != FD_MAGIC_NUMBER))
local_users.push_back(zombie);
-
return true;
}
diff --git a/src/modules/extra/m_pgsql.cpp b/src/modules/extra/m_pgsql.cpp
index 0a8c1fd11..1790fdfef 100644
--- a/src/modules/extra/m_pgsql.cpp
+++ b/src/modules/extra/m_pgsql.cpp
@@ -738,13 +738,12 @@ bool SQLConn::DoConnect()
}
this->state = I_CONNECTING;
- if (!this->Instance->SE->AddFd(this->fd,false,X_ESTAB_MODULE))
+ if (!this->Instance->SE->AddFd(this))
{
Instance->Log(DEBUG, "A PQsocket cant be added to the socket engine!");
Close();
return false;
}
- this->Instance->socket_ref[this->fd] = this;
/* Socket all hooked into the engine, now to tell PgSQL to start connecting */
@@ -754,9 +753,7 @@ bool SQLConn::DoConnect()
void SQLConn::Close()
{
Instance->Log(DEBUG,"SQLConn::Close");
-
- if(this->fd > 01)
- Instance->socket_ref[this->fd] = NULL;
+
this->fd = -1;
this->state = I_ERROR;
this->OnError(I_ERR_SOCKET);
diff --git a/src/modules/m_cgiirc.cpp b/src/modules/m_cgiirc.cpp
index 496162877..d70bd9561 100644
--- a/src/modules/m_cgiirc.cpp
+++ b/src/modules/m_cgiirc.cpp
@@ -60,7 +60,7 @@ class CGIResolver : public Resolver
virtual void OnLookupComplete(const std::string &result)
{
/* Check the user still exists */
- if ((them) && (them == ServerInstance->fd_ref_table[theirfd]))
+ if ((them) && (them == ServerInstance->SE->GetRef(theirfd)))
{
if (notify)
ServerInstance->WriteOpers("*** Connecting user %s detected as using CGI:IRC (%s), changing real host to %s from %s", them->nick, them->host, result.c_str(), typ.c_str());
@@ -73,7 +73,7 @@ class CGIResolver : public Resolver
virtual void OnError(ResolverError e, const std::string &errormessage)
{
- if ((them) && (them == ServerInstance->fd_ref_table[theirfd]))
+ if ((them) && (them == ServerInstance->SE->GetRef(theirfd)))
{
if (notify)
ServerInstance->WriteOpers("*** Connecting user %s detected as using CGI:IRC (%s), but their host can't be resolved from their %s!", them->nick, them->host,typ.c_str());
@@ -262,7 +262,7 @@ public:
try
{
- CGIResolver* r = new CGIResolver(NotifyOpers, user->password, false, user, user->fd, "PASS");
+ CGIResolver* r = new CGIResolver(NotifyOpers, user->password, false, user, user->GetFd(), "PASS");
ServerInstance->AddResolver(r);
}
catch (ModuleException& e)
@@ -317,8 +317,8 @@ public:
try
{
- ServerInstance->Log(DEBUG,"MAKE RESOLVER: %s %d %s",newip, user->fd, "IDENT");
- CGIResolver* r = new CGIResolver(NotifyOpers, newip, false, user, user->fd, "IDENT");
+ ServerInstance->Log(DEBUG,"MAKE RESOLVER: %s %d %s",newip, user->GetFd(), "IDENT");
+ CGIResolver* r = new CGIResolver(NotifyOpers, newip, false, user, user->GetFd(), "IDENT");
ServerInstance->AddResolver(r);
}
catch (ModuleException& e)
diff --git a/src/modules/m_ident.cpp b/src/modules/m_ident.cpp
index 5e842b070..a7ffe6052 100644
--- a/src/modules/m_ident.cpp
+++ b/src/modules/m_ident.cpp
@@ -41,7 +41,7 @@ class RFC1413 : public InspSocket
userrec* u; // user record that the lookup is associated with
int ufd;
- RFC1413(InspIRCd* SI, userrec* user, int maxtime) : InspSocket(SI, user->GetIPString(), 113, false, maxtime), u(user), ufd(user->fd)
+ RFC1413(InspIRCd* SI, userrec* user, int maxtime) : InspSocket(SI, user->GetIPString(), 113, false, maxtime), u(user), ufd(user->GetFd())
{
}
@@ -49,7 +49,7 @@ class RFC1413 : public InspSocket
{
// When we timeout, the connection failed within the allowed timeframe,
// so we just display a notice, and tidy off the ident_data.
- if (u && (Instance->fd_ref_table[ufd] == u))
+ if (u && (Instance->SE->GetRef(ufd) == u))
{
u->Shrink("ident_data");
u->WriteServ("NOTICE "+std::string(u->nick)+" :*** Could not find your ident, using "+std::string(u->ident)+" instead.");
@@ -80,7 +80,7 @@ class RFC1413 : public InspSocket
*j = '\0'; // truncate at invalid chars
if (*section)
{
- if (u && (Instance->fd_ref_table[ufd] == u))
+ if (u && (Instance->SE->GetRef(ufd) == u))
{
if (this->Instance->IsIdent(section))
{
@@ -121,7 +121,7 @@ class RFC1413 : public InspSocket
// descriptor that they were when the lookup began.
//
// Fixes issue reported by webs, 7 Jun 2006
- if (u && (Instance->fd_ref_table[ufd] == u))
+ if (u && (Instance->SE->GetRef(ufd) == u))
{
u->Shrink("ident_data");
}
@@ -129,7 +129,7 @@ class RFC1413 : public InspSocket
virtual void OnError(InspSocketError e)
{
- if (u && (Instance->fd_ref_table[ufd] == u))
+ if (u && (Instance->SE->GetRef(ufd) == u))
{
u->Shrink("ident_data");
}
@@ -137,11 +137,11 @@ class RFC1413 : public InspSocket
virtual bool OnConnected()
{
- if (u && (Instance->fd_ref_table[ufd] == u))
+ if (u && (Instance->SE->GetRef(ufd) == u))
{
uslen = sizeof(sock_us);
themlen = sizeof(sock_them);
- if ((getsockname(this->u->fd,(sockaddr*)&sock_us,&uslen) || getpeername(this->u->fd, (sockaddr*)&sock_them, &themlen)))
+ if ((getsockname(this->u->GetFd(),(sockaddr*)&sock_us,&uslen) || getpeername(this->u->GetFd(), (sockaddr*)&sock_them, &themlen)))
{
Instance->Log(DEBUG,"Ident: failed to get socket names, bailing");
return false;
diff --git a/src/modules/m_samode.cpp b/src/modules/m_samode.cpp
index 77d9a756d..2453308d3 100644
--- a/src/modules/m_samode.cpp
+++ b/src/modules/m_samode.cpp
@@ -57,7 +57,7 @@ class cmd_samode : public command_t
std::string result;
ServerInstance->Log(DEBUG,"SAMODE: Being handled");
userrec* n = new userrec(ServerInstance);
- n->fd = FD_MAGIC_NUMBER;
+ n->SetFd(FD_MAGIC_NUMBER);
ServerInstance->SendMode(parameters,pcnt,n);
delete n;
ServerInstance->Log(DEBUG,"SAMODE: Modechange handled");
diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp
index b3cc874bd..fde13ef98 100644
--- a/src/modules/m_spanningtree.cpp
+++ b/src/modules/m_spanningtree.cpp
@@ -309,7 +309,7 @@ class TreeServer : public classbase
for (std::vector<userrec*>::iterator n = time_to_die.begin(); n != time_to_die.end(); n++)
{
userrec* a = (userrec*)*n;
- ServerInstance->Log(DEBUG,"Kill %s fd=%d",a->nick,a->fd);
+ ServerInstance->Log(DEBUG,"Kill %s fd=%d",a->nick,a->GetFd());
if (!IS_LOCAL(a))
userrec::QuitUser(ServerInstance,a,reason_s);
}
@@ -932,7 +932,7 @@ class TreeSocket : public InspSocket
{
/* FMODE from a server, create a fake user to receive mode feedback */
who = new userrec(this->Instance);
- who->fd = FD_MAGIC_NUMBER;
+ who->SetFd(FD_MAGIC_NUMBER);
smode = true; /* Setting this flag tells us we should free the userrec later */
sourceserv = source; /* Set sourceserv to the actual source string */
}
@@ -1542,7 +1542,7 @@ class TreeSocket : public InspSocket
userrec* _new = new userrec(this->Instance);
this->Instance->clientlist[tempnick] = _new;
- _new->fd = FD_MAGIC_NUMBER;
+ _new->SetFd(FD_MAGIC_NUMBER);
strlcpy(_new->nick, tempnick,NICKMAX-1);
strlcpy(_new->host, params[2].c_str(),63);
strlcpy(_new->dhost, params[3].c_str(),63);
@@ -3135,7 +3135,7 @@ void GetListOfServersForChannel(chanrec* c, std::deque<TreeServer*> &list)
CUList *ulist = c->GetUsers();
for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++)
{
- if (i->second->fd < 0)
+ if (i->second->GetFd() < 0)
{
TreeServer* best = BestRouteTo(i->second->server);
if (best)
@@ -3689,7 +3689,7 @@ class ModuleSpanningTree : public Module
if ((IS_LOCAL(user)) && (pcnt > 1))
{
userrec* remote = ServerInstance->FindNick(parameters[1]);
- if ((remote) && (remote->fd < 0))
+ if ((remote) && (remote->GetFd() < 0))
{
std::deque<std::string> params;
params.push_back(parameters[1]);
@@ -4005,7 +4005,7 @@ class ModuleSpanningTree : public Module
if (target_type == TYPE_USER)
{
userrec* d = (userrec*)dest;
- if ((d->fd < 0) && (IS_LOCAL(user)))
+ if ((d->GetFd() < 0) && (IS_LOCAL(user)))
{
std::deque<std::string> params;
params.clear();
@@ -4053,7 +4053,7 @@ class ModuleSpanningTree : public Module
// route private messages which are targetted at clients only to the server
// which needs to receive them
userrec* d = (userrec*)dest;
- if ((d->fd < 0) && (IS_LOCAL(user)))
+ if ((d->GetFd() < 0) && (IS_LOCAL(user)))
{
std::deque<std::string> params;
params.clear();
diff --git a/src/modules/m_timedbans.cpp b/src/modules/m_timedbans.cpp
index d933c7f13..8639aa7df 100644
--- a/src/modules/m_timedbans.cpp
+++ b/src/modules/m_timedbans.cpp
@@ -177,7 +177,7 @@ class ModuleTimedBans : public Module
// hash and set its descriptor to FD_MAGIC_NUMBER so the data
// falls into the abyss :p
userrec* temp = new userrec(ServerInstance);
- temp->fd = FD_MAGIC_NUMBER;
+ temp->SetFd(FD_MAGIC_NUMBER);
/* FIX: Send mode remotely*/
std::deque<std::string> n;
n.push_back(setban[0]);
diff --git a/src/socket.cpp b/src/socket.cpp
index d28107f7f..50a4050e0 100644
--- a/src/socket.cpp
+++ b/src/socket.cpp
@@ -3,13 +3,13 @@
* +------------------------------------+
*
* InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
- * E-mail:
- * <brain@chatspike.net>
- * <Craig@chatspike.net>
+ * E-mail:
+ * <brain@chatspike.net>
+ * <Craig@chatspike.net>
*
* Written by Craig Edwards, Craig McLure, and others.
* This program is free but copyrighted software; see
- * the file COPYING for details.
+ * the file COPYING for details.
*
* ---------------------------------------------------
*/
@@ -19,7 +19,6 @@
#include "socket.h"
#include "inspircd.h"
#include "inspstring.h"
-
#include "socketengine.h"
#include "wildcard.h"
@@ -41,6 +40,75 @@ const char inverted_bits[8] = { 0x00, /* 00000000 - 0 bits - never actually used
0xFE /* 11111110 - 7 bits */
};
+
+ListenSocket::ListenSocket(InspIRCd* Instance, int sockfd, insp_sockaddr client, insp_sockaddr server, int port, char* addr) : ServerInstance(Instance)
+{
+ this->SetFd(sockfd);
+ Instance->Log(DEBUG,"Binding to port %s:%d",addr,port);
+ if (!Instance->BindSocket(this->fd,client,server,port,addr))
+ {
+ Instance->Log(DEBUG,"Binding failed!");
+ this->fd = -1;
+ }
+}
+
+void ListenSocket::HandleEvent(EventType et)
+{
+ insp_sockaddr sock_us; // our port number
+ socklen_t uslen; // length of our port number
+ insp_sockaddr client;
+ socklen_t length;
+ int incomingSockfd, in_port;
+
+ ServerInstance->Log(DEBUG,"Handle ListenSocket event");
+
+ uslen = sizeof(sock_us);
+ length = sizeof(client);
+ incomingSockfd = accept (this->GetFd(),(struct sockaddr*)&client, &length);
+
+ if ((incomingSockfd > -1) && (!getsockname(incomingSockfd, (sockaddr*)&sock_us, &uslen)))
+ {
+#ifdef IPV6
+ in_port = ntohs(sock_us.sin6_port);
+#else
+ in_port = ntohs(sock_us.sin_port);
+#endif
+ ServerInstance->Log(DEBUG,"Accepted socket %d",incomingSockfd);
+ NonBlocking(incomingSockfd);
+ if (ServerInstance->Config->GetIOHook(in_port))
+ {
+ try
+ {
+#ifdef IPV6
+ ServerInstance->Config->GetIOHook(in_port)->OnRawSocketAccept(incomingSockfd, insp_ntoa(client.sin6_addr), in_port);
+#else
+ ServerInstance->Config->GetIOHook(in_port)->OnRawSocketAccept(incomingSockfd, insp_ntoa(client.sin_addr), in_port);
+#endif
+ }
+ catch (ModuleException& modexcept)
+ {
+ ServerInstance->Log(DEBUG,"Module exception cought: %s",modexcept.GetReason());
+ }
+ }
+ ServerInstance->stats->statsAccept++;
+#ifdef IPV6
+ ServerInstance->Log(DEBUG,"Add ipv6 client");
+ userrec::AddClient(ServerInstance, incomingSockfd, in_port, false, client.sin6_addr);
+#else
+ ServerInstance->Log(DEBUG,"Add ipv4 client");
+ userrec::AddClient(ServerInstance, incomingSockfd, in_port, false, client.sin_addr);
+#endif
+ ServerInstance->Log(DEBUG,"Adding client on port %d fd=%d",in_port,incomingSockfd);
+ }
+ else
+ {
+ ServerInstance->Log(DEBUG,"Accept failed on fd %d: %s",incomingSockfd,strerror(errno));
+ shutdown(incomingSockfd,2);
+ close(incomingSockfd);
+ ServerInstance->stats->statsRefused++;
+ }
+}
+
/* Match raw bytes using CIDR bit matching, used by higher level MatchCIDR() */
bool irc::sockets::MatchCIDRBits(unsigned char* address, unsigned char* mask, unsigned int mask_bits)
{
@@ -356,31 +424,30 @@ int InspIRCd::BindPorts(bool bail)
{
for (int count = InitialPortCount; count < InitialPortCount + PortCount; count++)
{
- if ((Config->openSockfd[count] = OpenTCPSocket()) == ERROR)
+ int fd = OpenTCPSocket();
+ if (fd == ERROR)
{
- this->Log(DEBUG,"Bad fd %d binding port [%s:%d]",Config->openSockfd[count],Config->addrs[count],Config->ports[count]);
+ this->Log(DEBUG,"Bad fd %d binding port [%s:%d]",fd,Config->addrs[count],Config->ports[count]);
}
else
{
- if (!BindSocket(Config->openSockfd[count],client,server,Config->ports[count],Config->addrs[count]))
+ Config->openSockfd[count] = new ListenSocket(this,fd,client,server,Config->ports[count],Config->addrs[count]);
+ if (Config->openSockfd[count]->GetFd() > -1)
{
- this->Log(DEFAULT,"Failed to bind port [%s:%d]: %s",Config->addrs[count],Config->ports[count],strerror(errno));
- }
- else
- {
- /* Associate the new open port with a slot in the socket engine */
- if (Config->openSockfd[count] > -1)
+ if (!SE->AddFd(Config->openSockfd[count]))
{
- if (!SE->AddFd(Config->openSockfd[count],true,X_LISTEN))
- {
- this->Log(DEFAULT,"ERK! Failed to add listening port to socket engine!");
- shutdown(Config->openSockfd[count],2);
- close(Config->openSockfd[count]);
- }
- else
- BoundPortCount++;
+ this->Log(DEFAULT,"ERK! Failed to add listening port to socket engine!");
+ shutdown(Config->openSockfd[count]->GetFd(),2);
+ close(Config->openSockfd[count]->GetFd());
+ delete Config->openSockfd[count];
}
+ else
+ BoundPortCount++;
}
+ /*if (!BindSocket(Config->openSockfd[count],client,server,Config->ports[count],Config->addrs[count]))
+ {
+ this->Log(DEFAULT,"Failed to bind port [%s:%d]: %s",Config->addrs[count],Config->ports[count],strerror(errno));
+ }*/
}
}
return InitialPortCount + BoundPortCount;
@@ -420,21 +487,22 @@ int InspIRCd::BindPorts(bool bail)
for (int count = 0; count < PortCount; count++)
{
- if ((Config->openSockfd[BoundPortCount] = OpenTCPSocket()) == ERROR)
+ int fd = OpenTCPSocket();
+ if (fd == ERROR)
{
- this->Log(DEBUG,"Bad fd %d binding port [%s:%d]",Config->openSockfd[BoundPortCount],Config->addrs[count],Config->ports[count]);
+ this->Log(DEBUG,"Bad fd %d binding port [%s:%d]",fd,Config->addrs[count],Config->ports[count]);
}
else
{
- if (!BindSocket(Config->openSockfd[BoundPortCount],client,server,Config->ports[count],Config->addrs[count]))
+ Config->openSockfd[count] = new ListenSocket(this,fd,client,server,Config->ports[count],Config->addrs[count]);
+ if (Config->openSockfd[count]->GetFd() > -1)
{
- this->Log(DEFAULT,"Failed to bind port [%s:%d]: %s",Config->addrs[count],Config->ports[count],strerror(errno));
- }
- else
- {
- /* well we at least bound to one socket so we'll continue */
BoundPortCount++;
}
+ /*if (!BindSocket(Config->openSockfd[BoundPortCount],client,server,Config->ports[count],Config->addrs[count]))
+ {
+ this->Log(DEFAULT,"Failed to bind port [%s:%d]: %s",Config->addrs[count],Config->ports[count],strerror(errno));
+ }*/
}
}
return BoundPortCount;
diff --git a/src/socketengine.cpp b/src/socketengine.cpp
index 3f34d75fb..71ae4fe9b 100644
--- a/src/socketengine.cpp
+++ b/src/socketengine.cpp
@@ -15,21 +15,30 @@
*/
#include "inspircd_config.h"
-#include "globals.h"
#include "inspircd.h"
-#ifdef USE_EPOLL
-#include <sys/epoll.h>
-#endif
-#ifdef USE_KQUEUE
-#include <sys/types.h>
-#include <sys/event.h>
-#include <sys/time.h>
-#endif
#include <vector>
#include <string>
#include "socketengine.h"
-#include "inspircd.h"
+int EventHandler::GetFd()
+{
+ return this->fd;
+}
+
+void EventHandler::SetFd(int FD)
+{
+ this->fd = FD;
+}
+
+bool EventHandler::Readable()
+{
+ return true;
+}
+
+bool EventHandler::Writeable()
+{
+ return false;
+}
SocketEngine::SocketEngine(InspIRCd* Instance) : ServerInstance(Instance)
{
@@ -40,27 +49,26 @@ SocketEngine::~SocketEngine()
{
}
-char SocketEngine::GetType(int fd)
+bool SocketEngine::AddFd(EventHandler* eh)
{
- if ((fd < 0) || (fd > MAX_DESCRIPTORS))
- return X_EMPTY_SLOT;
- /* Mask off the top bit used for 'read/write' state */
- return (ref[fd] & ~0x80);
+ return true;
}
-bool SocketEngine::AddFd(int fd, bool readable, char type)
+bool SocketEngine::HasFd(int fd)
{
- return true;
+ if ((fd < 0) || (fd > MAX_DESCRIPTORS))
+ return false;
+ return ref[fd];
}
-bool SocketEngine::HasFd(int fd)
+EventHandler* SocketEngine::GetRef(int fd)
{
if ((fd < 0) || (fd > MAX_DESCRIPTORS))
return false;
- return (ref[fd] != 0);
+ return ref[fd];
}
-bool SocketEngine::DelFd(int fd)
+bool SocketEngine::DelFd(EventHandler* eh)
{
return true;
}
@@ -75,7 +83,7 @@ int SocketEngine::GetRemainingFds()
return 0;
}
-int SocketEngine::Wait(int* fdlist)
+int SocketEngine::Wait(EventHandler** fdlist)
{
return 0;
}
@@ -84,3 +92,4 @@ std::string SocketEngine::GetName()
{
return "misconfigured";
}
+
diff --git a/src/socketengine_epoll.cpp b/src/socketengine_epoll.cpp
index 64b1be63d..9057c6d65 100644
--- a/src/socketengine_epoll.cpp
+++ b/src/socketengine_epoll.cpp
@@ -15,15 +15,12 @@
*/
#include "inspircd_config.h"
-#include "globals.h"
#include "inspircd.h"
#include <sys/epoll.h>
#include <vector>
#include <string>
#include "socketengine_epoll.h"
-#include "inspircd.h"
-
EPollEngine::EPollEngine(InspIRCd* Instance) : SocketEngine(Instance)
{
EngineHandle = epoll_create(MAX_DESCRIPTORS);
@@ -44,8 +41,9 @@ EPollEngine::~EPollEngine()
close(EngineHandle);
}
-bool EPollEngine::AddFd(int fd, bool readable, char type)
+bool EPollEngine::AddFd(EventHandler* eh)
{
+ int fd = eh->GetFd();
if ((fd < 0) || (fd > MAX_DESCRIPTORS))
{
ServerInstance->Log(DEFAULT,"ERROR: FD of %d added above max of %d",fd,MAX_DESCRIPTORS);
@@ -59,19 +57,14 @@ bool EPollEngine::AddFd(int fd, bool readable, char type)
if (ref[fd])
return false;
- ref[fd] = type;
+ ref[fd] = eh;
- if (readable)
- {
- ServerInstance->Log(DEBUG,"Set readbit");
- ref[fd] |= X_READBIT;
- }
- ServerInstance->Log(DEBUG,"Add socket %d",fd);
+ ServerInstance->Log(DEBUG,"***** Add socket %d",fd);
struct epoll_event ev;
memset(&ev,0,sizeof(struct epoll_event));
ServerInstance->Log(DEBUG,"epoll: Add socket to events, ep=%d socket=%d",EngineHandle,fd);
- readable ? ev.events = EPOLLIN : ev.events = EPOLLOUT;
+ eh->Readable() ? ev.events = EPOLLIN : ev.events = EPOLLOUT;
ev.data.fd = fd;
int i = epoll_ctl(EngineHandle, EPOLL_CTL_ADD, fd, &ev);
if (i < 0)
@@ -84,16 +77,17 @@ bool EPollEngine::AddFd(int fd, bool readable, char type)
return true;
}
-bool EPollEngine::DelFd(int fd)
+bool EPollEngine::DelFd(EventHandler* eh)
{
- ServerInstance->Log(DEBUG,"EPollEngine::DelFd(%d)",fd);
+ ServerInstance->Log(DEBUG,"EPollEngine::DelFd(%d)",eh->GetFd());
+ int fd = eh->GetFd();
if ((fd < 0) || (fd > MAX_DESCRIPTORS))
return false;
struct epoll_event ev;
memset(&ev,0,sizeof(struct epoll_event));
- ref[fd] && X_READBIT ? ev.events = EPOLLIN : ev.events = EPOLLOUT;
+ ref[fd]->Readable() ? ev.events = EPOLLIN : ev.events = EPOLLOUT;
ev.data.fd = fd;
int i = epoll_ctl(EngineHandle, EPOLL_CTL_DEL, fd, &ev);
if (i < 0)
@@ -103,7 +97,7 @@ bool EPollEngine::DelFd(int fd)
}
CurrentSetSize--;
- ref[fd] = 0;
+ ref[fd] = NULL;
return true;
}
@@ -117,13 +111,13 @@ int EPollEngine::GetRemainingFds()
return MAX_DESCRIPTORS - CurrentSetSize;
}
-int EPollEngine::Wait(int* fdlist)
+int EPollEngine::Wait(EventHandler** fdlist)
{
int result = 0;
int i = epoll_wait(EngineHandle, events, MAX_DESCRIPTORS, 50);
for (int j = 0; j < i; j++)
- fdlist[result++] = events[j].data.fd;
+ fdlist[result++] = ref[events[j].data.fd];
return result;
}
@@ -132,3 +126,4 @@ std::string EPollEngine::GetName()
{
return "epoll";
}
+
diff --git a/src/socketengine_kqueue.cpp b/src/socketengine_kqueue.cpp
index 0c3226113..14864da79 100644
--- a/src/socketengine_kqueue.cpp
+++ b/src/socketengine_kqueue.cpp
@@ -45,8 +45,9 @@ KQueueEngine::~KQueueEngine()
close(EngineHandle);
}
-bool KQueueEngine::AddFd(int fd, bool readable, char type)
+bool KQueueEngine::AddFd(EventHandler* eh)
{
+ int fd = eh->GetFd();
if ((fd < 0) || (fd > MAX_DESCRIPTORS))
{
ServerInstance->Log(DEFAULT,"ERROR: FD of %d added above max of %d",fd,MAX_DESCRIPTORS);
@@ -61,17 +62,12 @@ bool KQueueEngine::AddFd(int fd, bool readable, char type)
if (ref[fd])
return false;
- ref[fd] = type;
- if (readable)
- {
- ServerInstance->Log(DEBUG,"Set readbit");
- ref[fd] |= X_READBIT;
- }
+ ref[fd] = eh;
ServerInstance->Log(DEBUG,"Add socket %d",fd);
struct kevent ke;
ServerInstance->Log(DEBUG,"kqueue: Add socket to events, kq=%d socket=%d",EngineHandle,fd);
- EV_SET(&ke, fd, readable ? EVFILT_READ : EVFILT_WRITE, EV_ADD, 0, 0, NULL);
+ EV_SET(&ke, fd, eh->Readable() ? EVFILT_READ : EVFILT_WRITE, EV_ADD, 0, 0, NULL);
int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
if (i == -1)
{
@@ -83,15 +79,17 @@ bool KQueueEngine::AddFd(int fd, bool readable, char type)
return true;
}
-bool KQueueEngine::DelFd(int fd)
+bool KQueueEngine::DelFd(EventHandler* eh)
{
+ int fd = eh->GetFd();
+
ServerInstance->Log(DEBUG,"KQueueEngine::DelFd(%d)",fd);
if ((fd < 0) || (fd > MAX_DESCRIPTORS))
return false;
struct kevent ke;
- EV_SET(&ke, fd, ref[fd] & X_READBIT ? EVFILT_READ : EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
+ EV_SET(&ke, fd, eh->Readable() ? EVFILT_READ : EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
if (i == -1)
{
@@ -100,7 +98,7 @@ bool KQueueEngine::DelFd(int fd)
}
CurrentSetSize--;
- ref[fd] = 0;
+ ref[fd] = NULL;
return true;
}
@@ -114,7 +112,7 @@ int KQueueEngine::GetRemainingFds()
return MAX_DESCRIPTORS - CurrentSetSize;
}
-int KQueueEngine::Wait(int* fdlist)
+int KQueueEngine::Wait(EventHandler** fdlist)
{
int result = 0;
@@ -122,7 +120,7 @@ int KQueueEngine::Wait(int* fdlist)
ts.tv_sec = 0;
int i = kevent(EngineHandle, NULL, 0, &ke_list[0], MAX_DESCRIPTORS, &ts);
for (int j = 0; j < i; j++)
- fdlist[result++] = ke_list[j].ident;
+ fdlist[result++] = ref[ke_list[j].ident];
return result;
}
diff --git a/src/socketengine_select.cpp b/src/socketengine_select.cpp
index 4e79dc19b..ec242b76d 100644
--- a/src/socketengine_select.cpp
+++ b/src/socketengine_select.cpp
@@ -35,8 +35,9 @@ SelectEngine::~SelectEngine()
ServerInstance->Log(DEBUG,"SelectEngine::~SelectEngine()");
}
-bool SelectEngine::AddFd(int fd, bool readable, char type)
+bool SelectEngine::AddFd(EventHandler* eh)
{
+ int fd = eh->GetFd();
if ((fd < 0) || (fd > MAX_DESCRIPTORS))
{
ServerInstance->Log(DEFAULT,"ERROR: FD of %d added above max of %d",fd,MAX_DESCRIPTORS);
@@ -53,20 +54,17 @@ bool SelectEngine::AddFd(int fd, bool readable, char type)
if (ref[fd])
return false;
- ref[fd] = type;
- if (readable)
- {
- ServerInstance->Log(DEBUG,"Set readbit");
- ref[fd] |= X_READBIT;
- }
+ ref[fd] = eh;
ServerInstance->Log(DEBUG,"Add socket %d",fd);
CurrentSetSize++;
return true;
}
-bool SelectEngine::DelFd(int fd)
+bool SelectEngine::DelFd(EventHandler* eh)
{
+ int fd = eh->GetFd();
+
ServerInstance->Log(DEBUG,"SelectEngine::DelFd(%d)",fd);
if ((fd < 0) || (fd > MAX_DESCRIPTORS))
@@ -80,7 +78,7 @@ bool SelectEngine::DelFd(int fd)
}
CurrentSetSize--;
- ref[fd] = 0;
+ ref[fd] = NULL;
return true;
}
@@ -94,7 +92,7 @@ int SelectEngine::GetRemainingFds()
return FD_SETSIZE - CurrentSetSize;
}
-int SelectEngine::Wait(int* fdlist)
+int SelectEngine::Wait(EventHandler** fdlist)
{
int result = 0;
@@ -104,7 +102,7 @@ int SelectEngine::Wait(int* fdlist)
int sresult;
for (std::map<int,int>::iterator a = fds.begin(); a != fds.end(); a++)
{
- if (ref[a->second] & X_READBIT)
+ if (ref[a->second]->Readable())
{
FD_SET (a->second, &rfdset);
}
@@ -122,7 +120,7 @@ int SelectEngine::Wait(int* fdlist)
for (std::map<int,int>::iterator a = fds.begin(); a != fds.end(); a++)
{
if ((FD_ISSET (a->second, &rfdset)) || (FD_ISSET (a->second, &wfdset)))
- fdlist[result++] = a->second;
+ fdlist[result++] = ref[a->second];
}
}
diff --git a/src/userprocess.cpp b/src/userprocess.cpp
index 8c048c760..aa16bd90e 100644
--- a/src/userprocess.cpp
+++ b/src/userprocess.cpp
@@ -55,11 +55,9 @@ void InspIRCd::ProcessUser(userrec* cu)
{
int result = EAGAIN;
- if (cu->fd == FD_MAGIC_NUMBER)
+ if (cu->GetFd() == FD_MAGIC_NUMBER)
return;
- this->Log(DEBUG,"Processing user with fd %d",cu->fd);
-
if (this->Config->GetIOHook(cu->GetPort()))
{
int result2 = 0;
@@ -67,7 +65,7 @@ void InspIRCd::ProcessUser(userrec* cu)
try
{
- MOD_RESULT = this->Config->GetIOHook(cu->GetPort())->OnRawSocketRead(cu->fd,ReadBuffer,sizeof(ReadBuffer),result2);
+ MOD_RESULT = this->Config->GetIOHook(cu->GetPort())->OnRawSocketRead(cu->GetFd(),ReadBuffer,sizeof(ReadBuffer),result2);
this->Log(DEBUG,"Data result returned by module: %d",MOD_RESULT);
}
catch (ModuleException& modexcept)
@@ -115,7 +113,7 @@ void InspIRCd::ProcessUser(userrec* cu)
ReadBuffer[result] = '\0';
current = cu;
- currfd = current->fd;
+ currfd = current->GetFd();
// add the data to the users buffer
if (result > 0)
@@ -216,7 +214,7 @@ void InspIRCd::ProcessUser(userrec* cu)
if (single_line.length() > 512)
single_line.resize(512);
- userrec* old_comp = this->fd_ref_table[currfd];
+ EventHandler* old_comp = this->SE->GetRef(currfd);
this->Parser->ProcessBuffer(single_line,current);
/*
@@ -225,8 +223,8 @@ void InspIRCd::ProcessUser(userrec* cu)
* there used to be an ugly, slow loop here. Now we have a reference
* table, life is much easier (and FASTER)
*/
- userrec* new_comp = this->fd_ref_table[currfd];
- if ((currfd < 0) || (!this->fd_ref_table[currfd]) || (old_comp != new_comp))
+ EventHandler* new_comp = this->SE->GetRef(currfd);
+ if (old_comp != new_comp)
{
return;
}
@@ -270,11 +268,10 @@ void InspIRCd::DoSocketTimeouts(time_t TIME)
{
InspSocket* s = *a;
int fd = s->GetFd();
- if ((s) && (fd >= 0) && (fd < MAX_DESCRIPTORS) && (this->socket_ref[fd] != NULL) && (s->Timeout(TIME)))
+ if ((s) && (fd >= 0) && (fd < MAX_DESCRIPTORS) && (this->SE->GetRef(fd) == s) && (s->Timeout(TIME)))
{
this->Log(DEBUG,"userprocess.cpp: Socket poll returned false, close and bail");
- this->socket_ref[fd] = NULL;
- SE->DelFd(fd);
+ SE->DelFd(s);
this->module_sockets.erase(a);
s->Close();
DELETE(s);
diff --git a/src/users.cpp b/src/users.cpp
index 261ee491e..3953db233 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -138,12 +138,12 @@ UserResolver::UserResolver(InspIRCd* Instance, userrec* user, std::string to_res
Resolver(Instance, to_resolve, forward ? DNS_QUERY_FORWARD : DNS_QUERY_REVERSE), bound_user(user)
{
this->fwd = forward;
- this->bound_fd = user->fd;
+ this->bound_fd = user->GetFd();
}
void UserResolver::OnLookupComplete(const std::string &result)
{
- if ((!this->fwd) && (ServerInstance->fd_ref_table[this->bound_fd] == this->bound_user))
+ if ((!this->fwd) && (ServerInstance->SE->GetRef(this->bound_fd) == this->bound_user))
{
ServerInstance->Log(DEBUG,"Commencing forward lookup");
this->bound_user->stored_host = result;
@@ -161,7 +161,7 @@ void UserResolver::OnLookupComplete(const std::string &result)
ServerInstance->Log(DEBUG,"Error in resolver: %s",e.GetReason());
}
}
- else if ((this->fwd) && (ServerInstance->fd_ref_table[this->bound_fd] == this->bound_user))
+ else if ((this->fwd) && (ServerInstance->SE->GetRef(this->bound_fd) == this->bound_user))
{
/* Both lookups completed */
if (this->bound_user->GetIPString() == result)
@@ -196,7 +196,7 @@ void UserResolver::OnLookupComplete(const std::string &result)
void UserResolver::OnError(ResolverError e, const std::string &errormessage)
{
- if (ServerInstance->fd_ref_table[this->bound_fd] == this->bound_user)
+ if (ServerInstance->SE->GetRef(this->bound_fd) == this->bound_user)
{
/* Error message here */
this->bound_user->WriteServ("NOTICE Auth :*** Could not resolve your hostname, using your IP address (%s) instead.", this->bound_user->GetIPString());
@@ -262,9 +262,10 @@ userrec::userrec(InspIRCd* Instance) : ServerInstance(Instance)
*password = *nick = *ident = *host = *dhost = *fullname = *awaymsg = *oper = 0;
server = (char*)Instance->FindServerNamePtr(Instance->Config->ServerName);
reset_due = ServerInstance->Time();
- lines_in = fd = lastping = signon = idle_lastmsg = nping = registered = 0;
+ lines_in = lastping = signon = idle_lastmsg = nping = registered = 0;
timeout = flood = bytes_in = bytes_out = cmds_in = cmds_out = 0;
haspassed = dns_done = false;
+ fd = -1;
recvq = "";
sendq = "";
WriteError = "";
@@ -690,7 +691,7 @@ void userrec::QuitUser(InspIRCd* Instance, userrec *user,const std::string &quit
}
}
- Instance->SE->DelFd(user->fd);
+ Instance->SE->DelFd(user);
user->CloseSocket();
}
@@ -714,7 +715,6 @@ void userrec::QuitUser(InspIRCd* Instance, userrec *user,const std::string &quit
Instance->Log(DEBUG,"deleting user hash value %lx",(unsigned long)user);
if (IS_LOCAL(user))
{
- Instance->fd_ref_table[user->fd] = NULL;
if (find(Instance->local_users.begin(),Instance->local_users.end(),user) != Instance->local_users.end())
Instance->local_users.erase(find(Instance->local_users.begin(),Instance->local_users.end(),user));
}
@@ -874,7 +874,6 @@ void userrec::AddClient(InspIRCd* Instance, int socket, int port, bool iscached,
_new->sendqmax = class_sqmax;
_new->recvqmax = class_rqmax;
- Instance->fd_ref_table[socket] = _new;
Instance->local_users.push_back(_new);
if (Instance->local_users.size() > Instance->Config->SoftLimit)
@@ -919,7 +918,7 @@ void userrec::AddClient(InspIRCd* Instance, int socket, int port, bool iscached,
if (socket > -1)
{
- if (!Instance->SE->AddFd(socket,true,X_ESTAB_CLIENT))
+ if (!Instance->SE->AddFd(_new))
{
userrec::QuitUser(Instance, _new, "Internal error handling connection");
return;
@@ -1799,3 +1798,9 @@ void userrec::ShowRULES()
this->WriteServ("NOTICE %s :End of %s rules.",this->nick,ServerInstance->Config->ServerName);
}
+void userrec::HandleEvent(EventType et)
+{
+ /* WARNING: May delete this user! */
+ ServerInstance->ProcessUser(this);
+}
+