diff options
82 files changed, 990 insertions, 1950 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. diff --git a/src/base.cpp b/src/base.cpp index 27eb4af23..2b022688d 100644 --- a/src/base.cpp +++ b/src/base.cpp @@ -26,6 +26,14 @@ classbase::classbase() { } +void classbase::cull() +{ +} + +classbase::~classbase() +{ +} + void BoolSet::Set(int number) { this->bits |= bitfields[number]; diff --git a/src/command_parse.cpp b/src/command_parse.cpp index 92d4b8c24..cbf6a1005 100644 --- a/src/command_parse.cpp +++ b/src/command_parse.cpp @@ -226,23 +226,6 @@ CmdResult CommandParser::CallHandler(const std::string &commandname, const std:: return CMD_INVALID; } -void CommandParser::DoLines(User* current, bool one_only) -{ - while (current->BufferIsReady()) - { - // use GetBuffer to copy single lines into the sanitized string - std::string single_line = current->GetBuffer(); - current->bytes_in += single_line.length(); - current->cmds_in++; - if (single_line.length() > MAXBUF - 2) // MAXBUF is 514 to allow for neccessary line terminators - single_line.resize(MAXBUF - 2); // So to trim to 512 here, we use MAXBUF - 2 - - // ProcessBuffer returns false if the user has gone over penalty - if (!ServerInstance->Parser->ProcessBuffer(single_line, current) || one_only) - break; - } -} - bool CommandParser::ProcessCommand(User *user, std::string &cmd) { std::vector<std::string> command_p; @@ -435,23 +418,12 @@ void CommandParser::RemoveCommand(Commandtable::iterator safei, Module* source) bool CommandParser::ProcessBuffer(std::string &buffer,User *user) { - std::string::size_type a; - - if (!user) + if (!user || buffer.empty()) return true; - while ((a = buffer.rfind("\n")) != std::string::npos) - buffer.erase(a); - while ((a = buffer.rfind("\r")) != std::string::npos) - buffer.erase(a); - - if (buffer.length()) - { - ServerInstance->Logs->Log("USERINPUT", DEBUG,"C[%d] I :%s %s",user->GetFd(), user->nick.c_str(), buffer.c_str()); - return this->ProcessCommand(user,buffer); - } - - return true; + ServerInstance->Logs->Log("USERINPUT", DEBUG, "C[%d] I :%s %s", + user->GetFd(), user->nick.c_str(), buffer.c_str()); + return ProcessCommand(user,buffer); } bool CommandParser::CreateCommand(Command *f) diff --git a/src/cull_list.cpp b/src/cull_list.cpp index 79c077ead..35fa44bfa 100644 --- a/src/cull_list.cpp +++ b/src/cull_list.cpp @@ -18,8 +18,12 @@ void CullList::Apply() { - for(std::vector<classbase*>::iterator i = list.begin(); i != list.end(); i++) - delete *i; + for(std::set<classbase*>::iterator i = list.begin(); i != list.end(); i++) + { + classbase* c = *i; + c->cull(); + delete c; + } list.clear(); } diff --git a/src/helperfuncs.cpp b/src/helperfuncs.cpp index 0ec8db966..80feae464 100644 --- a/src/helperfuncs.cpp +++ b/src/helperfuncs.cpp @@ -125,20 +125,16 @@ void InspIRCd::SendError(const std::string &s) { for (std::vector<User*>::const_iterator i = this->Users->local_users.begin(); i != this->Users->local_users.end(); i++) { - if ((*i)->registered == REG_ALL) + User* u = *i; + if (u->registered == REG_ALL) { - (*i)->WriteServ("NOTICE %s :%s",(*i)->nick.c_str(),s.c_str()); + u->WriteServ("NOTICE %s :%s",u->nick.c_str(),s.c_str()); } else { /* Unregistered connections receive ERROR, not a NOTICE */ - (*i)->Write("ERROR :" + s); + u->Write("ERROR :" + s); } - /* This might generate a whole load of EAGAIN, but we dont really - * care about this, as if we call SendError something catastrophic - * has occured anyway, and we wont receive the events for these. - */ - (*i)->FlushWriteBuf(); } } diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 1b23bff02..704fec475 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -110,7 +110,6 @@ void InspIRCd::Cleanup() { User* u = *i++; Users->QuitUser(u, "Server shutdown"); - u->CloseSocket(); } /* We do this more than once, so that any service providers get a @@ -323,7 +322,6 @@ InspIRCd::InspIRCd(int argc, char** argv) : * THIS MUST MATCH ORDER OF DECLARATION OF THE HandleWhateverFunc classes * within class InspIRCd. */ - HandleProcessUser(this), HandleIsNick(this), HandleIsIdent(this), HandleFloodQuitUser(this), @@ -336,7 +334,6 @@ InspIRCd::InspIRCd(int argc, char** argv) : * THIS MUST MATCH THE ORDER OF DECLARATION OF THE FUNCTORS, e.g. the methods * themselves within the class. */ - ProcessUser(&HandleProcessUser), IsChannel(&HandleIsChannel), IsSID(&HandleIsSID), Rehash(&HandleRehash), @@ -387,9 +384,8 @@ InspIRCd::InspIRCd(int argc, char** argv) : // This must be created first, so other parts of Insp can use it while starting up this->Logs = new LogManager(this); - SocketEngineFactory* SEF = new SocketEngineFactory(); - SE = SEF->Create(this); - delete SEF; + SocketEngineFactory SEF; + SE = SEF.Create(); this->Threads = new ThreadEngine(this); @@ -832,9 +828,6 @@ int InspIRCd::Run() /* if any users were quit, take them out */ this->GlobalCulls.Apply(); - /* If any inspsockets closed, remove them */ - this->BufferedSocketCull(); - if (this->s_signal) { this->SignalHandler(s_signal); @@ -845,18 +838,6 @@ int InspIRCd::Run() return 0; } -void InspIRCd::BufferedSocketCull() -{ - for (std::map<BufferedSocket*,BufferedSocket*>::iterator x = SocketCull.begin(); x != SocketCull.end(); ++x) - { - this->Logs->Log("MISC",DEBUG,"Cull socket"); - SE->DelFd(x->second); - x->second->Close(); - delete x->second; - } - SocketCull.clear(); -} - /**********************************************************************************/ /** diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp index 0350858e7..964582062 100644 --- a/src/inspsocket.cpp +++ b/src/inspsocket.cpp @@ -16,195 +16,100 @@ #include "inspstring.h" #include "socketengine.h" -bool BufferedSocket::Readable() +BufferedSocket::BufferedSocket() { - return (this->state != I_CONNECTING); + Timeout = NULL; + state = I_ERROR; } -BufferedSocket::BufferedSocket(InspIRCd* SI) +BufferedSocket::BufferedSocket(int newfd) { - this->Timeout = NULL; - this->state = I_DISCONNECTED; - this->fd = -1; - this->ServerInstance = SI; -} - -BufferedSocket::BufferedSocket(InspIRCd* SI, int newfd, const char* ip) -{ - this->Timeout = NULL; + Timeout = NULL; this->fd = newfd; this->state = I_CONNECTED; - strlcpy(this->IP,ip,MAXBUF); - this->ServerInstance = SI; - if (this->fd > -1) - this->ServerInstance->SE->AddFd(this); + if (fd > -1) + ServerInstance->SE->AddFd(this); } -BufferedSocket::BufferedSocket(InspIRCd* SI, const std::string &ipaddr, int aport, unsigned long maxtime, const std::string &connectbindip) +void BufferedSocket::DoConnect(const std::string &ipaddr, int aport, unsigned long maxtime, const std::string &connectbindip) { - this->cbindip = connectbindip; - this->fd = -1; - this->ServerInstance = SI; - strlcpy(host,ipaddr.c_str(),MAXBUF); - this->Timeout = NULL; - - strlcpy(this->host,ipaddr.c_str(),MAXBUF); - this->port = aport; - - irc::sockets::sockaddrs testaddr; - if (!irc::sockets::aptosa(host, aport, &testaddr)) - { - this->ServerInstance->Logs->Log("SOCKET", DEBUG,"BUG: Hostname passed to BufferedSocket, rather than an IP address!"); - this->OnError(I_ERR_CONNECT); - this->Close(); - this->fd = -1; - this->state = I_ERROR; - return; - } - else + BufferedSocketError err = BeginConnect(ipaddr, aport, maxtime, connectbindip); + if (err != I_ERR_NONE) { - strlcpy(this->IP,host,MAXBUF); - if (!this->DoConnect(maxtime)) - { - this->OnError(I_ERR_CONNECT); - this->Close(); - this->fd = -1; - this->state = I_ERROR; - return; - } + state = I_ERROR; + SetError(strerror(errno)); + OnError(err); } } -void BufferedSocket::SetQueues() +BufferedSocketError BufferedSocket::BeginConnect(const std::string &ipaddr, int aport, unsigned long maxtime, const std::string &connectbindip) { - // attempt to increase socket sendq and recvq as high as its possible - int sendbuf = 32768; - int recvbuf = 32768; - if(setsockopt(this->fd,SOL_SOCKET,SO_SNDBUF,(const char *)&sendbuf,sizeof(sendbuf)) || setsockopt(this->fd,SOL_SOCKET,SO_RCVBUF,(const char *)&recvbuf,sizeof(sendbuf))) + irc::sockets::sockaddrs addr, bind; + if (!irc::sockets::aptosa(ipaddr.c_str(), aport, &addr)) { - //this->ServerInstance->Log(DEFAULT, "Could not increase SO_SNDBUF/SO_RCVBUF for socket %u", GetFd()); - ; // do nothing. I'm a little sick of people trying to interpret this message as a result of why their incorrect setups don't work. + ServerInstance->Logs->Log("SOCKET", DEBUG, "BUG: Hostname passed to BufferedSocket, rather than an IP address!"); + return I_ERR_CONNECT; } -} -bool BufferedSocket::DoBindMagic(const std::string ¤t_ip) -{ - irc::sockets::sockaddrs s; - if (!irc::sockets::aptosa(current_ip.c_str(), 0, &s)) + bind.sa.sa_family = 0; + if (!connectbindip.empty()) { - errno = EADDRNOTAVAIL; - return false; - } - - if (ServerInstance->SE->Bind(this->fd, &s.sa, sa_size(s)) < 0) - { - this->state = I_ERROR; - this->OnError(I_ERR_BIND); - return false; + if (!irc::sockets::aptosa(connectbindip.c_str(), 0, &bind)) + { + return I_ERR_BIND; + } } - return true; + return BeginConnect(addr, bind, maxtime); } -/* Most irc servers require you to specify the ip you want to bind to. - * If you dont specify an IP, they rather dumbly bind to the first IP - * of the box (e.g. INADDR_ANY). In InspIRCd, we scan thought the IP - * addresses we've bound server ports to, and we try and bind our outbound - * connections to the first usable non-loopback and non-any IP we find. - * This is easier to configure when you have a lot of links and a lot - * of servers to configure. - */ -bool BufferedSocket::BindAddr(const std::string &ip_to_bind) +static void IncreaseOSBuffers(int fd) { - ConfigReader Conf(this->ServerInstance); - - // Case one: If they provided an IP, try bind it - if (!ip_to_bind.empty()) - { - // And if it fails, don't do anything. - return this->DoBindMagic(ip_to_bind); - } - - for (int j = 0; j < Conf.Enumerate("bind"); j++) - { - // We only want to try bind to a server ip. - if (Conf.ReadValue("bind","type",j) != "servers") - continue; - - // set current IP to the <bind> tag - std::string current_ip = Conf.ReadValue("bind","address",j); - - // Make sure IP is nothing local - if (current_ip == "*" || current_ip == "127.0.0.1" || current_ip.empty() || current_ip == "::1") - continue; - - // Try bind, don't fail if it doesn't bind though. - if (this->DoBindMagic(current_ip)) - return true; - } - - // NOTE: You may wonder WTF we are returning *true* here, but that is because there were no custom binds setup, and so we have nothing to do - // (remember, outgoing connections without binding are perfectly ok). - ServerInstance->Logs->Log("SOCKET", DEBUG,"nothing in the config to bind()!"); - return true; + // attempt to increase socket sendq and recvq as high as its possible + int sendbuf = 32768; + int recvbuf = 32768; + setsockopt(fd,SOL_SOCKET,SO_SNDBUF,(const char *)&sendbuf,sizeof(sendbuf)); + setsockopt(fd,SOL_SOCKET,SO_RCVBUF,(const char *)&recvbuf,sizeof(recvbuf)); + // on failure, do nothing. I'm a little sick of people trying to interpret this message as a result of why their incorrect setups don't work. } -bool BufferedSocket::DoConnect(unsigned long maxtime) +BufferedSocketError BufferedSocket::BeginConnect(const irc::sockets::sockaddrs& dest, const irc::sockets::sockaddrs& bind, unsigned long timeout) { - irc::sockets::sockaddrs addr; - irc::sockets::aptosa(this->host, this->port, &addr); - - this->fd = socket(addr.sa.sa_family, SOCK_STREAM, 0); + if (fd < 0) + fd = socket(dest.sa.sa_family, SOCK_STREAM, 0); - if (this->fd == -1) - { - this->state = I_ERROR; - this->OnError(I_ERR_SOCKET); - return false; - } + if (fd < 0) + return I_ERR_SOCKET; - if (!this->BindAddr(this->cbindip)) + if (bind.sa.sa_family != 0) { - this->Close(); - this->fd = -1; - return false; + if (ServerInstance->SE->Bind(fd, &bind.sa, sa_size(bind)) < 0) + return I_ERR_BIND; } - ServerInstance->SE->NonBlocking(this->fd); + ServerInstance->SE->NonBlocking(fd); - if (ServerInstance->SE->Connect(this, &addr.sa, sa_size(addr)) == -1) + if (ServerInstance->SE->Connect(this, &dest.sa, sa_size(dest)) == -1) { if (errno != EINPROGRESS) - { - this->OnError(I_ERR_CONNECT); - this->Close(); - this->state = I_ERROR; - return false; - } - - this->Timeout = new SocketTimeout(this->GetFd(), this->ServerInstance, this, maxtime, this->ServerInstance->Time()); - this->ServerInstance->Timers->AddTimer(this->Timeout); + return I_ERR_CONNECT; } this->state = I_CONNECTING; - if (this->fd > -1) - { - if (!this->ServerInstance->SE->AddFd(this)) - { - this->OnError(I_ERR_NOMOREFDS); - this->Close(); - this->state = I_ERROR; - return false; - } - this->SetQueues(); - } + + if (!ServerInstance->SE->AddFd(this, true)) + return I_ERR_NOMOREFDS; + + this->Timeout = new SocketTimeout(this->GetFd(), this, timeout, ServerInstance->Time()); + ServerInstance->Timers->AddTimer(this->Timeout); + + IncreaseOSBuffers(fd); ServerInstance->Logs->Log("SOCKET", DEBUG,"BufferedSocket::DoConnect success"); - return true; + return I_ERR_NONE; } - -void BufferedSocket::Close() +void StreamSocket::Close() { /* Save this, so we dont lose it, * otherise on failure, error messages @@ -213,190 +118,196 @@ void BufferedSocket::Close() int save = errno; if (this->fd > -1) { - if (this->GetIOHook()) + if (IOHook) { try { - this->GetIOHook()->OnRawSocketClose(this->fd); + IOHook->OnStreamSocketClose(this); } catch (CoreException& modexcept) { - ServerInstance->Logs->Log("SOCKET", DEFAULT,"%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason()); + ServerInstance->Logs->Log("SOCKET", DEFAULT,"%s threw an exception: %s", + modexcept.GetSource(), modexcept.GetReason()); } } ServerInstance->SE->Shutdown(this, 2); - if (ServerInstance->SE->Close(this) != -1) - this->OnClose(); - - if (ServerInstance->SocketCull.find(this) == ServerInstance->SocketCull.end()) - ServerInstance->SocketCull[this] = this; + ServerInstance->SE->DelFd(this); + ServerInstance->SE->Close(this); + fd = -1; } errno = save; } -std::string BufferedSocket::GetIP() +void StreamSocket::cull() { - return this->IP; + Close(); } -const char* BufferedSocket::Read() +bool StreamSocket::GetNextLine(std::string& line, char delim) { - if (!ServerInstance->SE->BoundsCheckFd(this)) - return NULL; - - int n = 0; - char* ReadBuffer = ServerInstance->GetReadBuffer(); + std::string::size_type i = recvq.find(delim); + if (i == std::string::npos) + return false; + line = recvq.substr(0, i - 1); + // TODO is this the most efficient way to split? + recvq = recvq.substr(i + 1); + return true; +} - if (this->GetIOHook()) +void StreamSocket::DoRead() +{ + if (IOHook) { - int result2 = 0; - int MOD_RESULT = 0; + int rv = -1; try { - MOD_RESULT = this->GetIOHook()->OnRawSocketRead(this->fd, ReadBuffer, ServerInstance->Config->NetBufferSize, result2); + rv = IOHook->OnStreamSocketRead(this, recvq); } catch (CoreException& modexcept) { - ServerInstance->Logs->Log("SOCKET", DEFAULT,"%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason()); + ServerInstance->Logs->Log("SOCKET", DEFAULT, "%s threw an exception: %s", + modexcept.GetSource(), modexcept.GetReason()); + return; } - if (MOD_RESULT < 0) + if (rv > 0) + OnDataReady(); + if (rv < 0) + SetError("Read Error"); // will not overwrite a better error message + } + else + { + char* ReadBuffer = ServerInstance->GetReadBuffer(); + int n = recv(fd, ReadBuffer, ServerInstance->Config->NetBufferSize, 0); + if (n > 0) { - n = -1; - errno = EAGAIN; + recvq.append(ReadBuffer, n); + OnDataReady(); } - else + else if (n == 0) { - n = result2; + error = "Connection closed"; + } + else if (errno != EAGAIN && errno != EINTR) + { + error = strerror(errno); } - } - else - { - n = recv(this->fd, ReadBuffer, ServerInstance->Config->NetBufferSize, 0); - } - - /* - * This used to do some silly bounds checking instead of just passing bufsize - 1 to recv. - * Not only does that make absolutely no sense, but it could potentially result in a read buffer's worth - * of data being thrown into the bit bucket for no good reason, which is just *stupid*.. do things correctly now. - * --w00t (july 2, 2008) - */ - if (n > 0) - { - ReadBuffer[n] = 0; - return ReadBuffer; - } - else - { - int err = errno; - if (err == EAGAIN) - return ""; - else - return NULL; } } -/* - * This function formerly tried to flush write buffer each call. - * While admirable in attempting to get the data out to wherever - * it is going, on a full socket, it's just going to syscall write() and - * EAGAIN constantly, instead of waiting in the SE to know if it can write - * which will chew a bit of CPU. - * - * So, now this function returns void (take note) and just adds to the sendq. - * - * It'll get written at a determinate point when the socketengine tells us it can write. - * -- w00t (april 1, 2008) - */ -void BufferedSocket::Write(const std::string &data) +void StreamSocket::DoWrite() { - /* Append the data to the back of the queue ready for writing */ - outbuffer.push_back(data); - - /* Mark ourselves as wanting write */ - this->ServerInstance->SE->WantWrite(this); -} + if (sendq.empty()) + return; -bool BufferedSocket::FlushWriteBuffer() -{ - errno = 0; - if ((this->fd > -1) && (this->state == I_CONNECTED)) + if (IOHook) { - if (this->GetIOHook()) + int rv = -1; + try { - while (outbuffer.size() && (errno != EAGAIN)) + while (!sendq.empty()) { - try + std::string& front = sendq.front(); + int itemlen = front.length(); + rv = IOHook->OnStreamSocketWrite(this, front); + if (rv > 0) + { + // consumed the entire string, and is ready for more + sendq_len -= itemlen; + sendq.pop_front(); + } + else if (rv == 0) { - /* XXX: The lack of buffering here is NOT a bug, modules implementing this interface have to - * implement their own buffering mechanisms - */ - this->GetIOHook()->OnRawSocketWrite(this->fd, outbuffer[0].c_str(), outbuffer[0].length()); - outbuffer.pop_front(); + // socket has blocked. Stop trying to send data. + // IOHook has requested unblock notification from the socketengine + + // Since it is possible that a partial write took place, adjust sendq_len + sendq_len = sendq_len - itemlen + front.length(); + return; } - catch (CoreException& modexcept) + else { - ServerInstance->Logs->Log("SOCKET", DEBUG,"%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason()); - return true; + SetError("Write Error"); // will not overwrite a better error message + return; } } } - else + catch (CoreException& modexcept) { - /* If we have multiple lines, try to send them all, - * not just the first one -- Brain - */ - while (outbuffer.size() && (errno != EAGAIN)) + ServerInstance->Logs->Log("SOCKET", DEBUG,"%s threw an exception: %s", + modexcept.GetSource(), modexcept.GetReason()); + } + } + else + { + // Prepare a writev() call to write all buffers efficiently + int bufcount = sendq.size(); + + // cap the number of buffers at IOV_MAX + if (bufcount > IOV_MAX) + bufcount = IOV_MAX; + + iovec* iovecs = new iovec[bufcount]; + for(int i=0; i < bufcount; i++) + { + iovecs[i].iov_base = const_cast<char*>(sendq[i].data()); + iovecs[i].iov_len = sendq[i].length(); + } + int rv = writev(fd, iovecs, bufcount); + delete[] iovecs; + if (rv == (int)sendq_len) + { + // it's our lucky day, everything got written out. Fast cleanup. + sendq_len = 0; + sendq.clear(); + } + else if (rv > 0) + { + // Partial write. Clean out strings from the sendq + sendq_len -= rv; + while (rv > 0 && !sendq.empty()) { - /* Send a line */ - int result = ServerInstance->SE->Send(this, outbuffer[0].c_str(), outbuffer[0].length(), 0); - - if (result > 0) + std::string& front = sendq.front(); + if (front.length() < (size_t)rv) { - if ((unsigned int)result >= outbuffer[0].length()) - { - /* The whole block was written (usually a line) - * Pop the block off the front of the queue, - * dont set errno, because we are clear of errors - * and want to try and write the next block too. - */ - outbuffer.pop_front(); - } - else - { - std::string temp = outbuffer[0].substr(result); - outbuffer[0] = temp; - /* We didnt get the whole line out. arses. - * Try again next time, i guess. Set errno, - * because we shouldnt be writing any more now, - * until the socketengine says its safe to do so. - */ - errno = EAGAIN; - } + // this string got fully written out + rv -= front.length(); + sendq.pop_front(); } - else if (result == 0) + else { - this->ServerInstance->SE->DelFd(this); - this->Close(); - return true; - } - else if ((result == -1) && (errno != EAGAIN)) - { - this->OnError(I_ERR_WRITE); - this->state = I_ERROR; - this->ServerInstance->SE->DelFd(this); - this->Close(); - return true; + // stopped in the middle of this string + front = front.substr(rv); + rv = 0; } } } + else if (rv == 0) + { + error = "Connection closed"; + } + else if (errno != EAGAIN && errno != EINTR) + { + error = strerror(errno); + } + if (sendq_len && error.empty()) + ServerInstance->SE->WantWrite(this); } +} + +void StreamSocket::WriteData(const std::string &data) +{ + bool newWrite = sendq.empty() && !data.empty(); - if ((errno == EAGAIN) && (fd > -1)) + /* Append the data to the back of the queue ready for writing */ + sendq.push_back(data); + sendq_len += data.length(); + + if (newWrite) { - this->ServerInstance->SE->WantWrite(this); + // TODO perhaps we should try writing first, before asking SE about writes? + // DoWrite(); + ServerInstance->SE->WantWrite(this); } - - return (fd < 0); } void SocketTimeout::Tick(time_t) @@ -421,57 +332,26 @@ void SocketTimeout::Tick(time_t) */ this->sock->state = I_ERROR; - if (ServerInstance->SocketCull.find(this->sock) == ServerInstance->SocketCull.end()) - ServerInstance->SocketCull[this->sock] = this->sock; + ServerInstance->GlobalCulls.AddItem(sock); } this->sock->Timeout = NULL; } -bool BufferedSocket::InternalMarkConnected() -{ - /* Our socket was in write-state, so delete it and re-add it - * in read-state. - */ - this->SetState(I_CONNECTED); +void BufferedSocket::OnConnected() { } +void BufferedSocket::OnTimeout() { return; } - if (this->GetIOHook()) +void BufferedSocket::DoWrite() +{ + if (state == I_CONNECTING) { - ServerInstance->Logs->Log("SOCKET",DEBUG,"Hook for raw connect"); - try - { - this->GetIOHook()->OnRawSocketConnect(this->fd); - } - catch (CoreException& modexcept) - { - ServerInstance->Logs->Log("SOCKET",DEBUG,"%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason()); - return false; - } + state = I_CONNECTED; + this->OnConnected(); + if (GetIOHook()) + GetIOHook()->OnStreamSocketConnect(this); } - return this->OnConnected(); -} - -void BufferedSocket::SetState(BufferedSocketState s) -{ - this->state = s; -} - -BufferedSocketState BufferedSocket::GetState() -{ - return this->state; -} - -bool BufferedSocket::OnConnected() { return true; } -void BufferedSocket::OnError(BufferedSocketError) { return; } -int BufferedSocket::OnDisconnect() { return 0; } -bool BufferedSocket::OnDataReady() { return true; } -bool BufferedSocket::OnWriteReady() -{ - // Default behaviour: just try write some. - return !this->FlushWriteBuffer(); + this->StreamSocket::DoWrite(); } -void BufferedSocket::OnTimeout() { return; } -void BufferedSocket::OnClose() { return; } BufferedSocket::~BufferedSocket() { @@ -483,68 +363,49 @@ BufferedSocket::~BufferedSocket() } } -void BufferedSocket::HandleEvent(EventType et, int errornum) +void StreamSocket::HandleEvent(EventType et, int errornum) { + BufferedSocketError errcode = I_ERR_OTHER; switch (et) { case EVENT_ERROR: { + SetError(strerror(errornum)); switch (errornum) { case ETIMEDOUT: - this->OnError(I_ERR_TIMEOUT); + errcode = I_ERR_TIMEOUT; break; case ECONNREFUSED: case 0: - this->OnError(this->state == I_CONNECTING ? I_ERR_CONNECT : I_ERR_WRITE); + errcode = I_ERR_CONNECT; break; case EADDRINUSE: - this->OnError(I_ERR_BIND); + errcode = I_ERR_BIND; break; case EPIPE: case EIO: - this->OnError(I_ERR_WRITE); + errcode = I_ERR_WRITE; break; } - - if (this->ServerInstance->SocketCull.find(this) == this->ServerInstance->SocketCull.end()) - this->ServerInstance->SocketCull[this] = this; - return; break; } case EVENT_READ: { - if (!this->OnDataReady()) - { - if (this->ServerInstance->SocketCull.find(this) == this->ServerInstance->SocketCull.end()) - this->ServerInstance->SocketCull[this] = this; - return; - } + DoRead(); break; } case EVENT_WRITE: { - if (this->state == I_CONNECTING) - { - if (!this->InternalMarkConnected()) - { - if (this->ServerInstance->SocketCull.find(this) == this->ServerInstance->SocketCull.end()) - this->ServerInstance->SocketCull[this] = this; - return; - } - return; - } - else - { - if (!this->OnWriteReady()) - { - if (this->ServerInstance->SocketCull.find(this) == this->ServerInstance->SocketCull.end()) - this->ServerInstance->SocketCull[this] = this; - return; - } - } + DoWrite(); break; } } + if (!error.empty()) + { + ServerInstance->Logs->Log("SOCKET", DEBUG, "Error on FD %d - '%s'", fd, error.c_str()); + OnError(errcode); + ServerInstance->GlobalCulls.AddItem(this); + } } diff --git a/src/modules.cpp b/src/modules.cpp index 51fecb47c..c11b63bec 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -159,11 +159,11 @@ void Module::OnGlobalOper(User*) { } void Module::OnPostConnect(User*) { } ModResult Module::OnAddBan(User*, Channel*, const std::string &) { return MOD_RES_PASSTHRU; } ModResult Module::OnDelBan(User*, Channel*, const std::string &) { return MOD_RES_PASSTHRU; } -void Module::OnRawSocketAccept(int, irc::sockets::sockaddrs*, irc::sockets::sockaddrs*) { } -int Module::OnRawSocketWrite(int, const char*, int) { return 0; } -void Module::OnRawSocketClose(int) { } -void Module::OnRawSocketConnect(int) { } -int Module::OnRawSocketRead(int, char*, unsigned int, int&) { return 0; } +void Module::OnStreamSocketAccept(StreamSocket*, irc::sockets::sockaddrs*, irc::sockets::sockaddrs*) { } +int Module::OnStreamSocketWrite(StreamSocket*, std::string&) { return -1; } +void Module::OnStreamSocketClose(StreamSocket*) { } +void Module::OnStreamSocketConnect(StreamSocket*) { } +int Module::OnStreamSocketRead(StreamSocket*, std::string&) { return -1; } void Module::OnUserMessage(User*, void*, int, const std::string&, char, const CUList&) { } void Module::OnUserNotice(User*, void*, int, const std::string&, char, const CUList&) { } void Module::OnRemoteKill(User*, User*, const std::string&, const std::string&) { } @@ -196,7 +196,7 @@ void Module::OnText(User*, void*, int, const std::string&, char, CUList&) { } void Module::OnRunTestSuite() { } void Module::OnNamesListItem(User*, Membership*, std::string&, std::string&) { } ModResult Module::OnNumeric(User*, unsigned int, const std::string&) { return MOD_RES_PASSTHRU; } -void Module::OnHookIO(EventHandler*, ListenSocketBase*) { } +void Module::OnHookIO(StreamSocket*, ListenSocketBase*) { } ModResult Module::OnHostCycle(User*) { return MOD_RES_PASSTHRU; } void Module::OnSendWhoLine(User*, User*, Channel*, std::string&) { } diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp index f458f5da1..27c466573 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -56,7 +56,6 @@ public: gnutls_session_t sess; issl_status status; - std::string outbuf; }; class CommandStartTLS : public Command @@ -83,7 +82,7 @@ class CommandStartTLS : public Command { user->WriteNumeric(670, "%s :STARTTLS successful, go ahead with TLS handshake", user->nick.c_str()); user->AddIOHook(creator); - creator->OnRawSocketAccept(user->GetFd(), NULL, NULL); + creator->OnStreamSocketAccept(user, NULL, NULL); } else user->WriteNumeric(691, "%s :STARTTLS failure", user->nick.c_str()); @@ -133,16 +132,14 @@ class ModuleSSLGnuTLS : public Module // Void return, guess we assume success gnutls_certificate_set_dh_params(x509_cred, dh_params); - Implementation eventlist[] = { I_On005Numeric, I_OnRawSocketConnect, I_OnRawSocketAccept, - I_OnRawSocketClose, I_OnRawSocketRead, I_OnRawSocketWrite, I_OnCleanup, - I_OnBufferFlushed, I_OnRequest, I_OnRehash, I_OnModuleRehash, I_OnPostConnect, + Implementation eventlist[] = { I_On005Numeric, I_OnRequest, I_OnRehash, I_OnModuleRehash, I_OnPostConnect, I_OnEvent, I_OnHookIO }; ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation)); ServerInstance->AddCommand(&starttls); } - virtual void OnRehash(User* user) + void OnRehash(User* user) { ConfigReader Conf(ServerInstance); @@ -168,7 +165,7 @@ class ModuleSSLGnuTLS : public Module sslports.erase(sslports.end() - 1); } - virtual void OnModuleRehash(User* user, const std::string ¶m) + void OnModuleRehash(User* user, const std::string ¶m) { if(param != "ssl") return; @@ -278,7 +275,7 @@ class ModuleSSLGnuTLS : public Module ServerInstance->Logs->Log("m_ssl_gnutls",DEFAULT, "m_ssl_gnutls.so: Failed to generate DH parameters (%d bits): %s", dh_bits, gnutls_strerror(ret)); } - virtual ~ModuleSSLGnuTLS() + ~ModuleSSLGnuTLS() { gnutls_x509_crt_deinit(x509_cert); gnutls_x509_privkey_deinit(x509_key); @@ -289,7 +286,7 @@ class ModuleSSLGnuTLS : public Module delete[] sessions; } - virtual void OnCleanup(int target_type, void* item) + void OnCleanup(int target_type, void* item) { if(target_type == TYPE_USER) { @@ -305,20 +302,20 @@ class ModuleSSLGnuTLS : public Module } } - virtual Version GetVersion() + Version GetVersion() { return Version("$Id$", VF_VENDOR, API_VERSION); } - virtual void On005Numeric(std::string &output) + void On005Numeric(std::string &output) { if (!sslports.empty()) output.append(" SSL=" + sslports); output.append(" STARTTLS"); } - virtual void OnHookIO(EventHandler* user, ListenSocketBase* lsb) + void OnHookIO(StreamSocket* user, ListenSocketBase* lsb) { if (!user->GetIOHook() && listenports.find(lsb) != listenports.end()) { @@ -327,7 +324,7 @@ class ModuleSSLGnuTLS : public Module } } - virtual const char* OnRequest(Request* request) + const char* OnRequest(Request* request) { ISHRequest* ISR = static_cast<ISHRequest*>(request); if (strcmp("IS_NAME", request->GetId()) == 0) @@ -336,20 +333,13 @@ class ModuleSSLGnuTLS : public Module } else if (strcmp("IS_HOOK", request->GetId()) == 0) { - const char* ret = "OK"; - try - { - ret = ISR->Sock->AddIOHook(this) ? "OK" : NULL; - } - catch (ModuleException &e) - { - return NULL; - } - return ret; + ISR->Sock->AddIOHook(this); + return "OK"; } else if (strcmp("IS_UNHOOK", request->GetId()) == 0) { - return ISR->Sock->DelIOHook() ? "OK" : NULL; + ISR->Sock->DelIOHook(); + return "OK"; } else if (strcmp("IS_HSDONE", request->GetId()) == 0) { @@ -383,12 +373,9 @@ class ModuleSSLGnuTLS : public Module } - virtual void OnRawSocketAccept(int fd, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) + void OnStreamSocketAccept(StreamSocket* user, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) { - /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) - return; - + int fd = user->GetFd(); issl_session* session = &sessions[fd]; /* For STARTTLS: Don't try and init a session on a socket that already has a session */ @@ -405,77 +392,67 @@ class ModuleSSLGnuTLS : public Module gnutls_certificate_server_set_request(session->sess, GNUTLS_CERT_REQUEST); // Request client certificate if any. - Handshake(session, fd); + Handshake(session, user); } - virtual void OnRawSocketConnect(int fd) + void OnStreamSocketConnect(StreamSocket* user) { - /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) - return; - - issl_session* session = &sessions[fd]; + issl_session* session = &sessions[user->GetFd()]; gnutls_init(&session->sess, GNUTLS_CLIENT); gnutls_set_default_priority(session->sess); // Avoid calling all the priority functions, defaults are adequate. gnutls_credentials_set(session->sess, GNUTLS_CRD_CERTIFICATE, x509_cred); gnutls_dh_set_prime_bits(session->sess, dh_bits); - gnutls_transport_set_ptr(session->sess, reinterpret_cast<gnutls_transport_ptr_t>(fd)); // Give gnutls the fd for the socket. + gnutls_transport_set_ptr(session->sess, reinterpret_cast<gnutls_transport_ptr_t>(user->GetFd())); - Handshake(session, fd); + Handshake(session, user); } - virtual void OnRawSocketClose(int fd) + void OnStreamSocketClose(StreamSocket* user) { - /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds())) - return; - - CloseSession(&sessions[fd]); + CloseSession(&sessions[user->GetFd()]); } - virtual int OnRawSocketRead(int fd, char* buffer, unsigned int count, int &readresult) + int OnStreamSocketRead(StreamSocket* user, std::string& recvq) { - /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) - return 0; - - issl_session* session = &sessions[fd]; + issl_session* session = &sessions[user->GetFd()]; if (!session->sess) { - readresult = 0; CloseSession(session); - return 1; + user->SetError("No SSL session"); + return -1; } if (session->status == ISSL_HANDSHAKING_READ) { // The handshake isn't finished, try to finish it. - if(!Handshake(session, fd)) + if(!Handshake(session, user)) { - errno = session->status == ISSL_CLOSING ? EIO : EAGAIN; - // Couldn't resume handshake. + if (session->status != ISSL_CLOSING) + return 0; + user->SetError("Handshake Failed"); return -1; } } else if (session->status == ISSL_HANDSHAKING_WRITE) { - errno = EAGAIN; - MakePollWrite(fd); - return -1; + MakePollWrite(user); + return 0; } // If we resumed the handshake then session->status will be ISSL_HANDSHAKEN. if (session->status == ISSL_HANDSHAKEN) { - unsigned int len = 0; - while (len < count) + char* buffer = ServerInstance->GetReadBuffer(); + size_t bufsiz = ServerInstance->Config->NetBufferSize; + size_t len = 0; + while (len < bufsiz) { - int ret = gnutls_record_recv(session->sess, buffer + len, count - len); + int ret = gnutls_record_recv(session->sess, buffer + len, bufsiz - len); if (ret > 0) { len += ret; @@ -484,60 +461,49 @@ class ModuleSSLGnuTLS : public Module { break; } + else if (ret == 0) + { + user->SetError("SSL Connection closed"); + CloseSession(session); + return -1; + } else { - if (ret != 0) - ServerInstance->Logs->Log("m_ssl_gnutls", DEFAULT, - "m_ssl_gnutls.so: Error while reading on fd %d: %s", - fd, gnutls_strerror(ret)); - - // if ret == 0, client closed connection. - readresult = 0; + user->SetError(gnutls_strerror(ret)); CloseSession(session); - return 1; + return -1; } } - readresult = len; if (len) { + recvq.append(buffer, len); return 1; } - else - { - errno = EAGAIN; - return -1; - } } else if (session->status == ISSL_CLOSING) - readresult = 0; + return -1; - return 1; + return 0; } - virtual int OnRawSocketWrite(int fd, const char* buffer, int count) + int OnStreamSocketWrite(StreamSocket* user, std::string& sendq) { - /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) - return 0; - - issl_session* session = &sessions[fd]; - const char* sendbuffer = buffer; + issl_session* session = &sessions[user->GetFd()]; if (!session->sess) { CloseSession(session); - return 1; + user->SetError("No SSL session"); + return -1; } - session->outbuf.append(sendbuffer, count); - sendbuffer = session->outbuf.c_str(); - count = session->outbuf.size(); - if (session->status == ISSL_HANDSHAKING_WRITE || session->status == ISSL_HANDSHAKING_READ) { // The handshake isn't finished, try to finish it. - Handshake(session, fd); - errno = session->status == ISSL_CLOSING ? EIO : EAGAIN; + Handshake(session, user); + if (session->status != ISSL_CLOSING) + return 0; + user->SetError("Handshake Failed"); return -1; } @@ -545,42 +511,41 @@ class ModuleSSLGnuTLS : public Module if (session->status == ISSL_HANDSHAKEN) { - ret = gnutls_record_send(session->sess, sendbuffer, count); + ret = gnutls_record_send(session->sess, sendq.data(), sendq.length()); - if (ret == 0) + if (ret == (int)sendq.length()) { - CloseSession(session); + return 1; } - else if (ret < 0) + else if (ret > 0) { - if(ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED) - { - ServerInstance->Logs->Log("m_ssl_gnutls", DEFAULT, - "m_ssl_gnutls.so: Error while writing to fd %d: %s", - fd, gnutls_strerror(ret)); - CloseSession(session); - } - else - { - errno = EAGAIN; - } + sendq = sendq.substr(ret); + MakePollWrite(user); + return 0; } - else + else if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) + { + MakePollWrite(user); + return 0; + } + else if (ret == 0) { - session->outbuf = session->outbuf.substr(ret); + CloseSession(session); + user->SetError("SSL Connection closed"); + return -1; + } + else // (ret < 0) + { + user->SetError(gnutls_strerror(ret)); + CloseSession(session); + return -1; } } - if (!session->outbuf.empty()) - MakePollWrite(fd); - - /* Who's smart idea was it to return 1 when we havent written anything? - * This fucks the buffer up in BufferedSocket :p - */ - return ret < 1 ? 0 : ret; + return 0; } - bool Handshake(issl_session* session, int fd) + bool Handshake(issl_session* session, EventHandler* user) { int ret = gnutls_handshake(session->sess); @@ -599,15 +564,11 @@ class ModuleSSLGnuTLS : public Module { // gnutls_handshake() wants to write() again. session->status = ISSL_HANDSHAKING_WRITE; - MakePollWrite(fd); + MakePollWrite(user); } } else { - // Handshake failed. - ServerInstance->Logs->Log("m_ssl_gnutls", DEFAULT, - "m_ssl_gnutls.so: Handshake failed on fd %d: %s", - fd, gnutls_strerror(ret)); CloseSession(session); session->status = ISSL_CLOSING; } @@ -619,18 +580,16 @@ class ModuleSSLGnuTLS : public Module // Change the seesion state session->status = ISSL_HANDSHAKEN; - EventHandler* user = ServerInstance->SE->GetRef(fd); - VerifyCertificate(session,user); // Finish writing, if any left - MakePollWrite(fd); + MakePollWrite(user); return true; } } - virtual void OnPostConnect(User* user) + void OnPostConnect(User* user) { // This occurs AFTER OnUserConnect so we can be sure the // protocol module has propagated the NICK message. @@ -646,22 +605,9 @@ class ModuleSSLGnuTLS : public Module } } - void MakePollWrite(int fd) + void MakePollWrite(EventHandler* eh) { - //OnRawSocketWrite(fd, NULL, 0); - EventHandler* eh = ServerInstance->SE->GetRef(fd); - if (eh) - ServerInstance->SE->WantWrite(eh); - } - - virtual void OnBufferFlushed(User* user) - { - if (user->GetIOHook() == this) - { - issl_session* session = &sessions[user->GetFd()]; - if (session && session->outbuf.size()) - OnRawSocketWrite(user->GetFd(), NULL, 0); - } + ServerInstance->SE->WantWrite(eh); } void CloseSession(issl_session* session) @@ -672,7 +618,6 @@ class ModuleSSLGnuTLS : public Module gnutls_deinit(session->sess); } - session->outbuf.clear(); session->sess = NULL; session->status = ISSL_NONE; } diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp index a33cf6bc2..e77fa23ff 100644 --- a/src/modules/extra/m_ssl_openssl.cpp +++ b/src/modules/extra/m_ssl_openssl.cpp @@ -59,7 +59,7 @@ public: unsigned int inbufoffset; char* inbuf; // Buffer OpenSSL reads into. - std::string outbuf; // Buffer for outgoing data that OpenSSL will not take. + std::string outbuf; int fd; bool outbound; @@ -95,7 +95,6 @@ class ModuleSSLOpenSSL : public Module SSL_CTX* ctx; SSL_CTX* clictx; - char* dummy; char cipher[MAXBUF]; std::string keyfile; @@ -137,14 +136,13 @@ class ModuleSSLOpenSSL : public Module // Needs the flag as it ignores a plain /rehash OnModuleRehash(NULL,"ssl"); - Implementation eventlist[] = { I_OnRawSocketConnect, I_OnRawSocketAccept, - I_OnRawSocketClose, I_OnRawSocketRead, I_OnRawSocketWrite, I_OnCleanup, I_On005Numeric, - I_OnBufferFlushed, I_OnRequest, I_OnRehash, I_OnModuleRehash, I_OnPostConnect, + Implementation eventlist[] = { + I_On005Numeric, I_OnBufferFlushed, I_OnRequest, I_OnRehash, I_OnModuleRehash, I_OnPostConnect, I_OnHookIO }; ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation)); } - virtual void OnHookIO(EventHandler* user, ListenSocketBase* lsb) + void OnHookIO(StreamSocket* user, ListenSocketBase* lsb) { if (!user->GetIOHook() && listenports.find(lsb) != listenports.end()) { @@ -153,7 +151,7 @@ class ModuleSSLOpenSSL : public Module } } - virtual void OnRehash(User* user) + void OnRehash(User* user) { ConfigReader Conf(ServerInstance); @@ -179,7 +177,7 @@ class ModuleSSLOpenSSL : public Module sslports.erase(sslports.end() - 1); } - virtual void OnModuleRehash(User* user, const std::string ¶m) + void OnModuleRehash(User* user, const std::string ¶m) { if (param != "ssl") return; @@ -266,13 +264,13 @@ class ModuleSSLOpenSSL : public Module fclose(dhpfile); } - virtual void On005Numeric(std::string &output) + void On005Numeric(std::string &output) { if (!sslports.empty()) output.append(" SSL=" + sslports); } - virtual ~ModuleSSLOpenSSL() + ~ModuleSSLOpenSSL() { SSL_CTX_free(ctx); SSL_CTX_free(clictx); @@ -280,7 +278,7 @@ class ModuleSSLOpenSSL : public Module delete[] sessions; } - virtual void OnCleanup(int target_type, void* item) + void OnCleanup(int target_type, void* item) { if (target_type == TYPE_USER) { @@ -296,13 +294,13 @@ class ModuleSSLOpenSSL : public Module } } - virtual Version GetVersion() + Version GetVersion() { return Version("$Id$", VF_VENDOR, API_VERSION); } - virtual const char* OnRequest(Request* request) + const char* OnRequest(Request* request) { ISHRequest* ISR = (ISHRequest*)request; if (strcmp("IS_NAME", request->GetId()) == 0) @@ -311,21 +309,13 @@ class ModuleSSLOpenSSL : public Module } else if (strcmp("IS_HOOK", request->GetId()) == 0) { - const char* ret = "OK"; - try - { - ret = ISR->Sock->AddIOHook((Module*)this) ? "OK" : NULL; - } - catch (ModuleException &e) - { - return NULL; - } - - return ret; + ISR->Sock->AddIOHook(this); + return "OK"; } else if (strcmp("IS_UNHOOK", request->GetId()) == 0) { - return ISR->Sock->DelIOHook() ? "OK" : NULL; + ISR->Sock->DelIOHook(); + return "OK"; } else if (strcmp("IS_HSDONE", request->GetId()) == 0) { @@ -353,11 +343,9 @@ class ModuleSSLOpenSSL : public Module } - virtual void OnRawSocketAccept(int fd, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) + void OnStreamSocketAccept(StreamSocket* user, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) { - /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) - return; + int fd = user->GetFd(); issl_session* session = &sessions[fd]; @@ -377,11 +365,12 @@ class ModuleSSLOpenSSL : public Module return; } - Handshake(session); + Handshake(user, session); } - virtual void OnRawSocketConnect(int fd) + void OnStreamSocketConnect(StreamSocket* user) { + int fd = user->GetFd(); /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() -1)) return; @@ -404,11 +393,12 @@ class ModuleSSLOpenSSL : public Module return; } - Handshake(session); + Handshake(user, session); } - virtual void OnRawSocketClose(int fd) + void OnStreamSocketClose(StreamSocket* user) { + int fd = user->GetFd(); /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) return; @@ -416,19 +406,19 @@ class ModuleSSLOpenSSL : public Module CloseSession(&sessions[fd]); } - virtual int OnRawSocketRead(int fd, char* buffer, unsigned int count, int &readresult) + int OnStreamSocketRead(StreamSocket* user, std::string& recvq) { + int fd = user->GetFd(); /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) - return 0; + return -1; issl_session* session = &sessions[fd]; if (!session->sess) { - readresult = 0; CloseSession(session); - return 1; + return -1; } if (session->status == ISSL_HANDSHAKING) @@ -436,17 +426,17 @@ class ModuleSSLOpenSSL : public Module if (session->rstat == ISSL_READ || session->wstat == ISSL_READ) { // The handshake isn't finished and it wants to read, try to finish it. - if (!Handshake(session)) + if (!Handshake(user, session)) { // Couldn't resume handshake. - errno = session->status == ISSL_NONE ? EIO : EAGAIN; - return -1; + if (session->status == ISSL_NONE) + return -1; + return 0; } } else { - errno = EAGAIN; - return -1; + return 0; } } @@ -456,51 +446,37 @@ class ModuleSSLOpenSSL : public Module { if (session->wstat == ISSL_READ) { - if(DoWrite(session) == 0) + if(DoWrite(user, session) == 0) return 0; } if (session->rstat == ISSL_READ) { - int ret = DoRead(session); + int ret = DoRead(user, session); if (ret > 0) { - if (count <= session->inbufoffset) - { - memcpy(buffer, session->inbuf, count); - // Move the stuff left in inbuf to the beginning of it - memmove(session->inbuf, session->inbuf + count, (session->inbufoffset - count)); - // Now we need to set session->inbufoffset to the amount of data still waiting to be handed to insp. - session->inbufoffset -= count; - // Insp uses readresult as the count of how much data there is in buffer, so: - readresult = count; - } - else - { - // There's not as much in the inbuf as there is space in the buffer, so just copy the whole thing. - memcpy(buffer, session->inbuf, session->inbufoffset); - - readresult = session->inbufoffset; - // Zero the offset, as there's nothing there.. - session->inbufoffset = 0; - } + recvq.append(session->inbuf, session->inbufoffset); + session->inbufoffset = 0; return 1; } - return ret; + else if (errno == EAGAIN || errno == EINTR) + return 0; + else + return -1; } } - return -1; + return 0; } - virtual int OnRawSocketWrite(int fd, const char* buffer, int count) + int OnStreamSocketWrite(StreamSocket* user, std::string& buffer) { + int fd = user->GetFd(); /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) - return 0; + return -1; - errno = EAGAIN; issl_session* session = &sessions[fd]; if (!session->sess) @@ -509,40 +485,53 @@ class ModuleSSLOpenSSL : public Module return -1; } - session->outbuf.append(buffer, count); - MakePollWrite(session); - if (session->status == ISSL_HANDSHAKING) { // The handshake isn't finished, try to finish it. if (session->rstat == ISSL_WRITE || session->wstat == ISSL_WRITE) { - if (!Handshake(session)) + if (!Handshake(user, session)) { // Couldn't resume handshake. - errno = session->status == ISSL_NONE ? EIO : EAGAIN; - return -1; + if (session->status == ISSL_NONE) + return -1; + return 0; } } } + int rv = 0; + + // don't pull items into the output buffer until they are + // unlikely to block; this allows sendq exceeded to continue + // to work for SSL users. + // TODO better signaling for I/O requests so this isn't needed + if (session->outbuf.empty()) + { + session->outbuf = buffer; + rv = 1; + } + if (session->status == ISSL_OPEN) { if (session->rstat == ISSL_WRITE) { - DoRead(session); + DoRead(user, session); } if (session->wstat == ISSL_WRITE) { - return DoWrite(session); + DoWrite(user, session); } } - return 1; + if (rv == 0 || !session->outbuf.empty()) + ServerInstance->SE->WantWrite(user); + + return rv; } - int DoWrite(issl_session* session) + int DoWrite(StreamSocket* user, issl_session* session) { if (!session->outbuf.size()) return -1; @@ -561,6 +550,7 @@ class ModuleSSLOpenSSL : public Module if (err == SSL_ERROR_WANT_WRITE) { session->wstat = ISSL_WRITE; + ServerInstance->SE->WantWrite(user); return -1; } else if (err == SSL_ERROR_WANT_READ) @@ -581,7 +571,7 @@ class ModuleSSLOpenSSL : public Module } } - int DoRead(issl_session* session) + int DoRead(StreamSocket* user, issl_session* session) { // Is this right? Not sure if the unencrypted data is garaunteed to be the same length. // Read into the inbuffer, offset from the beginning by the amount of data we have that insp hasn't taken yet. @@ -606,7 +596,7 @@ class ModuleSSLOpenSSL : public Module else if (err == SSL_ERROR_WANT_WRITE) { session->rstat = ISSL_WRITE; - MakePollWrite(session); + ServerInstance->SE->WantWrite(user); return -1; } else @@ -627,7 +617,7 @@ class ModuleSSLOpenSSL : public Module } } - bool Handshake(issl_session* session) + bool Handshake(EventHandler* user, issl_session* session) { int ret; @@ -650,7 +640,7 @@ class ModuleSSLOpenSSL : public Module { session->wstat = ISSL_WRITE; session->status = ISSL_HANDSHAKING; - MakePollWrite(session); + ServerInstance->SE->WantWrite(user); return true; } else @@ -669,7 +659,7 @@ class ModuleSSLOpenSSL : public Module session->status = ISSL_OPEN; - MakePollWrite(session); + ServerInstance->SE->WantWrite(user); return true; } @@ -682,34 +672,14 @@ class ModuleSSLOpenSSL : public Module return true; } - virtual void OnPostConnect(User* user) - { - // This occurs AFTER OnUserConnect so we can be sure the - // protocol module has propagated the NICK message. - if ((user->GetIOHook() == this) && (IS_LOCAL(user))) - { - if (sessions[user->GetFd()].sess) - user->WriteServ("NOTICE %s :*** You are connected using SSL cipher \"%s\"", user->nick.c_str(), SSL_get_cipher(sessions[user->GetFd()].sess)); - } - } - - void MakePollWrite(issl_session* session) - { - //OnRawSocketWrite(session->fd, NULL, 0); - EventHandler* eh = ServerInstance->SE->GetRef(session->fd); - if (eh) - { - ServerInstance->SE->WantWrite(eh); - } - } - - virtual void OnBufferFlushed(User* user) + void OnBufferFlushed(User* user) { if (user->GetIOHook() == this) { + std::string dummy; issl_session* session = &sessions[user->GetFd()]; if (session && session->outbuf.size()) - OnRawSocketWrite(user->GetFd(), NULL, 0); + OnStreamSocketWrite(user, dummy); } } diff --git a/src/modules/extra/m_ziplink.cpp b/src/modules/extra/m_ziplink.cpp index c220460bd..7d090d80a 100644 --- a/src/modules/extra/m_ziplink.cpp +++ b/src/modules/extra/m_ziplink.cpp @@ -67,29 +67,29 @@ class ModuleZLib : public Module total_out_compressed = total_in_compressed = 0; total_out_uncompressed = total_in_uncompressed = 0; - Implementation eventlist[] = { I_OnRawSocketConnect, I_OnRawSocketAccept, I_OnRawSocketClose, I_OnRawSocketRead, I_OnRawSocketWrite, I_OnStats, I_OnRequest }; - ServerInstance->Modules->Attach(eventlist, this, 7); + Implementation eventlist[] = { I_OnStats, I_OnRequest }; + ServerInstance->Modules->Attach(eventlist, this, 2); // Allocate a buffer which is used for reading and writing data net_buffer_size = ServerInstance->Config->NetBufferSize; net_buffer = new char[net_buffer_size]; } - virtual ~ModuleZLib() + ~ModuleZLib() { ServerInstance->Modules->UnpublishInterface("BufferedSocketHook", this); delete[] sessions; delete[] net_buffer; } - virtual Version GetVersion() + Version GetVersion() { return Version("$Id$", VF_VENDOR, API_VERSION); } /* Handle BufferedSocketHook API requests */ - virtual const char* OnRequest(Request* request) + const char* OnRequest(Request* request) { ISHRequest* ISR = (ISHRequest*)request; if (strcmp("IS_NAME", request->GetId()) == 0) @@ -99,22 +99,13 @@ class ModuleZLib : public Module } else if (strcmp("IS_HOOK", request->GetId()) == 0) { - /* Attach to an inspsocket */ - const char* ret = "OK"; - try - { - ret = ISR->Sock->AddIOHook((Module*)this) ? "OK" : NULL; - } - catch (ModuleException& e) - { - return NULL; - } - return ret; + ISR->Sock->AddIOHook(this); + return "OK"; } else if (strcmp("IS_UNHOOK", request->GetId()) == 0) { - /* Detach from an inspsocket */ - return ISR->Sock->DelIOHook() ? "OK" : NULL; + ISR->Sock->DelIOHook(); + return "OK"; } else if (strcmp("IS_HSDONE", request->GetId()) == 0) { @@ -134,7 +125,7 @@ class ModuleZLib : public Module } /* Handle stats z (misc stats) */ - virtual ModResult OnStats(char symbol, User* user, string_list &results) + ModResult OnStats(char symbol, User* user, string_list &results) { if (symbol == 'z') { @@ -174,10 +165,14 @@ class ModuleZLib : public Module return MOD_RES_PASSTHRU; } - virtual void OnRawSocketConnect(int fd) + void OnStreamSocketConnect(StreamSocket* user) { - if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) - return; + OnStreamSocketAccept(user, 0, 0); + } + + void OnRawSocketAccept(StreamSocket* user, irc::sockets::sockaddrs*, irc::sockets::sockaddrs*) + { + int fd = user->GetFd(); izip_session* session = &sessions[fd]; @@ -211,39 +206,33 @@ class ModuleZLib : public Module session->status = IZIP_OPEN; } - virtual void OnRawSocketAccept(int fd, irc::sockets::sockaddrs*, irc::sockets::sockaddrs*) - { - /* Nothing special needs doing here compared to connect() */ - OnRawSocketConnect(fd); - } - - virtual void OnRawSocketClose(int fd) + void OnStreamSocketClose(StreamSocket* user) { + int fd = user->GetFd(); CloseSession(&sessions[fd]); } - virtual int OnRawSocketRead(int fd, char* buffer, unsigned int count, int &readresult) + int OnStreamSocketRead(StreamSocket* user, std::string& recvq) { + int fd = user->GetFd(); /* Find the sockets session */ izip_session* session = &sessions[fd]; if (session->status == IZIP_CLOSED) - return 0; + return -1; - if (session->inbuf.length()) - { - /* Our input buffer is filling up. This is *BAD*. - * We can't return more data than fits into buffer - * (count bytes), so we will generate another read - * event on purpose by *NOT* reading from 'fd' at all - * for now. - */ - readresult = 0; - } - else + if (session->inbuf.empty()) { /* Read read_buffer_size bytes at a time to the buffer (usually 2.5k) */ - readresult = read(fd, net_buffer, net_buffer_size); + int readresult = read(fd, net_buffer, net_buffer_size); + + if (readresult < 0) + { + if (errno == EINTR || errno == EAGAIN) + return 0; + } + if (readresult <= 0) + return -1; total_in_compressed += readresult; @@ -252,10 +241,8 @@ class ModuleZLib : public Module } size_t in_len = session->inbuf.length(); - - /* Do we have anything to do? */ - if (in_len <= 0) - return 0; + char* buffer = ServerInstance->GetReadBuffer(); + int count = ServerInstance->Config->NetBufferSize; /* Prepare decompression */ session->d_stream.next_in = (Bytef *)session->inbuf.c_str(); @@ -302,8 +289,7 @@ class ModuleZLib : public Module } if (ret != Z_OK) { - readresult = 0; - return 0; + return -1; } /* Update the inbut buffer */ @@ -315,24 +301,18 @@ class ModuleZLib : public Module total_in_uncompressed += uncompressed_length; /* Null-terminate the buffer -- this doesnt harm binary data */ - buffer[uncompressed_length] = 0; - - /* Set the read size to the correct total size */ - readresult = uncompressed_length; - + recvq.append(buffer, uncompressed_length); return 1; } - virtual int OnRawSocketWrite(int fd, const char* buffer, int count) + int OnStreamSocketWrite(StreamSocket* user, std::string& sendq) { + int fd = user->GetFd(); izip_session* session = &sessions[fd]; - if (!count) /* Nothing to do! */ - return 0; - if(session->status != IZIP_OPEN) /* Seriously, wtf? */ - return 0; + return -1; int ret; @@ -343,8 +323,8 @@ class ModuleZLib : public Module do { /* Prepare compression */ - session->c_stream.next_in = (Bytef*)buffer + offset; - session->c_stream.avail_in = count - offset; + session->c_stream.next_in = (Bytef*)sendq.data() + offset; + session->c_stream.avail_in = sendq.length() - offset; session->c_stream.next_out = (Bytef*)net_buffer; session->c_stream.avail_out = net_buffer_size; @@ -378,7 +358,7 @@ class ModuleZLib : public Module /* Space before - space after stuff was added to this */ unsigned int compressed = net_buffer_size - session->c_stream.avail_out; - unsigned int uncompressed = count - session->c_stream.avail_in; + unsigned int uncompressed = sendq.length() - session->c_stream.avail_in; /* Make it skip the data which was compressed already */ offset += uncompressed; @@ -404,14 +384,11 @@ class ModuleZLib : public Module else { session->outbuf.clear(); - return 0; + return -1; } } - /* ALL LIES the lot of it, we havent really written - * this amount, but the layer above doesnt need to know. - */ - return count; + return 1; } void Error(izip_session* session, const std::string &text) diff --git a/src/modules/m_httpd.cpp b/src/modules/m_httpd.cpp index bdf4e424e..c1698accf 100644 --- a/src/modules/m_httpd.cpp +++ b/src/modules/m_httpd.cpp @@ -37,6 +37,7 @@ class HttpServerSocket : public BufferedSocket { FileReader* index; HttpState InternalState; + std::string ip; HTTPHeaders headers; std::string reqbuffer; @@ -48,7 +49,8 @@ class HttpServerSocket : public BufferedSocket public: - HttpServerSocket(InspIRCd* SI, int newfd, const char* ip, FileReader* ind) : BufferedSocket(SI, newfd, ip), index(ind), postsize(0) + HttpServerSocket(int newfd, const char* IP, FileReader* ind) + : BufferedSocket(newfd), index(ind), ip(IP), postsize(0) { InternalState = HTTP_SERVE_WAIT_REQUEST; } @@ -62,7 +64,7 @@ class HttpServerSocket : public BufferedSocket { } - virtual void OnClose() + virtual void OnError(BufferedSocketError) { } @@ -164,15 +166,15 @@ class HttpServerSocket : public BufferedSocket "<small>Powered by <a href='http://www.inspircd.org'>InspIRCd</a></small></body></html>"; SendHeaders(data.length(), response, empty); - this->Write(data); + WriteData(data); } void SendHeaders(unsigned long size, int response, HTTPHeaders &rheaders) { - this->Write(http_version + " "+ConvToStr(response)+" "+Response(response)+"\r\n"); + WriteData(http_version + " "+ConvToStr(response)+" "+Response(response)+"\r\n"); - time_t local = this->ServerInstance->Time(); + time_t local = ServerInstance->Time(); struct tm *timeinfo = gmtime(&local); char *date = asctime(timeinfo); date[strlen(date) - 1] = '\0'; @@ -191,40 +193,32 @@ class HttpServerSocket : public BufferedSocket */ rheaders.SetHeader("Connection", "Close"); - this->Write(rheaders.GetFormattedHeaders()); - this->Write("\r\n"); + WriteData(rheaders.GetFormattedHeaders()); + WriteData("\r\n"); } - virtual bool OnDataReady() + void OnDataReady() { - const char* data = this->Read(); - - /* Check that the data read is a valid pointer and it has some content */ - if (!data || !*data) - return false; - if (InternalState == HTTP_SERVE_RECV_POSTDATA) { - postdata.append(data); + postdata.append(recvq); if (postdata.length() >= postsize) ServeData(); } else { - reqbuffer.append(data); + reqbuffer.append(recvq); if (reqbuffer.length() >= 8192) { ServerInstance->Logs->Log("m_httpd",DEBUG, "m_httpd dropped connection due to an oversized request buffer"); reqbuffer.clear(); - return false; + SetError("Buffer"); } if (InternalState == HTTP_SERVE_WAIT_REQUEST) CheckRequestBuffer(); } - - return true; } void CheckRequestBuffer() @@ -314,18 +308,18 @@ class HttpServerSocket : public BufferedSocket { HTTPHeaders empty; SendHeaders(index->ContentSize(), 200, empty); - this->Write(index->Contents()); + WriteData(index->Contents()); } else { claimed = false; - HTTPRequest httpr(request_type,uri,&headers,this,this->GetIP(),postdata); + HTTPRequest httpr(request_type,uri,&headers,this,ip,postdata); Event acl((char*)&httpr, (Module*)HttpModule, "httpd_acl"); - acl.Send(this->ServerInstance); + acl.Send(ServerInstance); if (!claimed) { Event e((char*)&httpr, (Module*)HttpModule, "httpd_url"); - e.Send(this->ServerInstance); + e.Send(ServerInstance); if (!claimed) { SendHTTPError(404); @@ -337,7 +331,7 @@ class HttpServerSocket : public BufferedSocket void Page(std::stringstream* n, int response, HTTPHeaders *hheaders) { SendHeaders(n->str().length(), response, *hheaders); - this->Write(n->str()); + WriteData(n->str()); } }; @@ -358,7 +352,7 @@ class HttpListener : public ListenSocketBase int port; std::string incomingip; irc::sockets::satoap(&client, incomingip, port); - new HttpServerSocket(ServerInstance, nfd, incomingip.c_str(), index); + new HttpServerSocket(nfd, incomingip.c_str(), index); } }; @@ -426,7 +420,6 @@ class ModuleHttpServer : public Module httpsocks[i]->Close(); delete httpsocks[i]->GetIndex(); } - ServerInstance->BufferedSocketCull(); } virtual Version GetVersion() diff --git a/src/modules/m_spanningtree/addline.cpp b/src/modules/m_spanningtree/addline.cpp index 2f7b5132d..3e6d38070 100644 --- a/src/modules/m_spanningtree/addline.cpp +++ b/src/modules/m_spanningtree/addline.cpp @@ -24,7 +24,7 @@ bool TreeSocket::AddLine(const std::string &prefix, parameterlist ¶ms) { if (params.size() < 6) { - this->ServerInstance->SNO->WriteToSnoMask('d',"%s sent me a malformed ADDLINE of type %s.",prefix.c_str(),params[0].c_str()); + ServerInstance->SNO->WriteToSnoMask('d',"%s sent me a malformed ADDLINE of type %s.",prefix.c_str(),params[0].c_str()); return true; } @@ -43,7 +43,7 @@ bool TreeSocket::AddLine(const std::string &prefix, parameterlist ¶ms) if (!xlf) { - this->ServerInstance->SNO->WriteToSnoMask('d',"%s sent me an unknown ADDLINE type (%s).",setter.c_str(),params[0].c_str()); + ServerInstance->SNO->WriteToSnoMask('d',"%s sent me an unknown ADDLINE type (%s).",setter.c_str(),params[0].c_str()); return true; } @@ -54,7 +54,7 @@ bool TreeSocket::AddLine(const std::string &prefix, parameterlist ¶ms) } catch (ModuleException &e) { - this->ServerInstance->SNO->WriteToSnoMask('d',"Unable to ADDLINE type %s from %s: %s", params[0].c_str(), setter.c_str(), e.GetReason()); + ServerInstance->SNO->WriteToSnoMask('d',"Unable to ADDLINE type %s from %s: %s", params[0].c_str(), setter.c_str(), e.GetReason()); return true; } xl->SetCreateTime(atoi(params[3].c_str())); @@ -62,12 +62,12 @@ bool TreeSocket::AddLine(const std::string &prefix, parameterlist ¶ms) { if (xl->duration) { - this->ServerInstance->SNO->WriteToSnoMask('X',"%s added %s%s on %s to expire on %s: %s",setter.c_str(),params[0].c_str(),params[0].length() == 1 ? "-line" : "", + ServerInstance->SNO->WriteToSnoMask('X',"%s added %s%s on %s to expire on %s: %s",setter.c_str(),params[0].c_str(),params[0].length() == 1 ? "-line" : "", params[1].c_str(),ServerInstance->TimeString(xl->expiry).c_str(),params[5].c_str()); } else { - this->ServerInstance->SNO->WriteToSnoMask('X',"%s added permanent %s%s on %s: %s",setter.c_str(),params[0].c_str(),params[0].length() == 1 ? "-line" : "", + ServerInstance->SNO->WriteToSnoMask('X',"%s added permanent %s%s on %s: %s",setter.c_str(),params[0].c_str(),params[0].length() == 1 ? "-line" : "", params[1].c_str(),params[5].c_str()); } params[5] = ":" + params[5]; diff --git a/src/modules/m_spanningtree/admin.cpp b/src/modules/m_spanningtree/admin.cpp index 133da928b..e47078c7e 100644 --- a/src/modules/m_spanningtree/admin.cpp +++ b/src/modules/m_spanningtree/admin.cpp @@ -25,30 +25,30 @@ bool TreeSocket::Admin(const std::string &prefix, parameterlist ¶ms) { if (params.size() > 0) { - if (InspIRCd::Match(this->ServerInstance->Config->ServerName, params[0])) + if (InspIRCd::Match(ServerInstance->Config->ServerName, params[0])) { /* It's for our server */ string_list results; - User* source = this->ServerInstance->FindNick(prefix); + User* source = ServerInstance->FindNick(prefix); if (source) { parameterlist par; par.push_back(prefix); par.push_back(""); par[1] = std::string("::")+ServerInstance->Config->ServerName+" 256 "+source->nick+" :Administrative info for "+ServerInstance->Config->ServerName; - Utils->DoOneToOne(this->ServerInstance->Config->GetSID(), "PUSH",par, source->server); + Utils->DoOneToOne(ServerInstance->Config->GetSID(), "PUSH",par, source->server); par[1] = std::string("::")+ServerInstance->Config->ServerName+" 257 "+source->nick+" :Name - "+ServerInstance->Config->AdminName; - Utils->DoOneToOne(this->ServerInstance->Config->GetSID(), "PUSH",par, source->server); + Utils->DoOneToOne(ServerInstance->Config->GetSID(), "PUSH",par, source->server); par[1] = std::string("::")+ServerInstance->Config->ServerName+" 258 "+source->nick+" :Nickname - "+ServerInstance->Config->AdminNick; - Utils->DoOneToOne(this->ServerInstance->Config->GetSID(), "PUSH",par, source->server); + Utils->DoOneToOne(ServerInstance->Config->GetSID(), "PUSH",par, source->server); par[1] = std::string("::")+ServerInstance->Config->ServerName+" 258 "+source->nick+" :E-Mail - "+ServerInstance->Config->AdminEmail; - Utils->DoOneToOne(this->ServerInstance->Config->GetSID(), "PUSH",par, source->server); + Utils->DoOneToOne(ServerInstance->Config->GetSID(), "PUSH",par, source->server); } } else { /* Pass it on */ - User* source = this->ServerInstance->FindNick(prefix); + User* source = ServerInstance->FindNick(prefix); if (source) Utils->DoOneToOne(prefix, "ADMIN", params, params[0]); } diff --git a/src/modules/m_spanningtree/away.cpp b/src/modules/m_spanningtree/away.cpp index 2aac26bbd..354266554 100644 --- a/src/modules/m_spanningtree/away.cpp +++ b/src/modules/m_spanningtree/away.cpp @@ -20,7 +20,7 @@ bool TreeSocket::Away(const std::string &prefix, parameterlist ¶ms) { - User* u = this->ServerInstance->FindNick(prefix); + User* u = ServerInstance->FindNick(prefix); if (!u) return true; if (params.size()) diff --git a/src/modules/m_spanningtree/capab.cpp b/src/modules/m_spanningtree/capab.cpp index 66d448e55..7953468e4 100644 --- a/src/modules/m_spanningtree/capab.cpp +++ b/src/modules/m_spanningtree/capab.cpp @@ -23,7 +23,7 @@ std::string TreeSocket::MyModules(int filter) { - std::vector<std::string> modlist = this->ServerInstance->Modules->GetAllModuleNames(filter); + std::vector<std::string> modlist = ServerInstance->Modules->GetAllModuleNames(filter); if (filter == VF_COMMON && proto_version != ProtocolVersion) CompatAddModules(modlist); @@ -236,13 +236,13 @@ bool TreeSocket::Capab(const parameterlist ¶ms) } } - if(this->CapKeys.find("PREFIX") != this->CapKeys.end() && this->CapKeys.find("PREFIX")->second != this->ServerInstance->Modes->BuildPrefixes()) + if(this->CapKeys.find("PREFIX") != this->CapKeys.end() && this->CapKeys.find("PREFIX")->second != ServerInstance->Modes->BuildPrefixes()) reason = "One or more of the prefixes on the remote server are invalid on this server."; - if(this->CapKeys.find("CHANMODES") != this->CapKeys.end() && this->CapKeys.find("CHANMODES")->second != this->ServerInstance->Modes->GiveModeList(MASK_CHANNEL)) + if(this->CapKeys.find("CHANMODES") != this->CapKeys.end() && this->CapKeys.find("CHANMODES")->second != ServerInstance->Modes->GiveModeList(MASK_CHANNEL)) reason = "One or more of the channel modes on the remote server are invalid on this server."; - if(this->CapKeys.find("USERMODES") != this->CapKeys.end() && this->CapKeys.find("USERMODES")->second != this->ServerInstance->Modes->GiveModeList(MASK_USER)) + if(this->CapKeys.find("USERMODES") != this->CapKeys.end() && this->CapKeys.find("USERMODES")->second != ServerInstance->Modes->GiveModeList(MASK_USER)) reason = "One or more of the user modes on the remote server are invalid on this server."; @@ -255,8 +255,8 @@ bool TreeSocket::Capab(const parameterlist ¶ms) if (!this->GetTheirChallenge().empty() && (this->LinkState == CONNECTING)) { this->SendCapabilities(2); - this->WriteLine(std::string("SERVER ")+this->ServerInstance->Config->ServerName+" "+this->MakePass(OutboundPass, this->GetTheirChallenge())+" 0 "+ - ServerInstance->Config->GetSID()+" :"+this->ServerInstance->Config->ServerDesc); + this->WriteLine(std::string("SERVER ")+ServerInstance->Config->ServerName+" "+this->MakePass(OutboundPass, this->GetTheirChallenge())+" 0 "+ + ServerInstance->Config->GetSID()+" :"+ServerInstance->Config->ServerDesc); } } else @@ -265,7 +265,7 @@ bool TreeSocket::Capab(const parameterlist ¶ms) if (this->LinkState == CONNECTING) { this->SendCapabilities(2); - this->WriteLine(std::string("SERVER ")+this->ServerInstance->Config->ServerName+" "+OutboundPass+" 0 "+ServerInstance->Config->GetSID()+" :"+this->ServerInstance->Config->ServerDesc); + this->WriteLine(std::string("SERVER ")+ServerInstance->Config->ServerName+" "+OutboundPass+" 0 "+ServerInstance->Config->GetSID()+" :"+ServerInstance->Config->ServerDesc); } } diff --git a/src/modules/m_spanningtree/compat.cpp b/src/modules/m_spanningtree/compat.cpp index 8a6e6855f..71272edec 100644 --- a/src/modules/m_spanningtree/compat.cpp +++ b/src/modules/m_spanningtree/compat.cpp @@ -82,7 +82,7 @@ void TreeSocket::WriteLine(std::string line) ServerInstance->Logs->Log("m_spanningtree",DEBUG, "S[%d] O %s", this->GetFd(), line.c_str()); line.append("\r\n"); - this->Write(line); + this->WriteData(line); } diff --git a/src/modules/m_spanningtree/delline.cpp b/src/modules/m_spanningtree/delline.cpp index a1a9089ad..cadcdd14b 100644 --- a/src/modules/m_spanningtree/delline.cpp +++ b/src/modules/m_spanningtree/delline.cpp @@ -42,7 +42,7 @@ bool TreeSocket::DelLine(const std::string &prefix, parameterlist ¶ms) /* NOTE: No check needed on 'user', this function safely handles NULL */ if (ServerInstance->XLines->DelLine(params[1].c_str(), params[0], user)) { - this->ServerInstance->SNO->WriteToSnoMask('X',"%s removed %s%s on %s", setter.c_str(), + ServerInstance->SNO->WriteToSnoMask('X',"%s removed %s%s on %s", setter.c_str(), params[0].c_str(), params[0].length() == 1 ? "-line" : "", params[1].c_str()); Utils->DoOneToAllButSender(prefix,"DELLINE", params, prefix); } diff --git a/src/modules/m_spanningtree/encap.cpp b/src/modules/m_spanningtree/encap.cpp index 7b85a49d0..175257b0a 100644 --- a/src/modules/m_spanningtree/encap.cpp +++ b/src/modules/m_spanningtree/encap.cpp @@ -29,7 +29,7 @@ bool TreeSocket::Encap(const std::string &prefix, parameterlist ¶ms) { if (InspIRCd::Match(ServerInstance->Config->GetSID(), params[0])) { - User* who = this->ServerInstance->FindUUID(prefix); + User* who = ServerInstance->FindUUID(prefix); if (!who) who = Utils->ServerUser; diff --git a/src/modules/m_spanningtree/fhost.cpp b/src/modules/m_spanningtree/fhost.cpp index 1595b98aa..d31cffa39 100644 --- a/src/modules/m_spanningtree/fhost.cpp +++ b/src/modules/m_spanningtree/fhost.cpp @@ -25,7 +25,7 @@ bool TreeSocket::ChangeHost(const std::string &prefix, parameterlist ¶ms) { if (params.size() < 1) return true; - User* u = this->ServerInstance->FindNick(prefix); + User* u = ServerInstance->FindNick(prefix); if (u) { diff --git a/src/modules/m_spanningtree/fident.cpp b/src/modules/m_spanningtree/fident.cpp index 0744d9bf2..8cd3618db 100644 --- a/src/modules/m_spanningtree/fident.cpp +++ b/src/modules/m_spanningtree/fident.cpp @@ -25,7 +25,7 @@ bool TreeSocket::ChangeIdent(const std::string &prefix, parameterlist ¶ms) { if (params.size() < 1) return true; - User* u = this->ServerInstance->FindNick(prefix); + User* u = ServerInstance->FindNick(prefix); if (u) { u->ChangeIdent(params[0].c_str()); diff --git a/src/modules/m_spanningtree/fjoin.cpp b/src/modules/m_spanningtree/fjoin.cpp index 2c3606db1..7f11f40dd 100644 --- a/src/modules/m_spanningtree/fjoin.cpp +++ b/src/modules/m_spanningtree/fjoin.cpp @@ -59,7 +59,7 @@ bool TreeSocket::ForceJoin(const std::string &source, parameterlist ¶ms) time_t TS = atoi(params[1].c_str()); /* Timestamp given to us for remote side */ irc::tokenstream users((params.size() > 3) ? params[params.size() - 1] : ""); /* users from the user list */ bool apply_other_sides_modes = true; /* True if we are accepting the other side's modes */ - Channel* chan = this->ServerInstance->FindChan(channel); /* The channel we're sending joins to */ + Channel* chan = ServerInstance->FindChan(channel); /* The channel we're sending joins to */ bool created = !chan; /* True if the channel doesnt exist here yet */ std::string item; /* One item in the list of nicks */ @@ -123,7 +123,7 @@ bool TreeSocket::ForceJoin(const std::string &source, parameterlist ¶ms) modelist.push_back(params[idx]); } - this->ServerInstance->SendMode(modelist, Utils->ServerUser); + ServerInstance->SendMode(modelist, Utils->ServerUser); } /* Now, process every 'modes,nick' pair */ @@ -156,7 +156,7 @@ bool TreeSocket::ForceJoin(const std::string &source, parameterlist ¶ms) usr++; /* Check the user actually exists */ - who = this->ServerInstance->FindUUID(usr); + who = ServerInstance->FindUUID(usr); if (who) { /* Check that the user's 'direction' is correct */ @@ -168,7 +168,7 @@ bool TreeSocket::ForceJoin(const std::string &source, parameterlist ¶ms) for (std::string::iterator x = modes.begin(); x != modes.end(); ++x) modestack.Push(*x, who->nick); - Channel::JoinUser(this->ServerInstance, who, channel.c_str(), true, "", route_back_again->bursting, TS); + Channel::JoinUser(ServerInstance, who, channel.c_str(), true, "", route_back_again->bursting, TS); } else { diff --git a/src/modules/m_spanningtree/fmode.cpp b/src/modules/m_spanningtree/fmode.cpp index 3421f8045..3bca098d6 100644 --- a/src/modules/m_spanningtree/fmode.cpp +++ b/src/modules/m_spanningtree/fmode.cpp @@ -34,7 +34,7 @@ bool TreeSocket::ForceMode(const std::string &source, parameterlist ¶ms) std::string sourceserv; /* Are we dealing with an FMODE from a user, or from a server? */ - User* who = this->ServerInstance->FindNick(source); + User* who = ServerInstance->FindNick(source); if (who) { /* FMODE from a user, set sourceserv to the users server name */ @@ -66,7 +66,7 @@ bool TreeSocket::ForceMode(const std::string &source, parameterlist ¶ms) } /* Extract the TS value of the object, either User or Channel */ - User* dst = this->ServerInstance->FindNick(params[0]); + User* dst = ServerInstance->FindNick(params[0]); Channel* chan = NULL; time_t ourTS = 0; @@ -76,7 +76,7 @@ bool TreeSocket::ForceMode(const std::string &source, parameterlist ¶ms) } else { - chan = this->ServerInstance->FindChan(params[0]); + chan = ServerInstance->FindChan(params[0]); if (chan) { ourTS = chan->age; diff --git a/src/modules/m_spanningtree/fname.cpp b/src/modules/m_spanningtree/fname.cpp index a83591a4f..cc7625f12 100644 --- a/src/modules/m_spanningtree/fname.cpp +++ b/src/modules/m_spanningtree/fname.cpp @@ -25,7 +25,7 @@ bool TreeSocket::ChangeName(const std::string &prefix, parameterlist ¶ms) { if (params.size() < 1) return true; - User* u = this->ServerInstance->FindNick(prefix); + User* u = ServerInstance->FindNick(prefix); if (u) { u->ChangeName(params[0].c_str()); diff --git a/src/modules/m_spanningtree/ftopic.cpp b/src/modules/m_spanningtree/ftopic.cpp index 34e97dd11..5a6656e3e 100644 --- a/src/modules/m_spanningtree/ftopic.cpp +++ b/src/modules/m_spanningtree/ftopic.cpp @@ -27,14 +27,14 @@ bool TreeSocket::ForceTopic(const std::string &source, parameterlist ¶ms) if (params.size() != 4) return true; time_t ts = atoi(params[1].c_str()); - Channel* c = this->ServerInstance->FindChan(params[0]); + Channel* c = ServerInstance->FindChan(params[0]); if (c) { if ((ts >= c->topicset) || (c->topic.empty())) { if (c->topic != params[3]) { - User* user = this->ServerInstance->FindNick(source); + User* user = ServerInstance->FindNick(source); // Update topic only when it differs from current topic c->topic.assign(params[3], 0, ServerInstance->Config->Limits.MaxTopic); if (!user) diff --git a/src/modules/m_spanningtree/handshaketimer.cpp b/src/modules/m_spanningtree/handshaketimer.cpp index 56f34283b..814aa122c 100644 --- a/src/modules/m_spanningtree/handshaketimer.cpp +++ b/src/modules/m_spanningtree/handshaketimer.cpp @@ -37,15 +37,15 @@ HandshakeTimer::~HandshakeTimer() void HandshakeTimer::Tick(time_t TIME) { - if (!sock->GetHook()) + if (!sock->GetIOHook()) { CancelRepeat(); sock->SendCapabilities(1); } - else if (BufferedSocketHSCompleteRequest(sock, (Module*)Utils->Creator, sock->GetHook()).Send()) + else if (BufferedSocketHSCompleteRequest(sock, Utils->Creator, sock->GetIOHook()).Send()) { CancelRepeat(); - BufferedSocketAttachCertRequest(sock, (Module*)Utils->Creator, sock->GetHook()).Send(); + BufferedSocketAttachCertRequest(sock, Utils->Creator, sock->GetIOHook()).Send(); sock->SendCapabilities(1); } // otherwise, try again later diff --git a/src/modules/m_spanningtree/hmac.cpp b/src/modules/m_spanningtree/hmac.cpp index cc1b33f23..b7cddc47a 100644 --- a/src/modules/m_spanningtree/hmac.cpp +++ b/src/modules/m_spanningtree/hmac.cpp @@ -129,9 +129,9 @@ bool TreeSocket::ComparePass(const Link& link, const std::string &theirs) this->auth_challenge = !ourchallenge.empty() && !theirchallenge.empty(); std::string fp; - if (GetHook()) + if (GetIOHook()) { - BufferedSocketCertificateRequest req(this, Utils->Creator, GetHook()); + BufferedSocketCertificateRequest req(this, Utils->Creator, GetIOHook()); req.Send(); if (req.cert) { diff --git a/src/modules/m_spanningtree/kill.cpp b/src/modules/m_spanningtree/kill.cpp index c2026d0bb..e76fc7f3e 100644 --- a/src/modules/m_spanningtree/kill.cpp +++ b/src/modules/m_spanningtree/kill.cpp @@ -28,7 +28,7 @@ bool TreeSocket::RemoteKill(const std::string &prefix, parameterlist ¶ms) if (params.size() != 2) return true; - User* who = this->ServerInstance->FindNick(params[0]); + User* who = ServerInstance->FindNick(params[0]); if (who) { @@ -46,7 +46,7 @@ bool TreeSocket::RemoteKill(const std::string &prefix, parameterlist ¶ms) // this shouldn't ever be null, but it doesn't hurt to check who->Write(":%s KILL %s :%s (%s)", src->GetName().c_str(), who->nick.c_str(), src->GetName().c_str(), reason.c_str()); } - this->ServerInstance->Users->QuitUser(who, reason); + ServerInstance->Users->QuitUser(who, reason); } return true; } diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp index 1bc3dfe39..230c3109b 100644 --- a/src/modules/m_spanningtree/main.cpp +++ b/src/modules/m_spanningtree/main.cpp @@ -275,7 +275,7 @@ void ModuleSpanningTree::ConnectServer(Link* x, Autoconnect* y) /* Gave a hook, but it wasnt one we know */ if ((!x->Hook.empty()) && (Utils->hooks.find(x->Hook.c_str()) == Utils->hooks.end())) return; - TreeSocket* newsocket = new TreeSocket(Utils, ServerInstance, x->IPAddr,x->Port, x->Timeout ? x->Timeout : 10,x->Name.c_str(), x->Bind, y, x->Hook.empty() ? NULL : Utils->hooks[x->Hook.c_str()]); + TreeSocket* newsocket = new TreeSocket(Utils, x->IPAddr,x->Port, x->Timeout ? x->Timeout : 10,x->Name.c_str(), x->Bind, y, x->Hook.empty() ? NULL : Utils->hooks[x->Hook.c_str()]); if (newsocket->GetFd() > -1) { /* Handled automatically on success */ @@ -283,8 +283,7 @@ void ModuleSpanningTree::ConnectServer(Link* x, Autoconnect* y) else { ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: %s.",x->Name.c_str(),strerror(errno)); - if (ServerInstance->SocketCull.find(newsocket) == ServerInstance->SocketCull.end()) - ServerInstance->SocketCull[newsocket] = newsocket; + ServerInstance->GlobalCulls.AddItem(newsocket); Utils->DoFailOver(y); } } diff --git a/src/modules/m_spanningtree/metadata.cpp b/src/modules/m_spanningtree/metadata.cpp index 40a98d93b..135970a4a 100644 --- a/src/modules/m_spanningtree/metadata.cpp +++ b/src/modules/m_spanningtree/metadata.cpp @@ -33,26 +33,26 @@ bool TreeSocket::MetaData(const std::string &prefix, parameterlist ¶ms) { if (params[0] == "*") { - FOREACH_MOD_I(this->ServerInstance,I_OnDecodeMetaData,OnDecodeMetaData(NULL,params[1],params[2])); + FOREACH_MOD_I(ServerInstance,I_OnDecodeMetaData,OnDecodeMetaData(NULL,params[1],params[2])); } else if (*(params[0].c_str()) == '#') { - Channel* c = this->ServerInstance->FindChan(params[0]); + Channel* c = ServerInstance->FindChan(params[0]); if (c) { if (item) item->unserialize(FORMAT_NETWORK, c, params[2]); - FOREACH_MOD_I(this->ServerInstance,I_OnDecodeMetaData,OnDecodeMetaData(c,params[1],params[2])); + FOREACH_MOD_I(ServerInstance,I_OnDecodeMetaData,OnDecodeMetaData(c,params[1],params[2])); } } else if (*(params[0].c_str()) != '#') { - User* u = this->ServerInstance->FindNick(params[0]); + User* u = ServerInstance->FindNick(params[0]); if (u) { if (item) item->unserialize(FORMAT_NETWORK, u, params[2]); - FOREACH_MOD_I(this->ServerInstance,I_OnDecodeMetaData,OnDecodeMetaData(u,params[1],params[2])); + FOREACH_MOD_I(ServerInstance,I_OnDecodeMetaData,OnDecodeMetaData(u,params[1],params[2])); } } } diff --git a/src/modules/m_spanningtree/modules.cpp b/src/modules/m_spanningtree/modules.cpp index 6c9132794..7a20a98ff 100644 --- a/src/modules/m_spanningtree/modules.cpp +++ b/src/modules/m_spanningtree/modules.cpp @@ -26,7 +26,7 @@ bool TreeSocket::Modules(const std::string &prefix, parameterlist ¶ms) if (params.empty()) return true; - if (!InspIRCd::Match(this->ServerInstance->Config->ServerName, params[0])) + if (!InspIRCd::Match(ServerInstance->Config->ServerName, params[0])) { /* Pass it on, not for us */ Utils->DoOneToOne(prefix, "MODULES", params, params[0]); @@ -38,7 +38,7 @@ bool TreeSocket::Modules(const std::string &prefix, parameterlist ¶ms) par.push_back(prefix); par.push_back(""); - User* source = this->ServerInstance->FindNick(prefix); + User* source = ServerInstance->FindNick(prefix); if (!source) return true; diff --git a/src/modules/m_spanningtree/motd.cpp b/src/modules/m_spanningtree/motd.cpp index e42c53152..0c775d644 100644 --- a/src/modules/m_spanningtree/motd.cpp +++ b/src/modules/m_spanningtree/motd.cpp @@ -27,11 +27,11 @@ bool TreeSocket::Motd(const std::string &prefix, parameterlist ¶ms) { if (params.size() > 0) { - if (InspIRCd::Match(this->ServerInstance->Config->ServerName, params[0])) + if (InspIRCd::Match(ServerInstance->Config->ServerName, params[0])) { /* It's for our server */ string_list results; - User* source = this->ServerInstance->FindNick(prefix); + User* source = ServerInstance->FindNick(prefix); if (source) { @@ -42,27 +42,27 @@ bool TreeSocket::Motd(const std::string &prefix, parameterlist ¶ms) if (!ServerInstance->Config->MOTD.size()) { par[1] = std::string("::")+ServerInstance->Config->ServerName+" 422 "+source->nick+" :Message of the day file is missing."; - Utils->DoOneToOne(this->ServerInstance->Config->GetSID(), "PUSH",par, source->server); + Utils->DoOneToOne(ServerInstance->Config->GetSID(), "PUSH",par, source->server); return true; } par[1] = std::string("::")+ServerInstance->Config->ServerName+" 375 "+source->nick+" :"+ServerInstance->Config->ServerName+" message of the day"; - Utils->DoOneToOne(this->ServerInstance->Config->GetSID(), "PUSH",par, source->server); + Utils->DoOneToOne(ServerInstance->Config->GetSID(), "PUSH",par, source->server); for (unsigned int i = 0; i < ServerInstance->Config->MOTD.size(); i++) { par[1] = std::string("::")+ServerInstance->Config->ServerName+" 372 "+source->nick+" :- "+ServerInstance->Config->MOTD[i]; - Utils->DoOneToOne(this->ServerInstance->Config->GetSID(), "PUSH",par, source->server); + Utils->DoOneToOne(ServerInstance->Config->GetSID(), "PUSH",par, source->server); } par[1] = std::string("::")+ServerInstance->Config->ServerName+" 376 "+source->nick+" :End of message of the day."; - Utils->DoOneToOne(this->ServerInstance->Config->GetSID(), "PUSH",par, source->server); + Utils->DoOneToOne(ServerInstance->Config->GetSID(), "PUSH",par, source->server); } } else { /* Pass it on */ - User* source = this->ServerInstance->FindNick(prefix); + User* source = ServerInstance->FindNick(prefix); if (source) Utils->DoOneToOne(prefix, "MOTD", params, params[0]); } diff --git a/src/modules/m_spanningtree/netburst.cpp b/src/modules/m_spanningtree/netburst.cpp index ada10e6a1..3cfad9b63 100644 --- a/src/modules/m_spanningtree/netburst.cpp +++ b/src/modules/m_spanningtree/netburst.cpp @@ -30,16 +30,16 @@ void TreeSocket::DoBurst(TreeServer* s) { std::string name = s->GetName(); - std::string burst = ":" + this->ServerInstance->Config->GetSID() + " BURST " +ConvToStr(ServerInstance->Time()); - std::string endburst = ":" + this->ServerInstance->Config->GetSID() + " ENDBURST"; - this->ServerInstance->SNO->WriteToSnoMask('l',"Bursting to \2%s\2 (Authentication: %s%s).", + std::string burst = ":" + ServerInstance->Config->GetSID() + " BURST " +ConvToStr(ServerInstance->Time()); + std::string endburst = ":" + ServerInstance->Config->GetSID() + " ENDBURST"; + ServerInstance->SNO->WriteToSnoMask('l',"Bursting to \2%s\2 (Authentication: %s%s).", name.c_str(), this->auth_fingerprint ? "SSL Fingerprint and " : "", this->auth_challenge ? "challenge-response" : "plaintext password"); this->CleanNegotiationInfo(); this->WriteLine(burst); /* send our version string */ - this->WriteLine(std::string(":")+this->ServerInstance->Config->GetSID()+" VERSION :"+this->ServerInstance->GetVersionString()); + this->WriteLine(std::string(":")+ServerInstance->Config->GetSID()+" VERSION :"+ServerInstance->GetVersionString()); /* Send server tree */ this->SendServers(Utils->TreeRoot,s,1); /* Send users and their oper status */ @@ -47,9 +47,9 @@ void TreeSocket::DoBurst(TreeServer* s) /* Send everything else (channel modes, xlines etc) */ this->SendChannelModes(s); this->SendXLines(s); - FOREACH_MOD_I(this->ServerInstance,I_OnSyncNetwork,OnSyncNetwork(Utils->Creator,(void*)this)); + FOREACH_MOD_I(ServerInstance,I_OnSyncNetwork,OnSyncNetwork(Utils->Creator,(void*)this)); this->WriteLine(endburst); - this->ServerInstance->SNO->WriteToSnoMask('l',"Finished bursting to \2"+name+"\2."); + ServerInstance->SNO->WriteToSnoMask('l',"Finished bursting to \2"+name+"\2."); } /** Recursively send the server tree with distances as hops. @@ -91,7 +91,7 @@ void TreeSocket::SendFJoins(TreeServer* Current, Channel* c) size_t curlen, headlen; curlen = headlen = snprintf(list,MAXBUF,":%s FJOIN %s %lu +%s :", - this->ServerInstance->Config->GetSID().c_str(), c->name.c_str(), (unsigned long)c->age, c->ChanModes(true)); + ServerInstance->Config->GetSID().c_str(), c->name.c_str(), (unsigned long)c->age, c->ChanModes(true)); int numusers = 0; char* ptr = list + curlen; bool looped_once = false; @@ -103,7 +103,7 @@ void TreeSocket::SendFJoins(TreeServer* Current, Channel* c) for (UserMembCIter i = ulist->begin(); i != ulist->end(); i++) { size_t ptrlen = 0; - std::string modestr = this->ServerInstance->Modes->ModeString(i->first, c, false); + std::string modestr = ServerInstance->Modes->ModeString(i->first, c, false); if ((curlen + modestr.length() + i->first->uuid.length() + 4) > 480) { @@ -150,7 +150,7 @@ void TreeSocket::SendFJoins(TreeServer* Current, Channel* c) if ((params.length() >= ServerInstance->Config->Limits.MaxModes) || (currsize > 350)) { /* Wrap at MAXMODES */ - buffer.append(":").append(this->ServerInstance->Config->GetSID()).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(modes).append(params).append("\r\n"); + buffer.append(":").append(ServerInstance->Config->GetSID()).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(modes).append(params).append("\r\n"); modes.clear(); params.clear(); linesize = 1; @@ -159,7 +159,7 @@ void TreeSocket::SendFJoins(TreeServer* Current, Channel* c) /* Only send these if there are any */ if (!modes.empty()) - buffer.append(":").append(this->ServerInstance->Config->GetSID()).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(modes).append(params); + buffer.append(":").append(ServerInstance->Config->GetSID()).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(modes).append(params); this->WriteLine(buffer); } @@ -168,7 +168,7 @@ void TreeSocket::SendFJoins(TreeServer* Current, Channel* c) void TreeSocket::SendXLines(TreeServer* Current) { char data[MAXBUF]; - std::string n = this->ServerInstance->Config->GetSID(); + std::string n = ServerInstance->Config->GetSID(); const char* sn = n.c_str(); std::vector<std::string> types = ServerInstance->XLines->GetAllTypes(); @@ -209,9 +209,9 @@ void TreeSocket::SendChannelModes(TreeServer* Current) { char data[MAXBUF]; std::deque<std::string> list; - std::string n = this->ServerInstance->Config->GetSID(); + std::string n = ServerInstance->Config->GetSID(); const char* sn = n.c_str(); - for (chan_hash::iterator c = this->ServerInstance->chanlist->begin(); c != this->ServerInstance->chanlist->end(); c++) + for (chan_hash::iterator c = ServerInstance->chanlist->begin(); c != ServerInstance->chanlist->end(); c++) { SendFJoins(Current, c->second); if (!c->second->topic.empty()) @@ -230,7 +230,7 @@ void TreeSocket::SendChannelModes(TreeServer* Current) Utils->Creator->ProtoSendMetaData(this, c->second, i->first, value); } - FOREACH_MOD_I(this->ServerInstance,I_OnSyncChannel,OnSyncChannel(c->second,Utils->Creator,this)); + FOREACH_MOD_I(ServerInstance,I_OnSyncChannel,OnSyncChannel(c->second,Utils->Creator,this)); } } @@ -239,7 +239,7 @@ void TreeSocket::SendUsers(TreeServer* Current) { char data[MAXBUF]; std::string dataline; - for (user_hash::iterator u = this->ServerInstance->Users->clientlist->begin(); u != this->ServerInstance->Users->clientlist->end(); u++) + for (user_hash::iterator u = ServerInstance->Users->clientlist->begin(); u != ServerInstance->Users->clientlist->end(); u++) { if (u->second->registered == REG_ALL) { @@ -281,7 +281,7 @@ void TreeSocket::SendUsers(TreeServer* Current) Utils->Creator->ProtoSendMetaData(this, u->second, i->first, value); } - FOREACH_MOD_I(this->ServerInstance,I_OnSyncUser,OnSyncUser(u->second,Utils->Creator,this)); + FOREACH_MOD_I(ServerInstance,I_OnSyncUser,OnSyncUser(u->second,Utils->Creator,this)); } } } diff --git a/src/modules/m_spanningtree/nickcollide.cpp b/src/modules/m_spanningtree/nickcollide.cpp index a723c114f..4481ba35e 100644 --- a/src/modules/m_spanningtree/nickcollide.cpp +++ b/src/modules/m_spanningtree/nickcollide.cpp @@ -114,7 +114,7 @@ int TreeSocket::DoCollision(User *u, time_t remotets, const std::string &remotei } if (bChangeRemote) { - User *remote = this->ServerInstance->FindUUID(remoteuid); + User *remote = ServerInstance->FindUUID(remoteuid); /* * remote side needs to change. If this happens, we will modify * the UID or halt the propagation of the nick change command, diff --git a/src/modules/m_spanningtree/operquit.cpp b/src/modules/m_spanningtree/operquit.cpp index 5cdee3bc6..9128baa0f 100644 --- a/src/modules/m_spanningtree/operquit.cpp +++ b/src/modules/m_spanningtree/operquit.cpp @@ -26,7 +26,7 @@ bool TreeSocket::OperQuit(const std::string &prefix, parameterlist ¶ms) if (params.size() < 1) return true; - User* u = this->ServerInstance->FindNick(prefix); + User* u = ServerInstance->FindNick(prefix); if (u) { diff --git a/src/modules/m_spanningtree/opertype.cpp b/src/modules/m_spanningtree/opertype.cpp index c1105aa71..a1ad88007 100644 --- a/src/modules/m_spanningtree/opertype.cpp +++ b/src/modules/m_spanningtree/opertype.cpp @@ -29,11 +29,11 @@ bool TreeSocket::OperType(const std::string &prefix, parameterlist ¶ms) if (params.size() != 1) return true; std::string opertype = params[0]; - User* u = this->ServerInstance->FindNick(prefix); + User* u = ServerInstance->FindNick(prefix); if (u) { if (!IS_OPER(u)) - this->ServerInstance->Users->all_opers.push_back(u); + ServerInstance->Users->all_opers.push_back(u); u->modes[UM_OPERATOR] = 1; u->oper.assign(opertype, 0, 512); Utils->DoOneToAllButSender(u->uuid, "OPERTYPE", params, u->server); @@ -49,7 +49,7 @@ bool TreeSocket::OperType(const std::string &prefix, parameterlist ¶ms) */ if ( remoteserver->bursting || - this->ServerInstance->SilentULine(this->ServerInstance->FindServerNamePtr(u->server)) + ServerInstance->SilentULine(ServerInstance->FindServerNamePtr(u->server)) ) { dosend = false; @@ -57,7 +57,7 @@ bool TreeSocket::OperType(const std::string &prefix, parameterlist ¶ms) } if (dosend) - this->ServerInstance->SNO->WriteToSnoMask('O',"From %s: User %s (%s@%s) is now an IRC operator of type %s",u->server, u->nick.c_str(),u->ident.c_str(), u->host.c_str(), irc::Spacify(opertype.c_str())); + ServerInstance->SNO->WriteToSnoMask('O',"From %s: User %s (%s@%s) is now an IRC operator of type %s",u->server, u->nick.c_str(),u->ident.c_str(), u->host.c_str(), irc::Spacify(opertype.c_str())); } return true; } diff --git a/src/modules/m_spanningtree/override_stats.cpp b/src/modules/m_spanningtree/override_stats.cpp index 9986763d9..5d0239f84 100644 --- a/src/modules/m_spanningtree/override_stats.cpp +++ b/src/modules/m_spanningtree/override_stats.cpp @@ -78,8 +78,8 @@ ModResult ModuleSpanningTree::OnStats(char statschar, User* user, string_list &r ip = "*"; std::string transport("plaintext"); - if (Utils->Bindings[i]->GetIOHook()) - transport = BufferedSocketNameRequest(this, Utils->Bindings[i]->GetIOHook()).Send(); + if (Utils->Bindings[i]->Hook) + transport = BufferedSocketNameRequest(this, Utils->Bindings[i]->Hook).Send(); results.push_back(ConvToStr(ServerInstance->Config->ServerName) + " 249 "+user->nick+" :" + ip + ":" + ConvToStr(Utils->Bindings[i]->GetPort())+ " (server, " + transport + ")"); diff --git a/src/modules/m_spanningtree/ping.cpp b/src/modules/m_spanningtree/ping.cpp index 1318b60a0..c3467c984 100644 --- a/src/modules/m_spanningtree/ping.cpp +++ b/src/modules/m_spanningtree/ping.cpp @@ -31,13 +31,13 @@ bool TreeSocket::LocalPing(const std::string &prefix, parameterlist ¶ms) if (params.size() == 1) { std::string stufftobounce = params[0]; - this->WriteLine(std::string(":")+this->ServerInstance->Config->GetSID()+" PONG "+stufftobounce); + this->WriteLine(std::string(":")+ServerInstance->Config->GetSID()+" PONG "+stufftobounce); return true; } else { std::string forwardto = params[1]; - if (forwardto == this->ServerInstance->Config->ServerName || forwardto == this->ServerInstance->Config->GetSID()) + if (forwardto == ServerInstance->Config->ServerName || forwardto == ServerInstance->Config->GetSID()) { // this is a ping for us, send back PONG to the requesting server params[1] = params[0]; diff --git a/src/modules/m_spanningtree/pong.cpp b/src/modules/m_spanningtree/pong.cpp index b551ef6d2..274641897 100644 --- a/src/modules/m_spanningtree/pong.cpp +++ b/src/modules/m_spanningtree/pong.cpp @@ -52,7 +52,7 @@ bool TreeSocket::LocalPong(const std::string &prefix, parameterlist ¶ms) * dump the PONG reply back to their fd. If its a server, do nowt. * Services might want to send these s->s, but we dont need to yet. */ - User* u = this->ServerInstance->FindNick(prefix); + User* u = ServerInstance->FindNick(prefix); if (u) { u->WriteServ("PONG %s %s",params[0].c_str(),params[1].c_str()); diff --git a/src/modules/m_spanningtree/push.cpp b/src/modules/m_spanningtree/push.cpp index 88c6b55bd..778c2291c 100644 --- a/src/modules/m_spanningtree/push.cpp +++ b/src/modules/m_spanningtree/push.cpp @@ -28,7 +28,7 @@ bool TreeSocket::Push(const std::string &prefix, parameterlist ¶ms) { if (params.size() < 2) return true; - User* u = this->ServerInstance->FindNick(params[0]); + User* u = ServerInstance->FindNick(params[0]); if (!u) return true; if (IS_LOCAL(u)) diff --git a/src/modules/m_spanningtree/resolvers.cpp b/src/modules/m_spanningtree/resolvers.cpp index 73e67c4f7..c7c49b348 100644 --- a/src/modules/m_spanningtree/resolvers.cpp +++ b/src/modules/m_spanningtree/resolvers.cpp @@ -49,7 +49,7 @@ void ServernameResolver::OnLookupComplete(const std::string &result, unsigned in if ((!MyLink.Hook.empty()) && (Utils->hooks.find(MyLink.Hook.c_str()) == Utils->hooks.end())) return; - TreeSocket* newsocket = new TreeSocket(this->Utils, ServerInstance, result,MyLink.Port,MyLink.Timeout ? MyLink.Timeout : 10,MyLink.Name.c_str(), + TreeSocket* newsocket = new TreeSocket(this->Utils, result,MyLink.Port,MyLink.Timeout ? MyLink.Timeout : 10,MyLink.Name.c_str(), MyLink.Bind, myautoconnect, MyLink.Hook.empty() ? NULL : Utils->hooks[MyLink.Hook.c_str()]); if (newsocket->GetFd() > -1) { @@ -59,8 +59,7 @@ void ServernameResolver::OnLookupComplete(const std::string &result, unsigned in { /* Something barfed, show the opers */ ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: %s.",MyLink.Name.c_str(),strerror(errno)); - if (ServerInstance->SocketCull.find(newsocket) == ServerInstance->SocketCull.end()) - ServerInstance->SocketCull[newsocket] = newsocket; + ServerInstance->GlobalCulls.AddItem(newsocket); Utils->DoFailOver(myautoconnect); } } diff --git a/src/modules/m_spanningtree/save.cpp b/src/modules/m_spanningtree/save.cpp index 9969fdca7..cfa8dc794 100644 --- a/src/modules/m_spanningtree/save.cpp +++ b/src/modules/m_spanningtree/save.cpp @@ -32,7 +32,7 @@ bool TreeSocket::ForceNick(const std::string &prefix, parameterlist ¶ms) if (params.size() < 2) return true; - User* u = this->ServerInstance->FindNick(params[0]); + User* u = ServerInstance->FindNick(params[0]); time_t ts = atol(params[1].c_str()); if (u && u->age == ts) @@ -41,7 +41,7 @@ bool TreeSocket::ForceNick(const std::string &prefix, parameterlist ¶ms) if (!u->ForceNickChange(u->uuid.c_str())) { - this->ServerInstance->Users->QuitUser(u, "Nickname collision"); + ServerInstance->Users->QuitUser(u, "Nickname collision"); } } diff --git a/src/modules/m_spanningtree/server.cpp b/src/modules/m_spanningtree/server.cpp index c275f3490..025675642 100644 --- a/src/modules/m_spanningtree/server.cpp +++ b/src/modules/m_spanningtree/server.cpp @@ -49,7 +49,7 @@ bool TreeSocket::RemoteServer(const std::string &prefix, parameterlist ¶ms) this->SendError("Protocol error - Introduced remote server from unknown server "+ParentOfThis->GetName()); return false; } - if (!this->ServerInstance->IsSID(sid)) + if (!ServerInstance->IsSID(sid)) { this->SendError("Invalid format server ID: "+sid+"!"); return false; @@ -58,26 +58,26 @@ bool TreeSocket::RemoteServer(const std::string &prefix, parameterlist ¶ms) if (CheckDupe) { this->SendError("Server "+servername+" already exists!"); - this->ServerInstance->SNO->WriteToSnoMask('L', "Server \2"+CheckDupe->GetName()+"\2 being introduced from \2" + ParentOfThis->GetName() + "\2 denied, already exists. Closing link with " + ParentOfThis->GetName()); + ServerInstance->SNO->WriteToSnoMask('L', "Server \2"+CheckDupe->GetName()+"\2 being introduced from \2" + ParentOfThis->GetName() + "\2 denied, already exists. Closing link with " + ParentOfThis->GetName()); return false; } CheckDupe = Utils->FindServer(sid); if (CheckDupe) { this->SendError("Server ID "+sid+" already exists! You may want to specify the server ID for the server manually with <server:id> so they do not conflict."); - this->ServerInstance->SNO->WriteToSnoMask('L', "Server \2"+servername+"\2 being introduced from \2" + ParentOfThis->GetName() + "\2 denied, server ID already exists on the network. Closing link with " + ParentOfThis->GetName()); + ServerInstance->SNO->WriteToSnoMask('L', "Server \2"+servername+"\2 being introduced from \2" + ParentOfThis->GetName() + "\2 denied, server ID already exists on the network. Closing link with " + ParentOfThis->GetName()); return false; } Link* lnk = Utils->FindLink(servername); - TreeServer *Node = new TreeServer(this->Utils, this->ServerInstance, servername, description, sid, ParentOfThis,NULL, lnk ? lnk->Hidden : false); + TreeServer *Node = new TreeServer(this->Utils, ServerInstance, servername, description, sid, ParentOfThis,NULL, lnk ? lnk->Hidden : false); ParentOfThis->AddChild(Node); params[4] = ":" + params[4]; Utils->DoOneToAllButSender(prefix,"SERVER",params,prefix); - this->ServerInstance->SNO->WriteToSnoMask('L', "Server \002"+ParentOfThis->GetName()+"\002 introduced server \002"+servername+"\002 ("+description+")"); + ServerInstance->SNO->WriteToSnoMask('L', "Server \002"+ParentOfThis->GetName()+"\002 introduced server \002"+servername+"\002 ("+description+")"); return true; } @@ -110,11 +110,11 @@ bool TreeSocket::Outbound_Reply_Server(parameterlist ¶ms) if (hops) { this->SendError("Server too far away for authentication"); - this->ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, server is too far away for authentication"); + ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, server is too far away for authentication"); return false; } - if (!this->ServerInstance->IsSID(sid)) + if (!ServerInstance->IsSID(sid)) { this->SendError("Invalid format server ID: "+sid+"!"); return false; @@ -127,7 +127,7 @@ bool TreeSocket::Outbound_Reply_Server(parameterlist ¶ms) if (!ComparePass(*x, password)) { - this->ServerInstance->SNO->WriteToSnoMask('l',"Invalid password on link: %s", x->Name.c_str()); + ServerInstance->SNO->WriteToSnoMask('l',"Invalid password on link: %s", x->Name.c_str()); continue; } @@ -135,14 +135,14 @@ bool TreeSocket::Outbound_Reply_Server(parameterlist ¶ms) if (CheckDupe) { this->SendError("Server "+sname+" already exists on server "+CheckDupe->GetParent()->GetName()+"!"); - this->ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, already exists on server "+CheckDupe->GetParent()->GetName()); + ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, already exists on server "+CheckDupe->GetParent()->GetName()); return false; } CheckDupe = Utils->FindServer(sid); if (CheckDupe) { this->SendError("Server ID "+sid+" already exists on the network! You may want to specify the server ID for the server manually with <server:id> so they do not conflict."); - this->ServerInstance->SNO->WriteToSnoMask('l',"Server \2"+assign(servername)+"\2 being introduced denied, server ID already exists on the network. Closing link."); + ServerInstance->SNO->WriteToSnoMask('l',"Server \2"+assign(servername)+"\2 being introduced denied, server ID already exists on the network. Closing link."); return false; } @@ -158,7 +158,7 @@ bool TreeSocket::Outbound_Reply_Server(parameterlist ¶ms) Utils->timeoutlist.erase(this); - TreeServer *Node = new TreeServer(this->Utils, this->ServerInstance, sname, description, sid, Utils->TreeRoot, this, x->Hidden); + TreeServer *Node = new TreeServer(this->Utils, ServerInstance, sname, description, sid, Utils->TreeRoot, this, x->Hidden); Utils->TreeRoot->AddChild(Node); params[4] = ":" + params[4]; @@ -173,7 +173,7 @@ bool TreeSocket::Outbound_Reply_Server(parameterlist ¶ms) } this->SendError("Invalid credentials (check the other server's linking snomask for more information)"); - this->ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, invalid link credentials"); + ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, invalid link credentials"); return false; } @@ -205,11 +205,11 @@ bool TreeSocket::Inbound_Server(parameterlist ¶ms) if (hops) { this->SendError("Server too far away for authentication"); - this->ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, server is too far away for authentication"); + ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, server is too far away for authentication"); return false; } - if (!this->ServerInstance->IsSID(sid)) + if (!ServerInstance->IsSID(sid)) { this->SendError("Invalid format server ID: "+sid+"!"); return false; @@ -222,7 +222,7 @@ bool TreeSocket::Inbound_Server(parameterlist ¶ms) if (!ComparePass(*x, password)) { - this->ServerInstance->SNO->WriteToSnoMask('l',"Invalid password on link: %s", x->Name.c_str()); + ServerInstance->SNO->WriteToSnoMask('l',"Invalid password on link: %s", x->Name.c_str()); continue; } @@ -231,7 +231,7 @@ bool TreeSocket::Inbound_Server(parameterlist ¶ms) if (CheckDupe) { this->SendError("Server "+sname+" already exists on server "+CheckDupe->GetParent()->GetName()+"!"); - this->ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, already exists on server "+CheckDupe->GetParent()->GetName()); + ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, already exists on server "+CheckDupe->GetParent()->GetName()); return false; } @@ -242,30 +242,30 @@ bool TreeSocket::Inbound_Server(parameterlist ¶ms) if (CheckDupe) { this->SendError("Server ID "+CheckDupe->GetID()+" already exists on server "+CheckDupe->GetName()+"! You may want to specify the server ID for the server manually with <server:id> so they do not conflict."); - this->ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, server ID '"+CheckDupe->GetID()+ + ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, server ID '"+CheckDupe->GetID()+ "' already exists on server "+CheckDupe->GetName()); return false; } - this->ServerInstance->SNO->WriteToSnoMask('l',"Verified incoming server connection from \002"+sname+"\002["+(x->HiddenFromStats ? "<hidden>" : this->GetIP())+"] ("+description+")"); - if (this->Hook) + ServerInstance->SNO->WriteToSnoMask('l',"Verified incoming server connection from \002"+sname+"\002["+(x->HiddenFromStats ? "<hidden>" : this->IP)+"] ("+description+")"); + if (this->GetIOHook()) { - std::string name = BufferedSocketNameRequest((Module*)Utils->Creator, this->Hook).Send(); - this->ServerInstance->SNO->WriteToSnoMask('l',"Connection from \2"+sname+"\2["+(x->HiddenFromStats ? "<hidden>" : this->GetIP())+"] using transport \2"+name+"\2"); + std::string name = BufferedSocketNameRequest(Utils->Creator, this->GetIOHook()).Send(); + ServerInstance->SNO->WriteToSnoMask('l',"Connection from \2"+sname+"\2["+(x->HiddenFromStats ? "<hidden>" : this->IP)+"] using transport \2"+name+"\2"); } // this is good. Send our details: Our server name and description and hopcount of 0, // along with the sendpass from this block. this->SendCapabilities(2); - this->WriteLine(std::string("SERVER ")+this->ServerInstance->Config->ServerName+" "+this->MakePass(x->SendPass, this->GetTheirChallenge())+" 0 "+ServerInstance->Config->GetSID()+" :"+this->ServerInstance->Config->ServerDesc); + this->WriteLine(std::string("SERVER ")+ServerInstance->Config->ServerName+" "+this->MakePass(x->SendPass, this->GetTheirChallenge())+" 0 "+ServerInstance->Config->GetSID()+" :"+ServerInstance->Config->ServerDesc); // move to the next state, we are now waiting for THEM. this->LinkState = WAIT_AUTH_2; return true; } this->SendError("Invalid credentials"); - this->ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, invalid link credentials"); + ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, invalid link credentials"); return false; } diff --git a/src/modules/m_spanningtree/stats.cpp b/src/modules/m_spanningtree/stats.cpp index d67c5a3af..71f12d50b 100644 --- a/src/modules/m_spanningtree/stats.cpp +++ b/src/modules/m_spanningtree/stats.cpp @@ -32,11 +32,11 @@ bool TreeSocket::Stats(const std::string &prefix, parameterlist ¶ms) */ if (params.size() > 1) { - if (InspIRCd::Match(this->ServerInstance->Config->ServerName, params[1])) + if (InspIRCd::Match(ServerInstance->Config->ServerName, params[1])) { /* It's for our server */ string_list results; - User* source = this->ServerInstance->FindNick(prefix); + User* source = ServerInstance->FindNick(prefix); if (source) { parameterlist par; @@ -46,14 +46,14 @@ bool TreeSocket::Stats(const std::string &prefix, parameterlist ¶ms) for (size_t i = 0; i < results.size(); i++) { par[1] = "::" + results[i]; - Utils->DoOneToOne(this->ServerInstance->Config->GetSID(), "PUSH",par, source->server); + Utils->DoOneToOne(ServerInstance->Config->GetSID(), "PUSH",par, source->server); } } } else { /* Pass it on */ - User* source = this->ServerInstance->FindNick(prefix); + User* source = ServerInstance->FindNick(prefix); if (source) Utils->DoOneToOne(source->uuid, "STATS", params, params[1]); } diff --git a/src/modules/m_spanningtree/svsjoin.cpp b/src/modules/m_spanningtree/svsjoin.cpp index b6246e2f4..1664190f8 100644 --- a/src/modules/m_spanningtree/svsjoin.cpp +++ b/src/modules/m_spanningtree/svsjoin.cpp @@ -29,13 +29,13 @@ bool TreeSocket::ServiceJoin(const std::string &prefix, parameterlist ¶ms) if (params.size() < 2) return true; - User* u = this->ServerInstance->FindNick(params[0]); + User* u = ServerInstance->FindNick(params[0]); if (u) { /* only join if it's local, otherwise just pass it on! */ if (IS_LOCAL(u)) - Channel::JoinUser(this->ServerInstance, u, params[1].c_str(), false, "", false, ServerInstance->Time()); + Channel::JoinUser(ServerInstance, u, params[1].c_str(), false, "", false, ServerInstance->Time()); Utils->DoOneToAllButSender(prefix,"SVSJOIN",params,prefix); } return true; diff --git a/src/modules/m_spanningtree/svsnick.cpp b/src/modules/m_spanningtree/svsnick.cpp index 3af6961d0..7a723a36d 100644 --- a/src/modules/m_spanningtree/svsnick.cpp +++ b/src/modules/m_spanningtree/svsnick.cpp @@ -32,7 +32,7 @@ bool TreeSocket::SVSNick(const std::string &prefix, parameterlist ¶ms) if (params.size() < 3) return true; - User* u = this->ServerInstance->FindNick(params[0]); + User* u = ServerInstance->FindNick(params[0]); if (u) { @@ -48,7 +48,7 @@ bool TreeSocket::SVSNick(const std::string &prefix, parameterlist ¶ms) /* buh. UID them */ if (!u->ForceNickChange(u->uuid.c_str())) { - this->ServerInstance->Users->QuitUser(u, "Nickname collision"); + ServerInstance->Users->QuitUser(u, "Nickname collision"); return true; } } diff --git a/src/modules/m_spanningtree/svspart.cpp b/src/modules/m_spanningtree/svspart.cpp index 83e329b4e..1e26c90d9 100644 --- a/src/modules/m_spanningtree/svspart.cpp +++ b/src/modules/m_spanningtree/svspart.cpp @@ -34,8 +34,8 @@ bool TreeSocket::ServicePart(const std::string &prefix, parameterlist ¶ms) if (params.size() == 3) reason = params[2]; - User* u = this->ServerInstance->FindNick(params[0]); - Channel* c = this->ServerInstance->FindChan(params[1]); + User* u = ServerInstance->FindNick(params[0]); + Channel* c = ServerInstance->FindChan(params[1]); if (u) { diff --git a/src/modules/m_spanningtree/time.cpp b/src/modules/m_spanningtree/time.cpp index 82a7fe62e..6fdcf8b53 100644 --- a/src/modules/m_spanningtree/time.cpp +++ b/src/modules/m_spanningtree/time.cpp @@ -31,20 +31,20 @@ bool TreeSocket::Time(const std::string &prefix, parameterlist ¶ms) if (params.size() == 2) { // someone querying our time? - if (this->ServerInstance->Config->ServerName == params[0] || this->ServerInstance->Config->GetSID() == params[0]) + if (ServerInstance->Config->ServerName == params[0] || ServerInstance->Config->GetSID() == params[0]) { - User* u = this->ServerInstance->FindNick(params[1]); + User* u = ServerInstance->FindNick(params[1]); if (u) { params.push_back(ConvToStr(ServerInstance->Time())); params[0] = prefix; - Utils->DoOneToOne(this->ServerInstance->Config->GetSID(),"TIME",params,params[0]); + Utils->DoOneToOne(ServerInstance->Config->GetSID(),"TIME",params,params[0]); } } else { // not us, pass it on - User* u = this->ServerInstance->FindNick(params[1]); + User* u = ServerInstance->FindNick(params[1]); if (u) Utils->DoOneToOne(prefix,"TIME",params,params[0]); } @@ -52,7 +52,7 @@ bool TreeSocket::Time(const std::string &prefix, parameterlist ¶ms) else if (params.size() == 3) { // a response to a previous TIME - User* u = this->ServerInstance->FindNick(params[1]); + User* u = ServerInstance->FindNick(params[1]); if ((u) && (IS_LOCAL(u))) { std::string sourceserv = Utils->FindServer(prefix)->GetName(); diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h index a26e89f85..3c9484981 100644 --- a/src/modules/m_spanningtree/treesocket.h +++ b/src/modules/m_spanningtree/treesocket.h @@ -71,7 +71,6 @@ class TreeSocket : public BufferedSocket { SpanningTreeUtilities* Utils; /* Utility class */ std::string myhost; /* Canonical hostname */ - std::string in_buffer; /* Input buffer */ ServerState LinkState; /* Link state */ std::string InboundServerName; /* Server name sent to us by other side */ std::string InboundDescription; /* Server description (GECOS) sent to us by the other side */ @@ -80,10 +79,10 @@ class TreeSocket : public BufferedSocket int num_lost_servers; /* Servers lost in split */ time_t NextPing; /* Time when we are due to ping this server */ bool LastPingWasGood; /* Responded to last ping we sent? */ + std::string IP; std::string ModuleList; /* Required module list of other server from CAPAB */ std::string OptModuleList; /* Optional module list of other server from CAPAB */ std::map<std::string,std::string> CapKeys; /* CAPAB keys from other server */ - Module* Hook; /* I/O hooking module that we're attached to for this socket */ std::string ourchallenge; /* Challenge sent for challenge/response */ std::string theirchallenge; /* Challenge recv for challenge/response */ std::string OutboundPass; /* Outbound password */ @@ -101,13 +100,13 @@ class TreeSocket : public BufferedSocket * most of the action, and append a few of our own values * to it. */ - TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, std::string host, int port, unsigned long maxtime, const std::string &ServerName, const std::string &bindto, Autoconnect* myac, Module* HookMod = NULL); + TreeSocket(SpanningTreeUtilities* Util, std::string host, int port, unsigned long maxtime, const std::string &ServerName, const std::string &bindto, Autoconnect* myac, Module* HookMod = NULL); /** When a listening socket gives us a new file descriptor, * we must associate it with a socket without creating a new * connection. This constructor is used for this purpose. */ - TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, int newfd, char* ip, Autoconnect* myac, Module* HookMod = NULL); + TreeSocket(SpanningTreeUtilities* Util, int newfd, char* ip, Autoconnect* myac, Module* HookMod = NULL); /** Get link state */ @@ -137,10 +136,6 @@ class TreeSocket : public BufferedSocket */ void CleanNegotiationInfo(); - /** Return the module which we are hooking to for I/O encapsulation - */ - Module* GetHook(); - /** Destructor */ ~TreeSocket(); @@ -160,7 +155,7 @@ class TreeSocket : public BufferedSocket * to server docs on the inspircd.org site, the other side * will then send back its own server string. */ - virtual bool OnConnected(); + virtual void OnConnected(); /** Handle socket error event */ @@ -171,10 +166,6 @@ class TreeSocket : public BufferedSocket */ void SendError(const std::string &errormessage); - /** Handle socket disconnect event - */ - virtual int OnDisconnect(); - /** Recursively send the server tree with distances as hops. * This is used during network burst to inform the other server * (and any of ITS servers too) of what servers we know about. @@ -258,14 +249,9 @@ class TreeSocket : public BufferedSocket void DoBurst(TreeServer* s); /** This function is called when we receive data from a remote - * server. We buffer the data in a std::string (it doesnt stay - * there for long), reading using BufferedSocket::Read() which can - * read up to 16 kilobytes in one operation. - * - * IF THIS FUNCTION RETURNS FALSE, THE CORE CLOSES AND DELETES - * THE SOCKET OBJECT FOR US. + * server. */ - virtual bool OnDataReady(); + void OnDataReady(); /** Send one or more complete lines down the socket */ @@ -404,10 +390,9 @@ class TreeSocket : public BufferedSocket /** Handle socket timeout from connect() */ virtual void OnTimeout(); - - /** Handle socket close event + /** Handle server quit on close */ - virtual void OnClose(); + virtual void Close(); }; /* Used to validate the value lengths of multiple parameters for a command */ diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp index d59364751..55fbc2c91 100644 --- a/src/modules/m_spanningtree/treesocket1.cpp +++ b/src/modules/m_spanningtree/treesocket1.cpp @@ -34,17 +34,18 @@ * most of the action, and append a few of our own values * to it. */ -TreeSocket::TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, std::string shost, int iport, unsigned long maxtime, const std::string &ServerName, const std::string &bindto, Autoconnect* myac, Module* HookMod) - : BufferedSocket(SI, shost, iport, maxtime, bindto), Utils(Util), Hook(HookMod), myautoconnect(myac) +TreeSocket::TreeSocket(SpanningTreeUtilities* Util, std::string shost, int iport, unsigned long maxtime, const std::string &ServerName, const std::string &bindto, Autoconnect* myac, Module* HookMod) + : Utils(Util), IP(shost), myautoconnect(myac) { - age = SI->Time(); + age = ServerInstance->Time(); myhost = ServerName; capab_phase = 0; proto_version = 0; LinkState = CONNECTING; + DoConnect(shost, iport, maxtime, bindto); Utils->timeoutlist[this] = std::pair<std::string, int>(ServerName, maxtime); - if (Hook) - BufferedSocketHookRequest(this, (Module*)Utils->Creator, Hook).Send(); + if (HookMod) + BufferedSocketHookRequest(this, Utils->Creator, HookMod).Send(); hstimer = NULL; } @@ -52,18 +53,18 @@ TreeSocket::TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, std::string sh * we must associate it with a socket without creating a new * connection. This constructor is used for this purpose. */ -TreeSocket::TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, int newfd, char* ip, Autoconnect* myac, Module* HookMod) - : BufferedSocket(SI, newfd, ip), Utils(Util), Hook(HookMod), myautoconnect(myac) +TreeSocket::TreeSocket(SpanningTreeUtilities* Util, int newfd, char* ip, Autoconnect* myac, Module* HookMod) + : BufferedSocket(newfd), Utils(Util), IP(ip), myautoconnect(myac) { - age = SI->Time(); + age = ServerInstance->Time(); LinkState = WAIT_AUTH_1; capab_phase = 0; proto_version = 0; /* If we have a transport module hooked to the parent, hook the same module to this * socket, and set a timer waiting for handshake before we send CAPAB etc. */ - if (Hook) - BufferedSocketHookRequest(this, (Module*)Utils->Creator, Hook).Send(); + if (HookMod) + BufferedSocketHookRequest(this, Utils->Creator, HookMod).Send(); hstimer = new HandshakeTimer(ServerInstance, this, &(Utils->LinkBlocks[0]), this->Utils, 1); ServerInstance->Timers->AddTimer(hstimer); @@ -77,11 +78,6 @@ ServerState TreeSocket::GetLinkState() return this->LinkState; } -Module* TreeSocket::GetHook() -{ - return this->Hook; -} - void TreeSocket::CleanNegotiationInfo() { ModuleList.clear(); @@ -94,8 +90,8 @@ void TreeSocket::CleanNegotiationInfo() TreeSocket::~TreeSocket() { - if (Hook) - BufferedSocketUnhookRequest(this, (Module*)Utils->Creator, Hook).Send(); + if (GetIOHook()) + BufferedSocketUnhookRequest(this, Utils->Creator, GetIOHook()).Send(); if (hstimer) ServerInstance->Timers->DelTimer(hstimer); Utils->timeoutlist.erase(this); @@ -107,7 +103,7 @@ TreeSocket::~TreeSocket() * to server docs on the inspircd.org site, the other side * will then send back its own server string. */ -bool TreeSocket::OnConnected() +void TreeSocket::OnConnected() { if (this->LinkState == CONNECTING) { @@ -116,25 +112,17 @@ bool TreeSocket::OnConnected() { if (x->Name == this->myhost) { - ServerInstance->SNO->WriteToSnoMask('l', "Connection to \2%s\2[%s] started.", myhost.c_str(), (x->HiddenFromStats ? "<hidden>" : this->GetIP().c_str())); - if (Hook) - { - BufferedSocketHookRequest(this, (Module*)Utils->Creator, Hook).Send(); - ServerInstance->SNO->WriteToSnoMask('l', "Connection to \2%s\2[%s] using transport \2%s\2", myhost.c_str(), (x->HiddenFromStats ? "<hidden>" : this->GetIP().c_str()), - x->Hook.c_str()); - } + ServerInstance->SNO->WriteToSnoMask('l', "Connection to \2%s\2[%s] started.", myhost.c_str(), (x->HiddenFromStats ? "<hidden>" : this->IP.c_str())); this->OutboundPass = x->SendPass; - - /* found who we're supposed to be connecting to, send the neccessary gubbins. */ - if (this->GetHook()) + if (GetIOHook()) { + ServerInstance->SNO->WriteToSnoMask('l', "Connection to \2%s\2[%s] using transport \2%s\2", myhost.c_str(), (x->HiddenFromStats ? "<hidden>" : this->IP.c_str()), x->Hook.c_str()); hstimer = new HandshakeTimer(ServerInstance, this, &(*x), this->Utils, 1); ServerInstance->Timers->AddTimer(hstimer); } else this->SendCapabilities(1); - - return true; + return; } } } @@ -144,7 +132,6 @@ bool TreeSocket::OnConnected() * and rather harmless. */ ServerInstance->SNO->WriteToSnoMask('l', "Connection to \2%s\2 lost link tag(!)", myhost.c_str()); - return true; } void TreeSocket::OnError(BufferedSocketError e) @@ -174,21 +161,11 @@ void TreeSocket::OnError(BufferedSocketError e) } } -int TreeSocket::OnDisconnect() -{ - /* For the same reason as above, we don't - * handle OnDisconnect() - */ - return true; -} - void TreeSocket::SendError(const std::string &errormessage) { /* Display the error locally as well as sending it remotely */ - ServerInstance->SNO->WriteToSnoMask('l', "Sent \2ERROR\2 to %s: %s", (this->InboundServerName.empty() ? this->GetIP().c_str() : this->InboundServerName.c_str()), errormessage.c_str()); - this->WriteLine("ERROR :"+errormessage); - /* One last attempt to make sure the error reaches its target */ - this->FlushWriteBuffer(); + ServerInstance->SNO->WriteToSnoMask('l', "Sent \2ERROR\2 to %s: %s", (this->InboundServerName.empty() ? this->IP.c_str() : this->InboundServerName.c_str()), errormessage.c_str()); + WriteLine("ERROR :"+errormessage); } /** This function forces this server to quit, removing this server @@ -232,12 +209,12 @@ void TreeSocket::Squit(TreeServer* Current, const std::string &reason) Utils->DoOneToAllButSender(Current->GetParent()->GetName(),"SQUIT",params,Current->GetName()); if (Current->GetParent() == Utils->TreeRoot) { - this->ServerInstance->SNO->WriteToSnoMask('l', "Server \002"+Current->GetName()+"\002 split: "+reason); + ServerInstance->SNO->WriteToSnoMask('l', "Server \002"+Current->GetName()+"\002 split: "+reason); LocalSquit = true; } else { - this->ServerInstance->SNO->WriteToSnoMask('L', "Server \002"+Current->GetName()+"\002 split from server \002"+Current->GetParent()->GetName()+"\002 with reason: "+reason); + ServerInstance->SNO->WriteToSnoMask('L', "Server \002"+Current->GetName()+"\002 split from server \002"+Current->GetParent()->GetName()+"\002 with reason: "+reason); } num_lost_servers = 0; num_lost_users = 0; @@ -247,56 +224,41 @@ void TreeSocket::Squit(TreeServer* Current, const std::string &reason) Current->GetParent()->DelChild(Current); delete Current; if (LocalSquit) - this->ServerInstance->SNO->WriteToSnoMask('l', "Netsplit complete, lost \002%d\002 users on \002%d\002 servers.", num_lost_users, num_lost_servers); + ServerInstance->SNO->WriteToSnoMask('l', "Netsplit complete, lost \002%d\002 users on \002%d\002 servers.", num_lost_users, num_lost_servers); else - this->ServerInstance->SNO->WriteToSnoMask('L', "Netsplit complete, lost \002%d\002 users on \002%d\002 servers.", num_lost_users, num_lost_servers); + ServerInstance->SNO->WriteToSnoMask('L', "Netsplit complete, lost \002%d\002 users on \002%d\002 servers.", num_lost_users, num_lost_servers); } else ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Squit from unknown server"); } /** This function is called when we receive data from a remote - * server. We buffer the data in a std::string (it doesnt stay - * there for long), reading using BufferedSocket::Read() which can - * read up to 16 kilobytes in one operation. - * - * IF THIS FUNCTION RETURNS FALSE, THE CORE CLOSES AND DELETES - * THE SOCKET OBJECT FOR US. + * server. */ -bool TreeSocket::OnDataReady() +void TreeSocket::OnDataReady() { - const char* data = this->Read(); - /* Check that the data read is a valid pointer and it has some content */ - if (data && *data) + Utils->Creator->loopCall = true; + /* While there is at least one new line in the buffer, + * do something useful (we hope!) with it. + */ + while (recvq.find("\n") != std::string::npos) { - this->in_buffer.append(data); - Utils->Creator->loopCall = true; - /* While there is at least one new line in the buffer, - * do something useful (we hope!) with it. + std::string ret = recvq.substr(0,recvq.find("\n")-1); + recvq = recvq.substr(recvq.find("\n")+1,recvq.length()-recvq.find("\n")); + /* Use rfind here not find, as theres more + * chance of the \r being near the end of the + * string, not the start. */ - while (in_buffer.find("\n") != std::string::npos) + if (ret.find("\r") != std::string::npos) + ret = recvq.substr(0,recvq.find("\r")-1); + /* Process this one, abort if it + * didnt return true. + */ + if (!this->ProcessLine(ret)) { - std::string ret = in_buffer.substr(0,in_buffer.find("\n")-1); - in_buffer = in_buffer.substr(in_buffer.find("\n")+1,in_buffer.length()-in_buffer.find("\n")); - /* Use rfind here not find, as theres more - * chance of the \r being near the end of the - * string, not the start. - */ - if (ret.find("\r") != std::string::npos) - ret = in_buffer.substr(0,in_buffer.find("\r")-1); - /* Process this one, abort if it - * didnt return true. - */ - if (!this->ProcessLine(ret)) - { - return false; - } + SetError("ProcessLine returned false"); + break; } - Utils->Creator->loopCall = false; - return true; } - /* EAGAIN returns an empty but non-NULL string, so this - * evaluates to TRUE for EAGAIN but to FALSE for EOF. - */ - return (data && !*data); + Utils->Creator->loopCall = false; } diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp index 793802781..cf537f05b 100644 --- a/src/modules/m_spanningtree/treesocket2.cpp +++ b/src/modules/m_spanningtree/treesocket2.cpp @@ -32,7 +32,7 @@ bool TreeSocket::Error(parameterlist ¶ms) { if (params.size() < 1) return false; - this->ServerInstance->SNO->WriteToSnoMask('l',"ERROR from %s: %s",(!InboundServerName.empty() ? InboundServerName.c_str() : myhost.c_str()),params[0].c_str()); + ServerInstance->SNO->WriteToSnoMask('l',"ERROR from %s: %s",(!InboundServerName.empty() ? InboundServerName.c_str() : myhost.c_str()),params[0].c_str()); /* we will return false to cause the socket to close. */ return false; } @@ -126,9 +126,7 @@ bool TreeSocket::ProcessLine(std::string &line) } else { - // XXX ...wtf. - irc::string error = "Invalid command in negotiation phase: " + command; - this->SendError(assign(error)); + this->SendError(std::string("Invalid command in negotiation phase: ") + command.c_str()); return false; } break; @@ -171,7 +169,7 @@ bool TreeSocket::ProcessLine(std::string &line) Link* lnk = Utils->FindLink(InboundServerName); - Node = new TreeServer(this->Utils, this->ServerInstance, InboundServerName, InboundDescription, InboundSID, Utils->TreeRoot, this, lnk ? lnk->Hidden : false); + Node = new TreeServer(this->Utils, ServerInstance, InboundServerName, InboundDescription, InboundSID, Utils->TreeRoot, this, lnk ? lnk->Hidden : false); Utils->TreeRoot->AddChild(Node); parameterlist sparams; @@ -242,7 +240,7 @@ bool TreeSocket::ProcessLine(std::string &line) */ std::string direction = prefix; - User *t = this->ServerInstance->FindUUID(prefix); + User *t = ServerInstance->FindUUID(prefix); if (t) { /* Find UID */ @@ -316,7 +314,7 @@ bool TreeSocket::ProcessLine(std::string &line) } else if ((command == "NOTICE" || command == "PRIVMSG") && (Utils->IsServer(prefix))) { - return this->ServerMessage(assign(command), prefix, params, sourceserv); + return ServerMessage(assign(command), prefix, params, sourceserv); } else if (command == "STATS") { @@ -487,7 +485,7 @@ bool TreeSocket::ProcessLine(std::string &line) // Set prefix server as bursting if (!ServerSource) { - this->ServerInstance->SNO->WriteToSnoMask('l', "WTF: Got BURST from a nonexistant server(?): %s", (ServerSource ? ServerSource->GetName().c_str() : prefix.c_str())); + ServerInstance->SNO->WriteToSnoMask('l', "WTF: Got BURST from a nonexistant server(?): %s", (ServerSource ? ServerSource->GetName().c_str() : prefix.c_str())); return false; } @@ -498,7 +496,7 @@ bool TreeSocket::ProcessLine(std::string &line) { if (!ServerSource) { - this->ServerInstance->SNO->WriteToSnoMask('l', "WTF: Got ENDBURST from a nonexistant server(?): %s", (ServerSource ? ServerSource->GetName().c_str() : prefix.c_str())); + ServerInstance->SNO->WriteToSnoMask('l', "WTF: Got ENDBURST from a nonexistant server(?): %s", (ServerSource ? ServerSource->GetName().c_str() : prefix.c_str())); return false; } @@ -515,7 +513,7 @@ bool TreeSocket::ProcessLine(std::string &line) * Not a special s2s command. Emulate the user doing it. * This saves us having a huge ugly command parser again. */ - User* who = this->ServerInstance->FindUUID(prefix); + User* who = ServerInstance->FindUUID(prefix); if (ServerSource) { @@ -546,7 +544,7 @@ bool TreeSocket::ProcessLine(std::string &line) * On nick messages, check that the nick doesnt already exist here. * If it does, perform collision logic. */ - User* x = this->ServerInstance->FindNickOnly(params[0]); + User* x = ServerInstance->FindNickOnly(params[0]); if ((x) && (x != who)) { int collideret = 0; @@ -564,7 +562,7 @@ bool TreeSocket::ProcessLine(std::string &line) } } - switch (this->ServerInstance->CallCommandHandler(command.c_str(), params, who)) + switch (ServerInstance->CallCommandHandler(command.c_str(), params, who)) { case CMD_INVALID: /* @@ -607,13 +605,15 @@ void TreeSocket::OnTimeout() { if (this->LinkState == CONNECTING) { - this->ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Connection to \002%s\002 timed out.", myhost.c_str()); + ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Connection to \002%s\002 timed out.", myhost.c_str()); Utils->DoFailOver(myautoconnect); } } -void TreeSocket::OnClose() +void TreeSocket::Close() { + this->BufferedSocket::Close(); + // Test fix for big fuckup if (this->LinkState != CONNECTED) return; @@ -634,10 +634,10 @@ void TreeSocket::OnClose() if (!quitserver.empty()) { - this->ServerInstance->SNO->WriteToSnoMask('l', "Connection to '\2%s\2' failed.",quitserver.c_str()); + ServerInstance->SNO->WriteToSnoMask('l', "Connection to '\2%s\2' failed.",quitserver.c_str()); time_t server_uptime = ServerInstance->Time() - this->age; if (server_uptime) - this->ServerInstance->SNO->WriteToSnoMask('l', "Connection to '\2%s\2' was established for %s", quitserver.c_str(), Utils->Creator->TimeToStr(server_uptime).c_str()); + ServerInstance->SNO->WriteToSnoMask('l', "Connection to '\2%s\2' was established for %s", quitserver.c_str(), Utils->Creator->TimeToStr(server_uptime).c_str()); } } diff --git a/src/modules/m_spanningtree/uid.cpp b/src/modules/m_spanningtree/uid.cpp index b7c13b5f8..0f0e75a1d 100644 --- a/src/modules/m_spanningtree/uid.cpp +++ b/src/modules/m_spanningtree/uid.cpp @@ -64,9 +64,9 @@ bool TreeSocket::ParseUID(const std::string &source, parameterlist ¶ms) } /* check for collision */ - user_hash::iterator iter = this->ServerInstance->Users->clientlist->find(params[2]); + user_hash::iterator iter = ServerInstance->Users->clientlist->find(params[2]); - if (iter != this->ServerInstance->Users->clientlist->end()) + if (iter != ServerInstance->Users->clientlist->end()) { /* * Nick collision. @@ -87,19 +87,19 @@ bool TreeSocket::ParseUID(const std::string &source, parameterlist ¶ms) User* _new = NULL; try { - _new = new User(this->ServerInstance, params[0]); + _new = new User(ServerInstance, params[0]); } catch (...) { this->SendError("Protocol violation - Duplicate UUID '" + params[0] + "' on introduction of new user"); return false; } - (*(this->ServerInstance->Users->clientlist))[params[2]] = _new; + (*(ServerInstance->Users->clientlist))[params[2]] = _new; _new->SetFd(FD_MAGIC_NUMBER); _new->nick.assign(params[2], 0, MAXBUF); _new->host.assign(params[3], 0, 64); _new->dhost.assign(params[4], 0, 64); - _new->server = this->ServerInstance->FindServerNamePtr(remoteserver->GetName().c_str()); + _new->server = ServerInstance->FindServerNamePtr(remoteserver->GetName().c_str()); _new->ident.assign(params[5], 0, MAXBUF); _new->fullname.assign(params[params.size() - 1], 0, MAXBUF); _new->registered = REG_ALL; @@ -164,11 +164,11 @@ bool TreeSocket::ParseUID(const std::string &source, parameterlist ¶ms) bool dosend = true; - if ((this->Utils->quiet_bursts && remoteserver->bursting) || this->ServerInstance->SilentULine(_new->server)) + if ((this->Utils->quiet_bursts && remoteserver->bursting) || ServerInstance->SilentULine(_new->server)) dosend = false; if (dosend) - this->ServerInstance->SNO->WriteToSnoMask('C',"Client connecting at %s: %s!%s@%s [%s] [%s]", _new->server, _new->nick.c_str(), _new->ident.c_str(), _new->host.c_str(), _new->GetIPString(), _new->fullname.c_str()); + ServerInstance->SNO->WriteToSnoMask('C',"Client connecting at %s: %s!%s@%s [%s] [%s]", _new->server, _new->nick.c_str(), _new->ident.c_str(), _new->host.c_str(), _new->GetIPString(), _new->fullname.c_str()); params[params.size() - 1] = ":" + params[params.size() - 1]; Utils->DoOneToAllButSender(source, "UID", params, source); diff --git a/src/modules/m_spanningtree/utils.cpp b/src/modules/m_spanningtree/utils.cpp index b37aecc4b..8d3c55758 100644 --- a/src/modules/m_spanningtree/utils.cpp +++ b/src/modules/m_spanningtree/utils.cpp @@ -49,19 +49,18 @@ void ServerSocketListener::OnAcceptReady(int newsock) if (!found) { - this->ServerInstance->SNO->WriteToSnoMask('l', "Server connection from %s denied (no link blocks with that IP address)", ip); + ServerInstance->SNO->WriteToSnoMask('l', "Server connection from %s denied (no link blocks with that IP address)", ip); ServerInstance->SE->Close(newsock); return; } } - if (this->GetIOHook()) - { - this->GetIOHook()->OnRawSocketAccept(newsock, &client, &server); - } + /* we don't need to do anything with the pointer, creating it stores it in the necessary places */ + TreeSocket* ts = new TreeSocket(Utils, newsock, ip, NULL, Hook); + + if (Hook) + Hook->OnStreamSocketAccept(ts, &client, &server); - /* we don't need a pointer to this, creating it stores it in the necessary places */ - new TreeSocket(this->Utils, this->ServerInstance, newsock, ip, NULL, this->GetIOHook()); return; } @@ -73,7 +72,7 @@ void ServerSocketListener::OnAcceptReady(int newsock) */ TreeServer* SpanningTreeUtilities::FindServer(const std::string &ServerName) { - if (this->ServerInstance->IsSID(ServerName)) + if (ServerInstance->IsSID(ServerName)) return this->FindServerID(ServerName); server_hash::iterator iter = serverlist.find(ServerName.c_str()); @@ -150,12 +149,10 @@ bool SpanningTreeUtilities::IsServer(const std::string &ServerName) SpanningTreeUtilities::SpanningTreeUtilities(InspIRCd* Instance, ModuleSpanningTree* C) : ServerInstance(Instance), Creator(C) { - Bindings.clear(); - ServerInstance->Logs->Log("m_spanningtree",DEBUG,"***** Using SID for hash: %s *****", ServerInstance->Config->GetSID().c_str()); this->TreeRoot = new TreeServer(this, ServerInstance, ServerInstance->Config->ServerName, ServerInstance->Config->ServerDesc, ServerInstance->Config->GetSID()); - this->ServerUser = new FakeUser(ServerInstance, TreeRoot->GetID()); + ServerUser = new FakeUser(ServerInstance, TreeRoot->GetID()); this->ReadConfiguration(true); } @@ -182,7 +179,6 @@ SpanningTreeUtilities::~SpanningTreeUtilities() ServerUser->uuid = TreeRoot->GetID(); delete TreeRoot; delete ServerUser; - ServerInstance->BufferedSocketCull(); } void SpanningTreeUtilities::AddThisServer(TreeServer* server, TreeServerList &list) @@ -465,7 +461,6 @@ void SpanningTreeUtilities::ReadConfiguration(bool rebind) { delete Bindings[i]; } - ServerInstance->BufferedSocketCull(); Bindings.clear(); for (int j = 0; j < Conf->Enumerate("bind"); j++) @@ -498,7 +493,7 @@ void SpanningTreeUtilities::ReadConfiguration(bool rebind) } if (!transport.empty()) - listener->AddIOHook(hooks[transport.c_str()]); + listener->Hook = hooks[transport.c_str()]; Bindings.push_back(listener); } @@ -656,7 +651,7 @@ void SpanningTreeUtilities::DoFailOver(Autoconnect* x) { if (x->FailOver == x->Server) { - this->ServerInstance->SNO->WriteToSnoMask('l', "FAILOVER: Some muppet configured the failover for server \002%s\002 to point at itself. Not following it!", x->Server.c_str()); + ServerInstance->SNO->WriteToSnoMask('l', "FAILOVER: Some muppet configured the failover for server \002%s\002 to point at itself. Not following it!", x->Server.c_str()); return; } Link* TryThisOne = this->FindLink(x->FailOver.c_str()); @@ -669,13 +664,13 @@ void SpanningTreeUtilities::DoFailOver(Autoconnect* x) } else { - this->ServerInstance->SNO->WriteToSnoMask('l', "FAILOVER: Trying failover link for \002%s\002: \002%s\002...", x->Server.c_str(), TryThisOne->Name.c_str()); + ServerInstance->SNO->WriteToSnoMask('l', "FAILOVER: Trying failover link for \002%s\002: \002%s\002...", x->Server.c_str(), TryThisOne->Name.c_str()); Creator->ConnectServer(TryThisOne, NULL); } } else { - this->ServerInstance->SNO->WriteToSnoMask('l', "FAILOVER: Invalid failover server specified for server \002%s\002, will not follow!", x->Server.c_str()); + ServerInstance->SNO->WriteToSnoMask('l', "FAILOVER: Invalid failover server specified for server \002%s\002, will not follow!", x->Server.c_str()); } } } diff --git a/src/modules/m_spanningtree/utils.h b/src/modules/m_spanningtree/utils.h index 09c707131..1bdf127d8 100644 --- a/src/modules/m_spanningtree/utils.h +++ b/src/modules/m_spanningtree/utils.h @@ -47,8 +47,11 @@ class ServerSocketListener : public ListenSocketBase ServerSocketListener(InspIRCd* Instance, SpanningTreeUtilities *u, int port, char* addr) : ListenSocketBase(Instance, port, addr) { this->Utils = u; + Hook = NULL; } + Module* Hook; + virtual void OnAcceptReady(int nfd); }; diff --git a/src/modules/m_spanningtree/whois.cpp b/src/modules/m_spanningtree/whois.cpp index f12a7f109..79e2d7355 100644 --- a/src/modules/m_spanningtree/whois.cpp +++ b/src/modules/m_spanningtree/whois.cpp @@ -28,13 +28,13 @@ bool TreeSocket::Whois(const std::string &prefix, parameterlist ¶ms) { if (params.size() < 1) return true; - User* u = this->ServerInstance->FindNick(prefix); + User* u = ServerInstance->FindNick(prefix); if (u) { // an incoming request if (params.size() == 1) { - User* x = this->ServerInstance->FindNick(params[0]); + User* x = ServerInstance->FindNick(params[0]); if ((x) && (IS_LOCAL(x))) { char signon[MAXBUF]; @@ -58,7 +58,7 @@ bool TreeSocket::Whois(const std::string &prefix, parameterlist ¶ms) else if (params.size() == 3) { std::string who_did_the_whois = params[0]; - User* who_to_send_to = this->ServerInstance->FindNick(who_did_the_whois); + User* who_to_send_to = ServerInstance->FindNick(who_did_the_whois); if ((who_to_send_to) && (IS_LOCAL(who_to_send_to))) { // an incoming reply to a whois we sent out diff --git a/src/socket.cpp b/src/socket.cpp index ccae48a6d..cc9cb79b9 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -273,7 +273,7 @@ std::string irc::sockets::satouser(const irc::sockets::sockaddrs* sa) { return std::string(buffer); } -int irc::sockets::sa_size(irc::sockets::sockaddrs& sa) +int irc::sockets::sa_size(const irc::sockets::sockaddrs& sa) { if (sa.sa.sa_family == AF_INET) return sizeof(sa.in4); diff --git a/src/socketengine.cpp b/src/socketengine.cpp index af2f1b169..c0ae3f278 100644 --- a/src/socketengine.cpp +++ b/src/socketengine.cpp @@ -43,35 +43,7 @@ EventHandler::EventHandler() { - this->IOHook = NULL; -} - -bool EventHandler::AddIOHook(Module *IOHooker) -{ - if (this->IOHook) - return false; - - this->IOHook = IOHooker; - return true; -} - -bool EventHandler::DelIOHook() -{ - if (!this->IOHook) - return false; - - this->IOHook = NULL; - return true; -} - -Module *EventHandler::GetIOHook() -{ - return this->IOHook; -} - -int EventHandler::GetFd() -{ - return this->fd; + fd = -1; } void EventHandler::SetFd(int FD) @@ -79,21 +51,7 @@ void EventHandler::SetFd(int FD) this->fd = FD; } -bool EventHandler::Readable() -{ - return true; -} - -bool EventHandler::Writeable() -{ - return false; -} - -void SocketEngine::WantWrite(EventHandler* eh) -{ -} - -SocketEngine::SocketEngine(InspIRCd* Instance) : ServerInstance(Instance) +SocketEngine::SocketEngine() { TotalEvents = WriteEvents = ReadEvents = ErrorEvents = 0; lastempty = ServerInstance->Time(); @@ -104,11 +62,6 @@ SocketEngine::~SocketEngine() { } -bool SocketEngine::AddFd(EventHandler* eh) -{ - return true; -} - bool SocketEngine::HasFd(int fd) { if ((fd < 0) || (fd > MAX_DESCRIPTORS)) @@ -123,11 +76,6 @@ EventHandler* SocketEngine::GetRef(int fd) return ref[fd]; } -bool SocketEngine::DelFd(EventHandler* eh, bool force) -{ - return true; -} - int SocketEngine::GetMaxFds() { return 0; @@ -143,11 +91,6 @@ int SocketEngine::DispatchEvents() return 0; } -std::string SocketEngine::GetName() -{ - return "misconfigured"; -} - bool SocketEngine::BoundsCheckFd(EventHandler* eh) { if (!eh) diff --git a/src/socketengines/socketengine_epoll.cpp b/src/socketengines/socketengine_epoll.cpp index 1be0d7cd2..7fed6f250 100644 --- a/src/socketengines/socketengine_epoll.cpp +++ b/src/socketengines/socketengine_epoll.cpp @@ -16,7 +16,7 @@ #include "socketengines/socketengine_epoll.h" #include <ulimit.h> -EPollEngine::EPollEngine(InspIRCd* Instance) : SocketEngine(Instance) +EPollEngine::EPollEngine() { MAX_DESCRIPTORS = 0; // This is not a maximum, just a hint at the eventual number of sockets that may be polled. @@ -45,7 +45,7 @@ EPollEngine::~EPollEngine() delete[] events; } -bool EPollEngine::AddFd(EventHandler* eh) +bool EPollEngine::AddFd(EventHandler* eh, bool writeFirst) { int fd = eh->GetFd(); if ((fd < 0) || (fd > GetMaxFds() - 1)) @@ -68,7 +68,7 @@ bool EPollEngine::AddFd(EventHandler* eh) struct epoll_event ev; memset(&ev,0,sizeof(ev)); - eh->Readable() ? ev.events = EPOLLIN : ev.events = EPOLLOUT; + ev.events = writeFirst ? EPOLLOUT : EPOLLIN; ev.data.fd = fd; int i = epoll_ctl(EngineHandle, EPOLL_CTL_ADD, fd, &ev); if (i < 0) @@ -107,7 +107,6 @@ bool EPollEngine::DelFd(EventHandler* eh, bool force) struct epoll_event ev; memset(&ev,0,sizeof(ev)); - eh->Readable() ? ev.events = EPOLLIN : ev.events = EPOLLOUT; ev.data.fd = fd; int i = epoll_ctl(EngineHandle, EPOLL_CTL_DEL, fd, &ev); diff --git a/src/socketengines/socketengine_iocp.cpp b/src/socketengines/socketengine_iocp.cpp index ee2e5afa1..3c3181909 100644 --- a/src/socketengines/socketengine_iocp.cpp +++ b/src/socketengines/socketengine_iocp.cpp @@ -15,7 +15,7 @@ #include "exitcodes.h" #include <mswsock.h> -IOCPEngine::IOCPEngine(InspIRCd * Instance) : SocketEngine(Instance) +IOCPEngine::IOCPEngine() { MAX_DESCRIPTORS = 10240; @@ -47,7 +47,7 @@ IOCPEngine::~IOCPEngine() delete[] ref; } -bool IOCPEngine::AddFd(EventHandler* eh) +bool IOCPEngine::AddFd(EventHandler* eh, bool writeFirst) { /* Does it at least look valid? */ if (!eh) @@ -92,7 +92,7 @@ bool IOCPEngine::AddFd(EventHandler* eh) ServerInstance->Logs->Log("SOCKET",DEBUG, "New fake fd: %u, real fd: %u, address 0x%p", *fake_fd, eh->GetFd(), eh); /* post a write event if there is data to be written */ - if(eh->Writeable()) + if(writeFirst) WantWrite(eh); /* we're all good =) */ diff --git a/src/socketengines/socketengine_kqueue.cpp b/src/socketengines/socketengine_kqueue.cpp index bf09eaf74..cbe3e959d 100644 --- a/src/socketengines/socketengine_kqueue.cpp +++ b/src/socketengines/socketengine_kqueue.cpp @@ -19,7 +19,7 @@ #include "socketengines/socketengine_kqueue.h" #include <sys/sysctl.h> -KQueueEngine::KQueueEngine(InspIRCd* Instance) : SocketEngine(Instance) +KQueueEngine::KQueueEngine() { MAX_DESCRIPTORS = 0; this->RecoverFromFork(); @@ -54,7 +54,7 @@ KQueueEngine::~KQueueEngine() delete[] ke_list; } -bool KQueueEngine::AddFd(EventHandler* eh) +bool KQueueEngine::AddFd(EventHandler* eh, bool writeFirst) { int fd = eh->GetFd(); @@ -79,7 +79,7 @@ bool KQueueEngine::AddFd(EventHandler* eh) return false; } - if (!eh->Readable()) { + if (writeFirst) { // ...and sometimes want to write WantWrite(eh); } diff --git a/src/socketengines/socketengine_poll.cpp b/src/socketengines/socketengine_poll.cpp index cee6a90cb..6d5ddb9f5 100644 --- a/src/socketengines/socketengine_poll.cpp +++ b/src/socketengines/socketengine_poll.cpp @@ -19,7 +19,7 @@ #include <sys/sysctl.h> #endif -PollEngine::PollEngine(InspIRCd* Instance) : SocketEngine(Instance) +PollEngine::PollEngine() { // Poll requires no special setup (which is nice). CurrentSetSize = 0; @@ -39,7 +39,7 @@ PollEngine::~PollEngine() delete[] events; } -bool PollEngine::AddFd(EventHandler* eh) +bool PollEngine::AddFd(EventHandler* eh, bool writeFirst) { int fd = eh->GetFd(); if ((fd < 0) || (fd > GetMaxFds() - 1)) @@ -65,13 +65,13 @@ bool PollEngine::AddFd(EventHandler* eh) fd_mappings[fd] = index; ref[index] = eh; events[index].fd = fd; - if (eh->Readable()) + if (writeFirst) { - events[index].events = POLLIN; + events[index].events = POLLOUT; } else { - events[index].events = POLLOUT; + events[index].events = POLLIN; } ServerInstance->Logs->Log("SOCKET", DEBUG,"New file descriptor: %d (%d; index %d)", fd, events[fd].events, index); diff --git a/src/socketengines/socketengine_ports.cpp b/src/socketengines/socketengine_ports.cpp index 5efa545b0..eb08839d0 100644 --- a/src/socketengines/socketengine_ports.cpp +++ b/src/socketengines/socketengine_ports.cpp @@ -17,7 +17,7 @@ #include "socketengines/socketengine_ports.h" #include <ulimit.h> -PortsEngine::PortsEngine(InspIRCd* Instance) : SocketEngine(Instance) +PortsEngine::PortsEngine() { MAX_DESCRIPTORS = 0; EngineHandle = port_create(); @@ -44,7 +44,7 @@ PortsEngine::~PortsEngine() delete[] events; } -bool PortsEngine::AddFd(EventHandler* eh) +bool PortsEngine::AddFd(EventHandler* eh, bool writeFirst) { int fd = eh->GetFd(); if ((fd < 0) || (fd > GetMaxFds() - 1)) @@ -57,7 +57,7 @@ bool PortsEngine::AddFd(EventHandler* eh) return false; ref[fd] = eh; - port_associate(EngineHandle, PORT_SOURCE_FD, fd, eh->Readable() ? POLLRDNORM : POLLWRNORM, eh); + port_associate(EngineHandle, PORT_SOURCE_FD, fd, writeFirst ? POLLWRNORM : POLLRDNORM, eh); ServerInstance->Logs->Log("SOCKET",DEBUG,"New file descriptor: %d", fd); CurrentSetSize++; diff --git a/src/socketengines/socketengine_select.cpp b/src/socketengines/socketengine_select.cpp index 8c41df11b..7f6a4e283 100644 --- a/src/socketengines/socketengine_select.cpp +++ b/src/socketengines/socketengine_select.cpp @@ -18,7 +18,7 @@ #include "socketengines/socketengine_select.h" -SelectEngine::SelectEngine(InspIRCd* Instance) : SocketEngine(Instance) +SelectEngine::SelectEngine() { MAX_DESCRIPTORS = FD_SETSIZE; EngineHandle = 0; @@ -34,7 +34,7 @@ SelectEngine::~SelectEngine() delete[] ref; } -bool SelectEngine::AddFd(EventHandler* eh) +bool SelectEngine::AddFd(EventHandler* eh, bool writeFirst) { int fd = eh->GetFd(); if ((fd < 0) || (fd > GetMaxFds() - 1)) @@ -50,6 +50,8 @@ bool SelectEngine::AddFd(EventHandler* eh) ref[fd] = eh; CurrentSetSize++; + writeable[eh->GetFd()] = writeFirst; + ServerInstance->Logs->Log("SOCKET",DEBUG,"New file descriptor: %d", fd); return true; } @@ -101,16 +103,11 @@ int SelectEngine::DispatchEvents() /* Populate the select FD set (this is why select sucks compared to epoll, kqueue, IOCP) */ for (std::set<int>::iterator a = fds.begin(); a != fds.end(); a++) { - if (ref[*a]->Readable()) - /* Read notifications */ - FD_SET (*a, &rfdset); - else - /* Write notifications */ - FD_SET (*a, &wfdset); - /* Explicitly one-time writeable */ if (writeable[*a]) FD_SET (*a, &wfdset); + else + FD_SET (*a, &rfdset); /* All sockets must receive error notifications regardless */ FD_SET (*a, &errfdset); diff --git a/src/stats.cpp b/src/stats.cpp index 40ee40b18..02cfeaa7c 100644 --- a/src/stats.cpp +++ b/src/stats.cpp @@ -254,7 +254,7 @@ void InspIRCd::DoStats(char statschar, User* user, string_list &results) for (std::vector<User*>::iterator n = this->Users->local_users.begin(); n != this->Users->local_users.end(); n++) { User* i = *n; - results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->dhost+"] "+ConvToStr(i->sendq.length())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(this->Time() - i->age)); + results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->dhost+"] "+ConvToStr(i->getSendQSize())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(this->Time() - i->age)); } break; @@ -264,7 +264,7 @@ void InspIRCd::DoStats(char statschar, User* user, string_list &results) for (std::vector<User*>::iterator n = this->Users->local_users.begin(); n != this->Users->local_users.end(); n++) { User* i = *n; - results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->GetIPString()+"] "+ConvToStr(i->sendq.length())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(this->Time() - i->age)); + results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->GetIPString()+"] "+ConvToStr(i->getSendQSize())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(this->Time() - i->age)); } break; diff --git a/src/threadengines/threadengine_pthread.cpp b/src/threadengines/threadengine_pthread.cpp index 6e32634c5..a4a47f8fa 100644 --- a/src/threadengines/threadengine_pthread.cpp +++ b/src/threadengines/threadengine_pthread.cpp @@ -65,8 +65,7 @@ class ThreadSignalSocket : public BufferedSocket { SocketThread* parent; public: - ThreadSignalSocket(SocketThread* p, InspIRCd* SI, int newfd) : - BufferedSocket(SI, newfd, const_cast<char*>("0.0.0.0")), parent(p) {} + ThreadSignalSocket(SocketThread* p, int newfd) : BufferedSocket(newfd), parent(p) {} ~ThreadSignalSocket() { @@ -77,13 +76,14 @@ class ThreadSignalSocket : public BufferedSocket eventfd_write(fd, 1); } - virtual bool OnDataReady() + void OnDataReady() { - eventfd_t data; - if (eventfd_read(fd, &data)) - return false; + recvq.clear(); parent->OnNotify(); - return true; + } + + void OnError(BufferedSocketError) + { } }; @@ -92,7 +92,7 @@ SocketThread::SocketThread(InspIRCd* SI) int fd = eventfd(0, O_NONBLOCK); if (fd < 0) throw new CoreException("Could not create pipe " + std::string(strerror(errno))); - signal.sock = new ThreadSignalSocket(this, SI, fd); + signal.sock = new ThreadSignalSocket(this, fd); } #else @@ -101,8 +101,8 @@ class ThreadSignalSocket : public BufferedSocket SocketThread* parent; int send_fd; public: - ThreadSignalSocket(SocketThread* p, InspIRCd* SI, int recvfd, int sendfd) : - BufferedSocket(SI, recvfd, const_cast<char*>("0.0.0.0")), parent(p), send_fd(sendfd) {} + ThreadSignalSocket(SocketThread* p, int recvfd, int sendfd) : + BufferedSocket(recvfd), parent(p), send_fd(sendfd) {} ~ThreadSignalSocket() { @@ -115,13 +115,14 @@ class ThreadSignalSocket : public BufferedSocket write(send_fd, &dummy, 1); } - virtual bool OnDataReady() + void OnDataReady() { - char data; - if (read(this->fd, &data, 1) <= 0) - return false; + recvq.clear(); parent->OnNotify(); - return true; + } + + void OnError(BufferedSocketError) + { } }; @@ -130,7 +131,7 @@ SocketThread::SocketThread(InspIRCd* SI) int fds[2]; if (pipe(fds)) throw new CoreException("Could not create pipe " + std::string(strerror(errno))); - signal.sock = new ThreadSignalSocket(this, SI, fds[0], fds[1]); + signal.sock = new ThreadSignalSocket(this, fds[0], fds[1]); } #endif diff --git a/src/threadengines/threadengine_win32.cpp b/src/threadengines/threadengine_win32.cpp index 5c62b5081..fab75699e 100644 --- a/src/threadengines/threadengine_win32.cpp +++ b/src/threadengines/threadengine_win32.cpp @@ -55,20 +55,15 @@ class ThreadSignalSocket : public BufferedSocket { SocketThread* parent; public: - ThreadSignalSocket(SocketThread* t, InspIRCd* SI, int newfd, const char* ip) - : BufferedSocket(SI, newfd, ip), parent(t) + ThreadSignalSocket(SocketThread* t, int newfd) + : BufferedSocket(newfd), parent(t) { } - virtual bool OnDataReady() + void OnDataReady() { - char data = 0; - if (ServerInstance->SE->Recv(this, &data, 1, 0) > 0) - { - parent->OnNotify(); - return true; - } - return false; + recvq.clear(); + parent->OnNotify(); } }; @@ -92,7 +87,7 @@ SocketThread::SocketThread(InspIRCd* SI) int nfd = accept(listenFD); if (nfd < 0) throw CoreException("Could not create ITC pipe"); - new ThreadSignalSocket(parent, ServerInstance, nfd, "127.0.0.1"); + new ThreadSignalSocket(parent, nfd); closesocket(listenFD); SI->SE->Blocking(connFD); diff --git a/src/usermanager.cpp b/src/usermanager.cpp index b9eff5a39..6d04bdff7 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -46,7 +46,7 @@ void UserManager::AddUser(InspIRCd* Instance, int socket, ClientListenSocket* vi { try { - New->GetIOHook()->OnRawSocketAccept(socket, client, server); + New->GetIOHook()->OnStreamSocketAccept(New, client, server); } catch (CoreException& modexcept) { @@ -201,24 +201,18 @@ void UserManager::QuitUser(User *user, const std::string &quitreason, const char FOREACH_MOD_I(ServerInstance,I_OnUserDisconnect,OnUserDisconnect(user)); - user->UpdateNickHash(user->uuid.c_str()); - - user_hash::iterator iter = this->clientlist->find(user->uuid); - if (user->registered != REG_ALL) if (ServerInstance->Users->unregistered_count) ServerInstance->Users->unregistered_count--; if (IS_LOCAL(user)) { - if (!user->sendq.empty()) - user->FlushWriteBuf(); - + user->DoWrite(); if (user->GetIOHook()) { try { - user->GetIOHook()->OnRawSocketClose(user->GetFd()); + user->GetIOHook()->OnStreamSocketClose(user); } catch (CoreException& modexcept) { @@ -227,7 +221,9 @@ void UserManager::QuitUser(User *user, const std::string &quitreason, const char } ServerInstance->SE->DelFd(user); - user->CloseSocket(); + user->Close(); + // user->Close() will set fd to -1; this breaks IS_LOCAL. Fix + user->SetFd(INT_MAX); } /* @@ -255,19 +251,12 @@ void UserManager::QuitUser(User *user, const std::string &quitreason, const char user->AddToWhoWas(); } + user_hash::iterator iter = this->clientlist->find(user->nick); + if (iter != this->clientlist->end()) this->clientlist->erase(iter); else ServerInstance->Logs->Log("USERS", DEBUG, "iter == clientlist->end, can't remove them from hash... problematic.."); - - if (IS_LOCAL(user)) - { - std::vector<User*>::iterator x = find(local_users.begin(),local_users.end(),user); - if (x != local_users.end()) - local_users.erase(x); - else - ServerInstance->Logs->Log("USERS", DEBUG, "Failed to remove user from vector"); - } } diff --git a/src/userprocess.cpp b/src/userprocess.cpp index 4fcf87f66..b150f2828 100644 --- a/src/userprocess.cpp +++ b/src/userprocess.cpp @@ -36,102 +36,6 @@ void FloodQuitUserHandler::Call(User* current) } } -void ProcessUserHandler::Call(User* cu) -{ - int result = EAGAIN; - - if (cu->GetFd() == FD_MAGIC_NUMBER) - return; - - char* ReadBuffer = Server->GetReadBuffer(); - - if (cu->GetIOHook()) - { - int result2 = 0; - int MOD_RESULT = 0; - - try - { - MOD_RESULT = cu->GetIOHook()->OnRawSocketRead(cu->GetFd(), ReadBuffer, Server->Config->NetBufferSize, result2); - } - catch (CoreException& modexcept) - { - Server->Logs->Log("USERS",DEBUG, "%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason()); - } - - if (MOD_RESULT < 0) - { - result = -EAGAIN; - } - else - { - result = result2; - } - } - else - { - result = cu->ReadData(ReadBuffer, Server->Config->NetBufferSize); - } - - if ((result) && (result != -EAGAIN)) - { - User *current; - int currfd; - - Server->stats->statsRecv += result; - /* - * perform a check on the raw buffer as an array (not a string!) to remove - * character 0 which is illegal in the RFC - replace them with spaces. - */ - - for (int checker = 0; checker < result; checker++) - { - if (ReadBuffer[checker] == 0) - ReadBuffer[checker] = ' '; - } - - if (result > 0) - ReadBuffer[result] = '\0'; - - current = cu; - currfd = current->GetFd(); - - // add the data to the users buffer - if (result > 0) - { - if (!current->AddBuffer(ReadBuffer)) - { - // AddBuffer returned false, theres too much data in the user's buffer and theyre up to no good. - Server->FloodQuitUser(current); - return; - } - - /* If user is over penalty, dont process here, just build up */ - if (current->Penalty < 10) - Server->Parser->DoLines(current); - - return; - } - - if ((result == -1) && (errno != EAGAIN) && (errno != EINTR)) - { - Server->Users->QuitUser(cu, errno ? strerror(errno) : "EOF from client"); - return; - } - } - - // result EAGAIN means nothing read - else if ((result == EAGAIN) || (result == -EAGAIN)) - { - /* do nothing */ - } - else if (result == 0) - { - Server->Users->QuitUser(cu, "Connection closed"); - return; - } -} - /** * This function is called once a second from the mainloop. * It is intended to do background checking on all the user structs, e.g. @@ -154,8 +58,12 @@ void InspIRCd::DoBackgroundUserStuff() if (curr->Penalty) { curr->Penalty--; - if (curr->Penalty < 10) - Parser->DoLines(curr, true); + curr->OnDataReady(); + } + + if (curr->getSendQSize() == 0) + { + FOREACH_MOD(I_OnBufferFlushed,OnBufferFlushed(curr)); } switch (curr->registered) diff --git a/src/users.cpp b/src/users.cpp index fd0c168d9..5d6b1a01a 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -216,12 +216,8 @@ User::User(InspIRCd* Instance, const std::string &uid) fd = -1; server_sa.sa.sa_family = AF_UNSPEC; client_sa.sa.sa_family = AF_UNSPEC; - recvq.clear(); - sendq.clear(); MyClass = NULL; AllowedPrivs = AllowedOperCommands = NULL; - chans.clear(); - invites.clear(); if (uid.empty()) uuid.assign(Instance->GetUID(), 0, UUID_LENGTH - 1); @@ -309,15 +305,6 @@ const std::string& User::MakeHostIP() return this->cached_hostip; } -void User::CloseSocket() -{ - if (this->fd > -1) - { - ServerInstance->SE->Shutdown(this, 2); - ServerInstance->SE->Close(this); - } -} - const std::string User::GetFullHost() { if (!this->cached_fullhost.empty()) @@ -352,21 +339,6 @@ char* User::MakeWildHost() return nresult; } -int User::ReadData(void* buffer, size_t size) -{ - if (IS_LOCAL(this)) - { -#ifndef WIN32 - return read(this->fd, buffer, size); -#else - return recv(this->fd, (char*)buffer, size, 0); -#endif - } - else - return 0; -} - - const std::string User::GetFullRealHost() { if (!this->cached_fullrealhost.empty()) @@ -540,123 +512,60 @@ bool User::HasPrivPermission(const std::string &privstr, bool noisy) return false; } -bool User::AddBuffer(const std::string &a) +void User::OnDataReady() { - std::string::size_type start = 0; - std::string::size_type i = a.find('\r'); - - /* - * The old implementation here took a copy, and rfind() on \r, removing as it found them, before - * copying a second time onto the recvq. That's ok, but involves three copies minimum (recv() to buffer, - * buffer to here, here to recvq) - The new method now copies twice (recv() to buffer, buffer to recvq). - * - * We use find() instead of rfind() for clarity, however unlike the old code, our scanning of the string is - * contiguous: as we specify a startpoint, we never see characters we have scanned previously, making this - * marginally faster in cases with a number of \r hidden early on in the buffer. - * - * How it works: - * Start at first pos of string, find first \r, append everything in the chunk (excluding \r) to recvq. Set - * i ahead of the \r, search for next \r, add next chunk to buffer... repeat. - * -- w00t (7 may, 2008) - */ - if (i == std::string::npos) - { - // no \r that we need to dance around, just add to buffer - recvq.append(a); - } - else - { - // While we can find the end of a chunk to add - while (i != std::string::npos) - { - // Append the chunk that we have - recvq.append(a, start, (i - start)); - - // Start looking for the next one - start = i + 1; - i = a.find('\r', start); - } - - if (start != a.length()) - { - /* - * This is here to catch a corner case when we get something like: - * NICK w0 - * 0t\r\nU - * SER ... - * in successive calls to us. - * - * Without this conditional, the 'U' on the second case will be dropped, - * which is most *certainly* not the behaviour we want! - * -- w00t - */ - recvq.append(a, start, (a.length() - start)); - } - } + if (quitting) + return; - if (this->MyClass && !this->HasPrivPermission("users/flood/increased-buffers") && recvq.length() > this->MyClass->GetRecvqMax()) + if (MyClass && !HasPrivPermission("users/flood/increased-buffers") && recvq.length() > MyClass->GetRecvqMax()) { ServerInstance->Users->QuitUser(this, "RecvQ exceeded"); - ServerInstance->SNO->WriteToSnoMask('a', "User %s RecvQ of %lu exceeds connect class maximum of %lu",this->nick.c_str(),(unsigned long int)recvq.length(),this->MyClass->GetRecvqMax()); - return false; + ServerInstance->SNO->WriteToSnoMask('a', "User %s RecvQ of %lu exceeds connect class maximum of %lu", + nick.c_str(), (unsigned long)recvq.length(), MyClass->GetRecvqMax()); } - return true; -} - -bool User::BufferIsReady() -{ - return (recvq.find('\n') != std::string::npos); -} - -void User::ClearBuffer() -{ - recvq.clear(); -} - -std::string User::GetBuffer() -{ - try + while (this->Penalty < 10) { - if (recvq.empty()) - return ""; - - /* Strip any leading \r or \n off the string. - * Usually there are only one or two of these, - * so its is computationally cheap to do. - */ - std::string::iterator t = recvq.begin(); - while (t != recvq.end() && (*t == '\r' || *t == '\n')) - { - recvq.erase(t); - t = recvq.begin(); - } - - for (std::string::iterator x = recvq.begin(); x != recvq.end(); x++) + std::string line; + line.reserve(MAXBUF); + std::string::size_type qpos = 0; + while (qpos < recvq.length()) { - /* Find the first complete line, return it as the - * result, and leave the recvq as whats left - */ - if (*x == '\n') + char c = recvq[qpos++]; + switch (c) { - std::string ret = std::string(recvq.begin(), x); - recvq.erase(recvq.begin(), x + 1); - return ret; + case '\0': + c = ' '; + break; + case '\r': + continue; + case '\n': + goto eol_found; } + if (line.length() < MAXBUF - 2) + line.push_back(c); } - return ""; - } + // if we got here, the recvq ran out before we found a newline + return; +eol_found: + // just found a newline. Terminate the string, and pull it out of recvq + recvq = recvq.substr(qpos); - catch (...) - { - ServerInstance->Logs->Log("USERS", DEBUG,"Exception in User::GetBuffer()"); - return ""; + // TODO should this be moved to when it was inserted in recvq? + ServerInstance->stats->statsRecv += qpos; + this->bytes_in += qpos; + this->cmds_in++; + + ServerInstance->Parser->ProcessBuffer(line, this); } } void User::AddWriteBuf(const std::string &data) { - if (!this->quitting && this->MyClass && !this->HasPrivPermission("users/flood/increased-buffers") && sendq.length() + data.length() > this->MyClass->GetSendqMax()) + // Don't bother sending text to remote users! + if (IS_REMOTE(this)) + return; + if (!quitting && MyClass && getSendQSize() + data.length() > MyClass->GetSendqMax() && !HasPrivPermission("users/flood/increased-buffers")) { /* * Fix by brain - Set the error text BEFORE calling, because @@ -664,66 +573,36 @@ void User::AddWriteBuf(const std::string &data) * to repeatedly add the text to the sendq! */ ServerInstance->Users->QuitUser(this, "SendQ exceeded"); - ServerInstance->SNO->WriteToSnoMask('a', "User %s SendQ of %lu exceeds connect class maximum of %lu",this->nick.c_str(),(unsigned long int)sendq.length() + data.length(),this->MyClass->GetSendqMax()); + ServerInstance->SNO->WriteToSnoMask('a', "User %s SendQ of %lu exceeds connect class maximum of %lu", + nick.c_str(), (unsigned long)getSendQSize() + data.length(), MyClass->GetSendqMax()); return; } // We still want to append data to the sendq of a quitting user, // e.g. their ERROR message that says 'closing link' - if (data.length() > MAXBUF - 2) /* MAXBUF has a value of 514, to account for line terminators */ - sendq.append(data.substr(0,MAXBUF - 4)).append("\r\n"); /* MAXBUF-4 = 510 */ - else - sendq.append(data); + WriteData(data); } -// send AS MUCH OF THE USERS SENDQ as we are able to (might not be all of it) -void User::FlushWriteBuf() +void User::OnError(BufferedSocketError) { - if (this->fd == FD_MAGIC_NUMBER) - { - sendq.clear(); - return; - } + ServerInstance->Users->QuitUser(this, getError()); +} - if ((sendq.length()) && (this->fd != FD_MAGIC_NUMBER)) +void User::cull() +{ + if (!quitting) + ServerInstance->Users->QuitUser(this, "Culled without QuitUser"); + if (IS_LOCAL(this)) { - int old_sendq_length = sendq.length(); - int n_sent = ServerInstance->SE->Send(this, this->sendq.data(), this->sendq.length(), 0); + if (fd != INT_MAX) + Close(); - if (n_sent == -1) - { - if (errno == EAGAIN) - { - /* The socket buffer is full. This isnt fatal, - * try again later. - */ - ServerInstance->SE->WantWrite(this); - } - else - { - /* Fatal error, set write error and bail */ - ServerInstance->Users->QuitUser(this, errno ? strerror(errno) : "Write error"); - return; - } - } + std::vector<User*>::iterator x = find(ServerInstance->Users->local_users.begin(),ServerInstance->Users->local_users.end(),this); + if (x != ServerInstance->Users->local_users.end()) + ServerInstance->Users->local_users.erase(x); else - { - /* advance the queue */ - if (n_sent) - this->sendq = this->sendq.substr(n_sent); - /* update the user's stats counters */ - this->bytes_out += n_sent; - this->cmds_out++; - if (n_sent != old_sendq_length) - ServerInstance->SE->WantWrite(this); - } - } - - /* note: NOT else if! */ - if (this->sendq.empty()) - { - FOREACH_MOD(I_OnBufferFlushed,OnBufferFlushed(this)); + ServerInstance->Logs->Log("USERS", DEBUG, "Failed to remove user from vector"); } } @@ -1191,35 +1070,29 @@ bool User::SetClientIP(const char* sip) return irc::sockets::aptosa(sip, 0, &client_sa); } +static std::string wide_newline("\r\n"); + void User::Write(const std::string& text) { if (!ServerInstance->SE->BoundsCheckFd(this)) return; - ServerInstance->Logs->Log("USEROUTPUT", DEBUG,"C[%d] O %s", this->GetFd(), text.c_str()); - - if (this->GetIOHook()) + if (text.length() > MAXBUF - 2) { - /* XXX: The lack of buffering here is NOT a bug, modules implementing this interface have to - * implement their own buffering mechanisms - */ - try - { - this->GetIOHook()->OnRawSocketWrite(this->fd, text.data(), text.length()); - this->GetIOHook()->OnRawSocketWrite(this->fd, "\r\n", 2); - } - catch (CoreException& modexcept) - { - ServerInstance->Logs->Log("USEROUTPUT", DEBUG, "%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason()); - } - } - else - { - this->AddWriteBuf(text); - this->AddWriteBuf("\r\n"); + // this should happen rarely or never. Crop the string at 512 and try again. + std::string try_again = text.substr(0, MAXBUF - 2); + Write(try_again); + return; } + + ServerInstance->Logs->Log("USEROUTPUT", DEBUG,"C[%d] O %s", this->GetFd(), text.c_str()); + + this->AddWriteBuf(text); + this->AddWriteBuf(wide_newline); + ServerInstance->stats->statsSent += text.length() + 2; - ServerInstance->SE->WantWrite(this); + this->bytes_out += text.length() + 2; + this->cmds_out++; } /** Write() @@ -1904,25 +1777,6 @@ void User::ShowRULES() this->WriteNumeric(RPL_RULESEND, "%s :End of RULES command.",this->nick.c_str()); } -void User::HandleEvent(EventType et, int errornum) -{ - if (this->quitting) // drop everything, user is due to be quit - return; - - switch (et) - { - case EVENT_READ: - ServerInstance->ProcessUser(this); - break; - case EVENT_WRITE: - this->FlushWriteBuf(); - break; - case EVENT_ERROR: - ServerInstance->Users->QuitUser(this, errornum ? strerror(errornum) : "Client closed the connection"); - break; - } -} - void User::IncreasePenalty(int increase) { this->Penalty += increase; |