1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-07-08 06:43:12 +02:00

- Add support for proper FD accounting (rewrite of the fdlist code).

This is the first step to adding evented I/O.  Infact, writing the evented I/O code
  should now be quite easy.
This commit is contained in:
William Pitcock
2012-10-05 03:42:44 +00:00
parent b1b3f25278
commit b26207df50
10 changed files with 206 additions and 26 deletions
+22
View File
@@ -3,6 +3,28 @@
/* $Id$ */
#define FD_DESC_SZ (100)
typedef void (*IOCallbackFunc)(int fd, void *data);
typedef struct fd_entry {
int fd;
char desc[FD_DESC_SZ];
IOCallbackFunc read_callback;
IOCallbackFunc write_callback;
void *data;
time_t deadline;
unsigned char is_open;
} FDEntry;
extern MODVAR FDEntry fd_table[MAXCONNECTIONS + 1];
extern int fd_open(int fd, const char *desc);
extern void fd_close(int fd);
extern int fd_socket(int family, int type, int protocol, const char *desc);
extern int fd_accept(int sockfd);
extern void fd_desc(int fd, const char *desc);
typedef struct fdstruct {
int entry[MAXCONNECTIONS + 2];
int last_entry;
+105
View File
@@ -28,6 +28,111 @@
#include "proto.h"
#include <string.h>
/* new FD management code, based on mowgli.eventloop from atheme, hammered into Unreal by
* me, nenolod.
*/
FDEntry fd_table[MAXCONNECTIONS + 1];
int fd_open(int fd, const char *desc)
{
FDEntry *fde;
if ((fd < 0) || (fd >= MAXCONNECTIONS))
{
sendto_realops("[BUG] trying to add fd #%d to fd table, but MAXCONNECTIONS is %d",
fd, MAXCONNECTIONS);
ircd_log(LOG_ERROR, "[BUG] trying to add fd #%d to fd table, but MAXCONNECTIONS is %d",
fd, MAXCONNECTIONS);
return -1;
}
fde = &fd_table[fd];
memset(fde, 0, sizeof(FDEntry));
fde->fd = fd;
fde->is_open = 1;
strlcpy(fde->desc, desc, FD_DESC_SZ);
return fde->fd;
}
void fd_close(int fd)
{
FDEntry *fde;
if ((fd < 0) || (fd >= MAXCONNECTIONS))
{
sendto_realops("[BUG] trying to close fd #%d in fd table, but MAXCONNECTIONS is %d",
fd, MAXCONNECTIONS);
ircd_log(LOG_ERROR, "[BUG] trying to close fd #%d in fd table, but MAXCONNECTIONS is %d",
fd, MAXCONNECTIONS);
return;
}
fde = &fd_table[fd];
if (!fde->is_open)
{
sendto_realops("[BUG] trying to close fd #%d in fd table, but this FD isn't reported open",
fd, MAXCONNECTIONS);
ircd_log(LOG_ERROR, "[BUG] trying to close fd #%d in fd table, but this FD isn't reported open",
fd, MAXCONNECTIONS);
return;
}
memset(fde, 0, sizeof(FDEntry));
CLOSE_SOCK(fd);
}
int fd_socket(int family, int type, int protocol, const char *desc)
{
int fd;
fd = socket(family, type, protocol);
if (fd < 0)
return -1;
return fd_open(fd, desc);
}
int fd_accept(int sockfd)
{
const char buf[] = "Incoming connection";
int fd;
fd = accept(sockfd, NULL, NULL);
if (fd < 0)
return -1;
return fd_open(fd, buf);
}
void fd_desc(int fd, const char *desc)
{
FDEntry *fde;
if ((fd < 0) || (fd >= MAXCONNECTIONS))
{
sendto_realops("[BUG] trying to modify fd #%d in fd table, but MAXCONNECTIONS is %d",
fd, MAXCONNECTIONS);
ircd_log(LOG_ERROR, "[BUG] trying to modify fd #%d in fd table, but MAXCONNECTIONS is %d",
fd, MAXCONNECTIONS);
return;
}
fde = &fd_table[fd];
if (!fde->is_open)
{
sendto_realops("[BUG] trying to modify fd #%d in fd table, but this FD isn't reported open",
fd, MAXCONNECTIONS);
ircd_log(LOG_ERROR, "[BUG] trying to modify fd #%d in fd table, but this FD isn't reported open",
fd, MAXCONNECTIONS);
return;
}
strlcpy(fde->desc, desc, FD_DESC_SZ);
}
extern fdlist default_fdlist;
extern fdlist busycli_fdlist;
extern fdlist serv_fdlist;
+1 -1
View File
@@ -650,7 +650,7 @@ extern TS check_pings(TS currenttime)
if (!IsRegistered(cptr) && (DoingDNS(cptr) || DoingAuth(cptr)))
{
if (cptr->authfd >= 0) {
CLOSE_SOCK(cptr->authfd);
fd_close(cptr->authfd);
--OpenFiles;
cptr->authfd = -1;
cptr->count = 0;
+11 -1
View File
@@ -116,7 +116,7 @@ DLLFUNC CMD_FUNC(m_nick)
int ishold;
aClient *acptr, *serv = NULL;
aClient *acptrs;
char nick[NICKLEN + 2], *s;
char nick[NICKLEN + 2], *s, descbuf[BUFSIZE];
Membership *mp;
time_t lastnick = (time_t) 0;
int differ = 1, update_watch = 1;
@@ -770,6 +770,11 @@ DLLFUNC CMD_FUNC(m_nick)
if (IsPerson(sptr))
hash_check_watch(sptr, RPL_LOGOFF);
}
/* update fdlist --nenolod */
snprintf(descbuf, sizeof descbuf, "Client: %s", nick);
fd_desc(sptr->fd, descbuf);
(void)strcpy(sptr->name, nick);
(void)add_to_client_hash_table(nick, sptr);
if (IsServer(cptr) && parc > 7)
@@ -1049,6 +1054,11 @@ int _register_user(aClient *cptr, aClient *sptr, char *nick, char *username, cha
if (MyConnect(sptr))
{
char descbuf[BUFSIZE];
snprintf(descbuf, sizeof descbuf, "Client: %s", nick);
fd_desc(sptr->fd, descbuf);
IRCstats.unknown--;
IRCstats.me_clients++;
if (IsHidden(sptr))
+5
View File
@@ -311,6 +311,7 @@ DLLFUNC CMD_FUNC(m_server)
char *servername = NULL; /* Pointer for servername */
/* char *password = NULL; */
char *ch = NULL; /* */
char descbuf[BUFSIZE];
char *inpath = get_client_name(cptr, TRUE);
int hop = 0, numeric = 0;
char info[REALLEN + 61];
@@ -526,6 +527,10 @@ DLLFUNC CMD_FUNC(m_server)
}
if (aconf->options & CONNECT_QUARANTINE)
cptr->flags |= FLAGS_QUARANTINE;
snprintf(descbuf, sizeof descbuf, "Server: %s", servername);
fd_desc(cptr->fd, descbuf);
/* Start synch now */
if (m_server_synch(cptr, numeric, aconf) == FLUSH_BUFFER)
return FLUSH_BUFFER;
+21
View File
@@ -119,6 +119,7 @@ int stats_class(aClient *, char *);
int stats_zip(aClient *, char *);
int stats_officialchannels(aClient *, char *);
int stats_spamfilter(aClient *, char *);
int stats_fdtable(aClient *, char *);
#define SERVER_AS_PARA 0x1
#define FLAGS_AS_PARA 0x2
@@ -152,6 +153,7 @@ struct statstab StatsTable[] = {
{ 'T', "traffic", stats_traffic, 0 },
{ 'U', "uline", stats_uline, 0 },
{ 'V', "vhost", stats_vhost, 0 },
{ 'W', "fdtable", stats_fdtable, 0 },
{ 'X', "notlink", stats_notlink, 0 },
{ 'Y', "class", stats_class, 0 },
{ 'Z', "mem", stats_mem, 0 },
@@ -309,6 +311,8 @@ inline void stats_help(aClient *sptr)
"v - denyver - Send the deny version block list");
sendto_one(sptr, rpl_str(RPL_STATSHELP), me.name, sptr->name,
"V - vhost - Send the vhost block list");
sendto_one(sptr, rpl_str(RPL_STATSHELP), me.name, sptr->name,
"W - fdtable - Send the FD table listing");
sendto_one(sptr, rpl_str(RPL_STATSHELP), me.name, sptr->name,
"X - notlink - Send the list of servers that are not current linked");
sendto_one(sptr, rpl_str(RPL_STATSHELP), me.name, sptr->name,
@@ -799,6 +803,23 @@ int stats_traffic(aClient *sptr, char *para)
return 0;
}
int stats_fdtable(aClient *sptr, char *para)
{
int i;
for (i = 0; i < MAXCONNECTIONS; i++)
{
FDEntry *fde = &fd_table[i];
if (!fde->is_open)
continue;
sendto_one(sptr,
":%s %d %s :fd %3d, desc '%s', read-hdl %p, write-hdl %p, cbdata %p",
me.name, RPL_STATSDEBUG, sptr->name,
fde->fd, fde->desc, fde->read_callback, fde->write_callback, fde->data);
}
}
int stats_uline(aClient *sptr, char *para)
{
+12 -1
View File
@@ -81,13 +81,14 @@ static DNSReq *requests = NULL; /**< Linked list of requests (pending responses)
static DNSCache *cache_list = NULL; /**< Linked list of cache */
static DNSCache *cache_hashtbl[DNS_HASH_SIZE]; /**< Hash table of cache */
static ares_socket_t aresfds[ARES_GETSOCK_MAXNUM];
static unsigned int unrealdns_num_cache = 0; /**< # of cache entries in memory */
void init_resolver(int firsttime)
{
struct ares_options options;
int n;
int n, v, k;
int optmask;
if (requests)
@@ -139,10 +140,17 @@ int optmask;
NAME_SERVER);
MyFree(options.servers);
}
memset(&aresfds, 0, sizeof(aresfds));
v = ares_getsock(resolver_channel, aresfds, ARES_GETSOCK_MAXNUM);
for (k = 0; k < ARES_GETSOCK_MAXNUM; k++)
fd_open(aresfds[k], "DNS Resolver Socket");
}
void reinit_resolver(aClient *sptr)
{
int k;
#ifdef CHROOTDIR
/* Prevent people from killing their ircd accidently if in CHROOTDIR mode... */
FILE *fd;
@@ -159,6 +167,9 @@ FILE *fd;
fclose(fd);
#endif
for (k = 0; k < ARES_GETSOCK_MAXNUM; k++)
fd_close(aresfds[k]);
sendto_realops("%s requested reinitalization of resolver!", sptr->name);
sendto_realops("Destroying resolver channel, along with all currently pending queries...");
ares_destroy(resolver_channel);
+7 -5
View File
@@ -50,7 +50,7 @@ void ident_failed(aClient *cptr)
ircstp->is_abad++;
if (cptr->authfd != -1)
{
CLOSE_SOCK(cptr->authfd);
fd_close(cptr->authfd);
--OpenFiles;
cptr->authfd = -1;
}
@@ -74,14 +74,16 @@ void start_auth(aClient *cptr)
{
struct SOCKADDR_IN sock, us;
int len;
char buf[BUFSIZE];
if (IDENT_CHECK == 0) {
cptr->flags &= ~(FLAGS_WRAUTH | FLAGS_AUTH);
return;
}
Debug((DEBUG_NOTICE, "start_auth(%x) slot=%d, fd=%d, status=%d",
cptr, cptr->slot, cptr->fd, cptr->status));
if ((cptr->authfd = socket(AFINET, SOCK_STREAM, 0)) == -1)
snprintf(buf, sizeof buf, "identd: %s", get_client_name(cptr, TRUE));
if ((cptr->authfd = fd_socket(AFINET, SOCK_STREAM, 0, buf)) == -1)
{
Debug((DEBUG_ERROR, "Unable to create auth socket for %s:%s",
get_client_name(cptr, TRUE), strerror(get_sockerr(cptr))));
@@ -91,7 +93,7 @@ void start_auth(aClient *cptr)
if (++OpenFiles >= (MAXCONNECTIONS - 2))
{
sendto_ops("Can't allocate fd, too many connections.");
CLOSE_SOCK(cptr->authfd);
fd_close(cptr->authfd);
--OpenFiles;
cptr->authfd = -1;
return;
@@ -230,7 +232,7 @@ void read_authports(aClient *cptr)
Debug((DEBUG_ERROR, "bad auth reply in [%s]", cptr->buffer));
*ruser = '\0';
}
CLOSE_SOCK(cptr->authfd);
fd_close(cptr->authfd);
--OpenFiles;
cptr->authfd = -1;
cptr->count = 0;
+18 -16
View File
@@ -271,12 +271,12 @@ void close_connections(void)
if ((cptr = local[i]) != 0)
{
if (cptr->fd >= 0) {
CLOSE_SOCK(cptr->fd);
fd_close(cptr->fd);
cptr->fd = -2;
}
if (cptr->authfd >= 0)
{
CLOSE_SOCK(cptr->authfd);
fd_close(cptr->authfd);
cptr->authfd = -1;
}
}
@@ -450,7 +450,7 @@ int inetport(aClient *cptr, char *name, int port)
*/
if (cptr->fd == -1)
{
cptr->fd = socket(AFINET, SOCK_STREAM, 0);
cptr->fd = fd_socket(AFINET, SOCK_STREAM, 0, "Listener socket");
}
if (cptr->fd < 0)
{
@@ -462,7 +462,7 @@ int inetport(aClient *cptr, char *name, int port)
else if (++OpenFiles >= MAXCLIENTS)
{
sendto_ops("No more connections allowed (%s)", cptr->name);
CLOSE_SOCK(cptr->fd);
fd_close(cptr->fd);
cptr->fd = -1;
--OpenFiles;
return -1;
@@ -511,7 +511,7 @@ int inetport(aClient *cptr, char *name, int port)
"and/or via sysctl.");
}
#endif
CLOSE_SOCK(cptr->fd);
fd_close(cptr->fd);
cptr->fd = -1;
--OpenFiles;
return -1;
@@ -520,7 +520,7 @@ int inetport(aClient *cptr, char *name, int port)
if (getsockname(cptr->fd, (struct SOCKADDR *)&server, &len))
{
report_error("getsockname failed for %s:%s", cptr);
CLOSE_SOCK(cptr->fd);
fd_close(cptr->fd);
cptr->fd = -1;
--OpenFiles;
return -1;
@@ -1027,7 +1027,7 @@ void close_connection(aClient *cptr)
if (cptr->authfd >= 0)
{
CLOSE_SOCK(cptr->authfd);
fd_close(cptr->authfd);
cptr->authfd = -1;
--OpenFiles;
}
@@ -1044,7 +1044,7 @@ void close_connection(aClient *cptr)
cptr->ssl = NULL;
}
#endif
CLOSE_SOCK(cptr->fd);
fd_close(cptr->fd);
cptr->fd = -2;
--OpenFiles;
DBufClear(&cptr->sendQ);
@@ -1094,7 +1094,7 @@ void close_connection(aClient *cptr)
addto_fdlist(i, &oper_fdlist);
}
#endif
CLOSE_SOCK(j);
fd_close(j);
--OpenFiles;
}
#endif
@@ -1333,7 +1333,7 @@ add_con_refuse:
ircstp->is_ref++;
acptr->fd = -2;
free_client(acptr);
CLOSE_SOCK(fd);
fd_close(fd);
--OpenFiles;
return NULL;
}
@@ -1925,7 +1925,7 @@ int read_message(time_t delay, fdlist *listp)
(OPT_TYPE *)&err, &len) || err)
{
ircstp->is_abad++;
closesocket(cptr->authfd);
fd_close(cptr->authfd);
cptr->authfd = -1;
--OpenFiles;
cptr->flags &= ~(FLAGS_AUTH | FLAGS_WRAUTH);
@@ -2002,7 +2002,7 @@ int read_message(time_t delay, fdlist *listp)
*/
for (k = 0; k < LISTEN_SIZE; k++)
{ {
if ((fd = accept(cptr->fd, NULL, NULL)) < 0)
if ((fd = fd_accept(cptr->fd)) < 0)
{
if ((ERRNO != P_EWOULDBLOCK) && (ERRNO != P_ECONNABORTED))
report_baderror("Cannot accept connections %s:%s", cptr);
@@ -2045,7 +2045,7 @@ int read_message(time_t delay, fdlist *listp)
"ERROR :All connections in use\r\n",
31, 0, 0, 0);
#endif
CLOSE_SOCK(fd);
fd_close(fd);
--OpenFiles;
break;
}
@@ -2300,7 +2300,7 @@ int connect_server(ConfigItem_link *aconf, aClient *by, struct hostent *hp)
{
if (cptr->fd >= 0)
{
CLOSE_SOCK(cptr->fd);
fd_close(cptr->fd);
--OpenFiles;
}
cptr->fd = -2;
@@ -2325,7 +2325,7 @@ int connect_server(ConfigItem_link *aconf, aClient *by, struct hostent *hp)
sendto_one(by,
":%s NOTICE %s :*** Connect to host %s failed.",
me.name, by->name, cptr->name);
CLOSE_SOCK(cptr->fd);
fd_close(cptr->fd);
--OpenFiles;
cptr->fd = -2;
free_client(cptr);
@@ -2378,12 +2378,14 @@ static struct SOCKADDR *connect_inet(ConfigItem_link *aconf, aClient *cptr, int
{
static struct SOCKADDR_IN server;
struct hostent *hp;
char buf[BUFSIZE];
/*
* Might as well get sockhost from here, the connection is attempted
* with it so if it fails its useless.
*/
cptr->fd = socket(AFINET, SOCK_STREAM, 0);
snprintf(buf, sizeof buf, "Outgoing connection: %s", get_client_name(cptr, TRUE));
cptr->fd = fd_socket(AFINET, SOCK_STREAM, 0, buf);
if (cptr->fd < 0)
{
if (ERRNO == P_EMFILE)
+4 -2
View File
@@ -163,7 +163,9 @@ int succesfully_sent = 0;
n = 0;
for (servname = strtoken(&p, tmptimeservbuf, ","); servname; servname = strtoken(&p, NULL, ","))
{
s[n] = socket(AF_INET, SOCK_DGRAM, 0); /* always ipv4 */
char buf[BUFSIZE];
snprintf(buf, sizeof buf, "ntp client: %s", servname);
s[n] = fd_socket(AF_INET, SOCK_DGRAM, 0, buf); /* always ipv4 */
if (s[n] < 0)
{
ircsprintf(tserr, "unable to create socket: %s [%d]", STRERROR(ERRNO), (int)ERRNO);
@@ -281,7 +283,7 @@ gotit:
end:
for (i = 0; i < numservers; i++)
CLOSE_SOCK(s[i]);
fd_close(s[i]);
return reply;
}