]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Added basic sendq stuff - WARNING, there is no configuration yet, this CVS allows...
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>
Wed, 11 May 2005 21:54:47 +0000 (21:54 +0000)
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>
Wed, 11 May 2005 21:54:47 +0000 (21:54 +0000)
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@1361 e03df62e-2008-0410-955e-edbf42e46eb7

include/users.h
src/inspircd.cpp
src/modules/m_ident.cpp
src/users.cpp

index 73e1a1173f5e00f9c2fd70781090b04d68d37431..b747669c9c40b0a2dae4d8c9ecc8535a2ed5be20 100644 (file)
@@ -184,12 +184,21 @@ class userrec : public connection
         */
        std::string recvq;
 
+       /** User's send queue.
+        * Lines waiting to be sent are stored here until their buffer is flushed.
+        */
+       std::string sendq;
+
        /** Flood counters
         */
        long lines_in;
        time_t reset_due;
        long threshold;
 
+       /* Write error string
+        */
+       std::string WriteError;
+
        userrec();
        
        virtual ~userrec() {  }
@@ -253,7 +262,22 @@ class userrec : public connection
         * it is ok to read the buffer before calling GetBuffer().
         */
        std::string GetBuffer();
-       
+
+       /** Sets the write error for a connection. This is done because the actual disconnect
+        * of a client may occur at an inopportune time such as half way through /LIST output.
+        * The WriteErrors of clients are checked at a more ideal time (in the mainloop) and
+        * errored clients purged.
+        */
+       void SetWriteError(std::string error);
+
+       /** Returns the write error which last occured on this connection or an empty string
+        * if none occured.
+        */
+       std::string GetWriteError();
+
+       void AddWriteBuf(std::string data);
+       void FlushWriteBuf();
+
 };
 
 
index 8da1f7bf5734f491c2c5feaf54da2b89b50e2cee..d5ba7f8909f8aa1bdb7550af2e4d4dbc6ceb14c0 100644 (file)
@@ -596,6 +596,7 @@ void Write(int sock,char *text, ...)
        char textbuffer[MAXBUF];
        va_list argsPtr;
        char tb[MAXBUF];
+       int res;
        
        va_start (argsPtr, text);
        vsnprintf(textbuffer, MAXBUF, text, argsPtr);
@@ -604,16 +605,14 @@ void Write(int sock,char *text, ...)
        chop(tb);
        if ((sock != -1) && (sock != FD_MAGIC_NUMBER))
        {
-               int MOD_RESULT = 0;
-               FOREACH_RESULT(OnRawSocketWrite(sock,tb,bytes > 512 ? 512 : bytes));
-               if (!MOD_RESULT)
-                       write(sock,tb,bytes > 512 ? 512 : bytes);
                if (fd_ref_table[sock])
                {
-                       fd_ref_table[sock]->bytes_out += (bytes > 512 ? 512 : bytes);
-                       fd_ref_table[sock]->cmds_out++;
+                       int MOD_RESULT = 0;
+                       FOREACH_RESULT(OnRawSocketWrite(sock,tb,bytes));
+                       fd_ref_table[sock]->AddWriteBuf(tb);
+                       statsSent += bytes;
                }
-               statsSent += (bytes > 512 ? 512 : bytes);
+               else log(DEFAULT,"ERROR! attempted write to a user with no fd_ref_table entry!!!");
        }
 }
 
@@ -629,6 +628,7 @@ void WriteServ(int sock, char* text, ...)
                return;
        }
        char textbuffer[MAXBUF],tb[MAXBUF];
+       int res;
        va_list argsPtr;
        va_start (argsPtr, text);
        
