2020-03-29 09:16:53 +00:00
|
|
|
/*
|
|
|
|
* UnrealIRCd, src/fdlist.c
|
|
|
|
* Copyright (c) 2012 William Pitcock <nenolod@dereferenced.org>
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
* the Free Software Foundation; either version 1, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "unrealircd.h"
|
|
|
|
|
2023-05-05 22:12:01 +00:00
|
|
|
/* new FD management code, based on mowgli.eventloop from atheme, hammered into UnrealIRCd by
|
2020-03-29 09:16:53 +00:00
|
|
|
* me, nenolod.
|
|
|
|
*/
|
|
|
|
FDEntry fd_table[MAXCONNECTIONS + 1];
|
|
|
|
|
2022-01-15 05:16:34 +00:00
|
|
|
/** Notify I/O engine that a file descriptor opened.
|
|
|
|
* @param fd The file descriptor
|
|
|
|
* @param desc Description for in the fd table
|
|
|
|
* @param close_method Tell what a subsequent call to fd_close() should do,
|
|
|
|
* eg close the socket, file or don't close anything.
|
|
|
|
* @returns The file descriptor 'fd' or -1 in case of fatal error.
|
|
|
|
*/
|
|
|
|
int fd_open(int fd, const char *desc, FDCloseMethod close_method)
|
2020-03-29 09:16:53 +00:00
|
|
|
{
|
|
|
|
FDEntry *fde;
|
|
|
|
|
|
|
|
if ((fd < 0) || (fd >= MAXCONNECTIONS))
|
|
|
|
{
|
2022-01-15 05:16:34 +00:00
|
|
|
unreal_log(ULOG_ERROR, "io", "BUG_FD_OPEN_OUT_OF_RANGE", NULL,
|
|
|
|
"[BUG] trying to add fd $fd to fd table, but MAXCONNECTIONS is $maxconnections",
|
|
|
|
log_data_integer("fd", fd),
|
|
|
|
log_data_integer("maxconnections", MAXCONNECTIONS));
|
2020-03-29 09:16:53 +00:00
|
|
|
#ifdef DEBUGMODE
|
|
|
|
abort();
|
|
|
|
#endif
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
fde = &fd_table[fd];
|
|
|
|
memset(fde, 0, sizeof(FDEntry));
|
|
|
|
|
|
|
|
fde->fd = fd;
|
|
|
|
fde->is_open = 1;
|
|
|
|
fde->backend_flags = 0;
|
2022-01-15 05:16:34 +00:00
|
|
|
fde->close_method = close_method;
|
2020-03-29 09:16:53 +00:00
|
|
|
strlcpy(fde->desc, desc, FD_DESC_SZ);
|
|
|
|
|
|
|
|
return fde->fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
# define OPEN_MODES S_IRUSR|S_IWUSR
|
|
|
|
#else
|
|
|
|
# define OPEN_MODES S_IREAD|S_IWRITE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int fd_fileopen(const char *path, unsigned int flags)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
char comment[FD_DESC_SZ];
|
|
|
|
char pathbuf[BUFSIZE];
|
|
|
|
|
|
|
|
fd = open(path, flags, OPEN_MODES);
|
|
|
|
if (fd < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
strlcpy(pathbuf, path, sizeof pathbuf);
|
|
|
|
|
|
|
|
snprintf(comment, sizeof comment, "File: %s", unreal_getfilename(pathbuf));
|
|
|
|
|
2022-01-15 05:16:34 +00:00
|
|
|
return fd_open(fd, comment, FDCLOSE_FILE);
|
2020-03-29 09:16:53 +00:00
|
|
|
}
|
|
|
|
|
2022-01-15 05:16:34 +00:00
|
|
|
/** Internal function to unmap and optionally close the fd.
|
|
|
|
*/
|
|
|
|
/** Remove file descriptor from our table and possibly close the fd.
|
|
|
|
* The fd is closed (or not) according to the method specified in fd_open().
|
|
|
|
* @param fd The file descriptor
|
|
|
|
* @returns 1 on success, 0 on failure
|
|
|
|
*/
|
|
|
|
int fd_close(int fd)
|
2020-03-29 09:16:53 +00:00
|
|
|
{
|
|
|
|
FDEntry *fde;
|
|
|
|
unsigned int befl;
|
2022-01-15 05:16:34 +00:00
|
|
|
FDCloseMethod close_method;
|
2020-03-29 09:16:53 +00:00
|
|
|
|
|
|
|
if ((fd < 0) || (fd >= MAXCONNECTIONS))
|
|
|
|
{
|
2022-01-15 05:16:34 +00:00
|
|
|
unreal_log(ULOG_ERROR, "io", "BUG_FD_CLOSE_OUT_OF_RANGE", NULL,
|
|
|
|
"[BUG] trying to close fd $fd to fd table, but MAXCONNECTIONS is $maxconnections",
|
|
|
|
log_data_integer("fd", fd),
|
|
|
|
log_data_integer("maxconnections", MAXCONNECTIONS));
|
2020-03-29 09:16:53 +00:00
|
|
|
#ifdef DEBUGMODE
|
|
|
|
abort();
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
fde = &fd_table[fd];
|
|
|
|
if (!fde->is_open)
|
|
|
|
{
|
2022-01-15 05:16:34 +00:00
|
|
|
unreal_log(ULOG_ERROR, "io", "BUG_FD_CLOSE_NOT_OPEN", NULL,
|
|
|
|
"[BUG] trying to close fd $fd to fd table, but FD is (already) closed",
|
|
|
|
log_data_integer("fd", fd));
|
2020-03-29 09:16:53 +00:00
|
|
|
#ifdef DEBUGMODE
|
|
|
|
abort();
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
befl = fde->backend_flags;
|
2022-01-15 05:16:34 +00:00
|
|
|
close_method = fde->close_method;
|
2020-03-29 09:16:53 +00:00
|
|
|
memset(fde, 0, sizeof(FDEntry));
|
|
|
|
|
|
|
|
fde->fd = fd;
|
|
|
|
|
|
|
|
/* only notify the backend if it is actively tracking the FD */
|
|
|
|
if (befl)
|
|
|
|
fd_refresh(fd);
|
|
|
|
|
2022-01-15 05:16:34 +00:00
|
|
|
/* Finally, close the file or socket if requested to do so */
|
|
|
|
switch (close_method)
|
|
|
|
{
|
|
|
|
case FDCLOSE_SOCKET:
|
|
|
|
CLOSE_SOCK(fd);
|
|
|
|
break;
|
|
|
|
case FDCLOSE_FILE:
|
|
|
|
close(fd);
|
|
|
|
break;
|
|
|
|
case FDCLOSE_NONE:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2020-03-29 09:16:53 +00:00
|
|
|
|
2022-01-15 05:16:34 +00:00
|
|
|
return 1;
|
2020-03-29 09:16:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Deregister I/O notification for this file descriptor */
|
|
|
|
void fd_unnotify(int fd)
|
|
|
|
{
|
2022-01-15 05:16:34 +00:00
|
|
|
FDEntry *fde;
|
|
|
|
|
2020-03-29 09:16:53 +00:00
|
|
|
if ((fd < 0) || (fd >= MAXCONNECTIONS))
|
|
|
|
return;
|
|
|
|
|
|
|
|
fde = &fd_table[fd];
|
|
|
|
if (!fde || !fde->is_open)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fde->read_callback = fde->write_callback = NULL;
|
|
|
|
fd_refresh(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;
|
|
|
|
|
2022-01-15 05:16:34 +00:00
|
|
|
return fd_open(fd, desc, FDCLOSE_SOCKET);
|
2020-03-29 09:16:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int fd_accept(int sockfd)
|
|
|
|
{
|
|
|
|
const char buf[] = "Incoming connection";
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
fd = accept(sockfd, NULL, NULL);
|
|
|
|
if (fd < 0)
|
|
|
|
return -1;
|
|
|
|
|
2022-01-15 05:16:34 +00:00
|
|
|
return fd_open(fd, buf, FDCLOSE_SOCKET);
|
2020-03-29 09:16:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void fd_desc(int fd, const char *desc)
|
|
|
|
{
|
|
|
|
FDEntry *fde;
|
|
|
|
|
|
|
|
if ((fd < 0) || (fd >= MAXCONNECTIONS))
|
|
|
|
{
|
2022-01-15 05:16:34 +00:00
|
|
|
unreal_log(ULOG_ERROR, "io", "BUG_FD_DESC_OUT_OF_RANGE", NULL,
|
|
|
|
"[BUG] trying to fd_desc fd $fd in fd table, but MAXCONNECTIONS is $maxconnections",
|
|
|
|
log_data_integer("fd", fd),
|
|
|
|
log_data_integer("maxconnections", MAXCONNECTIONS));
|
2020-03-29 09:16:53 +00:00
|
|
|
#ifdef DEBUGMODE
|
|
|
|
abort();
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fde = &fd_table[fd];
|
|
|
|
if (!fde->is_open)
|
|
|
|
{
|
2022-01-15 05:16:34 +00:00
|
|
|
unreal_log(ULOG_ERROR, "io", "BUG_FD_DESC_NOT_OPEN", NULL,
|
|
|
|
"[BUG] trying to fd_desc fd $fd in fd table, but FD is (already) closed",
|
|
|
|
log_data_integer("fd", fd));
|
2020-03-29 09:16:53 +00:00
|
|
|
#ifdef DEBUGMODE
|
|
|
|
abort();
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
strlcpy(fde->desc, desc, FD_DESC_SZ);
|
|
|
|
}
|
|
|
|
|