]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Create StreamSocket for IO hooking implementation
authordanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>
Mon, 21 Sep 2009 13:26:31 +0000 (13:26 +0000)
committerdanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>
Mon, 21 Sep 2009 13:26:31 +0000 (13:26 +0000)
Fixes the SSL SendQ bug
Removes duplicate code between User and BufferedSocket
Simplify SSL module API
Simplify EventHandler API (Readable/Writeable moved to SE)
Add hook for culled objects to invoke callbacks prior to destructor
 Replace SocketCull with GlobalCull now that sockets can close themselves
Shorten common case of user read/parse/write path:
 User::Write is now zero-copy up to syscall/SSL invocation
 User::Read has only two copy/scan passes from read() to ProcessCommand

git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11752 e03df62e-2008-0410-955e-edbf42e46eb7

82 files changed:
include/base.h
include/cull_list.h
include/inspircd.h
include/inspsocket.h
include/modules.h
include/socket.h
include/socketengine.h
include/socketengines/socketengine_epoll.h
include/socketengines/socketengine_iocp.h
include/socketengines/socketengine_kqueue.h
include/socketengines/socketengine_poll.h
include/socketengines/socketengine_ports.h
include/socketengines/socketengine_select.h
include/users.h
src/base.cpp
src/command_parse.cpp
src/cull_list.cpp
src/helperfuncs.cpp
src/inspircd.cpp
src/inspsocket.cpp
src/modules.cpp
src/modules/extra/m_ssl_gnutls.cpp
src/modules/extra/m_ssl_openssl.cpp
src/modules/extra/m_ziplink.cpp
src/modules/m_httpd.cpp
src/modules/m_spanningtree/addline.cpp
src/modules/m_spanningtree/admin.cpp
src/modules/m_spanningtree/away.cpp
src/modules/m_spanningtree/capab.cpp
src/modules/m_spanningtree/compat.cpp
src/modules/m_spanningtree/delline.cpp
src/modules/m_spanningtree/encap.cpp
src/modules/m_spanningtree/fhost.cpp
src/modules/m_spanningtree/fident.cpp
src/modules/m_spanningtree/fjoin.cpp
src/modules/m_spanningtree/fmode.cpp
src/modules/m_spanningtree/fname.cpp
src/modules/m_spanningtree/ftopic.cpp
src/modules/m_spanningtree/handshaketimer.cpp
src/modules/m_spanningtree/hmac.cpp
src/modules/m_spanningtree/kill.cpp
src/modules/m_spanningtree/main.cpp
src/modules/m_spanningtree/metadata.cpp
src/modules/m_spanningtree/modules.cpp
src/modules/m_spanningtree/motd.cpp
src/modules/m_spanningtree/netburst.cpp
src/modules/m_spanningtree/nickcollide.cpp
src/modules/m_spanningtree/operquit.cpp
src/modules/m_spanningtree/opertype.cpp
src/modules/m_spanningtree/override_stats.cpp
src/modules/m_spanningtree/ping.cpp
src/modules/m_spanningtree/pong.cpp
src/modules/m_spanningtree/push.cpp
src/modules/m_spanningtree/resolvers.cpp
src/modules/m_spanningtree/save.cpp
src/modules/m_spanningtree/server.cpp
src/modules/m_spanningtree/stats.cpp
src/modules/m_spanningtree/svsjoin.cpp
src/modules/m_spanningtree/svsnick.cpp
src/modules/m_spanningtree/svspart.cpp
src/modules/m_spanningtree/time.cpp
src/modules/m_spanningtree/treesocket.h
src/modules/m_spanningtree/treesocket1.cpp
src/modules/m_spanningtree/treesocket2.cpp
src/modules/m_spanningtree/uid.cpp
src/modules/m_spanningtree/utils.cpp
src/modules/m_spanningtree/utils.h
src/modules/m_spanningtree/whois.cpp
src/socket.cpp
src/socketengine.cpp
src/socketengines/socketengine_epoll.cpp
src/socketengines/socketengine_iocp.cpp
src/socketengines/socketengine_kqueue.cpp
src/socketengines/socketengine_poll.cpp
src/socketengines/socketengine_ports.cpp
src/socketengines/socketengine_select.cpp
src/stats.cpp
src/threadengines/threadengine_pthread.cpp
src/threadengines/threadengine_win32.cpp
src/usermanager.cpp
src/userprocess.cpp
src/users.cpp

