static int fdw_poll_add_fd(int idx, t_fdwatch_type rw) { static int ridx; // eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d rw: %d", fd, rw); if (_ridx[idx] < 0) { ridx = nofds++; fds[ridx].fd = fdw_fd(fdw_fds + idx); _ridx[idx] = ridx; _rridx[ridx] = idx; // eventlog(eventlog_level_trace, __FUNCTION__, "adding new_ fd on %d", ridx); } else { if (fds[_ridx[idx]].fd != fdw_fd(fdw_fds + idx)) { eventlog(eventlog_level_error,__FUNCTION__,"BUG: found existent poll_fd entry for same idx with different fd"); return -1; } ridx = _ridx[idx]; // eventlog(eventlog_level_trace, __FUNCTION__, "updating fd on %d", ridx); } fds[ridx].events = 0; if (rw & fdwatch_type_read) fds[ridx].events |= POLLIN; if (rw & fdwatch_type_write) fds[ridx].events |= POLLOUT; return 0; }
static int fdw_select_cb(t_fdwatch_fd *cfd, void *data) { // eventlog(eventlog_level_trace, __FUNCTION__, "idx: %d fd: %d", idx, fdw_fd->fd); if (fdw_rw(cfd) & fdwatch_type_read && PSOCK_FD_ISSET(fdw_fd(cfd), rfds) && fdw_hnd(cfd)(fdw_data(cfd), fdwatch_type_read) == -2) return 0; if (fdw_rw(cfd) & fdwatch_type_write && PSOCK_FD_ISSET(fdw_fd(cfd), wfds)) fdw_hnd(cfd)(fdw_data(cfd), fdwatch_type_write); return 0; }
extern int fdwatch_del_fd(int idx) { if (idx < 0 || idx >= fdw_maxcons) { ERROR2("out of bounds idx [{}] (max: {})", idx, fdw_maxcons); return -1; } t_fdwatch_fd *cfd = fdw_fds + idx; if (!fdw_rw(cfd)) { ERROR0("found reseted rw"); return -1; } fdw->del(idx); /* remove it from uselist, add it to freelist */ uselist.remove(*cfd); freelist.push_back(*cfd); fdw_fd(cfd) = 0; fdw_rw(cfd) = 0; fdw_data(cfd) = NULL; fdw_hnd(cfd) = NULL; return 0; }
static int fdw_select_del_fd(int idx) { int fd; fd = fdw_fd(fdw_fds + idx); // eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d", fd); if (sr > 0) eventlog(eventlog_level_error, __FUNCTION__, "BUG: called while still handling sockets"); PSOCK_FD_CLR(fd, trfds); PSOCK_FD_CLR(fd, twfds); return 0; }
static int fdw_select_add_fd(int idx, t_fdwatch_type rw) { int fd; // eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d rw: %d", fd, rw); fd = fdw_fd(fdw_fds + idx); /* select() interface is limited by FD_SETSIZE max socket value */ if (fd >= FD_SETSIZE) return -1; if (rw & fdwatch_type_read) PSOCK_FD_SET(fd, trfds); else PSOCK_FD_CLR(fd, trfds); if (rw & fdwatch_type_write) PSOCK_FD_SET(fd, twfds); else PSOCK_FD_CLR(fd, twfds); if (smaxfd < fd) smaxfd = fd; return 0; }
int FDWEpollBackend::del(int idx) { // eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d", fd); if (sr > 0) ERROR0("BUG: called while still handling sockets"); if (fdw_rw(fdw_fds + idx)) { struct epoll_event tmpev; std::memset(&tmpev, 0, sizeof(tmpev)); tmpev.events = 0; tmpev.data.fd = idx; if (epoll_ctl(epfd, EPOLL_CTL_DEL, fdw_fd(fdw_fds + idx), &tmpev)) { ERROR0("got error from epoll_ctl()"); return -1; } } return 0; }
extern int fdwatch_add_fd(int fd, unsigned rw, fdwatch_handler h, void *data) { /* max sockets reached */ if (freelist.empty()) return -1; t_fdwatch_fd *cfd = &freelist.front(); fdw_fd(cfd) = fd; if (fdw->add(fdw_idx(cfd), rw)) return -1; /* add it to used sockets list, remove it from free list */ uselist.push_back(*cfd); freelist.remove(*cfd); fdw_rw(cfd) = rw; fdw_data(cfd) = data; fdw_hnd(cfd) = h; return fdw_idx(cfd); }
int FDWEpollBackend::add(int idx, unsigned rw) { // eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d rw: %d", fd, rw); struct epoll_event tmpev; std::memset(&tmpev, 0, sizeof(tmpev)); tmpev.events = 0; if (rw & fdwatch_type_read) tmpev.events |= EPOLLIN; if (rw & fdwatch_type_write) tmpev.events |= EPOLLOUT; int op = fdw_rw(fdw_fds + idx) ? EPOLL_CTL_MOD : EPOLL_CTL_ADD; tmpev.data.fd = idx; if (epoll_ctl(epfd, op, fdw_fd(fdw_fds + idx), &tmpev)) { ERROR0("got error from epoll_ctl()"); return -1; } return 0; }
int FDWKqueueBackend::add(int idx, unsigned rw) { int idxr; t_fdwatch_fd *cfd = fdw_fds + idx; /* eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d rw: %d", fd, rw); */ /* adding read event filter */ if (!(fdw_rw(cfd) & fdwatch_type_read) && rw & fdwatch_type_read) { if (rridx[idx] >= 0 && rridx[idx] < nochanges && kqchanges[rridx[idx]].ident == fdw_fd(cfd)) { idxr = rridx[idx]; /* eventlog(eventlog_level_trace, __FUNCTION__, "updating change event (read) fd on %d", ridx); */ } else { idxr = nochanges++; rridx[idx] = idxr; /* eventlog(eventlog_level_trace, __FUNCTION__, "adding new change event (read) fd on %d", ridx); */ } EV_SET(kqchanges.get() + idxr, fdw_fd(cfd), EVFILT_READ, EV_ADD, 0, 0, (void*)idx); } else if (fdw_rw(cfd) & fdwatch_type_read && !( rw & fdwatch_type_read)) { if (rridx[idx] >= 0 && rridx[idx] < nochanges && kqchanges[rridx[idx]].ident == fdw_fd(cfd)) { idxr = rridx[idx]; /* eventlog(eventlog_level_trace, __FUNCTION__, "updating change event (read) fd on %d", ridx); */ } else { idxr = nochanges++; rridx[idx] = idxr; /* eventlog(eventlog_level_trace, __FUNCTION__, "adding new change event (read) fd on %d", ridx); */ } EV_SET(kqchanges.get() + idxr, fdw_fd(cfd), EVFILT_READ, EV_DELETE, 0, 0, (void*)idx); } /* adding write event filter */ if (!(fdw_rw(cfd) & fdwatch_type_write) && rw & fdwatch_type_write) { if (wridx[idx] >= 0 && wridx[idx] < nochanges && kqchanges[wridx[idx]].ident == fdw_fd(cfd)) { idxr = wridx[idx]; /* eventlog(eventlog_level_trace, __FUNCTION__, "updating change event (write) fd on %d", ridx); */ } else { idxr = nochanges++; wridx[idx] = idxr; /* eventlog(eventlog_level_trace, __FUNCTION__, "adding new change event (write) fd on %d", ridx); */ } EV_SET(kqchanges.get() + idxr, fdw_fd(cfd), EVFILT_WRITE, EV_ADD, 0, 0, (void*)idx); } else if (fdw_rw(cfd) & fdwatch_type_write && !(rw & fdwatch_type_write)) { if (wridx[idx] >= 0 && wridx[idx] < nochanges && kqchanges[wridx[idx]].ident == fdw_fd(cfd)) { idxr = wridx[idx]; /* eventlog(eventlog_level_trace, __FUNCTION__, "updating change event (write) fd on %d", ridx); */ } else { idxr = nochanges++; wridx[idx] = idxr; /* eventlog(eventlog_level_trace, __FUNCTION__, "adding new change event (write) fd on %d", ridx); */ } EV_SET(kqchanges.get() + idxr, fdw_fd(cfd), EVFILT_WRITE, EV_DELETE, 0, 0, (void*)idx); } return 0; }
int FDWKqueueBackend::del(int idx) { /* eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d", fd); */ if (sr > 0) eventlog(eventlog_level_error, __FUNCTION__, "BUG: called while still handling sockets"); t_fdwatch_fd *cfd = fdw_fds + idx; /* the last event changes about this fd has not yet been sent to kernel */ if (fdw_rw(cfd) & fdwatch_type_read && nochanges && rridx[idx] >= 0 && rridx[idx] < nochanges && kqchanges[rridx[idx]].ident == fdw_fd(cfd)) { nochanges--; if (rridx[idx] < nochanges) { int oidx; oidx = (unsigned long)(kqchanges[nochanges].udata); if (kqchanges[nochanges].filter == EVFILT_READ && rridx[oidx] == nochanges) { /* eventlog(eventlog_level_trace, __FUNCTION__, "not last, moving %d", kqchanges[rnfds].ident); */ rridx[oidx] = rridx[idx]; std::memcpy(kqchanges.get() + rridx[idx], kqchanges.get() + nochanges, sizeof(struct kevent)); } if (kqchanges[nochanges].filter == EVFILT_WRITE && wridx[oidx] == nochanges) { /* eventlog(eventlog_level_trace, __FUNCTION__, "not last, moving %d", kqchanges[rnfds].ident); */ wridx[oidx] = rridx[idx]; std::memcpy(kqchanges.get() + rridx[idx], kqchanges.get() + nochanges, sizeof(struct kevent)); } } rridx[idx] = -1; } if (fdw_rw(cfd) & fdwatch_type_write && nochanges && wridx[idx] >= 0 && wridx[idx] < nochanges && kqchanges[wridx[idx]].ident == fdw_fd(cfd)) { nochanges--; if (wridx[idx] < nochanges) { int oidx; oidx = (unsigned long)(kqchanges[nochanges].udata); if (kqchanges[nochanges].filter == EVFILT_READ && rridx[oidx] == nochanges) { /* eventlog(eventlog_level_trace, __FUNCTION__, "not last, moving %d", kqchanges[rnfds].ident); */ rridx[oidx] = wridx[idx]; std::memcpy(kqchanges.get() + wridx[idx], kqchanges.get() + nochanges, sizeof(struct kevent)); } if (kqchanges[nochanges].filter == EVFILT_WRITE && wridx[oidx] == nochanges) { /* eventlog(eventlog_level_trace, __FUNCTION__, "not last, moving %d", kqchanges[rnfds].ident); */ wridx[oidx] = wridx[idx]; std::memcpy(kqchanges.get() + wridx[idx], kqchanges.get() + nochanges, sizeof(struct kevent)); } } wridx[idx] = -1; } /* here we presume the calling code does close() on the socket and if so * it is automatically removed from any kernel kqueues */ return 0; }