diff options
author | danieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7> | 2009-09-21 13:26:31 +0000 |
---|---|---|
committer | danieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7> | 2009-09-21 13:26:31 +0000 |
commit | e2af2347fc035d702e45f12e772223a8d578410d (patch) | |
tree | bfd80aac2858a9f4faedc316794fc1051dbaa72c /include | |
parent | 16fc672b685752007e47aed0fb97bc1ee7443c76 (diff) |
Create StreamSocket for IO hooking implementation
Fixes the SSL SendQ bug
Removes duplicate code between User and BufferedSocket
Simplify SSL module API
Simplify EventHandler API (Readable/Writeable moved to SE)
Add hook for culled objects to invoke callbacks prior to destructor
Replace SocketCull with GlobalCull now that sockets can close themselves
Shorten common case of user read/parse/write path:
User::Write is now zero-copy up to syscall/SSL invocation
User::Read has only two copy/scan passes from read() to ProcessCommand
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11752 e03df62e-2008-0410-955e-edbf42e46eb7
Diffstat (limited to 'include')
-rw-r--r-- | include/base.h | 4 | ||||
-rw-r--r-- | include/cull_list.h | 9 | ||||
-rw-r--r-- | include/inspircd.h | 19 | ||||
-rw-r--r-- | include/inspsocket.h | 327 | ||||
-rw-r--r-- | include/modules.h | 59 | ||||
-rw-r--r-- | include/socket.h | 2 | ||||
-rw-r--r-- | include/socketengine.h | 84 | ||||
-rw-r--r-- | include/socketengines/socketengine_epoll.h | 9 | ||||
-rw-r--r-- | include/socketengines/socketengine_iocp.h | 6 | ||||
-rw-r--r-- | include/socketengines/socketengine_kqueue.h | 9 | ||||
-rw-r--r-- | include/socketengines/socketengine_poll.h | 7 | ||||
-rw-r--r-- | include/socketengines/socketengine_ports.h | 8 | ||||
-rw-r--r-- | include/socketengines/socketengine_select.h | 8 | ||||
-rw-r--r-- | include/users.h | 75 |
14 files changed, 165 insertions, 461 deletions
diff --git a/include/base.h b/include/base.h index ab52545f9..b66051caf 100644 --- a/include/base.h +++ b/include/base.h @@ -28,7 +28,9 @@ class CoreExport classbase public: classbase(); - virtual ~classbase() { } + // Called just prior to destruction via cull list + virtual void cull(); + virtual ~classbase(); }; /** BoolSet is a utility class designed to hold eight bools in a bitmask. diff --git a/include/cull_list.h b/include/cull_list.h index 8c3827642..bd2fb45da 100644 --- a/include/cull_list.h +++ b/include/cull_list.h @@ -19,17 +19,14 @@ * avoid problems with references to deleted pointers if an object were deleted * during execution. */ -class CoreExport CullList : public classbase +class CoreExport CullList { - private: - std::vector<classbase*> list; + std::set<classbase*> list; public: - CullList() {} - /** Adds an item to the cull list */ - void AddItem(classbase* item) { list.push_back(item); } + void AddItem(classbase* item) { list.insert(item); } /** Applies the cull list (deletes the contents) */ diff --git a/include/inspircd.h b/include/inspircd.h index b927f0b1b..72e49c09a 100644 --- a/include/inspircd.h +++ b/include/inspircd.h @@ -277,7 +277,6 @@ class serverstats : public classbase class InspIRCd; -DEFINE_HANDLER1(ProcessUserHandler, void, User*); DEFINE_HANDLER2(IsNickHandler, bool, const char*, size_t); DEFINE_HANDLER1(IsIdentHandler, bool, const char*); DEFINE_HANDLER1(FloodQuitUserHandler, void, User*); @@ -386,7 +385,6 @@ class CoreExport InspIRCd : public classbase /**** Functors ****/ - ProcessUserHandler HandleProcessUser; IsNickHandler HandleIsNick; IsIdentHandler HandleIsIdent; FloodQuitUserHandler HandleFloodQuitUser; @@ -394,11 +392,6 @@ class CoreExport InspIRCd : public classbase IsSIDHandler HandleIsSID; RehashHandler HandleRehash; - /** BufferedSocket classes pending deletion after being closed. - * We don't delete these immediately as this may cause a segmentation fault. - */ - std::map<BufferedSocket*,BufferedSocket*> SocketCull; - /** Globally accessible fake user record. This is used to force mode changes etc across s2s, etc.. bit ugly, but.. better than how this was done in 1.1 * Reason for it: * kludge alert! @@ -527,13 +520,6 @@ class CoreExport 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 - * marked for deletion in the global CullList. - */ - caller1<void, User*> ProcessUser; - /** Bind all ports specified in the configuration file. * @return The number of ports bound without error */ @@ -924,11 +910,6 @@ class CoreExport InspIRCd : public classbase */ int Run(); - /** Force all BufferedSockets to be removed which are due to - * be culled. - */ - void BufferedSocketCull(); - /** Adds an extban char to the 005 token. */ void AddExtBanChar(char c); diff --git a/include/inspsocket.h b/include/inspsocket.h index 32f2dab1a..73aa748a0 100644 --- a/include/inspsocket.h +++ b/include/inspsocket.h @@ -36,6 +36,10 @@ enum BufferedSocketState */ enum BufferedSocketError { + /** No error */ + I_ERR_NONE, + /** Socket was closed by peer */ + I_ERR_DISCONNECT, /** Socket connect timed out */ I_ERR_TIMEOUT, /** Socket could not be created */ @@ -44,17 +48,16 @@ enum BufferedSocketError I_ERR_CONNECT, /** Socket could not bind to local port/ip */ I_ERR_BIND, - /** Socket could not reslve host (depreciated) */ - I_ERR_RESOLVE, /** Socket could not write data */ I_ERR_WRITE, /** No more file descriptors left to create socket! */ - I_ERR_NOMOREFDS + I_ERR_NOMOREFDS, + /** Some other error */ + I_ERR_OTHER }; /* Required forward declarations */ class BufferedSocket; -class InspIRCd; /** Used to time out socket connections */ @@ -65,10 +68,6 @@ class CoreExport SocketTimeout : public Timer */ BufferedSocket* sock; - /** Server instance creating the timeout class - */ - InspIRCd* ServerInstance; - /** File descriptor of class this is attached to */ int sfd; @@ -81,7 +80,7 @@ class CoreExport SocketTimeout : public Timer * @param secs_from_now Seconds from now to time out * @param now The current time */ - SocketTimeout(int fd, InspIRCd* Instance, BufferedSocket* thesock, long secs_from_now, time_t now) : Timer(secs_from_now, now), sock(thesock), ServerInstance(Instance), sfd(fd) { }; + SocketTimeout(int fd, BufferedSocket* thesock, long secs_from_now, time_t now) : Timer(secs_from_now, now), sock(thesock), sfd(fd) { } /** Handle tick event */ @@ -89,6 +88,67 @@ class CoreExport SocketTimeout : public Timer }; /** + * StreamSocket is a class that wraps a TCP socket and handles send + * and receive queues, including passing them to IO hooks + */ +class CoreExport StreamSocket : public EventHandler +{ + /** Module that handles raw I/O for this socket, or NULL */ + Module *IOHook; + /** Private send queue. Note that individual strings may be shared + */ + std::deque<std::string> sendq; + /** Length, in bytes, of the sendq */ + size_t sendq_len; + /** Error - if nonempty, the socket is dead, and this is the reason. */ + std::string error; + protected: + std::string recvq; + public: + StreamSocket() : IOHook(NULL), sendq_len(0) {} + inline Module* GetIOHook() { return IOHook; } + inline void AddIOHook(Module* m) { IOHook = m; } + inline void DelIOHook() { IOHook = NULL; } + /** Handle event from socket engine. + * This will call OnDataReady if there is *new* data in recvq + */ + virtual void HandleEvent(EventType et, int errornum = 0); + /** Dispatched from HandleEvent */ + virtual void DoRead(); + /** Dispatched from HandleEvent */ + virtual void DoWrite(); + + /** Sets the error message for this socket. Once set, the socket is dead. */ + void SetError(const std::string& err) { if (error.empty()) error = err; } + + /** Gets the error message for this socket. */ + const std::string& getError() const { return error; } + + /** Called when new data is present in recvq */ + virtual void OnDataReady() = 0; + /** Called when the socket gets an error from socket engine or IO hook */ + virtual void OnError(BufferedSocketError e) = 0; + + /** Send the given data out the socket, either now or when writes unblock + */ + void WriteData(const std::string& data); + /** Convenience function: read a line from the socket + * @param line The line read + * @param delim The line delimiter + * @return true if a line was read + */ + bool GetNextLine(std::string& line, char delim = '\n'); + /** Useful for implementing sendq exceeded */ + inline const size_t getSendQSize() const { return sendq_len; } + + /** + * Close the socket, remove from socket engine, etc + */ + virtual void Close(); + /** This ensures that close is called prior to destructor */ + virtual void cull(); +}; +/** * BufferedSocket is an extendable socket class which modules * can use for TCP socket support. It is fully integrated * into InspIRCds socket loop and attaches its sockets to @@ -97,34 +157,13 @@ class CoreExport SocketTimeout : public Timer * * To use BufferedSocket, you must inherit a class from it. */ -class CoreExport BufferedSocket : public EventHandler +class CoreExport BufferedSocket : public StreamSocket { public: - - /** Bind IP - */ - std::string cbindip; - - /** Instance we were created by - */ - InspIRCd* ServerInstance; - - /** Timeout class or NULL + /** Timeout object or NULL */ SocketTimeout* Timeout; - /** Socket output buffer (binary safe) - */ - std::deque<std::string> outbuffer; - - /** The hostname connected to - */ - char host[MAXBUF]; - - /** The port connected to - */ - int port; - /** * The state for this socket, either * listening, connecting, connected @@ -132,220 +171,52 @@ class CoreExport BufferedSocket : public EventHandler */ BufferedSocketState state; - /** - * The IP address being connected - * to stored in string form for - * easy retrieval by accessors. - */ - char IP[MAXBUF]; - - /** - * Used by accept() to indicate the - * sizes of the sockaddr_in structures - */ - socklen_t length; - - /** Flushes the write buffer - * @returns true if the writing failed, false if it was successful - */ - bool FlushWriteBuffer(); - - /** Set the queue sizes - * This private method sets the operating system queue - * sizes for this socket to 65535 so that it can queue - * more information without application-level queueing - * which was required in older software. - */ - void SetQueues(); - - /** When the socket has been marked as closing, this flag - * will be set to true, then the next time the socket is - * examined, the socket is deleted and closed. - */ - bool ClosePending; - - /** - * Bind to an address - * @param ip IP to bind to - * @return True is the binding succeeded - */ - bool BindAddr(const std::string &ip); - - /** (really) Try bind to a given IP setup. For internal use only. - */ - bool DoBindMagic(const std::string ¤t_ip); - - /** - * The default constructor does nothing - * and should not be used. - */ - BufferedSocket(InspIRCd* SI); - + BufferedSocket(); /** * This constructor is used to associate * an existing connecting with an BufferedSocket * class. The given file descriptor must be * valid, and when initialized, the BufferedSocket - * will be set with the given IP address - * and placed in CONNECTED state. - */ - BufferedSocket(InspIRCd* SI, int newfd, const char* ip); - - /** - * This constructor is used to create a new outbound connection to another host. - * Note that if you specify a hostname in the 'ipaddr' parameter, this class will not - * connect. You must resolve your hostnames before passing them to BufferedSocket. To do so, - * you should use the nonblocking class 'Resolver'. - * @param ipaddr The IP to connect to, or bind to - * @param port The port number to connect to - * @param maxtime Number of seconds to wait, if connecting, before the connection times out and an OnTimeout() event is generated - * @param connectbindip When creating an outbound connection, the IP to bind the connection to. If not defined, the port is not bound. - * @return On exit, GetState() returns I_ERROR if an error occured, and errno can be used to read the socket error. - */ - BufferedSocket(InspIRCd* SI, const std::string &ipaddr, int port, unsigned long maxtime, const std::string &connectbindip = ""); - - /** - * This method is called when an outbound - * connection on your socket is completed. - * @return false to abort the connection, true to continue - */ - virtual bool OnConnected(); - - /** - * This method is called when an error occurs. - * A closed socket in itself is not an error, - * however errors also generate close events. - * @param e The error type which occured + * will be placed in CONNECTED state. */ - virtual void OnError(BufferedSocketError e); + BufferedSocket(int newfd); - /** - * When an established connection is terminated, - * the OnDisconnect method is triggered. + /** Begin connection to the given address + * This will create a socket, register with socket engine, and start the asynchronous + * connection process. If an error is detected at this point (such as out of file descriptors), + * OnError will be called; otherwise, the state will become CONNECTING. + * @param dest Address to connect to + * @param bind Address to bind to (if NULL, no bind will be done) + * @param timeout Time to wait for connection */ - virtual int OnDisconnect(); + void DoConnect(const std::string &ipaddr, int aport, unsigned long maxtime, const std::string &connectbindip); - /** - * When there is data waiting to be read on a - * socket, the OnDataReady() method is called. - * Within this method, you *MUST* call the Read() - * method to read any pending data. At its lowest - * level, this event is signalled by the core via - * the socket engine. If you return false from this - * function, the core removes your socket from its - * list and erases it from the socket engine, then - * calls BufferedSocket::Close() and deletes it. - * @return false to close the socket + /** This method is called when an outbound connection on your socket is + * completed. */ - virtual bool OnDataReady(); + virtual void OnConnected(); - /** - * When it is ok to write to the socket, and a - * write event was requested, this method is - * triggered. - * - * Within this method you should call - * write() or send() etc, to send data to the - * other end of the socket. - * - * Further write events will not be triggered - * unless you call SocketEngine::WantWrite(). - * - * The default behaviour of this method is to - * flush the write buffer, respecting the IO - * hooking modules. - * - * XXX: this used to be virtual, ask us if you need it to be so. - * @return false to close the socket + /** When there is data waiting to be read on a socket, the OnDataReady() + * method is called. */ - bool OnWriteReady(); + virtual void OnDataReady() = 0; /** - * When an outbound connection fails, and the - * attempt times out, you will receive this event. - * The method will trigger once maxtime seconds are - * reached (as given in the constructor) just - * before the socket's descriptor is closed. - * A failed DNS lookup may cause this event if - * the DNS server is not responding, as well as - * a failed connect() call, because DNS lookups are - * nonblocking as implemented by this class. + * When an outbound connection fails, and the attempt times out, you + * will receive this event. The method will trigger once maxtime + * seconds are reached (as given in the constructor) just before the + * socket's descriptor is closed. A failed DNS lookup may cause this + * event if the DNS server is not responding, as well as a failed + * connect() call, because DNS lookups are nonblocking as implemented by + * this class. */ virtual void OnTimeout(); - /** - * Whenever close() is called, OnClose() will be - * called first. Please note that this means - * OnClose will be called alongside OnError(), - * OnTimeout(), and Close(). - */ - virtual void OnClose(); - - /** - * Reads all pending bytes from the socket - * into a char* array which can be up to - * 16 kilobytes in length. - */ - virtual const char* Read(); - - /** - * Returns the IP address associated with - * this connection, or an empty string if - * no IP address exists. - */ - std::string GetIP(); - - /** - * Writes a std::string to the socket. No carriage - * returns or linefeeds are appended to the string. - * @param data The data to send - */ - virtual void Write(const std::string &data); - - /** - * Changes the socket's state. The core uses this - * to change socket states, and you should not call - * it directly. - */ - void SetState(BufferedSocketState s); - - /** - * Returns the current socket state. - */ - BufferedSocketState GetState(); - - /** Mark a socket as being connected and call appropriate events. - */ - bool InternalMarkConnected(); - - /** - * This method causes the socket to close, and may - * also be triggered by other methods such as OnTimeout - * and OnError. - */ - virtual void Close(); - - /** - * The destructor may implicitly call OnClose(), and - * will close() and shutdown() the file descriptor - * used for this socket. - */ virtual ~BufferedSocket(); - - /** - * This method attempts to connect to a hostname. - * This method is asyncronous. - * @param maxtime Number of seconds to wait, if connecting, before the connection times out and an OnTimeout() event is generated - */ - virtual bool DoConnect(unsigned long maxtime); - - /** Handle event from EventHandler parent class - */ - void HandleEvent(EventType et, int errornum = 0); - - /** Returns true if this socket is readable - */ - bool Readable(); + protected: + virtual void DoWrite(); + BufferedSocketError BeginConnect(const irc::sockets::sockaddrs& dest, const irc::sockets::sockaddrs& bind, unsigned long timeout); + BufferedSocketError BeginConnect(const std::string &ipaddr, int aport, unsigned long maxtime, const std::string &connectbindip); }; #endif diff --git a/include/modules.h b/include/modules.h index f40cd49fd..982d83754 100644 --- a/include/modules.h +++ b/include/modules.h @@ -406,10 +406,9 @@ enum Implementation I_OnRawMode, I_OnCheckKey, I_OnCheckLimit, I_OnCheckBan, I_OnCheckChannelBan, I_OnExtBanCheck, I_OnStats, I_OnChangeLocalUserHost, I_OnChangeLocalUserGecos, I_OnPreTopicChange, I_OnPostTopicChange, I_OnEvent, I_OnRequest, I_OnGlobalOper, I_OnPostConnect, I_OnAddBan, - I_OnDelBan, I_OnRawSocketAccept, I_OnRawSocketClose, I_OnRawSocketWrite, I_OnRawSocketRead, - I_OnChangeLocalUserGECOS, I_OnUserRegister, I_OnChannelPreDelete, I_OnChannelDelete, + I_OnDelBan, I_OnChangeLocalUserGECOS, I_OnUserRegister, I_OnChannelPreDelete, I_OnChannelDelete, I_OnPostOper, I_OnSyncNetwork, I_OnSetAway, I_OnUserList, I_OnPostCommand, I_OnPostJoin, - I_OnWhoisLine, I_OnBuildExemptList, I_OnRawSocketConnect, I_OnGarbageCollect, I_OnBufferFlushed, + I_OnWhoisLine, I_OnBuildExemptList, I_OnGarbageCollect, I_OnBufferFlushed, I_OnText, I_OnPassCompare, I_OnRunTestSuite, I_OnNamesListItem, I_OnNumeric, I_OnHookIO, I_OnHostCycle, I_OnPreRehash, I_OnModuleRehash, I_OnSendWhoLine, I_OnChangeIdent, I_END @@ -1242,9 +1241,9 @@ class CoreExport Module : public Extensible * @param user The item to possibly install the I/O hook on * @param via The port that <user> connected on */ - virtual void OnHookIO(EventHandler* user, ListenSocketBase* via); + virtual void OnHookIO(StreamSocket*, ListenSocketBase* via); - /** Called immediately after any connection is accepted. This is intended for raw socket + /** Called immediately after any connection is accepted. This is intended for raw socket * processing (e.g. modules which wrap the tcp connection within another library) and provides * no information relating to a user record as the connection has not been assigned yet. * There are no return values from this call as all modules get an opportunity if required to @@ -1254,48 +1253,38 @@ class CoreExport Module : public Extensible * @param server The server IP address and port * @param localport The local port number the user connected to */ - virtual void OnRawSocketAccept(int fd, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server); + virtual void OnStreamSocketAccept(StreamSocket*, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server); - /** Called immediately before any write() operation on a user's socket in the core. Because - * this event is a low level event no user information is associated with it. It is intended - * for use by modules which may wrap connections within another API such as SSL for example. - * return a non-zero result if you have handled the write operation, in which case the core - * will not call write(). - * @param fd The file descriptor of the socket - * @param buffer A char* buffer being written - * @param Number of characters to write - * @return Number of characters actually written or 0 if you didn't handle the operation + /** + * Called when a hooked stream has data to write, or when the socket + * engine returns it as writable + * @param socket The socket in question + * @param sendq Data to send to the socket + * @return 1 if the sendq has been completely emptied, 0 if there is + * still data to send, and -1 if there was an error */ - virtual int OnRawSocketWrite(int fd, const char* buffer, int count); + virtual int OnStreamSocketWrite(StreamSocket*, std::string& sendq); /** Called immediately before any socket is closed. When this event is called, shutdown() * has not yet been called on the socket. * @param fd The file descriptor of the socket prior to close() */ - virtual void OnRawSocketClose(int fd); + virtual void OnStreamSocketClose(StreamSocket*); /** Called immediately upon connection of an outbound BufferedSocket which has been hooked * by a module. * @param fd The file descriptor of the socket immediately after connect() */ - virtual void OnRawSocketConnect(int fd); - - /** Called immediately before any read() operation on a client socket in the core. - * This occurs AFTER the select() or poll() so there is always data waiting to be read - * when this event occurs. - * Your event should return 1 if it has handled the reading itself, which prevents the core - * just using read(). You should place any data read into buffer, up to but NOT GREATER THAN - * the value of count. The value of readresult must be identical to an actual result that might - * be returned from the read() system call, for example, number of bytes read upon success, - * 0 upon EOF or closed socket, and -1 for error. If your function returns a nonzero value, - * you MUST set readresult. - * @param fd The file descriptor of the socket - * @param buffer A char* buffer being read to - * @param count The size of the buffer - * @param readresult The amount of characters read, or 0 - * @return nonzero if the event was handled, in which case readresult must be valid on exit - */ - virtual int OnRawSocketRead(int fd, char* buffer, unsigned int count, int &readresult); + virtual void OnStreamSocketConnect(StreamSocket*); + + /** + * Called when the stream socket has data to read + * @param socket The socket that is ready + * @param recvq The receive queue that new data should be appended to + * @return 1 if new data has been read, 0 if no new data is ready (but the + * socket is still connected), -1 if there was an error or close + */ + virtual int OnStreamSocketRead(StreamSocket*, std::string& recvq); /** Called whenever a user sets away or returns from being away. * The away message is available as a parameter, but should not be modified. diff --git a/include/socket.h b/include/socket.h index 5ca9fc18f..af3eccea2 100644 --- a/include/socket.h +++ b/include/socket.h @@ -99,7 +99,7 @@ namespace irc CoreExport int OpenTCPSocket(const char* addr, int socktype = SOCK_STREAM); /** Return the size of the structure for syscall passing */ - CoreExport int sa_size(irc::sockets::sockaddrs& sa); + CoreExport int sa_size(const irc::sockets::sockaddrs& sa); /** Convert an address-port pair into a binary sockaddr * @param addr The IP address, IPv4 or IPv6 diff --git a/include/socketengine.h b/include/socketengine.h index a191ff12d..4e87f7494 100644 --- a/include/socketengine.h +++ b/include/socketengine.h @@ -69,32 +69,11 @@ class CoreExport EventHandler : public Extensible * other forms of IPC. */ int fd; - - /** Pointer to the module which has hooked the given EventHandler for IO events. - */ - Module *IOHook; public: - - /** Return the current hooker of IO events for this socket, or NULL. - * @return Hooker module, if set, or NULL. - */ - Module *GetIOHook(); - - /** Set a module as hooking IO events on this socket. - * @param IOHooker The module hooking IO - * @return True if the hook could be added, false otherwise. - */ - bool AddIOHook(Module *IOHooker); - - /** Remove IO hooking from a module - * @return True if hooking was successfully removed, false otherwise. - */ - bool DelIOHook(); - /** Get the current file descriptor * @return The file descriptor of this handler */ - int GetFd(); + inline int GetFd() const { return fd; } /** Set a new file desciptor * @param FD The new file descriptor. Do not @@ -112,44 +91,10 @@ class CoreExport EventHandler : public Extensible */ 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. - * - * NOTE: You cannot set both Readable() and - * Writeable() to true. If you wish to receive - * a write event for your object, you must call - * SocketEngine::WantWrite() instead. This will - * trigger your objects next EVENT_WRITE type event. - */ - 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. - * - * NOTE: You cannot set both Readable() and - * Writeable() to true. If you wish to receive - * a write event for your object, you must call - * SocketEngine::WantWrite() instead. This will - * trigger your objects next EVENT_WRITE type event. - */ - 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 and wether you - * previously made a call to SocketEngine::WantWrite(). + * events are received. * @param et either one of EVENT_READ for read events, * and EVENT_WRITE for write events. */ @@ -177,9 +122,6 @@ class CoreExport EventHandler : public Extensible class CoreExport SocketEngine { protected: - /** Owner/Creator - */ - InspIRCd* ServerInstance; /** Handle to socket engine, where needed. */ int EngineHandle; @@ -211,9 +153,8 @@ public: * 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); + SocketEngine(); /** Destructor. * The destructor transparently tidies up @@ -221,15 +162,14 @@ public: */ virtual ~SocketEngine(); - /** 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 an object derived from - * EventHandler which implements HandleEvent() - * and optionally Readable() and Writeable(). + /** 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 an object derived from EventHandler which implements + * HandleEvent(). * @param eh An event handling object to add + * @param writeFirst Wait for a write event instead of a read */ - virtual bool AddFd(EventHandler* eh); + virtual bool AddFd(EventHandler* eh, bool writeFirst = false) = 0; /** If you call this function and pass it an * event handler, that event handler will @@ -242,7 +182,7 @@ public: * @param eh An event handler which wants to * receive the next writeability event. */ - virtual void WantWrite(EventHandler* eh); + virtual void WantWrite(EventHandler* eh) = 0; /** Returns the maximum number of file descriptors * you may store in the socket engine at any one time. @@ -273,7 +213,7 @@ public: * @param force *DANGEROUS* See method description! * @return True if the event handler was removed */ - virtual bool DelFd(EventHandler* eh, bool force = false); + virtual bool DelFd(EventHandler* eh, bool force = false) = 0; /** Returns true if a file descriptor exists in * the socket engine's list. @@ -305,7 +245,7 @@ public: * in /VERSION responses. * @return The socket engine name */ - virtual std::string GetName(); + virtual std::string GetName() = 0; /** Returns true if the file descriptors in the * given event handler are within sensible ranges diff --git a/include/socketengines/socketengine_epoll.h b/include/socketengines/socketengine_epoll.h index 6e6818212..3e08179ae 100644 --- a/include/socketengines/socketengine_epoll.h +++ b/include/socketengines/socketengine_epoll.h @@ -23,8 +23,6 @@ #include <sys/epoll.h> #define EP_DELAY 5 -class InspIRCd; - /** A specialisation of the SocketEngine class, designed to use linux 2.6 epoll(). */ class EPollEngine : public SocketEngine @@ -35,13 +33,12 @@ private: struct epoll_event* events; public: /** Create a new EPollEngine - * @param Instance The creator of this object */ - EPollEngine(InspIRCd* Instance); + EPollEngine(); /** Delete an EPollEngine */ virtual ~EPollEngine(); - virtual bool AddFd(EventHandler* eh); + virtual bool AddFd(EventHandler* eh, bool writeFirst = false); virtual int GetMaxFds(); virtual int GetRemainingFds(); virtual bool DelFd(EventHandler* eh, bool force = false); @@ -57,7 +54,7 @@ class SocketEngineFactory public: /** Create a new instance of SocketEngine based on EpollEngine */ - SocketEngine* Create(InspIRCd* Instance) { return new EPollEngine(Instance); } + SocketEngine* Create() { return new EPollEngine; } }; #endif diff --git a/include/socketengines/socketengine_iocp.h b/include/socketengines/socketengine_iocp.h index 302fdbd2c..dd34227d3 100644 --- a/include/socketengines/socketengine_iocp.h +++ b/include/socketengines/socketengine_iocp.h @@ -121,7 +121,7 @@ public: /** Creates an IOCP Socket Engine * @param Instance The creator of this object */ - IOCPEngine(InspIRCd* Instance); + IOCPEngine(); /** Deletes an IOCP socket engine and all the attached sockets */ @@ -131,7 +131,7 @@ public: * @param eh EventHandler to add * @return True if success, false if no room */ - bool AddFd(EventHandler* eh); + bool AddFd(EventHandler* eh, bool writeFirst = false); /** Gets the maximum number of file descriptors that this engine can handle. * @return The number of file descriptors @@ -234,7 +234,7 @@ class SocketEngineFactory public: /** Create a new instance of SocketEngine based on IOCPEngine */ - SocketEngine* Create(InspIRCd* Instance) { return new IOCPEngine(Instance); } + SocketEngine* Create() { return new IOCPEngine; } }; #endif diff --git a/include/socketengines/socketengine_kqueue.h b/include/socketengines/socketengine_kqueue.h index 41459f561..a09e93553 100644 --- a/include/socketengines/socketengine_kqueue.h +++ b/include/socketengines/socketengine_kqueue.h @@ -24,8 +24,6 @@ #include <sys/time.h> #include "socketengine.h" -class InspIRCd; - /** A specialisation of the SocketEngine class, designed to use FreeBSD kqueue(). */ class KQueueEngine : public SocketEngine @@ -39,13 +37,12 @@ private: struct timespec ts; public: /** Create a new KQueueEngine - * @param Instance The creator of this object */ - KQueueEngine(InspIRCd* Instance); + KQueueEngine(); /** Delete a KQueueEngine */ virtual ~KQueueEngine(); - virtual bool AddFd(EventHandler* eh); + virtual bool AddFd(EventHandler* eh, bool writeFirst = false); virtual int GetMaxFds(); virtual int GetRemainingFds(); virtual bool DelFd(EventHandler* eh, bool force = false); @@ -62,7 +59,7 @@ class SocketEngineFactory public: /** Create a new instance of SocketEngine based on KQueueEngine */ - SocketEngine* Create(InspIRCd* Instance) { return new KQueueEngine(Instance); } + SocketEngine* Create() { return new KQueueEngine; } }; #endif diff --git a/include/socketengines/socketengine_poll.h b/include/socketengines/socketengine_poll.h index df1100d09..725ad225c 100644 --- a/include/socketengines/socketengine_poll.h +++ b/include/socketengines/socketengine_poll.h @@ -48,13 +48,12 @@ private: std::map<int, unsigned int> fd_mappings; public: /** Create a new PollEngine - * @param Instance The creator of this object */ - PollEngine(InspIRCd* Instance); + PollEngine(); /** Delete a PollEngine */ virtual ~PollEngine(); - virtual bool AddFd(EventHandler* eh); + virtual bool AddFd(EventHandler* eh, bool writeFirst = false); virtual EventHandler* GetRef(int fd); virtual int GetMaxFds(); virtual int GetRemainingFds(); @@ -71,7 +70,7 @@ class SocketEngineFactory public: /** Create a new instance of SocketEngine based on PollEngine */ - SocketEngine* Create(InspIRCd* Instance) { return new PollEngine(Instance); } + SocketEngine* Create() { return new PollEngine; } }; #endif diff --git a/include/socketengines/socketengine_ports.h b/include/socketengines/socketengine_ports.h index 40d5da51a..03df456f2 100644 --- a/include/socketengines/socketengine_ports.h +++ b/include/socketengines/socketengine_ports.h @@ -26,8 +26,6 @@ #include "socketengine.h" #include <port.h> -class InspIRCd; - /** A specialisation of the SocketEngine class, designed to use solaris 10 I/O completion ports */ class PortsEngine : public SocketEngine @@ -40,11 +38,11 @@ public: /** Create a new PortsEngine * @param Instance The creator of this object */ - PortsEngine(InspIRCd* Instance); + PortsEngine(); /** Delete a PortsEngine */ virtual ~PortsEngine(); - virtual bool AddFd(EventHandler* eh); + virtual bool AddFd(EventHandler* eh, bool writeFirst = false); virtual int GetMaxFds(); virtual int GetRemainingFds(); virtual bool DelFd(EventHandler* eh, bool force = false); @@ -60,7 +58,7 @@ class SocketEngineFactory public: /** Create a new instance of SocketEngine based on PortsEngine */ - SocketEngine* Create(InspIRCd* Instance) { return new PortsEngine(Instance); } + SocketEngine* Create() { return new PortsEngine; } }; #endif diff --git a/include/socketengines/socketengine_select.h b/include/socketengines/socketengine_select.h index a248e8a8e..a1993f19f 100644 --- a/include/socketengines/socketengine_select.h +++ b/include/socketengines/socketengine_select.h @@ -24,8 +24,6 @@ #include "inspircd.h" #include "socketengine.h" -class InspIRCd; - /** A specialisation of the SocketEngine class, designed to use traditional select(). */ class SelectEngine : public SocketEngine @@ -45,11 +43,11 @@ public: /** Create a new SelectEngine * @param Instance The creator of this object */ - SelectEngine(InspIRCd* Instance); + SelectEngine(); /** Delete a SelectEngine */ virtual ~SelectEngine(); - virtual bool AddFd(EventHandler* eh); + virtual bool AddFd(EventHandler* eh, bool writeFirst = false); virtual int GetMaxFds(); virtual int GetRemainingFds(); virtual bool DelFd(EventHandler* eh, bool force = false); @@ -65,7 +63,7 @@ class SocketEngineFactory public: /** Create a new instance of SocketEngine based on SelectEngine */ - SocketEngine* Create(InspIRCd* Instance) { return new SelectEngine(Instance); } + SocketEngine* Create() { return new SelectEngine; } }; #endif diff --git a/include/users.h b/include/users.h index f9be74924..7ec35535f 100644 --- a/include/users.h +++ b/include/users.h @@ -15,6 +15,7 @@ #define __USERS_H__ #include "socket.h" +#include "inspsocket.h" #include "dns.h" #include "mode.h" @@ -210,7 +211,7 @@ class User; * connection is stored here primarily, from the user's socket ID (file descriptor) through to the * user's nickname and hostname. */ -class CoreExport User : public EventHandler +class CoreExport User : public StreamSocket { private: /** A list of channels the user has a pending invite to. @@ -405,17 +406,6 @@ class CoreExport User : public EventHandler */ std::string password; - /** User's receive queue. - * Lines from the IRCd awaiting processing are stored here. - * Upgraded april 2005, old system a bit hairy. - */ - std::string recvq; - - /** User's send queue. - * Lines waiting to be sent are stored here until their buffer is flushed. - */ - std::string sendq; - /** Whether or not to send an snotice about this user's quitting */ bool quietquit; @@ -596,44 +586,6 @@ class CoreExport User : public EventHandler */ bool HasModePermission(unsigned char mode, ModeType type); - /** Calls read() to read some data for this user using their fd. - * @param buffer The buffer to read into - * @param size The size of data to read - * @return The number of bytes read, or -1 if an error occured. - */ - int ReadData(void* buffer, size_t size); - - /** This method adds data to the read buffer of the user. - * The buffer can grow to any size within limits of the available memory, - * managed by the size of a std::string, however if any individual line in - * the buffer grows over 600 bytes in length (which is 88 chars over the - * RFC-specified limit per line) then the method will return false and the - * text will not be inserted. - * @param a The string to add to the users read buffer - * @return True if the string was successfully added to the read buffer - */ - bool AddBuffer(const std::string &a); - - /** This method returns true if the buffer contains at least one carriage return - * character (e.g. one complete line may be read) - * @return True if there is at least one complete line in the users buffer - */ - bool BufferIsReady(); - - /** This function clears the entire buffer by setting it to an empty string. - */ - void ClearBuffer(); - - /** This method returns the first available string at the tail end of the buffer - * and advances the tail end of the buffer past the string. This means it is - * a one way operation in a similar way to strtok(), and multiple calls return - * multiple lines if they are available. The results of this function if there - * are no lines to be read are unknown, always use BufferIsReady() to check if - * it is ok to read the buffer before calling GetBuffer(). - * @return The string at the tail end of this users buffer - */ - std::string GetBuffer(); - /** Adds to the user's write buffer. * You may add any amount of text up to this users sendq value, if you exceed the * sendq value, the user will be removed, and further buffer adds will be dropped. @@ -641,14 +593,6 @@ class CoreExport User : public EventHandler */ void AddWriteBuf(const std::string &data); - /** Flushes as much of the user's buffer to the file descriptor as possible. - * This function may not always flush the entire buffer, rather instead as much of it - * as it possibly can. If the send() call fails to send the entire buffer, the buffer - * position is advanced forwards and the rest of the data sent at the next call to - * this method. - */ - void FlushWriteBuf(); - /** Returns the list of channels this user has been invited to but has not yet joined. * @return A list of channels the user is invited to */ @@ -672,12 +616,6 @@ class CoreExport User : public EventHandler */ const std::string& MakeHostIP(); - /** Shuts down and closes the user's socket - * This will not cause the user to be deleted. Use InspIRCd::QuitUser for this, - * which will call CloseSocket() for you. - */ - void CloseSocket(); - /** Add the user to WHOWAS system */ void AddToWhoWas(); @@ -911,16 +849,13 @@ class CoreExport User : public EventHandler */ void DecreasePenalty(int decrease); - /** Handle socket event. - * From EventHandler class. - * @param et Event type - * @param errornum Error number for EVENT_ERROR events - */ - void HandleEvent(EventType et, int errornum = 0); + void OnDataReady(); + void OnError(BufferedSocketError error); /** Default destructor */ virtual ~User(); + virtual void cull(); }; /** Derived from Resolver, and performs user forward/reverse lookups. |