@@ -638,16 +638,14 @@ void WriteServ(int sock, char* text, ...)
        chop(tb);
        if ((sock != -1) && (sock != FD_MAGIC_NUMBER))
        {
-                int MOD_RESULT = 0;
-                FOREACH_RESULT(OnRawSocketWrite(sock,tb,bytes > 512 ? 512 : bytes));
-                if (!MOD_RESULT)
-                        write(sock,tb,bytes > 512 ? 512 : bytes);
                 if (fd_ref_table[sock])
                 {
-                        fd_ref_table[sock]->bytes_out += (bytes > 512 ? 512 : bytes);
-                        fd_ref_table[sock]->cmds_out++;
+                        int MOD_RESULT = 0;
+                        FOREACH_RESULT(OnRawSocketWrite(sock,tb,bytes));
+                        fd_ref_table[sock]->AddWriteBuf(tb);
+                       statsSent += bytes;
                 }
-               statsSent += (bytes > 512 ? 512 : bytes);
+               else log(DEFAULT,"ERROR! attempted write to a user with no fd_ref_table entry!!!");
        }
 }
 
@@ -664,6 +662,7 @@ void WriteFrom(int sock, userrec *user,char* text, ...)
        }
        char textbuffer[MAXBUF],tb[MAXBUF];
        va_list argsPtr;
+       int res;
        va_start (argsPtr, text);
        
        vsnprintf(textbuffer, MAXBUF, text, argsPtr);
@@ -672,16 +671,14 @@ void WriteFrom(int sock, userrec *user,char* text, ...)
        chop(tb);
        if ((sock != -1) && (sock != FD_MAGIC_NUMBER))
        {
-                int MOD_RESULT = 0;
-                FOREACH_RESULT(OnRawSocketWrite(sock,tb,bytes > 512 ? 512 : bytes));
-                if (!MOD_RESULT)
-                        write(sock,tb,bytes > 512 ? 512 : bytes);
                 if (fd_ref_table[sock])
                 {
-                        fd_ref_table[sock]->bytes_out += (bytes > 512 ? 512 : bytes);
-                        fd_ref_table[sock]->cmds_out++;
+                        int MOD_RESULT = 0;
+                        FOREACH_RESULT(OnRawSocketWrite(sock,tb,bytes));
+                        fd_ref_table[sock]->AddWriteBuf(tb);
+                       statsSent += bytes;
                 }
-               statsSent += (bytes > 512 ? 512 : bytes);
+               else log(DEFAULT,"ERROR! attempted write to a user with no fd_ref_table entry!!!");
        }
 }
 
@@ -2752,7 +2749,7 @@ void ShowMOTD(userrec *user)
        snprintf(buf,65535,":%s 376 %s :End of message of the day.\r\n", ServerName, user->nick);
         WholeMOTD = WholeMOTD + buf;
         // only one write operation
-        send(user->fd,WholeMOTD.c_str(),WholeMOTD.length(),0);
+        user->AddWriteBuf(WholeMOTD);
        statsSent += WholeMOTD.length();
 }
 
