void engine_change_fd_state(int fd, unsigned int stateplus) { int prevstate = (int) get_fd_internal(fd); if((stateplus & FDF_WANTREAD) && !(prevstate & FDF_WANTREAD)) { FD_SET(fd, &g_read_set); prevstate |= FDF_WANTREAD; } else if(!(stateplus & FDF_WANTREAD) && (prevstate & FDF_WANTREAD)) { FD_CLR(fd, &g_read_set); prevstate &= ~(FDF_WANTREAD); } if((stateplus & FDF_WANTWRITE) && !(prevstate & FDF_WANTWRITE)) { FD_SET(fd, &g_write_set); prevstate |= FDF_WANTWRITE; } else if(!(stateplus & FDF_WANTWRITE) && (prevstate & FDF_WANTWRITE)) { FD_CLR(fd, &g_write_set); prevstate &= ~(FDF_WANTWRITE); } set_fd_internal(fd, (void *) prevstate); }
void engine_change_fd_state(long fd, unsigned int stateplus) { long arrayidx = (long) get_fd_internal(fd); struct pollfd *pfd = &poll_fds[arrayidx]; pfd->events = 0; if(stateplus & FDF_WANTREAD) pfd->events |= POLLIN|POLLHUP|POLLERR; if(stateplus & FDF_WANTWRITE) pfd->events |= POLLOUT; }
void engine_del_fd(long fd) { long arrayidx = (long) get_fd_internal(fd); /* If it's at the end of the array, just chop it off */ if(arrayidx == last_pfd) { fdfprintf(stderr, "Removing %d[%d] from end of pollfds\n", last_pfd, fd); last_pfd--; return; } /* Otherwise, move the last array member to where the old one was */ fdfprintf(stderr, "Moving pfd %d[%d] to vacated spot %d[%d] -- now %d[%d]\n", last_pfd, poll_fds[last_pfd].fd, arrayidx, fd, last_pfd, fd); memcpy(&poll_fds[arrayidx], &poll_fds[last_pfd], sizeof(struct pollfd)); last_pfd--; set_fd_internal(poll_fds[arrayidx].fd, (void *) arrayidx); }
int engine_read_message(time_t delay) { struct pollfd events[ENGINE_MAX_EVENTS], *pevent; struct dvpoll dopoll; int nfds, i, numloops = 0, eventsfull; unsigned int fdflags, fdevents; int fdtype; void *fdvalue; aClient *cptr; aListener *lptr; dopoll.dp_fds = events; dopoll.dp_nfds = ENGINE_MAX_EVENTS; dopoll.dp_timeout = delay; do { nfds = ioctl(devpoll_id, DP_POLL, &dopoll); if (nfds < 0) { if (errno == EINTR || errno == EAGAIN) return -1; report_error("ioctl(devpoll): %s:%s", &me); sleep(5); return -1; } eventsfull = nfds == ENGINE_MAX_EVENTS; if (delay || numloops) NOW = timeofday = time(NULL); numloops++; for (i = 0, pevent = events; i < nfds; i++, pevent++) { fdevents = (unsigned int)get_fd_internal(pevent->fd); if (pevent->fd != -1) { int rr = (pevent->revents & (POLLIN|POLLHUP|POLLERR)) && (fdevents & (POLLIN|POLLHUP|POLLERR)); int rw = (pevent->revents & POLLOUT) && (fdevents & POLLOUT); get_fd_info(pevent->fd, &fdtype, &fdflags, &fdvalue); switch (fdtype) { case FDT_NONE: break; case FDT_AUTH: cptr = (aClient*)fdvalue; if (rr) read_authports(cptr); if (rw && cptr->authfd >= 0) send_authports(cptr); check_client_fd(cptr); break; case FDT_LISTENER: lptr = (aListener*)fdvalue; if (rr) accept_connection(lptr); break; case FDT_RESOLVER: do_dns_async(); break; case FDT_CLIENT: cptr = (aClient*)fdvalue; readwrite_client(cptr, rr, rw); break; case FDT_CALLBACKP: { struct fd_callbackp *fdcb = (struct fd_callbackp*)fdvalue; fdcb->rdf = rr; fdcb->wrf = rw; (*fdcb->callback)(fdcb); break; } default: abort(); } } } } while (eventsfull && numloops < ENGINE_MAX_LOOPS); return 0; }