]> arthur.barton.de Git - ngircd.git/blobdiff - src/ngircd/conn.c
Handle commands in the read buffer before reading more data
[ngircd.git] / src / ngircd / conn.c
index ef0f95fa73e8912d8e349d7c0ba71c5bd81c836d..ca7030f4ebae1e487910310da2278e96f8287252 100644 (file)
@@ -734,6 +734,18 @@ Conn_Handler(void)
                                continue;
                        }
 
+                       if (array_bytes(&My_Connections[i].rbuf) >= COMMAND_LEN) {
+                               /* There is still more data in the read buffer
+                                * than a single valid command can get long:
+                                * so either there is a complete command, or
+                                * invalid data. Therefore don't try to read in
+                                * even more data from the network but wait for
+                                * this command(s) to be handled first! */
+                               io_event_del(My_Connections[i].sock,
+                                            IO_WANTREAD);
+                               continue;
+                       }
+
                        io_event_add(My_Connections[i].sock, IO_WANTREAD);
                }
 
@@ -1543,49 +1555,43 @@ Socket2Index( int Sock )
  * @param Idx  Connection index.
  */
 static void
-Read_Request( CONN_ID Idx )
+Read_Request(CONN_ID Idx)
 {
        ssize_t len;
-       size_t readbuf_limit = READBUFFER_LEN;
        static const unsigned int maxbps = COMMAND_LEN / 2;
-       char readbuf[READBUFFER_MAX_LEN];
+       char readbuf[READBUFFER_LEN];
        time_t t;
        CLIENT *c;
-       assert( Idx > NONE );
-       assert( My_Connections[Idx].sock > NONE );
 
-       /* Make sure that there still exists a CLIENT structure associated
-        * with this connection and check if this is a server or not: */
-       c = Conn_GetClient(Idx);
-       if (c) {
-               /* Servers do get special read buffer limits, so they can
-                * process all the messages that are required while peering. */
-               if (Client_Type(c) == CLIENT_SERVER)
-                       readbuf_limit = READBUFFER_SLINK_LEN;
-       } else
-               LogDebug("Read request without client (connection %d)!?", Idx);
+       assert(Idx > NONE);
+       assert(My_Connections[Idx].sock > NONE);
 
+       /* Check if the read buffer is "full". Basically this shouldn't happen
+        * here, because as long as there possibly are commands in the read
+        * buffer (buffer usage > COMMAND_LEN), the socket shouldn't be
+        * scheduled for reading in Conn_Handler() at all ... */
 #ifdef ZLIB
-       if ((array_bytes(&My_Connections[Idx].rbuf) >= readbuf_limit) ||
-               (array_bytes(&My_Connections[Idx].zip.rbuf) >= readbuf_limit))
+       if ((array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN) ||
+               (array_bytes(&My_Connections[Idx].zip.rbuf) >= READBUFFER_LEN))
 #else
-       if (array_bytes(&My_Connections[Idx].rbuf) >= readbuf_limit)
+       if (array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN)
 #endif
        {
-               /* Read buffer is full */
                Log(LOG_ERR,
                    "Receive buffer space exhausted (connection %d): %d/%d bytes",
-                   Idx, array_bytes(&My_Connections[Idx].rbuf), readbuf_limit);
+                   Idx, array_bytes(&My_Connections[Idx].rbuf), READBUFFER_LEN);
                Conn_Close(Idx, "Receive buffer space exhausted", NULL, false);
                return;
        }
 
+       /* Now read new data from the network, up to READBUFFER_LEN bytes ... */
 #ifdef SSL_SUPPORT
        if (Conn_OPTION_ISSET(&My_Connections[Idx], CONN_SSL))
-               len = ConnSSL_Read( &My_Connections[Idx], readbuf, readbuf_limit);
+               len = ConnSSL_Read(&My_Connections[Idx], readbuf, sizeof(readbuf));
        else
 #endif
-       len = read(My_Connections[Idx].sock, readbuf, readbuf_limit);
+               len = read(My_Connections[Idx].sock, readbuf, sizeof(readbuf));
+
        if (len == 0) {
                LogDebug("Client \"%s:%u\" is closing connection %d ...",
                         My_Connections[Idx].host,
@@ -1595,13 +1601,20 @@ Read_Request( CONN_ID Idx )
        }
 
        if (len < 0) {
-               if( errno == EAGAIN ) return;
+               if (errno == EAGAIN)
+                       return;
+
                Log(LOG_ERR, "Read error on connection %d (socket %d): %s!",
                    Idx, My_Connections[Idx].sock, strerror(errno));
                Conn_Close(Idx, "Read error", "Client closed connection",
                           false);
                return;
        }
+
+       /* Now append the newly received data to the connection buffer.
+        * NOTE: This can lead to connection read buffers being bigger(!) than
+        * READBUFFER_LEN bytes, as we add up to READBUFFER_LEN new bytes to a
+        * buffer possibly being "almost" READBUFFER_LEN bytes already! */
 #ifdef ZLIB
        if (Conn_OPTION_ISSET(&My_Connections[Idx], CONN_ZIP)) {
                if (!array_catb(&My_Connections[Idx].zip.rbuf, readbuf,