]> jfr.im git - irc/evilnet/x3.git/blame - src/ioset-select.c
Minor typo in previous commit where returning 0 when it should have been 1 from opser...
[irc/evilnet/x3.git] / src / ioset-select.c
CommitLineData
1136f709 1/* ioset select() backend for srvx
2 * Copyright 2002-2006 srvx Development Team
3 *
4 * This file is part of srvx.
5 *
6 * srvx is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
be2c97a5 8 * the Free Software Foundation; either version 3 of the License, or
1136f709 9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 */
20
21#include "ioset-impl.h"
22#include "common.h"
23#include "log.h"
24
25#include <stdlib.h>
26#include <string.h>
27
28#ifdef HAVE_SYS_SELECT_H
29# include <sys/select.h>
30#endif
31
32#ifdef HAVE_SYS_SOCKET_H
33# include <sys/socket.h>
34#endif
35
36extern int clock_skew;
37static struct io_fd **fds;
38static unsigned int fds_size;
39static fd_set read_fds;
40static fd_set write_fds;
41static fd_set except_fds;
42
43static int
44ioset_select_init(void)
45{
46 return 1;
47}
48
49static void
50ioset_select_add(struct io_fd *fd)
51{
52 if ((unsigned)fd->fd >= fds_size) {
53 unsigned int old_size = fds_size;
54 fds_size = fd->fd + 8;
55 fds = realloc(fds, fds_size*sizeof(*fds));
56 memset(fds+old_size, 0, (fds_size-old_size)*sizeof(*fds));
57 }
58 fds[fd->fd] = fd;
59}
60
61static void
62ioset_select_remove(struct io_fd *fd, int closed)
63{
64 FD_CLR(fd->fd, &read_fds);
65 FD_CLR(fd->fd, &write_fds);
66 FD_CLR(fd->fd, &except_fds);
67 fds[fd->fd] = NULL;
68 (void)closed;
69}
70
71static void
72ioset_select_update(struct io_fd *fd)
73{
74 (void)fd;
75}
76
77static void
78ioset_select_cleanup(void)
79{
80 free(fds);
81}
82
83#if DEBUG_FDSETS
84static void
85debug_fdsets(const char *msg, int nfds, fd_set *read_fds, fd_set *write_fds, fd_set *except_fds, struct timeval *select_timeout) {
86 static const char *flag_text[8] = { "---", "r", "w", "rw", "e", "er", "ew", "erw" };
87 char buf[MAXLEN];
88 int pos, ii, flags;
89 struct timeval now;
90
91 for (pos=ii=0; ii<nfds; ++ii) {
92 flags = FD_ISSET(ii, read_fds) ? 1 : 0;
93 flags |= FD_ISSET(ii, write_fds) ? 2 : 0;
94 flags |= FD_ISSET(ii, except_fds) ? 4 : 0;
95 if (flags)
96 pos += sprintf(buf+pos, " %d%s", ii, flag_text[flags]);
97 }
98 gettimeofday(&now, NULL);
99 if (select_timeout) {
100 log_module(MAIN_LOG, LOG_DEBUG, "%s, at %lu.%06lu:%s (timeout %lu.%06lu)", msg, (unsigned long)now.tv_sec, (unsigned long)now.tv_usec, buf, (unsigned long)select_timeout->tv_sec, (unsigned long)select_timeout->tv_usec);
101 } else {
102 log_module(MAIN_LOG, LOG_DEBUG, "%s, at %lu.%06lu:%s (no timeout)", msg, (unsigned long)now.tv_sec, (unsigned long)now.tv_usec, buf);
103 }
104}
105#else
106# define debug_fdsets(MSG, NFDS, READ_FDS, WRITE_FDS, EXCEPT_FDS, SELECT_TIMEOUT) (void)0
107#endif
108
109static int
110ioset_select_loop(struct timeval *timeout)
111{
112 struct io_fd *fd;
113 unsigned int nn;
114 int select_result;
115 int max_fd;
116
117 /* Set up read_fds and write_fds fdsets. */
118 FD_ZERO(&read_fds);
119 FD_ZERO(&write_fds);
120 FD_ZERO(&except_fds);
121 max_fd = -1;
122 for (nn=0; nn<fds_size; nn++) {
123 if (!(fd = fds[nn]))
124 continue;
125 max_fd = nn;
126 FD_SET(nn, &read_fds);
127 FD_SET(nn, &except_fds);
128 if (fd_wants_writes(fd))
129 FD_SET(nn, &write_fds);
130 }
131
132 /* Check for activity, update time. */
133 debug_fdsets("Entering select", max_fd+1, &read_fds, &write_fds, &except_fds, timeout);
134 select_result = select(max_fd + 1, &read_fds, &write_fds, NULL, timeout);
135 debug_fdsets("After select", max_fd+1, &read_fds, &write_fds, &except_fds, timeout);
136 now = time(NULL) + clock_skew;
137 if (select_result < 0) {
138 if (errno != EINTR) {
139 log_module(MAIN_LOG, LOG_ERROR, "select() error %d: %s", errno, strerror(errno));
140 close_socket();
141 }
142 return 1;
143 }
144
145 /* Call back anybody that has connect or read activity and wants to know. */
146 for (nn=0; nn<fds_size; nn++) {
147 ioset_events(fds[nn], FD_ISSET(nn, &read_fds) | FD_ISSET(nn, &except_fds), FD_ISSET(nn, &write_fds));
148 }
149 return 0;
150}
151
152struct io_engine io_engine_select = {
153 .name = "select",
154 .init = ioset_select_init,
155 .add = ioset_select_add,
156 .remove = ioset_select_remove,
157 .update = ioset_select_update,
158 .loop = ioset_select_loop,
159 .cleanup = ioset_select_cleanup,
160};