index ab52545f9716992ddb8fa31f2f06828f48a45e17..b66051cafe7a365d0b718d07c0ae048696328c74 100644 (file)
@@ -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.
index 8c38276429c15490be501f93093754528848acf1..bd2fb45dae899f220f7ebb9fb1ff0d6585a5c4ed 100644 (file)
  * 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)
         */
index b927f0b1b6edc4df099e9bb217e91715f1cbcb7f..72e49c09ac493d3507e22374ed626ca8c729796a 100644 (file)
@@ -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);
index 32f2dab1a7d9861d7080be243aaa2bb2ccb81737..73aa748a0326384f50627166614d2e9c61eb4407 100644 (file)
@@ -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,13 +80,74 @@ 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
         */
        virtual void Tick(time_t now);
 };
 
+/**
+ * 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
@@ -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 &current_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
index f40cd49fd0f8e4d681986054b402dd7ea6ee57ce..982d83754a12e7c9127a8c8d98699524e091ee1f 100644 (file)
@@ -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.
index 5ca9fc18fc967e199ae7d74d450ba0d0f1e6bdda..af3eccea2a94b1e90c65fc92f04bb338a929b797 100644 (file)
@@ -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
index a191ff12d7c00fd6db2b317037feab1b157c5ac7..4e87f7494db694336422f50a68beeff3c96aa0d6 100644 (file)
@@ -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
index 6e681821254b77c90e65f6f95cdd86e4c1fc18d1..3e08179ae4180959757336ec33cbea8a8ba11c3f 100644 (file)
@@ -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
index 302fdbd2ce24e0c85e8c073d9614e8f79a7a46d5..dd34227d35125a474043f18975748368353cfca5 100644 (file)
@@ -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
index 41459f56167213856256f4a828eadf8bb812d8bc..a09e93553607cfd0e84923053521f3f54ab7cd39 100644 (file)
@@ -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
index df1100d095fb78cf2991d9c488adc6ee00f621b4..725ad225c13422114ab17a7a73005b7a7b71270b 100644 (file)
@@ -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
index 40d5da51ac2829728733a5629e300c86985a1262..03df456f20907b4f1008fa85903c33a514fa233d 100644 (file)
@@ -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
index a248e8a8e2999493e1cd5ea6b81552d14b061273..a1993f19ffcbb2e4c6d182fed2aeaa1749fa9602 100644 (file)
@@ -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
index f9be74924f7aebe1120f8011a5c998d5c6b93199..7ec35535f919c362db788436b6d05c624423229e 100644 (file)
@@ -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.
index 27eb4af23be1b517f56ba995570005ea5bfaeb33..2b022688df8ebf2960973a4d58add9e43b8eda15 100644 (file)
@@ -26,6 +26,14 @@ classbase::classbase()
 {
 }
 
+void classbase::cull()
+{
+}
+
+classbase::~classbase()
+{
+}
+
 void BoolSet::Set(int number)
 {
        this->bits |= bitfields[number];
index 92d4b8c24be46452faa0723c3f9a903d19fe60e5..cbf6a1005a614402b9fe285efc365353316c0f93 100644 (file)
@@ -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)
index 79c077ead4b4e077c3b0d53c21f4be1956424618..35fa44bfa113c1a3e0ad9b6945ce260d21d5664b 100644 (file)
 
 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();
 }
 
index 0ec8db966601540fe60e04324e8a958c8b65eef1..80feae464c6e52468463de830163772c3d8a58be 100644 (file)
@@ -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();
        }
 }
 
index 1b23bff028abf53bb9c091e56f68ea6de3af5b93..704fec475b40a4d2560cdb3ec4180ef1cd99e4d4 100644 (file)
@@ -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();
-}
-
 /**********************************************************************************/
 
 /**
index 0350858e7ce693ad391825570d3237fe0c466f42..964582062db41f2e4daec79154c81c177d645cdb 100644 (file)
 #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 &current_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);
+       }
 }
 
index 51fecb47c238f8106cfe607202ed1318c0adae9d..c11b63becef06e893564ebb4a159e8fc68a8d930 100644 (file)
@@ -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&) { }
 
index f458f5da14e5c5eff61d22e9943c698acdc7a5d9..27c466573c88d7c7a1d02c6b3d683067cf45a0d9 100644 (file)
@@ -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 &param)
+       void OnModuleRehash(User* user, const std::string &param)
        {
                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;
        }
index a33cf6bc218228928c5aaedc96664af807b6f5c9..e77fa23ff95dbef9effe27fe9f5a8ca3b4ff082e 100644 (file)
@@ -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 &param)
+       void OnModuleRehash(User* user, const std::string &param)
        {
                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);
                }
        }
 
index c220460bd858078444f945b269854ccef91b005e..7d090d80a5f9bd81cf1563df58567a4d37171679 100644 (file)
@@ -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)
index bdf4e424e9a2fba01d4ff1f5104e26a8553707c6..c1698accf32125b3f7b69c6f54ed56054cf85ced 100644 (file)
@@ -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()
index 2f7b5132d84dc30f38d99ca9cb010e14d9965d17..3e6d380701558e84dc93e7d3ebf6fbe05faac80c 100644 (file)
@@ -24,7 +24,7 @@ bool TreeSocket::AddLine(const std::string &prefix, parameterlist &params)
 {
        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 &params)
 
        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 &params)
        }
        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 &params)
        {
                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];
index 133da928ba08569c3e4df5a99901e44bd1b1a5bb..e47078c7ec62b446eb9848e4eb0f48a5330d3f7f 100644 (file)
@@ -25,30 +25,30 @@ bool TreeSocket::Admin(const std::string &prefix, parameterlist &params)
 {
        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]);
                }
index 2aac26bbd910d6fe3ac8662e386670cdbf9d8577..35426655403aeb79d242c610f33f9484cf15ec21 100644 (file)
@@ -20,7 +20,7 @@
 
 bool TreeSocket::Away(const std::string &prefix, parameterlist &params)
 {
-       User* u = this->ServerInstance->FindNick(prefix);
+       User* u = ServerInstance->FindNick(prefix);
        if (!u)
                return true;
        if (params.size())
index 66d448e55d1a837b30b82cf728e068d85a7aef38..7953468e4cb39583bee7538b817be414b786847c 100644 (file)
@@ -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 &params)
                        }
                }
 
-               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 &params)
                        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 &params)
                        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);
                        }
                }
 
index 8a6e6855ffbd7a047da5eeb9cb7f5d7ad77e50ce..71272edec6b13e70e948e3136678bd60ec08852a 100644 (file)
@@ -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);
 }
 
 
index a1a9089ad6114772faaf88168a9fdd21e611b59b..cadcdd14b5e0b31aff0967f92e2fa1ec6e0e71eb 100644 (file)
@@ -42,7 +42,7 @@ bool TreeSocket::DelLine(const std::string &prefix, parameterlist &params)
        /* 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);
        }
index 7b85a49d0ae163e0535148a5f49819a4d252e9d6..175257b0a804e64b02865ef8432a606a539d06db 100644 (file)
@@ -29,7 +29,7 @@ bool TreeSocket::Encap(const std::string &prefix, parameterlist &params)
        {
                if (InspIRCd::Match(ServerInstance->Config->GetSID(), params[0]))
                {
-                       User* who = this->ServerInstance->FindUUID(prefix);
+                       User* who = ServerInstance->FindUUID(prefix);
                        if (!who)
                                who = Utils->ServerUser;
 
index 1595b98aa74beeaa2180655d6f6cb70e2568ab4c..d31cffa394950582cdc16e87d856303017aa253a 100644 (file)
@@ -25,7 +25,7 @@ bool TreeSocket::ChangeHost(const std::string &prefix, parameterlist &params)
 {
        if (params.size() < 1)
                return true;
-       User* u = this->ServerInstance->FindNick(prefix);
+       User* u = ServerInstance->FindNick(prefix);
 
        if (u)
        {
index 0744d9bf2fa535c0230a2f6418ac3d2c4fc6a66d..8cd3618db8732e2d741d0a9fb2b5a3d5484eec19 100644 (file)
@@ -25,7 +25,7 @@ bool TreeSocket::ChangeIdent(const std::string &prefix, parameterlist &params)
 {
        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());
index 2c3606db173295d748268e45388f69553596b064..7f11f40dd1dd7f5194b4a2a0188b6d9b93880734 100644 (file)
@@ -59,7 +59,7 @@ bool TreeSocket::ForceJoin(const std::string &source, parameterlist &params)
        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 &params)
                        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 &params)
                        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 &params)
                                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
                        {
index 3421f8045c4be52ed88817dbdc3dcc883f918576..3bca098d62898eedef49bb23036161af221194f2 100644 (file)
@@ -34,7 +34,7 @@ bool TreeSocket::ForceMode(const std::string &source, parameterlist &params)
        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 &params)
 
        }
        /* 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 &params)
        }
        else
        {
-               chan = this->ServerInstance->FindChan(params[0]);
+               chan = ServerInstance->FindChan(params[0]);
                if (chan)
                {
                        ourTS = chan->age;
index a83591a4f410de5a49e458257502d715df4934a4..cc7625f12b1fc3ad5b3edc54f81acf242a344dc9 100644 (file)
@@ -25,7 +25,7 @@ bool TreeSocket::ChangeName(const std::string &prefix, parameterlist &params)
 {
        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());
index 34e97dd11815367c0aea279d52b273ff6a86413e..5a6656e3ee83d9a422bc2a20842b98e980184d60 100644 (file)
@@ -27,14 +27,14 @@ bool TreeSocket::ForceTopic(const std::string &source, parameterlist &params)
        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)
index 56f34283b72bdd5bc33ee4bf4b0892922e533bcd..814aa122c7ab8a38d95bfe426ce44a98e73733b4 100644 (file)
@@ -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
index cc1b33f238b016bcadbf85a6d181af8c7c1ba9a4..b7cddc47ac750ce23ef349f043a830a051202a0a 100644 (file)
@@ -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)
                {
index c2026d0bb4d8fcca9c1660edfb4e6b43f1c28521..e76fc7f3e52bb0048cdf7251dbb1fce6b3fea138 100644 (file)
@@ -28,7 +28,7 @@ bool TreeSocket::RemoteKill(const std::string &prefix, parameterlist &params)
        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 &params)
                        // 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;
 }
index 1bc3dfe3925b9f7fed8c62b400ea438f0f337316..230c3109b8b9ad29cc7211a6bade76e6a897af1d 100644 (file)
@@ -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);
                }
        }
index 40a98d93b2fa2b16905baaa6f5bf6281bc4101e6..135970a4a2509036ef9fdd727bb1c941a9e2d0a5 100644 (file)
@@ -33,26 +33,26 @@ bool TreeSocket::MetaData(const std::string &prefix, parameterlist &params)
        {
                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]));
                        }
                }
        }
index 6c91327946d126261abb55f8d4bcf669cdc0f3df..7a20a98ff32088a1c96b245f0f3ae06ef5037355 100644 (file)
@@ -26,7 +26,7 @@ bool TreeSocket::Modules(const std::string &prefix, parameterlist &params)
        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 &params)
        par.push_back(prefix);
        par.push_back("");
 
-       User* source = this->ServerInstance->FindNick(prefix);
+       User* source = ServerInstance->FindNick(prefix);
        if (!source)
                return true;
 
index e42c53152f65c46666aac97e021135522359c7d6..0c775d6442e5e6bfe0e7854453311f16eb8d263a 100644 (file)
@@ -27,11 +27,11 @@ bool TreeSocket::Motd(const std::string &prefix, parameterlist &params)
 {
        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 &params)
                                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]);
                }
index ada10e6a11d1e93e8fcfc5294d722f07b7395b99..3cfad9b63fa051cd1774cd388716601eb9a8681d 100644 (file)
 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));
                }
        }
 }
index a723c114f082e2af24d44028b2b83c8a28d8710a..4481ba35e1a37996ec9add9d80e8f87271a30779 100644 (file)
@@ -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,
index 5cdee3bc6f7d647136f04797a8576c5c6b581203..9128baa0ffaff10c21223bc3d2ece96d21605e0f 100644 (file)
@@ -26,7 +26,7 @@ bool TreeSocket::OperQuit(const std::string &prefix, parameterlist &params)
        if (params.size() < 1)
                return true;
 
-       User* u = this->ServerInstance->FindNick(prefix);
+       User* u = ServerInstance->FindNick(prefix);
 
        if (u)
        {
index c1105aa71c7b19cd956f6196f789f7bdc847714f..a1ad88007bcb845a302eaa3a485c12e8ba474fc7 100644 (file)
@@ -29,11 +29,11 @@ bool TreeSocket::OperType(const std::string &prefix, parameterlist &params)
        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 &params)
                         */
                        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 &params)
                }
 
                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;
 }
