commit - 5c3e02393b5d12c00f68d5216f45bb5281b0cea9
commit + f67ad15a36ca6c284e5d7f27ba6762eae9a5a3e5
blob - fbce09f68a8fd0fda303107ba4d8e0380ea428a9
blob + ab1191cf4ef7b95c0adfa0868bd2c65c636dc624
--- ChangeLog
+++ ChangeLog
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)
--
-$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 $
blob - 19b554242453fcc6095a7b3409bb34d7b778a1cc
blob + fdf324471ff27613c6024293c2f8448012aefa5e
--- INSTALL
+++ INSTALL
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>]
--
-$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 $
blob - b5c9cb7c653eda56b8d3b07e47ce78d718466a4d
blob + 0391335fc3e48db443a59db75bd8bcc6a7b958d4
--- configure.in
+++ configure.in
#
# 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
# (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)
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)],
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)],
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"
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
],
AC_CHECK_FUNCS(kqueue, x_io_backend=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,
]
)
+# include support for "zeroconf"?
+
x_zeroconf_on=no
AC_ARG_WITH(zeroconf,
[ --with-zeroconf enable support for "Zeroconf"],
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],
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],
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)],
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
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!],
blob - 62373868818b6882e72048481202b270959cdee9
blob + 74435aa8861eb31b788141269dc865cafd0549d1
--- contrib/Debian/ngircd.init
+++ contrib/Debian/ngircd.init
#
# 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
blob - 18e4d900cf7334a9b3b7f93f003cdbf5c3142e39
blob + 2b731aac22d96d08a96930fcba9319cfb04f6377
--- doc/Platforms.txt
+++ doc/Platforms.txt
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
(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 $
blob - 87dbe8bdae302ca7e52b44aedc5779d988113d09
blob + 5d5bc1cc0eccb7cef605af40fec047bcf287ca0d
--- doc/sample-ngircd.conf
+++ doc/sample-ngircd.conf
-# $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
;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 ...
blob - 40a0c09d239db29a150c3e3f5ae84d72605097c7
blob + b2d0fb553b3be566b7de1da801e604e448eedd6f
--- doc/src/Makefile.am
+++ doc/src/Makefile.am
# (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 \
blob - bd18cd6f47ae2ceb43cce96869176484c5961686
blob + b523240694a2e965346c6feea58d942d5a3bb681
--- src/ngircd/array.c
+++ src/ngircd/array.c
#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>
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);
blob - 294e90673326adb03fd7cdb0c21b65209b2adef6
blob + 94993d4c12578bf957ba0a6dabd1638cef048817
--- src/ngircd/channel.c
+++ src/ngircd/channel.c
#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>
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 );
}
{
CHANNEL *c, *c_next;
CL2CHAN *cl2chan, *cl2chan_next;
-
+
/* Channel-Strukturen freigeben */
c = My_Channels;
while( c )
blob - e92d7c3ae18b441667d80fc30b0becde862b061b
blob + 3795b0e98c0bba13d29de6c400e15fb6f43bccd1
--- src/ngircd/client.c
+++ src/ngircd/client.c
#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>
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;
c = (CLIENT *)c->next;
}
} /* 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 */
Client_User( CLIENT *Client )
{
assert( Client != NULL );
- if( Client->user[0] ) return Client->user;
- else return "~";
+ return Client->user[0] ? Client->user : "~";
} /* Client_User */
Client_MyServerCount( void )
{
CLIENT *c;
- unsigned long cnt;
+ unsigned long cnt = 0;
- cnt = 0;
c = My_Clients;
while( c )
{
Client_OperCount( void )
{
CLIENT *c;
- unsigned long cnt;
+ unsigned long cnt = 0;
- cnt = 0;
c = My_Clients;
while( c )
{
blob - 3e81a01faf7ae02a790c2ff9ece2626ba02d1f4d
blob + 9c8013737018ad329cc09d3f718735fac58879ae
--- src/ngircd/client.h
+++ src/ngircd/client.h
* (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)
*/
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 ));
blob - 10821292fd78f6d17bffd3151bb2079d6f240c35
blob + 6dc99772330d36ead686e9ab41b369b78d11f889
--- src/ngircd/conf.c
+++ src/ngircd/conf.c
#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>
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 : "");
/* 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++;
}
/* Initial topic */
if (!array_copys( &Conf_Channel[chancount].topic, Arg))
Config_Error_TooLong( Line, Var );
+ 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 */
blob - 391adef3f70652a63f5c6d7ee4e13614830766ae
blob + 5ef603c6e335bf0c634ecda3b850544a1c67610e
--- src/ngircd/conf.h
+++ src/ngircd/conf.h
* (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)
*/
{
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;
blob - 9da3dfb80418591d247c39b3adff6d031177d0ae
blob + 3259c3907e6be438d12e0f8a4b5fa53a4c374b2d
--- src/ngircd/conn-func.h
+++ src/ngircd/conn-func.h
* (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)
*/
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
blob - f5799e7f041523cbe6abaeea3b8d3a7db97e6160
blob + 03163e5577bf7e4953693bde5cbdae7984b8dcef
--- src/ngircd/conn.c
+++ src/ngircd/conn.c
#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>
{
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?!");
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;
}
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;
}
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;
}
My_Connections[new_sock].sock = new_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 );
blob - dd9b05f89e074e34052d66f81d2e95bac063ed6c
blob + 4733fd5240f0918ec5ace97affe2cc0e7aa29315
--- src/ngircd/io.c
+++ src/ngircd/io.c
#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>
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
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) */
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;
}
-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;
-#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;
+#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;
- return ret;
+ library_initialized = true;
+ }
+}
#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);
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;
+ if (io_masterfd >= 0)
+ library_initialized = true;
+}
+#endif
- return ret;
+
+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;
}
#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;
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,
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
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)
struct kevent *events;
bool ret;
int len = (int) array_length(&io_evcache, sizeof (struct kevent));
-
+
if (!len) /* nothing to do */
return true;
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);
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;
}
-bool
-io_close(int fd)
+#ifdef IO_USE_DEVPOLL
+static void
+io_close_devpoll(int fd)
{
- io_event *i;
+ 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 */
+ --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;
+
i = io_event_get(fd);
#ifdef IO_USE_KQUEUE
if (array_length(&io_evcache, sizeof (struct kevent))) /* pending data in cache? */
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
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
#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)
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;
#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:
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
}
#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 */
}
blob - dfc27b076fe740f8008cfe1e45c32c56fe1fa15c
blob + 150cc5186dbdc44cf44bd253b4d1ddf5bca0d189
--- src/ngircd/io.h
+++ src/ngircd/io.h
*
* 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"
blob - 217b79aa0bbdc9e4c3f3ed25e811a2fa29871c35
blob + 2f27687a61d04fbce2624807537c26b99726b611
--- src/ngircd/lists.c
+++ src/ngircd/lists.c
#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>
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 ));