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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Tue Jun 6 03:41:38 2006 UTC (19 years, 9 months ago) by sysadm
CVS Tags: pvpgn_1-7-4-0_MIL
Branch point for: GNU, MAIN
Content type: text/x-csrc
Initial revision

1 sysadm 1.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