1 #include "fdevent.h"
2 #include "buffer.h"
3 #include "log.h"
4 
5 #include <sys/time.h>
6 #include <sys/types.h>
7 
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <errno.h>
12 #include <signal.h>
13 #include <fcntl.h>
14 #include <assert.h>
15 
16 #ifdef USE_SELECT
17 
fdevent_select_reset(fdevents * ev)18 static int fdevent_select_reset(fdevents *ev) {
19 	FD_ZERO(&(ev->select_set_read));
20 	FD_ZERO(&(ev->select_set_write));
21 	FD_ZERO(&(ev->select_set_error));
22 	ev->select_max_fd = -1;
23 
24 	return 0;
25 }
26 
fdevent_select_event_del(fdevents * ev,int fde_ndx,int fd)27 static int fdevent_select_event_del(fdevents *ev, int fde_ndx, int fd) {
28 	if (fde_ndx < 0) return -1;
29 
30 	FD_CLR(fd, &(ev->select_set_read));
31 	FD_CLR(fd, &(ev->select_set_write));
32 	FD_CLR(fd, &(ev->select_set_error));
33 
34 	return -1;
35 }
36 
fdevent_select_event_set(fdevents * ev,int fde_ndx,int fd,int events)37 static int fdevent_select_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
38 	UNUSED(fde_ndx);
39 
40 	/* we should be protected by max-fds, but you never know */
41 	assert(fd < ((int)FD_SETSIZE));
42 
43 	if (events & FDEVENT_IN) {
44 		FD_SET(fd, &(ev->select_set_read));
45 	} else {
46 		FD_CLR(fd, &(ev->select_set_read));
47 	}
48 	if (events & FDEVENT_OUT) {
49 		FD_SET(fd, &(ev->select_set_write));
50 	} else {
51 		FD_CLR(fd, &(ev->select_set_write));
52 	}
53 	FD_SET(fd, &(ev->select_set_error));
54 
55 	if (fd > ev->select_max_fd) ev->select_max_fd = fd;
56 
57 	return fd;
58 }
59 
fdevent_select_poll(fdevents * ev,int timeout_ms)60 static int fdevent_select_poll(fdevents *ev, int timeout_ms) {
61 	struct timeval tv;
62 
63 	tv.tv_sec =  timeout_ms / 1000;
64 	tv.tv_usec = (timeout_ms % 1000) * 1000;
65 
66 	ev->select_read = ev->select_set_read;
67 	ev->select_write = ev->select_set_write;
68 	ev->select_error = ev->select_set_error;
69 
70 	return select(ev->select_max_fd + 1, &(ev->select_read), &(ev->select_write), &(ev->select_error), &tv);
71 }
72 
fdevent_select_event_get_revent(fdevents * ev,size_t ndx)73 static int fdevent_select_event_get_revent(fdevents *ev, size_t ndx) {
74 	int revents = 0;
75 
76 	if (FD_ISSET(ndx, &(ev->select_read))) {
77 		revents |= FDEVENT_IN;
78 	}
79 	if (FD_ISSET(ndx, &(ev->select_write))) {
80 		revents |= FDEVENT_OUT;
81 	}
82 	if (FD_ISSET(ndx, &(ev->select_error))) {
83 		revents |= FDEVENT_ERR;
84 	}
85 
86 	return revents;
87 }
88 
fdevent_select_event_get_fd(fdevents * ev,size_t ndx)89 static int fdevent_select_event_get_fd(fdevents *ev, size_t ndx) {
90 	UNUSED(ev);
91 
92 	return ndx;
93 }
94 
fdevent_select_event_next_fdndx(fdevents * ev,int ndx)95 static int fdevent_select_event_next_fdndx(fdevents *ev, int ndx) {
96 	int i;
97 
98 	i = (ndx < 0) ? 0 : ndx + 1;
99 
100 	for (; i < ev->select_max_fd + 1; i++) {
101 		if (FD_ISSET(i, &(ev->select_read))) return i;
102 		if (FD_ISSET(i, &(ev->select_write))) return i;
103 		if (FD_ISSET(i, &(ev->select_error))) return i;
104 	}
105 
106 	return -1;
107 }
108 
fdevent_select_init(fdevents * ev)109 int fdevent_select_init(fdevents *ev) {
110 	ev->type = FDEVENT_HANDLER_SELECT;
111 #define SET(x) \
112 	ev->x = fdevent_select_##x;
113 
114 	SET(reset);
115 	SET(poll);
116 
117 	SET(event_del);
118 	SET(event_set);
119 
120 	SET(event_next_fdndx);
121 	SET(event_get_fd);
122 	SET(event_get_revent);
123 
124 	return 0;
125 }
126 
127 #else
fdevent_select_init(fdevents * ev)128 int fdevent_select_init(fdevents *ev) {
129 	UNUSED(ev);
130 
131 	return -1;
132 }
133 #endif
134