1
0
mirror of https://github.com/osmarks/ngircd.git synced 2025-06-03 06:54:09 +00:00

sync with HEAD.

This commit is contained in:
Florian Westphal 2007-04-03 22:08:50 +00:00
parent 5c3e02393b
commit f67ad15a36
18 changed files with 605 additions and 191 deletions

View File

@ -11,6 +11,14 @@
ngIRCd 0.10.2
- Predefined Channel configuration now allows specification of channel key
(mode k) and maximum user count (mode l).
- When using epoll() IO interface, compile in the select() interface as
well and fall back to it when epoll() isn't available on runtime.
- New configure option "--without-select" to disable select() IO API
(even when using epoll(), see above).
- Added support for IO APIs "poll()" and "/dev/poll".
- Reorganized internal handling of invite and ban lists.
ngIRCd 0.10.1 (2006-12-17)
@ -676,4 +684,4 @@ ngIRCd 0.0.1, 31.12.2001
--
$Id: ChangeLog,v 1.302.2.10 2007/04/03 20:23:30 fw Exp $
$Id: ChangeLog,v 1.302.2.11 2007/04/03 22:08:50 fw Exp $

14
INSTALL
View File

@ -149,14 +149,20 @@ standard locations.
The Z compression library ("libz") is required for this option.
* IO Backend (autodetected by default):
--with-select[=<path>] / --without-select
--with-poll[=<path>] / --without-poll
--with-devpoll[=<path>] / --without-devpoll
--with-epoll[=<path>] / --without-epoll
--with-kqueue[=<path>] / --without-kqueue
ngIRCd can use three different IO "backends": the "old school" select()
ngIRCd can use different IO "backends": the "old school" select() and poll()
API which should be supported by most UNIX-like operating systems, or the
more efficient and flexible epoll() (Linux 2.6) or kqueue() (BSD) APIs.
more efficient and flexible epoll() (Linux >=2.6), kqueue() (BSD) and
/dev/poll APIs.
By default the IO backend is autodetected, but you can use "--without-xxx"
to disable a more enhanced API and force the daemon to use select().
to disable a more enhanced API.
When using the epoll() API, support for select() is compiled in as well by
default to enable the binary to run on older Linux kernels (<2.6), too.
* IDENT-Support:
--with-ident[=<path>]
@ -241,4 +247,4 @@ number. In both cases the server exits after the output.
--
$Id: INSTALL,v 1.23.2.1 2006/08/02 08:19:38 alex Exp $
$Id: INSTALL,v 1.23.2.2 2007/04/03 22:08:50 fw Exp $

View File

