/** * events_network_register(func, cookie, s, op): * Register ${func}(${cookie}) to be run when socket ${s} is ready for * reading or writing depending on whether ${op} is EVENTS_NETWORK_OP_READ or * EVENTS_NETWORK_OP_WRITE. If there is already an event registration for * this ${s}/${op} pair, errno will be set to EEXIST and the function will * fail. */ int events_network_register(int (*func)(void *), void * cookie, int s, int op) { struct eventrec ** r; /* Initialize if necessary. */ if (initsocketlist()) goto err0; /* Sanity-check socket number. */ if ((s < 0) || (s >= (int)FD_SETSIZE)) { warn0("Invalid file descriptor for network event: %d", s); goto err0; } /* Sanity-check operation. */ if ((op != EVENTS_NETWORK_OP_READ) && (op != EVENTS_NETWORK_OP_WRITE)) { warn0("Invalid operation for network event: %d", op); goto err0; } /* Grow the array if necessary. */ if (((size_t)(s) >= socketlist_getsize(S)) && (growsocketlist(s + 1) != 0)) goto err0; /* Look up the relevant event pointer. */ if (op == EVENTS_NETWORK_OP_READ) r = &socketlist_get(S, s)->reader; else r = &socketlist_get(S, s)->writer; /* Error out if we already have an event registered. */ if (*r != NULL) { errno = EEXIST; goto err0; } /* Register the new event. */ if ((*r = events_mkrec(func, cookie)) == NULL) goto err0; /* * Increment events-registered counter; and if it was zero, start the * inter-select duration clock. */ if (nev++ == 0) events_network_selectstats_startclock(); /* Success! */ return (0); err0: /* Failure! */ return (-1); }
/** * events_timer_register(func, cookie, timeo): * Register ${func}(${cookie}) to be run ${timeo} in the future. Return a * cookie which can be passed to events_timer_cancel or events_timer_reset. */ void * events_timer_register(int (*func)(void *), void * cookie, const struct timeval * timeo) { struct eventrec * r; struct timerrec * t; struct timeval tv; /* Create the timer queue if it doesn't exist yet. */ if (Q == NULL) { if ((Q = timerqueue_init()) == NULL) goto err0; } /* Bundle into an eventrec record. */ if ((r = events_mkrec(func, cookie)) == NULL) goto err0; /* Create a timer record. */ if ((t = malloc(sizeof(struct timerrec))) == NULL) goto err1; t->r = r; memcpy(&t->tv_orig, timeo, sizeof(struct timeval)); /* Compute the absolute timeout. */ if (monoclock_get(&tv)) goto err2; tv.tv_sec += t->tv_orig.tv_sec; if ((tv.tv_usec += t->tv_orig.tv_usec) >= 1000000) { tv.tv_usec -= 1000000; tv.tv_sec += 1; } /* Add this to the timer queue. */ if ((t->cookie = timerqueue_add(Q, &tv, t)) == NULL) goto err2; /* Success! */ return (t); err2: free(t); err1: events_freerec(r); err0: /* Failure! */ return (NULL); }