diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2014-02-18 18:38:41 +0000 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2014-02-18 18:38:41 +0000 |
commit | 1acde3cb8eab299a0994f243616de4e8ee028c0a (patch) | |
tree | c5d9ee16b8a89d3e0e77abd5427c16ff38af6bb3 | |
parent | 558d8ae997bba5128830dddf6d35bb97f3fedf6f (diff) | |
download | libmicrohttpd-1acde3cb8eab299a0994f243616de4e8ee028c0a.tar.gz libmicrohttpd-1acde3cb8eab299a0994f243616de4e8ee028c0a.zip |
add ability to use socketspair instead of pipe, implement W32 pipe/socketspair emulation, implement MHD_SYS_select_
configure.ac: add "--disable-pipes" option
-rw-r--r-- | configure.ac | 33 | ||||
-rw-r--r-- | src/include/microhttpd.h | 3 | ||||
-rw-r--r-- | src/include/platform.h | 12 | ||||
-rw-r--r-- | src/microhttpd/daemon.c | 81 | ||||
-rw-r--r-- | src/microhttpd/internal.h | 5 | ||||
-rw-r--r-- | src/platform/platform_interface.h | 67 | ||||
-rw-r--r-- | src/platform/w32functions.c | 77 | ||||
-rw-r--r-- | src/platform/w32functions.h | 8 |
8 files changed, 237 insertions, 49 deletions
diff --git a/configure.ac b/configure.ac index 6b5f5e42..366a7864 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -167,6 +167,7 @@ netbsd*) | |||
167 | AM_CONDITIONAL(HAVE_GNU_LD, false) | 167 | AM_CONDITIONAL(HAVE_GNU_LD, false) |
168 | AM_CONDITIONAL(HAVE_W32, false) | 168 | AM_CONDITIONAL(HAVE_W32, false) |
169 | LDFLAGS="$LDFLAGS" | 169 | LDFLAGS="$LDFLAGS" |
170 | os_is_windows=yes | ||
170 | ;; | 171 | ;; |
171 | *mingw*) | 172 | *mingw*) |
172 | AC_DEFINE_UNQUOTED(MINGW,1,[This is a MinGW system]) | 173 | AC_DEFINE_UNQUOTED(MINGW,1,[This is a MinGW system]) |
@@ -180,6 +181,7 @@ netbsd*) | |||
180 | AC_SUBST(PLIBC_LIBS) | 181 | AC_SUBST(PLIBC_LIBS) |
181 | AC_SUBST(PLIBC_LDFLAGS) | 182 | AC_SUBST(PLIBC_LDFLAGS) |
182 | AC_SUBST(PLIBC_CPPFLAGS) | 183 | AC_SUBST(PLIBC_CPPFLAGS) |
184 | os_is_windows=yes | ||
183 | ;; | 185 | ;; |
184 | *openedition*) | 186 | *openedition*) |
185 | AC_DEFINE_UNQUOTED(OS390,1,[This is a OS/390 system]) | 187 | AC_DEFINE_UNQUOTED(OS390,1,[This is a OS/390 system]) |
@@ -229,6 +231,37 @@ AC_CHECK_HEADERS([sys/types.h sys/time.h sys/msg.h netdb.h netinet/in.h netinet/ | |||
229 | 231 | ||
230 | AC_CHECK_HEADERS([search.h], AM_CONDITIONAL(HAVE_TSEARCH, true), AM_CONDITIONAL(HAVE_TSEARCH, false)) | 232 | AC_CHECK_HEADERS([search.h], AM_CONDITIONAL(HAVE_TSEARCH, true), AM_CONDITIONAL(HAVE_TSEARCH, false)) |
231 | 233 | ||
234 | # Check for pipe/socketpair signaling | ||
235 | AC_MSG_CHECKING([[whether to disable pipes signaling]]) | ||
236 | AC_ARG_ENABLE([[pipes]], | ||
237 | [AS_HELP_STRING([[--disable-pipes]], [[disable internal singalling by pipes and use socket pair instead]])], | ||
238 | [], [[enable_pipes=yes]]) | ||
239 | AS_IF([[test "x$os_is_windows" = "xyes"]], [disable_pipes=yes | ||
240 | AC_MSG_RESULT([[yes, forced on W32]])], | ||
241 | [[test "x$enable_pipes" != "xno"]], [disable_pipes=no | ||
242 | AC_MSG_RESULT([[$disable_pipes]])], | ||
243 | [AC_LINK_IFELSE([AC_LANG_PROGRAM([[ | ||
244 | #ifdef HAVE_SYS_TYPES_H | ||
245 | #include <sys/types.h> | ||
246 | #endif | ||
247 | #ifdef HAVE_SYS_SOCKET_H | ||
248 | #include <sys/socket.h> | ||
249 | #endif | ||
250 | ]],[[ | ||
251 | int sv[2]; | ||
252 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0) return 1 | ||
253 | |||
254 | ]])], | ||
255 | [disable_pipes=yes | ||
256 | AC_MSG_RESULT([[yes, socketpair in available]])], | ||
257 | [disable_pipes=no | ||
258 | AC_MSG_RESULT([[no, socketpair in not available]])] | ||
259 | ) | ||
260 | ]) | ||
261 | if test "x$disable_pipes" = "xyes"; then | ||
262 | AC_DEFINE([[MHD_DONT_USE_PIPES]], [[1]], [Define to use pair of sockets instead of pipes for signaling]) | ||
263 | fi | ||
264 | |||
232 | # Check for plibc.h from system, if not found, use our own | 265 | # Check for plibc.h from system, if not found, use our own |
233 | AC_CHECK_HEADERS([plibc.h],our_private_plibc_h=0,our_private_plibc_h=1) | 266 | AC_CHECK_HEADERS([plibc.h],our_private_plibc_h=0,our_private_plibc_h=1) |
234 | AM_CONDITIONAL(USE_PRIVATE_PLIBC_H, test x$our_private_plibc_h = x1) | 267 | AM_CONDITIONAL(USE_PRIVATE_PLIBC_H, test x$our_private_plibc_h = x1) |
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h index 14fe3b31..2d38cf1c 100644 --- a/src/include/microhttpd.h +++ b/src/include/microhttpd.h | |||
@@ -520,7 +520,8 @@ enum MHD_FLAG | |||
520 | * use of this option is automatic (as in, you do not even have to | 520 | * use of this option is automatic (as in, you do not even have to |
521 | * specify it), if #MHD_USE_NO_LISTEN_SOCKET is specified. In | 521 | * specify it), if #MHD_USE_NO_LISTEN_SOCKET is specified. In |
522 | * "external" `select()` mode, this option is always simply ignored. | 522 | * "external" `select()` mode, this option is always simply ignored. |
523 | * On W32 a pair of sockets is used instead of a pipe. | 523 | * MHD can be build for use a pair of sockets instead of a pipe. |
524 | * Pair of sockets is forced on W32. | ||
524 | * | 525 | * |
525 | * You must also use this option if you use internal select mode | 526 | * You must also use this option if you use internal select mode |
526 | * or a thread pool in conjunction with #MHD_add_connection. | 527 | * or a thread pool in conjunction with #MHD_add_connection. |
diff --git a/src/include/platform.h b/src/include/platform.h index 01361f53..55b32159 100644 --- a/src/include/platform.h +++ b/src/include/platform.h | |||
@@ -135,4 +135,16 @@ typedef SOCKET MHD_socket; | |||
135 | #define MHD_SOCKET_DEFINED 1 | 135 | #define MHD_SOCKET_DEFINED 1 |
136 | #endif /* MHD_SOCKET_DEFINED */ | 136 | #endif /* MHD_SOCKET_DEFINED */ |
137 | 137 | ||
138 | /* Force don't use pipes on W32 */ | ||
139 | #if defined(_WIN32) && !defined(MHD_DONT_USE_PIPES) | ||
140 | #define MHD_DONT_USE_PIPES 1 | ||
141 | #endif /* defined(_WIN32) && !defined(MHD_DONT_USE_PIPES) */ | ||
142 | |||
143 | /* MHD_pipe is type for pipe FDs*/ | ||
144 | #ifndef MHD_DONT_USE_PIPES | ||
145 | typedef int MHD_pipe; | ||
146 | #else /* ! MHD_DONT_USE_PIPES */ | ||
147 | typedef MHD_socket MHD_pipe; | ||
148 | #endif /* ! MHD_DONT_USE_PIPES */ | ||
149 | |||
138 | #endif | 150 | #endif |
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index 4ab43f9d..2bbb7b2a 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c | |||
@@ -728,7 +728,7 @@ MHD_handle_connection (void *data) | |||
728 | /* how did we get here!? */ | 728 | /* how did we get here!? */ |
729 | goto exit; | 729 | goto exit; |
730 | } | 730 | } |
731 | num_ready = SELECT (max + 1, &rs, &ws, NULL, tvp); | 731 | num_ready = MHD_SYS_select_ (max + 1, &rs, &ws, NULL, tvp); |
732 | if (num_ready < 0) | 732 | if (num_ready < 0) |
733 | { | 733 | { |
734 | if (EINTR == MHD_socket_errno_) | 734 | if (EINTR == MHD_socket_errno_) |
@@ -1306,8 +1306,8 @@ internal_add_connection (struct MHD_Daemon *daemon, | |||
1306 | } | 1306 | } |
1307 | else | 1307 | else |
1308 | if ( (MHD_YES == external_add) && | 1308 | if ( (MHD_YES == external_add) && |
1309 | (-1 != daemon->wpipe[1]) && | 1309 | (MHD_INVALID_PIPE_ != daemon->wpipe[1]) && |
1310 | (1 != WRITE (daemon->wpipe[1], "n", 1)) ) | 1310 | (1 != MHD_pipe_write_ (daemon->wpipe[1], "n", 1)) ) |
1311 | { | 1311 | { |
1312 | #if HAVE_MESSAGES | 1312 | #if HAVE_MESSAGES |
1313 | MHD_DLOG (daemon, | 1313 | MHD_DLOG (daemon, |
@@ -1477,8 +1477,8 @@ MHD_resume_connection (struct MHD_Connection *connection) | |||
1477 | MHD_PANIC ("Failed to acquire cleanup mutex\n"); | 1477 | MHD_PANIC ("Failed to acquire cleanup mutex\n"); |
1478 | connection->resuming = MHD_YES; | 1478 | connection->resuming = MHD_YES; |
1479 | daemon->resuming = MHD_YES; | 1479 | daemon->resuming = MHD_YES; |
1480 | if ( (-1 != daemon->wpipe[1]) && | 1480 | if ( (MHD_INVALID_PIPE_ != daemon->wpipe[1]) && |
1481 | (1 != WRITE (daemon->wpipe[1], "r", 1)) ) | 1481 | (1 != MHD_pipe_write_ (daemon->wpipe[1], "r", 1)) ) |
1482 | { | 1482 | { |
1483 | #if HAVE_MESSAGES | 1483 | #if HAVE_MESSAGES |
1484 | MHD_DLOG (daemon, | 1484 | MHD_DLOG (daemon, |
@@ -1963,9 +1963,9 @@ MHD_run_from_select (struct MHD_Daemon *daemon, | |||
1963 | (FD_ISSET (ds, read_fd_set)) ) | 1963 | (FD_ISSET (ds, read_fd_set)) ) |
1964 | (void) MHD_accept_connection (daemon); | 1964 | (void) MHD_accept_connection (daemon); |
1965 | /* drain signaling pipe to avoid spinning select */ | 1965 | /* drain signaling pipe to avoid spinning select */ |
1966 | if ( (-1 != daemon->wpipe[0]) && | 1966 | if ( (MHD_INVALID_PIPE_ != daemon->wpipe[0]) && |
1967 | (FD_ISSET (daemon->wpipe[0], read_fd_set)) ) | 1967 | (FD_ISSET (daemon->wpipe[0], read_fd_set)) ) |
1968 | (void) read (daemon->wpipe[0], &tmp, sizeof (tmp)); | 1968 | (void) MHD_pipe_read_ (daemon->wpipe[0], &tmp, sizeof (tmp)); |
1969 | 1969 | ||
1970 | if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) | 1970 | if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) |
1971 | { | 1971 | { |
@@ -2064,7 +2064,7 @@ MHD_select (struct MHD_Daemon *daemon, | |||
2064 | FD_SET (daemon->socket_fd, &rs); | 2064 | FD_SET (daemon->socket_fd, &rs); |
2065 | } | 2065 | } |
2066 | } | 2066 | } |
2067 | if (-1 != daemon->wpipe[0]) | 2067 | if (MHD_INVALID_PIPE_ != daemon->wpipe[0]) |
2068 | { | 2068 | { |
2069 | FD_SET (daemon->wpipe[0], &rs); | 2069 | FD_SET (daemon->wpipe[0], &rs); |
2070 | /* update max file descriptor */ | 2070 | /* update max file descriptor */ |
@@ -2089,7 +2089,7 @@ MHD_select (struct MHD_Daemon *daemon, | |||
2089 | } | 2089 | } |
2090 | if (MHD_INVALID_SOCKET == max) | 2090 | if (MHD_INVALID_SOCKET == max) |
2091 | return MHD_YES; | 2091 | return MHD_YES; |
2092 | num_ready = SELECT (max + 1, &rs, &ws, &es, tv); | 2092 | num_ready = MHD_SYS_select_ (max + 1, &rs, &ws, &es, tv); |
2093 | if (MHD_YES == daemon->shutdown) | 2093 | if (MHD_YES == daemon->shutdown) |
2094 | return MHD_NO; | 2094 | return MHD_NO; |
2095 | if (num_ready < 0) | 2095 | if (num_ready < 0) |
@@ -2150,7 +2150,7 @@ MHD_poll_all (struct MHD_Daemon *daemon, | |||
2150 | poll_listen = (int) poll_server; | 2150 | poll_listen = (int) poll_server; |
2151 | poll_server++; | 2151 | poll_server++; |
2152 | } | 2152 | } |
2153 | if (-1 != daemon->wpipe[0]) | 2153 | if (MHD_INVALID_PIPE_ != daemon->wpipe[0]) |
2154 | { | 2154 | { |
2155 | p[poll_server].fd = daemon->wpipe[0]; | 2155 | p[poll_server].fd = daemon->wpipe[0]; |
2156 | p[poll_server].events = POLLIN; | 2156 | p[poll_server].events = POLLIN; |
@@ -2284,7 +2284,7 @@ MHD_poll_listen_socket (struct MHD_Daemon *daemon, | |||
2284 | poll_listen = poll_count; | 2284 | poll_listen = poll_count; |
2285 | poll_count++; | 2285 | poll_count++; |
2286 | } | 2286 | } |
2287 | if (-1 != daemon->wpipe[0]) | 2287 | if (MHD_INVALID_PIPE_ != daemon->wpipe[0]) |
2288 | { | 2288 | { |
2289 | p[poll_count].fd = daemon->wpipe[0]; | 2289 | p[poll_count].fd = daemon->wpipe[0]; |
2290 | p[poll_count].events = POLLIN; | 2290 | p[poll_count].events = POLLIN; |
@@ -2456,10 +2456,10 @@ MHD_epoll (struct MHD_Daemon *daemon, | |||
2456 | { | 2456 | { |
2457 | if (NULL == events[i].data.ptr) | 2457 | if (NULL == events[i].data.ptr) |
2458 | continue; /* shutdown signal! */ | 2458 | continue; /* shutdown signal! */ |
2459 | if ( (-1 != daemon->wpipe[0]) && | 2459 | if ( (MHD_INVALID_PIPE_ != daemon->wpipe[0]) && |
2460 | (daemon->wpipe[0] == events[i].data.fd) ) | 2460 | (daemon->wpipe[0] == events[i].data.fd) ) |
2461 | { | 2461 | { |
2462 | (void) read (daemon->wpipe[0], &tmp, sizeof (tmp)); | 2462 | (void) MHD_pipe_read_ (daemon->wpipe[0], &tmp, sizeof (tmp)); |
2463 | continue; | 2463 | continue; |
2464 | } | 2464 | } |
2465 | if (daemon != events[i].data.ptr) | 2465 | if (daemon != events[i].data.ptr) |
@@ -2692,7 +2692,7 @@ MHD_quiesce_daemon (struct MHD_Daemon *daemon) | |||
2692 | ret = daemon->socket_fd; | 2692 | ret = daemon->socket_fd; |
2693 | if (MHD_INVALID_SOCKET == ret) | 2693 | if (MHD_INVALID_SOCKET == ret) |
2694 | return MHD_INVALID_SOCKET; | 2694 | return MHD_INVALID_SOCKET; |
2695 | if ( (-1 == daemon->wpipe[1]) && | 2695 | if ( (MHD_INVALID_PIPE_ == daemon->wpipe[1]) && |
2696 | (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) ) | 2696 | (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) ) |
2697 | { | 2697 | { |
2698 | #if HAVE_MESSAGES | 2698 | #if HAVE_MESSAGES |
@@ -3140,7 +3140,7 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon) | |||
3140 | #endif | 3140 | #endif |
3141 | return MHD_NO; | 3141 | return MHD_NO; |
3142 | } | 3142 | } |
3143 | if ( (-1 != daemon->wpipe[0]) && | 3143 | if ( (MHD_INVALID_PIPE_ != daemon->wpipe[0]) && |
3144 | (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME)) ) | 3144 | (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME)) ) |
3145 | { | 3145 | { |
3146 | event.events = EPOLLIN | EPOLLET; | 3146 | event.events = EPOLLIN | EPOLLET; |
@@ -3250,8 +3250,8 @@ MHD_start_daemon_va (unsigned int flags, | |||
3250 | daemon->pool_increment = MHD_BUF_INC_SIZE; | 3250 | daemon->pool_increment = MHD_BUF_INC_SIZE; |
3251 | daemon->unescape_callback = &MHD_http_unescape; | 3251 | daemon->unescape_callback = &MHD_http_unescape; |
3252 | daemon->connection_timeout = 0; /* no timeout */ | 3252 | daemon->connection_timeout = 0; /* no timeout */ |
3253 | daemon->wpipe[0] = -1; | 3253 | daemon->wpipe[0] = MHD_INVALID_PIPE_; |
3254 | daemon->wpipe[1] = -1; | 3254 | daemon->wpipe[1] = MHD_INVALID_PIPE_; |
3255 | #if HAVE_MESSAGES | 3255 | #if HAVE_MESSAGES |
3256 | daemon->custom_error_log = (MHD_LogCallback) &vfprintf; | 3256 | daemon->custom_error_log = (MHD_LogCallback) &vfprintf; |
3257 | daemon->custom_error_log_cls = stderr; | 3257 | daemon->custom_error_log_cls = stderr; |
@@ -3263,13 +3263,7 @@ MHD_start_daemon_va (unsigned int flags, | |||
3263 | #endif | 3263 | #endif |
3264 | if (0 == (flags & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION))) | 3264 | if (0 == (flags & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION))) |
3265 | use_pipe = 0; /* useless if we are using 'external' select */ | 3265 | use_pipe = 0; /* useless if we are using 'external' select */ |
3266 | if ( (use_pipe) && | 3266 | if ( (use_pipe) && (0 != MHD_pipe_ (daemon->wpipe)) ) |
3267 | #ifdef WINDOWS | ||
3268 | (0 != SOCKETPAIR (AF_INET, SOCK_STREAM, IPPROTO_TCP, daemon->wpipe)) | ||
3269 | #else | ||
3270 | (0 != PIPE (daemon->wpipe)) | ||
3271 | #endif | ||
3272 | ) | ||
3273 | { | 3267 | { |
3274 | #if HAVE_MESSAGES | 3268 | #if HAVE_MESSAGES |
3275 | MHD_DLOG (daemon, | 3269 | MHD_DLOG (daemon, |
@@ -3288,9 +3282,9 @@ MHD_start_daemon_va (unsigned int flags, | |||
3288 | MHD_DLOG (daemon, | 3282 | MHD_DLOG (daemon, |
3289 | "file descriptor for control pipe exceeds maximum value\n"); | 3283 | "file descriptor for control pipe exceeds maximum value\n"); |
3290 | #endif | 3284 | #endif |
3291 | if (0 != CLOSE (daemon->wpipe[0])) | 3285 | if (0 != MHD_pipe_close_ (daemon->wpipe[0])) |
3292 | MHD_PANIC ("close failed\n"); | 3286 | MHD_PANIC ("close failed\n"); |
3293 | if (0 != CLOSE (daemon->wpipe[1])) | 3287 | if (0 != MHD_pipe_close_ (daemon->wpipe[1])) |
3294 | MHD_PANIC ("close failed\n"); | 3288 | MHD_PANIC ("close failed\n"); |
3295 | free (daemon); | 3289 | free (daemon); |
3296 | return NULL; | 3290 | return NULL; |
@@ -3705,17 +3699,12 @@ MHD_start_daemon_va (unsigned int flags, | |||
3705 | d->worker_pool = NULL; | 3699 | d->worker_pool = NULL; |
3706 | 3700 | ||
3707 | if ( (MHD_USE_SUSPEND_RESUME == (flags & MHD_USE_SUSPEND_RESUME)) && | 3701 | if ( (MHD_USE_SUSPEND_RESUME == (flags & MHD_USE_SUSPEND_RESUME)) && |
3708 | #ifdef WINDOWS | 3702 | (0 != MHD_pipe_ (d->wpipe)) ) |
3709 | (0 != SOCKETPAIR (AF_INET, SOCK_STREAM, IPPROTO_TCP, d->wpipe)) | ||
3710 | #else | ||
3711 | (0 != PIPE (d->wpipe)) | ||
3712 | #endif | ||
3713 | ) | ||
3714 | { | 3703 | { |
3715 | #if HAVE_MESSAGES | 3704 | #if HAVE_MESSAGES |
3716 | MHD_DLOG (daemon, | 3705 | MHD_DLOG (daemon, |
3717 | "Failed to create worker control pipe: %s\n", | 3706 | "Failed to create worker control pipe: %s\n", |
3718 | MHD_strerror_ (errno)); | 3707 | MHD_pipe_last_strerror_() ); |
3719 | #endif | 3708 | #endif |
3720 | goto thread_failed; | 3709 | goto thread_failed; |
3721 | } | 3710 | } |
@@ -3728,9 +3717,9 @@ MHD_start_daemon_va (unsigned int flags, | |||
3728 | MHD_DLOG (daemon, | 3717 | MHD_DLOG (daemon, |
3729 | "file descriptor for worker control pipe exceeds maximum value\n"); | 3718 | "file descriptor for worker control pipe exceeds maximum value\n"); |
3730 | #endif | 3719 | #endif |
3731 | if (0 != CLOSE (d->wpipe[0])) | 3720 | if (0 != MHD_pipe_close_ (d->wpipe[0])) |
3732 | MHD_PANIC ("close failed\n"); | 3721 | MHD_PANIC ("close failed\n"); |
3733 | if (0 != CLOSE (d->wpipe[1])) | 3722 | if (0 != MHD_pipe_close_ (d->wpipe[1])) |
3734 | MHD_PANIC ("close failed\n"); | 3723 | MHD_PANIC ("close failed\n"); |
3735 | goto thread_failed; | 3724 | goto thread_failed; |
3736 | } | 3725 | } |
@@ -3906,7 +3895,7 @@ epoll_shutdown (struct MHD_Daemon *daemon) | |||
3906 | { | 3895 | { |
3907 | struct epoll_event event; | 3896 | struct epoll_event event; |
3908 | 3897 | ||
3909 | if (-1 == daemon->wpipe[1]) | 3898 | if (MHD_INVALID_PIPE_ == daemon->wpipe[1]) |
3910 | { | 3899 | { |
3911 | /* wpipe was required in this mode, how could this happen? */ | 3900 | /* wpipe was required in this mode, how could this happen? */ |
3912 | MHD_PANIC ("Internal error\n"); | 3901 | MHD_PANIC ("Internal error\n"); |
@@ -3957,9 +3946,9 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) | |||
3957 | #endif | 3946 | #endif |
3958 | } | 3947 | } |
3959 | } | 3948 | } |
3960 | if (-1 != daemon->wpipe[1]) | 3949 | if (MHD_INVALID_PIPE_ != daemon->wpipe[1]) |
3961 | { | 3950 | { |
3962 | if (1 != WRITE (daemon->wpipe[1], "e", 1)) | 3951 | if (1 != MHD_pipe_write_ (daemon->wpipe[1], "e", 1)) |
3963 | MHD_PANIC ("failed to signal shutdown via pipe"); | 3952 | MHD_PANIC ("failed to signal shutdown via pipe"); |
3964 | } | 3953 | } |
3965 | #ifdef HAVE_LISTEN_SHUTDOWN | 3954 | #ifdef HAVE_LISTEN_SHUTDOWN |
@@ -3990,9 +3979,9 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) | |||
3990 | /* MHD_USE_NO_LISTEN_SOCKET disables thread pools, hence we need to check */ | 3979 | /* MHD_USE_NO_LISTEN_SOCKET disables thread pools, hence we need to check */ |
3991 | for (i = 0; i < daemon->worker_pool_size; ++i) | 3980 | for (i = 0; i < daemon->worker_pool_size; ++i) |
3992 | { | 3981 | { |
3993 | if (-1 != daemon->worker_pool[i].wpipe[1]) | 3982 | if (MHD_INVALID_PIPE_ != daemon->worker_pool[i].wpipe[1]) |
3994 | { | 3983 | { |
3995 | if (1 != WRITE (daemon->worker_pool[i].wpipe[1], "e", 1)) | 3984 | if (1 != MHD_pipe_write_ (daemon->worker_pool[i].wpipe[1], "e", 1)) |
3996 | MHD_PANIC ("failed to signal shutdown via pipe"); | 3985 | MHD_PANIC ("failed to signal shutdown via pipe"); |
3997 | } | 3986 | } |
3998 | if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused))) | 3987 | if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused))) |
@@ -4006,11 +3995,11 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) | |||
4006 | #endif | 3995 | #endif |
4007 | if ( (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME)) ) | 3996 | if ( (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME)) ) |
4008 | { | 3997 | { |
4009 | if (-1 != daemon->worker_pool[i].wpipe[1]) | 3998 | if (MHD_INVALID_PIPE_ != daemon->worker_pool[i].wpipe[1]) |
4010 | { | 3999 | { |
4011 | if (0 != CLOSE (daemon->worker_pool[i].wpipe[0])) | 4000 | if (0 != MHD_pipe_close_ (daemon->worker_pool[i].wpipe[0])) |
4012 | MHD_PANIC ("close failed\n"); | 4001 | MHD_PANIC ("close failed\n"); |
4013 | if (0 != CLOSE (daemon->worker_pool[i].wpipe[1])) | 4002 | if (0 != MHD_pipe_close_ (daemon->worker_pool[i].wpipe[1])) |
4014 | MHD_PANIC ("close failed\n"); | 4003 | MHD_PANIC ("close failed\n"); |
4015 | } | 4004 | } |
4016 | } | 4005 | } |
@@ -4058,11 +4047,11 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) | |||
4058 | pthread_mutex_destroy (&daemon->per_ip_connection_mutex); | 4047 | pthread_mutex_destroy (&daemon->per_ip_connection_mutex); |
4059 | pthread_mutex_destroy (&daemon->cleanup_connection_mutex); | 4048 | pthread_mutex_destroy (&daemon->cleanup_connection_mutex); |
4060 | 4049 | ||
4061 | if (-1 != daemon->wpipe[1]) | 4050 | if (MHD_INVALID_PIPE_ != daemon->wpipe[1]) |
4062 | { | 4051 | { |
4063 | if (0 != CLOSE (daemon->wpipe[0])) | 4052 | if (0 != MHD_pipe_close_ (daemon->wpipe[0])) |
4064 | MHD_PANIC ("close failed\n"); | 4053 | MHD_PANIC ("close failed\n"); |
4065 | if (0 != CLOSE (daemon->wpipe[1])) | 4054 | if (0 != MHD_pipe_close_ (daemon->wpipe[1])) |
4066 | MHD_PANIC ("close failed\n"); | 4055 | MHD_PANIC ("close failed\n"); |
4067 | } | 4056 | } |
4068 | free (daemon); | 4057 | free (daemon); |
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h index c2a0441a..05ea244a 100644 --- a/src/microhttpd/internal.h +++ b/src/microhttpd/internal.h | |||
@@ -1102,9 +1102,10 @@ struct MHD_Daemon | |||
1102 | * Pipe we use to signal shutdown, unless | 1102 | * Pipe we use to signal shutdown, unless |
1103 | * 'HAVE_LISTEN_SHUTDOWN' is defined AND we have a listen | 1103 | * 'HAVE_LISTEN_SHUTDOWN' is defined AND we have a listen |
1104 | * socket (which we can then 'shutdown' to stop listening). | 1104 | * socket (which we can then 'shutdown' to stop listening). |
1105 | * On W32 this is a socketpair, not a pipe. | 1105 | * MHD can be build with usage of socketpair instead of |
1106 | * pipe (forced on W32). | ||
1106 | */ | 1107 | */ |
1107 | int wpipe[2]; | 1108 | MHD_pipe wpipe[2]; |
1108 | 1109 | ||
1109 | /** | 1110 | /** |
1110 | * Are we shutting down? | 1111 | * Are we shutting down? |
diff --git a/src/platform/platform_interface.h b/src/platform/platform_interface.h index 1fc3399e..42cfae23 100644 --- a/src/platform/platform_interface.h +++ b/src/platform/platform_interface.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #ifndef MHD_PLATFORM_INTERFACE_H | 26 | #ifndef MHD_PLATFORM_INTERFACE_H |
27 | #define MHD_PLATFORM_INTERFACE_H | 27 | #define MHD_PLATFORM_INTERFACE_H |
28 | 28 | ||
29 | #include "platform.h" | ||
29 | #if defined(_WIN32) && !defined(__CYGWIN__) | 30 | #if defined(_WIN32) && !defined(__CYGWIN__) |
30 | #include "w32functions.h" | 31 | #include "w32functions.h" |
31 | #endif | 32 | #endif |
@@ -66,4 +67,70 @@ | |||
66 | #define MHD_set_socket_errno_(errnum) MHD_W32_set_last_winsock_error_((errnum)) | 67 | #define MHD_set_socket_errno_(errnum) MHD_W32_set_last_winsock_error_((errnum)) |
67 | #endif | 68 | #endif |
68 | 69 | ||
70 | /* MHD_SYS_select_ is wrapper macro for system select() function */ | ||
71 | #if !defined(MHD_WINSOCK_SOCKETS) | ||
72 | #define MHD_SYS_select_(n,r,w,e,t) select((n),(r),(w),(e),(t)) | ||
73 | #else | ||
74 | #define MHD_SYS_select_(n,r,w,e,t) select((int)0,(r),(w),(e),(t)) | ||
75 | #endif | ||
76 | |||
77 | /* MHD_pipe_ create pipe (!MHD_DONT_USE_PIPES) / | ||
78 | * create two connected sockets (MHD_DONT_USE_PIPES) */ | ||
79 | #ifndef MHD_DONT_USE_PIPES | ||
80 | #define MHD_pipe_(fdarr) pipe((fdarr)) | ||
81 | #else /* MHD_DONT_USE_PIPES */ | ||
82 | #if !defined(_WIN32) || defined(__CYGWIN__) | ||
83 | #define MHD_pipe_(fdarr) socketpair(AF_LOCAL, SOCK_STREAM, 0, (fdarr)) | ||
84 | #else /* !defined(_WIN32) || defined(__CYGWIN__) */ | ||
85 | #define MHD_pipe_(fdarr) MHD_W32_pair_of_sockets_((fdarr)) | ||
86 | #endif /* !defined(_WIN32) || defined(__CYGWIN__) */ | ||
87 | #endif /* MHD_DONT_USE_PIPES */ | ||
88 | |||
89 | /* MHD_pipe_errno_ is errno of last function (!MHD_DONT_USE_PIPES) / | ||
90 | * errno of last emulated pipe function (MHD_DONT_USE_PIPES) */ | ||
91 | #ifndef MHD_DONT_USE_PIPES | ||
92 | #define MHD_pipe_errno_ errno | ||
93 | #else | ||
94 | #define MHD_pipe_errno_ MHD_socket_errno_ | ||
95 | #endif | ||
96 | |||
97 | /* MHD_pipe_last_strerror_ is description string of last errno (!MHD_DONT_USE_PIPES) / | ||
98 | * description string of last pipe error (MHD_DONT_USE_PIPES) */ | ||
99 | #ifndef MHD_DONT_USE_PIPES | ||
100 | #define MHD_pipe_last_strerror_() strerror(errno) | ||
101 | #else | ||
102 | #define MHD_pipe_last_strerror_() MHD_socket_last_strerr_() | ||
103 | #endif | ||
104 | |||
105 | /* MHD_pipe_write_ write data to real pipe (!MHD_DONT_USE_PIPES) / | ||
106 | * write data to emulated pipe (MHD_DONT_USE_PIPES) */ | ||
107 | #ifndef MHD_DONT_USE_PIPES | ||
108 | #define MHD_pipe_write_(fd, ptr, sz) write((fd), (const void*)(ptr), (sz)) | ||
109 | #else | ||
110 | #define MHD_pipe_write_(fd, ptr, sz) send((fd), (const char*)(ptr), (sz), 0) | ||
111 | #endif | ||
112 | |||
113 | /* MHD_pipe_read_ read data from real pipe (!MHD_DONT_USE_PIPES) / | ||
114 | * read data from emulated pipe (MHD_DONT_USE_PIPES) */ | ||
115 | #ifndef MHD_DONT_USE_PIPES | ||
116 | #define MHD_pipe_read_(fd, ptr, sz) read((fd), (void*)(ptr), (sz)) | ||
117 | #else | ||
118 | #define MHD_pipe_read_(fd, ptr, sz) recv((fd), (char*)(ptr), (sz), 0) | ||
119 | #endif | ||
120 | |||
121 | /* MHD_pipe_close_(fd) close any FDs (non-W32) / | ||
122 | * close emulated pipe FDs (W32) */ | ||
123 | #ifndef MHD_DONT_USE_PIPES | ||
124 | #define MHD_pipe_close_(fd) close((fd)) | ||
125 | #else | ||
126 | #define MHD_pipe_close_(fd) MHD_socket_close_((fd)) | ||
127 | #endif | ||
128 | |||
129 | /* MHD_INVALID_PIPE_ is a value of bad pipe FD */ | ||
130 | #ifndef MHD_DONT_USE_PIPES | ||
131 | #define MHD_INVALID_PIPE_ (-1) | ||
132 | #else | ||
133 | #define MHD_INVALID_PIPE_ MHD_INVALID_SOCKET | ||
134 | #endif | ||
135 | |||
69 | #endif // MHD_PLATFORM_INTERFACE_H | 136 | #endif // MHD_PLATFORM_INTERFACE_H |
diff --git a/src/platform/w32functions.c b/src/platform/w32functions.c index a0b35dec..34c5d73d 100644 --- a/src/platform/w32functions.c +++ b/src/platform/w32functions.c | |||
@@ -541,3 +541,80 @@ void MHD_W32_set_last_winsock_error_(int errnum) | |||
541 | break; | 541 | break; |
542 | } | 542 | } |
543 | } | 543 | } |
544 | |||
545 | /** | ||
546 | * Create pair of mutually connected TCP/IP sockets on loopback address | ||
547 | * @param sockets_pair array to receive resulted sockets | ||
548 | * @return zero on success, -1 otherwise | ||
549 | */ | ||
550 | int MHD_W32_pair_of_sockets_(SOCKET sockets_pair[2]) | ||
551 | { | ||
552 | int i; | ||
553 | if (!sockets_pair) | ||
554 | { | ||
555 | errno = EINVAL; | ||
556 | return -1; | ||
557 | } | ||
558 | |||
559 | #define PAIRMAXTRYIES 800 | ||
560 | for (i = 0; i < PAIRMAXTRYIES; i++) | ||
561 | { | ||
562 | struct sockaddr_in listen_addr; | ||
563 | SOCKET listen_s; | ||
564 | static const int c_addinlen = sizeof(struct sockaddr_in); /* help compiler to optimize */ | ||
565 | int addr_len = c_addinlen; | ||
566 | int opt = 1; | ||
567 | |||
568 | listen_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | ||
569 | if (INVALID_SOCKET == listen_s) | ||
570 | break; /* can't create even single socket */ | ||
571 | |||
572 | listen_addr.sin_family = AF_INET; | ||
573 | listen_addr.sin_port = htons(0); | ||
574 | listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | ||
575 | if (0 == bind(listen_s, (struct sockaddr*) &listen_addr, c_addinlen) | ||
576 | && 0 == listen(listen_s, 1) | ||
577 | && 0 == getsockname(listen_s, (struct sockaddr*) &listen_addr, | ||
578 | &addr_len)) | ||
579 | { | ||
580 | SOCKET client_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | ||
581 | if (INVALID_SOCKET != client_s) | ||
582 | { | ||
583 | if (0 == ioctlsocket(client_s, FIONBIO, (u_long*) &opt) | ||
584 | && (0 == connect(client_s, (struct sockaddr*) &listen_addr, c_addinlen) | ||
585 | || WSAGetLastError() == WSAEWOULDBLOCK)) | ||
586 | { | ||
587 | struct sockaddr_in accepted_from_addr; | ||
588 | addr_len = c_addinlen; | ||
589 | SOCKET server_s = accept(listen_s, | ||
590 | (struct sockaddr*) &accepted_from_addr, &addr_len); | ||
591 | if (INVALID_SOCKET != server_s) | ||
592 | { | ||
593 | struct sockaddr_in client_addr; | ||
594 | addr_len = c_addinlen; | ||
595 | opt = 0; | ||
596 | if (0 == getsockname(client_s, (struct sockaddr*) &client_addr, &addr_len) | ||
597 | && accepted_from_addr.sin_family == client_addr.sin_family | ||
598 | && accepted_from_addr.sin_port == client_addr.sin_port | ||
599 | && accepted_from_addr.sin_addr.s_addr == client_addr.sin_addr.s_addr | ||
600 | && 0 == ioctlsocket(client_s, FIONBIO, (u_long*) &opt) | ||
601 | && 0 == ioctlsocket(server_s, FIONBIO, (u_long*) &opt)) | ||
602 | { | ||
603 | closesocket(listen_s); | ||
604 | sockets_pair[0] = client_s; | ||
605 | sockets_pair[1] = server_s; | ||
606 | return 0; | ||
607 | } | ||
608 | closesocket(server_s); | ||
609 | } | ||
610 | } | ||
611 | closesocket(client_s); | ||
612 | } | ||
613 | } | ||
614 | closesocket(listen_s); | ||
615 | } | ||
616 | |||
617 | sockets_pair[0] = INVALID_SOCKET; | ||
618 | sockets_pair[1] = INVALID_SOCKET; | ||
619 | return -1; | ||
620 | } | ||
diff --git a/src/platform/w32functions.h b/src/platform/w32functions.h index d780db65..2c0cdcff 100644 --- a/src/platform/w32functions.h +++ b/src/platform/w32functions.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <errno.h> | 32 | #include <errno.h> |
33 | #include <winsock2.h> | 33 | #include <winsock2.h> |
34 | #include "platform.h" | 34 | #include "platform.h" |
35 | #include "platform_interface.h" | ||
35 | 36 | ||
36 | #ifdef __cplusplus | 37 | #ifdef __cplusplus |
37 | extern "C" | 38 | extern "C" |
@@ -170,6 +171,13 @@ const char* MHD_W32_strerror_last_winsock_(void); | |||
170 | */ | 171 | */ |
171 | void MHD_W32_set_last_winsock_error_(int errnum); | 172 | void MHD_W32_set_last_winsock_error_(int errnum); |
172 | 173 | ||
174 | /** | ||
175 | * Create pair of mutually connected TCP/IP sockets on loopback address | ||
176 | * @param sockets_pair array to receive resulted sockets | ||
177 | * @return zero on success, -1 otherwise | ||
178 | */ | ||
179 | int MHD_W32_pair_of_sockets_(SOCKET sockets_pair[2]); | ||
180 | |||
173 | #ifdef __cplusplus | 181 | #ifdef __cplusplus |
174 | } | 182 | } |
175 | #endif | 183 | #endif |