00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdinc.h"
00027 #include "fdlist.h"
00028 #include "hook.h"
00029 #include "ircd.h"
00030 #include "s_bsd.h"
00031 #include "s_log.h"
00032
00033
00034
00035
00036
00037
00038
00039 static fd_set select_readfds, tmpreadfds;
00040 static fd_set select_writefds, tmpwritefds;
00041 static int highest_fd = -1;
00042 static dlink_node *hookptr;
00043
00044
00045
00046
00047
00048
00049 static void *
00050 changing_fdlimit(va_list args)
00051 {
00052 int fdmax = va_arg(args, int);
00053
00054 if (fdmax > FD_SETSIZE)
00055 fdmax = FD_SETSIZE;
00056
00057 return pass_callback(hookptr, fdmax);
00058 }
00059
00060
00061
00062
00063
00064
00065
00066 void
00067 init_netio(void)
00068 {
00069 FD_ZERO(&select_readfds);
00070 FD_ZERO(&select_writefds);
00071
00072 hookptr = install_hook(fdlimit_cb, changing_fdlimit);
00073 }
00074
00075
00076
00077
00078
00079
00080
00081 void
00082 comm_setselect(fde_t *F, unsigned int type, PF *handler,
00083 void *client_data, time_t timeout)
00084 {
00085 int new_events;
00086
00087 if ((type & COMM_SELECT_READ))
00088 {
00089 F->read_handler = handler;
00090 F->read_data = client_data;
00091 }
00092
00093 if ((type & COMM_SELECT_WRITE))
00094 {
00095 F->write_handler = handler;
00096 F->write_data = client_data;
00097 }
00098
00099 new_events = (F->read_handler ? COMM_SELECT_READ : 0) |
00100 (F->write_handler ? COMM_SELECT_WRITE : 0);
00101
00102 if (timeout != 0)
00103 F->timeout = CurrentTime + (timeout / 1000);
00104
00105 if (new_events != F->evcache)
00106 {
00107 if ((new_events & COMM_SELECT_READ))
00108 FD_SET(F->fd, &select_readfds);
00109 else
00110 {
00111 FD_CLR(F->fd, &select_readfds);
00112 FD_CLR(F->fd, &tmpreadfds);
00113 }
00114
00115 if ((new_events & COMM_SELECT_WRITE))
00116 FD_SET(F->fd, &select_writefds);
00117 else
00118 {
00119 FD_CLR(F->fd, &select_writefds);
00120 FD_CLR(F->fd, &tmpwritefds);
00121 }
00122
00123 if (new_events == 0)
00124 {
00125 if (highest_fd == F->fd)
00126 while (highest_fd >= 0 && (FD_ISSET(highest_fd, &select_readfds) ||
00127 FD_ISSET(highest_fd, &select_writefds)))
00128 highest_fd--;
00129 }
00130 else if (F->evcache == 0)
00131 if (F->fd > highest_fd)
00132 highest_fd = F->fd;
00133
00134 F->evcache = new_events;
00135 }
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 void
00147 comm_select(void)
00148 {
00149 struct timeval to;
00150 int num, fd;
00151 fde_t *F;
00152 PF *hdl;
00153
00154
00155 memcpy(&tmpreadfds, &select_readfds, sizeof(fd_set));
00156 memcpy(&tmpwritefds, &select_writefds, sizeof(fd_set));
00157
00158 to.tv_sec = 0;
00159 to.tv_usec = SELECT_DELAY * 1000;
00160 num = select(highest_fd + 1, &tmpreadfds, &tmpwritefds, NULL, &to);
00161
00162 set_time();
00163
00164 if (num < 0)
00165 {
00166 #ifdef HAVE_USLEEP
00167 usleep(50000);
00168 #endif
00169 return;
00170 }
00171
00172 for (fd = 0; fd <= highest_fd && num > 0; fd++)
00173 if (FD_ISSET(fd, &tmpreadfds) || FD_ISSET(fd, &tmpwritefds))
00174 {
00175 num--;
00176
00177 F = lookup_fd(fd);
00178 if (F == NULL || !F->flags.open)
00179 continue;
00180
00181 if (FD_ISSET(fd, &tmpreadfds))
00182 if ((hdl = F->read_handler) != NULL)
00183 {
00184 F->read_handler = NULL;
00185 hdl(F, F->read_data);
00186 if (!F->flags.open)
00187 continue;
00188 }
00189
00190 if (FD_ISSET(fd, &tmpwritefds))
00191 if ((hdl = F->write_handler) != NULL)
00192 {
00193 F->write_handler = NULL;
00194 hdl(F, F->write_data);
00195 if (!F->flags.open)
00196 continue;
00197 }
00198
00199 comm_setselect(F, 0, NULL, NULL, 0);
00200 }
00201 }