diff options
author | Christian Grothoff <christian@grothoff.org> | 2018-03-14 05:31:09 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2018-03-14 05:31:09 +0100 |
commit | 8abd74f3dc9a0482111a2fc8f99b59434f80acd9 (patch) | |
tree | 4a4848ddcb42594287060f84c6dcd9319857394e | |
parent | 7d7ccbcdbdc45e72b30cb180eaf892dc782c408a (diff) | |
download | libmicrohttpd-8abd74f3dc9a0482111a2fc8f99b59434f80acd9.tar.gz libmicrohttpd-8abd74f3dc9a0482111a2fc8f99b59434f80acd9.zip |
add suspend_resume_epoll example (from mailinglist)
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | po/Makefile.in.in | 72 | ||||
-rw-r--r-- | src/examples/Makefile.am | 12 | ||||
-rw-r--r-- | src/examples/suspend_resume_epoll.c | 202 |
6 files changed, 239 insertions, 51 deletions
@@ -46,3 +46,4 @@ po/POTFILES | |||
46 | po/configargs.stamp | 46 | po/configargs.stamp |
47 | **~ | 47 | **~ |
48 | doc/libmicrohttpd.log | 48 | doc/libmicrohttpd.log |
49 | src/examples/suspend_resume_epoll | ||
@@ -57,6 +57,7 @@ Denis Dowling <denis.dowling@hsd.com.au> | |||
57 | Louis Benoit <louisbenoit@videotron.ca> | 57 | Louis Benoit <louisbenoit@videotron.ca> |
58 | Flavio Coelin <flavio.ceolin@intel.com> | 58 | Flavio Coelin <flavio.ceolin@intel.com> |
59 | Silvio Clecio <silvioprog@gmail.com> | 59 | Silvio Clecio <silvioprog@gmail.com> |
60 | Robert D Kosisko <rkocisko@gmail.com> | ||
60 | 61 | ||
61 | Documentation contributions also came from: | 62 | Documentation contributions also came from: |
62 | Marco Maggi <marco.maggi-ipsu@poste.it> | 63 | Marco Maggi <marco.maggi-ipsu@poste.it> |
diff --git a/configure.ac b/configure.ac index 71557497..e503a5da 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -735,6 +735,8 @@ if test "$enable_epoll" != "no"; then | |||
735 | fi | 735 | fi |
736 | fi | 736 | fi |
737 | 737 | ||
738 | AM_CONDITIONAL([MHD_HAVE_EPOLL], [[test "x$enable_epoll" = xyes]]) | ||
739 | |||
738 | if test "x$enable_epoll" = "xyes"; then | 740 | if test "x$enable_epoll" = "xyes"; then |
739 | AC_CACHE_CHECK([for epoll_create1()], [mhd_cv_have_epoll_create1], [ | 741 | AC_CACHE_CHECK([for epoll_create1()], [mhd_cv_have_epoll_create1], [ |
740 | AC_LINK_IFELSE([ | 742 | AC_LINK_IFELSE([ |
diff --git a/po/Makefile.in.in b/po/Makefile.in.in index 38c293d2..fce63a6e 100644 --- a/po/Makefile.in.in +++ b/po/Makefile.in.in | |||
@@ -1,19 +1,20 @@ | |||
1 | # Makefile for PO directory in any package using GNU gettext. | 1 | # Makefile for PO directory in any package using GNU gettext. |
2 | # Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper <drepper@gnu.ai.mit.edu> | 2 | # Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper <drepper@gnu.ai.mit.edu> |
3 | # | 3 | # |
4 | # Copying and distribution of this file, with or without modification, | 4 | # This file can be copied and used freely without restrictions. It can |
5 | # are permitted in any medium without royalty provided the copyright | 5 | # be used in projects which are not available under the GNU General Public |
6 | # notice and this notice are preserved. This file is offered as-is, | 6 | # License but which still want to provide support for the GNU gettext |
7 | # without any warranty. | 7 | # functionality. |
8 | # Please note that the actual code of GNU gettext is covered by the GNU | ||
9 | # General Public License and is *not* in the public domain. | ||
8 | # | 10 | # |
9 | # Origin: gettext-0.19.8 | 11 | # Origin: gettext-0.18.2 |
10 | GETTEXT_MACRO_VERSION = 0.19 | 12 | GETTEXT_MACRO_VERSION = 0.18 |
11 | 13 | ||
12 | PACKAGE = @PACKAGE@ | 14 | PACKAGE = @PACKAGE@ |
13 | VERSION = @VERSION@ | 15 | VERSION = @VERSION@ |
14 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ | 16 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ |
15 | 17 | ||
16 | SED = @SED@ | ||
17 | SHELL = /bin/sh | 18 | SHELL = /bin/sh |
18 | @SET_MAKE@ | 19 | @SET_MAKE@ |
19 | 20 | ||
@@ -43,11 +44,6 @@ install_sh = $(SHELL) @install_sh@ | |||
43 | MKDIR_P = @MKDIR_P@ | 44 | MKDIR_P = @MKDIR_P@ |
44 | mkdir_p = @mkdir_p@ | 45 | mkdir_p = @mkdir_p@ |
45 | 46 | ||
46 | # When building gettext-tools, we prefer to use the built programs | ||
47 | # rather than installed programs. However, we can't do that when we | ||
48 | # are cross compiling. | ||
49 | CROSS_COMPILING = @CROSS_COMPILING@ | ||
50 | |||
51 | GMSGFMT_ = @GMSGFMT@ | 47 | GMSGFMT_ = @GMSGFMT@ |
52 | GMSGFMT_no = @GMSGFMT@ | 48 | GMSGFMT_no = @GMSGFMT@ |
53 | GMSGFMT_yes = @GMSGFMT_015@ | 49 | GMSGFMT_yes = @GMSGFMT_015@ |
@@ -80,16 +76,6 @@ POTFILES = \ | |||
80 | 76 | ||
81 | CATALOGS = @CATALOGS@ | 77 | CATALOGS = @CATALOGS@ |
82 | 78 | ||
83 | POFILESDEPS_ = $(srcdir)/$(DOMAIN).pot | ||
84 | POFILESDEPS_yes = $(POFILESDEPS_) | ||
85 | POFILESDEPS_no = | ||
86 | POFILESDEPS = $(POFILESDEPS_$(PO_DEPENDS_ON_POT)) | ||
87 | |||
88 | DISTFILESDEPS_ = update-po | ||
89 | DISTFILESDEPS_yes = $(DISTFILESDEPS_) | ||
90 | DISTFILESDEPS_no = | ||
91 | DISTFILESDEPS = $(DISTFILESDEPS_$(DIST_DEPENDS_ON_UPDATE_PO)) | ||
92 | |||
93 | # Makevars gets inserted here. (Don't remove this line!) | 79 | # Makevars gets inserted here. (Don't remove this line!) |
94 | 80 | ||
95 | .SUFFIXES: | 81 | .SUFFIXES: |
@@ -156,25 +142,15 @@ stamp-po: $(srcdir)/$(DOMAIN).pot | |||
156 | # heuristic whether some file in the top level directory mentions "GNU xyz". | 142 | # heuristic whether some file in the top level directory mentions "GNU xyz". |
157 | # If GNU 'find' is available, we avoid grepping through monster files. | 143 | # If GNU 'find' is available, we avoid grepping through monster files. |
158 | $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed | 144 | $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed |
159 | package_gnu="$(PACKAGE_GNU)"; \ | 145 | if { if (LC_ALL=C find --version) 2>/dev/null | grep GNU >/dev/null; then \ |
160 | test -n "$$package_gnu" || { \ | 146 | LC_ALL=C find -L $(top_srcdir) -maxdepth 1 -type f -size -10000000c -exec grep 'GNU @PACKAGE@' /dev/null '{}' ';' 2>/dev/null; \ |
161 | if { if (LC_ALL=C find --version) 2>/dev/null | grep GNU >/dev/null; then \ | 147 | else \ |
162 | LC_ALL=C find -L $(top_srcdir) -maxdepth 1 -type f \ | 148 | LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null; \ |
163 | -size -10000000c -exec grep 'GNU @PACKAGE@' \ | 149 | fi; \ |
164 | /dev/null '{}' ';' 2>/dev/null; \ | 150 | } | grep -v 'libtool:' >/dev/null; then \ |
165 | else \ | 151 | package_gnu='GNU '; \ |
166 | LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null; \ | ||
167 | fi; \ | ||
168 | } | grep -v 'libtool:' >/dev/null; then \ | ||
169 | package_gnu=yes; \ | ||
170 | else \ | ||
171 | package_gnu=no; \ | ||
172 | fi; \ | ||
173 | }; \ | ||
174 | if test "$$package_gnu" = "yes"; then \ | ||
175 | package_prefix='GNU '; \ | ||
176 | else \ | 152 | else \ |
177 | package_prefix=''; \ | 153 | package_gnu=''; \ |
178 | fi; \ | 154 | fi; \ |
179 | if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \ | 155 | if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \ |
180 | msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ | 156 | msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ |
@@ -194,17 +170,12 @@ $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed | |||
194 | --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ | 170 | --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ |
195 | --files-from=$(srcdir)/POTFILES.in \ | 171 | --files-from=$(srcdir)/POTFILES.in \ |
196 | --copyright-holder='$(COPYRIGHT_HOLDER)' \ | 172 | --copyright-holder='$(COPYRIGHT_HOLDER)' \ |
197 | --package-name="$${package_prefix}@PACKAGE@" \ | 173 | --package-name="$${package_gnu}@PACKAGE@" \ |
198 | --package-version='@VERSION@' \ | 174 | --package-version='@VERSION@' \ |
199 | --msgid-bugs-address="$$msgid_bugs_address" \ | 175 | --msgid-bugs-address="$$msgid_bugs_address" \ |
200 | ;; \ | 176 | ;; \ |
201 | esac | 177 | esac |
202 | test ! -f $(DOMAIN).po || { \ | 178 | test ! -f $(DOMAIN).po || { \ |
203 | if test -f $(srcdir)/$(DOMAIN).pot-header; then \ | ||
204 | sed -e '1,/^#$$/d' < $(DOMAIN).po > $(DOMAIN).1po && \ | ||
205 | cat $(srcdir)/$(DOMAIN).pot-header $(DOMAIN).1po > $(DOMAIN).po; \ | ||
206 | rm -f $(DOMAIN).1po; \ | ||
207 | fi; \ | ||
208 | if test -f $(srcdir)/$(DOMAIN).pot; then \ | 179 | if test -f $(srcdir)/$(DOMAIN).pot; then \ |
209 | sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ | 180 | sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ |
210 | sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ | 181 | sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ |
@@ -227,14 +198,13 @@ $(srcdir)/$(DOMAIN).pot: | |||
227 | 198 | ||
228 | # This target rebuilds a PO file if $(DOMAIN).pot has changed. | 199 | # This target rebuilds a PO file if $(DOMAIN).pot has changed. |
229 | # Note that a PO file is not touched if it doesn't need to be changed. | 200 | # Note that a PO file is not touched if it doesn't need to be changed. |
230 | $(POFILES): $(POFILESDEPS) | 201 | $(POFILES): $(srcdir)/$(DOMAIN).pot |
231 | @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ | 202 | @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ |
232 | if test -f "$(srcdir)/$${lang}.po"; then \ | 203 | if test -f "$(srcdir)/$${lang}.po"; then \ |
233 | test -f $(srcdir)/$(DOMAIN).pot || $(MAKE) $(srcdir)/$(DOMAIN).pot; \ | ||
234 | test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ | 204 | test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ |
235 | echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \ | 205 | echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \ |
236 | cd $(srcdir) \ | 206 | cd $(srcdir) \ |
237 | && { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ | 207 | && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ |
238 | '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ | 208 | '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ |
239 | $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \ | 209 | $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \ |
240 | *) \ | 210 | *) \ |
@@ -391,7 +361,7 @@ maintainer-clean: distclean | |||
391 | 361 | ||
392 | distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) | 362 | distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) |
393 | dist distdir: | 363 | dist distdir: |
394 | test -z "$(DISTFILESDEPS)" || $(MAKE) $(DISTFILESDEPS) | 364 | $(MAKE) update-po |
395 | @$(MAKE) dist2 | 365 | @$(MAKE) dist2 |
396 | # This is a separate target because 'update-po' must be executed before. | 366 | # This is a separate target because 'update-po' must be executed before. |
397 | dist2: stamp-po $(DISTFILES) | 367 | dist2: stamp-po $(DISTFILES) |
@@ -435,7 +405,7 @@ update-po: Makefile | |||
435 | 405 | ||
436 | .nop.po-update: | 406 | .nop.po-update: |
437 | @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ | 407 | @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ |
438 | if test "$(PACKAGE)" = "gettext-tools" && test "$(CROSS_COMPILING)" != "yes"; then PATH=`pwd`/../src:$$PATH; fi; \ | 408 | if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ |
439 | tmpdir=`pwd`; \ | 409 | tmpdir=`pwd`; \ |
440 | echo "$$lang:"; \ | 410 | echo "$$lang:"; \ |
441 | test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ | 411 | test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ |
diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am index 58f4b4aa..545a236a 100644 --- a/src/examples/Makefile.am +++ b/src/examples/Makefile.am | |||
@@ -29,6 +29,11 @@ noinst_PROGRAMS = \ | |||
29 | fileserver_example_external_select \ | 29 | fileserver_example_external_select \ |
30 | refuse_post_example | 30 | refuse_post_example |
31 | 31 | ||
32 | if MHD_HAVE_EPOLL | ||
33 | noinst_PROGRAMS += \ | ||
34 | suspend_resume_epoll | ||
35 | endif | ||
36 | |||
32 | EXTRA_DIST = msgs_i18n.c | 37 | EXTRA_DIST = msgs_i18n.c |
33 | noinst_EXTRA_DIST = msgs_i18n.c | 38 | noinst_EXTRA_DIST = msgs_i18n.c |
34 | 39 | ||
@@ -123,6 +128,13 @@ benchmark_CPPFLAGS = \ | |||
123 | benchmark_LDADD = \ | 128 | benchmark_LDADD = \ |
124 | $(top_builddir)/src/microhttpd/libmicrohttpd.la | 129 | $(top_builddir)/src/microhttpd/libmicrohttpd.la |
125 | 130 | ||
131 | suspend_resume_epoll_SOURCES = \ | ||
132 | suspend_resume_epoll.c | ||
133 | suspend_resume_epoll_CPPFLAGS = \ | ||
134 | $(AM_CPPFLAGS) $(CPU_COUNT_DEF) | ||
135 | suspend_resume_epoll_LDADD = \ | ||
136 | $(top_builddir)/src/microhttpd/libmicrohttpd.la | ||
137 | |||
126 | benchmark_https_SOURCES = \ | 138 | benchmark_https_SOURCES = \ |
127 | benchmark_https.c | 139 | benchmark_https.c |
128 | benchmark_https_CPPFLAGS = \ | 140 | benchmark_https_CPPFLAGS = \ |
diff --git a/src/examples/suspend_resume_epoll.c b/src/examples/suspend_resume_epoll.c new file mode 100644 index 00000000..adff673c --- /dev/null +++ b/src/examples/suspend_resume_epoll.c | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | This file is part of libmicrohttpd | ||
3 | Copyright (C) 2018 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2.1 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | /** | ||
20 | * @file suspend_resume_epoll.c | ||
21 | * @brief example for how to use libmicrohttpd with epoll() and | ||
22 | * resume a suspended connection | ||
23 | * @author Robert D Kocisko | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include <microhttpd.h> | ||
28 | #include <sys/epoll.h> | ||
29 | #include <sys/timerfd.h> | ||
30 | #include <limits.h> | ||
31 | |||
32 | #define TIMEOUT_INFINITE -1 | ||
33 | |||
34 | struct Request { | ||
35 | struct MHD_Connection *connection; | ||
36 | int timerfd; | ||
37 | }; | ||
38 | |||
39 | |||
40 | static int epfd; | ||
41 | |||
42 | static struct epoll_event evt; | ||
43 | |||
44 | |||
45 | static int | ||
46 | ahc_echo (void *cls, | ||
47 | struct MHD_Connection *connection, | ||
48 | const char *url, | ||
49 | const char *method, | ||
50 | const char *version, | ||
51 | const char *upload_data, size_t *upload_data_size, void **ptr) | ||
52 | { | ||
53 | struct MHD_Response *response; | ||
54 | int ret; | ||
55 | struct Request* req; | ||
56 | struct itimerspec ts; | ||
57 | (void)url; /* Unused. Silence compiler warning. */ | ||
58 | (void)version; /* Unused. Silence compiler warning. */ | ||
59 | (void)upload_data; /* Unused. Silence compiler warning. */ | ||
60 | (void)upload_data_size; /* Unused. Silence compiler warning. */ | ||
61 | |||
62 | req = *ptr; | ||
63 | if (!req) | ||
64 | { | ||
65 | |||
66 | req = malloc(sizeof(struct Request)); | ||
67 | req->connection = connection; | ||
68 | req->timerfd = 0; | ||
69 | *ptr = req; | ||
70 | return MHD_YES; | ||
71 | } | ||
72 | |||
73 | if (req->timerfd) | ||
74 | { | ||
75 | // send response (echo request url) | ||
76 | response = MHD_create_response_from_buffer (strlen (url), | ||
77 | (void *) url, | ||
78 | MHD_RESPMEM_MUST_COPY); | ||
79 | ret = MHD_queue_response (connection, MHD_HTTP_OK, response); | ||
80 | MHD_destroy_response (response); | ||
81 | return ret; | ||
82 | } | ||
83 | else | ||
84 | { | ||
85 | // create timer and suspend connection | ||
86 | req->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); | ||
87 | if (-1 == req->timerfd) | ||
88 | { | ||
89 | printf("timerfd_create: %s", strerror(errno)); | ||
90 | return MHD_NO; | ||
91 | } | ||
92 | evt.events = EPOLLIN; | ||
93 | evt.data.ptr = req; | ||
94 | if (-1 == epoll_ctl(epfd, EPOLL_CTL_ADD, req->timerfd, &evt)) | ||
95 | { | ||
96 | printf("epoll_ctl: %s", strerror(errno)); | ||
97 | return MHD_NO; | ||
98 | } | ||
99 | ts.it_value.tv_sec = 1; | ||
100 | ts.it_value.tv_nsec = 0; | ||
101 | ts.it_interval.tv_sec = 0; | ||
102 | ts.it_interval.tv_nsec = 0; | ||
103 | if (-1 == timerfd_settime(req->timerfd, 0, &ts, NULL)) | ||
104 | { | ||
105 | printf("timerfd_settime: %s", strerror(errno)); | ||
106 | return MHD_NO; | ||
107 | } | ||
108 | MHD_suspend_connection(connection); | ||
109 | return MHD_YES; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | |||
114 | static int | ||
115 | connection_done(struct MHD_Connection *connection, | ||
116 | void **con_cls, | ||
117 | enum MHD_RequestTerminationCode toe) | ||
118 | { | ||
119 | free(*con_cls); | ||
120 | } | ||
121 | |||
122 | |||
123 | int | ||
124 | main (int argc, | ||
125 | char *const *argv) | ||
126 | { | ||
127 | struct MHD_Daemon *d; | ||
128 | const union MHD_DaemonInfo * info; | ||
129 | int current_event_count; | ||
130 | struct epoll_event events_list[1]; | ||
131 | struct Request *req; | ||
132 | uint64_t timer_expirations; | ||
133 | |||
134 | if (argc != 2) | ||
135 | { | ||
136 | printf ("%s PORT\n", argv[0]); | ||
137 | return 1; | ||
138 | } | ||
139 | d = MHD_start_daemon (MHD_USE_EPOLL | MHD_ALLOW_SUSPEND_RESUME, | ||
140 | atoi (argv[1]), | ||
141 | NULL, NULL, &ahc_echo, NULL, | ||
142 | MHD_OPTION_NOTIFY_COMPLETED, &connection_done, NULL, | ||
143 | MHD_OPTION_END); | ||
144 | if (d == NULL) | ||
145 | return 1; | ||
146 | |||
147 | info = MHD_get_daemon_info(d, MHD_DAEMON_INFO_EPOLL_FD); | ||
148 | if (info == NULL) | ||
149 | return 1; | ||
150 | |||
151 | epfd = epoll_create1(EPOLL_CLOEXEC); | ||
152 | if (-1 == epfd) | ||
153 | return 1; | ||
154 | |||
155 | evt.events = EPOLLIN; | ||
156 | evt.data.ptr = NULL; | ||
157 | if (-1 == epoll_ctl(epfd, EPOLL_CTL_ADD, info->epoll_fd, &evt)) | ||
158 | return 1; | ||
159 | |||
160 | while (1) | ||
161 | { | ||
162 | int timeout; | ||
163 | MHD_UNSIGNED_LONG_LONG to; | ||
164 | |||
165 | if (MHD_YES != | ||
166 | MHD_get_timeout (d, | ||
167 | &to)) | ||
168 | timeout = TIMEOUT_INFINITE; | ||
169 | else | ||
170 | timeout = (to < INT_MAX - 1) ? (int) to : (INT_MAX - 1); | ||
171 | current_event_count = epoll_wait(epfd, events_list, 1, timeout); | ||
172 | |||
173 | if (1 == current_event_count) | ||
174 | { | ||
175 | if (events_list[0].data.ptr) | ||
176 | { | ||
177 | // A timer has timed out | ||
178 | req = events_list[0].data.ptr; | ||
179 | // read from the fd so the system knows we heard the notice | ||
180 | if (-1 == read(req->timerfd, &timer_expirations, sizeof(timer_expirations))) | ||
181 | { | ||
182 | return 1; | ||
183 | } | ||
184 | // Now resume the connection | ||
185 | MHD_resume_connection(req->connection); | ||
186 | } | ||
187 | } | ||
188 | else if (0 == current_event_count) | ||
189 | { | ||
190 | // no events: continue | ||
191 | } | ||
192 | else | ||
193 | { | ||
194 | // error | ||
195 | return 1; | ||
196 | } | ||
197 | if (! MHD_run(d)) | ||
198 | return 1; | ||
199 | } | ||
200 | |||
201 | return 0; | ||
202 | } | ||