/[LeafOK_CVS]/pvpgn-1.7.4/src/common/fdwatch.c
ViewVC logotype

Contents of /pvpgn-1.7.4/src/common/fdwatch.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (show annotations) (vendor branch)
Tue Jun 6 03:41:38 2006 UTC (19 years, 9 months ago) by sysadm
Branch: GNU, MAIN
CVS Tags: arelease, HEAD
Changes since 1.1: +0 -0 lines
Content type: text/x-csrc
no message

1 /*
2 * Abstraction API/layer for the various ways PvPGN can inspect sockets state
3 * 2003 (C) dizzy@roedu.net
4 *
5 * Code is based on the ideas found in thttpd project.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (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, USA.
20 */
21
22 #include "common/setup_before.h"
23 #ifdef HAVE_STRING_H
24 # include <string.h>
25 #else
26 # ifdef HAVE_STRINGS_H
27 # include <strings.h>
28 # endif
29 #endif
30 #ifdef STDC_HEADERS
31 # include <stdlib.h>
32 #else
33 # ifdef HAVE_MALLOC_H
34 # include <malloc.h>
35 # endif
36 #endif
37 #include "common/eventlog.h"
38 #define FDWATCH_BACKEND
39 #include "fdwatch.h"
40 #ifdef HAVE_SELECT
41 #include "fdwatch_select.h"
42 #endif
43 #ifdef HAVE_POLL
44 #include "fdwatch_poll.h"
45 #endif
46 #ifdef HAVE_KQUEUE
47 #include "fdwatch_kqueue.h"
48 #endif
49 #ifdef HAVE_EPOLL
50 #include "fdwatch_epoll.h"
51 #endif
52 #include "common/rlimit.h"
53 #include "common/xalloc.h"
54 #include "common/setup_after.h"
55
56 int fdw_maxcons;
57 t_fdwatch_fd *fdw_fds = NULL;
58
59 static t_fdw_backend * fdw = NULL;
60 static DECLARE_ELIST_INIT(freelist);
61 static DECLARE_ELIST_INIT(uselist);
62
63 extern int fdwatch_init(int maxcons)
64 {
65 int i, maxsys;
66
67 maxsys = get_socket_limit();
68 if (maxsys > 0) maxcons = (maxcons < maxsys) ? maxcons : maxsys;
69 if (maxcons < 32) {
70 eventlog(eventlog_level_fatal, __FUNCTION__, "too few sockets available (%d)",maxcons);
71 return -1;
72 }
73 fdw_maxcons = maxcons;
74
75 fdw_fds = xmalloc(sizeof(t_fdwatch_fd) * fdw_maxcons);
76 memset(fdw_fds, 0, sizeof(t_fdwatch_fd) * fdw_maxcons);
77 /* add all slots to the freelist */
78 for(i = 0; i < fdw_maxcons; i++)
79 elist_add_tail(&freelist,&(fdw_fds[i].freelist));
80
81 #ifdef HAVE_EPOLL
82 fdw = &fdw_epoll;
83 if (!fdw->init(fdw_maxcons)) goto ok;
84 #endif
85 #ifdef HAVE_KQUEUE
86 fdw = &fdw_kqueue;
87 if (!fdw->init(fdw_maxcons)) goto ok;
88 #endif
89 #ifdef HAVE_POLL
90 fdw = &fdw_poll;
91 if (!fdw->init(fdw_maxcons)) goto ok;
92 goto ok;
93 #endif
94 #ifdef HAVE_SELECT
95 fdw = &fdw_select;
96 if (!fdw->init(fdw_maxcons)) goto ok;
97 #endif
98
99 eventlog(eventlog_level_fatal, __FUNCTION__, "Found no working fdwatch layer");
100 fdw = NULL;
101 fdwatch_close();
102 return -1;
103
104 ok:
105 return 0;
106 }
107
108 extern int fdwatch_close(void)
109 {
110 if (fdw) { fdw->close(); fdw = NULL; }
111 if (fdw_fds) { xfree((void*)fdw_fds); fdw_fds = NULL; }
112 elist_init(&freelist);
113 elist_init(&uselist);
114
115 return 0;
116 }
117
118 extern int fdwatch_add_fd(int fd, t_fdwatch_type rw, fdwatch_handler h, void *data)
119 {
120 t_fdwatch_fd *cfd;
121
122 if (elist_empty(&freelist)) return -1; /* max sockets reached */
123
124 cfd = elist_entry(elist_next(&freelist),t_fdwatch_fd,freelist);
125 fdw_fd(cfd) = fd;
126
127 if (fdw->add_fd(fdw_idx(cfd), rw)) return -1;
128
129 /* add it to used sockets list, remove it from free list */
130 elist_add_tail(&uselist,&cfd->uselist);
131 elist_del(&cfd->freelist);
132
133 fdw_rw(cfd) = rw;
134 fdw_data(cfd) = data;
135 fdw_hnd(cfd) = h;
136
137 return fdw_idx(cfd);
138 }
139
140 extern int fdwatch_update_fd(int idx, t_fdwatch_type rw)
141 {
142 if (idx<0 || idx>=fdw_maxcons) {
143 eventlog(eventlog_level_error,__FUNCTION__,"out of bounds idx [%d] (max: %d)",idx, fdw_maxcons);
144 return -1;
145 }
146 /* do not allow completly reset the access because then backend codes
147 * can get confused */
148 if (!rw) {
149 eventlog(eventlog_level_error,__FUNCTION__,"tried to reset rw, not allowed");
150 return -1;
151 }
152
153 if (!fdw_rw(fdw_fds + idx)) {
154 eventlog(eventlog_level_error,__FUNCTION__,"found reseted rw");
155 return -1;
156 }
157
158 if (fdw->add_fd(idx, rw)) return -1;
159 fdw_rw(&fdw_fds[idx]) = rw;
160
161 return 0;
162 }
163
164 extern int fdwatch_del_fd(int idx)
165 {
166 t_fdwatch_fd *cfd;
167
168 if (idx<0 || idx>=fdw_maxcons) {
169 eventlog(eventlog_level_error,__FUNCTION__,"out of bounds idx [%d] (max: %d)",idx, fdw_maxcons);
170 return -1;
171 }
172
173 cfd = fdw_fds + idx;
174 if (!fdw_rw(cfd)) {
175 eventlog(eventlog_level_error,__FUNCTION__,"found reseted rw");
176 return -1;
177 }
178
179 fdw->del_fd(idx);
180
181 /* remove it from uselist, add it to freelist */
182 elist_del(&cfd->uselist);
183 elist_add_tail(&freelist,&cfd->freelist);
184
185 fdw_fd(cfd) = 0;
186 fdw_rw(cfd) = 0;
187 fdw_data(cfd) = NULL;
188 fdw_hnd(cfd) = NULL;
189
190 return 0;
191 }
192
193 extern int fdwatch(long timeout_msec)
194 {
195 return fdw->watch(timeout_msec);
196 }
197
198 extern void fdwatch_handle(void)
199 {
200 fdw->handle();
201 }
202
203 extern void fdwatch_traverse(t_fdw_cb cb, void *data)
204 {
205 t_elist *curr;
206
207 elist_for_each(curr,&uselist)
208 {
209 if (cb(elist_entry(curr,t_fdwatch_fd,uselist),data)) break;
210 }
211 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1