]> arthur.barton.de Git - ngircd-alex.git/blobdiff - src/ngircd/conn.c
- Verbindungen mit Lesefehlern werden nun korrekt terminiert.
[ngircd-alex.git] / src / ngircd / conn.c
index af12162c272f1c2c8c3254bcf5f8cce447562c8f..70b4cf7df4c2b3fe8e27f49f1659e48d37b6b0fd 100644 (file)
@@ -9,11 +9,17 @@
  * 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.13 2001/12/26 03:36:57 alex Exp $
  *
  * connect.h: Verwaltung aller Netz-Verbindungen ("connections")
  *
  * $Log: conn.c,v $
+ * 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.
  *
@@ -72,6 +78,7 @@
 #include <sys/socket.h>
 #include <sys/time.h>
 #include <sys/types.h>
+#include <time.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
@@ -81,6 +88,7 @@
 
 #include "ngircd.h"
 #include "client.h"
+#include "conf.h"
 #include "log.h"
 #include "parse.h"
 #include "tool.h"
@@ -105,6 +113,8 @@ typedef struct _Connection
        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;
 
 
@@ -115,6 +125,7 @@ LOCAL CONN_ID Socket2Index( INT Sock );
 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;
@@ -240,34 +251,36 @@ 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 )
                {
@@ -509,6 +522,8 @@ LOCAL VOID New_Connection( INT 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 );
@@ -559,10 +574,11 @@ LOCAL VOID Read_Request( CONN_ID Idx )
        {
                /* 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';
@@ -577,6 +593,9 @@ LOCAL VOID Read_Request( CONN_ID Idx )
                return;
        }
 
+       /* Timestamp aktualisieren */
+       My_Connections[Idx].lastdata = time( NULL );
+
        Handle_Buffer( Idx );
 } /* Read_Request */
 
@@ -622,4 +641,36 @@ LOCAL VOID Handle_Buffer( CONN_ID Idx )
 } /* 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_PONG_Timeout )
+                               {
+                                       /* Timeout */
+                                       Log( LOG_NOTICE, "Connection %d: Ping timeout." );
+                                       Conn_Close( i, "Ping timeout" );
+                               }
+                       }
+                       else if( My_Connections[i].lastdata < time( NULL ) - Conf_PING_Timeout )
+                       {
+                               /* 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- */