index 9986763d92f04c5775c2553b89c3b1d2c5299e2e..5d0239f8463754fb9856bf438a916d36a2c97868 100644 (file)
@@ -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 + ")");
index 1318b60a0975e2a714258dc836c5f7180ed892bf..c3467c984d6a854e714355b2439bbea56694c837 100644 (file)
@@ -31,13 +31,13 @@ bool TreeSocket::LocalPing(const std::string &prefix, parameterlist &params)
        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];
index b551ef6d2e89f8c436d7c0ca56e1917cb055c6f6..27464189781541f4e8c45f7f380c3a444f74f131 100644 (file)
@@ -52,7 +52,7 @@ bool TreeSocket::LocalPong(const std::string &prefix, parameterlist &params)
                         * 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());
index 88c6b55bdb13d52fe71774451c1b0b34e6570dbe..778c2291cad09cfdfada27961f43085535f2238e 100644 (file)
@@ -28,7 +28,7 @@ bool TreeSocket::Push(const std::string &prefix, parameterlist &params)
 {
        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))
index 73e67c4f7e40da4326f23673b10a42e1e56c69d8..c7c49b348872879f673879508d583346f4d9ec0d 100644 (file)
@@ -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);
                }
        }
index 9969fdca713bcfc85b253b2311e55cc2135064a3..cfa8dc7943974707ce72565092474e88693de408 100644 (file)
@@ -32,7 +32,7 @@ bool TreeSocket::ForceNick(const std::string &prefix, parameterlist &params)
        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 &params)
 
                if (!u->ForceNickChange(u->uuid.c_str()))
                {
-                       this->ServerInstance->Users->QuitUser(u, "Nickname collision");
+                       ServerInstance->Users->QuitUser(u, "Nickname collision");
                }
        }
 
