Commit Diff


commit - cddc7e719de391564b9667e734dc15456afec5d8
commit + 302bd8ddafc70c285f41f28eb0280b38e54ae9ec
blob - 44b2020f5445a206bfed0e13b84325c3460f7d04
blob + bb7ae734950c7f1e46608a73bfdd3c07ab095e39
--- ChangeLog
+++ ChangeLog
@@ -10,8 +10,11 @@
                                -- ChangeLog --
 
 
-ngIRCd 0.10.2 (2007-05-05)
+ngIRCd 0.10.2
 
+  - Server links are allowed to use larger write buffers now (up to 50 KB).
+
+  ngIRCd 0.10.2-pre1 (2007-05-05)
   - Fix compressed server links (broken since 0.10.0).
   - Predefined Channel configuration now allows specification of channel key
     (mode k) and maximum user count (mode l).
@@ -685,4 +688,4 @@ ngIRCd 0.0.1, 31.12.2001
 
 
 -- 
-$Id: ChangeLog,v 1.302.2.14 2007/05/05 20:43:11 alex Exp $
+$Id: ChangeLog,v 1.302.2.15 2007/05/18 22:11:18 alex Exp $
blob - 2421e10737b03e4c3cf740012e5c7f5b7c8c0557
blob + 9b1eaf43621488a05795adf944238b77b46e85fa
--- src/ngircd/conn-zip.c
+++ src/ngircd/conn-zip.c
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2006 Alexander Barton (alex@barton.de)
+ * Copyright (c)2001-2007 Alexander Barton (alex@barton.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,7 +22,7 @@
 /* enable more zlib related debug messages: */
 /* #define DEBUG_ZLIB */
 
-static char UNUSED id[] = "$Id: conn-zip.c,v 1.11 2006/07/23 15:19:20 alex Exp $";
+static char UNUSED id[] = "$Id: conn-zip.c,v 1.11.2.1 2007/05/18 22:11:19 alex Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -82,48 +82,64 @@ Zip_InitConn( CONN_ID Idx )
 } /* Zip_InitConn */
 
 
+/**
+ * Copy data to the compression buffer of a connection. We do collect
+ * some data there until it's full so that we can achieve better
+ * compression ratios.
+ * If the (pre-)compression buffer is full, we try to flush it ("actually
+ * compress some data") and to add the new (uncompressed) data afterwards.
+ * @param Idx Connection handle.
+ * @param Data Pointer to the data.
+ * @param Len Length of the data to add.
+ * @return true on success, false otherwise. */
 GLOBAL bool
 Zip_Buffer( CONN_ID Idx, char *Data, size_t Len )
 {
-	/* Daten zum Komprimieren im "Kompressions-Puffer" sammeln.
-	* Es wird true bei Erfolg, sonst false geliefert. */
+	size_t buflen;
 
 	assert( Idx > NONE );
 	assert( Data != NULL );
 	assert( Len > 0 );
-	assert( Len <= ZWRITEBUFFER_LEN );
 
-	if (Len > ZWRITEBUFFER_LEN)
-		return false;
-
-	if ( array_bytes( &My_Connections[Idx].zip.wbuf ) >= ZWRITEBUFFER_LEN ) {
+	buflen = array_bytes(&My_Connections[Idx].zip.wbuf);
+	if (buflen + Len >= WRITEBUFFER_SLINK_LEN) {
 		/* compression buffer is full, flush */
 		if( ! Zip_Flush( Idx )) return false;
 	}
 
+	/* check again; if zip buf is still too large do not append data:
+	 * otherwise the zip wbuf would grow too large */
+	buflen = array_bytes(&My_Connections[Idx].zip.wbuf);
+	if (buflen + Len >= WRITEBUFFER_SLINK_LEN)
+		return false;
+
 	return array_catb(&My_Connections[Idx].zip.wbuf, Data, Len);
 } /* Zip_Buffer */
 
 
+/**
+ * Compress data in ZIP buffer and move result to the write buffer of
+ * the connection.
+ * @param Idx Connection handle.
+ * @retrun true on success, false otherwise.
+ */
 GLOBAL bool
 Zip_Flush( CONN_ID Idx )
 {
-	/* Daten komprimieren und in Schreibpuffer kopieren.
-	* Es wird true bei Erfolg, sonst false geliefert. */
-
 	int result;
-	unsigned char zipbuf[WRITEBUFFER_LEN];
+	unsigned char zipbuf[WRITEBUFFER_SLINK_LEN];
 	int zipbuf_used = 0;
 	z_stream *out;
 
 	out = &My_Connections[Idx].zip.out;
 
-	out->next_in = array_start(&My_Connections[Idx].zip.wbuf);
-	if (!out->next_in)
-		return false;
-
 	out->avail_in = (uInt)array_bytes(&My_Connections[Idx].zip.wbuf);
+	if (!out->avail_in)
+		return true;	/* nothing to do. */
 
+	out->next_in = array_start(&My_Connections[Idx].zip.wbuf);
+	assert(out->next_in != NULL);
+
 	out->next_out = zipbuf;
 	out->avail_out = (uInt)sizeof zipbuf;
 
@@ -139,14 +155,26 @@ Zip_Flush( CONN_ID Idx )
 		return false;
 	}
 
-	assert(out->avail_out <= WRITEBUFFER_LEN);
-	zipbuf_used = WRITEBUFFER_LEN - out->avail_out;
+	if (out->avail_out <= 0) {
+		/* Not all data was compressed, because data became
+		 * bigger while compressing it. */
+		Log (LOG_ALERT, "Compression error: buffer overvlow!?");
+		Conn_Close(Idx, "Compression error!", NULL, false);
+		return false;
+	}
+
+	assert(out->avail_out <= WRITEBUFFER_SLINK_LEN);
+
+	zipbuf_used = WRITEBUFFER_SLINK_LEN - out->avail_out;
 #ifdef DEBUG_ZIP
 	Log(LOG_DEBUG, "zipbuf_used: %d", zipbuf_used);
 #endif
 	if (!array_catb(&My_Connections[Idx].wbuf,
-			(char *)zipbuf, (size_t) zipbuf_used))
+			(char *)zipbuf, (size_t) zipbuf_used)) {
+		Log (LOG_ALERT, "Compression error: can't copy data!?");
+		Conn_Close(Idx, "Compression error!", NULL, false);
 		return false;
+	}
 
 	My_Connections[Idx].bytes_out += zipbuf_used;
 	My_Connections[Idx].zip.bytes_out += array_bytes(&My_Connections[Idx].zip.wbuf); 
