aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2014-02-18 18:38:41 +0000
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2014-02-18 18:38:41 +0000
commit1acde3cb8eab299a0994f243616de4e8ee028c0a (patch)
treec5d9ee16b8a89d3e0e77abd5427c16ff38af6bb3
parent558d8ae997bba5128830dddf6d35bb97f3fedf6f (diff)
downloadlibmicrohttpd-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.ac33
-rw-r--r--src/include/microhttpd.h3
-rw-r--r--src/include/platform.h12
-rw-r--r--src/microhttpd/daemon.c81
-rw-r--r--src/microhttpd/internal.h5
-rw-r--r--src/platform/platform_interface.h67
-rw-r--r--src/platform/w32functions.c77
-rw-r--r--src/platform/w32functions.h8
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
230AC_CHECK_HEADERS([search.h], AM_CONDITIONAL(HAVE_TSEARCH, true), AM_CONDITIONAL(HAVE_TSEARCH, false)) 232AC_CHECK_HEADERS([search.h], AM_CONDITIONAL(HAVE_TSEARCH, true), AM_CONDITIONAL(HAVE_TSEARCH, false))
231 233
234# Check for pipe/socketpair signaling
235AC_MSG_CHECKING([[whether to disable pipes signaling]])
236AC_ARG_ENABLE([[pipes]],
237 [AS_HELP_STRING([[--disable-pipes]], [[disable internal singalling by pipes and use socket pair instead]])],
238 [], [[enable_pipes=yes]])
239AS_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 ])
261if 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])
263fi
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
233AC_CHECK_HEADERS([plibc.h],our_private_plibc_h=0,our_private_plibc_h=1) 266AC_CHECK_HEADERS([plibc.h],our_private_plibc_h=0,our_private_plibc_h=1)
234AM_CONDITIONAL(USE_PRIVATE_PLIBC_H, test x$our_private_plibc_h = x1) 267AM_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
145typedef int MHD_pipe;
146#else /* ! MHD_DONT_USE_PIPES */
147typedef 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 */
550int 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
37extern "C" 38extern "C"
@@ -170,6 +171,13 @@ const char* MHD_W32_strerror_last_winsock_(void);
170 */ 171 */
171void MHD_W32_set_last_winsock_error_(int errnum); 172void 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 */
179int MHD_W32_pair_of_sockets_(SOCKET sockets_pair[2]);
180
173#ifdef __cplusplus 181#ifdef __cplusplus
174} 182}
175#endif 183#endif