index c275f349007e9ae6cfc68cb1ebe3e7816164417d..0256756425f4b815152d34d4ff53bd6c272c90af 100644 (file)
@@ -49,7 +49,7 @@ bool TreeSocket::RemoteServer(const std::string &prefix, parameterlist &params)
                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 &params)
        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 &params)
        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 &params)
 
                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 &params)
                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 &params)
 
                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 &params)
        }
 
        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 &params)
        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 &params)
 
                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 &params)
                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 &params)
                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;
 }
 
index d67c5a3af55e0f8e920b1fed771508e5988d8889..71f12d50b8e3ee07f042a6b9210483cd61a95908 100644 (file)
@@ -32,11 +32,11 @@ bool TreeSocket::Stats(const std::string &prefix, parameterlist &params)
         */
        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 &params)
                                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]);
                }
index b6246e2f4040637270c036c080332d283f2c7e09..1664190f8ba468773044163322c8088761b4cf18 100644 (file)
@@ -29,13 +29,13 @@ bool TreeSocket::ServiceJoin(const std::string &prefix, parameterlist &params)
        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;
index 3af6961d07493c096e44450db18ee487e8b91205..7a723a36d4d6835318c53da31f084807dc408d59 100644 (file)
@@ -32,7 +32,7 @@ bool TreeSocket::SVSNick(const std::string &prefix, parameterlist &params)
        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 &params)
                                /* 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;
                                }
                        }
index 83e329b4e46fef0b0a1cd6ce093320df92f29f43..1e26c90d99b1a05ae8a8d8a68979dd8d173411d1 100644 (file)
@@ -34,8 +34,8 @@ bool TreeSocket::ServicePart(const std::string &prefix, parameterlist &params)
        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)
        {
index 82a7fe62e33249b19f0da1ee2c28540ef23149f2..6fdcf8b5391eba2e8afc6228f7694b4862ad0881 100644 (file)
@@ -31,20 +31,20 @@ bool TreeSocket::Time(const std::string &prefix, parameterlist &params)
        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 &params)
        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();
index a26e89f8563f56cb41d98fdbf44155398539d823..3c94849818f1f177327e7b08b8de3b362d0acc8a 100644 (file)
@@ -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 */
index d59364751c761f6f30057c6decc4f026663f8cee..55fbc2c91e8e55cf925300ac4e743396cb944c05 100644 (file)
  * 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;
 }
