int rb_select_select(long delay) { int num; int fd; PF *hdl; rb_fde_t *F; struct timeval to; /* Copy over the read/write sets so we don't have to rebuild em */ memcpy(&tmpreadfds, &select_readfds, sizeof(fd_set)); memcpy(&tmpwritefds, &select_writefds, sizeof(fd_set)); for (;;) { to.tv_sec = 0; to.tv_usec = delay * 1000; num = select(rb_maxfd + 1, &tmpreadfds, &tmpwritefds, NULL, &to); if (num >= 0) break; if (rb_ignore_errno(errno)) continue; rb_set_time(); /* error! */ return -1; /* NOTREACHED */ } rb_set_time(); if (num == 0) return 0; /* XXX we *could* optimise by falling out after doing num fds ... */ for (fd = 0; fd < rb_maxfd + 1; fd++) { F = rb_find_fd(fd); if (F == NULL) continue; if (FD_ISSET(fd, &tmpreadfds)) { hdl = F->read_handler; F->read_handler = NULL; if (hdl) hdl(F, F->read_data); } if (!IsFDOpen(F)) continue; /* Read handler closed us..go on */ if (FD_ISSET(fd, &tmpwritefds)) { hdl = F->write_handler; F->write_handler = NULL; if (hdl) hdl(F, F->write_data); } if (F->read_handler == NULL) select_update_selectfds(F, RB_SELECT_READ, NULL); if (F->write_handler == NULL) select_update_selectfds(F, RB_SELECT_WRITE, NULL); } return 0; }
int main(int argc, char *argv[]) { setup_signals(); authd_helper = rb_helper_child(parse_request, error_cb, NULL, NULL, NULL, 256, 256, 256); /* XXX fix me */ if(authd_helper == NULL) { fprintf(stderr, "authd is not meant to be invoked by end users\n"); exit(EX_ERROR); } rb_set_time(); setup_signals(); authd_option_handlers = rb_dictionary_create("authd options handlers", rb_strcasecmp); init_resolver(); init_providers(); rb_init_prng(NULL, RB_PRNG_DEFAULT); rb_helper_loop(authd_helper, 0); /* * XXX this function will never be called from here -- is it necessary? */ destroy_providers(); return 0; }
/* * ms_svinfo - SVINFO message handler * parv[1] = TS_CURRENT for the server * parv[2] = TS_MIN for the server * parv[3] = unused, send 0 * parv[4] = server's idea of UTC time */ static int ms_svinfo(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { signed long deltat; time_t theirtime; char squitreason[120]; /* SVINFO isnt remote. */ if(source_p != client_p) return 0; if(TS_CURRENT < atoi(parv[2]) || atoi(parv[1]) < TS_MIN) { /* TS version is too low on one of the sides, drop the link */ sendto_realops_snomask(SNO_GENERAL, L_ALL, "Link %s dropped, wrong TS protocol version (%s,%s)", source_p->name, parv[1], parv[2]); rb_snprintf(squitreason, sizeof squitreason, "Incompatible TS version (%s,%s)", parv[1], parv[2]); exit_client(source_p, source_p, source_p, squitreason); return 0; } /* * since we're here, might as well set rb_current_time() while we're at it */ rb_set_time(); theirtime = atol(parv[4]); deltat = labs(theirtime - rb_current_time()); if(deltat > ConfigFileEntry.ts_max_delta) { sendto_realops_snomask(SNO_GENERAL, L_ALL, "Link %s dropped, excessive TS delta" " (my TS=%ld, their TS=%ld, delta=%ld)", source_p->name, (long) rb_current_time(), (long) theirtime, deltat); ilog(L_SERVER, "Link %s dropped, excessive TS delta" " (my TS=%ld, their TS=%ld, delta=%ld)", log_client_name(source_p, SHOW_IP), (long) rb_current_time(), (long) theirtime, deltat); rb_snprintf(squitreason, sizeof squitreason, "Excessive TS delta (my TS=%ld, their TS=%ld, delta=%ld)", (long) rb_current_time(), (long) theirtime, deltat); disable_server_conf_autoconn(source_p->name); exit_client(source_p, source_p, source_p, squitreason); return 0; } if(deltat > ConfigFileEntry.ts_warn_delta) { sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Link %s notable TS delta" " (my TS=%ld, their TS=%ld, delta=%ld)", source_p->name, (long) rb_current_time(), (long) theirtime, deltat); } return 0; }
/* * ms_svinfo - SVINFO message handler * parv[0] = sender prefix * parv[1] = TS_CURRENT for the server * parv[2] = TS_MIN for the server * parv[3] = unused, send 0 * parv[4] = server's idea of UTC time */ static int ms_svinfo(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { long int deltat; time_t theirtime; /* SVINFO isnt remote. */ if(source_p != client_p) return 0; if(TS_CURRENT < atoi(parv[2]) || atoi(parv[1]) < TS_MIN) { /* TS version is too low on one of the sides, drop the link */ sendto_realops_flags(UMODE_ALL, L_ALL, "Link %s dropped, wrong TS protocol version (%s,%s)", source_p->name, parv[1], parv[2]); exit_client(source_p, source_p, source_p, "Incompatible TS version"); return 0; } /* * since we're here, might as well call rb_set_time() while we're at it */ rb_set_time(); theirtime = atol(parv[4]); deltat = labs(theirtime - rb_current_time()); if(deltat > ConfigFileEntry.ts_max_delta) { sendto_realops_flags(UMODE_ALL, L_ALL, "Link %s dropped, excessive TS delta" " (my TS=%" RBTT_FMT ", their TS=%" RBTT_FMT " delta=%ld)", source_p->name, rb_current_time(), theirtime, deltat); ilog(L_SERVER, "Link %s dropped, excessive TS delta" " (my TS=%" RBTT_FMT ", their TS=%" RBTT_FMT ", delta=%ld)", log_client_name(source_p, SHOW_IP), rb_current_time(), theirtime, deltat); exit_client(source_p, source_p, source_p, "Excessive TS delta"); return 0; } if(deltat > ConfigFileEntry.ts_warn_delta) { sendto_realops_flags(UMODE_ALL, L_ALL, "Link %s notable TS delta" " (my TS=% " RBTT_FMT ", their TS=%" RBTT_FMT ", delta=%ld)", source_p->name, rb_current_time(), theirtime, deltat); } return 0; }
int rb_init_netio_ports(void) { if((pe = port_create()) < 0) { return errno; } pemax = getdtablesize(); pelst = rb_malloc(sizeof(port_event_t) * pemax); zero_timespec.tv_sec = 0; zero_timespec.tv_nsec = 0; rb_set_time(); return 0; }
int rb_select_ports(long delay) { int i, fd; unsigned int nget = 1; struct timespec poll_time; struct timespec *p = NULL; struct ev_entry *ev; if(delay >= 0) { poll_time.tv_sec = delay / 1000; poll_time.tv_nsec = (delay % 1000) * 1000000; p = &poll_time; } i = port_getn(pe, pelst, pemax, &nget, p); rb_set_time(); if(i == -1) return RB_OK; for(i = 0; (unsigned)i < nget; i++) { if(pelst[i].portev_source == PORT_SOURCE_FD) { fd = pelst[i].portev_object; PF *hdl = NULL; rb_fde_t *F = pelst[i].portev_user; if((pelst[i].portev_events & (POLLIN | POLLHUP | POLLERR)) && (hdl = F->read_handler)) { F->read_handler = NULL; hdl(F, F->read_data); } if((pelst[i].portev_events & (POLLOUT | POLLHUP | POLLERR)) && (hdl = F->write_handler)) { F->write_handler = NULL; hdl(F, F->write_data); } } else if(pelst[i].portev_source == PORT_SOURCE_TIMER) { ev = (struct ev_entry *)pelst[i].portev_user; rb_run_event(ev); } } return RB_OK; }
int rb_select_win32(long delay) { MSG msg; if(has_set_timer == 0) { /* XXX should probably have this handle all the events * instead of busy looping */ SetTimer(hwnd, 0, delay, NULL); has_set_timer = 1; } if(GetMessage(&msg, NULL, 0, 0) == FALSE) { rb_lib_die("GetMessage failed..byebye"); } rb_set_time(); DispatchMessage(&msg); return RB_OK; }
int main(int argc, char **argv) { res_helper = rb_helper_child(parse_request, error_cb, NULL, NULL, NULL, 256); /* XXX fix me */ if(res_helper == NULL) { fprintf(stderr, "This is ircd-ratbox resolver. You know you aren't supposed to run me directly?\n"); fprintf(stderr, "You get an Id tag for this: $Id$\n"); fprintf(stderr, "Bleep blorp.\n"); exit(1); } rb_set_time(); setup_signals(); init_resolver(); rb_init_prng(NULL, RB_PRNG_DEFAULT); rb_event_add("check_rehash", check_rehash, NULL, 5); report_nameservers(); rb_helper_loop(res_helper, 0); }
int rb_select_epoll(long delay) { int num, i, flags, old_flags, op; struct epoll_event ep_event; int o_errno; void *data; num = epoll_wait(ep_info->ep, ep_info->pfd, ep_info->pfd_size, delay); /* save errno as rb_set_time() will likely clobber it */ o_errno = errno; rb_set_time(); errno = o_errno; if(num < 0 && !rb_ignore_errno(o_errno)) return RB_ERROR; if(num <= 0) return RB_OK; for(i = 0; i < num; i++) { PF *hdl; rb_fde_t *F = ep_info->pfd[i].data.ptr; old_flags = F->pflags; if(ep_info->pfd[i].events & (EPOLLIN | EPOLLHUP | EPOLLERR)) { hdl = F->read_handler; data = F->read_data; F->read_handler = NULL; F->read_data = NULL; if(hdl) { hdl(F, data); } } if(!IsFDOpen(F)) continue; if(ep_info->pfd[i].events & (EPOLLOUT | EPOLLHUP | EPOLLERR)) { hdl = F->write_handler; data = F->write_data; F->write_handler = NULL; F->write_data = NULL; if(hdl) { hdl(F, data); } } if(!IsFDOpen(F)) continue; flags = 0; if(F->read_handler != NULL) flags |= EPOLLIN; if(F->write_handler != NULL) flags |= EPOLLOUT; if(old_flags != flags) { if(flags == 0) op = EPOLL_CTL_DEL; else op = EPOLL_CTL_MOD; F->pflags = ep_event.events = flags; ep_event.data.ptr = F; if(op == EPOLL_CTL_MOD || op == EPOLL_CTL_ADD) ep_event.events |= EPOLLET; if(epoll_ctl(ep_info->ep, op, F->fd, &ep_event) != 0) { rb_lib_log("rb_select_epoll(): epoll_ctl failed: %s", strerror(errno)); } } } return RB_OK; }
int rb_select_poll(long delay) { int num; int fd; int ci; PF *hdl; void *data; struct pollfd *pfd; int revents; num = poll(pollfd_list.pollfds, pollfd_list.maxindex + 1, delay); rb_set_time(); if(num < 0) { if(!rb_ignore_errno(errno)) return RB_OK; else return RB_ERROR; } if(num == 0) return RB_OK; /* XXX we *could* optimise by falling out after doing num fds ... */ for(ci = 0; ci < pollfd_list.maxindex + 1; ci++) { rb_fde_t *F; pfd = &pollfd_list.pollfds[ci]; revents = pfd->revents; fd = pfd->fd; if(revents == 0 || fd == -1) continue; F = rb_find_fd(fd); if(F == NULL) continue; if(revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { hdl = F->read_handler; data = F->read_data; F->read_handler = NULL; F->read_data = NULL; if(hdl) hdl(F, data); } if(IsFDOpen(F) && (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))) { hdl = F->write_handler; data = F->write_data; F->write_handler = NULL; F->write_data = NULL; if(hdl) hdl(F, data); } if(F->read_handler == NULL) rb_setselect_poll(F, RB_SELECT_READ, NULL, NULL); if(F->write_handler == NULL) rb_setselect_poll(F, RB_SELECT_WRITE, NULL, NULL); } return 0; }
int rb_select_kqueue(long delay) { int num, i; struct timespec poll_time; struct timespec *pt; rb_fde_t *F; if(delay < 0) { pt = NULL; } else { pt = &poll_time; poll_time.tv_sec = delay / 1000; poll_time.tv_nsec = (delay % 1000) * 1000000; } for(;;) { num = kevent(kq, kqlst, kqoff, kqout, kqmax, pt); kqoff = 0; if(num >= 0) break; if(rb_ignore_errno(errno)) break; rb_set_time(); return RB_ERROR; /* NOTREACHED */ } rb_set_time(); if(num == 0) return RB_OK; /* No error.. */ for(i = 0; i < num; i++) { PF *hdl = NULL; if(kqout[i].flags & EV_ERROR) { errno = kqout[i].data; /* XXX error == bad! -- adrian */ continue; /* XXX! */ } switch (kqout[i].filter) { case EVFILT_READ: F = kqout[i].udata; if((hdl = F->read_handler) != NULL) { F->read_handler = NULL; hdl(F, F->read_data); } break; case EVFILT_WRITE: F = kqout[i].udata; if((hdl = F->write_handler) != NULL) { F->write_handler = NULL; hdl(F, F->write_data); } break; #if defined(EVFILT_TIMER) case EVFILT_TIMER: rb_run_event(kqout[i].udata); break; #endif default: /* Bad! -- adrian */ break; } } return RB_OK; }
int rb_select_devpoll(long delay) { int num, i; struct pollfd pollfds[maxfd]; struct dvpoll dopoll; do { for(;;) { dopoll.dp_timeout = delay; dopoll.dp_nfds = maxfd; dopoll.dp_fds = &pollfds[0]; num = ioctl(dpfd, DP_POLL, &dopoll); if(num >= 0) break; if(rb_ignore_errno(errno)) break; rb_set_time(); return RB_ERROR; } rb_set_time(); if(num == 0) continue; for(i = 0; i < num; i++) { int fd = dopoll.dp_fds[i].fd; PF *hdl = NULL; rb_fde_t *F = rb_find_fd(fd); if((dopoll.dp_fds[i].revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) && (dopoll.dp_fds[i].events & (POLLRDNORM | POLLIN))) { if((hdl = F->read_handler) != NULL) { F->read_handler = NULL; hdl(F, F->read_data); /* * this call used to be with a NULL pointer, BUT * in the devpoll case we only want to update the * poll set *if* the handler changes state (active -> * NULL or vice versa.) */ devpoll_update_events(F, RB_SELECT_READ, F->read_handler); } } if(!IsFDOpen(F)) continue; /* Read handler closed us..go on to do something more useful */ if((dopoll.dp_fds[i].revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) && (dopoll.dp_fds[i].events & (POLLWRNORM | POLLOUT))) { if((hdl = F->write_handler) != NULL) { F->write_handler = NULL; hdl(F, F->write_data); /* See above similar code in the read case */ devpoll_update_events(F, RB_SELECT_WRITE, F->write_handler); } } } return RB_OK; } while(0); /* XXX Get here, we broke! */ return 0; }
/* int rb_select(long delay) * Input: The maximum time to delay. * Output: Returns -1 on error, 0 on success. * Side-effects: Deregisters future interest in IO and calls the handlers * if an event occurs for an FD. * Comments: Check all connections for new connections and input data * that is to be processed. Also check for connections with data queued * and whether we can write it out. * Called to do the new-style IO, courtesy of squid (like most of this * new IO code). This routine handles the stuff we've hidden in * rb_setselect and fd_table[] and calls callbacks for IO ready * events. */ int rb_select_sigio(long delay) { int num = 0; int revents = 0; int sig; int fd; int ci; PF *hdl; rb_fde_t *F; void *data; siginfo_t si; struct timespec timeout; if(rb_sigio_supports_event() || delay >= 0) { timeout.tv_sec = (delay / 1000); timeout.tv_nsec = (delay % 1000) * 1000000; } for(;;) { if(!sigio_is_screwed) { if(can_do_event || delay < 0) { sig = sigwaitinfo(&our_sigset, &si); } else sig = sigtimedwait(&our_sigset, &si, &timeout); if(sig > 0) { if(sig == SIGIO) { rb_lib_log ("Kernel RT Signal queue overflowed. Is ulimit -i too small(or perhaps /proc/sys/kernel/rtsig-max on old kernels)"); sigio_is_screwed = 1; break; } #ifdef SIGIO_SCHED_EVENT if(sig == RTSIGTIM && can_do_event) { struct ev_entry *ev = (struct ev_entry *)si.si_ptr; if(ev == NULL) continue; rb_run_event(ev); continue; } #endif fd = si.si_fd; pollfd_list.pollfds[fd].revents |= si.si_band; revents = pollfd_list.pollfds[fd].revents; num++; F = rb_find_fd(fd); if(F == NULL) continue; if(revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { hdl = F->read_handler; data = F->read_data; F->read_handler = NULL; F->read_data = NULL; if(hdl) hdl(F, data); } if(revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { hdl = F->write_handler; data = F->write_data; F->write_handler = NULL; F->write_data = NULL; if(hdl) hdl(F, data); } } else break; } else break; } if(!sigio_is_screwed) { /* We don't need to proceed */ rb_set_time(); return 0; } signal(RTSIGIO, SIG_IGN); signal(RTSIGIO, SIG_DFL); sigio_is_screwed = 0; num = poll(pollfd_list.pollfds, pollfd_list.maxindex + 1, delay); rb_set_time(); if(num < 0) { if(!rb_ignore_errno(errno)) return RB_OK; else return RB_ERROR; } if(num == 0) return RB_OK; /* XXX we *could* optimise by falling out after doing num fds ... */ for(ci = 0; ci < pollfd_list.maxindex + 1; ci++) { if(((revents = pollfd_list.pollfds[ci].revents) == 0) || (pollfd_list.pollfds[ci].fd) == -1) continue; fd = pollfd_list.pollfds[ci].fd; F = rb_find_fd(fd); if(F == NULL) continue; if(revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { hdl = F->read_handler; data = F->read_data; F->read_handler = NULL; F->read_data = NULL; if(hdl) hdl(F, data); } if(IsFDOpen(F) && (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))) { hdl = F->write_handler; data = F->write_data; F->write_handler = NULL; F->write_data = NULL; if(hdl) hdl(F, data); } if(F->read_handler == NULL) rb_setselect_sigio(F, RB_SELECT_READ, NULL, NULL); if(F->write_handler == NULL) rb_setselect_sigio(F, RB_SELECT_WRITE, NULL, NULL); } return 0; }