@@ -4342,6 +4339,14 @@ int InspIRCd(char** argv, int argc)
                                        // we don't check the state of remote users.
                                        if ((curr->fd != -1) && (curr->fd != FD_MAGIC_NUMBER))
                                        {
+                                               curr->FlushWriteBuf();
+                                               if (curr->GetWriteError() != "")
+                                               {
+                                                       log(DEBUG,"InspIRCd: write error: %s",curr->GetWriteError().c_str());
+                                                       kill_link(curr,curr->GetWriteError().c_str());
+                                                       goto label;
+                                               }
+
                                                FD_SET (curr->fd, &sfd);
 
                                                // registration timeout -- didnt send USER/NICK/HOST in the time specified in
@@ -4400,6 +4405,15 @@ int InspIRCd(char** argv, int argc)
                                        // we don't check the state of remote users.
                                        if ((curr->fd != -1) && (curr->fd != FD_MAGIC_NUMBER))
                                        {
+
+                                                curr->FlushWriteBuf();
+                                                if (curr->GetWriteError() != "")
+                                                {
+                                                        log(DEBUG,"InspIRCd: write error: %s",curr->GetWriteError().c_str());
+                                                        kill_link(curr,curr->GetWriteError().c_str());
+                                                        goto label;
+                                                }
+
                                                // registration timeout -- didnt send USER/NICK/HOST in the time specified in
                                                // their connection class.
                                                if ((TIME > curr->timeout) && (curr->registered != 7))
index fda3c9086795408d990857cf7227d1bcc5b5ac7c..0e79cf496023d8cbbedef47df787400f8e11dbf3 100644 (file)
@@ -54,19 +54,20 @@ Server *Srv;
 class RFC1413
 {
  protected:
-       int fd;                 // file descriptor
-       userrec* u;             // user record that the lookup is associated with
-       sockaddr_in addr;       // address we're connecting to
-       in_addr addy;           // binary ip address
-       int state;              // state (this class operates on a state engine)
-       char ibuf[MAXBUF];      // input buffer
-       sockaddr_in sock_us;    // our port number
-       sockaddr_in sock_them;  // their port number
-       socklen_t uslen;        // length of our port number
-       socklen_t themlen;      // length of their port number
-       int nrecv;              // how many bytes we've received
-       time_t timeout_end;     // how long until the operation times out
-       bool timeout;           // true if we've timed out and should bail
+       int fd;                  // file descriptor
+       userrec* u;              // user record that the lookup is associated with
+       sockaddr_in addr;        // address we're connecting to
+       in_addr addy;            // binary ip address
+       int state;               // state (this class operates on a state engine)
+       char ibuf[MAXBUF];       // input buffer
+       sockaddr_in sock_us;     // our port number
+       sockaddr_in sock_them;   // their port number
+       socklen_t uslen;         // length of our port number
+       socklen_t themlen;       // length of their port number
+       int nrecv;               // how many bytes we've received
+       time_t timeout_end;      // how long until the operation times out
+       bool timeout;            // true if we've timed out and should bail
+       char ident_request[128]; // buffer used to make up the request string
  public:
 
        // The destructor makes damn sure the socket is freed :)
@@ -172,7 +173,8 @@ class RFC1413
                                        else
                                        {
                                                // send the request in the following format: theirsocket,oursocket
-                                               Write(this->fd,"%d,%d",ntohs(sock_them.sin_port),ntohs(sock_us.sin_port));
+                                               snprintf(ident_request,127,"%d,%d\r\n",ntohs(sock_them.sin_port),ntohs(sock_us.sin_port));
+                                               send(this->fd,ident_request,strlen(ident_request),0);
                                                Srv->Log(DEBUG,"Sent ident request, moving to state 2");
                                                state = IDENT_STATE_WAITDATA;
                                        }
index 73e0019aa0040a51956b43801f6e40c539471af4..0e676600edb5b6571a67375644b3e844d7419228 100644 (file)
@@ -47,6 +47,7 @@ userrec::userrec()
        haspassed = false;
        dns_done = false;
        recvq = "";
+       sendq = "";
        strcpy(result,"");
        for (int i = 0; i < MAXCHANS; i++)
        {
@@ -217,3 +218,45 @@ std::string userrec::GetBuffer()
         return ret;
 }
 
+void userrec::AddWriteBuf(std::string data)
+{
+        std::stringstream stream;
+        stream << sendq << data;
+        sendq = stream.str();
+}
+
+// send AS MUCH OF THE USERS SENDQ as we are able to (might not be all of it)
+void userrec::FlushWriteBuf()
+{
+       if (sendq.length())
+       {
+               char* tb = (char*)this->sendq.c_str();
+               int n_sent = write(this->fd,tb,this->sendq.length());
+               if (n_sent == -1)
+               {
+                       this->SetWriteError(strerror(errno));
+               }
+               else
+               {
+                       // advance the queue
+                       tb += n_sent;
+                       this->sendq = tb;
+                       // update the user's stats counters
+                       this->bytes_out += n_sent;
+                       this->cmds_out++;
+               }
+       }
+}
+
+void userrec::SetWriteError(std::string error)
+{
+       log(DEBUG,"Setting error string for %s to '%s'",this->nick,error.c_str());
+       // don't try to set the error twice, its already set take the first string.
+       if (this->WriteError == "")
+               this->WriteError = error;
+}
+
+std::string userrec::GetWriteError()
+{
+       return this->WriteError;
+}