@@ -178,10 +206,9 @@ Unzip_Buffer( CONN_ID Idx )
 		return true;
 
 	in = &My_Connections[Idx].zip.in;
-	
+
 	in->next_in = array_start(&My_Connections[Idx].zip.rbuf);
-	if (!in->next_in)
-		return false;
+	assert(in->next_in != NULL);
 
 	in->avail_in = z_rdatalen;
 	in->next_out = unzipbuf;
blob - 3333b31bd24c5e37940479f5316786e8d2852654
blob + 53d6f6e15d0fadd181c8fdb46e4eaa4aa8a474cc
--- src/ngircd/conn.c
+++ src/ngircd/conn.c
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2005 Alexander Barton <alex@barton.de>
+ * Copyright (c)2001-2007 Alexander Barton (alex@barton.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -17,7 +17,7 @@
 #include "portab.h"
 #include "io.h"
 
-static char UNUSED id[] = "$Id: conn.c,v 1.198.2.5 2007/05/09 13:21:38 fw Exp $";
+static char UNUSED id[] = "$Id: conn.c,v 1.198.2.6 2007/05/18 22:11:19 alex Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -609,56 +609,75 @@ va_dcl
 
 
 /**
- * Append Data to outbound write buf.
- * @param Idx Index fo the connection.
- * @param Data pointer to data
- * @param Len length of Data
+ * Append Data to the outbound write buffer of a connection.
+ * @param Idx Index of the connection.
+ * @param Data pointer to the data.
+ * @param Len length of Data.
  * @return true on success, false otherwise.
  */
 static bool
 Conn_Write( CONN_ID Idx, char *Data, size_t Len )
 {
-
+	CLIENT *c;
+	size_t writebuf_limit = WRITEBUFFER_LEN;
 	assert( Idx > NONE );
 	assert( Data != NULL );
 	assert( Len > 0 );
 
+	c = Conn_GetClient(Idx);
+	assert( c != NULL);
+
+	/* Servers do get special write buffer limits, so they can generate
+	 * all the messages that are required while peering. */
+	if (Client_Type(c) == CLIENT_SERVER)
+		writebuf_limit = WRITEBUFFER_SLINK_LEN;
+
 	/* Is the socket still open? A previous call to Conn_Write()
 	 * may have closed the connection due to a fatal error.
-	 * In this case it is sufficient to return an error */
+	 * In this case it is sufficient to return an error, as well. */
 	if( My_Connections[Idx].sock <= NONE ) {
-		LogDebug("Skipped write on closed socket (connection %d).", Idx );
+		LogDebug("Skipped write on closed socket (connection %d).", Idx);
 		return false;
 	}
 
-	/* check if outbound buffer has enough space for data.
-	 * the idea is to keep data buffered  before sending, e.g. to improve
-	 * compression */
-	if( array_bytes(&My_Connections[Idx].wbuf) >= WRITEBUFFER_LEN) {
-		/* Buffer is full, flush. Handle_Write deals with low-level errors, if any. */
-		if( ! Handle_Write( Idx )) return false;
-
-		/* check again: if our writebuf is twice als large as the initial limit: Kill connection */
-		if( array_bytes(&My_Connections[Idx].wbuf) >= (WRITEBUFFER_LEN*2)) {
-			Log(LOG_NOTICE, "Write buffer overflow (connection %d, size %lu byte)!", Idx,
-					(unsigned long) array_bytes(&My_Connections[Idx].wbuf));
-			Conn_Close( Idx, "Write buffer overflow!", NULL, false );
-			return false;
-		}
-	}
-
 #ifdef ZLIB
 	if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ZIP )) {
-		/* compress and move data to write buffer */
-		if( ! Zip_Buffer( Idx, Data, Len )) return false;
+		/* Compressed link:
+		 * Zip_Buffer() does all the dirty work for us: it flushes
+		 * the (pre-)compression buffers if required and handles
+		 * all error conditions. */
+		if (!Zip_Buffer(Idx, Data, Len))
+			return false;
 	}
 	else
 #endif
 	{
-		/* copy data to write buffer */
-		if (!array_catb( &My_Connections[Idx].wbuf, Data, Len ))
+		/* Uncompressed link:
+		 * Check if outbound buffer has enough space for the data. */
+		if (array_bytes(&My_Connections[Idx].wbuf) + Len >=
+		    writebuf_limit) {
+			/* Buffer is full, flush it. Handle_Write deals with
+			 * low-level errors, if any. */
+			if (!Handle_Write(Idx))
+				return false;
+		}
+
+		/* When the write buffer is still too big after flushing it,
+		 * the connection will be killed. */
+		if (array_bytes(&My_Connections[Idx].wbuf) + Len >=
+		    writebuf_limit) {
+			Log(LOG_NOTICE,
+			    "Write buffer overflow (connection %d, size %lu byte)!",
+			    Idx,
+			    (unsigned long)array_bytes(&My_Connections[Idx].wbuf));
+			Conn_Close(Idx, "Write buffer overflow!", NULL, false);
 			return false;
+		}
 
+		/* Copy data to write buffer */
+		if (!array_catb(&My_Connections[Idx].wbuf, Data, Len))
+			return false;
+
 		My_Connections[Idx].bytes_out += Len;
 	}
 
