diff options
author | brain <brain@e03df62e-2008-0410-955e-edbf42e46eb7> | 2006-08-18 01:08:14 +0000 |
---|---|---|
committer | brain <brain@e03df62e-2008-0410-955e-edbf42e46eb7> | 2006-08-18 01:08:14 +0000 |
commit | e381b06561228aaea752deda20a62c6dc99a560e (patch) | |
tree | 2119fe8bc8895597261935f389004e3c6bafe6a8 | |
parent | 3c82d2d767186dd6d386dbbe08219ad8612e299e (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
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); +} + |