diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | doc/libmicrohttpd.texi | 14 | ||||
-rw-r--r-- | src/include/microhttpd.h | 10 | ||||
-rw-r--r-- | src/microhttpd/connection.c | 3 | ||||
-rw-r--r-- | src/microhttpd/connection_https.c | 6 | ||||
-rw-r--r-- | src/microhttpd/daemon.c | 239 | ||||
-rw-r--r-- | src/microhttpd/internal.c | 2 | ||||
-rw-r--r-- | src/microhttpd/internal.h | 9 |
8 files changed, 212 insertions, 76 deletions
@@ -1,3 +1,8 @@ | |||
1 | Wed Oct 29 20:45:21 CET 2014 | ||
2 | Adding MHD_OPTION_LISTENING_ADDRESS_REUSE option allowing clients | ||
3 | to force allowing re-use of the address:port combination | ||
4 | (SO_REUSEPORT). -MS | ||
5 | |||
1 | Wed Oct 29 16:27:05 CET 2014 | 6 | Wed Oct 29 16:27:05 CET 2014 |
2 | Adding MHD_DAEMON_INFO_CURRENT_CONNECTIONS to allow clients | 7 | Adding MHD_DAEMON_INFO_CURRENT_CONNECTIONS to allow clients |
3 | to query the number of active connections. -MS | 8 | to query the number of active connections. -MS |
diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi index dcfbfc9d..91579c62 100644 --- a/doc/libmicrohttpd.texi +++ b/doc/libmicrohttpd.texi | |||
@@ -856,6 +856,20 @@ by the HTTPS daemon for key exchange. This option must be followed by | |||
856 | a @code{const char *} argument. The argument would be a zero-terminated | 856 | a @code{const char *} argument. The argument would be a zero-terminated |
857 | string with a PEM encoded PKCS3 DH parameters structure suitable | 857 | string with a PEM encoded PKCS3 DH parameters structure suitable |
858 | for passing to @code{gnutls_dh_parms_import_pkcs3}. | 858 | for passing to @code{gnutls_dh_parms_import_pkcs3}. |
859 | |||
860 | @item MHD_OPTION_LISTENING_ADDRESS_REUSE | ||
861 | @cindex bind, restricting bind | ||
862 | @cindex reusing listening address | ||
863 | This option must be followed by a @code{unsigned int} argument. | ||
864 | If this option is present and true (nonzero) parameter is given, allow reusing | ||
865 | the address:port of the listening socket (using @code{SO_REUSEPORT} on most | ||
866 | platforms, and @code{SO_REUSEADDR} on Windows). If a false (zero) parameter is | ||
867 | given, disallow reusing the the address:port of the listening socket (this | ||
868 | usually requires no special action, but @code{SO_EXCLUSIVEADDRUSE} is needed on | ||
869 | Windows). If this option is not present, default behaviour is undefined | ||
870 | (currently, @code{SO_REUSEADDR} is used on all platforms, which disallows | ||
871 | address:port reusing with the exception of Windows). | ||
872 | |||
859 | @end table | 873 | @end table |
860 | @end deftp | 874 | @end deftp |
861 | 875 | ||
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h index aac7b61b..27a29d42 100644 --- a/src/include/microhttpd.h +++ b/src/include/microhttpd.h | |||
@@ -846,8 +846,16 @@ enum MHD_OPTION | |||
846 | * HTTPS daemon for key exchange. | 846 | * HTTPS daemon for key exchange. |
847 | * This option must be followed by a `const char *` argument. | 847 | * This option must be followed by a `const char *` argument. |
848 | */ | 848 | */ |
849 | MHD_OPTION_HTTPS_MEM_DHPARAMS = 24 | 849 | MHD_OPTION_HTTPS_MEM_DHPARAMS = 24, |
850 | 850 | ||
851 | /** | ||
852 | * If present and set to true, allow reusing address:port socket | ||
853 | * (by using SO_REUSEPORT on most platform, or platform-specific ways). | ||
854 | * If present and set to false, disallow reusing address:port socket | ||
855 | * (does nothing on most plaform, but uses SO_EXCLUSIVEADDRUSE on Windows). | ||
856 | * This option must be followed by a `unsigned int` argument. | ||
857 | */ | ||
858 | MHD_OPTION_LISTENING_ADDRESS_REUSE = 25, | ||
851 | }; | 859 | }; |
852 | 860 | ||
853 | 861 | ||
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index 772af9f5..0515e1fb 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c | |||
@@ -1306,7 +1306,8 @@ parse_cookie_header (struct MHD_Connection *connection) | |||
1306 | if (NULL == cpy) | 1306 | if (NULL == cpy) |
1307 | { | 1307 | { |
1308 | #if HAVE_MESSAGES | 1308 | #if HAVE_MESSAGES |
1309 | MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n"); | 1309 | MHD_DLOG (connection->daemon, |
1310 | "Not enough memory to parse cookies!\n"); | ||
1310 | #endif | 1311 | #endif |
1311 | transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, | 1312 | transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, |
1312 | REQUEST_TOO_BIG); | 1313 | REQUEST_TOO_BIG); |
diff --git a/src/microhttpd/connection_https.c b/src/microhttpd/connection_https.c index b566d83c..0d7d5980 100644 --- a/src/microhttpd/connection_https.c +++ b/src/microhttpd/connection_https.c | |||
@@ -134,8 +134,10 @@ MHD_tls_connection_handle_idle (struct MHD_Connection *connection) | |||
134 | unsigned int timeout; | 134 | unsigned int timeout; |
135 | 135 | ||
136 | #if DEBUG_STATES | 136 | #if DEBUG_STATES |
137 | MHD_DLOG (connection->daemon, "%s: state: %s\n", | 137 | MHD_DLOG (connection->daemon, |
138 | __FUNCTION__, MHD_state_to_string (connection->state)); | 138 | "%s: state: %s\n", |
139 | __FUNCTION__, | ||
140 | MHD_state_to_string (connection->state)); | ||
139 | #endif | 141 | #endif |
140 | timeout = connection->connection_timeout; | 142 | timeout = connection->connection_timeout; |
141 | if ( (timeout != 0) && (timeout <= (MHD_monotonic_time() - connection->last_activity))) | 143 | if ( (timeout != 0) && (timeout <= (MHD_monotonic_time() - connection->last_activity))) |
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index 52cea5d8..b8b0ed55 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c | |||
@@ -552,7 +552,8 @@ MHD_init_daemon_certificate (struct MHD_Daemon *daemon) | |||
552 | return 0; | 552 | return 0; |
553 | #endif | 553 | #endif |
554 | #if HAVE_MESSAGES | 554 | #if HAVE_MESSAGES |
555 | MHD_DLOG (daemon, "You need to specify a certificate and key location\n"); | 555 | MHD_DLOG (daemon, |
556 | "You need to specify a certificate and key location\n"); | ||
556 | #endif | 557 | #endif |
557 | return -1; | 558 | return -1; |
558 | } | 559 | } |
@@ -736,7 +737,9 @@ MHD_get_fdset2 (struct MHD_Daemon *daemon, | |||
736 | #if DEBUG_CONNECT | 737 | #if DEBUG_CONNECT |
737 | #if HAVE_MESSAGES | 738 | #if HAVE_MESSAGES |
738 | if (NULL != max_fd) | 739 | if (NULL != max_fd) |
739 | MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd); | 740 | MHD_DLOG (daemon, |
741 | "Maximum socket in select set: %d\n", | ||
742 | *max_fd); | ||
740 | #endif | 743 | #endif |
741 | #endif | 744 | #endif |
742 | return MHD_YES; | 745 | return MHD_YES; |
@@ -826,7 +829,7 @@ MHD_handle_connection (void *data) | |||
826 | { | 829 | { |
827 | #if HAVE_MESSAGES | 830 | #if HAVE_MESSAGES |
828 | MHD_DLOG (con->daemon, | 831 | MHD_DLOG (con->daemon, |
829 | "Can't add FD to fd_set\n"); | 832 | "Can't add FD to fd_set\n"); |
830 | #endif | 833 | #endif |
831 | goto exit; | 834 | goto exit; |
832 | } | 835 | } |
@@ -1200,7 +1203,9 @@ internal_add_connection (struct MHD_Daemon *daemon, | |||
1200 | 1203 | ||
1201 | #if HAVE_MESSAGES | 1204 | #if HAVE_MESSAGES |
1202 | #if DEBUG_CONNECT | 1205 | #if DEBUG_CONNECT |
1203 | MHD_DLOG (daemon, "Accepted connection on socket %d\n", client_socket); | 1206 | MHD_DLOG (daemon, |
1207 | "Accepted connection on socket %d\n", | ||
1208 | client_socket); | ||
1204 | #endif | 1209 | #endif |
1205 | #endif | 1210 | #endif |
1206 | if ( (daemon->connections == daemon->connection_limit) || | 1211 | if ( (daemon->connections == daemon->connection_limit) || |
@@ -1226,7 +1231,8 @@ internal_add_connection (struct MHD_Daemon *daemon, | |||
1226 | { | 1231 | { |
1227 | #if DEBUG_CLOSE | 1232 | #if DEBUG_CLOSE |
1228 | #if HAVE_MESSAGES | 1233 | #if HAVE_MESSAGES |
1229 | MHD_DLOG (daemon, "Connection rejected, closing connection\n"); | 1234 | MHD_DLOG (daemon, |
1235 | "Connection rejected, closing connection\n"); | ||
1230 | #endif | 1236 | #endif |
1231 | #endif | 1237 | #endif |
1232 | if (0 != MHD_socket_close_ (client_socket)) | 1238 | if (0 != MHD_socket_close_ (client_socket)) |
@@ -1415,7 +1421,8 @@ internal_add_connection (struct MHD_Daemon *daemon, | |||
1415 | { | 1421 | { |
1416 | eno = errno; | 1422 | eno = errno; |
1417 | #if HAVE_MESSAGES | 1423 | #if HAVE_MESSAGES |
1418 | MHD_DLOG (daemon, "Failed to create a thread: %s\n", | 1424 | MHD_DLOG (daemon, |
1425 | "Failed to create a thread: %s\n", | ||
1419 | MHD_strerror_ (res_thread_create)); | 1426 | MHD_strerror_ (res_thread_create)); |
1420 | #endif | 1427 | #endif |
1421 | goto cleanup; | 1428 | goto cleanup; |
@@ -1839,7 +1846,9 @@ MHD_accept_connection (struct MHD_Daemon *daemon) | |||
1839 | #endif | 1846 | #endif |
1840 | #if HAVE_MESSAGES | 1847 | #if HAVE_MESSAGES |
1841 | #if DEBUG_CONNECT | 1848 | #if DEBUG_CONNECT |
1842 | MHD_DLOG (daemon, "Accepted connection on socket %d\n", s); | 1849 | MHD_DLOG (daemon, |
1850 | "Accepted connection on socket %d\n", | ||
1851 | s); | ||
1843 | #endif | 1852 | #endif |
1844 | #endif | 1853 | #endif |
1845 | (void) internal_add_connection (daemon, s, | 1854 | (void) internal_add_connection (daemon, s, |
@@ -1961,7 +1970,8 @@ MHD_get_timeout (struct MHD_Daemon *daemon, | |||
1961 | if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) | 1970 | if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) |
1962 | { | 1971 | { |
1963 | #if HAVE_MESSAGES | 1972 | #if HAVE_MESSAGES |
1964 | MHD_DLOG (daemon, "Illegal call to MHD_get_timeout\n"); | 1973 | MHD_DLOG (daemon, |
1974 | "Illegal call to MHD_get_timeout\n"); | ||
1965 | #endif | 1975 | #endif |
1966 | return MHD_NO; | 1976 | return MHD_NO; |
1967 | } | 1977 | } |
@@ -2196,7 +2206,9 @@ MHD_select (struct MHD_Daemon *daemon, | |||
2196 | if (EINTR == MHD_socket_errno_) | 2206 | if (EINTR == MHD_socket_errno_) |
2197 | return MHD_YES; | 2207 | return MHD_YES; |
2198 | #if HAVE_MESSAGES | 2208 | #if HAVE_MESSAGES |
2199 | MHD_DLOG (daemon, "select failed: %s\n", MHD_socket_last_strerr_ ()); | 2209 | MHD_DLOG (daemon, |
2210 | "select failed: %s\n", | ||
2211 | MHD_socket_last_strerr_ ()); | ||
2200 | #endif | 2212 | #endif |
2201 | return MHD_NO; | 2213 | return MHD_NO; |
2202 | } | 2214 | } |
@@ -2401,7 +2413,9 @@ MHD_poll_listen_socket (struct MHD_Daemon *daemon, | |||
2401 | if (EINTR == MHD_socket_errno_) | 2413 | if (EINTR == MHD_socket_errno_) |
2402 | return MHD_YES; | 2414 | return MHD_YES; |
2403 | #if HAVE_MESSAGES | 2415 | #if HAVE_MESSAGES |
2404 | MHD_DLOG (daemon, "poll failed: %s\n", MHD_socket_last_strerr_ ()); | 2416 | MHD_DLOG (daemon, |
2417 | "poll failed: %s\n", | ||
2418 | MHD_socket_last_strerr_ ()); | ||
2405 | #endif | 2419 | #endif |
2406 | return MHD_NO; | 2420 | return MHD_NO; |
2407 | } | 2421 | } |
@@ -2492,10 +2506,9 @@ MHD_epoll (struct MHD_Daemon *daemon, | |||
2492 | &event)) | 2506 | &event)) |
2493 | { | 2507 | { |
2494 | #if HAVE_MESSAGES | 2508 | #if HAVE_MESSAGES |
2495 | if (0 != (daemon->options & MHD_USE_DEBUG)) | 2509 | MHD_DLOG (daemon, |
2496 | MHD_DLOG (daemon, | 2510 | "Call to epoll_ctl failed: %s\n", |
2497 | "Call to epoll_ctl failed: %s\n", | 2511 | MHD_socket_last_strerr_ ()); |
2498 | MHD_socket_last_strerr_ ()); | ||
2499 | #endif | 2512 | #endif |
2500 | return MHD_NO; | 2513 | return MHD_NO; |
2501 | } | 2514 | } |
@@ -2544,10 +2557,9 @@ MHD_epoll (struct MHD_Daemon *daemon, | |||
2544 | if (EINTR == MHD_socket_errno_) | 2557 | if (EINTR == MHD_socket_errno_) |
2545 | return MHD_YES; | 2558 | return MHD_YES; |
2546 | #if HAVE_MESSAGES | 2559 | #if HAVE_MESSAGES |
2547 | if (0 != (daemon->options & MHD_USE_DEBUG)) | 2560 | MHD_DLOG (daemon, |
2548 | MHD_DLOG (daemon, | 2561 | "Call to epoll_wait failed: %s\n", |
2549 | "Call to epoll_wait failed: %s\n", | 2562 | MHD_socket_last_strerr_ ()); |
2550 | MHD_socket_last_strerr_ ()); | ||
2551 | #endif | 2563 | #endif |
2552 | return MHD_NO; | 2564 | return MHD_NO; |
2553 | } | 2565 | } |
@@ -2994,7 +3006,8 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
2994 | if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0) | 3006 | if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0) |
2995 | { | 3007 | { |
2996 | #if HAVE_MESSAGES | 3008 | #if HAVE_MESSAGES |
2997 | MHD_DLOG(daemon, "Error initializing DH parameters\n"); | 3009 | MHD_DLOG(daemon, |
3010 | "Error initializing DH parameters\n"); | ||
2998 | #endif | 3011 | #endif |
2999 | return MHD_NO; | 3012 | return MHD_NO; |
3000 | } | 3013 | } |
@@ -3004,7 +3017,8 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
3004 | GNUTLS_X509_FMT_PEM) < 0) | 3017 | GNUTLS_X509_FMT_PEM) < 0) |
3005 | { | 3018 | { |
3006 | #if HAVE_MESSAGES | 3019 | #if HAVE_MESSAGES |
3007 | MHD_DLOG(daemon, "Bad Diffie-Hellman parameters format\n"); | 3020 | MHD_DLOG(daemon, |
3021 | "Bad Diffie-Hellman parameters format\n"); | ||
3008 | #endif | 3022 | #endif |
3009 | gnutls_dh_params_deinit (daemon->https_mem_dhparams); | 3023 | gnutls_dh_params_deinit (daemon->https_mem_dhparams); |
3010 | return MHD_NO; | 3024 | return MHD_NO; |
@@ -3028,7 +3042,7 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
3028 | ret = gnutls_priority_init (&daemon->priority_cache, | 3042 | ret = gnutls_priority_init (&daemon->priority_cache, |
3029 | pstr = va_arg (ap, const char*), | 3043 | pstr = va_arg (ap, const char*), |
3030 | NULL); | 3044 | NULL); |
3031 | if (ret != GNUTLS_E_SUCCESS) | 3045 | if (GNUTLS_E_SUCCESS != ret) |
3032 | { | 3046 | { |
3033 | #if HAVE_MESSAGES | 3047 | #if HAVE_MESSAGES |
3034 | MHD_DLOG (daemon, | 3048 | MHD_DLOG (daemon, |
@@ -3084,6 +3098,9 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
3084 | daemon->fastopen_queue_size = va_arg (ap, unsigned int); | 3098 | daemon->fastopen_queue_size = va_arg (ap, unsigned int); |
3085 | break; | 3099 | break; |
3086 | #endif | 3100 | #endif |
3101 | case MHD_OPTION_LISTENING_ADDRESS_REUSE: | ||
3102 | daemon->listening_address_reuse = va_arg (ap, unsigned int) ? 1 : -1; | ||
3103 | break; | ||
3087 | case MHD_OPTION_ARRAY: | 3104 | case MHD_OPTION_ARRAY: |
3088 | oa = va_arg (ap, struct MHD_OptionItem*); | 3105 | oa = va_arg (ap, struct MHD_OptionItem*); |
3089 | i = 0; | 3106 | i = 0; |
@@ -3109,6 +3126,7 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
3109 | case MHD_OPTION_PER_IP_CONNECTION_LIMIT: | 3126 | case MHD_OPTION_PER_IP_CONNECTION_LIMIT: |
3110 | case MHD_OPTION_THREAD_POOL_SIZE: | 3127 | case MHD_OPTION_THREAD_POOL_SIZE: |
3111 | case MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE: | 3128 | case MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE: |
3129 | case MHD_OPTION_LISTENING_ADDRESS_REUSE: | ||
3112 | if (MHD_YES != parse_options (daemon, | 3130 | if (MHD_YES != parse_options (daemon, |
3113 | servaddr, | 3131 | servaddr, |
3114 | opt, | 3132 | opt, |
@@ -3254,10 +3272,9 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon) | |||
3254 | if (-1 == daemon->epoll_fd) | 3272 | if (-1 == daemon->epoll_fd) |
3255 | { | 3273 | { |
3256 | #if HAVE_MESSAGES | 3274 | #if HAVE_MESSAGES |
3257 | if (0 != (daemon->options & MHD_USE_DEBUG)) | 3275 | MHD_DLOG (daemon, |
3258 | MHD_DLOG (daemon, | 3276 | "Call to epoll_create1 failed: %s\n", |
3259 | "Call to epoll_create1 failed: %s\n", | 3277 | MHD_socket_last_strerr_ ()); |
3260 | MHD_socket_last_strerr_ ()); | ||
3261 | #endif | 3278 | #endif |
3262 | return MHD_NO; | 3279 | return MHD_NO; |
3263 | } | 3280 | } |
@@ -3274,10 +3291,9 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon) | |||
3274 | &event)) | 3291 | &event)) |
3275 | { | 3292 | { |
3276 | #if HAVE_MESSAGES | 3293 | #if HAVE_MESSAGES |
3277 | if (0 != (daemon->options & MHD_USE_DEBUG)) | 3294 | MHD_DLOG (daemon, |
3278 | MHD_DLOG (daemon, | 3295 | "Call to epoll_ctl failed: %s\n", |
3279 | "Call to epoll_ctl failed: %s\n", | 3296 | MHD_socket_last_strerr_ ()); |
3280 | MHD_socket_last_strerr_ ()); | ||
3281 | #endif | 3297 | #endif |
3282 | return MHD_NO; | 3298 | return MHD_NO; |
3283 | } | 3299 | } |
@@ -3293,10 +3309,9 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon) | |||
3293 | &event)) | 3309 | &event)) |
3294 | { | 3310 | { |
3295 | #if HAVE_MESSAGES | 3311 | #if HAVE_MESSAGES |
3296 | if (0 != (daemon->options & MHD_USE_DEBUG)) | 3312 | MHD_DLOG (daemon, |
3297 | MHD_DLOG (daemon, | 3313 | "Call to epoll_ctl failed: %s\n", |
3298 | "Call to epoll_ctl failed: %s\n", | 3314 | MHD_socket_last_strerr_ ()); |
3299 | MHD_socket_last_strerr_ ()); | ||
3300 | #endif | 3315 | #endif |
3301 | return MHD_NO; | 3316 | return MHD_NO; |
3302 | } | 3317 | } |
@@ -3379,6 +3394,7 @@ MHD_start_daemon_va (unsigned int flags, | |||
3379 | } | 3394 | } |
3380 | #endif | 3395 | #endif |
3381 | daemon->socket_fd = MHD_INVALID_SOCKET; | 3396 | daemon->socket_fd = MHD_INVALID_SOCKET; |
3397 | daemon->listening_address_reuse = 0; | ||
3382 | daemon->options = (enum MHD_OPTION) flags; | 3398 | daemon->options = (enum MHD_OPTION) flags; |
3383 | #if WINDOWS | 3399 | #if WINDOWS |
3384 | /* Winsock is broken with respect to 'shutdown'; | 3400 | /* Winsock is broken with respect to 'shutdown'; |
@@ -3553,25 +3569,111 @@ MHD_start_daemon_va (unsigned int flags, | |||
3553 | if (MHD_INVALID_SOCKET == socket_fd) | 3569 | if (MHD_INVALID_SOCKET == socket_fd) |
3554 | { | 3570 | { |
3555 | #if HAVE_MESSAGES | 3571 | #if HAVE_MESSAGES |
3556 | if (0 != (flags & MHD_USE_DEBUG)) | 3572 | MHD_DLOG (daemon, |
3557 | MHD_DLOG (daemon, | 3573 | "Call to socket failed: %s\n", |
3558 | "Call to socket failed: %s\n", | 3574 | MHD_socket_last_strerr_ ()); |
3559 | MHD_socket_last_strerr_ ()); | ||
3560 | #endif | 3575 | #endif |
3561 | goto free_and_fail; | 3576 | goto free_and_fail; |
3562 | } | 3577 | } |
3563 | if ( (0 > setsockopt (socket_fd, | 3578 | |
3564 | SOL_SOCKET, | 3579 | /* Apply the socket options according to listening_address_reuse. */ |
3565 | SO_REUSEADDR, | 3580 | if (0 == daemon->listening_address_reuse) |
3566 | (void*)&on, sizeof (on))) && | 3581 | { |
3567 | (0 != (flags & MHD_USE_DEBUG)) ) | 3582 | /* No user requirement, use "traditional" default SO_REUSEADDR, |
3568 | { | 3583 | and do not fail if it doesn't work */ |
3584 | if (0 > setsockopt (socket_fd, | ||
3585 | SOL_SOCKET, | ||
3586 | SO_REUSEADDR, | ||
3587 | (void*)&on, sizeof (on))) | ||
3569 | #if HAVE_MESSAGES | 3588 | #if HAVE_MESSAGES |
3570 | MHD_DLOG (daemon, | 3589 | MHD_DLOG (daemon, |
3571 | "setsockopt failed: %s\n", | 3590 | "setsockopt failed: %s\n", |
3572 | MHD_socket_last_strerr_ ()); | 3591 | MHD_socket_last_strerr_ ()); |
3573 | #endif | 3592 | #endif |
3574 | } | 3593 | } |
3594 | else if (daemon->listening_address_reuse > 0) | ||
3595 | { | ||
3596 | /* User requested to allow reusing listening address:port. | ||
3597 | * Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms. | ||
3598 | * Fail if SO_REUSEPORT does not exist or setsockopt fails. | ||
3599 | */ | ||
3600 | #ifdef _WIN32 | ||
3601 | /* SO_REUSEADDR on W32 has the same semantics | ||
3602 | as SO_REUSEPORT on BSD/Linux */ | ||
3603 | if (0 > setsockopt (socket_fd, | ||
3604 | SOL_SOCKET, | ||
3605 | SO_REUSEADDR, | ||
3606 | (void*)&on, sizeof (on))) | ||
3607 | { | ||
3608 | #if HAVE_MESSAGES | ||
3609 | MHD_DLOG (daemon, | ||
3610 | "setsockopt failed: %s\n", | ||
3611 | MHD_socket_last_strerr_ ()); | ||
3612 | #endif | ||
3613 | goto free_and_fail; | ||
3614 | } | ||
3615 | #else | ||
3616 | #ifndef SO_REUSEPORT | ||
3617 | #ifdef LINUX | ||
3618 | /* Supported since Linux 3.9, but often not present (or commented out) | ||
3619 | in the headers at this time; but 15 is reserved for this and | ||
3620 | thus should be safe to use. */ | ||
3621 | #define SO_REUSEPORT 15 | ||
3622 | #endif | ||
3623 | #endif | ||
3624 | #ifdef SO_REUSEPORT | ||
3625 | if (0 > setsockopt (socket_fd, | ||
3626 | SOL_SOCKET, | ||
3627 | SO_REUSEPORT, | ||
3628 | (void*)&on, sizeof (on))) | ||
3629 | { | ||
3630 | #if HAVE_MESSAGES | ||
3631 | MHD_DLOG (daemon, | ||
3632 | "setsockopt failed: %s\n", | ||
3633 | MHD_socket_last_strerr_ ()); | ||
3634 | #endif | ||
3635 | goto free_and_fail; | ||
3636 | } | ||
3637 | #else | ||
3638 | /* we're supposed to allow address:port re-use, but | ||
3639 | on this platform we cannot; fail hard */ | ||
3640 | #if HAVE_MESSAGES | ||
3641 | MHD_DLOG (daemon, | ||
3642 | "Cannot allow listening address reuse: SO_REUSEPORT not defined\n"); | ||
3643 | #endif | ||
3644 | goto free_and_fail; | ||
3645 | #endif | ||
3646 | #endif | ||
3647 | } | ||
3648 | else /* if (daemon->listening_address_reuse < 0) */ | ||
3649 | { | ||
3650 | /* User requested to disallow reusing listening address:port. | ||
3651 | * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE | ||
3652 | * is used. Fail if it does not exist or setsockopt fails. | ||
3653 | */ | ||
3654 | #ifdef _WIN32 | ||
3655 | #ifdef SO_EXCLUSIVEADDRUSE | ||
3656 | if (0 > setsockopt (socket_fd, | ||
3657 | SOL_SOCKET, | ||
3658 | SO_EXCLUSIVEADDRUSE, | ||
3659 | (void*)&on, sizeof (on))) | ||
3660 | { | ||
3661 | #if HAVE_MESSAGES | ||
3662 | MHD_DLOG (daemon, | ||
3663 | "setsockopt failed: %s\n", | ||
3664 | MHD_socket_last_strerr_ ()); | ||
3665 | #endif | ||
3666 | goto free_and_fail; | ||
3667 | } | ||
3668 | #else /* SO_EXCLUSIVEADDRUSE not defined on W32? */ | ||
3669 | #if HAVE_MESSAGES | ||
3670 | MHD_DLOG (daemon, | ||
3671 | "Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n"); | ||
3672 | #endif | ||
3673 | goto free_and_fail; | ||
3674 | #endif | ||
3675 | #endif /* _WIN32 */ | ||
3676 | } | ||
3575 | 3677 | ||
3576 | /* check for user supplied sockaddr */ | 3678 | /* check for user supplied sockaddr */ |
3577 | #if HAVE_INET6 | 3679 | #if HAVE_INET6 |
@@ -3621,28 +3723,24 @@ MHD_start_daemon_va (unsigned int flags, | |||
3621 | const char | 3723 | const char |
3622 | #endif | 3724 | #endif |
3623 | on = (MHD_USE_DUAL_STACK != (flags & MHD_USE_DUAL_STACK)); | 3725 | on = (MHD_USE_DUAL_STACK != (flags & MHD_USE_DUAL_STACK)); |
3624 | if ( (0 > setsockopt (socket_fd, | 3726 | if (0 > setsockopt (socket_fd, |
3625 | IPPROTO_IPV6, IPV6_V6ONLY, | 3727 | IPPROTO_IPV6, IPV6_V6ONLY, |
3626 | &on, sizeof (on))) && | 3728 | &on, sizeof (on))) |
3627 | (0 != (flags & MHD_USE_DEBUG)) ) | ||
3628 | { | ||
3629 | #if HAVE_MESSAGES | 3729 | #if HAVE_MESSAGES |
3630 | MHD_DLOG (daemon, | 3730 | MHD_DLOG (daemon, |
3631 | "setsockopt failed: %s\n", | 3731 | "setsockopt failed: %s\n", |
3632 | MHD_socket_last_strerr_ ()); | 3732 | MHD_socket_last_strerr_ ()); |
3633 | #endif | 3733 | #endif |
3634 | } | ||
3635 | #endif | 3734 | #endif |
3636 | #endif | 3735 | #endif |
3637 | } | 3736 | } |
3638 | if (-1 == bind (socket_fd, servaddr, addrlen)) | 3737 | if (-1 == bind (socket_fd, servaddr, addrlen)) |
3639 | { | 3738 | { |
3640 | #if HAVE_MESSAGES | 3739 | #if HAVE_MESSAGES |
3641 | if (0 != (flags & MHD_USE_DEBUG)) | 3740 | MHD_DLOG (daemon, |
3642 | MHD_DLOG (daemon, | 3741 | "Failed to bind to port %u: %s\n", |
3643 | "Failed to bind to port %u: %s\n", | 3742 | (unsigned int) port, |
3644 | (unsigned int) port, | 3743 | MHD_socket_last_strerr_ ()); |
3645 | MHD_socket_last_strerr_ ()); | ||
3646 | #endif | 3744 | #endif |
3647 | if (0 != MHD_socket_close_ (socket_fd)) | 3745 | if (0 != MHD_socket_close_ (socket_fd)) |
3648 | MHD_PANIC ("close failed\n"); | 3746 | MHD_PANIC ("close failed\n"); |
@@ -3686,10 +3784,9 @@ MHD_start_daemon_va (unsigned int flags, | |||
3686 | if (listen (socket_fd, 32) < 0) | 3784 | if (listen (socket_fd, 32) < 0) |
3687 | { | 3785 | { |
3688 | #if HAVE_MESSAGES | 3786 | #if HAVE_MESSAGES |
3689 | if (0 != (flags & MHD_USE_DEBUG)) | 3787 | MHD_DLOG (daemon, |
3690 | MHD_DLOG (daemon, | 3788 | "Failed to listen for connections: %s\n", |
3691 | "Failed to listen for connections: %s\n", | 3789 | MHD_socket_last_strerr_ ()); |
3692 | MHD_socket_last_strerr_ ()); | ||
3693 | #endif | 3790 | #endif |
3694 | if (0 != MHD_socket_close_ (socket_fd)) | 3791 | if (0 != MHD_socket_close_ (socket_fd)) |
3695 | MHD_PANIC ("close failed\n"); | 3792 | MHD_PANIC ("close failed\n"); |
@@ -3705,11 +3802,10 @@ MHD_start_daemon_va (unsigned int flags, | |||
3705 | (0 == (flags & (MHD_USE_POLL | MHD_USE_EPOLL_LINUX_ONLY)) ) ) | 3802 | (0 == (flags & (MHD_USE_POLL | MHD_USE_EPOLL_LINUX_ONLY)) ) ) |
3706 | { | 3803 | { |
3707 | #if HAVE_MESSAGES | 3804 | #if HAVE_MESSAGES |
3708 | if ((flags & MHD_USE_DEBUG) != 0) | 3805 | MHD_DLOG (daemon, |
3709 | MHD_DLOG (daemon, | 3806 | "Socket descriptor larger than FD_SETSIZE: %d > %d\n", |
3710 | "Socket descriptor larger than FD_SETSIZE: %d > %d\n", | 3807 | socket_fd, |
3711 | socket_fd, | 3808 | FD_SETSIZE); |
3712 | FD_SETSIZE); | ||
3713 | #endif | 3809 | #endif |
3714 | if (0 != MHD_socket_close_ (socket_fd)) | 3810 | if (0 != MHD_socket_close_ (socket_fd)) |
3715 | MHD_PANIC ("close failed\n"); | 3811 | MHD_PANIC ("close failed\n"); |
@@ -4123,7 +4219,8 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) | |||
4123 | 4219 | ||
4124 | #if DEBUG_CLOSE | 4220 | #if DEBUG_CLOSE |
4125 | #if HAVE_MESSAGES | 4221 | #if HAVE_MESSAGES |
4126 | MHD_DLOG (daemon, "MHD listen socket shutdown\n"); | 4222 | MHD_DLOG (daemon, |
4223 | "MHD listen socket shutdown\n"); | ||
4127 | #endif | 4224 | #endif |
4128 | #endif | 4225 | #endif |
4129 | 4226 | ||
diff --git a/src/microhttpd/internal.c b/src/microhttpd/internal.c index 597457f8..37ba1471 100644 --- a/src/microhttpd/internal.c +++ b/src/microhttpd/internal.c | |||
@@ -95,7 +95,7 @@ MHD_DLOG (const struct MHD_Daemon *daemon, const char *format, ...) | |||
95 | { | 95 | { |
96 | va_list va; | 96 | va_list va; |
97 | 97 | ||
98 | if ((daemon->options & MHD_USE_DEBUG) == 0) | 98 | if (0 == (daemon->options & MHD_USE_DEBUG)) |
99 | return; | 99 | return; |
100 | va_start (va, format); | 100 | va_start (va, format); |
101 | daemon->custom_error_log (daemon->custom_error_log_cls, format, va); | 101 | daemon->custom_error_log (daemon->custom_error_log_cls, format, va); |
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h index 17798b30..4b25ccb3 100644 --- a/src/microhttpd/internal.h +++ b/src/microhttpd/internal.h | |||
@@ -1099,6 +1099,15 @@ struct MHD_Daemon | |||
1099 | */ | 1099 | */ |
1100 | MHD_socket socket_fd; | 1100 | MHD_socket socket_fd; |
1101 | 1101 | ||
1102 | /** | ||
1103 | * Whether to allow/disallow/ignore reuse of listening address. | ||
1104 | * The semantics is the following: | ||
1105 | * 0: ignore (user did not ask for neither allow/disallow, use SO_REUSEADDR) | ||
1106 | * >0: allow (use SO_REUSEPORT on most platforms, SO_REUSEADDR on Windows) | ||
1107 | * <0: disallow (mostly no action, SO_EXCLUSIVEADDRUSE on Windows) | ||
1108 | */ | ||
1109 | int listening_address_reuse; | ||
1110 | |||
1102 | #if EPOLL_SUPPORT | 1111 | #if EPOLL_SUPPORT |
1103 | /** | 1112 | /** |
1104 | * File descriptor associated with our epoll loop. | 1113 | * File descriptor associated with our epoll loop. |