@@ -868,24 +887,23 @@ Handle_Write( CONN_ID Idx )
 	wdatalen = array_bytes(&My_Connections[Idx].wbuf );
 
 #ifdef ZLIB
-	if (wdatalen == 0 && !array_bytes(&My_Connections[Idx].zip.wbuf)) {
-		io_event_del(My_Connections[Idx].sock, IO_WANTWRITE );
-		return true;
+	if (wdatalen == 0) {
+		/* Write buffer is empty, so we try to flush the compression
+		 * buffer and get some data to work with from there :-) */
+		if (!Zip_Flush(Idx))
+			return false;
+
+		/* Now the write buffer most probably has changed: */
+		wdatalen = array_bytes(&My_Connections[Idx].wbuf);
 	}
+#endif
 
-	/* write buffer empty, but not compression buffer?
-         * -> flush compression buffer! */
-	if (wdatalen == 0)
-		Zip_Flush(Idx);
-#else
 	if (wdatalen == 0) {
+		/* Still no data, fine. */
 		io_event_del(My_Connections[Idx].sock, IO_WANTWRITE );
 		return true;
 	}
-#endif
 
-	/* Zip_Flush() may have changed the write buffer ... */
-	wdatalen = array_bytes(&My_Connections[Idx].wbuf);
 	LogDebug
 	    ("Handle_Write() called for connection %d, %ld bytes pending ...",
 	     Idx, wdatalen);
@@ -1047,47 +1065,52 @@ Socket2Index( int Sock )
 } /* Socket2Index */
 
 