index 7938027815301c06f9f4a0a6174316cbc6237250..cf537f05b02384ec451f7d28833ca98a9b62918d 100644 (file)
@@ -32,7 +32,7 @@ bool TreeSocket::Error(parameterlist &params)
 {
        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());
        }
 }
index b7c13b5f85403208343c9f3ae71082192b7e38d0..0f0e75a1d8e06d3f0bb5d386fe8ea4f83f7fc9b8 100644 (file)
@@ -64,9 +64,9 @@ bool TreeSocket::ParseUID(const std::string &source, parameterlist &params)
        }
 
        /* 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 &params)
        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 &params)
 
        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);
index b37aecc4bfbd68fd935689cf7625a3244b54f453..8d3c55758f91ac237f2e897aeab18e0fd06bcb5a 100644 (file)
@@ -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());
                }
        }
 }
index 09c70713126218220970926dcbc40e106c3a92f8..1bdf127d840d73a42f7ebfb177fc0ca3cc7b05a0 100644 (file)
@@ -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);
 };
 
index f12a7f1090500c6e947a8d437f4b215a2ee915bc..79e2d73552cab91572cf7bd5619d4ce9da523d1b 100644 (file)
@@ -28,13 +28,13 @@ bool TreeSocket::Whois(const std::string &prefix, parameterlist &params)
 {
        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 &params)
                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
index ccae48a6d7cc654e2f7db2f063e5191f4dbd3595..cc9cb79b9e6fa1920aafc2d32d4647f22738165a 100644 (file)
@@ -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);
index af2f1b16972b33fbfb340730ba8926f3a8965c2d..c0ae3f278945982345107f66a4a46c96fe1e799a 100644 (file)
 
 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)
index 1be0d7cd2f2943b995cac1e3fdb2080f591609ba..7fed6f250f786dcbcf39d7c284ae71023fc3c9a2 100644 (file)
@@ -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);
 
index ee2e5afa18fe3f5d29a5f4e8e0f2bf9f601da323..3c31819099ca8c3032f044e4b4c6cbf603341fec 100644 (file)
@@ -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 =) */
index bf09eaf740066eb9b3c679dfdbf68449fbb3e241..cbe3e959d203bd75dccfe988d409b7f01be1478f 100644 (file)
@@ -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);
        }
