unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

fdlist.c (5340B)

      1 /*
      2  * UnrealIRCd, src/fdlist.c
      3  * Copyright (c) 2012 William Pitcock <nenolod@dereferenced.org>
      4  *
      5  *   This program is free software; you can redistribute it and/or modify
      6  *   it under the terms of the GNU General Public License as published by
      7  *   the Free Software Foundation; either version 1, or (at your option)
      8  *   any later version.
      9  *
     10  *   This program is distributed in the hope that it will be useful,
     11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  *   GNU General Public License for more details.
     14  *
     15  *   You should have received a copy of the GNU General Public License
     16  *   along with this program; if not, write to the Free Software
     17  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     18  */
     19 
     20 #include "unrealircd.h"
     21 
     22 /* new FD management code, based on mowgli.eventloop from atheme, hammered into UnrealIRCd by
     23  * me, nenolod.
     24  */
     25 FDEntry fd_table[MAXCONNECTIONS + 1];
     26 
     27 /** Notify I/O engine that a file descriptor opened.
     28  * @param fd		The file descriptor
     29  * @param desc		Description for in the fd table
     30  * @param close_method	Tell what a subsequent call to fd_close() should do,
     31  *                      eg close the socket, file or don't close anything.
     32  * @returns The file descriptor 'fd' or -1 in case of fatal error.
     33  */
     34 int fd_open(int fd, const char *desc, FDCloseMethod close_method)
     35 {
     36 	FDEntry *fde;
     37 
     38 	if ((fd < 0) || (fd >= MAXCONNECTIONS))
     39 	{
     40 		unreal_log(ULOG_ERROR, "io", "BUG_FD_OPEN_OUT_OF_RANGE", NULL,
     41 		           "[BUG] trying to add fd $fd to fd table, but MAXCONNECTIONS is $maxconnections",
     42 		           log_data_integer("fd", fd),
     43 		           log_data_integer("maxconnections", MAXCONNECTIONS));
     44 #ifdef DEBUGMODE
     45 		abort();
     46 #endif
     47 		return -1;
     48 	}
     49 
     50 	fde = &fd_table[fd];
     51 	memset(fde, 0, sizeof(FDEntry));
     52 
     53 	fde->fd = fd;
     54 	fde->is_open = 1;
     55 	fde->backend_flags = 0;
     56 	fde->close_method = close_method;
     57 	strlcpy(fde->desc, desc, FD_DESC_SZ);
     58 
     59 	return fde->fd;
     60 }
     61 
     62 #ifndef _WIN32
     63 # define OPEN_MODES	S_IRUSR|S_IWUSR
     64 #else
     65 # define OPEN_MODES	S_IREAD|S_IWRITE
     66 #endif
     67 
     68 int fd_fileopen(const char *path, unsigned int flags)
     69 {
     70 	int fd;
     71 	char comment[FD_DESC_SZ];
     72 	char pathbuf[BUFSIZE];
     73 
     74 	fd = open(path, flags, OPEN_MODES);
     75 	if (fd < 0)
     76 		return -1;
     77 
     78 	strlcpy(pathbuf, path, sizeof pathbuf);
     79 
     80 	snprintf(comment, sizeof comment, "File: %s", unreal_getfilename(pathbuf));
     81 
     82 	return fd_open(fd, comment, FDCLOSE_FILE);
     83 }
     84 
     85 /** Internal function to unmap and optionally close the fd.
     86  */
     87 /** Remove file descriptor from our table and possibly close the fd.
     88  * The fd is closed (or not) according to the method specified in fd_open().
     89  * @param fd	The file descriptor
     90  * @returns 1 on success, 0 on failure
     91  */
     92 int fd_close(int fd)
     93 {
     94 	FDEntry *fde;
     95 	unsigned int befl;
     96 	FDCloseMethod close_method;
     97 
     98 	if ((fd < 0) || (fd >= MAXCONNECTIONS))
     99 	{
    100 		unreal_log(ULOG_ERROR, "io", "BUG_FD_CLOSE_OUT_OF_RANGE", NULL,
    101 		           "[BUG] trying to close fd $fd to fd table, but MAXCONNECTIONS is $maxconnections",
    102 		           log_data_integer("fd", fd),
    103 		           log_data_integer("maxconnections", MAXCONNECTIONS));
    104 #ifdef DEBUGMODE
    105 		abort();
    106 #endif
    107 		return 0;
    108 	}
    109 
    110 	fde = &fd_table[fd];
    111 	if (!fde->is_open)
    112 	{
    113 		unreal_log(ULOG_ERROR, "io", "BUG_FD_CLOSE_NOT_OPEN", NULL,
    114 		           "[BUG] trying to close fd $fd to fd table, but FD is (already) closed",
    115 		           log_data_integer("fd", fd));
    116 #ifdef DEBUGMODE
    117 		abort();
    118 #endif
    119 		return 0;
    120 	}
    121 
    122 	befl = fde->backend_flags;
    123 	close_method = fde->close_method;
    124 	memset(fde, 0, sizeof(FDEntry));
    125 
    126 	fde->fd = fd;
    127 
    128 	/* only notify the backend if it is actively tracking the FD */
    129 	if (befl)
    130 		fd_refresh(fd);
    131 
    132 	/* Finally, close the file or socket if requested to do so */
    133 	switch (close_method)
    134 	{
    135 		case FDCLOSE_SOCKET:
    136 			CLOSE_SOCK(fd);
    137 			break;
    138 		case FDCLOSE_FILE:
    139 			close(fd);
    140 			break;
    141 		case FDCLOSE_NONE:
    142 		default:
    143 			break;
    144 	}
    145 
    146 	return 1;
    147 }
    148 
    149 /* Deregister I/O notification for this file descriptor */
    150 void fd_unnotify(int fd)
    151 {
    152 	FDEntry *fde;
    153 
    154 	if ((fd < 0) || (fd >= MAXCONNECTIONS))
    155 		return;
    156 	
    157 	fde = &fd_table[fd];
    158 	if (!fde || !fde->is_open)
    159 		return;
    160 		
    161 	fde->read_callback = fde->write_callback = NULL;
    162 	fd_refresh(fd);
    163 }
    164 
    165 int fd_socket(int family, int type, int protocol, const char *desc)
    166 {
    167 	int fd;
    168 
    169 	fd = socket(family, type, protocol);
    170 	if (fd < 0)
    171 		return -1;
    172 
    173 	return fd_open(fd, desc, FDCLOSE_SOCKET);
    174 }
    175 
    176 int fd_accept(int sockfd)
    177 {
    178 	const char buf[] = "Incoming connection";
    179 	int fd;
    180 
    181 	fd = accept(sockfd, NULL, NULL);
    182 	if (fd < 0)
    183 		return -1;
    184 
    185 	return fd_open(fd, buf, FDCLOSE_SOCKET);
    186 }
    187 
    188 void fd_desc(int fd, const char *desc)
    189 {
    190 	FDEntry *fde;
    191 
    192 	if ((fd < 0) || (fd >= MAXCONNECTIONS))
    193 	{
    194 		unreal_log(ULOG_ERROR, "io", "BUG_FD_DESC_OUT_OF_RANGE", NULL,
    195 		           "[BUG] trying to fd_desc fd $fd in fd table, but MAXCONNECTIONS is $maxconnections",
    196 		           log_data_integer("fd", fd),
    197 		           log_data_integer("maxconnections", MAXCONNECTIONS));
    198 #ifdef DEBUGMODE
    199 		abort();
    200 #endif
    201 		return;
    202 	}
    203 
    204 	fde = &fd_table[fd];
    205 	if (!fde->is_open)
    206 	{
    207 		unreal_log(ULOG_ERROR, "io", "BUG_FD_DESC_NOT_OPEN", NULL,
    208 		           "[BUG] trying to fd_desc fd $fd in fd table, but FD is (already) closed",
    209 		           log_data_integer("fd", fd));
    210 #ifdef DEBUGMODE
    211 		abort();
    212 #endif
    213 		return;
    214 	}
    215 
    216 	strlcpy(fde->desc, desc, FD_DESC_SZ);
    217 }
    218