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