1 #include "fdevent.h"
2 #include "buffer.h"
3 #include "log.h"
4 
5 #include <assert.h>
6 
7 #ifdef USE_LIBEV
8 
9 # include <ev.h>
10 
io_watcher_cb(struct ev_loop * loop,ev_io * w,int revents)11 static void io_watcher_cb(struct ev_loop *loop, ev_io *w, int revents) {
12 	fdevents *ev = w->data;
13 	fdnode *fdn = ev->fdarray[w->fd];
14 	int r = 0;
15 	UNUSED(loop);
16 
17 	if (revents & EV_READ) r |= FDEVENT_IN;
18 	if (revents & EV_WRITE) r |= FDEVENT_OUT;
19 	if (revents & EV_ERROR) r |= FDEVENT_ERR;
20 
21 	switch (r = (*fdn->handler)(ev->srv, fdn->ctx, r)) {
22 	case HANDLER_FINISHED:
23 	case HANDLER_GO_ON:
24 	case HANDLER_WAIT_FOR_EVENT:
25 	case HANDLER_WAIT_FOR_FD:
26 		break;
27 	case HANDLER_ERROR:
28 		/* should never happen */
29 		SEGFAULT();
30 		break;
31 	default:
32 		log_error_write(ev->srv, __FILE__, __LINE__, "d", r);
33 		break;
34 	}
35 }
36 
fdevent_libev_free(fdevents * ev)37 static void fdevent_libev_free(fdevents *ev) {
38 	UNUSED(ev);
39 }
40 
fdevent_libev_event_del(fdevents * ev,int fde_ndx,int fd)41 static int fdevent_libev_event_del(fdevents *ev, int fde_ndx, int fd) {
42 	fdnode *fdn;
43 	ev_io *watcher;
44 
45 	if (-1 == fde_ndx) return -1;
46 
47 	fdn = ev->fdarray[fd];
48 	watcher = fdn->handler_ctx;
49 
50 	if (!watcher) return -1;
51 
52 	ev_io_stop(ev->libev_loop, watcher);
53 	free(watcher);
54 	fdn->handler_ctx = NULL;
55 
56 	return -1;
57 }
58 
fdevent_libev_event_set(fdevents * ev,int fde_ndx,int fd,int events)59 static int fdevent_libev_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
60 	fdnode *fdn = ev->fdarray[fd];
61 	ev_io *watcher = fdn->handler_ctx;
62 	int ev_events = 0;
63 	UNUSED(fde_ndx);
64 
65 	if (events & FDEVENT_IN)  ev_events |= EV_READ;
66 	if (events & FDEVENT_OUT) ev_events |= EV_WRITE;
67 
68 	if (!watcher) {
69 		fdn->handler_ctx = watcher = calloc(1, sizeof(ev_io));
70 		assert(watcher);
71 
72 		ev_io_init(watcher, io_watcher_cb, fd, ev_events);
73 		watcher->data = ev;
74 		ev_io_start(ev->libev_loop, watcher);
75 	} else {
76 		if ((watcher->events & (EV_READ | EV_WRITE)) != ev_events) {
77 			ev_io_stop(ev->libev_loop, watcher);
78 			ev_io_set(watcher, watcher->fd, ev_events);
79 			ev_io_start(ev->libev_loop, watcher);
80 		}
81 	}
82 
83 	return fd;
84 }
85 
timeout_watcher_cb(struct ev_loop * loop,ev_timer * w,int revents)86 static void timeout_watcher_cb(struct ev_loop *loop, ev_timer *w, int revents) {
87 	UNUSED(loop);
88 	UNUSED(w);
89 	UNUSED(revents);
90 }
91 
92 
fdevent_libev_poll(fdevents * ev,int timeout_ms)93 static int fdevent_libev_poll(fdevents *ev, int timeout_ms) {
94 	ev_timer timeout_watcher;
95 
96 	ev_init(&timeout_watcher, timeout_watcher_cb);
97 	ev_timer_set(&timeout_watcher, ((ev_tstamp) timeout_ms)/1000.0, 0.0);
98 	ev_timer_start(ev->libev_loop, &timeout_watcher);
99 
100 	ev_loop(ev->libev_loop, EVLOOP_ONESHOT);
101 
102 	ev_timer_stop(ev->libev_loop, &timeout_watcher);
103 
104 	return 0;
105 }
106 
fdevent_libev_event_get_revent(fdevents * ev,size_t ndx)107 static int fdevent_libev_event_get_revent(fdevents *ev, size_t ndx) {
108 	UNUSED(ev);
109 	UNUSED(ndx);
110 
111 	return 0;
112 }
113 
fdevent_libev_event_get_fd(fdevents * ev,size_t ndx)114 static int fdevent_libev_event_get_fd(fdevents *ev, size_t ndx) {
115 	UNUSED(ev);
116 	UNUSED(ndx);
117 
118 	return -1;
119 }
120 
fdevent_libev_event_next_fdndx(fdevents * ev,int ndx)121 static int fdevent_libev_event_next_fdndx(fdevents *ev, int ndx) {
122 	UNUSED(ev);
123 	UNUSED(ndx);
124 
125 	return -1;
126 }
127 
fdevent_libev_reset(fdevents * ev)128 static int fdevent_libev_reset(fdevents *ev) {
129 	UNUSED(ev);
130 
131 	ev_default_fork();
132 
133 	return 0;
134 }
135 
fdevent_libev_init(fdevents * ev)136 int fdevent_libev_init(fdevents *ev) {
137 	ev->type = FDEVENT_HANDLER_LIBEV;
138 #define SET(x) \
139 	ev->x = fdevent_libev_##x;
140 
141 	SET(free);
142 	SET(poll);
143 	SET(reset);
144 
145 	SET(event_del);
146 	SET(event_set);
147 
148 	SET(event_next_fdndx);
149 	SET(event_get_fd);
150 	SET(event_get_revent);
151 
152 	if (NULL == (ev->libev_loop = ev_default_loop(0))) {
153 		log_error_write(ev->srv, __FILE__, __LINE__, "S",
154 			"ev_default_loop failed , try to set server.event-handler = \"poll\" or \"select\"");
155 
156 		return -1;
157 	}
158 
159 	return 0;
160 }
161 
162 #else
fdevent_libev_init(fdevents * ev)163 int fdevent_libev_init(fdevents *ev) {
164 	UNUSED(ev);
165 
166 	log_error_write(ev->srv, __FILE__, __LINE__, "S",
167 		"libev not supported, try to set server.event-handler = \"poll\" or \"select\"");
168 
169 	return -1;
170 }
171 #endif
172