+/**
+ * Read data from the network to the read buffer. If an error occures,
+ * the socket of this connection will be shut down.
+ */
 static void
 Read_Request( CONN_ID Idx )
 {
-	/* Daten von Socket einlesen und entsprechend behandeln.
-	 * Tritt ein Fehler auf, so wird der Socket geschlossen. */
-
 	ssize_t len;
-	char readbuf[1024];
+	char readbuf[READBUFFER_LEN];
 	CLIENT *c;
-
 	assert( Idx > NONE );
 	assert( My_Connections[Idx].sock > NONE );
 
 #ifdef ZLIB
-	if (( array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN ) ||
-		( array_bytes(&My_Connections[Idx].zip.rbuf) >= ZREADBUFFER_LEN ))
+	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) >= READBUFFER_LEN )
+	if (array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN)
 #endif
 	{
-		/* Der Lesepuffer ist voll */
-		Log( LOG_ERR, "Receive buffer overflow (connection %d): %d bytes!", Idx,
-						array_bytes(&My_Connections[Idx].rbuf));
+		/* Read buffer is full */
+		Log(LOG_ERR,
+		    "Receive buffer overflow (connection %d): %d bytes!",
+		    Idx, array_bytes(&My_Connections[Idx].rbuf));
 		Conn_Close( Idx, "Receive buffer overflow!", NULL, false );
 		return;
 	}
 
-	len = read( My_Connections[Idx].sock, readbuf, sizeof readbuf -1 );
-	if( len == 0 ) {
-		Log( LOG_INFO, "%s:%d (%s) is closing the connection ...",
-			My_Connections[Idx].host, ntohs( My_Connections[Idx].addr.sin_port),
-					inet_ntoa( My_Connections[Idx].addr.sin_addr ));
-		Conn_Close( Idx, "Socket closed!", "Client closed connection", false );
+	len = read(My_Connections[Idx].sock, readbuf, sizeof(readbuf));
+	if (len == 0) {
+		Log(LOG_INFO, "%s:%d (%s) is closing the connection ...",
+		    My_Connections[Idx].host,
+		    ntohs(My_Connections[Idx].addr.sin_port),
+		    inet_ntoa( My_Connections[Idx].addr.sin_addr));
+		Conn_Close(Idx,
+			   "Socket closed!", "Client closed connection",
+			   false);
 		return;
 	}
 
-	if( len < 0 ) {
+	if (len < 0) {
 		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 );
+		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;
 	}
 #ifdef ZLIB
@@ -1223,11 +1246,6 @@ Handle_Buffer( CONN_ID Idx )
 			/* The last Command activated Socket-Compression.
 			 * Data that was read after that needs to be copied to Unzip-buf
 			 * for decompression */
-			if( array_bytes(&My_Connections[Idx].rbuf)> ZREADBUFFER_LEN ) {
-				Log( LOG_ALERT, "Connection %d: No space left in unzip buf (need %u bytes)!",
-								Idx, array_bytes(&My_Connections[Idx].rbuf ));
-				return false;
-			}
 			if (!array_copy( &My_Connections[Idx].zip.rbuf, &My_Connections[Idx].rbuf ))
 				return false;
 
blob - 5f98e806b806754f9abc0b70ae317b757d2bdf09
blob + 3cfe2f7dea57b8c80e066ced2f4f5772224ee959
--- src/ngircd/defines.h
+++ src/ngircd/defines.h
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2005 Alexander Barton (alex@barton.de)
+ * Copyright (c)2001-2007 Alexander Barton (alex@barton.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  *
- * $Id: defines.h,v 1.58 2006/06/15 20:28:15 alex Exp $
+ * $Id: defines.h,v 1.58.2.1 2007/05/18 22:11:19 alex Exp $
  */
 
 
@@ -70,14 +70,9 @@
 					   connection in bytes. */
 #define WRITEBUFFER_LEN 4096		/* Size of the write buffer of a
 					   connection in bytes. */
+#define WRITEBUFFER_SLINK_LEN 51200	/* Size of the write buffer of a
+					   server link connection in bytes. */
 
-#ifdef ZLIB
-#define ZREADBUFFER_LEN 1024		/* Size of the compressed read buffer
-					   of a connection in bytes. */
-#define ZWRITEBUFFER_LEN 4096		/* Size of the compressed write buffer
-					   of a connection in bytes. */
-#endif
-
 #define PROTOVER "0210"			/* Implemented IRC protocol version,
 					   see RFC 2813 section 4.1.1. */
 #define PROTOIRC "-IRC"			/* Protocol suffix, see RFC 2813