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:
@@ -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
@@ -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
@@ -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
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user