index cee6a90cb59ee023cf533e046b535951302a230c..6d5ddb9f5c58ac937973657a39426763fec9ce72 100644 (file)
@@ -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);
index 5efa545b0563fa0a165d2662552ec669ecd608ac..eb08839d018472e39c6f1a03bee4568b9df66922 100644 (file)
@@ -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++;
index 8c41df11b745bc5e585a4270d5875d07aae6569f..7f6a4e283742dc1bb1f3e0ede9b050704426d793 100644 (file)
@@ -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);
index 40ee40b189f5608c08637262eea79720f8b5f5db..02cfeaa7c8e87bbbaae776f90043d6fba0ba3efa 100644 (file)
@@ -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;
 
index 6e32634c5c4c0050bc2037a25c3123941446d777..a4a47f8fa37784b10d0c3ef7dc158cd6e753bb84 100644 (file)
@@ -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
 
index 5c62b5081b89c5ad8d9fdc4cd3baa461e15b2c68..fab75699e4730707751bc8388d21d662d2a98638 100644 (file)
@@ -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);
index b9eff5a3991b21da78fecd74b6998055ba72be28..6d04bdff7e3edf7e1367982b21df3328cb19b9d3 100644 (file)
@@ -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");
-       }
 }
 
 
index 4fcf87f66e5db1c28113630334d47b940fc49b9a..b150f2828ebb4951b809ee0189a84bb572831ba7 100644 (file)
@@ -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)
index fd0c168d94c317f5d937bddf28852ec21d50640c..5d6b1a01a748f928f5d57dc80d1d0c64565fc6ea 100644 (file)
@@ -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;