+ /* pruefen, ob Daten im Schreibpuffer sind. Wenn ja, zunaechst
+ * pruefen, ob diese gesendet werden koennen */
+ if( My_Connections[Idx].wdatalen > 0 )
+ {
+ if( ! Try_Write( Idx )) return FALSE;
+ }
+
+ /* pruefen, ob im Schreibpuffer genuegend Platz ist */
+ if( WRITEBUFFER_LEN - My_Connections[Idx].wdatalen - Len <= 0 )
+ {
+ /* der Puffer ist dummerweise voll ... */
+ Log( LOG_NOTICE, "Write buffer overflow (connection %d)!", Idx );
+ Conn_Close( Idx, "Write buffer overflow!", NULL, FALSE );
+ return FALSE;
+ }
+
+ /* Daten in Puffer kopieren */
+ memcpy( My_Connections[Idx].wbuf + My_Connections[Idx].wdatalen, Data, Len );
+ My_Connections[Idx].wdatalen += Len;
+
+ /* pruefen, on Daten vorhanden sind und geschrieben werden koennen */
+ if( My_Connections[Idx].wdatalen > 0 )
+ {
+ if( ! Try_Write( Idx )) return FALSE;
+ }
+
+ return TRUE;
+} /* Conn_Write */
+
+
+GLOBAL VOID
+Conn_Close( CONN_ID Idx, CHAR *LogMsg, CHAR *FwdMsg, BOOLEAN InformClient )
+{
+ /* Verbindung schliessen. Evtl. noch von Resolver
+ * Sub-Prozessen offene Pipes werden geschlossen. */
+
+ CLIENT *c;
+
+ assert( Idx >= 0 );
+ assert( My_Connections[Idx].sock > NONE );
+
+ if( InformClient )
+ {
+ if( FwdMsg ) Conn_WriteStr( Idx, "ERROR :%s", FwdMsg );
+ else Conn_WriteStr( Idx, "ERROR :Closing connection." );
+ if( My_Connections[Idx].sock == NONE ) return;
+ }
+
+ if( close( My_Connections[Idx].sock ) != 0 )
+ {
+ Log( LOG_ERR, "Error closing connection %d with %s:%d - %s!", Idx, inet_ntoa( My_Connections[Idx].addr.sin_addr ), ntohs( My_Connections[Idx].addr.sin_port), strerror( errno ));
+ }
+ else
+ {
+ Log( LOG_INFO, "Connection %d with %s:%d closed.", Idx, inet_ntoa( My_Connections[Idx].addr.sin_addr ), ntohs( My_Connections[Idx].addr.sin_port ));
+ }
+
+ c = Client_GetFromConn( Idx );
+ if( c ) Client_Destroy( c, LogMsg, FwdMsg, TRUE );
+
+ if( My_Connections[Idx].res_stat )
+ {
+ /* Resolver-Strukturen freigeben, wenn noch nicht geschehen */
+ FD_CLR( My_Connections[Idx].res_stat->pipe[0], &Resolver_FDs );
+ close( My_Connections[Idx].res_stat->pipe[0] );
+ close( My_Connections[Idx].res_stat->pipe[1] );
+ free( My_Connections[Idx].res_stat );
+ }
+
+ /* Bei Server-Verbindungen lasttry-Zeitpunkt so setzen, dass
+ * der naechste Verbindungsversuch in RECONNECT_DELAY Sekunden
+ * gestartet wird. */
+ if(( My_Connections[Idx].our_server >= 0 ) && ( Conf_Server[My_Connections[Idx].our_server].lasttry < time( NULL )))
+ {
+ /* Okay, die Verbindung stand schon "genuegend lange" */
+ Conf_Server[My_Connections[Idx].our_server].lasttry = time( NULL ) - Conf_ConnectRetry + RECONNECT_DELAY;
+ }
+
+ FD_CLR( My_Connections[Idx].sock, &My_Sockets );
+ FD_CLR( My_Connections[Idx].sock, &My_Connects );
+ My_Connections[Idx].sock = NONE;
+} /* Conn_Close */
+
+
+GLOBAL VOID
+Conn_UpdateIdle( CONN_ID Idx )
+{
+ /* Idle-Timer zuruecksetzen */
+
+ assert( Idx >= 0 );
+ My_Connections[Idx].lastprivmsg = time( NULL );
+}
+
+
+GLOBAL time_t
+Conn_GetIdle( CONN_ID Idx )
+{
+ /* Idle-Time einer Verbindung liefern (in Sekunden) */
+
+ assert( Idx >= 0 );
+ return time( NULL ) - My_Connections[Idx].lastprivmsg;
+} /* Conn_GetIdle */
+
+
+GLOBAL time_t
+Conn_LastPing( CONN_ID Idx )
+{
+ /* Zeitpunkt des letzten PING liefern */
+
+ assert( Idx >= 0 );
+ return My_Connections[Idx].lastping;
+} /* Conn_LastPing */
+
+
+LOCAL BOOLEAN
+Try_Write( CONN_ID Idx )
+{
+ /* Versuchen, Daten aus dem Schreib-Puffer in den
+ * Socket zu schreiben. */
+
+ fd_set write_socket;
+
+ assert( Idx >= 0 );
+ assert( My_Connections[Idx].sock > NONE );
+ assert( My_Connections[Idx].wdatalen > 0 );
+
+ FD_ZERO( &write_socket );
+ FD_SET( My_Connections[Idx].sock, &write_socket );
+ if( select( My_Connections[Idx].sock + 1, NULL, &write_socket, NULL, 0 ) == -1 )
+ {
+ /* Fehler! */
+ if( errno != EINTR )
+ {
+ Log( LOG_ALERT, "select() failed: %s!", strerror( errno ));
+ Conn_Close( Idx, "Server error!", NULL, FALSE );
+ return FALSE;
+ }
+ }
+
+ if( FD_ISSET( My_Connections[Idx].sock, &write_socket )) return Handle_Write( Idx );
+ else return TRUE;
+} /* Try_Write */
+
+
+LOCAL VOID
+Handle_Read( INT Sock )
+{
+ /* Aktivitaet auf einem Socket verarbeiten:
+ * - neue Clients annehmen,
+ * - Daten von Clients verarbeiten,
+ * - Resolver-Rueckmeldungen annehmen. */
+
+ CONN_ID idx;
+
+ assert( Sock >= 0 );
+
+ if( FD_ISSET( Sock, &My_Listeners ))