1 #include "fdevent.h"
2 #include "buffer.h"
3 #include "log.h"
4 
5 #include <sys/types.h>
6 
7 #include <unistd.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <errno.h>
12 #include <signal.h>
13 #include <fcntl.h>
14 
15 #ifdef HAVE_LIBMTCP
16 #include "mtcp_api.h"
17 #include "mtcp_epoll.h"
18 /*----------------------------------------------------------------------------*/
19 static void
fdevent_libmtcp_epoll_free(fdevents * ev)20 fdevent_libmtcp_epoll_free(fdevents *ev)
21 {
22 	mtcp_close(ev->srv->mctx, ev->epoll_fd);
23 	free(ev->_epoll_events);
24 }
25 /*----------------------------------------------------------------------------*/
26 static int
fdevent_libmtcp_epoll_event_del(fdevents * ev,int fde_ndx,int fd)27 fdevent_libmtcp_epoll_event_del(fdevents *ev, int fde_ndx, int fd)
28 {
29   /*struct mtcp_epoll_event ep;*/
30 
31 	if (fde_ndx < 0) return -1;
32 #if 0
33 	memset(&ep, 0, sizeof(ep));
34 
35 	ep.data.sock = fd;
36 	ep.data.ptr = NULL;
37 #endif
38 	if (0 != mtcp_epoll_ctl(ev->srv->mctx, ev->epoll_fd, MOS_EPOLL_CTL_DEL, fd, NULL/*&ep*/)) {
39 		log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
40 				"epoll_ctl failed: ", strerror(errno), ", dying");
41 
42 		SEGFAULT();
43 
44 		return 0;
45 	}
46 
47 
48 	return -1;
49 }
50 /*----------------------------------------------------------------------------*/
51 static int
fdevent_libmtcp_epoll_event_set(fdevents * ev,int fde_ndx,int fd,int events)52 fdevent_libmtcp_epoll_event_set(fdevents *ev, int fde_ndx, int fd, int events)
53 {
54 	struct mtcp_epoll_event ep;
55 	int add = 0;
56 
57 	if (fde_ndx == -1) add = 1;
58 	/*memset(&ep, 0, sizeof(struct mtcp_epoll_event));*/
59 	ep.events = 0;
60 
61 	if (events & FDEVENT_IN)  ep.events |= MOS_EPOLLIN;
62 	if (events & FDEVENT_OUT) ep.events |= MOS_EPOLLOUT;
63 
64 	/**
65 	 *
66 	 * with EPOLLET we don't get a FDEVENT_HUP
67 	 * if the close is delay after everything has
68 	 * sent.
69 	 *
70 	 */
71 
72 	ep.events |= MOS_EPOLLERR | MOS_EPOLLHUP /* | EPOLLET */;
73 
74 	/*ep.data.ptr = NULL;*/
75 	ep.data.sock = fd;
76 
77 	if (0 != mtcp_epoll_ctl(ev->srv->mctx, ev->epoll_fd, add ? MOS_EPOLL_CTL_ADD : MOS_EPOLL_CTL_MOD, fd, &ep)) {
78 		log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
79 			"epoll_ctl failed: ", strerror(errno), ", dying");
80 
81 		SEGFAULT();
82 
83 		return 0;
84 	}
85 
86 	return fd;
87 }
88 /*----------------------------------------------------------------------------*/
89 static int
fdevent_libmtcp_epoll_poll(fdevents * ev,int timeout_ms)90 fdevent_libmtcp_epoll_poll(fdevents *ev, int timeout_ms)
91 {
92 	return mtcp_epoll_wait(ev->srv->mctx, ev->epoll_fd, ev->_epoll_events,
93 			       ev->maxfds, timeout_ms);
94 }
95 /*----------------------------------------------------------------------------*/
96 static int
fdevent_libmtcp_epoll_event_get_revent(fdevents * ev,size_t ndx)97 fdevent_libmtcp_epoll_event_get_revent(fdevents *ev, size_t ndx)
98 {
99 	int events = 0, e;
100 
101 	e = ev->_epoll_events[ndx].events;
102 	if (e & MOS_EPOLLIN) events |= FDEVENT_IN;
103 	if (e & MOS_EPOLLOUT) events |= FDEVENT_OUT;
104 	if (e & MOS_EPOLLERR) events |= FDEVENT_ERR;
105 	if (e & MOS_EPOLLHUP) events |= FDEVENT_HUP;
106 	if (e & MOS_EPOLLPRI) events |= FDEVENT_PRI;
107 
108 	return events;
109 }
110 /*----------------------------------------------------------------------------*/
111 static int
fdevent_libmtcp_epoll_event_get_fd(fdevents * ev,size_t ndx)112 fdevent_libmtcp_epoll_event_get_fd(fdevents *ev, size_t ndx)
113 {
114 	return ev->_epoll_events[ndx].data.sock;
115 }
116 /*----------------------------------------------------------------------------*/
117 static int
fdevent_libmtcp_epoll_event_next_fdndx(fdevents * ev,int ndx)118 fdevent_libmtcp_epoll_event_next_fdndx(fdevents *ev, int ndx)
119 {
120 	size_t i;
121 
122 	UNUSED(ev);
123 
124 	i = (ndx < 0) ? 0 : ndx + 1;
125 
126 	return i;
127 }
128 /*----------------------------------------------------------------------------*/
129 int
fdevent_libmtcp_epoll_init(fdevents * ev)130 fdevent_libmtcp_epoll_init(fdevents *ev)
131 {
132 	ev->type = FDEVENT_HANDLER_LIBMTCP;
133 #define SET(x)					\
134 	ev->x = fdevent_libmtcp_epoll_##x;
135 
136 	SET(free);
137 	SET(poll);
138 
139 	SET(event_del);
140 	SET(event_set);
141 
142 	SET(event_next_fdndx);
143 	SET(event_get_fd);
144 	SET(event_get_revent);
145 
146 	/* setting the max events logic based on `epserver' logic */
147 	if (-1 == (ev->epoll_fd = mtcp_epoll_create(ev->srv->mctx, ev->srv->max_conns * 3))) {
148 		log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
149 			"epoll_create failed (", strerror(errno), ")");
150 
151 		return -1;
152 	}
153 
154 	ev->_epoll_events = calloc(ev->srv->max_conns * 3,
155 				  sizeof(struct mtcp_epoll_event));
156 	if (NULL == ev->_epoll_events) {
157 		log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
158 				"_epoll_events calloc failed!", strerror(errno), ")");
159 		return -1;
160 	}
161 
162 	return 0;
163 }
164 /*----------------------------------------------------------------------------*/
165 #else
166 int
fdevent_libmtcp_epoll_init(fdevents * ev)167 fdevent_libmtcp_epoll_init(fdevents *ev)
168 {
169 	UNUSED(ev);
170 
171 	log_error_write(ev->srv, __FILE__, __LINE__, "S",
172 			"libmtcp-epoll not supported, try to set server.event-handler = \"poll\" or \"select\"");
173 
174 	return -1;
175 }
176 /*----------------------------------------------------------------------------*/
177 #endif /* !HAVE_LIBMTCP */
178