* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an comBase beteiligten Autoren finden Sie in der Datei AUTHORS.
*
- * $Id: conn.c,v 1.11 2001/12/25 23:15:16 alex Exp $
+ * $Id: conn.c,v 1.15 2001/12/27 16:35:04 alex Exp $
*
* connect.h: Verwaltung aller Netz-Verbindungen ("connections")
*
* $Log: conn.c,v $
+ * Revision 1.15 2001/12/27 16:35:04 alex
+ * - vergessene Variable bei Ping-Timeout-Logmeldung ergaenzt. Opsa.
+ *
+ * Revision 1.14 2001/12/26 14:45:37 alex
+ * - "Code Cleanups".
+ *
+ * Revision 1.13 2001/12/26 03:36:57 alex
+ * - Verbindungen mit Lesefehlern werden nun korrekt terminiert.
+ *
+ * Revision 1.12 2001/12/26 03:20:53 alex
+ * - PING/PONG-Timeout implementiert.
+ *
* Revision 1.11 2001/12/25 23:15:16 alex
* - buffer werden nun periodisch geprueft, keine haengenden Clients mehr.
*
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "ngircd.h"
#include "client.h"
+#include "conf.h"
#include "log.h"
#include "parse.h"
#include "tool.h"
INT rdatalen; /* Laenge der Daten im Lesepuffer */
CHAR wbuf[WRITEBUFFER_LEN + 1]; /* Schreibpuffer */
INT wdatalen; /* Laenge der Daten im Schreibpuffer */
+ time_t lastdata; /* Letzte Aktivitaet */
+ time_t lastping; /* Letzter PING */
} CONNECTION;
LOCAL VOID Read_Request( CONN_ID Idx );
LOCAL BOOLEAN Try_Write( CONN_ID Idx );
LOCAL VOID Handle_Buffer( CONN_ID Idx );
+LOCAL VOID Check_Connections( VOID );
LOCAL fd_set My_Listener;
} /* Conn_Exit */
-GLOBAL BOOLEAN Conn_New_Listener( CONST INT Port )
+GLOBAL BOOLEAN Conn_NewListener( CONST INT Port )
{
/* Neuen Listen-Socket erzeugen: der Server wartet dann
* auf dem angegebenen Port auf Verbindungen. */
Log( LOG_INFO, "Now listening on port %d, socket %d.", Port, sock );
return TRUE;
-} /* Conn_New_Listener */
+} /* Conn_NewListener */
GLOBAL VOID Conn_Handler( INT Timeout )
time_t start;
INT i;
- /* Timeout initialisieren */
- tv.tv_sec = 0;
- tv.tv_usec = 50000;
-
start = time( NULL );
- while( time( NULL ) - start < Timeout )
+ while(( time( NULL ) - start < Timeout ) && ( ! NGIRCd_Quit ))
{
- /* noch volle Schreib-Puffer suchen */
- FD_ZERO( &write_sockets );
+ Check_Connections( );
+
+ /* Timeout initialisieren */
+ tv.tv_sec = 0;
+ tv.tv_usec = 50000;
+
+ /* noch volle Lese-Buffer suchen */
for( i = 0; i < MAX_CONNECTIONS; i++ )
{
- if(( My_Connections[i].sock >= 0 ) && ( My_Connections[i].wdatalen > 0 ))
+ if(( My_Connections[i].sock >= 0 ) && ( My_Connections[i].rdatalen > 0 ))
{
- /* Socket der Verbindung in Set aufnehmen */
- FD_SET( My_Connections[i].sock, &write_sockets );
+ /* Kann aus dem Buffer noch ein Befehl extrahiert werden? */
+ Handle_Buffer( i );
}
}
- /* noch volle Lese-Buffer suchen */
+ /* noch volle Schreib-Puffer suchen */
+ FD_ZERO( &write_sockets );
for( i = 0; i < MAX_CONNECTIONS; i++ )
{
- if(( My_Connections[i].sock >= 0 ) && ( My_Connections[i].rdatalen > 0 ))
+ if(( My_Connections[i].sock >= 0 ) && ( My_Connections[i].wdatalen > 0 ))
{
- /* Kann aus dem Buffer noch ein Befehl extrahiert werden? */
- Handle_Buffer( i );
+ /* Socket der Verbindung in Set aufnehmen */
+ FD_SET( My_Connections[i].sock, &write_sockets );
}
}
-
+
read_sockets = My_Sockets;
if( select( My_Max_Fd + 1, &read_sockets, &write_sockets, NULL, &tv ) == -1 )
{
}
/* Client-Struktur initialisieren */
- if( ! Client_New_Local( idx, inet_ntoa( new_addr.sin_addr )))
+ if( ! Client_NewLocal( idx, inet_ntoa( new_addr.sin_addr )))
{
Log( LOG_ALERT, "Can't accept connection: can't create client structure!" );
close( new_sock );
My_Connections[idx].addr = new_addr;
My_Connections[idx].rdatalen = 0;
My_Connections[idx].wdatalen = 0;
+ My_Connections[idx].lastdata = time( NULL );
+ My_Connections[idx].lastping = 0;
/* Neuen Socket registrieren */
FD_SET( new_sock, &My_Sockets );
{
/* Fehler beim Lesen */
Log( LOG_ALERT, "Read error on connection %d: %s!", Idx, strerror( errno ));
- Conn_Close( Idx, "Read error!" );
+ Conn_Close( Idx, NULL );
return;
}
+ /* Lesebuffer updaten */
My_Connections[Idx].rdatalen += len;
assert( My_Connections[Idx].rdatalen <= READBUFFER_LEN );
My_Connections[Idx].rbuf[My_Connections[Idx].rdatalen] = '\0';
return;
}
+ /* Timestamp aktualisieren */
+ My_Connections[Idx].lastdata = time( NULL );
+
Handle_Buffer( Idx );
} /* Read_Request */
} /* Handle_Buffer */
+LOCAL VOID Check_Connections( VOID )
+{
+ /* Pruefen, ob Verbindungen noch "alive" sind */
+
+ INT i;
+
+ for( i = 0; i < MAX_CONNECTIONS; i++ )
+ {
+ if( My_Connections[i].sock != NONE )
+ {
+ if( My_Connections[i].lastping > My_Connections[i].lastdata )
+ {
+ /* es wurde bereits ein PING gesendet */
+ if( My_Connections[i].lastping < time( NULL ) - Conf_PongTimeout )
+ {
+ /* Timeout */
+ Log( LOG_NOTICE, "Connection %d: Ping timeout.", i );
+ Conn_Close( i, "Ping timeout" );
+ }
+ }
+ else if( My_Connections[i].lastdata < time( NULL ) - Conf_PingTimeout )
+ {
+ /* es muss ein PING gesendet werden */
+ Log( LOG_DEBUG, "Connection %d: sending PING ...", i );
+ My_Connections[i].lastping = time( NULL );
+ Conn_WriteStr( i, "PING :%s", This_Server->nick );
+ }
+ }
+ }
+} /* Conn_Check */
+
+
/* -eof- */