#include "portab.h"
#include "io.h"
-static char UNUSED id[] = "$Id: conn.c,v 1.200 2006/12/17 23:04:45 fw Exp $";
+static char UNUSED id[] = "$Id: conn.c,v 1.207 2007/05/09 13:21:11 fw Exp $";
#include "imp.h"
#include <assert.h>
static bool Handle_Write PARAMS(( CONN_ID Idx ));
+static bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, size_t Len ));
static int New_Connection PARAMS(( int Sock ));
static CONN_ID Socket2Index PARAMS(( int Sock ));
static void Read_Request PARAMS(( CONN_ID Idx ));
{
int res, err;
socklen_t sock_len;
- CLIENT *c;
CONN_ID idx = Socket2Index( sock );
if (idx <= NONE) {
LogDebug("cb_connserver wants to write on unknown socket?!");
Conf_Server[Conf_GetServer(idx)].port,
idx, strerror(err));
- /* Clean up the CLIENT structure (to avoid silly log
- * messages) and call Conn_Close() to do the rest. */
- c = Conn_GetClient(idx);
- if (c)
- Client_DestroyNow(c);
-
- Conn_Close(idx, "Can't connect!", NULL, false);
-
+ Conn_Close(idx, "Can't connect!", NULL, false);
return;
}
} /* Conn_Exit */
-static int
+static unsigned int
ports_initlisteners(array *a, void (*func)(int,short))
{
- int created = 0;
+ unsigned int created = 0;
size_t len;
int fd;
UINT16 *port;
}
-GLOBAL int
+GLOBAL unsigned int
Conn_InitListeners( void )
{
/* Initialize ports on which the server should accept connections */
- int created;
+ unsigned int created;
if (!io_library_init(CONNECTION_POOL)) {
Log(LOG_EMERG, "Cannot initialize IO routines: %s", strerror(errno));
if( ! Init_Socket( sock )) return -1;
if (bind(sock, (struct sockaddr *)&addr, (socklen_t)sizeof(addr)) != 0) {
- Log( LOG_CRIT, "Can't bind socket: %s!", strerror( errno ));
+ Log( LOG_CRIT, "Can't bind socket (port %d) : %s!", Port, strerror( errno ));
close( sock );
return -1;
}
} /* Conn_WriteStr */
-GLOBAL bool
+/**
+ * Append Data to outbound write buf.
+ * @param Idx Index fo the connection.
+ * @param Data pointer to data
+ * @param Len length of Data
+ * @return true on success, false otherwise.
+ */
+static bool
Conn_Write( CONN_ID Idx, char *Data, size_t Len )
{
- /* Daten in Socket schreiben. Bei "fatalen" Fehlern wird
- * der Client disconnectiert und false geliefert. */
-
+ CLIENT *c;
+ size_t writebuf_limit = WRITEBUFFER_LEN;
assert( Idx > NONE );
assert( Data != NULL );
assert( Len > 0 );
- /* Ist der entsprechende Socket ueberhaupt noch offen? In einem
- * "Handler-Durchlauf" kann es passieren, dass dem nicht mehr so
- * ist, wenn einer von mehreren Conn_Write()'s fehlgeschlagen ist.
- * In diesem Fall wird hier einfach ein Fehler geliefert. */
+ c = Conn_GetClient(Idx);
+ assert( c != NULL);
+ if (Client_Type(c) == CLIENT_SERVER)
+ writebuf_limit = WRITEBUFFER_LEN * 10;
+ /* 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 */
if( My_Connections[Idx].sock <= NONE ) {
LogDebug("Skipped write on closed socket (connection %d).", Idx );
return false;
}
- /* Pruefen, ob im Schreibpuffer genuegend Platz ist. Ziel ist es,
- * moeglichts viel im Puffer zu haben und _nicht_ gleich alles auf den
- * Socket zu schreiben (u.a. wg. Komprimierung). */
- if( array_bytes(&My_Connections[Idx].wbuf) >= WRITEBUFFER_LEN) {
- /* Der Puffer ist dummerweise voll. Jetzt versuchen, den Puffer
- * zu schreiben, wenn das nicht klappt, haben wir ein Problem ... */
+ /* 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) >= writebuf_limit) {
+ /* 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)!", Idx );
+ if (array_bytes(&My_Connections[Idx].wbuf) >= (writebuf_limit*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 )) {
- /* Daten komprimieren und in Puffer kopieren */
+ /* compress and move data to write buffer */
if( ! Zip_Buffer( Idx, Data, Len )) return false;
}
else
#endif
{
- /* Daten in Puffer kopieren */
+ /* copy data to write buffer */
if (!array_catb( &My_Connections[Idx].wbuf, Data, Len ))
return false;
/* Mark link as "closing" */
Conn_OPTION_ADD( &My_Connections[Idx], CONN_ISCLOSING );
-
+
if (LogMsg)
txt = LogMsg;
else
(double)My_Connections[Idx].bytes_out / 1024);
}
#endif
-
/* Send ERROR to client (see RFC!) */
if (FwdMsg)
Conn_WriteStr(Idx, "ERROR :%s", FwdMsg);
Init_Conn_Struct(Pool_Size++);
}
+ /* register callback */
+ if (!io_event_create( new_sock, IO_WANTREAD, cb_clientserver)) {
+ Log(LOG_ALERT, "Can't accept connection: io_event_create failed!");
+ Simple_Message(new_sock, "ERROR :Internal error");
+ close(new_sock);
+ return -1;
+ }
+
c = Client_NewLocal( new_sock, inet_ntoa( new_addr.sin_addr ), CLIENT_UNKNOWN, false );
if( ! c ) {
- Log( LOG_ALERT, "Can't accept connection: can't create client structure!" );
- Simple_Message( new_sock, "ERROR :Internal error" );
- close( new_sock );
+ Log(LOG_ALERT, "Can't accept connection: can't create client structure!");
+ Simple_Message(new_sock, "ERROR :Internal error");
+ io_close(new_sock);
return -1;
}
My_Connections[new_sock].addr = new_addr;
My_Connections[new_sock].client = c;
- /* register callback */
- if (!io_event_create( new_sock, IO_WANTREAD, cb_clientserver)) {
- Simple_Message( new_sock, "ERROR :Internal error" );
- Conn_Close( new_sock, "io_event_create() failed", NULL, false );
- return -1;
- }
-
Log( LOG_INFO, "Accepted connection %d from %s:%d on socket %d.", new_sock,
inet_ntoa( new_addr.sin_addr ), ntohs( new_addr.sin_port), Sock );
/* Daten von Socket einlesen und entsprechend behandeln.
* Tritt ein Fehler auf, so wird der Socket geschlossen. */
+ size_t readbuf_limit = READBUFFER_LEN;
ssize_t len;
- char readbuf[1024];
+ char readbuf[READBUFFER_LEN];
CLIENT *c;
-
assert( Idx > NONE );
assert( My_Connections[Idx].sock > NONE );
+ c = Conn_GetClient(Idx);
+ assert ( c != NULL);
+ if (Client_Type(c) == CLIENT_SERVER)
+ readbuf_limit = READBUFFER_LEN * 10;
#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) >= readbuf_limit) ||
+ (array_bytes(&My_Connections[Idx].zip.rbuf) >= readbuf_limit))
#else
- if ( array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN )
+ if (array_bytes(&My_Connections[Idx].rbuf) >= readbuf_limit)
#endif
{
/* Der Lesepuffer ist voll */
return;
}
- len = read( My_Connections[Idx].sock, readbuf, sizeof readbuf -1 );
+ 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),
} else
#endif
{
- readbuf[len] = 0;
- if (!array_cats( &My_Connections[Idx].rbuf, readbuf )) {
+ if (!array_catb( &My_Connections[Idx].rbuf, readbuf, len)) {
Log( LOG_ERR, "Could not append recieved data to input buffer (connn %d): %d bytes!", Idx, len );
Conn_Close( Idx, "Receive buffer overflow!", NULL, false );
}
/* 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;
assert( Idx >= 0 );
c = array_get(&My_ConnArray, sizeof (CONNECTION), (size_t)Idx);
-
+
assert(c != NULL);
-
+
return c ? c->client : NULL;
}