File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src / fdevent.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:35:00 2016 UTC (7 years, 8 months ago) by misho
Branches: lighttpd, MAIN
CVS tags: v1_4_41p8, HEAD
lighttpd 1.4.41

    1: #include "first.h"
    2: 
    3: #include "base.h"
    4: #include "log.h"
    5: 
    6: #include <sys/types.h>
    7: 
    8: #include <unistd.h>
    9: #include <stdlib.h>
   10: #include <string.h>
   11: #include <errno.h>
   12: #include <stdio.h>
   13: #include <fcntl.h>
   14: #include <assert.h>
   15: 
   16: 
   17: fdevents *fdevent_init(server *srv, size_t maxfds, fdevent_handler_t type) {
   18: 	fdevents *ev;
   19: 
   20: 	ev = calloc(1, sizeof(*ev));
   21: 	force_assert(NULL != ev);
   22: 	ev->srv = srv;
   23: 	ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));
   24: 	force_assert(NULL != ev->fdarray);
   25: 	ev->maxfds = maxfds;
   26: 
   27: 	switch(type) {
   28: 	case FDEVENT_HANDLER_POLL:
   29: 		if (0 != fdevent_poll_init(ev)) {
   30: 			log_error_write(srv, __FILE__, __LINE__, "S",
   31: 				"event-handler poll failed");
   32: 			goto error;
   33: 		}
   34: 		return ev;
   35: 	case FDEVENT_HANDLER_SELECT:
   36: 		if (0 != fdevent_select_init(ev)) {
   37: 			log_error_write(srv, __FILE__, __LINE__, "S",
   38: 				"event-handler select failed");
   39: 			goto error;
   40: 		}
   41: 		return ev;
   42: 	case FDEVENT_HANDLER_LINUX_SYSEPOLL:
   43: 		if (0 != fdevent_linux_sysepoll_init(ev)) {
   44: 			log_error_write(srv, __FILE__, __LINE__, "S",
   45: 				"event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"");
   46: 			goto error;
   47: 		}
   48: 		return ev;
   49: 	case FDEVENT_HANDLER_SOLARIS_DEVPOLL:
   50: 		if (0 != fdevent_solaris_devpoll_init(ev)) {
   51: 			log_error_write(srv, __FILE__, __LINE__, "S",
   52: 				"event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"");
   53: 			goto error;
   54: 		}
   55: 		return ev;
   56: 	case FDEVENT_HANDLER_SOLARIS_PORT:
   57: 		if (0 != fdevent_solaris_port_init(ev)) {
   58: 			log_error_write(srv, __FILE__, __LINE__, "S",
   59: 				"event-handler solaris-eventports failed, try to set server.event-handler = \"poll\" or \"select\"");
   60: 			goto error;
   61: 		}
   62: 		return ev;
   63: 	case FDEVENT_HANDLER_FREEBSD_KQUEUE:
   64: 		if (0 != fdevent_freebsd_kqueue_init(ev)) {
   65: 			log_error_write(srv, __FILE__, __LINE__, "S",
   66: 				"event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"");
   67: 			goto error;
   68: 		}
   69: 		return ev;
   70: 	case FDEVENT_HANDLER_LIBEV:
   71: 		if (0 != fdevent_libev_init(ev)) {
   72: 			log_error_write(srv, __FILE__, __LINE__, "S",
   73: 				"event-handler libev failed, try to set server.event-handler = \"poll\" or \"select\"");
   74: 			goto error;
   75: 		}
   76: 		return ev;
   77: 	case FDEVENT_HANDLER_UNSET:
   78: 		break;
   79: 	}
   80: 
   81: error:
   82: 	free(ev->fdarray);
   83: 	free(ev);
   84: 
   85: 	log_error_write(srv, __FILE__, __LINE__, "S",
   86: 		"event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"");
   87: 	return NULL;
   88: }
   89: 
   90: void fdevent_free(fdevents *ev) {
   91: 	size_t i;
   92: 	if (!ev) return;
   93: 
   94: 	if (ev->free) ev->free(ev);
   95: 
   96: 	for (i = 0; i < ev->maxfds; i++) {
   97: 		if (ev->fdarray[i]) free(ev->fdarray[i]);
   98: 	}
   99: 
  100: 	free(ev->fdarray);
  101: 	free(ev);
  102: }
  103: 
  104: int fdevent_reset(fdevents *ev) {
  105: 	if (ev->reset) return ev->reset(ev);
  106: 
  107: 	return 0;
  108: }
  109: 
  110: static fdnode *fdnode_init(void) {
  111: 	fdnode *fdn;
  112: 
  113: 	fdn = calloc(1, sizeof(*fdn));
  114: 	force_assert(NULL != fdn);
  115: 	fdn->fd = -1;
  116: 	return fdn;
  117: }
  118: 
  119: static void fdnode_free(fdnode *fdn) {
  120: 	free(fdn);
  121: }
  122: 
  123: int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
  124: 	fdnode *fdn;
  125: 
  126: 	fdn = fdnode_init();
  127: 	fdn->handler = handler;
  128: 	fdn->fd      = fd;
  129: 	fdn->ctx     = ctx;
  130: 	fdn->handler_ctx = NULL;
  131: 	fdn->events  = 0;
  132: 
  133: 	ev->fdarray[fd] = fdn;
  134: 
  135: 	return 0;
  136: }
  137: 
  138: int fdevent_unregister(fdevents *ev, int fd) {
  139: 	fdnode *fdn;
  140: 
  141: 	if (!ev) return 0;
  142: 	fdn = ev->fdarray[fd];
  143: 
  144: 	fdnode_free(fdn);
  145: 
  146: 	ev->fdarray[fd] = NULL;
  147: 
  148: 	return 0;
  149: }
  150: 
  151: void fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
  152: 	if (-1 == fd) return;
  153: 	if (NULL == ev->fdarray[fd]) return;
  154: 
  155: 	if (ev->event_del) *fde_ndx = ev->event_del(ev, *fde_ndx, fd);
  156: 	ev->fdarray[fd]->events = 0;
  157: }
  158: 
  159: void fdevent_event_set(fdevents *ev, int *fde_ndx, int fd, int events) {
  160: 	if (-1 == fd) return;
  161: 
  162: 	/*(Note: skips registering with kernel if initial events is 0,
  163:          * so caller should pass non-zero events for initial registration.
  164:          * If never registered due to never being called with non-zero events,
  165:          * then FDEVENT_HUP or FDEVENT_ERR will never be returned.) */
  166: 	if (ev->fdarray[fd]->events == events) return;/*(no change; nothing to do)*/
  167: 
  168: 	if (ev->event_set) *fde_ndx = ev->event_set(ev, *fde_ndx, fd, events);
  169: 	ev->fdarray[fd]->events = events;
  170: }
  171: 
  172: void fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int event) {
  173: 	int events;
  174: 	if (-1 == fd) return;
  175: 
  176: 	events = ev->fdarray[fd]->events;
  177: 	if ((events & event) || 0 == event) return; /*(no change; nothing to do)*/
  178: 
  179: 	events |= event;
  180: 	if (ev->event_set) *fde_ndx = ev->event_set(ev, *fde_ndx, fd, events);
  181: 	ev->fdarray[fd]->events = events;
  182: }
  183: 
  184: void fdevent_event_clr(fdevents *ev, int *fde_ndx, int fd, int event) {
  185: 	int events;
  186: 	if (-1 == fd) return;
  187: 
  188: 	events = ev->fdarray[fd]->events;
  189: 	if (!(events & event)) return; /*(no change; nothing to do)*/
  190: 
  191: 	events &= ~event;
  192: 	if (ev->event_set) *fde_ndx = ev->event_set(ev, *fde_ndx, fd, events);
  193: 	ev->fdarray[fd]->events = events;
  194: }
  195: 
  196: int fdevent_poll(fdevents *ev, int timeout_ms) {
  197: 	if (ev->poll == NULL) SEGFAULT();
  198: 	return ev->poll(ev, timeout_ms);
  199: }
  200: 
  201: int fdevent_event_get_revent(fdevents *ev, size_t ndx) {
  202: 	if (ev->event_get_revent == NULL) SEGFAULT();
  203: 
  204: 	return ev->event_get_revent(ev, ndx);
  205: }
  206: 
  207: int fdevent_event_get_fd(fdevents *ev, size_t ndx) {
  208: 	if (ev->event_get_fd == NULL) SEGFAULT();
  209: 
  210: 	return ev->event_get_fd(ev, ndx);
  211: }
  212: 
  213: fdevent_handler fdevent_get_handler(fdevents *ev, int fd) {
  214: 	if (ev->fdarray[fd] == NULL) SEGFAULT();
  215: 	if (ev->fdarray[fd]->fd != fd) SEGFAULT();
  216: 
  217: 	return ev->fdarray[fd]->handler;
  218: }
  219: 
  220: void * fdevent_get_context(fdevents *ev, int fd) {
  221: 	if (ev->fdarray[fd] == NULL) SEGFAULT();
  222: 	if (ev->fdarray[fd]->fd != fd) SEGFAULT();
  223: 
  224: 	return ev->fdarray[fd]->ctx;
  225: }
  226: 
  227: void fd_close_on_exec(int fd) {
  228: #ifdef FD_CLOEXEC
  229: 	if (fd < 0) return;
  230: 	force_assert(-1 != fcntl(fd, F_SETFD, FD_CLOEXEC));
  231: #else
  232: 	UNUSED(fd);
  233: #endif
  234: }
  235: 
  236: int fdevent_fcntl_set(fdevents *ev, int fd) {
  237: 	fd_close_on_exec(fd);
  238: 	if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd);
  239: #ifdef O_NONBLOCK
  240: 	return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
  241: #else
  242: 	return 0;
  243: #endif
  244: }
  245: 
  246: 
  247: int fdevent_event_next_fdndx(fdevents *ev, int ndx) {
  248: 	if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx);
  249: 
  250: 	return -1;
  251: }
  252: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>