commit - 40f07f2f5cb9282d5216c2ac531a9ff8169b468b
commit + 6da91c34b4c525501f403e192a43448c15f23aca
blob - b67d71365a086705f309123cf7f5145ac727e9ee
blob + e60cde71b3d1e1fc0a5461366c7c1c2ba223f3d1
--- src/ngircd/conn.c
+++ src/ngircd/conn.c
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
- * $Id: conn.c,v 1.41 2002/02/27 14:47:04 alex Exp $
+ * $Id: conn.c,v 1.42 2002/03/02 00:23:32 alex Exp $
*
* connect.h: Verwaltung aller Netz-Verbindungen ("connections")
*
* $Log: conn.c,v $
+ * Revision 1.42 2002/03/02 00:23:32 alex
+ * - ausgehende Verbindungen werden nun asyncron connectiert und blockieren
+ * nicht mehr den Server. Dadurch waren einige Aenderungen noetig.
+ * - diverse Log-Meldungen ueberarbeitet.
+ *
* Revision 1.41 2002/02/27 14:47:04 alex
* - Logging bei Timeout von Verbindungen geaendert.
*
LOCAL VOID Check_Connections( VOID );
LOCAL VOID Check_Servers( VOID );
LOCAL VOID Init_Conn_Struct( INT Idx );
+LOCAL BOOLEAN Init_Socket( INT Sock );
LOCAL VOID New_Server( INT Server, CONN_ID Idx );
LOCAL RES_STAT *ResolveAddr( struct sockaddr_in *Addr );
LOCAL fd_set My_Listeners;
LOCAL fd_set My_Sockets;
LOCAL fd_set My_Resolvers;
+LOCAL fd_set My_Connects;
LOCAL INT My_Max_Fd;
FD_ZERO( &My_Listeners );
FD_ZERO( &My_Sockets );
FD_ZERO( &My_Resolvers );
+ FD_ZERO( &My_Connects );
My_Max_Fd = 0;
{
if( My_Connections[idx].sock == i ) break;
}
- if( idx < MAX_CONNECTIONS ) Conn_Close( idx, NULL, "Server going down", TRUE );
- else if( FD_ISSET( i, &My_Listeners ))
+ if( FD_ISSET( i, &My_Listeners ))
{
close( i );
Log( LOG_DEBUG, "Listening socket %d closed.", i );
}
+ else if( FD_ISSET( i, &My_Connects ))
+ {
+ close( i );
+ Log( LOG_DEBUG, "Connection %d closed during creation (socket %d).", idx, i );
+ }
+ else if( idx < MAX_CONNECTIONS ) Conn_Close( idx, NULL, "Server going down", TRUE );
else
{
+ Log( LOG_WARNING, "Closing unknown connection %d ...", i );
close( i );
- Log( LOG_WARNING, "Unknown connection %d closed.", i );
}
}
}
* Socket nicht erteugt werden, so wird NULL geliefert.*/
struct sockaddr_in addr;
- INT sock, on = 1;
+ INT sock;
/* Server-"Listen"-Socket initialisieren */
memset( &addr, 0, sizeof( addr ));
return FALSE;
}
- /* Socket-Optionen setzen */
- if( fcntl( sock, F_SETFL, O_NONBLOCK ) != 0 )
- {
- Log( LOG_CRIT, "Can't enable non-blocking mode: %s!", strerror( errno ));
- close( sock );
- return FALSE;
- }
- if( setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &on, (socklen_t)sizeof( on )) != 0)
- {
- Log( LOG_ERR, "Can't set socket options: %s!", strerror( errno ));
- /* dieser Fehler kann ignoriert werden. */
- }
+ if( ! Init_Socket( sock )) return FALSE;
/* an Port binden */
if( bind( sock, (struct sockaddr *)&addr, (socklen_t)sizeof( addr )) != 0 )
/* Socket der Verbindung in Set aufnehmen */
FD_SET( My_Connections[i].sock, &write_sockets );
}
+ }
+ /* Sockets mit im Aufbau befindlichen ausgehenden Verbindungen suchen */
+ for( i = 0; i < MAX_CONNECTIONS; i++ )
+ {
+ if(( My_Connections[i].sock > NONE ) && ( FD_ISSET( My_Connections[i].sock, &My_Connects ))) FD_SET( My_Connections[i].sock, &write_sockets );
}
/* von welchen Sockets koennte gelesen werden? */
if(( My_Connections[i].sock > NONE ) && ( My_Connections[i].host[0] == '\0' ))
{
/* Hier muss noch auf den Resolver Sub-Prozess gewartet werden */
+ FD_CLR( My_Connections[i].sock, &read_sockets );
+ }
+ if(( My_Connections[i].sock > NONE ) && ( FD_ISSET( My_Connections[i].sock, &My_Connects )))
+ {
+ /* Hier laeuft noch ein asyncrones connect() */
FD_CLR( My_Connections[i].sock, &read_sockets );
}
}
LOCAL BOOLEAN Handle_Write( CONN_ID Idx )
{
- /* Daten aus Schreibpuffer versenden */
+ /* Daten aus Schreibpuffer versenden bzw. Connection aufbauen */
- INT len;
+ INT len, res, err;
assert( Idx >= 0 );
assert( My_Connections[Idx].sock > NONE );
+
+ if( FD_ISSET( My_Connections[Idx].sock, &My_Connects ))
+ {
+ /* es soll nichts geschrieben werden, sondern ein
+ * connect() hat ein Ergebnis geliefert */
+
+ FD_CLR( My_Connections[Idx].sock, &My_Connects );
+
+ /* Ergebnis des connect() ermitteln */
+ len = sizeof( err );
+ res = getsockopt( My_Connections[Idx].sock, SOL_SOCKET, SO_ERROR, &err, &len );
+ assert( len == sizeof( err ));
+
+ /* Fehler aufgetreten? */
+ if(( res != 0 ) || ( err != 0 ))
+ {
+ /* Fehler! */
+ if( res != 0 ) Log( LOG_CRIT, "getsockopt (connection %d): %s!", Idx, strerror( errno ));
+ else Log( LOG_CRIT, "Can't connect socket to \"%s:%d\" (connection %d): %s!", My_Connections[Idx].host, Conf_Server[My_Connections[Idx].our_server].port, Idx, strerror( err ));
+
+ /* Socket etc. pp. aufraeumen */
+ FD_CLR( My_Connections[Idx].sock, &My_Sockets );
+ close( My_Connections[Idx].sock );
+ Init_Conn_Struct( Idx );
+ return FALSE;
+ }
+ Log( LOG_DEBUG, "Connection %d with \"%s:%d\" established, now sendig PASS and SERVER ...", Idx, My_Connections[Idx].host, Conf_Server[My_Connections[Idx].our_server].port );
+
+ /* PASS und SERVER verschicken */
+ Conn_WriteStr( Idx, "PASS %s "PASSSERVERADD, Conf_Server[My_Connections[Idx].our_server].pwd );
+ Conn_WriteStr( Idx, "SERVER %s :%s", Conf_ServerName, Conf_ServerInfo );
+
+ return TRUE;
+ }
+
assert( My_Connections[Idx].wdatalen > 0 );
/* Daten schreiben */
Log( LOG_CRIT, "Can't create socket: %s!", strerror( errno ));
return;
}
- if( connect( new_sock, (struct sockaddr *)&new_addr, sizeof( new_addr )) < 0)
+
+ if( ! Init_Socket( new_sock )) return;
+
+ connect( new_sock, (struct sockaddr *)&new_addr, sizeof( new_addr ));
+ if( errno != EINPROGRESS )
{
+
close( new_sock );
Init_Conn_Struct( Idx );
Log( LOG_CRIT, "Can't connect socket: %s!", strerror( errno ));
return;
}
Client_SetIntroducer( c, c );
-
+
/* Verbindung registrieren */
My_Connections[Idx].sock = new_sock;
My_Connections[Idx].addr = new_addr;
/* Neuen Socket registrieren */
FD_SET( new_sock, &My_Sockets );
+ FD_SET( new_sock, &My_Connects );
if( new_sock > My_Max_Fd ) My_Max_Fd = new_sock;
-
- /* PASS und SERVER verschicken */
- Conn_WriteStr( Idx, "PASS %s "PASSSERVERADD, Conf_Server[Server].pwd );
- Conn_WriteStr( Idx, "SERVER %s :%s", Conf_ServerName, Conf_ServerInfo );
} /* New_Server */
} /* Init_Conn_Struct */
+LOCAL BOOLEAN Init_Socket( INT Sock )
+{
+ /* Socket-Optionen setzen */
+
+ INT on = 1;
+
+ if( fcntl( Sock, F_SETFL, O_NONBLOCK ) != 0 )
+ {
+ Log( LOG_CRIT, "Can't enable non-blocking mode: %s!", strerror( errno ));
+ close( Sock );
+ return FALSE;
+ }
+ if( setsockopt( Sock, SOL_SOCKET, SO_REUSEADDR, &on, (socklen_t)sizeof( on )) != 0)
+ {
+ Log( LOG_ERR, "Can't set socket options: %s!", strerror( errno ));
+ /* dieser Fehler kann ignoriert werden. */
+ }
+
+ return TRUE;
+} /* Init_Socket */
+
+
LOCAL RES_STAT *ResolveAddr( struct sockaddr_in *Addr )
{
/* IP (asyncron!) aufloesen. Bei Fehler, z.B. wenn der