@ -1,6 +1,6 @@
#
# ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2006 Alexander Barton <alex@barton.de>
# Copyright (c)2001-2005 Alexander Barton <alex@barton.de>
#
# 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
@ -8,13 +8,13 @@
# (at your option) any later version.
# Please read the file COPYING, README and AUTHORS for more information.
#
# $Id: configure.in,v 1.118.2.8 2006/12/17 14:06:19 alex Exp $
# $Id: configure.in,v 1.118.2.9 2007/04/03 22:08:50 fw Exp $
#
# -- Initialisation --
AC_PREREQ(2.50)
AC_INIT(ngircd, 0.10.1)
AC_INIT(ngircd, CVSHEAD)
AC_CONFIG_SRCDIR(src/ngircd/ngircd.c)
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE(1.6)
@ -143,12 +143,10 @@ AC_CHECK_FUNCS([ \
AC_CHECK_FUNCS(inet_aton isdigit sigaction snprintf vsnprintf strdup strlcpy strlcat)
AC_CHECK_FUNCS(select,[AC_CHECK_HEADERS(sys/select.h)],
AC_MSG_ERROR([required function select() is missing!])
)
# -- Configuration options --
# use syslog?
x_syslog_on=no
AC_ARG_WITH(syslog,
[ --without-syslog disable syslog (autodetected by default)],
@ -174,6 +172,8 @@ if test "$x_syslog_on" = "yes"; then
AC_CHECK_HEADERS(syslog.h,,AC_MSG_ERROR([required C header missing!]))
fi
# use zlib compression?
x_zlib_on=no
AC_ARG_WITH(zlib,
[ --without-zlib disable zlib compression (autodetected by default)],
@ -198,29 +198,83 @@ if test "$x_zlib_on" = "yes"; then
AC_CHECK_HEADERS(zlib.h,,AC_MSG_ERROR([required C header missing!]))
fi
# detect which IO API to use:
x_io_backend=select\(\)
AC_ARG_WITH(epoll,
[ --without-epoll disable epoll support (autodetected by default)],
x_io_backend=none
AC_ARG_WITH(select,
[ --without-select disable select IO support (autodetected by default)],
[ if test "$withval" != "no"; then
if test "$withval" != "yes"; then
CFLAGS="-I$withval/include $CFLAGS"
CPPFLAGS="-I$withval/include $CPPFLAGS"
LDFLAGS="-L$withval/lib $LDFLAGS"
fi
AC_CHECK_FUNCS(epoll_create, x_io_backend=epoll\(\),
AC_MSG_ERROR([Can't enable epoll support!])
AC_CHECK_FUNCS(select, x_io_select=yes,
AC_MSG_ERROR([Can't enable select IO support!])
)
fi
],
[
AC_CHECK_FUNCS(epoll_create, x_io_backend=epoll\(\))
AC_CHECK_FUNCS(select, x_io_select=yes)
]
)
AC_ARG_WITH(poll,
[ --without-poll disable poll support (autodetected by default)],
[ if test "$withval" != "no"; then
if test "$withval" != "yes"; then
CFLAGS="-I$withval/include $CFLAGS"
CPPFLAGS="-I$withval/include $CPPFLAGS"
LDFLAGS="-L$withval/lib $LDFLAGS"
fi
AC_CHECK_FUNCS(poll, x_io_backend=poll\(\),
AC_MSG_ERROR([Can't enable poll IO support!])
)
fi
],
[
AC_CHECK_FUNCS(poll, x_io_backend=poll\(\))
]
)
AC_ARG_WITH(devpoll,
[ --without-devpoll disable /dev/poll IO support (autodetected by default)],
[ if test "$withval" != "no"; then
if test "$withval" != "yes"; then
CFLAGS="-I$withval/include $CFLAGS"
CPPFLAGS="-I$withval/include $CPPFLAGS"
LDFLAGS="-L$withval/lib $LDFLAGS"
fi
AC_CHECK_HEADERS(sys/devpoll.h,,AC_MSG_ERROR([required C header missing!]))
fi
],
[
AC_CHECK_HEADERS(sys/devpoll.h, x_io_backend=/dev/poll)
]
)
AC_ARG_WITH(epoll,
[ --without-epoll disable epoll IO support (autodetected by default)],
[ if test "$withval" != "no"; then
if test "$withval" != "yes"; then
CFLAGS="-I$withval/include $CFLAGS"
CPPFLAGS="-I$withval/include $CPPFLAGS"
LDFLAGS="-L$withval/lib $LDFLAGS"
fi
AC_CHECK_FUNCS(epoll_create, x_io_epoll=yes,
AC_MSG_ERROR([Can't enable epoll IO support!])
)
fi
],
[
AC_CHECK_FUNCS(epoll_create, x_io_epoll=yes)
]
)
AC_ARG_WITH(kqueue,
[ --without-kqueue disable kqueue support (autodetected by default)],
[ --without-kqueue disable kqueue IO support (autodetected by default)],
[ if test "$withval" != "no"; then
if test "$withval" != "yes"; then
CFLAGS="-I$withval/include $CFLAGS"
@ -228,7 +282,7 @@ AC_ARG_WITH(kqueue,
LDFLAGS="-L$withval/lib $LDFLAGS"
fi
AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue\(\),
AC_MSG_ERROR([Can't enable kqueue support!])
AC_MSG_ERROR([Can't enable kqueue IO support!])
)
fi
],
@ -237,6 +291,27 @@ AC_ARG_WITH(kqueue,
]
)
if test "$x_io_epoll" = "yes" -a "$x_io_select" = "yes"; then
# when epoll() and select() are available, we'll use both!
x_io_backend="epoll(), select()"
else
if test "$x_io_epoll" = "yes"; then
# we prefere epoll() if it is available
x_io_backend="epoll()"
else
if test "$x_io_select" = "yes" -a "$x_io_backend" = "none"; then
# we'll use select, when available and no "better"
# interface has been detected ...
x_io_backend="select()"
fi
fi
fi
if test "$x_io_backend" = "none"; then
AC_MSG_ERROR([No useabe IO API activated/found!?])
fi
# use TCP wrappers?
x_tcpwrap_on=no
AC_ARG_WITH(tcp-wrappers,
@ -267,6 +342,8 @@ int deny_severity = 0;
]
)
# include support for "zeroconf"?
x_zeroconf_on=no
AC_ARG_WITH(zeroconf,
[ --with-zeroconf enable support for "Zeroconf"],
@ -315,6 +392,8 @@ if test "$x_zeroconf_on" = "howl"; then
AC_DEFINE(ZEROCONF, 1)
fi
# do IDENT requests using libident?
x_identauth_on=no
AC_ARG_WITH(ident,
[ --with-ident enable "IDENT" ("AUTH") protocol support],
@ -336,6 +415,8 @@ if test "$x_identauth_on" = "yes"; then
AC_CHECK_HEADERS(ident.h,,AC_MSG_ERROR([required C header missing!]))
fi
# compile in IRC+ protocol support?
x_ircplus_on=yes
AC_ARG_ENABLE(ircplus,
[ --disable-ircplus disable IRC+ protocol],
@ -345,6 +426,8 @@ if test "$x_ircplus_on" = "yes"; then
AC_DEFINE(IRCPLUS, 1)
fi
# compile in IRC "sniffer"?
x_sniffer_on=no; x_debug_on=no
AC_ARG_ENABLE(sniffer,
[ --enable-sniffer enable IRC traffic sniffer (enables debug mode)],
@ -354,6 +437,8 @@ AC_ARG_ENABLE(sniffer,
fi
)
# enable additional debugging code?
AC_ARG_ENABLE(debug,
[ --enable-debug show additional debug output],
if test "$enableval" = "yes"; then x_debug_on=yes; fi
@ -363,6 +448,8 @@ if test "$x_debug_on" = "yes"; then
test "$GCC" = "yes" && CFLAGS="-pedantic $CFLAGS"
fi
# enable "strict RFC rules"?
x_strict_rfc_on=no
AC_ARG_ENABLE(strict-rfc,
[ --enable-strict-rfc strict RFC conformance -- may break clients!],

View File

@ -2,9 +2,20 @@
#
# ngIRCd start and stop script for Debian-based systems
#
# $Id: ngircd.init,v 1.6 2005/07/26 19:37:18 alex Exp $
# $Id: ngircd.init,v 1.6.2.1 2007/04/03 22:08:50 fw Exp $
#
### BEGIN INIT INFO
# Provides: ircd
# Required-Start: $local_fs
# Required-Stop: $local_fs
# Should-Start: $syslog $network
# Should-Stop: $syslog $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Next Generation IRC Server
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/ngircd
NAME=ngIRCd

View File

@ -51,6 +51,7 @@ powerpc/apple/darwin7.4.0 gcc 3.3 0.8.0 04-05-30 alex Y Y Y Y
powerpc/apple/darwin7.9.0 gcc 3.3 CVSHEAD 06-05-07 fw Y Y Y Y (3)
powerpc/apple/darwin8.1.0 gcc 4.0 0.9.x-CVS 05-06-27 alex Y Y Y Y
powerpc/unknown/linux-gnu gcc 3.3.3 0.8.0 04-05-30 alex Y Y Y Y
powerpc/unknown/openbsd3.6 gcc 2.95.3 0.10.0 06-10-08 alex Y Y n Y
sparc/sun/solaris2.6 gcc 2.95.3 0.7.x-CVS 03-04-22 alex Y Y Y Y
sparc/sun/solaris2.7 gcc 3.3 0.8.0 04-05-30 alex Y Y Y Y
sparc/unkn./netbsdelf1.6.1 gcc 2.95.3 0.8.0 04-05-30 alex Y Y Y Y
@ -73,4 +74,4 @@ Notes
(3) Using the kqueue() IO interface.
--
$Id: Platforms.txt,v 1.14.2.1 2006/09/09 18:10:56 alex Exp $
$Id: Platforms.txt,v 1.14.2.2 2007/04/03 22:08:51 fw Exp $

View File

@ -1,4 +1,4 @@
# $Id: sample-ngircd.conf,v 1.37.2.1 2006/12/02 13:10:43 fw Exp $
# $Id: sample-ngircd.conf,v 1.37.2.2 2007/04/03 22:08:51 fw Exp $
#
# This is a sample configuration file for the ngIRCd, which must be adepted
@ -178,7 +178,13 @@
;Topic = a great topic
# Initial channel modes
;Modes = tn
;Modes = tnk
# initial channel password (mode k)
;Key = Secret
# maximum users per channel (mode l)
;MaxUsers = 23
[Channel]
# More [Channel] sections, if you like ...

View File

@ -8,14 +8,14 @@
# (at your option) any later version.
# Please read the file COPYING, README and AUTHORS for more information.
#
# $Id: Makefile.am,v 1.2 2006/04/08 16:35:03 alex Exp $
# $Id: Makefile.am,v 1.2.2.1 2007/04/03 22:08:52 fw Exp $
#
maintainer-clean-local:
rm -f Makefile Makefile.in
distclean-local:
rm -f html
rm -rf html
srcdoc:
@doxygen --version >/dev/null 2>&1 \

View File

@ -12,7 +12,7 @@
#include "array.h"
static char UNUSED id[] = "$Id: array.c,v 1.11.2.2 2006/12/17 23:00:17 fw Exp $";
static char UNUSED id[] = "$Id: array.c,v 1.11.2.3 2007/04/03 22:08:52 fw Exp $";
#include <assert.h>
@ -270,7 +270,7 @@ void
array_free(array * a)
{
assert(a != NULL);
#ifdef DEBUG
#ifdef DEBUG_ARRAY
Log(LOG_DEBUG,
"array_free(): %u bytes free'd (%u bytes still used at time of free()).",
a->allocated, a->used);

View File

@ -17,7 +17,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: channel.c,v 1.56.2.2 2007/04/03 20:23:31 fw Exp $";
static char UNUSED id[] = "$Id: channel.c,v 1.56.2.3 2007/04/03 22:08:52 fw Exp $";
#include "imp.h"
#include <assert.h>
@ -131,6 +131,9 @@ Channel_InitPredefined( void )
while (*c)
Channel_ModeAdd(chan, *c++);
Channel_SetKey(chan, Conf_Channel[i].key);
Channel_SetMaxUsers(chan, Conf_Channel[i].maxusers);
Log(LOG_INFO, "Created pre-defined channel \"%s\".",
Conf_Channel[i].name );
}
@ -145,7 +148,7 @@ Channel_Exit( void )
{
CHANNEL *c, *c_next;
CL2CHAN *cl2chan, *cl2chan_next;
/* Channel-Strukturen freigeben */
c = My_Channels;
while( c )

View File

@ -17,7 +17,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: client.c,v 1.91.2.1 2006/12/02 14:00:00 fw Exp $";
static char UNUSED id[] = "$Id: client.c,v 1.91.2.2 2007/04/03 22:08:52 fw Exp $";
#include "imp.h"
#include <assert.h>
@ -68,10 +68,6 @@ static CLIENT *Init_New_Client PARAMS((CONN_ID Idx, CLIENT *Introducer,
CLIENT *TopServer, int Type, char *ID, char *User, char *Hostname,
char *Info, int Hops, int Token, char *Modes, bool Idented));
#ifndef Client_DestroyNow
GLOBAL void Client_DestroyNow PARAMS((CLIENT *Client ));
#endif
long Max_Users = 0, My_Max_Users = 0;
@ -336,43 +332,14 @@ Client_Destroy( CLIENT *Client, char *LogMsg, char *FwdMsg, bool SendQuit )
} /* Client_Destroy */
GLOBAL void
Client_DestroyNow( CLIENT *Client )
{
/* Destroy client structure immediately. This function is only
* intended for the connection layer to remove client structures
* of connections that can't be established! */
CLIENT *last, *c;
assert( Client != NULL );
last = NULL;
c = My_Clients;
while( c )
{
if( c == Client )
{
/* Wir haben den Client gefunden: entfernen */
if( last ) last->next = c->next;
else My_Clients = (CLIENT *)c->next;
free( c );
break;
}
last = c;
c = (CLIENT *)c->next;
}
} /* Client_DestroyNow */
GLOBAL void
Client_SetHostname( CLIENT *Client, char *Hostname )
{
/* Hostname eines Clients setzen */
assert( Client != NULL );
assert( Hostname != NULL );
strlcpy( Client->host, Hostname, sizeof( Client->host ));
} /* Client_SetHostname */
@ -661,8 +628,7 @@ GLOBAL char *
Client_User( CLIENT *Client )
{
assert( Client != NULL );
if( Client->user[0] ) return Client->user;
else return "~";
return Client->user[0] ? Client->user : "~";
} /* Client_User */
@ -916,9 +882,8 @@ GLOBAL unsigned long
Client_MyServerCount( void )
{
CLIENT *c;
unsigned long cnt;
unsigned long cnt = 0;
cnt = 0;
c = My_Clients;
while( c )
{
@ -933,9 +898,8 @@ GLOBAL unsigned long
Client_OperCount( void )
{
CLIENT *c;
unsigned long cnt;
unsigned long cnt = 0;
cnt = 0;
c = My_Clients;
while( c )
{

View File

@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: client.h,v 1.42.2.2 2006/12/02 14:26:53 fw Exp $
* $Id: client.h,v 1.42.2.3 2007/04/03 22:08:52 fw Exp $
*
* Client management (header)
*/
@ -80,9 +80,6 @@ GLOBAL CLIENT *Client_NewRemoteServer PARAMS(( CLIENT *Introducer, char *Hostnam
GLOBAL CLIENT *Client_NewRemoteUser PARAMS(( CLIENT *Introducer, char *Nick, int Hops, char *User, char *Hostname, int Token, char *Modes, char *Info, bool Idented ));
GLOBAL void Client_Destroy PARAMS(( CLIENT *Client, char *LogMsg, char *FwdMsg, bool SendQuit ));
#ifdef CONN_MODULE
GLOBAL void Client_DestroyNow PARAMS(( CLIENT *Client ));
#endif
GLOBAL CLIENT *Client_ThisServer PARAMS(( void ));

View File

@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: conf.c,v 1.92.2.3 2006/12/02 13:10:43 fw Exp $";
static char UNUSED id[] = "$Id: conf.c,v 1.92.2.4 2007/04/03 22:08:52 fw Exp $";
#include "imp.h"
#include <assert.h>
@ -240,6 +240,8 @@ Conf_Test( void )
puts( "[CHANNEL]" );
printf( " Name = %s\n", Conf_Channel[i].name );
printf( " Modes = %s\n", Conf_Channel[i].modes );
printf( " Key = %s\n", Conf_Channel[i].key );
printf( " MaxUsers = %lu\n", Conf_Channel[i].maxusers );
topic = (char*)array_start(&Conf_Channel[i].topic);
printf( " Topic = %s\n\n", topic ? topic : "");
@ -555,6 +557,8 @@ Read_Config( void )
/* Initialize new channel structure */
strcpy( Conf_Channel[Conf_Channel_Count].name, "" );
strcpy( Conf_Channel[Conf_Channel_Count].modes, "" );
strcpy( Conf_Channel[Conf_Channel_Count].key, "" );
Conf_Channel[Conf_Channel_Count].maxusers = 0;
array_free(&Conf_Channel[Conf_Channel_Count].topic);
Conf_Channel_Count++;
}
@ -968,6 +972,22 @@ Handle_CHANNEL( int Line, char *Var, char *Arg )
return;
}
if( strcasecmp( Var, "Key" ) == 0 ) {
/* Initial Channel Key (mode k) */
len = strlcpy(Conf_Channel[chancount].key, Arg, sizeof(Conf_Channel[chancount].key));
if (len >= sizeof( Conf_Channel[chancount].key ))
Config_Error_TooLong(Line, Var);
return;
}
if( strcasecmp( Var, "MaxUsers" ) == 0 ) {
/* maximum user limit, mode l */
Conf_Channel[chancount].maxusers = (unsigned long) atol(Arg);
if (Conf_Channel[chancount].maxusers == 0)
Config_Error_NaN(Line, Var);
return;
}
Config_Error( LOG_ERR, "%s, line %d (section \"Channel\"): Unknown variable \"%s\"!",
NGIRCd_ConfFile, Line, Var );
} /* Handle_CHANNEL */

View File

@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: conf.h,v 1.40.2.1 2006/12/02 13:10:43 fw Exp $
* $Id: conf.h,v 1.40.2.2 2007/04/03 22:08:52 fw Exp $
*
* Configuration management (header)
*/
@ -49,6 +49,8 @@ typedef struct _Conf_Channel
{
char name[CHANNEL_NAME_LEN]; /* Name of the channel */
char modes[CHANNEL_MODE_LEN]; /* Initial channel modes */
char key[CLIENT_PASS_LEN]; /* Channel key ("password", mode "k" ) */
unsigned long maxusers; /* maximum usercount for this channel, mode "l" */
array topic; /* Initial topic */
} CONF_CHANNEL;

View File

@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: conn-func.h,v 1.5 2006/05/10 21:24:01 alex Exp $
* $Id: conn-func.h,v 1.5.2.1 2007/04/03 22:08:52 fw Exp $
*
* Connection management: Global functions (header)
*/
@ -52,9 +52,9 @@ GLOBAL UINT16 Conn_Options PARAMS(( CONN_ID Idx ));
GLOBAL void Conn_ResetWCounter PARAMS(( void ));
GLOBAL long Conn_WCounter PARAMS(( void ));
#define Conn_OPTION_ADD( x, opt ) ( (x)->options |= opt )
#define Conn_OPTION_DEL( x, opt ) ( (x)->options &= ~opt )
#define Conn_OPTION_ISSET( x, opt ) ( (x)->options & opt )
#define Conn_OPTION_ADD( x, opt ) ( (x)->options |= (opt) )
#define Conn_OPTION_DEL( x, opt ) ( (x)->options &= ~(opt) )
#define Conn_OPTION_ISSET( x, opt ) ( ((x)->options & (opt)) != 0)
#endif

View File

@ -17,7 +17,7 @@
#include "portab.h"
#include "io.h"
static char UNUSED id[] = "$Id: conn.c,v 1.198.2.2 2006/12/17 23:06:29 fw Exp $";
static char UNUSED id[] = "$Id: conn.c,v 1.198.2.3 2007/04/03 22:08:52 fw Exp $";
#include "imp.h"
#include <assert.h>
@ -123,7 +123,6 @@ cb_connserver(int sock, UNUSED short what)
{
int res, err;
socklen_t sock_len;
CLIENT *c;
CONN_ID idx = Socket2Index( sock );
if (idx <= NONE) {
LogDebug("cb_connserver wants to write on unknown socket?!");
@ -150,14 +149,7 @@ cb_connserver(int sock, UNUSED short what)
Conf_Server[Conf_GetServer(idx)].port,
idx, strerror(err));
/* Clean up the CLIENT structure (to avoid silly log
* messages) and call Conn_Close() to do the rest. */
c = Conn_GetClient(idx);
if (c)
Client_DestroyNow(c);
Conn_Close(idx, "Can't connect!", NULL, false);
Conn_Close(idx, "Can't connect!", NULL, false);
return;
}
@ -384,7 +376,7 @@ NewListener( const UINT16 Port )
if( ! Init_Socket( sock )) return -1;
if (bind(sock, (struct sockaddr *)&addr, (socklen_t)sizeof(addr)) != 0) {
Log( LOG_CRIT, "Can't bind socket: %s!", strerror( errno ));
Log( LOG_CRIT, "Can't bind socket (port %d) : %s!", Port, strerror( errno ));
close( sock );
return -1;
}
@ -995,11 +987,19 @@ New_Connection( int Sock )
Init_Conn_Struct(Pool_Size++);
}
/* register callback */
if (!io_event_create( new_sock, IO_WANTREAD, cb_clientserver)) {
Log(LOG_ALERT, "Can't accept connection: io_event_create failed!");
Simple_Message(new_sock, "ERROR :Internal error");
close(new_sock);
return -1;
}
c = Client_NewLocal( new_sock, inet_ntoa( new_addr.sin_addr ), CLIENT_UNKNOWN, false );
if( ! c ) {
Log( LOG_ALERT, "Can't accept connection: can't create client structure!" );
Simple_Message( new_sock, "ERROR :Internal error" );
close( new_sock );
Log(LOG_ALERT, "Can't accept connection: can't create client structure!");
Simple_Message(new_sock, "ERROR :Internal error");
io_close(new_sock);
return -1;
}
@ -1008,13 +1008,6 @@ New_Connection( int Sock )
My_Connections[new_sock].addr = new_addr;
My_Connections[new_sock].client = c;
/* register callback */
if (!io_event_create( new_sock, IO_WANTREAD, cb_clientserver)) {
Simple_Message( new_sock, "ERROR :Internal error" );
Conn_Close( new_sock, "io_event_create() failed", NULL, false );
return -1;
}
Log( LOG_INFO, "Accepted connection %d from %s:%d on socket %d.", new_sock,
inet_ntoa( new_addr.sin_addr ), ntohs( new_addr.sin_port), Sock );

View File

@ -12,7 +12,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: io.c,v 1.16 2006/07/23 23:11:44 alex Exp $";
static char UNUSED id[] = "$Id: io.c,v 1.16.2.1 2007/04/03 22:08:52 fw Exp $";
#include <assert.h>
#include <stdlib.h>
@ -34,25 +34,40 @@ typedef struct {
short what;
} io_event;
#define INIT_IOEVENT { NULL, -1, 0, NULL }
#define IO_ERROR 4
#define INIT_IOEVENT { NULL, -1, 0, NULL }
#define IO_ERROR 4
#ifdef HAVE_EPOLL_CREATE
#define IO_USE_EPOLL 1
# define IO_USE_EPOLL 1
# ifdef HAVE_SELECT
# define IO_USE_SELECT 1
# endif
#else
# ifdef HAVE_KQUEUE
#define IO_USE_KQUEUE 1
# else
#define IO_USE_SELECT 1
#endif
#endif
# ifdef HAVE_KQUEUE
# define IO_USE_KQUEUE 1
# else
# ifdef HAVE_SYS_DEVPOLL_H
# define IO_USE_DEVPOLL 1
# else
# ifdef HAVE_POLL
# define IO_USE_POLL 1
# else
# ifdef HAVE_SELECT
# define IO_USE_SELECT 1
# else
# error "no IO API available!?"
# endif /* HAVE_SELECT */
# endif /* HAVE_POLL */
# endif /* HAVE_SYS_DEVPOLL_H */
# endif /* HAVE_KQUEUE */
#endif /* HAVE_EPOLL_CREATE */
static bool library_initialized;
static bool library_initialized = false;
#ifdef IO_USE_EPOLL
#include <sys/epoll.h>
static int io_masterfd;
static int io_masterfd = -1;
static bool io_event_change_epoll(int fd, short what, const int action);
static int io_dispatch_epoll(struct timeval *tv);
#endif
@ -67,6 +82,22 @@ static int io_dispatch_kqueue(struct timeval *tv);
static bool io_event_change_kqueue(int, short, const int action);
#endif
#ifdef IO_USE_POLL
#include <poll.h>
static array pollfds;
static int poll_maxfd;
static bool io_event_change_poll(int fd, short what);
#endif
#ifdef IO_USE_DEVPOLL
#include <sys/devpoll.h>
static int io_masterfd;
static bool io_event_change_devpoll(int fd, short what);
#endif
#ifdef IO_USE_SELECT
#include "defines.h" /* for conn.h */
#include "conn.h" /* for CONN_IDX (needed by resolve.h) */
@ -77,7 +108,11 @@ static fd_set readers;
static fd_set writers;
static int select_maxfd; /* the select() interface sucks badly */
static int io_dispatch_select(struct timeval *tv);
#ifndef IO_USE_EPOLL
#define io_masterfd -1
#endif
#endif /* IO_USE_SELECT */
static array io_events;
@ -98,40 +133,45 @@ io_event_get(int fd)
}
bool
io_library_init(unsigned int eventsize)
#ifdef IO_USE_DEVPOLL
static void
io_library_init_devpoll(unsigned int eventsize)
{
#if defined(IO_USE_EPOLL) || defined(IO_USE_KQUEUE)
bool ret;
io_masterfd = open("/dev/poll", O_RDWR);
if (io_masterfd >= 0)
library_initialized = true;
Log(LOG_INFO, "IO subsystem: /dev/poll (initial maxfd %u, masterfd %d).",
eventsize, io_masterfd);
}
#endif
#ifdef IO_USE_EPOLL
int ecreate_hint = (int)eventsize;
if (ecreate_hint <= 0)
ecreate_hint = 128;
#ifdef IO_USE_POLL
static void
io_library_init_poll(unsigned int eventsize)
{
struct pollfd *p;
array_init(&pollfds);
poll_maxfd = 0;
Log(LOG_INFO, "IO subsystem: poll (initial maxfd %u).",
eventsize);
p = array_alloc(&pollfds, sizeof(struct pollfd), eventsize);
if (p) {
unsigned i;
p = array_start(&pollfds);
for (i = 0; i < eventsize; i++)
p[i].fd = -1;
library_initialized = true;
}
}
#endif
if (library_initialized)
return true;
#ifdef IO_USE_SELECT
#ifdef FD_SETSIZE
if (eventsize >= FD_SETSIZE)
eventsize = FD_SETSIZE - 1;
#endif
#endif
if ((eventsize > 0) && !array_alloc(&io_events, sizeof(io_event), (size_t)eventsize))
eventsize = 0;
#ifdef IO_USE_EPOLL
io_masterfd = epoll_create(ecreate_hint);
Log(LOG_INFO,
"IO subsystem: epoll (hint size %d, initial maxfd %u, masterfd %d).",
ecreate_hint, eventsize, io_masterfd);
ret = io_masterfd >= 0;
if (ret) library_initialized = true;
return ret;
#endif
#ifdef IO_USE_SELECT
static void
io_library_init_select(unsigned int eventsize)
{
Log(LOG_INFO, "IO subsystem: select (initial maxfd %u).",
eventsize);
FD_ZERO(&readers);
@ -144,24 +184,82 @@ io_library_init(unsigned int eventsize)
Conf_MaxConnections = FD_SETSIZE - 1;
}
#else
Log(LOG_WARNING,
"FD_SETSIZE undefined, don't know how many descriptors select() can handle on your platform ...");
#endif /* FD_SETSIZE */
library_initialized = true;
return true;
}
#endif /* SELECT */
#ifdef IO_USE_EPOLL
static void
io_library_init_epoll(unsigned int eventsize)
{
int ecreate_hint = (int)eventsize;
if (ecreate_hint <= 0)
ecreate_hint = 128;
io_masterfd = epoll_create(ecreate_hint);
if (io_masterfd >= 0) {
library_initialized = true;
Log(LOG_INFO,
"IO subsystem: epoll (hint size %d, initial maxfd %u, masterfd %d).",
ecreate_hint, eventsize, io_masterfd);
}
}
#endif
#ifdef IO_USE_KQUEUE
static void
io_library_init_kqueue(unsigned int eventsize)
{
io_masterfd = kqueue();
Log(LOG_INFO,
"IO subsystem: kqueue (initial maxfd %u, masterfd %d)",
eventsize, io_masterfd);
ret = io_masterfd >= 0;
if (ret) library_initialized = true;
return ret;
if (io_masterfd >= 0)
library_initialized = true;
}
#endif
bool
io_library_init(unsigned int eventsize)
{
if (library_initialized)
return true;
#ifdef IO_USE_SELECT
#ifndef FD_SETSIZE
Log(LOG_WARNING,
"FD_SETSIZE undefined, don't know how many descriptors select() can handle on your platform ...");
#else
if (eventsize >= FD_SETSIZE)
eventsize = FD_SETSIZE - 1;
#endif /* FD_SETSIZE */
#endif /* IO_USE_SELECT */
if ((eventsize > 0) && !array_alloc(&io_events, sizeof(io_event), (size_t)eventsize))
eventsize = 0;
#ifdef IO_USE_EPOLL
io_library_init_epoll(eventsize);
#ifdef IO_USE_SELECT
if (io_masterfd < 0)
Log(LOG_INFO, "Can't initialize epoll() IO interface, falling back to select() ...");
#endif
#endif
#ifdef IO_USE_KQUEUE
io_library_init_kqueue(eventsize);
#endif
#ifdef IO_USE_DEVPOLL
io_library_init_devpoll(eventsize);
#endif
#ifdef IO_USE_POLL
io_library_init_poll(eventsize);
#endif
#ifdef IO_USE_SELECT
if (! library_initialized)
io_library_init_select(eventsize);
#endif
return library_initialized;
}
@ -171,11 +269,15 @@ io_library_shutdown(void)
#ifdef IO_USE_SELECT
FD_ZERO(&readers);
FD_ZERO(&writers);
#else
close(io_masterfd); /* kqueue, epoll */
#endif
#ifdef IO_USE_EPOLL
if (io_masterfd >= 0)
close(io_masterfd);
io_masterfd = -1;
#endif
#ifdef IO_USE_KQUEUE
close(io_masterfd);
io_masterfd = -1;
array_free(&io_evcache);
#endif
library_initialized = false;
@ -201,18 +303,14 @@ io_event_create(int fd, short what, void (*cbfunc) (int, short))
io_event *i;
assert(fd >= 0);
#ifdef IO_USE_SELECT
#ifdef FD_SETSIZE
#if defined(IO_USE_SELECT) && defined(FD_SETSIZE)
if (fd >= FD_SETSIZE) {
Log(LOG_ERR,
"fd %d exceeds FD_SETSIZE (%u) (select can't handle more file descriptors)",
fd, FD_SETSIZE);
return false;
}
#endif /* FD_SETSIZE */
#endif /* IO_USE_SELECT */
#endif
i = (io_event *) array_alloc(&io_events, sizeof(io_event), (size_t) fd);
if (!i) {
Log(LOG_WARNING,
@ -223,6 +321,12 @@ io_event_create(int fd, short what, void (*cbfunc) (int, short))
i->callback = cbfunc;
i->what = 0;
#ifdef IO_USE_DEVPOLL
ret = io_event_change_devpoll(fd, what);
#endif
#ifdef IO_USE_POLL
ret = io_event_change_poll(fd, what);
#endif
#ifdef IO_USE_EPOLL
ret = io_event_change_epoll(fd, what, EPOLL_CTL_ADD);
#endif
@ -230,13 +334,57 @@ io_event_create(int fd, short what, void (*cbfunc) (int, short))
ret = io_event_change_kqueue(fd, what, EV_ADD|EV_ENABLE);
#endif
#ifdef IO_USE_SELECT
ret = io_event_add(fd, what);
if (io_masterfd < 0)
ret = io_event_add(fd, what);
#endif
if (ret) i->what = what;
return ret;
}
#ifdef IO_USE_DEVPOLL
static bool
io_event_change_devpoll(int fd, short what)
{
struct pollfd p;
p.events = 0;
if (what & IO_WANTREAD)
p.events = POLLIN | POLLPRI;
if (what & IO_WANTWRITE)
p.events |= POLLOUT;
p.fd = fd;
return write(io_masterfd, &p, sizeof p) == (ssize_t)sizeof p;
}
#endif
#ifdef IO_USE_POLL
static bool
io_event_change_poll(int fd, short what)
{
struct pollfd *p;
short events = 0;
if (what & IO_WANTREAD)
events = POLLIN | POLLPRI;
if (what & IO_WANTWRITE)
events |= POLLOUT;
p = array_alloc(&pollfds, sizeof *p, fd);
if (p) {
p->events = events;
p->fd = fd;
if (fd > poll_maxfd)
poll_maxfd = fd;
}
return p != NULL;
}
#endif
#ifdef IO_USE_EPOLL
static bool
io_event_change_epoll(int fd, short what, const int action)
@ -260,7 +408,7 @@ io_event_kqueue_commit_cache(void)
struct kevent *events;
bool ret;
int len = (int) array_length(&io_evcache, sizeof (struct kevent));
if (!len) /* nothing to do */
return true;
@ -293,7 +441,7 @@ io_event_change_kqueue(int fd, short what, const int action)
ret = array_catb(&io_evcache, (char*) &kev, sizeof (kev));
if (!ret)
ret = kevent(io_masterfd, &kev,1, NULL, 0, NULL) == 0;
}
}
if (ret && (what & IO_WANTWRITE)) {
EV_SET(&kev, fd, EVFILT_WRITE, action, 0, 0, 0);
@ -315,19 +463,27 @@ io_event_add(int fd, short what)
io_event *i = io_event_get(fd);
if (!i) return false;
if (i->what == what) return true;
if ((i->what & what) == what) /* event type is already registered */
return true;
#ifdef DEBUG_IO
Log(LOG_DEBUG, "io_event_add(): fd %d (arg: %d), what %d.", i->fd, fd, what);
Log(LOG_DEBUG, "io_event_add(): fd %d, what %d.", fd, what);
#endif
i->what |= what;
#ifdef IO_USE_EPOLL
return io_event_change_epoll(fd, i->what, EPOLL_CTL_MOD);
if (io_masterfd >= 0)
return io_event_change_epoll(fd, i->what, EPOLL_CTL_MOD);
#endif
#ifdef IO_USE_KQUEUE
return io_event_change_kqueue(fd, what, EV_ADD | EV_ENABLE);
#endif
#ifdef IO_USE_DEVPOLL
return io_event_change_devpoll(fd, i->what);
#endif
#ifdef IO_USE_POLL
return io_event_change_poll(fd, i->what);
#endif
#ifdef IO_USE_SELECT
if (fd > select_maxfd)
select_maxfd = fd;
@ -358,22 +514,77 @@ io_setnonblock(int fd)
}
#ifdef IO_USE_DEVPOLL
static void
io_close_devpoll(int fd)
{
struct pollfd p;
p.events = POLLREMOVE;
p.fd = fd;
write(io_masterfd, &p, sizeof p);
}
#else
static inline void io_close_devpoll(int UNUSED x) { /* NOTHING */ }
#endif
#ifdef IO_USE_POLL
static void
io_close_poll(int fd)
{
struct pollfd *p;
p = array_get(&pollfds, sizeof *p, fd);
if (!p) return;
p->fd = -1;
if (fd == poll_maxfd) {
while (poll_maxfd > 0) {
--poll_maxfd;
p = array_get(&pollfds, sizeof *p, poll_maxfd);
if (p && p->fd >= 0)
break;
}
}
}
#else
static inline void io_close_poll(int UNUSED x) { /* NOTHING */ }
#endif
#ifdef IO_USE_SELECT
static void
io_close_select(int fd)
{
io_event *i;
if (io_masterfd >= 0) /* Are we using epoll()? */
return;
FD_CLR(fd, &writers);
FD_CLR(fd, &readers);
i = io_event_get(fd);
if (!i) return;
if (fd == select_maxfd) {
while (select_maxfd>0) {
--select_maxfd; /* find largest fd */
i = io_event_get(select_maxfd);
if (i && i->callback) break;
}
}
}
#else
static inline void io_close_select(int UNUSED x) { /* NOTHING */ }
#endif
bool
io_close(int fd)
{
io_event *i;
#ifdef IO_USE_SELECT
FD_CLR(fd, &writers);
FD_CLR(fd, &readers);
if (fd == select_maxfd) {
while (select_maxfd>0) {
--select_maxfd; /* find largest fd */
i = io_event_get(select_maxfd);
if (i && i->callback) break;
}
}
#endif
i = io_event_get(fd);
#ifdef IO_USE_KQUEUE
if (array_length(&io_evcache, sizeof (struct kevent))) /* pending data in cache? */
@ -385,8 +596,13 @@ io_close(int fd)
if (i) {
io_event_change_kqueue(fd, i->what, EV_DELETE);
io_event_kqueue_commit_cache();
}
}
#endif
io_close_devpoll(fd);
io_close_poll(fd);
io_close_select(fd);
#ifdef IO_USE_EPOLL
io_event_change_epoll(fd, 0, EPOLL_CTL_DEL);
#endif
@ -409,8 +625,15 @@ io_event_del(int fd, short what)
i->what &= ~what;
#ifdef IO_USE_DEVPOLL
return io_event_change_devpoll(fd, i->what);
#endif
#ifdef IO_USE_POLL
return io_event_change_poll(fd, i->what);
#endif
#ifdef IO_USE_EPOLL
return io_event_change_epoll(fd, i->what, EPOLL_CTL_MOD);
if (io_masterfd >= 0)
return io_event_change_epoll(fd, i->what, EPOLL_CTL_MOD);
#endif
#ifdef IO_USE_KQUEUE
@ -465,6 +688,92 @@ io_dispatch_select(struct timeval *tv)
#endif
#ifdef IO_USE_DEVPOLL
static int
io_dispatch_devpoll(struct timeval *tv)
{
struct dvpoll dvp;
time_t sec = tv->tv_sec * 1000;
int i, total, ret, timeout = tv->tv_usec + sec;
short what;
struct pollfd p[100];
if (timeout < 0)
timeout = 1000;
total = 0;
do {
dvp.dp_timeout = timeout;
dvp.dp_nfds = 100;
dvp.dp_fds = p;
ret = ioctl(io_masterfd, DP_POLL, &dvp);
total += ret;
if (ret <= 0)
return total;
for (i=0; i < ret ; i++) {
what = 0;
if (p[i].revents & (POLLIN|POLLPRI))
what = IO_WANTREAD;
if (p[i].revents & POLLOUT)
what |= IO_WANTWRITE;
if (p[i].revents && !what) {
/* other flag is set, probably POLLERR */
what = IO_ERROR;
}
io_docallback(p[i].fd, what);
}
} while (ret == 100);
return total;
}
#endif
#ifdef IO_USE_POLL
static int
io_dispatch_poll(struct timeval *tv)
{
time_t sec = tv->tv_sec * 1000;
int i, ret, timeout = tv->tv_usec + sec;
int fds_ready;
short what;
struct pollfd *p = array_start(&pollfds);
if (timeout < 0)
timeout = 1000;
ret = poll(p, poll_maxfd + 1, timeout);
if (ret <= 0)
return ret;
fds_ready = ret;
for (i=0; i <= poll_maxfd; i++) {
what = 0;
if (p[i].revents & (POLLIN|POLLPRI))
what = IO_WANTREAD;
if (p[i].revents & POLLOUT)
what |= IO_WANTWRITE;
if (p[i].revents && !what) {
/* other flag is set, probably POLLERR */
what = IO_ERROR;
}
if (what) {
fds_ready--;
io_docallback(i, what);
}
if (fds_ready <= 0)
break;
}
return ret;
}
#endif
#ifdef IO_USE_EPOLL
static int
io_dispatch_epoll(struct timeval *tv)
@ -516,7 +825,7 @@ io_dispatch_kqueue(struct timeval *tv)
int newevents_len;
ts.tv_sec = tv->tv_sec;
ts.tv_nsec = tv->tv_usec * 1000;
do {
newevents_len = (int) array_length(&io_evcache, sizeof (struct kevent));
newevents = (newevents_len > 0) ? array_start(&io_evcache) : NULL;
@ -541,10 +850,10 @@ io_dispatch_kqueue(struct timeval *tv)
#ifdef DEBUG
LogDebug("kev.flag has EV_EOF set, setting IO_ERROR",
kev[i].filter, kev[i].ident);
#endif
#endif
io_docallback((int)kev[i].ident, IO_ERROR);
continue;
}
}
switch (kev[i].filter) {
case EVFILT_READ:
@ -575,14 +884,21 @@ io_dispatch_kqueue(struct timeval *tv)
int
io_dispatch(struct timeval *tv)
{
#ifdef IO_USE_EPOLL
if (io_masterfd >= 0)
return io_dispatch_epoll(tv);
#endif
#ifdef IO_USE_SELECT
return io_dispatch_select(tv);
#endif
#ifdef IO_USE_KQUEUE
return io_dispatch_kqueue(tv);
#endif
#ifdef IO_USE_EPOLL
return io_dispatch_epoll(tv);
#ifdef IO_USE_DEVPOLL
return io_dispatch_devpoll(tv);
#endif
#ifdef IO_USE_POLL
return io_dispatch_poll(tv);
#endif
}
@ -597,9 +913,9 @@ io_docallback(int fd, short what)
#endif
i = io_event_get(fd);
if (i->callback) { /* callback might be NULL if a previous callback function
if (i->callback) { /* callback might be NULL if a previous callback function
called io_close on this fd */
i->callback(fd, (what & IO_ERROR) ? i->what : what);
}
}
/* if error indicator is set, we return the event(s) that were registered */
}

View File

@ -7,10 +7,10 @@
*
* I/O abstraction interface header
*
* $Id: io.h,v 1.3 2005/07/14 09:15:58 alex Exp $
* $Id: io.h,v 1.3.2.1 2007/04/03 22:08:52 fw Exp $
*/
#ifndef io_H_inclucded
#ifndef io_H_included
#define io_H_included
#include "portab.h"

View File

@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: lists.c,v 1.18.2.2 2007/04/03 20:23:31 fw Exp $";
static char UNUSED id[] = "$Id: lists.c,v 1.18.2.3 2007/04/03 22:08:52 fw Exp $";
#include "imp.h"
#include <assert.h>
@ -80,7 +80,7 @@ Lists_Add(struct list_head *header, const char *Mask, bool OnlyOnce )
newelem = malloc(sizeof(struct list_elem));
if( ! newelem ) {
Log( LOG_EMERG, "Can't allocate memory for new Ban/Invite entry!" );
return NULL;
return false;
}
strlcpy( newelem->mask, Mask, sizeof( newelem->mask ));