/* * fds_select_check * * given an fd_set that has been passed to select, as well as a list of * fds that are being monitored, figure out which ones have an event and * use the callback provided to deal with the event. */ static void fds_select_check(fd_set *fdset, dlist_t *fds, int *count) { scamper_fd_poll_t *fdp; dlist_node_t *node; /* stop now if there is nothing to check */ if(fdset == NULL || *count == 0) { return; } /* nodes in this list should not be removed while this function is called */ dlist_lock(fds); /* loop through */ node = dlist_head_node(fds); while(node != NULL && *count > 0) { fdp = (scamper_fd_poll_t *)dlist_node_item(node); node = dlist_node_next(node); if(FD_ISSET(fdp->fdn->fd, fdset)) { fdp->cb(fdp->fdn->fd, fdp->param); (*count)--; } } /* can modify the list now */ dlist_unlock(fds); return; }
/* * fds_select_assemble * * given a list of scamper_fd_poll_t structures held in a list, compose an * fd_set for them to pass to select. */ static fd_set *fds_select_assemble(dlist_t *fds, fd_set *fdset, int *nfds) { scamper_fd_poll_t *fdp; dlist_node_t *node; int count = 0; FD_ZERO(fdset); node = dlist_head_node(fds); while(node != NULL) { /* file descriptor associated with the node */ fdp = (scamper_fd_poll_t *)dlist_node_item(node); /* get the next node incase this node is subsequently removed */ node = dlist_node_next(node); /* if there is nothing using this fdn any longer, then stop polling it */ if(fdp->fdn->refcnt == 0 && fdp->fdn->rc0 == NULL) { fd_refcnt_0(fdp->fdn); continue; } /* if the inactive flag is set, then skip over this file descriptor */ if((fdp->flags & SCAMPER_FD_POLL_FLAG_INACTIVE) != 0) { dlist_node_eject(fds, fdp->node); fdp->list = NULL; continue; } /* monitor this file descriptor */ FD_SET(fdp->fdn->fd, fdset); count++; /* update the maxfd seen if appropriate */ if(*nfds < fdp->fdn->fd) { *nfds = fdp->fdn->fd; } } /* * if there are no fds in the set to monitor, then return a null pointer * to pass to select */ if(count == 0) { return NULL; } return fdset; }
static rtsock_pair_t *rtsock_pair_get(uint16_t seq) { rtsock_pair_t *pair; dlist_node_t *node; for(node=dlist_head_node(pairs); node != NULL; node=dlist_node_next(node)) { pair = dlist_node_item(node); if(pair->seq != seq) continue; dlist_node_pop(pairs, node); pair->node = NULL; return pair; } return NULL; }
static void sniff_check(scamper_dl_rec_t *dl) { scamper_task_sig_t *sig; s2t_t *s2t; dlist_node_t *n; scamper_addr_t src; uint16_t id; if(dlist_count(sniff) <= 0) return; if(SCAMPER_DL_IS_ICMP_ECHO_REPLY(dl)) id = dl->dl_icmp_id; else if(SCAMPER_DL_IS_ICMP_Q_ICMP_ECHO(dl)) id = dl->dl_icmp_icmp_id; else return; if(SCAMPER_DL_IS_IPV4(dl)) src.type = SCAMPER_ADDR_TYPE_IPV4; else if(SCAMPER_DL_IS_IPV6(dl)) src.type = SCAMPER_ADDR_TYPE_IPV6; else return; src.addr = dl->dl_ip_dst; for(n = dlist_head_node(sniff); n != NULL; n = dlist_node_next(n)) { s2t = dlist_node_item(n); sig = s2t->sig; if(sig->sig_sniff_icmp_id != id) continue; if(scamper_addr_cmp(sig->sig_sniff_src, &src) != 0) continue; if(s2t->task->funcs->handle_dl != NULL) s2t->task->funcs->handle_dl(s2t->task, dl); } return; }
static int fds_poll(struct timeval *tv) { scamper_fd_t *fd; dlist_node_t *n; int timeout; int rc, count = 0, in = 0, out = 0; size_t size; n = dlist_head_node(fd_list); while(n != NULL) { fd = dlist_node_item(n); n = dlist_node_next(n); /* if there is nothing using this fdn any longer, then stop polling it */ if(fd->refcnt == 0 && fd->rc0 == NULL) { fd_refcnt_0(fd); continue; } /* don't poll an inactive fd */ if((fd->read.flags & SCAMPER_FD_POLL_FLAG_INACTIVE) != 0 && (fd->write.flags & SCAMPER_FD_POLL_FLAG_INACTIVE) != 0) continue; if(count + 1 > poll_fdc) { size = (count+1) * sizeof(struct pollfd); if(realloc_wrap((void **)&poll_fds, size) != 0) { printerror(errno,strerror,__func__,"could not realloc poll_fds"); return -1; } poll_fdc = count + 1; } poll_fds[count].fd = fd->fd; poll_fds[count].events = 0; poll_fds[count].revents = 0; if((fd->read.flags & SCAMPER_FD_POLL_FLAG_INACTIVE) == 0) { poll_fds[count].events |= POLLIN; in++; } if((fd->write.flags & SCAMPER_FD_POLL_FLAG_INACTIVE) == 0) { poll_fds[count].events |= POLLOUT; out++; } count++; } if(tv != NULL) { timeout = (tv->tv_sec * 1000) + (tv->tv_usec / 1000); if(timeout == 0 && tv->tv_usec != 0) timeout++; } else { timeout = -1; } if((rc = poll(poll_fds, count, timeout)) < 0) { printerror(errno, strerror, __func__, "could not poll"); return -1; } if(rc > 0) { if(in != 0) fds_poll_check(POLLIN, rc < in ? rc : in, count); if(out != 0) fds_poll_check(POLLOUT, rc < out ? rc : out, count); } return 0; }