ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/libio/comm/fdlist.c
Revision: 68
Committed: Tue Oct 4 00:44:29 2005 UTC (20 years, 9 months ago) by adx
Content type: text/x-csrc
File size: 5226 byte(s)
Log Message:
- removed last references to the ircd core, libio is independent now
- to do: split headers

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * fdlist.c: Maintains a list of file descriptors.
4 *
5 * Copyright (C) 2002 by the past and present ircd coders, and others.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id: fdlist.c 33 2005-10-02 20:50:00Z knight $
23 */
24 #include "stdinc.h"
25 #include "fdlist.h"
26 #include "common.h"
27 #include "event.h"
28 #include "irc_string.h"
29 #include "rlimits.h"
30 #include "s_bsd.h" /* comm_setselect */
31 #include "s_conf.h" /* ServerInfo */
32 #include "memory.h"
33
34 fde_t *fd_hash[FD_HASH_SIZE];
35 fde_t *fd_next_in_loop = NULL;
36 int number_fd = LEAKED_FDS;
37 int hard_fdlimit = 0;
38 struct Callback *fdlimit_cb = NULL;
39
40 static void *
41 changing_fdlimit(va_list args)
42 {
43 hard_fdlimit = va_arg(args, int);
44 return NULL;
45 }
46
47 void
48 fdlist_init(void)
49 {
50 memset(&fd_hash, 0, sizeof(fd_hash));
51
52 fdlimit_cb = register_callback("changing_fdlimit", changing_fdlimit);
53 eventAddIsh("recalc_fdlimit", recalc_fdlimit, NULL, 58);
54 recalc_fdlimit(NULL);
55 }
56
57 void
58 recalc_fdlimit(void *unused)
59 {
60 #ifdef _WIN32
61 /* this is what WSAStartup() usually returns. Even though they say
62 * the value is for compatibility reasons and should be ignored,
63 * we actually can create even more sockets... */
64 hard_fdlimit = 32767;
65 #else
66 int fdmax;
67 struct rlimit limit;
68
69 if (!getrlimit(RLIMIT_FD_MAX, &limit))
70 {
71 limit.rlim_cur = limit.rlim_max;
72 setrlimit(RLIMIT_FD_MAX, &limit);
73 }
74
75 fdmax = getdtablesize();
76
77 /* under no condition shall this raise over 65536
78 * for example user ip heap is sized 2*hard_fdlimit */
79 fdmax = IRCD_MIN(fdmax, 65536);
80
81 if (fdmax != hard_fdlimit)
82 execute_callback(fdlimit_cb, fdmax);
83 #endif
84 }
85
86 static inline unsigned int
87 hash_fd(int fd)
88 {
89 #ifdef _WIN32
90 return ((((unsigned) fd) >> 2) % FD_HASH_SIZE);
91 #else
92 return (((unsigned) fd) % FD_HASH_SIZE);
93 #endif
94 }
95
96 fde_t *
97 lookup_fd(int fd)
98 {
99 fde_t *F = fd_hash[hash_fd(fd)];
100
101 while (F)
102 {
103 if (F->fd == fd)
104 return (F);
105 F = F->hnext;
106 }
107
108 return (NULL);
109 }
110
111 /* Called to open a given filedescriptor */
112 void
113 fd_open(fde_t *F, int fd, int is_socket, const char *desc)
114 {
115 unsigned int hashv = hash_fd(fd);
116 assert(fd >= 0);
117
118 F->fd = fd;
119 F->comm_index = -1;
120 if (desc)
121 strlcpy(F->desc, desc, sizeof(F->desc));
122 /* Note: normally we'd have to clear the other flags,
123 * but currently F is always cleared before calling us.. */
124 F->flags.open = 1;
125 F->flags.is_socket = is_socket;
126 F->hnext = fd_hash[hashv];
127 fd_hash[hashv] = F;
128
129 number_fd++;
130 }
131
132 /* Called to close a given filedescriptor */
133 void
134 fd_close(fde_t *F)
135 {
136 unsigned int hashv = hash_fd(F->fd);
137
138 if (F == fd_next_in_loop)
139 fd_next_in_loop = F->hnext;
140
141 if (F->flags.is_socket)
142 comm_setselect(F, COMM_SELECT_WRITE | COMM_SELECT_READ, NULL, NULL, 0);
143
144 if (F->dns_query != NULL)
145 {
146 delete_resolver_queries(F->dns_query);
147 MyFree(F->dns_query);
148 }
149
150 #ifdef HAVE_LIBCRYPTO
151 if (F->ssl)
152 SSL_free(F->ssl);
153 #endif
154
155 if (fd_hash[hashv] == F)
156 fd_hash[hashv] = F->hnext;
157 else {
158 fde_t *prev;
159
160 /* let it core if not found */
161 for (prev = fd_hash[hashv]; prev->hnext != F; prev = prev->hnext)
162 ;
163 prev->hnext = F->hnext;
164 }
165
166 /* Unlike squid, we're actually closing the FD here! -- adrian */
167 #ifdef _WIN32
168 if (F->flags.is_socket)
169 closesocket(F->fd);
170 else
171 CloseHandle((HANDLE)F->fd);
172 #else
173 close(F->fd);
174 #endif
175 number_fd--;
176 #ifdef INVARIANTS
177 memset(F, '\0', sizeof(fde_t));
178 #endif
179 }
180
181 /*
182 * fd_note() - set the fd note
183 *
184 * Note: must be careful not to overflow fd_table[fd].desc when
185 * calling.
186 */
187 void
188 fd_note(fde_t *F, const char *format, ...)
189 {
190 va_list args;
191
192 if (format != NULL)
193 {
194 va_start(args, format);
195 vsnprintf(F->desc, sizeof(F->desc), format, args);
196 va_end(args);
197 }
198 else
199 F->desc[0] = '\0';
200 }
201
202 /* Make sure stdio descriptors (0-2) and profiler descriptor (3)
203 * always go somewhere harmless. Use -foreground for profiling
204 * or executing from gdb */
205 #ifndef _WIN32
206 void
207 close_standard_fds(void)
208 {
209 int i;
210
211 for (i = 0; i < LOWEST_SAFE_FD; i++)
212 {
213 close(i);
214 if (open(PATH_DEVNULL, O_RDWR) < 0)
215 exit(-1); /* we're hosed if we can't even open /dev/null */
216 }
217 }
218 #endif
219
220 void
221 close_fds(fde_t *one)
222 {
223 int i;
224 fde_t *F;
225
226 for (i = 0; i < FD_HASH_SIZE; i++)
227 for (F = fd_hash[i]; F != NULL; F = F->hnext)
228 if (F != one)
229 {
230 #ifdef _WIN32
231 if (F->flags.is_socket)
232 closesocket(F->fd);
233 else
234 CloseHandle((HANDLE)F->fd);
235 #else
236 close(F->fd);
237 #endif
238 }
239 }

Properties

Name Value
svn:eol-style native
svn:keywords "Id Revision"