/*
* ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2010 Alexander Barton <alex@barton.de>
+ * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* Please read the file COPYING, README and AUTHORS for more information.
*/
+#undef DEBUG_BUFFER
+
#define CONN_MODULE
#include "portab.h"
#include "ngircd.h"
#include "array.h"
#include "client.h"
+#include "class.h"
#include "conf.h"
#include "conn-ssl.h"
#include "conn-zip.h"
/**
- * Initialite connecion module.
+ * Initialize connecion module.
*/
GLOBAL void
Conn_Init( void )
* they don't hold connections open that the main process wants to close.
*/
GLOBAL void
-Conn_CloseAllSockets(void)
+Conn_CloseAllSockets(int ExceptOf)
{
CONN_ID idx;
for(idx = 0; idx < Pool_Size; idx++) {
- if(My_Connections[idx].sock > NONE)
+ if(My_Connections[idx].sock > NONE &&
+ My_Connections[idx].sock != ExceptOf)
close(My_Connections[idx].sock);
}
}
Check_Servers();
Check_Connections();
+ /* Expire outdated class/list items */
+ Class_Expire();
+
/* Look for non-empty read buffers ... */
for (i = 0; i < Pool_Size; i++) {
if ((My_Connections[i].sock > NONE)
if (array_bytes(&My_Connections[Idx].wbuf) + Len >=
writebuf_limit) {
Log(LOG_NOTICE,
- "Write buffer overflow (connection %d, limit is %lu bytes, %lu bytes new, %lu bytes pending)!",
+ "Write buffer space exhausted (connection %d, limit is %lu bytes, %lu bytes new, %lu bytes pending)",
Idx, writebuf_limit, Len,
(unsigned long)array_bytes(&My_Connections[Idx].wbuf));
- Conn_Close(Idx, "Write buffer overflow!", NULL, false);
+ Conn_Close(Idx, "Write buffer space exhausted", NULL, false);
return false;
}
GLOBAL void
Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClient )
{
- /* Close connection. Open pipes of asyncronous resolver
+ /* Close connection. Open pipes of asynchronous resolver
* sub-processes are closed down. */
CLIENT *c;
return true;
}
+#ifdef DEBUG_BUFFER
LogDebug
("Handle_Write() called for connection %d, %ld bytes pending ...",
Idx, wdatalen);
+#endif
#ifdef SSL_SUPPORT
if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_SSL )) {
assert(Sock > NONE);
+ LogDebug("Accepting new connection on socket %d ...", Sock);
+
new_sock_len = (int)sizeof(new_addr);
new_sock = accept(Sock, (struct sockaddr *)&new_addr,
(socklen_t *)&new_sock_len);
if (!Conf_Ident)
identsock = -1;
#endif
- if (Conf_DNS)
+ if (Conf_DNS) {
+ if (Conf_NoticeAuth) {
+#ifdef IDENTAUTH
+ if (Conf_Ident)
+ (void)Conn_WriteStr(new_sock,
+ "NOTICE AUTH :*** Looking up your hostname and checking ident");
+ else
+#endif
+ (void)Conn_WriteStr(new_sock,
+ "NOTICE AUTH :*** Looking up your hostname");
+ }
Resolve_Addr(&My_Connections[new_sock].proc_stat, &new_addr,
identsock, cb_Read_Resolver_Result);
+ }
Account_Connection();
return new_sock;
{
/* Read buffer is full */
Log(LOG_ERR,
- "Receive buffer overflow (connection %d): %d bytes!",
+ "Receive buffer space exhausted (connection %d): %d bytes",
Idx, array_bytes(&My_Connections[Idx].rbuf));
- Conn_Close( Idx, "Receive buffer overflow!", NULL, false );
+ Conn_Close(Idx, "Receive buffer space exhausted", NULL, false);
return;
}
if (!array_catb(&My_Connections[Idx].zip.rbuf, readbuf,
(size_t) len)) {
Log(LOG_ERR,
- "Could not append recieved data to zip input buffer (connn %d): %d bytes!",
+ "Could not append recieved data to zip input buffer (connection %d): %d bytes!",
Idx, len);
- Conn_Close(Idx, "Receive buffer overflow!", NULL,
+ Conn_Close(Idx, "Receive buffer space exhausted", NULL,
false);
return;
}
#endif
{
if (!array_catb( &My_Connections[Idx].rbuf, readbuf, len)) {
- Log( LOG_ERR, "Could not append recieved data to input buffer (connn %d): %d bytes!", Idx, len );
- Conn_Close( Idx, "Receive buffer overflow!", NULL, false );
+ Log(LOG_ERR,
+ "Could not append recieved data to input buffer (connection %d): %d bytes!",
+ Idx, len);
+ Conn_Close(Idx, "Receive buffer space exhausted", NULL, false );
}
}
CLIENT *c;
c = Conn_GetClient(Idx);
- assert( c != NULL);
+ starttime = time(NULL);
+
+ assert(c != NULL);
/* Servers do get special command limits, so they can process
* all the messages that are required while peering. */
switch (Client_Type(c)) {
case CLIENT_SERVER:
- maxcmd = MAX_COMMANDS_SERVER; break;
+ /* Allow servers to send more commands in the first 10 secods
+ * to speed up server login and network synchronisation. */
+ if (starttime - Client_StartTime(c) < 10)
+ maxcmd = MAX_COMMANDS_SERVER * 5;
+ else
+ maxcmd = MAX_COMMANDS_SERVER;
+ break;
case CLIENT_SERVICE:
maxcmd = MAX_COMMANDS_SERVICE; break;
}
- starttime = time(NULL);
for (i=0; i < maxcmd; i++) {
/* Check penalty */
if (My_Connections[Idx].delaytime > starttime)
return 0; /* error -> connection has been closed */
array_moveleft(&My_Connections[Idx].rbuf, 1, len);
+#ifdef DEBUG_BUFFER
LogDebug("Connection %d: %d bytes left in read buffer.",
Idx, array_bytes(&My_Connections[Idx].rbuf));
+#endif
#ifdef ZLIB
if ((!old_z) && (My_Connections[Idx].options & CONN_ZIP) &&
(array_bytes(&My_Connections[Idx].rbuf) > 0)) {
return;
}
+ if (!io_event_create( new_sock, IO_WANTWRITE, cb_connserver)) {
+ Log(LOG_ALERT, "io_event_create(): could not add fd %d", strerror(errno));
+ close(new_sock);
+ return;
+ }
+
My_Connections = array_start(&My_ConnArray);
assert(My_Connections[new_sock].sock <= 0);
c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWNSERVER, false);
if (!c) {
Log( LOG_ALERT, "Can't establish connection: can't create client structure!" );
- close( new_sock );
+ io_close(new_sock);
return;
}
strlcpy( My_Connections[new_sock].host, Conf_Server[Server].host,
sizeof(My_Connections[new_sock].host ));
- /* Register new socket */
- if (!io_event_create( new_sock, IO_WANTWRITE, cb_connserver)) {
- Log( LOG_ALERT, "io_event_create(): could not add fd %d", strerror(errno));
- Conn_Close( new_sock, "io_event_create() failed", NULL, false );
- Init_Conn_Struct( new_sock );
- Conf_Server[Server].conn_id = NONE;
- }
#ifdef SSL_SUPPORT
if (Conf_Server[Server].SSLConnect && !ConnSSL_PrepareConnect( &My_Connections[new_sock],
&Conf_Server[Server] ))
* Initialize options of a new socket.
*
* For example, we try to set socket options SO_REUSEADDR and IPTOS_LOWDELAY.
- * Errors shouldn't be fatal and therefore are ignored.
+ * The socket is automatically closed if a fatal error is encountered.
*
* @param Sock Socket handle.
+ * @returns false if socket was closed due to fatal error.
*/
static bool
Init_Socket( int Sock )
/* Set type of service (TOS) */
#if defined(IPPROTO_IP) && defined(IPTOS_LOWDELAY)
value = IPTOS_LOWDELAY;
- LogDebug("Setting IP_TOS on socket %d to IPTOS_LOWDELAY.", Sock);
if (setsockopt(Sock, IPPROTO_IP, IP_TOS, &value,
(socklen_t) sizeof(value))) {
LogDebug("Can't set socket option IP_TOS: %s!",
strerror(errno));
/* ignore this error */
- }
+ } else
+ LogDebug("IP_TOS on socket %d has been set to IPTOS_LOWDELAY.",
+ Sock);
#endif
return true;
/* Read result from pipe */
len = Proc_Read(&Conf_Server[i].res_stat, dest_addrs, sizeof(dest_addrs));
+ Proc_Close(&Conf_Server[i].res_stat);
if (len == 0) {
/* Error resolving hostname: reset server structure */
Conf_Server[i].conn_id = NONE;
/* Read result from pipe */
len = Proc_Read(&My_Connections[i].proc_stat, readbuf, sizeof readbuf -1);
+ Proc_Close(&My_Connections[i].proc_stat);
if (len == 0)
return;
strlcpy(My_Connections[i].host, readbuf,
sizeof(My_Connections[i].host));
Client_SetHostname(c, readbuf);
+ if (Conf_NoticeAuth)
+ (void)Conn_WriteStr(i,
+ "NOTICE AUTH :*** Found your hostname");
#ifdef IDENTAUTH
++identptr;
if (*identptr) {
Log(LOG_INFO, "IDENT lookup for connection %d: \"%s\".", i, identptr);
Client_SetUser(c, identptr, true);
+ if (Conf_NoticeAuth)
+ (void)Conn_WriteStr(i,
+ "NOTICE AUTH :*** Got ident response");
} else {
Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i);
+ if (Conf_NoticeAuth && Conf_Ident)
+ (void)Conn_WriteStr(i,
+ "NOTICE AUTH :*** No ident response");
}
#endif
}
} /* Conn_GetFromProc */
+#ifndef STRICT_RFC
+
+GLOBAL long
+Conn_GetAuthPing(CONN_ID Idx)
+{
+ assert (Idx != NONE);
+ return My_Connections[Idx].auth_ping;
+} /* Conn_GetAuthPing */
+
+GLOBAL void
+Conn_SetAuthPing(CONN_ID Idx, long ID)
+{
+ assert (Idx != NONE);
+ My_Connections[Idx].auth_ping = ID;
+} /* Conn_SetAuthPing */
+
+#endif
+
+
#ifdef SSL_SUPPORT
/**