1
0
mirror of https://github.com/osmarks/ngircd.git synced 2025-01-30 01:04:44 +00:00

- ausgehende Verbindungen werden nun asyncron connectiert und blockieren

nicht mehr den Server. Dadurch waren einige Aenderungen noetig.
- diverse Log-Meldungen ueberarbeitet.
This commit is contained in:
Alexander Barton 2002-03-02 00:23:32 +00:00
parent 40f07f2f5c
commit 6da91c34b4

View File

@ -9,11 +9,16 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. * 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") * connect.h: Verwaltung aller Netz-Verbindungen ("connections")
* *
* $Log: conn.c,v $ * $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 * Revision 1.41 2002/02/27 14:47:04 alex
* - Logging bei Timeout von Verbindungen geaendert. * - Logging bei Timeout von Verbindungen geaendert.
* *
@ -223,6 +228,7 @@ LOCAL VOID Handle_Buffer( CONN_ID Idx );
LOCAL VOID Check_Connections( VOID ); LOCAL VOID Check_Connections( VOID );
LOCAL VOID Check_Servers( VOID ); LOCAL VOID Check_Servers( VOID );
LOCAL VOID Init_Conn_Struct( INT Idx ); LOCAL VOID Init_Conn_Struct( INT Idx );
LOCAL BOOLEAN Init_Socket( INT Sock );
LOCAL VOID New_Server( INT Server, CONN_ID Idx ); LOCAL VOID New_Server( INT Server, CONN_ID Idx );
LOCAL RES_STAT *ResolveAddr( struct sockaddr_in *Addr ); LOCAL RES_STAT *ResolveAddr( struct sockaddr_in *Addr );
@ -236,6 +242,7 @@ LOCAL CHAR *Resolv_Error( INT H_Error );
LOCAL fd_set My_Listeners; LOCAL fd_set My_Listeners;
LOCAL fd_set My_Sockets; LOCAL fd_set My_Sockets;
LOCAL fd_set My_Resolvers; LOCAL fd_set My_Resolvers;
LOCAL fd_set My_Connects;
LOCAL INT My_Max_Fd; LOCAL INT My_Max_Fd;
@ -252,6 +259,7 @@ GLOBAL VOID Conn_Init( VOID )
FD_ZERO( &My_Listeners ); FD_ZERO( &My_Listeners );
FD_ZERO( &My_Sockets ); FD_ZERO( &My_Sockets );
FD_ZERO( &My_Resolvers ); FD_ZERO( &My_Resolvers );
FD_ZERO( &My_Connects );
My_Max_Fd = 0; My_Max_Fd = 0;
@ -278,16 +286,21 @@ GLOBAL VOID Conn_Exit( VOID )
{ {
if( My_Connections[idx].sock == i ) break; if( My_Connections[idx].sock == i ) break;
} }
if( idx < MAX_CONNECTIONS ) Conn_Close( idx, NULL, "Server going down", TRUE ); if( FD_ISSET( i, &My_Listeners ))
else if( FD_ISSET( i, &My_Listeners ))
{ {
close( i ); close( i );
Log( LOG_DEBUG, "Listening socket %d closed.", i ); Log( LOG_DEBUG, "Listening socket %d closed.", i );
} }
else else if( FD_ISSET( i, &My_Connects ))
{ {
close( i ); close( i );
Log( LOG_WARNING, "Unknown connection %d closed.", 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 );
} }
} }
} }
@ -301,7 +314,7 @@ GLOBAL BOOLEAN Conn_NewListener( CONST INT Port )
* Socket nicht erteugt werden, so wird NULL geliefert.*/ * Socket nicht erteugt werden, so wird NULL geliefert.*/
struct sockaddr_in addr; struct sockaddr_in addr;
INT sock, on = 1; INT sock;
/* Server-"Listen"-Socket initialisieren */ /* Server-"Listen"-Socket initialisieren */
memset( &addr, 0, sizeof( addr )); memset( &addr, 0, sizeof( addr ));
@ -317,18 +330,7 @@ GLOBAL BOOLEAN Conn_NewListener( CONST INT Port )
return FALSE; return FALSE;
} }
/* Socket-Optionen setzen */ if( ! Init_Socket( sock )) return FALSE;
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. */
}
/* an Port binden */ /* an Port binden */
if( bind( sock, (struct sockaddr *)&addr, (socklen_t)sizeof( addr )) != 0 ) if( bind( sock, (struct sockaddr *)&addr, (socklen_t)sizeof( addr )) != 0 )
@ -407,6 +409,11 @@ GLOBAL VOID Conn_Handler( INT Timeout )
FD_SET( My_Connections[i].sock, &write_sockets ); 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? */ /* von welchen Sockets koennte gelesen werden? */
read_sockets = My_Sockets; read_sockets = My_Sockets;
@ -417,6 +424,11 @@ GLOBAL VOID Conn_Handler( INT Timeout )
/* Hier muss noch auf den Resolver Sub-Prozess gewartet werden */ /* Hier muss noch auf den Resolver Sub-Prozess gewartet werden */
FD_CLR( My_Connections[i].sock, &read_sockets ); 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 );
}
} }
for( i = 0; i < My_Max_Fd + 1; i++ ) for( i = 0; i < My_Max_Fd + 1; i++ )
{ {
@ -662,12 +674,47 @@ LOCAL VOID Handle_Read( INT Sock )
LOCAL BOOLEAN Handle_Write( CONN_ID Idx ) 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( Idx >= 0 );
assert( My_Connections[Idx].sock > NONE ); 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 ); assert( My_Connections[Idx].wdatalen > 0 );
/* Daten schreiben */ /* Daten schreiben */
@ -1026,8 +1073,13 @@ LOCAL VOID New_Server( INT Server, CONN_ID Idx )
Log( LOG_CRIT, "Can't create socket: %s!", strerror( errno )); Log( LOG_CRIT, "Can't create socket: %s!", strerror( errno ));
return; 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 ); close( new_sock );
Init_Conn_Struct( Idx ); Init_Conn_Struct( Idx );
Log( LOG_CRIT, "Can't connect socket: %s!", strerror( errno )); Log( LOG_CRIT, "Can't connect socket: %s!", strerror( errno ));
@ -1044,7 +1096,7 @@ LOCAL VOID New_Server( INT Server, CONN_ID Idx )
return; return;
} }
Client_SetIntroducer( c, c ); Client_SetIntroducer( c, c );
/* Verbindung registrieren */ /* Verbindung registrieren */
My_Connections[Idx].sock = new_sock; My_Connections[Idx].sock = new_sock;
My_Connections[Idx].addr = new_addr; My_Connections[Idx].addr = new_addr;
@ -1052,11 +1104,8 @@ LOCAL VOID New_Server( INT Server, CONN_ID Idx )
/* Neuen Socket registrieren */ /* Neuen Socket registrieren */
FD_SET( new_sock, &My_Sockets ); FD_SET( new_sock, &My_Sockets );
FD_SET( new_sock, &My_Connects );
if( new_sock > My_Max_Fd ) My_Max_Fd = new_sock; 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 */ } /* New_Server */
@ -1078,6 +1127,28 @@ LOCAL VOID Init_Conn_Struct( INT Idx )
} /* Init_Conn_Struct */ } /* 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 ) LOCAL RES_STAT *ResolveAddr( struct sockaddr_in *Addr )
{ {
/* IP (asyncron!) aufloesen. Bei Fehler, z.B. wenn der /* IP (asyncron!) aufloesen. Bei Fehler, z.B. wenn der